[SCM] Packaging for Google Go branch, weekly-debian-sid, updated. debian-weekly/2011.05.22-2-5-gf9ecfcc

Ondřej Surý ondrej at sury.org
Fri Jun 3 09:51:30 UTC 2011


The following commit has been merged in the weekly-debian-sid branch:
commit 13f4fcd5bf09c70942b6c85a2b919ffa1ca0c6a8
Author: Ondřej Surý <ondrej at sury.org>
Date:   Fri Jun 3 11:31:24 2011 +0200

    Imported Upstream version 2011.06.02

diff --git a/CONTRIBUTORS b/CONTRIBUTORS
index ae77a71..0fd2b9f 100644
--- a/CONTRIBUTORS
+++ b/CONTRIBUTORS
@@ -207,6 +207,7 @@ Vincent Vanackere <vincent.vanackere at gmail.com>
 Vinu Rajashekhar <vinutheraj at gmail.com>
 Vish Subramanian <vish at google.com>
 Wei Guangjing <vcc.163 at gmail.com>
+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>
diff --git a/doc/all.css b/doc/all.css
index 84df1f8..a985d8f 100644
--- a/doc/all.css
+++ b/doc/all.css
@@ -198,3 +198,8 @@ span.alert {
   padding: 0.25em 1em;
   background: #F4F4F4;
 }
+sup.new {
+  color: red;
+  font-size: 8px;
+  line-height: 0;
+}
diff --git a/doc/contrib.html b/doc/contrib.html
index 0efe814..84d2cda 100644
--- a/doc/contrib.html
+++ b/doc/contrib.html
@@ -49,7 +49,10 @@ systems and architectures.</p>
 <p>Features and ideas being developed or discussed by the Go team.</p>
 
 <h3 id="release"><a href="devel/release.html">Release History</a></h3>
-<p>A summary of the changes between tagged releases of Go.</p>
+<p>A summary of the changes between Go releases.</p>
+
+<h3 id="release"><a href="devel/weekly.html">Weekly Snapshot History</a></h3>
+<p>A summary of the changes between weekly snapshots of Go.</p>
 
 <h3 id="golang-dev"><a href="http://groups.google.com/group/golang-dev">Developer Mailing List</a></h3>
 <p>The <a href="http://groups.google.com/group/golang-dev">golang-dev</a>
diff --git a/doc/devel/weekly.html b/doc/devel/weekly.html
index dc73407..40b4efe 100644
--- a/doc/devel/weekly.html
+++ b/doc/devel/weekly.html
@@ -14,6 +14,127 @@ hg pull
 hg update weekly.<i>YYYY-MM-DD</i>
 </pre>
 
+<h2 id="2011-06-02">2011-06-02</h2>
+
+<pre>
+This release 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.
+This code:
+	args := []string{“diff”, “-u”, “file1.txt”, “file2.txt”}
+	p, err := exec.Run(“/usr/bin/diff”, args, os.Environ(), "",
+		exec.DevNull, exec.Pipe, exec.DevNull)
+	if err != nil {
+		return nil, err
+	}
+	var buf bytes.Buffer
+	io.Copy(&buf, p.Stdout)
+	w, err := p.Wait(0)
+	p.Close()
+	if err != nil {
+		return nil, err
+	}
+	return buf.Bytes(), err
+can be rewritten as:
+	return exec.Command(“diff”, “-u”, “file1.txt”, “file2.txt”).Output()
+See the exec package documentation for the details ("godoc exec").
+
+By setting the GOPATH environment variable you can use goinstall to build and
+install your own code and external libraries outside of the Go tree (and avoid
+writing Makefiles).
+See the goinstall command documentation for the details ("godoc goinstall").
+
+Other changes:
+* 5g: alignment fixes.
+* 6l, 8l: fix Mach-O binaries with many dynamic libraries.
+* 8l: emit resources (.rsrc) in Windows PE.  (thanks Wei Guangjing).
+* asn1: fix marshalling of empty optional RawValues (thanks Mikkel Krautz).
+* big: make Int and Rat implement fmt.Scanner (thanks Evan Shaw),
+	~8x faster number scanning,
+	remove some unnecessary conversions.
+* cgo: restrict #cgo directives to prevent shell expansion (thanks Gustavo Niemeyer),
+	support pkg-config for flags and libs (thanks Gustavo Niemeyer).
+* compress/flate: fix Huffman tree bug,
+	do not use background goroutines.
+* crypto/openpgp: add support for symmetrically encrypting files.
+* crypto/tls/generate_cert.go: fix misspelling of O_CREATE.
+* dashboard: send notification emails when the build breaks.
+* doc: mention go/printer instead of container/vector in effective go,
+	put Release History link on 'Documentation' page,
+	put Weekly Snapshot History link on 'Contributing' page.
+* encoding/base64: add DecodeString and EncodeToString.
+* encoding/binary: add a non-reflect fast path for Read,
+	add a non-reflect fast path for Write.
+* encoding/hex: add hex dumping.
+* encoding/line: delete package. Its functionality is now in bufio.
+* filepath: Abs must always return a clean path (thanks Gustavo Niemeyer).
+* fmt: fix bug in UnreadRune,
+	make %q work for integers, printing a quoted character literal,
+	return EOF when out of input in Scan*.
+* gc: check parameter declarations in interface fields (thanks Anthony Martin),
+	disallow ... in type conversions (thanks Anthony Martin),
+	do not force heap allocation on referencing outer variable in a closure,
+	fix m[x], _ = y.(T),
+	implement new shift rules,
+	patch y.tab.c to fix build when using Bison 2.5,
+	relax assignability of method receivers (thanks Anthony Martin),
+	typecheck the whole tree before walking.
+* go/scanner: don't allow "0x" and "0X" as integers (thanks Evan Shaw).
+* gobuilder: fixes for windows (thanks Alex Brainman).
+* godoc: basic setup for running godoc on local app engine emulator,
+	display advert for the package dashboard on package list page.
+* 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: Transport hook to register non-http(s) protocols,
+	add client+server benchmark,
+	catch Handler goroutine panics,
+	fix Set-Cookie date parsing,
+	have client set Content-Length when possible,
+	let Transport use a custom net.Dial function,
+	propagate Set-Cookie in reverse proxy,
+	ServeFile shouldn't send Content-Length when Content-Encoding is set.
+* image: add a SubImage method.
+* image/gif: simplify blockReader.Read.
+* image/png: fix encoding of images that don't start at (0, 0).
+* io, net, http: sendfile support.
+* io: add ByteScanner, RuneScanner interfaces.
+* ld: add -w to disable dwarf, make errors obviously from dwarf.
+* mail: new package.
+* mime/multipart: misc code/doc fixes.
+* misc/cgo: remove reference to 'destroy' function.
+* misc/emacs: don't select the mark after gofmt (thanks Eric Eisner).
+* misc/gophertool: Chrome extension to aid in Go development
+* misc/vim: limit Fmt command to Go buffers (thanks Yasuhiro Matsumoto).
+* net: if we stop polling, remove any pending events for the socket,
+	update IP multicast socket options (thanks Mikio Hara).
+* os: Fix test to work on Solaris,
+	fix Readdir(0) on EOF,
+	fix Readdir, Readdirnames (thanks Yuval Pavel Zholkover),
+	fix os.MkdirAll with backslash path separator (thanks Yasuhiro Matsumoto),
+	handle OpenFile flag parameter properly on Windows (thanks Alex Brainman).
+* path/filepath: remove string constants.
+* pkg: spelling tweaks, I-Z (thanks Robert Hencke).
+* quietgcc: fix typo, respect $TMPDIR.
+* runtime: do not garbage collect windows callbacks (thanks Alex Brainman),
+	fix mmap error return on linux (thanks Dmitry Chestnykh),
+	reset GOMAXPROCS during tests,
+	save cdecl registers in Windows SEH handler (thanks Alexey Borzenkov).
+* spec: be precise with the use of the informal ellipsis and the Go token,
+	clarify rules for shifts.
+* strconv: add QuoteRune; analogous to Quote but for runes rather than strings.
+* strings: implement UnreadByte, UnreadRune.
+* sync: always wake up sleeping goroutines on Cond.Signal (thanks Gustavo Niemeyer).
+* sync/atomic: fix check64.
+* syscall: add ProcAttr field to pass an unescaped command line on windows (thanks Vincent Vanackere),
+	add routing messages support for Linux and BSD (thanks Mikio Hara).
+* template: fixes and clean-ups (thanks Gustavo Niemeyer).
+* time: fix Format bug: midnight/noon are 12AM/PM not 0AM/PM.
+* unicode: make the tables smaller.
+</pre>
+
 <h2 id="2011-05-22">2011-05-22</h2>
 
 <pre>
diff --git a/doc/docs.html b/doc/docs.html
index 50df221..f6ff05c 100644
--- a/doc/docs.html
+++ b/doc/docs.html
@@ -59,6 +59,12 @@ An introduction to Go for C++ programmers.
 
 <h2 id="tutorials_nonenglish">Non-English Documentation</h2>
 
+<h3 id="docs_be">Belarusian — Беларуская</h3>
+
+<ul>
+<li><a href="http://www.designcontest.com/show/faq-be">faq-be</a> - Frequently Asked Questions.</li>
+</ul>
+
 <h3 id="docs_cn">Chinese — 中文</h3>
 
 <ul>
@@ -113,6 +119,9 @@ The built-in documentation for the Go tools.
 The official Go Language specification. 
 </p>
 
+<h3 id="release"><a href="devel/release.html">Release History</a></h3>
+<p>A summary of the changes between Go releases.</p>
+
 <h3 id="go_mem"><a href="go_mem.html">The Go Memory Model</a></h3>
 <p>
 A document that specifies the conditions under which reads of a variable in
diff --git a/doc/effective_go.html b/doc/effective_go.html
index 86b2d63..972772d 100644
--- a/doc/effective_go.html
+++ b/doc/effective_go.html
@@ -297,9 +297,9 @@ determines just which package is being used.
 <p>
 Another convention is that the package name is the base name of
 its source directory;
-the package in <code>src/pkg/container/vector</code>
-is imported as <code>"container/vector"</code> but has name <code>vector</code>,
-not <code>container_vector</code> and not <code>containerVector</code>.
+the package in <code>src/pkg/encoding/base64</code>
+is imported as <code>"encoding/base64"</code> but has name <code>base64</code>,
+not <code>encoding_base64</code> and not <code>encodingBase64</code>.
 </p>
 
 <p>
@@ -935,13 +935,14 @@ example of its possibilities.
 
 <h2 id="data">Data</h2>
 
-<h3 id="allocation_new">Allocation with <code>new()</code></h3>
+<h3 id="allocation_new">Allocation with <code>new</code></h3>
 
 <p>
-Go has two allocation primitives, <code>new()</code> and <code>make()</code>.
+Go has two allocation primitives, the built-in functions
+<code>new</code> and <code>make</code>.
 They do different things and apply to different types, which can be confusing,
 but the rules are simple.
-Let's talk about <code>new()</code> first.
+Let's talk about <code>new</code> first.
 It's a built-in function essentially the same as its namesakes
 in other languages: <code>new(T)</code> allocates zeroed storage for a new item of type
 <code>T</code> and returns its address, a value of type <code>*T</code>.
@@ -950,9 +951,9 @@ In Go terminology, it returns a pointer to a newly allocated zero value of type
 </p>
 
 <p>
-Since the memory returned by <code>new()</code> is zeroed, it's helpful to arrange that the
+Since the memory returned by <code>new</code> is zeroed, it's helpful to arrange that the
 zeroed object can be used without further initialization.  This means a user of
-the data structure can create one with <code>new()</code> and get right to
+the data structure can create one with <code>new</code> and get right to
 work.
 For example, the documentation for <code>bytes.Buffer</code> states that
 "the zero value for <code>Buffer</code> is an empty buffer ready to use."
@@ -1065,7 +1066,7 @@ s := []string      {Enone: "no error", Eio: "Eio", Einval: "invalid argument"}
 m := map[int]string{Enone: "no error", Eio: "Eio", Einval: "invalid argument"}
 </pre>
 
-<h3 id="allocation_make">Allocation with <code>make()</code></h3>
+<h3 id="allocation_make">Allocation with <code>make</code></h3>
 
 <p>
 Back to allocation.
@@ -1099,8 +1100,8 @@ In contrast, <code>new([]int)</code> returns a pointer to a newly allocated, zer
 structure, that is, a pointer to a <code>nil</code> slice value.
 
 <p>
-These examples illustrate the difference between <code>new()</code> and
-<code>make()</code>.
+These examples illustrate the difference between <code>new</code> and
+<code>make</code>.
 </p>
 
 <pre>
@@ -1116,9 +1117,9 @@ v := make([]int, 100)
 </pre>
 
 <p>
-Remember that <code>make()</code> applies only to maps, slices and channels
+Remember that <code>make</code> applies only to maps, slices and channels
 and does not return a pointer.
-To obtain an explicit pointer allocate with <code>new()</code>.
+To obtain an explicit pointer allocate with <code>new</code>.
 </p>
 
 <h3 id="arrays">Arrays</h3>
@@ -1473,7 +1474,7 @@ map[string] int
 </pre>
 <p>
 If you want to control the default format for a custom type, all that's required is to define
-a method <code>String() string</code> on the type.
+a method with the signature <code>String() string</code> on the type.
 For our simple type <code>T</code>, that might look like this.
 </p>
 <pre>
@@ -1495,7 +1496,7 @@ that's more efficient and idiomatic for struct types.
 See the section below on <a href="#pointers_vs_values">pointers vs. value receivers</a> for more information.)
 </p>
 <p>
-Our <code>String()</code> method is able to call <code>Sprintf</code> because the
+Our <code>String</code> method is able to call <code>Sprintf</code> because the
 print routines are fully reentrant and can be used recursively.
 We can even go one step further and pass a print routine's arguments directly to another such routine.
 The signature of <code>Printf</code> uses the type <code>...interface{}</code>
@@ -1683,19 +1684,20 @@ var (
 <h3 id="init">The init function</h3>
 
 <p>
-Finally, each source file can define its own <code>init()</code> function to
-set up whatever state is required.  The only restriction is that, although
+Finally, each source file can define its own niladic <code>init</code> function to
+set up whatever state is required.  (Actually each file can have multiple
+<code>init</code> functions.) The only restriction is that, although
 goroutines can be launched during initialization, they will not begin
 execution until it completes; initialization always runs as a single thread
 of execution.
-And finally means finally: <code>init()</code> is called after all the
+And finally means finally: <code>init</code> is called after all the
 variable declarations in the package have evaluated their initializers,
 and those are evaluated only after all the imported packages have been
 initialized.
 </p>
 <p>
 Besides initializations that cannot be expressed as declarations,
-a common use of <code>init()</code> functions is to verify or repair
+a common use of <code>init</code> functions is to verify or repair
 correctness of the program state before real execution begins.
 </p>
 
@@ -1899,7 +1901,7 @@ on every instance of a common method.
 In such cases, the constructor should return an interface value
 rather than the implementing type.
 As an example, in the hash libraries
-both <code>crc32.NewIEEE()</code> and <code>adler32.New()</code>
+both <code>crc32.NewIEEE</code> and <code>adler32.New</code>
 return the interface type <code>hash.Hash32</code>.
 Substituting the CRC-32 algorithm for Adler-32 in a Go program
 requires only changing the constructor call;
diff --git a/doc/go_spec.html b/doc/go_spec.html
index 5f8b5e6..0c08e14 100644
--- a/doc/go_spec.html
+++ b/doc/go_spec.html
@@ -1,5 +1,5 @@
 <!-- title The Go Programming Language Specification -->
-<!-- subtitle Version of May 15, 2011 -->
+<!-- subtitle Version of May 24, 2011 -->
 
 <!--
 TODO
@@ -10,7 +10,6 @@ TODO
 [ ] clarify what a field name is in struct declarations
     (struct{T} vs struct {T T} vs struct {t T})
 [ ] need explicit language about the result type of operations
-[ ] may want to have some examples for the types of shift operations
 [ ] should string(1<<s) and float32(1<<s) be valid?
 [ ] should probably write something about evaluation order of statements even
 	though obvious
@@ -49,7 +48,7 @@ The syntax is specified using Extended Backus-Naur Form (EBNF):
 Production  = production_name "=" [ Expression ] "." .
 Expression  = Alternative { "|" Alternative } .
 Alternative = Term { Term } .
-Term        = production_name | token [ "..." token ] | Group | Option | Repetition .
+Term        = production_name | token [ "…" token ] | Group | Option | Repetition .
 Group       = "(" Expression ")" .
 Option      = "[" Expression "]" .
 Repetition  = "{" Expression "}" .
@@ -73,8 +72,12 @@ double quotes <code>""</code> or back quotes <code>``</code>.
 </p>
 
 <p>
-The form <code>a ... b</code> represents the set of characters from
-<code>a</code> through <code>b</code> as alternatives.
+The form <code>a … b</code> represents the set of characters from
+<code>a</code> through <code>b</code> as alternatives. The horizontal
+ellipis … is also used elsewhere in the spec to informally denote various
+enumerations or code snippets that are not further specified. The character …
+(as opposed to the three characters <code>...</code>) is not a token of the Go
+language.
 </p>
 
 <h2 id="Source_code_representation">Source code representation</h2>
@@ -123,9 +126,9 @@ The underscore character <code>_</code> (U+005F) is considered a letter.
 </p>
 <pre class="ebnf">
 letter        = unicode_letter | "_" .
-decimal_digit = "0" ... "9" .
-octal_digit   = "0" ... "7" .
-hex_digit     = "0" ... "9" | "A" ... "F" | "a" ... "f" .
+decimal_digit = "0" … "9" .
+octal_digit   = "0" … "7" .
+hex_digit     = "0" … "9" | "A" … "F" | "a" … "f" .
 </pre>
 
 <h2 id="Lexical_elements">Lexical elements</h2>
@@ -287,7 +290,7 @@ An optional prefix sets a non-decimal base: <code>0</code> for octal, <code>0x</
 </p>
 <pre class="ebnf">
 int_lit     = decimal_lit | octal_lit | hex_lit .
-decimal_lit = ( "1" ... "9" ) { decimal_digit } .
+decimal_lit = ( "1" … "9" ) { decimal_digit } .
 octal_lit   = "0" { octal_digit } .
 hex_lit     = "0" ( "x" | "X" ) hex_digit { hex_digit } .
 </pre>
@@ -822,7 +825,7 @@ make([]T, length, capacity)
 </pre>
 
 <p>
-The <code>make()</code> call allocates a new, hidden array to which the returned
+A call to <code>make</code> allocates a new, hidden array to which the returned
 slice value refers. That is, executing
 </p>
 
@@ -1054,9 +1057,9 @@ have the method set
 </p>
 
 <pre>
-func (p T) Read(b Buffer) bool { return ... }
-func (p T) Write(b Buffer) bool { return ... }
-func (p T) Close() { ... }
+func (p T) Read(b Buffer) bool { return … }
+func (p T) Write(b Buffer) bool { return … }
+func (p T) Close() { … }
 </pre>
 
 <p>
@@ -1094,8 +1097,8 @@ If <code>S1</code> and <code>S2</code> also implement
 </p>
 
 <pre>
-func (p T) Lock() { ... }
-func (p T) Unlock() { ... }
+func (p T) Lock() { … }
+func (p T) Unlock() { … }
 </pre>
 
 <p>
@@ -1177,7 +1180,6 @@ maps grow to accommodate the number of items
 stored in them, with the exception of <code>nil</code> maps.
 A <code>nil</code> map is equivalent to an empty map except that no elements
 may be added.
-</code>
 
 <h3 id="Channel_types">Channel types</h3>
 
@@ -1697,7 +1699,7 @@ of an interface type or of elements of a composite type remains unchanged:
 </p>
 
 <pre>
-// A Mutex is a data type with two methods Lock and Unlock.
+// A Mutex is a data type with two methods, Lock and Unlock.
 type Mutex struct         { /* Mutex fields */ }
 func (m *Mutex) Lock()    { /* Lock implementation */ }
 func (m *Mutex) Unlock()  { /* Unlock implementation */ }
@@ -2100,7 +2102,7 @@ element index plus one. A slice literal has the form
 </p>
 
 <pre>
-[]T{x1, x2, ... xn}
+[]T{x1, x2, … xn}
 </pre>
 
 <p>
@@ -2108,7 +2110,7 @@ and is a shortcut for a slice operation applied to an array literal:
 </p>
 
 <pre>
-[n]T{x1, x2, ... xn}[0 : n]
+[n]T{x1, x2, … xn}[0 : n]
 </pre>
 
 <p>
@@ -2134,8 +2136,8 @@ parentheses.
 </p>
 
 <pre>
-if x == (T{a,b,c}[i]) { ... }
-if (x == T{a,b,c}[i]) { ... }
+if x == (T{a,b,c}[i]) { … }
+if (x == T{a,b,c}[i]) { … }
 </pre>
 
 <p>
@@ -2568,11 +2570,11 @@ Given an expression <code>f</code> of function type
 </p>
 
 <pre>
-f(a1, a2, ... an)
+f(a1, a2, … an)
 </pre>
 
 <p>
-calls <code>f</code> with arguments <code>a1, a2, ... an</code>.
+calls <code>f</code> with arguments <code>a1, a2, … an</code>.
 Except for one special case, arguments must be single-valued expressions
 <a href="#Assignability">assignable</a> to the parameter types of
 <code>F</code> and are evaluated before the function is called.
@@ -2651,7 +2653,7 @@ arguments bound to the final parameter and may differ for each call site.
 Given the function and call
 </p>
 <pre>
-func Greeting(prefix string, who ... string)
+func Greeting(prefix string, who ...string)
 Greeting("hello:", "Joe", "Anna", "Eileen")
 </pre>
 
@@ -2702,42 +2704,34 @@ unary_op   = "+" | "-" | "!" | "^" | "*" | "&" | "<-" .
 <p>
 Comparisons are discussed <a href="#Comparison_operators">elsewhere</a>.
 For other binary operators, the operand types must be <a href="#Type_identity">identical</a>
-unless the operation involves channels, shifts, or untyped <a href="#Constants">constants</a>.
+unless the operation involves shifts or untyped <a href="#Constants">constants</a>.
 For operations involving constants only, see the section on
 <a href="#Constant_expressions">constant expressions</a>.
 </p>
 
 <p>
-In a channel send, the first operand is always a channel and the second
-must be a value <a href="#Assignability">assignable</a>
-to the channel's element type.
-</p>
-
-<p>
-Except for shift operations,
-if one operand is an untyped <a href="#Constants">constant</a>
+Except for shift operations, if one operand is an untyped <a href="#Constants">constant</a>
 and the other operand is not, the constant is <a href="#Conversions">converted</a>
 to the type of the other operand.
 </p>
 
 <p>
-The right operand in a shift operation must have unsigned integer type
+The right operand in a shift expression must have unsigned integer type
 or be an untyped constant that can be converted to unsigned integer type.
-</p>
-
-<p>
-If the left operand of a non-constant shift operation is an untyped constant,
-the type of constant is what it would be if the shift operation were replaced by
-the left operand alone.
+If the left operand of a non-constant shift expression is an untyped constant,
+the type of the constant is what it would be if the shift expression were
+replaced by its left operand alone.
 </p>
 
 <pre>
 var s uint = 33
-var i = 1<<s            // 1 has type int
-var j = int32(1<<s)     // 1 has type int32; j == 0
-var u = uint64(1<<s)    // 1 has type uint64; u == 1<<33
-var f = float32(1<<s)   // illegal: 1 has type float32, cannot shift
-var g = float32(1<<33)  // legal; 1<<33 is a constant shift operation; g == 1<<33
+var i = 1<<s           // 1 has type int
+var j int32 = 1<<s     // 1 has type int32; j == 0
+var k = uint64(1<<s)   // 1 has type uint64; k == 1<<33
+var m int = 1.0<<s     // legal: 1.0 has type int
+var u = 1.0<<s         // illegal: 1.0 has type float64, cannot shift
+var v float32 = 1<<s   // illegal: 1 has type float32, cannot shift
+var w int64 = 1.0<<33  // legal: 1.0<<33 is a constant shift expression
 </pre>
 
 <h3 id="Operator_precedence">Operator precedence</h3>
@@ -2869,8 +2863,8 @@ be replaced by a bitwise "and" operation:
 <p>
 The shift operators shift the left operand by the shift count specified by the
 right operand. They implement arithmetic shifts if the left operand is a signed
-integer and logical shifts if it is an unsigned integer. The shift count must
-be an unsigned integer. There is no upper limit on the shift count. Shifts behave
+integer and logical shifts if it is an unsigned integer.
+There is no upper limit on the shift count. Shifts behave
 as if the left operand is shifted <code>n</code> times by 1 for a shift
 count of <code>n</code>.
 As a result, <code>x << 1</code> is the same as <code>x*2</code>
@@ -3382,21 +3376,35 @@ 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
+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.
 </p>
 
 <p>
-Applying an operator to untyped constants results in an untyped
+A constant <a href="#Comparison_operators">comparison</a> always yields
+a constant of type <code>bool</code>. 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
+(§<a href="#Arithmetic_operators">Arithmetic operators</a>).
+Applying all other operators to untyped constants results in an untyped
 constant of the same kind (that is, a boolean, integer, floating-point,
-complex, or string constant), except for
-<a href="#Comparison_operators">comparison operators</a>, which result in
-a constant of type <code>bool</code>.
+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 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)
+</pre>
+
 <p>
 Imaginary literals are untyped complex constants (with zero real part)
 and may be combined in binary
@@ -4886,7 +4894,7 @@ package main
 
 import "fmt"
 
-// Send the sequence 2, 3, 4, ... to channel 'ch'.
+// Send the sequence 2, 3, 4, … to channel 'ch'.
 func generate(ch chan<- int) {
 	for i := 2; ; i++ {
 		ch <- i  // Send 'i' to channel 'ch'.
@@ -4926,7 +4934,7 @@ func main() {
 <h3 id="The_zero_value">The zero value</h3>
 <p>
 When memory is allocated to store a value, either through a declaration
-or <code>make()</code> or <code>new()</code> call,
+or a call of <code>make</code> or <code>new</code>,
 and no explicit initialization is provided, the memory is
 given a default initialization.  Each element of such a value is
 set to the <i>zero value</i> for its type: <code>false</code> for booleans,
@@ -4984,7 +4992,7 @@ func init()
 <p>
 defined in its source.
 A package may contain multiple
-<code>init()</code> functions, even
+<code>init</code> functions, even
 within a single source file; they execute
 in unspecified order.
 </p>
@@ -5014,8 +5022,8 @@ 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,
+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.
 </p>
 <p>
@@ -5037,7 +5045,7 @@ arguments and returns no value.
 </p>
 
 <pre>
-func main() { ... }
+func main() { … }
 </pre>
 
 <p>
diff --git a/doc/go_tutorial.html b/doc/go_tutorial.html
index c87254e..cfdd0ec 100644
--- a/doc/go_tutorial.html
+++ b/doc/go_tutorial.html
@@ -341,7 +341,7 @@ Using slices one can write this function (from <code>sum.go</code>):
 15    }
 </pre>
 <p>
-Note how the return type (<code>int</code>) is defined for <code>sum()</code> by stating it
+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
@@ -373,7 +373,7 @@ There are also maps, which you can initialize like this:
     m := map[string]int{"one":1 , "two":2}
 </pre>
 <p>
-The built-in function <code>len()</code>, which returns number of elements,
+The built-in function <code>len</code>, which returns number of elements,
 makes its first appearance in <code>sum</code>.  It works on strings, arrays,
 slices, maps, and channels.
 <p>
@@ -401,7 +401,7 @@ for more examples of its use.
 Most types in Go are values. If you have an <code>int</code> or a <code>struct</code>
 or an array, assignment
 copies the contents of the object.
-To allocate a new variable, use <code>new()</code>, which
+To allocate a new variable, use the built-in function <code>new</code>, which
 returns a pointer to the allocated storage.
 <p>
 <pre>
@@ -418,7 +418,7 @@ or the more idiomatic
 Some types—maps, slices, and channels (see below)—have reference semantics.
 If you're holding a slice or a map and you modify its contents, other variables
 referencing the same underlying data will see the modification.  For these three
-types you want to use the built-in function <code>make()</code>:
+types you want to use the built-in function <code>make</code>:
 <p>
 <pre>
     m := make(map[string]int)
@@ -432,11 +432,11 @@ If you just declare the map, as in
 </pre>
 <p>
 it creates a <code>nil</code> reference that cannot hold anything. To use the map,
-you must first initialize the reference using <code>make()</code> or by assignment from an
+you must first initialize the reference using <code>make</code> or by assignment from an
 existing map.
 <p>
 Note that <code>new(T)</code> returns type <code>*T</code> while <code>make(T)</code> returns type
-<code>T</code>.  If you (mistakenly) allocate a reference object with <code>new()</code>,
+<code>T</code>.  If you (mistakenly) allocate a reference object with <code>new</code> rather than <code>make</code>,
 you receive a pointer to a nil reference, equivalent to
 declaring an uninitialized variable and taking its address.
 <p>
@@ -767,7 +767,7 @@ Building on the <code>file</code> package, here's a simple version of the Unix u
 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
 initialization statement.  The <code>switch</code> on line 18 uses one to create variables
-<code>nr</code> and <code>er</code> to hold the return values from <code>f.Read()</code>.  (The <code>if</code> on line 25
+<code>nr</code> and <code>er</code> to hold the return values from the call to <code>f.Read</code>.  (The <code>if</code> on line 25
 has the same idea.)  The <code>switch</code> statement is general: it evaluates the cases
 from  top to bottom looking for the first case that matches the value; the
 case expressions don't need to be constants or even integers, as long as
@@ -779,14 +779,14 @@ in a <code>for</code> statement, a missing value means <code>true</code>.  In fa
 is a form of <code>if-else</code> chain. While we're here, it should be mentioned that in
 <code>switch</code> statements each <code>case</code> has an implicit <code>break</code>.
 <p>
-Line 25 calls <code>Write()</code> by slicing the incoming buffer, which is itself a slice.
+Line 25 calls <code>Write</code> by slicing the incoming buffer, which is itself a slice.
 Slices provide the standard Go way to handle I/O buffers.
 <p>
 Now let's make a variant of <code>cat</code> that optionally does <code>rot13</code> on its input.
 It's easy to do by just processing the bytes, but instead we will exploit
 Go's notion of an <i>interface</i>.
 <p>
-The <code>cat()</code> subroutine uses only two methods of <code>f</code>: <code>Read()</code> and <code>String()</code>,
+The <code>cat</code> subroutine uses only two methods of <code>f</code>: <code>Read</code> and <code>String</code>,
 so let's start by defining an interface that has exactly those two methods.
 Here is code from <code>progs/cat_rot13.go</code>:
 <p>
@@ -838,7 +838,7 @@ To use the new feature, we define a flag:
 14    var rot13Flag = flag.Bool("rot13", false, "rot13 the input")
 </pre>
 <p>
-and use it from within a mostly unchanged <code>cat()</code> function:
+and use it from within a mostly unchanged <code>cat</code> function:
 <p>
 <pre> <!-- progs/cat_rot13.go /func.cat/ /^}/ -->
 52    func cat(r reader) {
@@ -866,7 +866,7 @@ and use it from within a mostly unchanged <code>cat()</code> function:
 74    }
 </pre>
 <p>
-(We could also do the wrapping in <code>main</code> and leave <code>cat()</code> mostly alone, except
+(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.)
 Lines 56 through 58 set it all up: If the <code>rot13</code> flag is true, wrap the <code>reader</code>
 we received into a <code>rotate13</code> and proceed.  Note that the interface variables
@@ -1055,7 +1055,7 @@ to that of the <code>Printf</code> call above.
 </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
+just give it a <code>String</code> method that returns a string.  The print
 routines will examine the value to inquire whether it implements
 the method and if so, use it rather than some other formatting.
 Here's a simple example.
@@ -1076,14 +1076,14 @@ Here's a simple example.
 21    }
 </pre>
 <p>
-Since <code>*testType</code> has a <code>String()</code> method, the
+Since <code>*testType</code> has a <code>String</code> method, the
 default formatter for that type will use it and produce the output
 <p>
 <pre>
     77 Sunset Strip
 </pre>
 <p>
-Observe that the <code>String()</code> method calls <code>Sprint</code> (the obvious Go
+Observe that the <code>String</code> method calls <code>Sprint</code> (the obvious Go
 variant that returns a string) to do its formatting; special formatters
 can use the <code>fmt</code> library recursively.
 <p>
@@ -1096,7 +1096,7 @@ and such, but that's getting a little off the main thread so we'll leave it
 as an exploration exercise.
 <p>
 You might ask, though, how <code>Printf</code> can tell whether a type implements
-the <code>String()</code> method.  Actually what it does is ask if the value can
+the <code>String</code> method.  Actually what it does is ask if the value can
 be converted to an interface variable that implements the method.
 Schematically, given a value <code>v</code>, it does this:
 <p>
@@ -1141,7 +1141,7 @@ interface type defined in the <code>io</code> library:
 <p>
 (This interface is another conventional name, this time for <code>Write</code>; there are also
 <code>io.Reader</code>, <code>io.ReadWriter</code>, and so on.)
-Thus you can call <code>Fprintf</code> on any type that implements a standard <code>Write()</code>
+Thus you can call <code>Fprintf</code> on any type that implements a standard <code>Write</code>
 method, not just files but also network channels, buffers, whatever
 you want.
 <p>
diff --git a/doc/go_tutorial.txt b/doc/go_tutorial.txt
index ab02baf..ebf58ec 100644
--- a/doc/go_tutorial.txt
+++ b/doc/go_tutorial.txt
@@ -272,7 +272,7 @@ Using slices one can write this function (from "sum.go"):
 
 --PROG progs/sum.go /sum/ /^}/
 
-Note how the return type ("int") is defined for "sum()" by stating it
+Note how the return type ("int") is defined for "sum" by stating it
 after the parameter list.
 
 To call the function, we slice the array.  This intricate call (we'll show
@@ -296,7 +296,7 @@ There are also maps, which you can initialize like this:
 
 	m := map[string]int{"one":1 , "two":2}
 
-The built-in function "len()", which returns number of elements,
+The built-in function "len", which returns number of elements,
 makes its first appearance in "sum".  It works on strings, arrays,
 slices, maps, and channels.
 
@@ -321,7 +321,7 @@ An Interlude about Allocation
 Most types in Go are values. If you have an "int" or a "struct"
 or an array, assignment
 copies the contents of the object.
-To allocate a new variable, use "new()", which
+To allocate a new variable, use the built-in function "new", which
 returns a pointer to the allocated storage.
 
 	type T struct { a, b int }
@@ -334,7 +334,7 @@ or the more idiomatic
 Some types—maps, slices, and channels (see below)—have reference semantics.
 If you're holding a slice or a map and you modify its contents, other variables
 referencing the same underlying data will see the modification.  For these three
-types you want to use the built-in function "make()":
+types you want to use the built-in function "make":
 
 	m := make(map[string]int)
 
@@ -344,11 +344,11 @@ If you just declare the map, as in
 	var m map[string]int
 
 it creates a "nil" reference that cannot hold anything. To use the map,
-you must first initialize the reference using "make()" or by assignment from an
+you must first initialize the reference using "make" or by assignment from an
 existing map.
 
 Note that "new(T)" returns type "*T" while "make(T)" returns type
-"T".  If you (mistakenly) allocate a reference object with "new()",
+"T".  If you (mistakenly) allocate a reference object with "new" rather than "make",
 you receive a pointer to a nil reference, equivalent to
 declaring an uninitialized variable and taking its address.
 
@@ -526,7 +526,7 @@ Building on the "file" package, here's a simple version of the Unix utility "cat
 By now this should be easy to follow, but the "switch" statement introduces some
 new features.  Like a "for" loop, an "if" or "switch" can include an
 initialization statement.  The "switch" on line 18 uses one to create variables
-"nr" and "er" to hold the return values from "f.Read()".  (The "if" on line 25
+"nr" and "er" to hold the return values from the call to "f.Read".  (The "if" on line 25
 has the same idea.)  The "switch" statement is general: it evaluates the cases
 from  top to bottom looking for the first case that matches the value; the
 case expressions don't need to be constants or even integers, as long as
@@ -538,14 +538,14 @@ in a "for" statement, a missing value means "true".  In fact, such a "switch"
 is a form of "if-else" chain. While we're here, it should be mentioned that in
 "switch" statements each "case" has an implicit "break".
 
-Line 25 calls "Write()" by slicing the incoming buffer, which is itself a slice.
+Line 25 calls "Write" by slicing the incoming buffer, which is itself a slice.
 Slices provide the standard Go way to handle I/O buffers.
 
 Now let's make a variant of "cat" that optionally does "rot13" on its input.
 It's easy to do by just processing the bytes, but instead we will exploit
 Go's notion of an <i>interface</i>.
 
-The "cat()" subroutine uses only two methods of "f": "Read()" and "String()",
+The "cat" subroutine uses only two methods of "f": "Read" and "String",
 so let's start by defining an interface that has exactly those two methods.
 Here is code from "progs/cat_rot13.go":
 
@@ -569,11 +569,11 @@ To use the new feature, we define a flag:
 
 --PROG progs/cat_rot13.go /rot13Flag/
 
-and use it from within a mostly unchanged "cat()" function:
+and use it from within a mostly unchanged "cat" function:
 
 --PROG progs/cat_rot13.go /func.cat/ /^}/
 
-(We could also do the wrapping in "main" and leave "cat()" mostly alone, except
+(We could also do the wrapping in "main" and leave "cat" mostly alone, except
 for changing the type of the argument; consider that an exercise.)
 Lines 56 through 58 set it all up: If the "rot13" flag is true, wrap the "reader"
 we received into a "rotate13" and proceed.  Note that the interface variables
@@ -701,19 +701,19 @@ to that of the "Printf" call above.
 --PROG progs/print.go 'NR==21' 'NR==22'
 
 If you have your own type you'd like "Printf" or "Print" to format,
-just give it a "String()" method that returns a string.  The print
+just give it a "String" method that returns a string.  The print
 routines will examine the value to inquire whether it implements
 the method and if so, use it rather than some other formatting.
 Here's a simple example.
 
 --PROG progs/print_string.go 'NR==9' END
 
-Since "*testType" has a "String()" method, the
+Since "*testType" has a "String" method, the
 default formatter for that type will use it and produce the output
 
 	77 Sunset Strip
 
-Observe that the "String()" method calls "Sprint" (the obvious Go
+Observe that the "String" method calls "Sprint" (the obvious Go
 variant that returns a string) to do its formatting; special formatters
 can use the "fmt" library recursively.
 
@@ -726,7 +726,7 @@ and such, but that's getting a little off the main thread so we'll leave it
 as an exploration exercise.
 
 You might ask, though, how "Printf" can tell whether a type implements
-the "String()" method.  Actually what it does is ask if the value can
+the "String" method.  Actually what it does is ask if the value can
 be converted to an interface variable that implements the method.
 Schematically, given a value "v", it does this:
 
@@ -765,7 +765,7 @@ interface type defined in the "io" library:
 
 (This interface is another conventional name, this time for "Write"; there are also
 "io.Reader", "io.ReadWriter", and so on.)
-Thus you can call "Fprintf" on any type that implements a standard "Write()"
+Thus you can call "Fprintf" on any type that implements a standard "Write"
 method, not just files but also network channels, buffers, whatever
 you want.
 
diff --git a/doc/root.html b/doc/root.html
index 6722d00..8d76928 100644
--- a/doc/root.html
+++ b/doc/root.html
@@ -78,6 +78,7 @@ google.setOnLoadCallback(loadFeed);
             <li><a href="/doc/effective_go.html">Effective Go</a></li>
             <li><a href="/doc/go_faq.html">Go FAQ</a></li>
             <li><a href="/doc/docs.html">Other Documentation</a></li>
+            <li><a href="http://code.google.com/appengine/docs/go/">Go for Google App Engine</a> <sup class="new">New!</sup></li>
           </ul>
         </div>
         <div id="resources-contributors" >
diff --git a/lib/godoc/package.html b/lib/godoc/package.html
index 4205f93..cb3ffa2 100644
--- a/lib/godoc/package.html
+++ b/lib/godoc/package.html
@@ -91,6 +91,11 @@
 	</p>
 {.end}
 {.section 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>
diff --git a/misc/cgo/gmp/gmp.go b/misc/cgo/gmp/gmp.go
index f7bbe9c..7faa71b 100644
--- a/misc/cgo/gmp/gmp.go
+++ b/misc/cgo/gmp/gmp.go
@@ -86,9 +86,8 @@ explicitly in Go to pointers to arrays, as they do (implicitly) in C.
 
 Garbage collection is the big problem.  It is fine for the Go world to
 have pointers into the C world and to free those pointers when they
-are no longer needed.  To help, the garbage collector calls an
-object's destroy() method prior to collecting it.  C pointers can be
-wrapped by Go objects with appropriate destroy methods.
+are no longer needed.  To help, the Go code can define Go objects
+holding the C pointers and use runtime.SetFinalizer on those Go objects.
 
 It is much more difficult for the C world to have pointers into the Go
 world, because the Go garbage collector is unaware of the memory
diff --git a/misc/chrome/gophertool/README.txt b/misc/chrome/gophertool/README.txt
new file mode 100644
index 0000000..a7c0b4b
--- /dev/null
+++ b/misc/chrome/gophertool/README.txt
@@ -0,0 +1,8 @@
+To install:
+
+1) chrome://extensions/
+2) click "[+] Developer Mode" in top right
+3) "Load unpacked extension..."
+4) pick $GOROOT/misc/chrome/gophertool
+
+Done.  It'll now auto-reload from source.
diff --git a/misc/chrome/gophertool/background.html b/misc/chrome/gophertool/background.html
new file mode 100644
index 0000000..058c181
--- /dev/null
+++ b/misc/chrome/gophertool/background.html
@@ -0,0 +1,24 @@
+<html>
+<!--
+ Copyright 2011 The Go Authors. All rights reserved.
+ Use of this source code is governed by a BSD-style
+ license that can be found in the LICENSE file.
+-->
+<head>
+<script src="gopher.js"></script>
+<script>
+    
+chrome.omnibox.onInputEntered.addListener(function(t) {
+  var url = urlForInput(t);
+  if (url) {
+    chrome.tabs.getSelected(null, function(tab) {
+      if (!tab) return;
+      chrome.tabs.update(tab.id, { "url": url, "selected": true });
+    });
+  }
+});
+
+</script>
+</head>
+</html>
+
diff --git a/misc/chrome/gophertool/gopher.js b/misc/chrome/gophertool/gopher.js
new file mode 100644
index 0000000..847c1c7
--- /dev/null
+++ b/misc/chrome/gophertool/gopher.js
@@ -0,0 +1,34 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+var numericRE = /^\d+$/;
+var commitRE = /^(?:\d+:)?([0-9a-f]{6,20})$/; // e.g "8486:ab29d2698a47" or "ab29d2698a47"
+var pkgRE = /^[a-z0-9_\/]+$/;
+
+function urlForInput(t) {
+    if (!t) {
+        return null;
+    }
+
+    if (numericRE.test(t)) {
+        if (t < 1000000) {
+            return "http://code.google.com/p/go/issues/detail?id=" + t;
+        }
+        return "http://codereview.appspot.com/" + t + "/";
+    }
+
+    var match = commitRE.exec(t);
+    if (match) {
+        return "http://code.google.com/p/go/source/detail?r=" + match[1];
+    }
+
+    if (pkgRE.test(t)) {
+        // TODO: make this smarter, using a list of packages + substring matches.
+        // Get the list from godoc itself in JSON format?
+        // TODO: prefer localhost:6060 to golang.org if localhost:6060 is responding. 
+        return "http://golang.org/pkg/" + t;
+    }
+
+    return null;
+}
diff --git a/misc/chrome/gophertool/gopher.png b/misc/chrome/gophertool/gopher.png
new file mode 100644
index 0000000..0d1abb7
Binary files /dev/null and b/misc/chrome/gophertool/gopher.png differ
diff --git a/misc/chrome/gophertool/manifest.json b/misc/chrome/gophertool/manifest.json
new file mode 100644
index 0000000..3a2540a
--- /dev/null
+++ b/misc/chrome/gophertool/manifest.json
@@ -0,0 +1,17 @@
+{
+  "name": "Hacking Gopher",
+  "version": "1.0",
+  "description": "Go Hacking utility",
+  "background_page": "background.html",
+  "browser_action": {
+    "default_icon": "gopher.png",
+    "popup": "popup.html"
+  },
+  "omnibox": { "keyword": "golang" },
+  "icons": {
+    "16": "gopher.png"
+  },
+  "permissions": [
+     "tabs"
+  ]
+}
diff --git a/misc/chrome/gophertool/popup.html b/misc/chrome/gophertool/popup.html
new file mode 100644
index 0000000..ebbc71f
--- /dev/null
+++ b/misc/chrome/gophertool/popup.html
@@ -0,0 +1,54 @@
+<html>
+<!--
+ Copyright 2011 The Go Authors. All rights reserved.
+ Use of this source code is governed by a BSD-style
+ license that can be found in the LICENSE file.
+-->
+<head>
+<script src="gopher.js"></script>
+<script>
+    
+function focusinput() {
+  document.getElementById("inputbox").focus();
+}
+
+function navigate() {
+  var box = document.getElementById("inputbox");
+  box.focus();
+
+  var t = box.value;
+  if (t == "") {
+    return false;
+  }
+
+  var success = function(url) {
+    console.log("matched " + t + " to: " + url)
+    box.value = "";
+    openURL(url);
+    return false;  // cancel form submission
+  };
+
+  var url = urlForInput(t);
+  if (url) {
+    return success(url);
+  }
+
+  console.log("no match for text: " + t)
+  return false;
+}
+
+function openURL(url) {
+  chrome.tabs.create({ "url": url })
+}
+
+</script>
+</head>
+<body onload="focusinput()" style='margin: 0.5em; font-family: sans;'>
+<small><a href="#" onclick="openURL('http://code.google.com/p/go/issues/list')">issue</a>,
+<a href="#" onclick="openURL('http://codereview.appspot.com/')">codereview</a>,
+<a href="#" onclick="openURL('http://code.google.com/p/go/source/list')">commit</a>, or
+<a href="#" onclick="openURL('http://golang.org/pkg/')">pkg</a> id/name:</small>
+<form style='margin: 0' onsubmit="return navigate();"><nobr><input id="inputbox" size=10 /><input type="submit" value="go" /></nobr></form>
+<small>Also: <a href="#" onclick="openURL('http://godashboard.appspot.com/')">buildbots</small>
+</body>
+</html>
diff --git a/misc/dashboard/builder/exec.go b/misc/dashboard/builder/exec.go
index 988d216..0db5091 100644
--- a/misc/dashboard/builder/exec.go
+++ b/misc/dashboard/builder/exec.go
@@ -18,16 +18,12 @@ func run(envv []string, dir string, argv ...string) os.Error {
 	if *verbose {
 		log.Println("run", argv)
 	}
-	bin, err := lookPath(argv[0])
-	if err != nil {
-		return err
-	}
-	p, err := exec.Run(bin, argv, envv, dir,
-		exec.DevNull, exec.DevNull, exec.PassThrough)
-	if err != nil {
-		return err
-	}
-	return p.Close()
+	argv = useBash(argv)
+	cmd := exec.Command(argv[0], argv[1:]...)
+	cmd.Dir = dir
+	cmd.Env = envv
+	cmd.Stderr = os.Stderr
+	return cmd.Run()
 }
 
 // runLog runs a process and returns the combined stdout/stderr, 
@@ -36,16 +32,8 @@ func runLog(envv []string, logfile, dir string, argv ...string) (output string,
 	if *verbose {
 		log.Println("runLog", argv)
 	}
-	bin, err := lookPath(argv[0])
-	if err != nil {
-		return
-	}
-	p, err := exec.Run(bin, argv, envv, dir,
-		exec.DevNull, exec.Pipe, exec.MergeWithStdout)
-	if err != nil {
-		return
-	}
-	defer p.Close()
+	argv = useBash(argv)
+
 	b := new(bytes.Buffer)
 	var w io.Writer = b
 	if logfile != "" {
@@ -56,21 +44,30 @@ func runLog(envv []string, logfile, dir string, argv ...string) (output string,
 		defer f.Close()
 		w = io.MultiWriter(f, b)
 	}
-	_, err = io.Copy(w, p.Stdout)
-	if err != nil {
-		return
-	}
-	wait, err := p.Wait(0)
+
+	cmd := exec.Command(argv[0], argv[1:]...)
+	cmd.Dir = dir
+	cmd.Env = envv
+	cmd.Stdout = w
+	cmd.Stderr = w
+
+	err = cmd.Run()
+	output = b.String()
 	if err != nil {
+		if ws, ok := err.(*os.Waitmsg); ok {
+			exitStatus = ws.ExitStatus()
+		}
 		return
 	}
-	return b.String(), wait.WaitStatus.ExitStatus(), nil
+	return
 }
 
-// lookPath looks for cmd in $PATH if cmd does not begin with / or ./ or ../.
-func lookPath(cmd string) (string, os.Error) {
-	if strings.HasPrefix(cmd, "/") || strings.HasPrefix(cmd, "./") || strings.HasPrefix(cmd, "../") {
-		return cmd, nil
+// useBash prefixes a list of args with 'bash' if the first argument
+// is a bash script.
+func useBash(argv []string) []string {
+	// TODO(brainman): choose a more reliable heuristic here.
+	if strings.HasSuffix(argv[0], ".bash") {
+		argv = append([]string{"bash"}, argv...)
 	}
-	return exec.LookPath(cmd)
+	return argv
 }
diff --git a/misc/dashboard/builder/main.go b/misc/dashboard/builder/main.go
index c1536ab..5ba5c11 100644
--- a/misc/dashboard/builder/main.go
+++ b/misc/dashboard/builder/main.go
@@ -12,6 +12,7 @@ import (
 	"os"
 	"path"
 	"regexp"
+	"runtime"
 	"strconv"
 	"strings"
 	"time"
@@ -347,6 +348,9 @@ func (b *Builder) buildHash(hash string) (err os.Error) {
 
 // envv returns an environment for build/bench execution
 func (b *Builder) envv() []string {
+	if runtime.GOOS == "windows" {
+		return b.envvWindows()
+	}
 	e := []string{
 		"GOOS=" + b.goos,
 		"GOARCH=" + b.goarch,
@@ -358,6 +362,42 @@ func (b *Builder) envv() []string {
 	return e
 }
 
+// windows version of envv
+func (b *Builder) envvWindows() []string {
+	start := map[string]string{
+		"GOOS":         b.goos,
+		"GOARCH":       b.goarch,
+		"GOROOT_FINAL": "/c/go",
+	}
+	for _, name := range extraEnv {
+		start[name] = os.Getenv(name)
+	}
+	skip := map[string]bool{
+		"GOBIN":   true,
+		"GOROOT":  true,
+		"INCLUDE": true,
+		"LIB":     true,
+	}
+	var e []string
+	for name, v := range start {
+		e = append(e, name+"="+v)
+		skip[name] = true
+	}
+	for _, kv := range os.Environ() {
+		s := strings.Split(kv, "=", 2)
+		name := strings.ToUpper(s[0])
+		switch {
+		case name == "":
+			// variables, like "=C:=C:\", just copy them
+			e = append(e, kv)
+		case !skip[name]:
+			e = append(e, kv)
+			skip[name] = true
+		}
+	}
+	return e
+}
+
 func isDirectory(name string) bool {
 	s, err := os.Stat(name)
 	return err == nil && s.IsDirectory()
@@ -455,7 +495,7 @@ func commitPoll(key string) {
 
 	// Pass 1.  Fill in parents and add new log entries to logsByHash.
 	// Empty parent means take parent from next log entry.
-	// Non-empty parent has form 1234:hashhashhash; we weant full hash.
+	// Non-empty parent has form 1234:hashhashhash; we want full hash.
 	for i := range logs {
 		l := &logs[i]
 		log.Printf("hg log: %s < %s\n", l.Hash, l.Parent)
@@ -516,7 +556,7 @@ func addCommit(hash, key string) bool {
 
 	// Create commit.
 	if err := postCommit(key, l); err != nil {
-		log.Printf("faield to add %s to dashboard: %v", err)
+		log.Printf("failed to add %s to dashboard: %v", key, err)
 		return false
 	}
 	return true
diff --git a/misc/dashboard/godashboard/app.yaml b/misc/dashboard/godashboard/app.yaml
index 455da57..4fd05f2 100644
--- a/misc/dashboard/godashboard/app.yaml
+++ b/misc/dashboard/godashboard/app.yaml
@@ -1,5 +1,5 @@
 application: godashboard
-version: 6
+version: 7
 runtime: python
 api_version: 1
 
diff --git a/misc/dashboard/godashboard/gobuild.py b/misc/dashboard/godashboard/gobuild.py
index baddb0e..ee700c7 100644
--- a/misc/dashboard/godashboard/gobuild.py
+++ b/misc/dashboard/godashboard/gobuild.py
@@ -12,15 +12,12 @@ 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 binascii
 import datetime
 import hashlib
 import hmac
 import logging
 import os
 import re
-import struct
-import time
 import bz2
 
 # local imports
@@ -346,16 +343,98 @@ class Build(webapp.RequestHandler):
         key = 'todo-%s' % builder
         memcache.delete(key)
 
-        # TODO: Send mail for build breakage.
+        c = getBrokenCommit(node, builder)
+        if c is not None and not c.fail_notification_sent:
+            notifyBroken(c, builder)
 
         self.response.set_status(200)
 
-def failed(c, builder):
+
+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__').limit(20)
+    for c in q:
+        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_by_key_name('%08x-%s' % (c.num, c.node))
+	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 False
+    return None
 
 def node(num):
     q = Commit.all()
diff --git a/misc/dashboard/googlecode_upload.py b/misc/dashboard/googlecode_upload.py
index 3b1d432..e87db88 100755
--- a/misc/dashboard/googlecode_upload.py
+++ b/misc/dashboard/googlecode_upload.py
@@ -70,7 +70,7 @@ def upload(file, project_name, user_name, password, summary, labels=None):
 
   Returns: a tuple:
     http_status: 201 if the upload succeeded, something else if an
-                 error occured.
+                 error occurred.
     http_reason: The human-readable string associated with http_status
     file_url: If the upload succeeded, the URL of the file on Google
               Code, None otherwise.
diff --git a/misc/emacs/go-mode.el b/misc/emacs/go-mode.el
index 532f464..03f0a2a 100644
--- a/misc/emacs/go-mode.el
+++ b/misc/emacs/go-mode.el
@@ -523,7 +523,7 @@ Replace the current buffer on success; display errors on failure."
                    (erase-buffer)
                    (insert-buffer-substring outbuf)
                    (goto-char (min old-point (point-max)))
-                   (if old-mark (set-mark (min old-mark (point-max))))
+                   (if old-mark (push-mark (min old-mark (point-max)) t))
                    (kill-buffer errbuf))
 
                ;; gofmt failed: display the errors
diff --git a/misc/godoc/README b/misc/godoc/README
new file mode 100644
index 0000000..3c8d830
--- /dev/null
+++ b/misc/godoc/README
@@ -0,0 +1,22 @@
+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
new file mode 100644
index 0000000..f8b46db
--- /dev/null
+++ b/misc/godoc/app.yaml
@@ -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.
+
+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
new file mode 100644
index 0000000..0fd0bd5
--- /dev/null
+++ b/misc/godoc/init.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.
+
+// 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 f3e2ff5..f1dc1bc 100644
--- a/misc/goplay/goplay.go
+++ b/misc/goplay/goplay.go
@@ -5,7 +5,6 @@
 package main
 
 import (
-	"bytes"
 	"exec"
 	"flag"
 	"http"
@@ -140,32 +139,7 @@ func error(w http.ResponseWriter, out []byte, err os.Error) {
 
 // run executes the specified command and returns its output and an error.
 func run(cmd ...string) ([]byte, os.Error) {
-	// find the specified binary
-	bin, err := exec.LookPath(cmd[0])
-	if err != nil {
-		// report binary as well as the error
-		return nil, os.NewError(cmd[0] + ": " + err.String())
-	}
-
-	// run the binary and read its combined stdout and stderr into a buffer
-	p, err := exec.Run(bin, cmd, os.Environ(), "", exec.DevNull, exec.Pipe, exec.MergeWithStdout)
-	if err != nil {
-		return nil, err
-	}
-	var buf bytes.Buffer
-	io.Copy(&buf, p.Stdout)
-	w, err := p.Wait(0)
-	p.Close()
-	if err != nil {
-		return nil, err
-	}
-
-	// set the error return value if the program had a non-zero exit status
-	if !w.Exited() || w.ExitStatus() != 0 {
-		err = os.ErrorString("running " + cmd[0] + ": " + w.String())
-	}
-
-	return buf.Bytes(), err
+	return exec.Command(cmd[0], cmd[1:]...).CombinedOutput()
 }
 
 var frontPage, output *template.Template // HTML templates
diff --git a/misc/vim/ftplugin/go/fmt.vim b/misc/vim/ftplugin/go/fmt.vim
index 18a2156..a299dfc 100644
--- a/misc/vim/ftplugin/go/fmt.vim
+++ b/misc/vim/ftplugin/go/fmt.vim
@@ -13,7 +13,7 @@
 "       replacing the buffer with stderr output.
 "
 
-command! Fmt call s:GoFormat()
+command! -buffer Fmt call s:GoFormat()
 
 function! s:GoFormat()
     let view = winsaveview()
diff --git a/src/Make.pkg b/src/Make.pkg
index 966bc61..86a2e9f 100644
--- a/src/Make.pkg
+++ b/src/Make.pkg
@@ -79,7 +79,7 @@ testpackage-clean:
 install: $(INSTALLFILES)
 
 $(TARGDIR)/$(TARG).a: _obj/$(TARG).a
-	@test -d $(QUOTED_GOROOT)/pkg && mkdir -p $(TARGDIR)/$(dir)
+	@mkdir -p $(TARGDIR)/$(dir)
 	cp _obj/$(TARG).a "$@"
 
 _go_.$O: $(GOFILES) $(PREREQ)
@@ -227,7 +227,7 @@ _obj/$(SWIG_PREFIX)-%.so: _obj/%_wrapcxx.o
 	$(HOST_CXX) $(_CGO_CFLAGS_$(GOARCH)) -o $@ $^ $(SWIG_LDFLAGS) $(_CGO_LDFLAGS_$(GOOS)) $(_SWIG_LDFLAGS_$(GOOS))
 
 $(TARGDIR)/swig/$(SWIG_PREFIX)-%.so: _obj/$(SWIG_PREFIX)-%.so
-	@test -d $(QUOTED_GOROOT)/pkg && mkdir -p $(TARGDIR)/swig
+	@mkdir -p $(TARGDIR)/swig
 	cp $< "$@"
 
 all: $(SWIG_SOS)
diff --git a/src/cmd/5g/Makefile b/src/cmd/5g/Makefile
index 6873fbc..b47014a 100644
--- a/src/cmd/5g/Makefile
+++ b/src/cmd/5g/Makefile
@@ -15,16 +15,17 @@ HFILES=\
 
 OFILES=\
 	../5l/enam.$O\
-	list.$O\
-	galign.$O\
-	gobj.$O\
-	ggen.$O\
-	gsubr.$O\
 	cgen.$O\
 	cgen64.$O\
 	cplx.$O\
-	reg.$O\
+	galign.$O\
+	ggen.$O\
+	gobj.$O\
+	gsubr.$O\
+	list.$O\
 	peep.$O\
+	pgen.$O\
+	reg.$O\
 
 LIB=\
 	../gc/gc.a\
diff --git a/src/cmd/5g/cgen.c b/src/cmd/5g/cgen.c
index 4e5f7eb..76e2707 100644
--- a/src/cmd/5g/cgen.c
+++ b/src/cmd/5g/cgen.c
@@ -1190,7 +1190,8 @@ void
 sgen(Node *n, Node *res, int32 w)
 {
 	Node dst, src, tmp, nend;
-	int32 c, q, odst, osrc;
+	int32 c, odst, osrc;
+	int dir, align, op;
 	Prog *p, *ploop;
 
 	if(debug['g']) {
@@ -1200,17 +1201,39 @@ sgen(Node *n, Node *res, int32 w)
 	}
 	if(w == 0)
 		return;
-	if(n->ullman >= UINF && res->ullman >= UINF) {
-		fatal("sgen UINF");
-	}
-
 	if(w < 0)
 		fatal("sgen copy %d", w);
+	if(n->ullman >= UINF && res->ullman >= UINF)
+		fatal("sgen UINF");
+	if(n->type == T)
+		fatal("sgen: missing type");
+
+	// determine alignment.
+	// want to avoid unaligned access, so have to use
+	// smaller operations for less aligned types.
+	// for example moving [4]byte must use 4 MOVB not 1 MOVW.
+	align = n->type->align;
+	op = 0;
+	switch(align) {
+	default:
+		fatal("sgen: invalid alignment %d for %T", align, n->type);
+	case 1:
+		op = AMOVB;
+		break;
+	case 2:
+		op = AMOVH;
+		break;
+	case 4:
+		op = AMOVW;
+		break;
+	}
+	if(w%align)
+		fatal("sgen: unaligned size %d (align=%d) for %T", w, align, n->type);
+	c = w / align;
 
 	// offset on the stack
 	osrc = stkof(n);
 	odst = stkof(res);
-
 	if(osrc != -1000 && odst != -1000 && (osrc == 1000 || odst == 1000)) {
 		// osrc and odst both on stack, and at least one is in
 		// an unknown position.  Could generate code to test
@@ -1221,12 +1244,15 @@ sgen(Node *n, Node *res, int32 w)
 		sgen(&tmp, res, w);
 		return;
 	}
-
-	if(osrc % 4 != 0 || odst %4 != 0)
-		fatal("sgen: non word(4) aligned offset src %d or dst %d", osrc, odst);
+	if(osrc%align != 0 || odst%align != 0)
+		fatal("sgen: unaligned offset src %d or dst %d (align %d)", osrc, odst, align);
+	// if we are copying forward on the stack and
+	// the src and dst overlap, then reverse direction
+	dir = align;
+	if(osrc < odst && odst < osrc+w)
+		dir = -dir;
 
 	regalloc(&dst, types[tptr], res);
-
 	if(n->ullman >= res->ullman) {
 		agen(n, &dst);	// temporarily use dst
 		regalloc(&src, types[tptr], N);
@@ -1240,141 +1266,64 @@ sgen(Node *n, Node *res, int32 w)
 
 	regalloc(&tmp, types[TUINT32], N);
 
-	c = w % 4;	// bytes
-	q = w / 4;	// quads
-
-	// if we are copying forward on the stack and
-	// the src and dst overlap, then reverse direction
-	if(osrc < odst && odst < osrc+w) {
-		if(c != 0)
-			fatal("sgen: reverse character copy not implemented");
-		if(q >= 4) {
-			regalloc(&nend, types[TUINT32], N);
-			// set up end marker to 4 bytes before source
-			p = gins(AMOVW, &src, &nend);
-			p->from.type = D_CONST;
-			p->from.offset = -4;
-
-			// move src and dest to the end of block
-			p = gins(AMOVW, &src, &src);
-			p->from.type = D_CONST;
-			p->from.offset = (q-1)*4;
-
-			p = gins(AMOVW, &dst, &dst);
-			p->from.type = D_CONST;
-			p->from.offset = (q-1)*4;
-
-			p = gins(AMOVW, &src, &tmp);
-			p->from.type = D_OREG;
-			p->from.offset = -4;
-			p->scond |= C_PBIT;
-			ploop = p;
+	// set up end marker
+	memset(&nend, 0, sizeof nend);
+	if(c >= 4) {
+		regalloc(&nend, types[TUINT32], N);
 
-			p = gins(AMOVW, &tmp, &dst);
-			p->to.type = D_OREG;
-			p->to.offset = -4;
-			p->scond |= C_PBIT;
-
-			p = gins(ACMP, &src, N);
-			raddr(&nend, p);
+		p = gins(AMOVW, &src, &nend);
+		p->from.type = D_CONST;
+		if(dir < 0)
+			p->from.offset = dir;
+		else
+			p->from.offset = w;
+	}
 
-			patch(gbranch(ABNE, T), ploop);
+	// move src and dest to the end of block if necessary
+	if(dir < 0) {
+		p = gins(AMOVW, &src, &src);
+		p->from.type = D_CONST;
+		p->from.offset = w + dir;
 
- 			regfree(&nend);
-		} else {
-			// move src and dest to the end of block
-			p = gins(AMOVW, &src, &src);
-			p->from.type = D_CONST;
-			p->from.offset = (q-1)*4;
-
-			p = gins(AMOVW, &dst, &dst);
-			p->from.type = D_CONST;
-			p->from.offset = (q-1)*4;
-
-			while(q > 0) {
-				p = gins(AMOVW, &src, &tmp);
-				p->from.type = D_OREG;
-				p->from.offset = -4;
- 				p->scond |= C_PBIT;
-
-				p = gins(AMOVW, &tmp, &dst);
-				p->to.type = D_OREG;
-				p->to.offset = -4;
- 				p->scond |= C_PBIT;
-
-				q--;
-			}
-		}
+		p = gins(AMOVW, &dst, &dst);
+		p->from.type = D_CONST;
+		p->from.offset = w + dir;
+	}
+	
+	// move
+	if(c >= 4) {
+		p = gins(op, &src, &tmp);
+		p->from.type = D_OREG;
+		p->from.offset = dir;
+		p->scond |= C_PBIT;
+		ploop = p;
+
+		p = gins(op, &tmp, &dst);
+		p->to.type = D_OREG;
+		p->to.offset = dir;
+		p->scond |= C_PBIT;
+
+		p = gins(ACMP, &src, N);
+		raddr(&nend, p);
+
+		patch(gbranch(ABNE, T), ploop);
+ 		regfree(&nend);
 	} else {
-		// normal direction
-		if(q >= 4) {
-			regalloc(&nend, types[TUINT32], N);
-			p = gins(AMOVW, &src, &nend);
-			p->from.type = D_CONST;
-			p->from.offset = q*4;
-
-			p = gins(AMOVW, &src, &tmp);
+		while(c-- > 0) {
+			p = gins(op, &src, &tmp);
 			p->from.type = D_OREG;
-			p->from.offset = 4;
+			p->from.offset = dir;
 			p->scond |= C_PBIT;
 			ploop = p;
-
-			p = gins(AMOVW, &tmp, &dst);
+	
+			p = gins(op, &tmp, &dst);
 			p->to.type = D_OREG;
-			p->to.offset = 4;
+			p->to.offset = dir;
 			p->scond |= C_PBIT;
-
-			p = gins(ACMP, &src, N);
-			raddr(&nend, p);
-
-			patch(gbranch(ABNE, T), ploop);
-
- 			regfree(&nend);
-		} else
-		while(q > 0) {
-			p = gins(AMOVW, &src, &tmp);
-			p->from.type = D_OREG;
-			p->from.offset = 4;
- 			p->scond |= C_PBIT;
-
-			p = gins(AMOVW, &tmp, &dst);
-			p->to.type = D_OREG;
-			p->to.offset = 4;
- 			p->scond |= C_PBIT;
-
-			q--;
-		}
-
-		if (c != 0) {
-			//	MOVW	(src), tmp
-			p = gins(AMOVW, &src, &tmp);
-			p->from.type = D_OREG;
-
-			//	MOVW	tmp<<((4-c)*8),src
-			gshift(AMOVW, &tmp, SHIFT_LL, ((4-c)*8), &src);
-
-			//	MOVW	src>>((4-c)*8),src
-			gshift(AMOVW, &src, SHIFT_LR, ((4-c)*8), &src);
-
-			//	MOVW	(dst), tmp
-			p = gins(AMOVW, &dst, &tmp);
-			p->from.type = D_OREG;
-
-			//	MOVW	tmp>>(c*8),tmp
-			gshift(AMOVW, &tmp, SHIFT_LR, (c*8), &tmp);
-
-			//	MOVW	tmp<<(c*8),tmp
-			gshift(AMOVW, &tmp, SHIFT_LL, c*8, &tmp);
-
-			//	ORR		src, tmp
-			gins(AORR, &src, &tmp);
-
-			//	MOVW	tmp, (dst)
-			p = gins(AMOVW, &tmp, &dst);
-			p->to.type = D_OREG;
 		}
 	}
- 	regfree(&dst);
+
+	regfree(&dst);
 	regfree(&src);
 	regfree(&tmp);
 }
diff --git a/src/cmd/5g/ggen.c b/src/cmd/5g/ggen.c
index 7197709..0bc1b38 100644
--- a/src/cmd/5g/ggen.c
+++ b/src/cmd/5g/ggen.c
@@ -7,107 +7,9 @@
 #include "gg.h"
 #include "opt.h"
 
-static Prog *pret;
-
 void
-compile(Node *fn)
+defframe(Prog *ptxt)
 {
-	Plist *pl;
-	Node nod1;
-	Prog *ptxt;
-	int32 lno;
-	Type *t;
-	Iter save;
-
-	if(newproc == N) {
-		newproc = sysfunc("newproc");
-		deferproc = sysfunc("deferproc");
-		deferreturn = sysfunc("deferreturn");
-		panicindex = sysfunc("panicindex");
-		panicslice = sysfunc("panicslice");
-		throwreturn = sysfunc("throwreturn");
-	}
-
-	if(fn->nbody == nil)
-		return;
-
-	// set up domain for labels
-	clearlabels();
-
-	lno = setlineno(fn);
-
-	curfn = fn;
-	dowidth(curfn->type);
-
-	if(curfn->type->outnamed) {
-		// add clearing of the output parameters
-		t = structfirst(&save, getoutarg(curfn->type));
-		while(t != T) {
-			if(t->nname != N)
-				curfn->nbody = concat(list1(nod(OAS, t->nname, N)), curfn->nbody);
-			t = structnext(&save);
-		}
-	}
-
-	hasdefer = 0;
-	walk(curfn);
-	if(nerrors != 0 || isblank(curfn->nname))
-		goto ret;
-
-	allocparams();
-
-	continpc = P;
-	breakpc = P;
-
-	pl = newplist();
-	pl->name = curfn->nname;
-	
-	setlineno(curfn);
-
-	nodconst(&nod1, types[TINT32], 0);
-	ptxt = gins(ATEXT, curfn->nname, &nod1);
-	afunclit(&ptxt->from);
-
-	ginit();
-	genlist(curfn->enter);
-	
-	pret = nil;
-	if(hasdefer || curfn->exit) {
-		Prog *p1;
-
-		p1 = gjmp(nil);
-		pret = gjmp(nil);
-		patch(p1, pc);
-	}
-
-	genlist(curfn->nbody);
-	gclean();
-	checklabels();
-	if(nerrors != 0)
-		goto ret;
-
-	if(curfn->type->outtuple != 0)
-		ginscall(throwreturn, 0);
-
-	if(pret)
-		patch(pret, pc);
-	ginit();
-	if(hasdefer)
-		ginscall(deferreturn, 0);
-	if(curfn->exit)
-		genlist(curfn->exit);
-	gclean();
-	if(nerrors != 0)
-		goto ret;
-	if(curfn->endlineno)
-		lineno = curfn->endlineno;
-	pc->as = ARET;	// overwrite AEND
-	pc->lineno = lineno;
-
-	if(!debug['N'] || debug['R'] || debug['P']) {
-		regopt(ptxt);
-	}
-
 	// fill in argument size
 	ptxt->to.type = D_CONST2;
 	ptxt->reg = 0; // flags
@@ -118,12 +20,6 @@ compile(Node *fn)
 		maxstksize = stksize;
 	ptxt->to.offset = rnd(maxstksize+maxarg, widthptr);
 	maxstksize = 0;
-
-	if(debug['f'])
-		frame(0);
-
-ret:
-	lineno = lno;
 }
 
 /*
@@ -197,7 +93,7 @@ ginscall(Node *f, int proc)
 			nodconst(&con, types[TINT32], 0);
 			p = gins(ACMP, &con, N);
 			p->reg = 0;
-			patch(gbranch(ABNE, T), pret);
+			patch(gbranch(ABNE, T), retpc);
 		}
 		break;
 	}
@@ -401,7 +297,7 @@ cgen_ret(Node *n)
 {
 	genlist(n->list);		// copy out args
 	if(hasdefer || curfn->exit)
-		gjmp(pret);
+		gjmp(retpc);
 	else
 		gins(ARET, N, N);
 }
diff --git a/src/cmd/5l/asm.c b/src/cmd/5l/asm.c
index 9e9c2c1..81c08e3 100644
--- a/src/cmd/5l/asm.c
+++ b/src/cmd/5l/asm.c
@@ -1977,3 +1977,9 @@ genasmsym(void (*put)(Sym*, char*, int, vlong, vlong, int, Sym*))
 		Bprint(&bso, "symsize = %ud\n", symsize);
 	Bflush(&bso);
 }
+
+void
+setpersrc(Sym *s)
+{
+	USED(s);
+}
diff --git a/src/cmd/6g/Makefile b/src/cmd/6g/Makefile
index 023f5d1..64fa153 100644
--- a/src/cmd/6g/Makefile
+++ b/src/cmd/6g/Makefile
@@ -14,16 +14,17 @@ HFILES=\
 	opt.h\
 
 OFILES=\
-	list.$O\
-	gobj.$O\
-	galign.$O\
-	ggen.$O\
+	../6l/enam.$O\
 	cgen.$O\
 	cplx.$O\
+	galign.$O\
+	ggen.$O\
+	gobj.$O\
 	gsubr.$O\
+	list.$O\
 	peep.$O\
+	pgen.$O\
 	reg.$O\
-	../6l/enam.$O\
 
 LIB=\
 	../gc/gc.a\
diff --git a/src/cmd/6g/ggen.c b/src/cmd/6g/ggen.c
index ce66b43..5260335 100644
--- a/src/cmd/6g/ggen.c
+++ b/src/cmd/6g/ggen.c
@@ -7,121 +7,18 @@
 #include "gg.h"
 #include "opt.h"
 
-static Prog *pret;
-
 void
-compile(Node *fn)
+defframe(Prog *ptxt)
 {
-	Plist *pl;
-	Node nod1;
-	Prog *ptxt;
-	int32 lno;
-	Type *t;
-	Iter save;
-
-	if(newproc == N) {
-		newproc = sysfunc("newproc");
-		deferproc = sysfunc("deferproc");
-		deferreturn = sysfunc("deferreturn");
-		panicindex = sysfunc("panicindex");
-		panicslice = sysfunc("panicslice");
-		throwreturn = sysfunc("throwreturn");
-	}
-
-	if(fn->nbody == nil)
-		return;
-
-	// set up domain for labels
-	clearlabels();
-
-	lno = setlineno(fn);
-
-	curfn = fn;
-	dowidth(curfn->type);
-
-	if(curfn->type->outnamed) {
-		// add clearing of the output parameters
-		t = structfirst(&save, getoutarg(curfn->type));
-		while(t != T) {
-			if(t->nname != N)
-				curfn->nbody = concat(list1(nod(OAS, t->nname, N)), curfn->nbody);
-			t = structnext(&save);
-		}
-	}
-
-	hasdefer = 0;
-	walk(curfn);
-	if(nerrors != 0 || isblank(curfn->nname))
-		goto ret;
-
-	allocparams();
-
-	continpc = P;
-	breakpc = P;
-
-	pl = newplist();
-	pl->name = curfn->nname;
-
-	setlineno(curfn);
-
-	nodconst(&nod1, types[TINT32], 0);
-	ptxt = gins(ATEXT, curfn->nname, &nod1);
-	afunclit(&ptxt->from);
-
-	ginit();
-	genlist(curfn->enter);
-
-	pret = nil;
-	if(hasdefer || curfn->exit) {
-		Prog *p1;
-
-		p1 = gjmp(nil);
-		pret = gjmp(nil);
-		patch(p1, pc);
-	}
-
-	genlist(curfn->nbody);
-	gclean();
-	checklabels();
-	if(nerrors != 0)
-		goto ret;
-	if(curfn->endlineno)
-		lineno = curfn->endlineno;
-
-	if(curfn->type->outtuple != 0)
-		ginscall(throwreturn, 0);
-
-	if(pret)
-		patch(pret, pc);
-	ginit();
-	if(hasdefer)
-		ginscall(deferreturn, 0);
-	if(curfn->exit)
-		genlist(curfn->exit);
-	gclean();
-	if(nerrors != 0)
-		goto ret;
-	pc->as = ARET;	// overwrite AEND
-	pc->lineno = lineno;
-
-	if(!debug['N'] || debug['R'] || debug['P']) {
-		regopt(ptxt);
-	}
-
 	// fill in argument size
 	ptxt->to.offset = rnd(curfn->type->argwid, widthptr);
 
 	// fill in final stack size
 	ptxt->to.offset <<= 32;
 	ptxt->to.offset |= rnd(stksize+maxarg, widthptr);
-
-	if(debug['f'])
-		frame(0);
-
-ret:
-	lineno = lno;
 }
 
+
 /*
  * generate:
  *	call f
@@ -163,7 +60,7 @@ ginscall(Node *f, int proc)
 		if(proc == 2) {
 			nodreg(&reg, types[TINT64], D_AX);
 			gins(ATESTQ, &reg, &reg);
-			patch(gbranch(AJNE, T), pret);
+			patch(gbranch(AJNE, T), retpc);
 		}
 		break;
 	}
@@ -355,7 +252,7 @@ cgen_ret(Node *n)
 {
 	genlist(n->list);		// copy out args
 	if(hasdefer || curfn->exit)
-		gjmp(pret);
+		gjmp(retpc);
 	else
 		gins(ARET, N, N);
 }
diff --git a/src/cmd/6l/asm.c b/src/cmd/6l/asm.c
index 6dffa20..320f4c9 100644
--- a/src/cmd/6l/asm.c
+++ b/src/cmd/6l/asm.c
@@ -828,6 +828,7 @@ asmb(void)
 				dwarfemitdebugsections();
 			}
 			break;
+		case Hdarwin:
 		case Hwindows:
 			seek(cout, symo, 0);
 			if(debug['v'])
diff --git a/src/cmd/6l/obj.c b/src/cmd/6l/obj.c
index d53814a..e3191bb 100644
--- a/src/cmd/6l/obj.c
+++ b/src/cmd/6l/obj.c
@@ -177,7 +177,7 @@ main(int argc, char *argv[])
 		 */
 		tlsoffset = 0x8a0;
 		machoinit();
-		HEADR = MACHORESERVE;
+		HEADR = INITIAL_MACHO_HEADR;
 		if(INITRND == -1)
 			INITRND = 4096;
 		if(INITTEXT == -1)
diff --git a/src/cmd/8g/Makefile b/src/cmd/8g/Makefile
index 09cf8d4..b459782 100644
--- a/src/cmd/8g/Makefile
+++ b/src/cmd/8g/Makefile
@@ -15,15 +15,16 @@ HFILES=\
 
 OFILES=\
 	../8l/enam.$O\
-	list.$O\
-	galign.$O\
-	gobj.$O\
-	ggen.$O\
-	gsubr.$O\
 	cgen.$O\
 	cgen64.$O\
 	cplx.$O\
+	galign.$O\
+	ggen.$O\
+	gobj.$O\
+	gsubr.$O\
+	list.$O\
 	peep.$O\
+	pgen.$O\
 	reg.$O\
 
 LIB=\
diff --git a/src/cmd/8g/ggen.c b/src/cmd/8g/ggen.c
index 2231525..25adb38 100644
--- a/src/cmd/8g/ggen.c
+++ b/src/cmd/8g/ggen.c
@@ -7,106 +7,9 @@
 #include "gg.h"
 #include "opt.h"
 
-static Prog *pret;
-
 void
-compile(Node *fn)
+defframe(Prog *ptxt)
 {
-	Plist *pl;
-	Node nod1;
-	Prog *ptxt;
-	int32 lno;
-	Type *t;
-	Iter save;
-
-	if(newproc == N) {
-		newproc = sysfunc("newproc");
-		deferproc = sysfunc("deferproc");
-		deferreturn = sysfunc("deferreturn");
-		panicindex = sysfunc("panicindex");
-		panicslice = sysfunc("panicslice");
-		throwreturn = sysfunc("throwreturn");
-	}
-
-	if(fn->nbody == nil)
-		return;
-
-	// set up domain for labels
-	clearlabels();
-
-	lno = setlineno(fn);
-
-	curfn = fn;
-	dowidth(curfn->type);
-
-	if(curfn->type->outnamed) {
-		// add clearing of the output parameters
-		t = structfirst(&save, getoutarg(curfn->type));
-		while(t != T) {
-			if(t->nname != N)
-				curfn->nbody = concat(list1(nod(OAS, t->nname, N)), curfn->nbody);
-			t = structnext(&save);
-		}
-	}
-
-	hasdefer = 0;
-	walk(curfn);
-	if(nerrors != 0 || isblank(curfn->nname))
-		goto ret;
-
-	allocparams();
-
-	continpc = P;
-	breakpc = P;
-
-	pl = newplist();
-	pl->name = curfn->nname;
-
-	setlineno(curfn);
-
-	nodconst(&nod1, types[TINT32], 0);
-	ptxt = gins(ATEXT, curfn->nname, &nod1);
-	afunclit(&ptxt->from);
-
-	ginit();
-	genlist(curfn->enter);
-
-	pret = nil;
-	if(hasdefer || curfn->exit) {
-		Prog *p1;
-
-		p1 = gjmp(nil);
-		pret = gjmp(nil);
-		patch(p1, pc);
-	}
-
-	genlist(curfn->nbody);
-	gclean();
-	checklabels();
-	if(nerrors != 0)
-		goto ret;
-	if(curfn->endlineno)
-		lineno = curfn->endlineno;
-
-	if(curfn->type->outtuple != 0)
-		ginscall(throwreturn, 0);
-
-	if(pret)
-		patch(pret, pc);
-	ginit();
-	if(hasdefer)
-		ginscall(deferreturn, 0);
-	if(curfn->exit)
-		genlist(curfn->exit);
-	gclean();
-	if(nerrors != 0)
-		goto ret;
-	pc->as = ARET;	// overwrite AEND
-	pc->lineno = lineno;
-
-	if(!debug['N'] || debug['R'] || debug['P']) {
-		regopt(ptxt);
-	}
 	// fill in argument size
 	ptxt->to.offset2 = rnd(curfn->type->argwid, widthptr);
 
@@ -115,12 +18,6 @@ compile(Node *fn)
 		maxstksize = stksize;
 	ptxt->to.offset = rnd(maxstksize+maxarg, widthptr);
 	maxstksize = 0;
-
-	if(debug['f'])
-		frame(0);
-
-ret:
-	lineno = lno;
 }
 
 void
@@ -200,7 +97,7 @@ ginscall(Node *f, int proc)
 		if(proc == 2) {
 			nodreg(&reg, types[TINT64], D_AX);
 			gins(ATESTL, &reg, &reg);
-			patch(gbranch(AJNE, T), pret);
+			patch(gbranch(AJNE, T), retpc);
 		}
 		break;
 	}
@@ -391,8 +288,8 @@ void
 cgen_ret(Node *n)
 {
 	genlist(n->list);		// copy out args
-	if(pret)
-		gjmp(pret);
+	if(retpc)
+		gjmp(retpc);
 	else
 		gins(ARET, N, N);
 }
diff --git a/src/cmd/8l/asm.c b/src/cmd/8l/asm.c
index 7de7753..c426a88 100644
--- a/src/cmd/8l/asm.c
+++ b/src/cmd/8l/asm.c
@@ -781,6 +781,7 @@ asmb(void)
 				cflush();
 			}
 			break;
+		case Hdarwin:
 		case Hwindows:
 			seek(cout, symo, 0);
 			if(debug['v'])
diff --git a/src/cmd/8l/obj.c b/src/cmd/8l/obj.c
index f84a30f..440dcb7 100644
--- a/src/cmd/8l/obj.c
+++ b/src/cmd/8l/obj.c
@@ -218,7 +218,7 @@ main(int argc, char *argv[])
 		 */
 		tlsoffset = 0x468;
 		machoinit();
-		HEADR = MACHORESERVE;
+		HEADR = INITIAL_MACHO_HEADR;
 		if(INITTEXT == -1)
 			INITTEXT = 4096+HEADR;
 		if(INITDAT == -1)
diff --git a/src/cmd/cgo/doc.go b/src/cmd/cgo/doc.go
index b3aa9ad..064725c 100644
--- a/src/cmd/cgo/doc.go
+++ b/src/cmd/cgo/doc.go
@@ -35,9 +35,17 @@ systems.  For example:
 	// #include <png.h>
 	import "C"
 
-C identifiers or field names that are keywords in Go can be
-accessed by prefixing them with an underscore: if x points at
-a C struct with a field named "type", x._type accesses the field.
+Alternatively, CFLAGS and LDFLAGS may be obtained via the pkg-config
+tool using a '#cgo pkg-config:' directive followed by the package names.
+For example:
+
+	// #cgo pkg-config: png cairo
+	// #include <png.h>
+	import "C"
+
+Within the Go file, C identifiers or field names that are keywords in Go
+can be accessed by prefixing them with an underscore: if x points at a C
+struct with a field named "type", x._type accesses the field.
 
 The standard C numeric types are available under the names
 C.char, C.schar (signed char), C.uchar (unsigned char),
diff --git a/src/cmd/cgo/gcc.go b/src/cmd/cgo/gcc.go
index ac65613..fa7602c 100644
--- a/src/cmd/cgo/gcc.go
+++ b/src/cmd/cgo/gcc.go
@@ -100,27 +100,81 @@ NextLine:
 			fatalf("%s: bad #cgo option: %s", srcfile, fields[0])
 		}
 
-		if k != "CFLAGS" && k != "LDFLAGS" {
-			fatalf("%s: unsupported #cgo option %s", srcfile, k)
-		}
-
-		v := strings.TrimSpace(fields[1])
-		args, err := splitQuoted(v)
+		args, err := splitQuoted(fields[1])
 		if err != nil {
-			fatalf("%s: bad #cgo option %s: %s", srcfile, k, err.String())
+			fatalf("%s: bad #cgo option %s: %s", srcfile, k, err)
 		}
-		if oldv, ok := p.CgoFlags[k]; ok {
-			p.CgoFlags[k] = oldv + " " + v
-		} else {
-			p.CgoFlags[k] = v
+		for _, arg := range args {
+			if !safeName(arg) {
+				fatalf("%s: #cgo option %s is unsafe: %s", srcfile, k, arg)
+			}
 		}
-		if k == "CFLAGS" {
-			p.GccOptions = append(p.GccOptions, args...)
+
+		switch k {
+
+		case "CFLAGS", "LDFLAGS":
+			p.addToFlag(k, args)
+
+		case "pkg-config":
+			cflags, ldflags, err := pkgConfig(args)
+			if err != nil {
+				fatalf("%s: bad #cgo option %s: %s", srcfile, k, err)
+			}
+			p.addToFlag("CFLAGS", cflags)
+			p.addToFlag("LDFLAGS", ldflags)
+
+		default:
+			fatalf("%s: unsupported #cgo option %s", srcfile, k)
+
 		}
 	}
 	f.Preamble = strings.Join(linesOut, "\n")
 }
 
+// addToFlag appends args to flag.  All flags are later written out onto the
+// _cgo_flags file for the build system to use.
+func (p *Package) addToFlag(flag string, args []string) {
+	if oldv, ok := p.CgoFlags[flag]; ok {
+		p.CgoFlags[flag] = oldv + " " + strings.Join(args, " ")
+	} else {
+		p.CgoFlags[flag] = strings.Join(args, " ")
+	}
+	if flag == "CFLAGS" {
+		// We'll also need these when preprocessing for dwarf information.
+		p.GccOptions = append(p.GccOptions, args...)
+	}
+}
+
+// pkgConfig runs pkg-config and extracts --libs and --cflags information
+// for packages.
+func pkgConfig(packages []string) (cflags, ldflags []string, err os.Error) {
+	for _, name := range packages {
+		if len(name) == 0 || name[0] == '-' {
+			return nil, nil, os.NewError(fmt.Sprintf("invalid name: %q", name))
+		}
+	}
+
+	args := append([]string{"pkg-config", "--cflags"}, packages...)
+	stdout, stderr, ok := run(nil, args)
+	if !ok {
+		os.Stderr.Write(stderr)
+		return nil, nil, os.NewError("pkg-config failed")
+	}
+	cflags, err = splitQuoted(string(stdout))
+	if err != nil {
+		return
+	}
+
+	args = append([]string{"pkg-config", "--libs"}, packages...)
+	stdout, stderr, ok = run(nil, args)
+	if !ok {
+		os.Stderr.Write(stderr)
+		return nil, nil, os.NewError("pkg-config failed")
+	}
+	ldflags, err = splitQuoted(string(stdout))
+	return
+}
+
 // splitQuoted splits the string s around each instance of one or more consecutive
 // white space characters while taking into account quotes and escaping, and
 // returns an array of substrings of s or an empty list if s contains only white space.
@@ -182,6 +236,20 @@ func splitQuoted(s string) (r []string, err os.Error) {
 	return args, err
 }
 
+var safeBytes = []byte("+-.,/0123456789=ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz")
+
+func safeName(s string) bool {
+	if s == "" {
+		return false
+	}
+	for i := 0; i < len(s); i++ {
+		if c := s[i]; c < 0x80 && bytes.IndexByte(safeBytes, c) < 0 {
+			return false
+		}
+	}
+	return true
+}
+
 // Translate rewrites f.AST, the original Go input, to remove
 // references to the imported package C, replacing them with
 // references to the equivalent Go types, functions, and variables.
diff --git a/src/cmd/cgo/out.go b/src/cmd/cgo/out.go
index 2ce4e97..dbc7bcf 100644
--- a/src/cmd/cgo/out.go
+++ b/src/cmd/cgo/out.go
@@ -142,7 +142,7 @@ func dynimport(obj string) {
 	if f, err := pe.Open(obj); err == nil {
 		sym, err := f.ImportedSymbols()
 		if err != nil {
-			fatalf("cannot load imported symbols from PE file %s: v", obj, err)
+			fatalf("cannot load imported symbols from PE file %s: %v", obj, err)
 		}
 		for _, s := range sym {
 			ss := strings.Split(s, ":", -1)
diff --git a/src/cmd/gc/Makefile b/src/cmd/gc/Makefile
index dbfd864..286618e 100644
--- a/src/cmd/gc/Makefile
+++ b/src/cmd/gc/Makefile
@@ -49,7 +49,7 @@ include ../../Make.clib
 install: $(LIB)
 
 y1.tab.c: y.tab.c	# make yystate global, yytname mutable
-	cat y.tab.c | sed '/ int yystate;/d; s/int yychar;/int yychar, yystate;/; s/static const char \*const yytname/const char *yytname/' >y1.tab.c
+	cat y.tab.c | sed '/ int yystate;/d; s/int yychar;/int yychar, yystate;/; s/static const char \*const yytname/const char *yytname/; s/char const \*yymsgp/char *yymsgp/' >y1.tab.c
 
 yerr.h: bisonerrors go.errors y.tab.h	# y.tab.h rule generates y.output too
 	awk -f bisonerrors y.output go.errors >yerr.h
diff --git a/src/cmd/gc/align.c b/src/cmd/gc/align.c
index a8454bf..7fcac48 100644
--- a/src/cmd/gc/align.c
+++ b/src/cmd/gc/align.c
@@ -234,9 +234,11 @@ dowidth(Type *t)
 			if(t->bound > cap)
 				yyerror("type %lT larger than address space", t);
 			w = t->bound * t->type->width;
-			if(w == 0)
-				w = 1;
 			t->align = t->type->align;
+			if(w == 0) {
+				w = 1;
+				t->align = 1;
+			}
 		}
 		else if(t->bound == -1) {
 			w = sizeof_Array;
@@ -253,10 +255,10 @@ dowidth(Type *t)
 		if(t->funarg)
 			fatal("dowidth fn struct %T", t);
 		w = widstruct(t, 0, 1);
-		if(w == 0)
+		if(w == 0) {
 			w = 1;
-		//if(t->align < widthptr)
-		//	warn("align %d: %T\n", t->align, t);
+			t->align = 1;
+		}
 		break;
 
 	case TFUNC:
diff --git a/src/cmd/gc/closure.c b/src/cmd/gc/closure.c
index eb70143..906dadb 100644
--- a/src/cmd/gc/closure.c
+++ b/src/cmd/gc/closure.c
@@ -75,7 +75,7 @@ closurebody(NodeList *body)
 }
 
 void
-typecheckclosure(Node *func)
+typecheckclosure(Node *func, int top)
 {
 	Node *oldfn;
 	NodeList *l;
@@ -106,6 +106,10 @@ typecheckclosure(Node *func)
 			v->op = 0;
 			continue;
 		}
+		// For a closure that is called in place, but not
+		// inside a go statement, avoid moving variables to the heap.
+		if ((top & (Ecall|Eproc)) == Ecall)
+			v->heapaddr->etype = 1;
 		typecheck(&v->heapaddr, Erv);
 		func->enter = list(func->enter, v->heapaddr);
 		v->heapaddr = N;
@@ -199,3 +203,41 @@ walkclosure(Node *func, NodeList **init)
 	walkexpr(&call, init);
 	return call;
 }
+
+// Special case for closures that get called in place.
+// Optimize runtime.closure(X, __func__xxxx_, .... ) away
+// to __func__xxxx_(Y ....).
+// On entry, expect n->op == OCALL, n->left->op == OCLOSURE.
+void
+walkcallclosure(Node *n, NodeList **init)
+{
+	Node *z;
+	NodeList *ll, *cargs;
+
+	walkexpr(&n->left, init);
+	cargs =	n->left    // FUNC runtime.closure
+		->list     // arguments
+		->next     // skip first
+		->next;    // skip second
+
+	n->left = n->left  // FUNC runtime.closure
+		->list     // arguments
+		->next     // skip first
+		->n        // AS (to indreg) 
+		->right;   // argument  == the generated function 
+
+	// New arg list for n. First the closure-args, stolen from
+	// runtime.closure's 3rd and following,
+	ll = nil;
+	for (; cargs; cargs = cargs->next)
+		ll = list(ll, cargs->n->right);  // cargs->n is the OAS(INDREG, arg)
+
+	// then an extra zero, to fill the dummy return pointer slot,
+	z = nod(OXXX, N, N);
+	nodconst(z, types[TUINTPTR], 0);
+	z->typecheck = 1;
+	ll = list(ll, z);
+
+	// and finally the original parameter list.
+	n->list = concat(ll, n->list);
+}
diff --git a/src/cmd/gc/const.c b/src/cmd/gc/const.c
index a36ec68..8fe9072 100644
--- a/src/cmd/gc/const.c
+++ b/src/cmd/gc/const.c
@@ -103,6 +103,8 @@ convlit1(Node **np, Type *t, int explicit)
 	case ORSH:
 		convlit1(&n->left, t, explicit && isideal(n->left->type));
 		t = n->left->type;
+		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);
 			t = T;
@@ -514,6 +516,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);
+		nr->val = toint(nr->val);
 		break;
 	}
 
diff --git a/src/cmd/gc/dcl.c b/src/cmd/gc/dcl.c
index 99af18d..78c6763 100644
--- a/src/cmd/gc/dcl.c
+++ b/src/cmd/gc/dcl.c
@@ -188,6 +188,7 @@ declare(Node *n, int ctxt)
 		else if(n->op == ONAME)
 			gen = ++vargen;
 		pushdcl(s);
+		n->curfn = curfn;
 	}
 	if(ctxt == PAUTO)
 		n->xoffset = BADWIDTH;
@@ -524,6 +525,30 @@ colas(NodeList *left, NodeList *right)
 }
 
 /*
+ * declare the arguments in an
+ * interface field declaration.
+ */
+void
+ifacedcl(Node *n)
+{
+	if(n->op != ODCLFIELD || n->right == N)
+		fatal("ifacedcl");
+
+	dclcontext = PAUTO;
+	markdcl();
+	funcdepth++;
+	n->outer = curfn;
+	curfn = n;
+	funcargs(n->right);
+
+	// funcbody is normally called after the parser has
+	// seen the body of a function but since an interface
+	// field declaration does not have a body, we must
+	// call it now to pop the current declaration context.
+	funcbody(n);
+}
+
+/*
  * declare the function proper
  * and declare the arguments.
  * called in extern-declaration context
@@ -1226,9 +1251,6 @@ funccompile(Node *n, int isclosure)
 
 	if(curfn)
 		fatal("funccompile %S inside %S", n->nname->sym, curfn->nname->sym);
-	curfn = n;
-	typechecklist(n->nbody, Etop);
-	curfn = nil;
 
 	stksize = 0;
 	dclcontext = PAUTO;
diff --git a/src/cmd/gc/gen.c b/src/cmd/gc/gen.c
index 8ad6c43..0b6f5bb 100644
--- a/src/cmd/gc/gen.c
+++ b/src/cmd/gc/gen.c
@@ -59,6 +59,8 @@ allocparams(void)
 			fatal("bad width");
 		stksize += w;
 		stksize = rnd(stksize, n->type->align);
+		if(thechar == '5')
+			stksize = rnd(stksize, widthptr);
 		n->xoffset = -stksize;
 	}
 	lineno = lno;
@@ -698,6 +700,8 @@ tempname(Node *n, Type *t)
 	w = t->width;
 	stksize += w;
 	stksize = rnd(stksize, t->align);
+	if(thechar == '5')
+		stksize = rnd(stksize, widthptr);
 	n->xoffset = -stksize;
 	n->pun = anyregalloc();
 }
diff --git a/src/cmd/gc/go.h b/src/cmd/gc/go.h
index 359881e..f5c0443 100644
--- a/src/cmd/gc/go.h
+++ b/src/cmd/gc/go.h
@@ -254,6 +254,7 @@ struct	Node
 	Node*	ntype;
 	Node*	defn;
 	Node*	pack;	// real package for import . names
+	Node*	curfn;	// function for local variables
 
 	// ONAME func param with PHEAP
 	Node*	heapaddr;	// temp holding heap address of param
@@ -517,15 +518,16 @@ enum
 
 enum
 {
-	Etop = 1<<1,	// evaluated at statement level
-	Erv = 1<<2,	// evaluated in value context
+	Etop = 1<<1,		// evaluated at statement level
+	Erv = 1<<2,		// evaluated in value context
 	Etype = 1<<3,
-	Ecall = 1<<4,	// call-only expressions are ok
+	Ecall = 1<<4,		// call-only expressions are ok
 	Efnstruct = 1<<5,	// multivalue function returns are ok
 	Eiota = 1<<6,		// iota is ok
 	Easgn = 1<<7,		// assigning to expression
 	Eindir = 1<<8,		// indirecting through expression
 	Eaddr = 1<<9,		// taking address of expression
+	Eproc = 1<<10,		// inside a go statement
 };
 
 #define	BITS	5
@@ -815,8 +817,9 @@ int	bset(Bits a, uint n);
  */
 Node*	closurebody(NodeList *body);
 void	closurehdr(Node *ntype);
-void	typecheckclosure(Node *func);
+void	typecheckclosure(Node *func, int top);
 Node*	walkclosure(Node *func, NodeList **init);
+void	walkcallclosure(Node *n, NodeList **init);
 
 /*
  *	const.c
@@ -870,6 +873,7 @@ void	funcbody(Node *n);
 void	funccompile(Node *n, int isclosure);
 void	funchdr(Node *n);
 Type*	functype(Node *this, NodeList *in, NodeList *out);
+void	ifacedcl(Node *n);
 int	isifacemethod(Type *f);
 void	markdcl(void);
 Node*	methodname(Node *n, Type *t);
@@ -1209,6 +1213,7 @@ EXTERN	Prog*	continpc;
 EXTERN	Prog*	breakpc;
 EXTERN	Prog*	pc;
 EXTERN	Prog*	firstpc;
+EXTERN	Prog*	retpc;
 
 EXTERN	Node*	nodfp;
 
@@ -1222,6 +1227,7 @@ void	cgen_callinter(Node *n, Node *res, int proc);
 void	cgen_ret(Node *n);
 void	clearfat(Node *n);
 void	compile(Node*);
+void	defframe(Prog*);
 int	dgostringptr(Sym*, int off, char *str);
 int	dgostrlitptr(Sym*, int off, Strlit*);
 int	dstringptr(Sym *s, int off, char *str);
diff --git a/src/cmd/gc/go.y b/src/cmd/gc/go.y
index 7adfd00..fdaab4f 100644
--- a/src/cmd/gc/go.y
+++ b/src/cmd/gc/go.y
@@ -1380,6 +1380,7 @@ interfacedcl:
 	new_name indcl
 	{
 		$$ = nod(ODCLFIELD, $1, $2);
+		ifacedcl($$);
 	}
 |	packname
 	{
diff --git a/src/cmd/gc/init.c b/src/cmd/gc/init.c
index af4eb03..8818db0 100644
--- a/src/cmd/gc/init.c
+++ b/src/cmd/gc/init.c
@@ -182,11 +182,14 @@ fninit(NodeList *n)
 	// (11)
 	a = nod(ORETURN, N, N);
 	r = list(r, a);
-
 	exportsym(fn->nname);
 
 	fn->nbody = r;
 	funcbody(fn);
+
+	curfn = fn;
 	typecheck(&fn, Etop);
+	typechecklist(r, Etop);
+	curfn = nil;
 	funccompile(fn, 0);
 }
diff --git a/src/cmd/gc/lex.c b/src/cmd/gc/lex.c
index 04dd0d5..5e2f73f 100644
--- a/src/cmd/gc/lex.c
+++ b/src/cmd/gc/lex.c
@@ -235,13 +235,14 @@ main(int argc, char *argv[])
 	if(debug['f'])
 		frame(1);
 
-	// Process top-level declarations in three phases.
+	// Process top-level declarations in four phases.
 	// Phase 1: const, type, and names and types of funcs.
 	//   This will gather all the information about types
 	//   and methods but doesn't depend on any of it.
 	// Phase 2: Variable assignments.
 	//   To check interface assignments, depends on phase 1.
-	// Phase 3: Function bodies.
+	// Phase 3: Type check function bodies.
+	// Phase 4: Compile function bodies.
 	defercheckwidth();
 	for(l=xtop; l; l=l->next)
 		if(l->n->op != ODCL && l->n->op != OAS)
@@ -251,17 +252,28 @@ main(int argc, char *argv[])
 			typecheck(&l->n, Etop);
 	resumetypecopy();
 	resumecheckwidth();
+
+	for(l=xtop; l; l=l->next)
+		if(l->n->op == ODCLFUNC) {
+			curfn = l->n;
+			typechecklist(l->n->nbody, Etop);
+		}
+	curfn = nil;
+
 	for(l=xtop; l; l=l->next)
 		if(l->n->op == ODCLFUNC)
 			funccompile(l->n, 0);
+
 	if(nerrors == 0)
 		fninit(xtop);
+
 	while(closures) {
 		l = closures;
 		closures = nil;
 		for(; l; l=l->next)
 			funccompile(l->n, 1);
 	}
+
 	dclchecks();
 
 	if(nerrors)
diff --git a/src/cmd/gc/obj.c b/src/cmd/gc/obj.c
index 9f4b7b3..f34fc76 100644
--- a/src/cmd/gc/obj.c
+++ b/src/cmd/gc/obj.c
@@ -284,6 +284,7 @@ stringsym(char *s, int len)
 		off = dsname(sym, off, s+n, m);
 	}
 	off = duint8(sym, off, 0);  // terminating NUL for runtime
+	off = (off+widthptr-1)&~(widthptr-1);  // round to pointer alignment
 	ggloblsym(sym, off, 1);
 	text();
 	
diff --git a/src/cmd/gc/pgen.c b/src/cmd/gc/pgen.c
new file mode 100644
index 0000000..9bd845d
--- /dev/null
+++ b/src/cmd/gc/pgen.c
@@ -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.
+
+#undef	EXTERN
+#define	EXTERN
+#include "gg.h"
+#include "opt.h"
+
+void
+compile(Node *fn)
+{
+	Plist *pl;
+	Node nod1, *n;
+	Prog *ptxt;
+	int32 lno;
+	Type *t;
+	Iter save;
+
+	if(newproc == N) {
+		newproc = sysfunc("newproc");
+		deferproc = sysfunc("deferproc");
+		deferreturn = sysfunc("deferreturn");
+		panicindex = sysfunc("panicindex");
+		panicslice = sysfunc("panicslice");
+		throwreturn = sysfunc("throwreturn");
+	}
+
+	if(fn->nbody == nil)
+		return;
+
+	// set up domain for labels
+	clearlabels();
+
+	lno = setlineno(fn);
+
+	curfn = fn;
+	dowidth(curfn->type);
+
+	if(curfn->type->outnamed) {
+		// add clearing of the output parameters
+		t = structfirst(&save, getoutarg(curfn->type));
+		while(t != T) {
+			if(t->nname != N) {
+				n = nod(OAS, t->nname, N);
+				typecheck(&n, Etop);
+				curfn->nbody = concat(list1(n), curfn->nbody);
+			}
+			t = structnext(&save);
+		}
+	}
+
+	hasdefer = 0;
+	walk(curfn);
+	if(nerrors != 0 || isblank(curfn->nname))
+		goto ret;
+
+	allocparams();
+
+	continpc = P;
+	breakpc = P;
+
+	pl = newplist();
+	pl->name = curfn->nname;
+
+	setlineno(curfn);
+
+	nodconst(&nod1, types[TINT32], 0);
+	ptxt = gins(ATEXT, curfn->nname, &nod1);
+	afunclit(&ptxt->from);
+
+	ginit();
+	genlist(curfn->enter);
+
+	retpc = nil;
+	if(hasdefer || curfn->exit) {
+		Prog *p1;
+
+		p1 = gjmp(nil);
+		retpc = gjmp(nil);
+		patch(p1, pc);
+	}
+
+	genlist(curfn->nbody);
+	gclean();
+	checklabels();
+	if(nerrors != 0)
+		goto ret;
+	if(curfn->endlineno)
+		lineno = curfn->endlineno;
+
+	if(curfn->type->outtuple != 0)
+		ginscall(throwreturn, 0);
+
+	if(retpc)
+		patch(retpc, pc);
+	ginit();
+	if(hasdefer)
+		ginscall(deferreturn, 0);
+	if(curfn->exit)
+		genlist(curfn->exit);
+	gclean();
+	if(nerrors != 0)
+		goto ret;
+	pc->as = ARET;	// overwrite AEND
+	pc->lineno = lineno;
+
+	if(!debug['N'] || debug['R'] || debug['P']) {
+		regopt(ptxt);
+	}
+
+	defframe(ptxt);
+
+	if(debug['f'])
+		frame(0);
+
+ret:
+	lineno = lno;
+}
diff --git a/src/cmd/gc/sinit.c b/src/cmd/gc/sinit.c
index be96a14..eb7ef31 100644
--- a/src/cmd/gc/sinit.c
+++ b/src/cmd/gc/sinit.c
@@ -173,10 +173,10 @@ initfix(NodeList *l)
 
 /*
  * from here down is the walk analysis
- * of composit literals.
+ * of composite literals.
  * most of the work is to generate
  * data statements for the constant
- * part of the composit literal.
+ * part of the composite literal.
  */
 
 static	void	structlit(int ctxt, int pass, Node *n, Node *var, NodeList **init);
diff --git a/src/cmd/gc/subr.c b/src/cmd/gc/subr.c
index 326a5ba..4c0819c 100644
--- a/src/cmd/gc/subr.c
+++ b/src/cmd/gc/subr.c
@@ -3170,7 +3170,10 @@ genwrapper(Type *rcvr, Type *method, Sym *newnam, int iface)
 		dumplist("genwrapper body", fn->nbody);
 
 	funcbody(fn);
+	curfn = fn;
 	typecheck(&fn, Etop);
+	typechecklist(fn->nbody, Etop);
+	curfn = nil;
 	funccompile(fn, 0);
 }
 
diff --git a/src/cmd/gc/typecheck.c b/src/cmd/gc/typecheck.c
index 9aaf3e6..44d0835 100644
--- a/src/cmd/gc/typecheck.c
+++ b/src/cmd/gc/typecheck.c
@@ -29,8 +29,8 @@ static void	typecheckfunc(Node*);
 static void	checklvalue(Node*, char*);
 static void	checkassign(Node*);
 static void	checkassignlist(NodeList*);
-static void stringtoarraylit(Node**);
-static Node* resolve(Node*);
+static void	stringtoarraylit(Node**);
+static Node*	resolve(Node*);
 static Type*	getforwtype(Node*);
 
 /*
@@ -780,7 +780,7 @@ reswitch:
 			n = r;
 			goto reswitch;
 		}
-		typecheck(&n->left, Erv | Etype | Ecall);
+		typecheck(&n->left, Erv | Etype | Ecall |(top&Eproc));
 		l = n->left;
 		if(l->op == ONAME && l->etype != 0) {
 			if(n->isddd && l->etype != OAPPEND)
@@ -794,7 +794,7 @@ reswitch:
 		defaultlit(&n->left, T);
 		l = n->left;
 		if(l->op == OTYPE) {
-			if(n->isddd)
+			if(n->isddd || l->type->bound == -100)
 				yyerror("invalid use of ... in type conversion", l);
 			// pick off before type-checking arguments
 			ok |= Erv;
@@ -822,7 +822,13 @@ reswitch:
 
 		case ODOTMETH:
 			n->op = OCALLMETH;
-			typecheckaste(OCALL, n->left, 0, getthisx(t), list1(l->left), "method receiver");
+			// typecheckaste was used here but there wasn't enough
+			// information further down the call chain to know if we
+			// were testing a method receiver for unexported fields.
+			// It isn't necessary, so just do a sanity check.
+			tp = getthisx(t)->type->type;
+			if(l->left == N || !eqtype(l->left->type, tp))
+				fatal("method receiver");
 			break;
 
 		default:
@@ -1021,9 +1027,9 @@ reswitch:
 		
 		// copy([]byte, string)
 		if(isslice(n->left->type) && n->right->type->etype == TSTRING) {
-		        if (n->left->type->type ==types[TUINT8])
-			        goto ret;
-		        yyerror("arguments to copy have different element types: %lT and string", n->left->type);
+			if (n->left->type->type == types[TUINT8])
+				goto ret;
+			yyerror("arguments to copy have different element types: %lT and string", n->left->type);
 			goto error;
 		}
 			       
@@ -1211,7 +1217,7 @@ reswitch:
 
 	case OCLOSURE:
 		ok |= Erv;
-		typecheckclosure(n);
+		typecheckclosure(n, top);
 		if(n->type == T)
 			goto error;
 		goto ret;
@@ -1240,11 +1246,15 @@ reswitch:
 		goto ret;
 
 	case ODEFER:
-	case OPROC:
 		ok |= Etop;
 		typecheck(&n->left, Etop);
 		goto ret;
 
+	case OPROC:
+		ok |= Etop;
+		typecheck(&n->left, Etop|Eproc);
+		goto ret;
+
 	case OFOR:
 		ok |= Etop;
 		typechecklist(n->ninit, Etop);
@@ -2159,7 +2169,9 @@ addrescapes(Node *n)
 		if(n->noescape)
 			break;
 		switch(n->class) {
-		case PAUTO:
+		case PPARAMREF:
+			addrescapes(n->defn);
+			break;
 		case PPARAM:
 		case PPARAMOUT:
 			// if func param, need separate temporary
@@ -2167,16 +2179,17 @@ addrescapes(Node *n)
 			// the function type has already been checked
 			// (we're in the function body)
 			// so the param already has a valid xoffset.
-			if(n->class == PPARAM || n->class == PPARAMOUT) {
-				// expression to refer to stack copy
-				n->stackparam = nod(OPARAM, n, N);
-				n->stackparam->type = n->type;
-				n->stackparam->addable = 1;
-				if(n->xoffset == BADWIDTH)
-					fatal("addrescapes before param assignment");
-				n->stackparam->xoffset = n->xoffset;
-				n->xoffset = 0;
-			}
+
+			// expression to refer to stack copy
+			n->stackparam = nod(OPARAM, n, N);
+			n->stackparam->type = n->type;
+			n->stackparam->addable = 1;
+			if(n->xoffset == BADWIDTH)
+				fatal("addrescapes before param assignment");
+			n->stackparam->xoffset = n->xoffset;
+			n->xoffset = 0;
+			// fallthrough
+		case PAUTO:
 
 			n->class |= PHEAP;
 			n->addable = 0;
@@ -2189,7 +2202,9 @@ addrescapes(Node *n)
 			snprint(buf, sizeof buf, "&%S", n->sym);
 			n->heapaddr->sym = lookup(buf);
 			n->heapaddr->class = PHEAP-1;	// defer tempname to allocparams
-			curfn->dcl = list(curfn->dcl, n->heapaddr);
+			n->heapaddr->ullman = 1;
+			n->curfn->dcl = list(n->curfn->dcl, n->heapaddr);
+
 			break;
 		}
 		break;
diff --git a/src/cmd/gc/walk.c b/src/cmd/gc/walk.c
index b3b4005..ccc65ff 100644
--- a/src/cmd/gc/walk.c
+++ b/src/cmd/gc/walk.c
@@ -66,6 +66,7 @@ walk(Node *fn)
 	int lno;
 
 	curfn = fn;
+
 	if(debug['W']) {
 		snprint(s, sizeof(s), "\nbefore %S", curfn->nname->sym);
 		dumplist(s, curfn->nbody);
@@ -73,7 +74,7 @@ walk(Node *fn)
 	if(curfn->type->outtuple)
 		if(walkret(curfn->nbody))
 			yyerror("function ends without a return statement");
-	typechecklist(curfn->nbody, Etop);
+
 	lno = lineno;
 	for(l=fn->dcl; l; l=l->next) {
 		n = l->n;
@@ -468,8 +469,10 @@ walkstmt(Node **np)
 	case OPANIC:
 	case OEMPTY:
 	case ORECOVER:
-		if(n->typecheck == 0)
+		if(n->typecheck == 0) {
+			dump("missing typecheck:", n);
 			fatal("missing typecheck");
+		}
 		init = n->ninit;
 		n->ninit = nil;
 		walkexpr(&n, &init);
@@ -770,8 +773,15 @@ walkexpr(Node **np, NodeList **init)
 		t = n->left->type;
 		if(n->list && n->list->n->op == OAS)
 			goto ret;
-		walkexpr(&n->left, init);
+
+		if(n->left->op == OCLOSURE) {
+			walkcallclosure(n, init);
+			t = n->left->type;
+		} else
+			walkexpr(&n->left, init);
+
 		walkexprlist(n->list, init);
+
 		ll = ascompatte(n->op, n->isddd, getinarg(t), n->list, 0, init);
 		n->list = reorder1(ll);
 		if(isselect(n)) {
@@ -1525,7 +1535,7 @@ ascompatee(int op, NodeList *nl, NodeList *nr, NodeList **init)
 static int
 fncall(Node *l, Type *rt)
 {
-	if(l->ullman >= UINF)
+	if(l->ullman >= UINF || l->op == OINDEXMAP)
 		return 1;
 	if(eqtype(l->type, rt))
 		return 0;
diff --git a/src/cmd/godoc/spec.go b/src/cmd/godoc/spec.go
index f8b95e3..d863ca0 100644
--- a/src/cmd/godoc/spec.go
+++ b/src/cmd/godoc/spec.go
@@ -99,7 +99,8 @@ func (p *ebnfParser) parseTerm() bool {
 
 	case token.STRING:
 		p.next()
-		if p.tok == token.ELLIPSIS {
+		const ellipsis = "…" // U+2026, the horizontal ellipsis character
+		if p.tok == token.ILLEGAL && p.lit == ellipsis {
 			p.next()
 			p.expect(token.STRING)
 		}
@@ -157,7 +158,7 @@ func (p *ebnfParser) parse(fset *token.FileSet, out io.Writer, src []byte) {
 	p.out = out
 	p.src = src
 	p.file = fset.AddFile("", fset.Base(), len(src))
-	p.scanner.Init(p.file, src, p, 0)
+	p.scanner.Init(p.file, src, p, scanner.AllowIllegalChars)
 	p.next() // initializes pos, tok, lit
 
 	// process source
diff --git a/src/cmd/gofix/main.go b/src/cmd/gofix/main.go
index 4f7e923..ba2061a 100644
--- a/src/cmd/gofix/main.go
+++ b/src/cmd/gofix/main.go
@@ -248,17 +248,5 @@ func diff(b1, b2 []byte) (data []byte, err os.Error) {
 	f1.Write(b1)
 	f2.Write(b2)
 
-	diffcmd, err := exec.LookPath("diff")
-	if err != nil {
-		return nil, err
-	}
-
-	c, err := exec.Run(diffcmd, []string{"diff", f1.Name(), f2.Name()}, nil, "",
-		exec.DevNull, exec.Pipe, exec.MergeWithStdout)
-	if err != nil {
-		return nil, err
-	}
-	defer c.Close()
-
-	return ioutil.ReadAll(c.Stdout)
+	return exec.Command("diff", f1.Name(), f2.Name()).CombinedOutput()
 }
diff --git a/src/cmd/gofmt/gofmt.go b/src/cmd/gofmt/gofmt.go
index 5dd801d..16bcd3c 100644
--- a/src/cmd/gofmt/gofmt.go
+++ b/src/cmd/gofmt/gofmt.go
@@ -245,14 +245,14 @@ func gofmtMain() {
 func diff(b1, b2 []byte) (data []byte, err os.Error) {
 	f1, err := ioutil.TempFile("", "gofmt")
 	if err != nil {
-		return nil, err
+		return
 	}
 	defer os.Remove(f1.Name())
 	defer f1.Close()
 
 	f2, err := ioutil.TempFile("", "gofmt")
 	if err != nil {
-		return nil, err
+		return
 	}
 	defer os.Remove(f2.Name())
 	defer f2.Close()
@@ -260,17 +260,5 @@ func diff(b1, b2 []byte) (data []byte, err os.Error) {
 	f1.Write(b1)
 	f2.Write(b2)
 
-	diffcmd, err := exec.LookPath("diff")
-	if err != nil {
-		return nil, err
-	}
-
-	c, err := exec.Run(diffcmd, []string{"diff", "-u", f1.Name(), f2.Name()},
-		nil, "", exec.DevNull, exec.Pipe, exec.MergeWithStdout)
-	if err != nil {
-		return nil, err
-	}
-	defer c.Close()
-
-	return ioutil.ReadAll(c.Stdout)
+	return exec.Command("diff", "-u", f1.Name(), f2.Name()).CombinedOutput()
 }
diff --git a/src/cmd/goinstall/doc.go b/src/cmd/goinstall/doc.go
index 15845b5..13c37d0 100644
--- a/src/cmd/goinstall/doc.go
+++ b/src/cmd/goinstall/doc.go
@@ -3,7 +3,6 @@
 // license that can be found in the LICENSE file.
 
 /*
-
 Goinstall is an experiment in automatic package installation.
 It installs packages, possibly downloading them from the internet.
 It maintains a list of public Go packages at http://godashboard.appspot.com/package.
@@ -100,5 +99,59 @@ Instead, it invokes "make install" after locating the package sources.
 For local packages without a Makefile and all remote packages,
 goinstall creates and uses a temporary Makefile constructed from
 the import path and the list of Go files in the package.
+
+
+The GOPATH Environment Variable
+
+GOPATH may be set to a colon-separated list of paths inside which Go code,
+package objects, and executables may be found.
+
+Set a GOPATH to use goinstall to build and install your own code and
+external libraries outside of the Go tree (and to avoid writing Makefiles).
+
+The top-level directory structure of a GOPATH is prescribed:
+
+The 'src' directory is for source code. The directory naming inside 'src'
+determines the package import path or executable name.
+
+The 'pkg' directory is for package objects. Like the Go tree, package objects
+are stored inside a directory named after the target operating system and
+processor architecture ('pkg/$GOOS_$GOARCH').
+A package whose source is located at '$GOPATH/src/foo/bar' would be imported
+as 'foo/bar' and installed as '$GOPATH/pkg/$GOOS_$GOARCH/foo/bar.a'.
+
+The 'bin' directory is for executable files.
+Goinstall installs program binaries using the name of the source folder.
+A binary whose source is at 'src/foo/qux' would be built and installed to
+'$GOPATH/bin/qux'. (Note 'bin/qux', not 'bin/foo/qux' - this is such that
+you can put the bin directory in your PATH.) 
+
+Here's an example directory layout:
+
+	GOPATH=/home/user/gocode
+
+	/home/user/gocode/
+		src/foo/
+			bar/               (go code in package bar)
+			qux/               (go code in package main)
+		bin/qux                    (executable file)
+		pkg/linux_amd64/foo/bar.a  (object file)
+
+Run 'goinstall foo/bar' to build and install the package 'foo/bar'
+(and its dependencies).
+Goinstall will search each GOPATH (in order) for 'src/foo/bar'.
+If the directory cannot be found, goinstall will attempt to fetch the
+source from a remote repository and write it to the 'src' directory of the
+first GOPATH (or $GOROOT/src/pkg if GOPATH is not set).
+
+Goinstall recognizes relative and absolute paths (paths beginning with / or .).
+The following commands would build our example packages:
+
+	goinstall /home/user/gocode/src/foo/bar  # build and install foo/bar
+	cd /home/user/gocode/src/foo
+	goinstall ./bar  # build and install foo/bar (again)
+	cd qux
+	goinstall .      # build and install foo/qux
+
 */
 package documentation
diff --git a/src/cmd/goinstall/download.go b/src/cmd/goinstall/download.go
index 7dad596..2edf85e 100644
--- a/src/cmd/goinstall/download.go
+++ b/src/cmd/goinstall/download.go
@@ -31,23 +31,36 @@ func maybeReportToDashboard(path string) {
 	}
 }
 
-var googlecode = regexp.MustCompile(`^([a-z0-9\-]+\.googlecode\.com/(svn|hg))(/[a-z0-9A-Z_.\-/]*)?$`)
-var github = regexp.MustCompile(`^(github\.com/[a-z0-9A-Z_.\-]+/[a-z0-9A-Z_.\-]+)(/[a-z0-9A-Z_.\-/]*)?$`)
-var bitbucket = regexp.MustCompile(`^(bitbucket\.org/[a-z0-9A-Z_.\-]+/[a-z0-9A-Z_.\-]+)(/[a-z0-9A-Z_.\-/]*)?$`)
-var launchpad = 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_.\-/]+)?$`)
+var vcsPatterns = map[string]*regexp.Regexp{
+	"googlecode": regexp.MustCompile(`^([a-z0-9\-]+\.googlecode\.com/(svn|hg))(/[a-z0-9A-Z_.\-/]*)?$`),
+	"github":     regexp.MustCompile(`^(github\.com/[a-z0-9A-Z_.\-]+/[a-z0-9A-Z_.\-]+)(/[a-z0-9A-Z_.\-/]*)?$`),
+	"bitbucket":  regexp.MustCompile(`^(bitbucket\.org/[a-z0-9A-Z_.\-]+/[a-z0-9A-Z_.\-]+)(/[a-z0-9A-Z_.\-/]*)?$`),
+	"launchpad":  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_.\-/]+)?$`),
+}
+
+// isRemote returns true if the provided package path
+// matches one of the supported remote repositories.
+func isRemote(pkg string) bool {
+	for _, r := range vcsPatterns {
+		if r.MatchString(pkg) {
+			return true
+		}
+	}
+	return false
+}
 
 // download checks out or updates pkg from the remote server.
 func download(pkg, srcDir string) os.Error {
 	if strings.Contains(pkg, "..") {
 		return os.ErrorString("invalid path (contains ..)")
 	}
-	if m := bitbucket.FindStringSubmatch(pkg); m != nil {
+	if m := vcsPatterns["bitbucket"].FindStringSubmatch(pkg); m != nil {
 		if err := vcsCheckout(&hg, srcDir, m[1], "http://"+m[1], m[1]); err != nil {
 			return err
 		}
 		return nil
 	}
-	if m := googlecode.FindStringSubmatch(pkg); m != nil {
+	if m := vcsPatterns["googlecode"].FindStringSubmatch(pkg); m != nil {
 		var v *vcs
 		switch m[2] {
 		case "hg":
@@ -63,7 +76,7 @@ func download(pkg, srcDir string) os.Error {
 		}
 		return nil
 	}
-	if m := github.FindStringSubmatch(pkg); m != nil {
+	if m := vcsPatterns["github"].FindStringSubmatch(pkg); m != nil {
 		if strings.HasSuffix(m[1], ".git") {
 			return os.ErrorString("repository " + pkg + " should not have .git suffix")
 		}
@@ -72,7 +85,7 @@ func download(pkg, srcDir string) os.Error {
 		}
 		return nil
 	}
-	if m := launchpad.FindStringSubmatch(pkg); m != nil {
+	if m := vcsPatterns["launchpad"].FindStringSubmatch(pkg); m != nil {
 		// Either lp.net/<project>[/<series>[/<path>]]
 		//	 or lp.net/~<user or team>/<project>/<branch>[/<path>]
 		if err := vcsCheckout(&bzr, srcDir, m[1], "https://"+m[1], m[1]); err != nil {
diff --git a/src/cmd/goinstall/main.go b/src/cmd/goinstall/main.go
index 6cd9290..721e719 100644
--- a/src/cmd/goinstall/main.go
+++ b/src/cmd/goinstall/main.go
@@ -12,7 +12,6 @@ import (
 	"flag"
 	"fmt"
 	"go/token"
-	"io"
 	"io/ioutil"
 	"os"
 	"path/filepath"
@@ -32,9 +31,8 @@ var (
 	argv0         = os.Args[0]
 	errors        = false
 	parents       = make(map[string]string)
-	root          = runtime.GOROOT()
 	visit         = make(map[string]status)
-	logfile       = filepath.Join(root, "goinstall.log")
+	logfile       = filepath.Join(runtime.GOROOT(), "goinstall.log")
 	installedPkgs = make(map[string]bool)
 
 	allpkg            = flag.Bool("a", false, "install all previously installed packages")
@@ -52,14 +50,30 @@ const (
 	done
 )
 
+func logf(format string, args ...interface{}) {
+	format = "%s: " + format
+	args = append([]interface{}{argv0}, args...)
+	fmt.Fprintf(os.Stderr, format, args...)
+}
+
+func vlogf(format string, args ...interface{}) {
+	if *verbose {
+		logf(format, args...)
+	}
+}
+
+func errorf(format string, args ...interface{}) {
+	errors = true
+	logf(format, args...)
+}
+
 func main() {
 	flag.Usage = usage
 	flag.Parse()
-	if root == "" {
+	if runtime.GOROOT() == "" {
 		fmt.Fprintf(os.Stderr, "%s: no $GOROOT\n", argv0)
 		os.Exit(1)
 	}
-	root += filepath.FromSlash("/src/pkg/")
 
 	// special case - "unsafe" is already installed
 	visit["unsafe"] = done
@@ -88,6 +102,11 @@ func main() {
 		usage()
 	}
 	for _, path := range args {
+		if strings.HasPrefix(path, "http://") {
+			errorf("'http://' used in remote path, try '%s'\n", path[7:])
+			continue
+		}
+
 		install(path, "")
 	}
 	if errors {
@@ -143,49 +162,44 @@ func install(pkg, parent string) {
 	}
 	visit[pkg] = visiting
 	parents[pkg] = parent
-	if *verbose {
-		fmt.Println(pkg)
-	}
+
+	vlogf("%s: visit\n", pkg)
 
 	// Check whether package is local or remote.
 	// If remote, download or update it.
-	var dir string
-	proot := gopath[0] // default to GOROOT
-	local := false
-	if strings.HasPrefix(pkg, "http://") {
-		fmt.Fprintf(os.Stderr, "%s: %s: 'http://' used in remote path, try '%s'\n", argv0, pkg, pkg[7:])
-		errors = true
+	proot, pkg, err := findPackageRoot(pkg)
+	// Don't build the standard library.
+	if err == nil && proot.goroot && isStandardPath(pkg) {
+		if parent == "" {
+			errorf("%s: can not goinstall the standard library\n", pkg)
+		} else {
+			vlogf("%s: skipping standard library\n", pkg)
+		}
+		visit[pkg] = done
 		return
 	}
-	if isLocalPath(pkg) {
-		dir = pkg
-		local = true
-	} else if isStandardPath(pkg) {
-		dir = filepath.Join(root, filepath.FromSlash(pkg))
-		local = true
-	} else {
-		proot = findPkgroot(pkg)
-		err := download(pkg, proot.srcDir())
-		dir = filepath.Join(proot.srcDir(), pkg)
-		if err != nil {
-			fmt.Fprintf(os.Stderr, "%s: %s: %s\n", argv0, pkg, err)
-			errors = true
-			visit[pkg] = done
-			return
-		}
+	// Download remote packages if not found or forced with -u flag.
+	remote := isRemote(pkg)
+	if remote && (err == ErrPackageNotFound || (err == nil && *update)) {
+		vlogf("%s: download\n", pkg)
+		err = download(pkg, proot.srcDir())
 	}
+	if err != nil {
+		errorf("%s: %v\n", pkg, err)
+		visit[pkg] = done
+		return
+	}
+	dir := filepath.Join(proot.srcDir(), pkg)
 
 	// Install prerequisites.
 	dirInfo, err := scanDir(dir, parent == "")
 	if err != nil {
-		fmt.Fprintf(os.Stderr, "%s: %s: %s\n", argv0, pkg, err)
-		errors = true
+		errorf("%s: %v\n", pkg, err)
 		visit[pkg] = done
 		return
 	}
 	if len(dirInfo.goFiles) == 0 {
-		fmt.Fprintf(os.Stderr, "%s: %s: package has no files\n", argv0, pkg)
-		errors = true
+		errorf("%s: package has no files\n", pkg)
 		visit[pkg] = done
 		return
 	}
@@ -198,22 +212,16 @@ func install(pkg, parent string) {
 	// Install this package.
 	if !errors {
 		isCmd := dirInfo.pkgName == "main"
-		if err := domake(dir, pkg, proot, local, isCmd); err != nil {
-			fmt.Fprintf(os.Stderr, "%s: installing %s: %s\n", argv0, pkg, err)
-			errors = true
-		} else if !local && *logPkgs {
-			// mark this package as installed in $GOROOT/goinstall.log
+		if err := domake(dir, pkg, proot, isCmd); err != nil {
+			errorf("installing: %v\n", err)
+		} else if remote && *logPkgs {
+			// mark package as installed in $GOROOT/goinstall.log
 			logPackage(pkg)
 		}
 	}
 	visit[pkg] = done
 }
 
-// Is this a local path?  /foo ./foo ../foo . ..
-func isLocalPath(s string) bool {
-	const sep = string(filepath.Separator)
-	return strings.HasPrefix(s, sep) || strings.HasPrefix(s, "."+sep) || strings.HasPrefix(s, ".."+sep) || s == "." || s == ".."
-}
 
 // Is this a standard package path?  strings container/vector etc.
 // Assume that if the first element has a dot, it's a domain name
@@ -237,40 +245,22 @@ func quietRun(dir string, stdin []byte, cmd ...string) os.Error {
 }
 
 // genRun implements run and quietRun.
-func genRun(dir string, stdin []byte, cmd []string, quiet bool) os.Error {
-	bin, err := exec.LookPath(cmd[0])
+func genRun(dir string, stdin []byte, arg []string, quiet bool) os.Error {
+	cmd := exec.Command(arg[0], arg[1:]...)
+	cmd.Stdin = bytes.NewBuffer(stdin)
+	cmd.Dir = dir
+	vlogf("%s: %s %s\n", dir, cmd.Path, strings.Join(arg[1:], " "))
+	out, err := cmd.CombinedOutput()
 	if err != nil {
-		return err
-	}
-	p, err := exec.Run(bin, cmd, os.Environ(), dir, exec.Pipe, exec.Pipe, exec.MergeWithStdout)
-	if *verbose {
-		fmt.Fprintf(os.Stderr, "%s: %s; %s %s\n", argv0, dir, bin, strings.Join(cmd[1:], " "))
-	}
-	if err != nil {
-		return err
-	}
-	go func() {
-		p.Stdin.Write(stdin)
-		p.Stdin.Close()
-	}()
-	var buf bytes.Buffer
-	io.Copy(&buf, p.Stdout)
-	io.Copy(&buf, p.Stdout)
-	w, err := p.Wait(0)
-	p.Close()
-	if err != nil {
-		return err
-	}
-	if !w.Exited() || w.ExitStatus() != 0 {
 		if !quiet || *verbose {
 			if dir != "" {
 				dir = "cd " + dir + "; "
 			}
-			fmt.Fprintf(os.Stderr, "%s: === %s%s\n", argv0, dir, strings.Join(cmd, " "))
-			os.Stderr.Write(buf.Bytes())
-			fmt.Fprintf(os.Stderr, "--- %s\n", w)
+			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)
 		}
-		return os.ErrorString("running " + cmd[0] + ": " + w.String())
+		return os.ErrorString("running " + arg[0] + ": " + err.String())
 	}
 	return nil
 }
diff --git a/src/cmd/goinstall/make.go b/src/cmd/goinstall/make.go
index b2ca82b..0c44481 100644
--- a/src/cmd/goinstall/make.go
+++ b/src/cmd/goinstall/make.go
@@ -14,26 +14,14 @@ import (
 )
 
 // domake builds the package in dir.
-// If local is false, the package was copied from an external system.
-// For non-local packages or packages without Makefiles,
 // domake generates a standard Makefile and passes it
 // to make on standard input.
-func domake(dir, pkg string, root *pkgroot, local, isCmd bool) (err os.Error) {
-	needMakefile := true
-	if local {
-		_, err := os.Stat(dir + "/Makefile")
-		if err == nil {
-			needMakefile = false
-		}
-	}
-	cmd := []string{"gomake"}
-	var makefile []byte
-	if needMakefile {
-		if makefile, err = makeMakefile(dir, pkg, root, isCmd); err != nil {
-			return err
-		}
-		cmd = append(cmd, "-f-")
+func domake(dir, pkg string, root *pkgroot, isCmd bool) (err os.Error) {
+	makefile, err := makeMakefile(dir, pkg, root, isCmd)
+	if err != nil {
+		return err
 	}
+	cmd := []string{"bash", "gomake", "-f-"}
 	if *clean {
 		cmd = append(cmd, "clean")
 	}
@@ -51,16 +39,8 @@ func makeMakefile(dir, pkg string, root *pkgroot, isCmd bool) ([]byte, os.Error)
 	targ := pkg
 	targDir := root.pkgDir()
 	if isCmd {
-		// use the last part of the package name only
+		// use the last part of the package name for targ
 		_, targ = filepath.Split(pkg)
-		// if building the working dir use the directory name
-		if targ == "." {
-			d, err := filepath.Abs(dir)
-			if err != nil {
-				return nil, os.NewError("finding path: " + err.String())
-			}
-			_, targ = filepath.Split(d)
-		}
 		targDir = root.binDir()
 	}
 	dirInfo, err := scanDir(dir, isCmd)
diff --git a/src/cmd/goinstall/path.go b/src/cmd/goinstall/path.go
index 1153e04..b8c3929 100644
--- a/src/cmd/goinstall/path.go
+++ b/src/cmd/goinstall/path.go
@@ -5,10 +5,12 @@
 package main
 
 import (
+	"fmt"
 	"log"
 	"os"
 	"path/filepath"
 	"runtime"
+	"strings"
 )
 
 var (
@@ -19,6 +21,7 @@ var (
 
 // set up gopath: parse and validate GOROOT and GOPATH variables
 func init() {
+	root := runtime.GOROOT()
 	p, err := newPkgroot(root)
 	if err != nil {
 		log.Fatalf("Invalid GOROOT %q: %v", root, err)
@@ -105,13 +108,42 @@ func (r *pkgroot) hasPkg(name string) bool {
 	// TODO(adg): check object version is consistent
 }
 
-// findPkgroot searches each of the gopath roots
-// for the source code for the given import path.
-func findPkgroot(importPath string) *pkgroot {
+
+var ErrPackageNotFound = os.NewError("package could not be found locally")
+
+// findPackageRoot takes an import or filesystem path and returns the
+// root where the package source should be and the package import path.
+func findPackageRoot(path string) (root *pkgroot, pkg string, err os.Error) {
+	if isLocalPath(path) {
+		if path, err = filepath.Abs(path); err != nil {
+			return
+		}
+		for _, r := range gopath {
+			rpath := r.srcDir() + string(filepath.Separator)
+			if !strings.HasPrefix(path, rpath) {
+				continue
+			}
+			root = r
+			pkg = path[len(rpath):]
+			return
+		}
+		err = fmt.Errorf("path %q not inside a GOPATH", path)
+		return
+	}
+	root = defaultRoot
+	pkg = path
 	for _, r := range gopath {
-		if r.hasSrcDir(importPath) {
-			return r
+		if r.hasSrcDir(path) {
+			root = r
+			return
 		}
 	}
-	return defaultRoot
+	err = ErrPackageNotFound
+	return
+}
+
+// Is this a local path?  /foo ./foo ../foo . ..
+func isLocalPath(s string) bool {
+	const sep = string(filepath.Separator)
+	return strings.HasPrefix(s, sep) || strings.HasPrefix(s, "."+sep) || strings.HasPrefix(s, ".."+sep) || s == "." || s == ".."
 }
diff --git a/src/cmd/gotest/gotest.go b/src/cmd/gotest/gotest.go
index 8c81baf..4cb3da2 100644
--- a/src/cmd/gotest/gotest.go
+++ b/src/cmd/gotest/gotest.go
@@ -285,8 +285,8 @@ func doRun(argv []string, returnStdout bool) string {
 			}
 			cmd += `"` + v + `"`
 		}
-		command = "sh"
-		argv = []string{"sh", "-c", cmd}
+		command = "bash"
+		argv = []string{"bash", "-c", cmd}
 	}
 	var err os.Error
 	argv[0], err = exec.LookPath(argv[0])
diff --git a/src/cmd/hgpatch/main.go b/src/cmd/hgpatch/main.go
index 2dcb523..8ee3422 100644
--- a/src/cmd/hgpatch/main.go
+++ b/src/cmd/hgpatch/main.go
@@ -10,7 +10,6 @@ import (
 	"exec"
 	"flag"
 	"fmt"
-	"io"
 	"io/ioutil"
 	"os"
 	"patch"
@@ -333,6 +332,7 @@ func run(argv []string, input []byte) (out string, err os.Error) {
 		err = os.EINVAL
 		goto Error
 	}
+
 	prog, ok := lookPathCache[argv[0]]
 	if !ok {
 		prog, err = exec.LookPath(argv[0])
@@ -341,40 +341,15 @@ func run(argv []string, input []byte) (out string, err os.Error) {
 		}
 		lookPathCache[argv[0]] = prog
 	}
-	// fmt.Fprintf(os.Stderr, "%v\n", argv);
-	var cmd *exec.Cmd
-	if len(input) == 0 {
-		cmd, err = exec.Run(prog, argv, os.Environ(), "", exec.DevNull, exec.Pipe, exec.MergeWithStdout)
-		if err != nil {
-			goto Error
-		}
-	} else {
-		cmd, err = exec.Run(prog, argv, os.Environ(), "", exec.Pipe, exec.Pipe, exec.MergeWithStdout)
-		if err != nil {
-			goto Error
-		}
-		go func() {
-			cmd.Stdin.Write(input)
-			cmd.Stdin.Close()
-		}()
-	}
-	defer cmd.Close()
-	var buf bytes.Buffer
-	_, err = io.Copy(&buf, cmd.Stdout)
-	out = buf.String()
-	if err != nil {
-		cmd.Wait(0)
-		goto Error
-	}
-	w, err := cmd.Wait(0)
-	if err != nil {
-		goto Error
+
+	cmd := exec.Command(prog, argv[1:]...)
+	if len(input) > 0 {
+		cmd.Stdin = bytes.NewBuffer(input)
 	}
-	if !w.Exited() || w.ExitStatus() != 0 {
-		err = w
-		goto Error
+	bs, err := cmd.CombinedOutput()
+	if err == nil {
+		return string(bs), nil
 	}
-	return
 
 Error:
 	err = &runError{dup(argv), err}
diff --git a/src/cmd/ld/dwarf.c b/src/cmd/ld/dwarf.c
index ed11f5e..de600f5 100644
--- a/src/cmd/ld/dwarf.c
+++ b/src/cmd/ld/dwarf.c
@@ -529,8 +529,10 @@ find_or_diag(DWDie *die, char* name)
 {
 	DWDie *r;
 	r = find(die, name);
-	if (r == nil)
+	if (r == nil) {
 		diag("dwarf find: %s has no %s", getattr(die, DW_AT_name)->data, name);
+		errorexit();
+	}
 	return r;
 }
 
@@ -613,7 +615,7 @@ putattr(int form, int cls, vlong value, char *data)
 
 	case DW_FORM_ref_addr:	// reference to a DIE in the .info section
 		if (data == nil) {
-			diag("null dwarf reference");
+			diag("dwarf: null reference");
 			LPUT(0);  // invalid dwarf, gdb will complain.
 		} else {
 			if (((DWDie*)data)->offs == 0)
@@ -631,7 +633,7 @@ putattr(int form, int cls, vlong value, char *data)
 	case DW_FORM_strp:	// string
 	case DW_FORM_indirect:	// (see Section 7.5.3)
 	default:
-		diag("Unsupported atribute form %d / class %d", form, cls);
+		diag("dwarf: unsupported attribute form %d / class %d", form, cls);
 		errorexit();
 	}
 }
@@ -823,7 +825,7 @@ decode_inuxi(uchar* p, int sz)
 		inuxi = inuxi8;
 		break;
 	default:
-		diag("decode inuxi %d", sz);
+		diag("dwarf: decode inuxi %d", sz);
 		errorexit();
 	}
 	for (i = 0; i < sz; i++)
@@ -1013,7 +1015,7 @@ defgotype(Sym *gotype)
 		return find_or_diag(&dwtypes, "<unspecified>");
 
 	if (strncmp("type.", gotype->name, 5) != 0) {
-		diag("Type name doesn't start with \".type\": %s", gotype->name);
+		diag("dwarf: type name doesn't start with \".type\": %s", gotype->name);
 		return find_or_diag(&dwtypes, "<unspecified>");
 	}
 	name = gotype->name + 5;  // could also decode from Type.string
@@ -1164,7 +1166,7 @@ defgotype(Sym *gotype)
 		break;
 
 	default:
-		diag("definition of unknown kind %d: %s", kind, gotype->name);
+		diag("dwarf: definition of unknown kind %d: %s", kind, gotype->name);
 		die = newdie(&dwtypes, DW_ABRV_TYPEDECL, name);
 		newrefattr(die, DW_AT_type, find_or_diag(&dwtypes, "<unspecified>"));
 	 }
@@ -1513,12 +1515,12 @@ decodez(char *s)
 	ss = s + 1;	// first is 0
 	while((o = ((uint8)ss[0] << 8) | (uint8)ss[1]) != 0) {
 		if (o < 0 || o >= ftabsize) {
-			diag("corrupt z entry");
+			diag("dwarf: corrupt z entry");
 			return 0;
 		}
 		f = ftab[o];
 		if (f == nil) {
-			diag("corrupt z entry");
+			diag("dwarf: corrupt z entry");
 			return 0;
 		}
 		len += strlen(f) + 1;	// for the '/'
@@ -1630,11 +1632,11 @@ checknesting(void)
 	int i;
 
 	if (includetop < 0) {
-		diag("corrupt z stack");
+		diag("dwarf: corrupt z stack");
 		errorexit();
 	}
 	if (includetop >= nelem(includestack)) {
-		diag("nesting too deep");
+		diag("dwarf: nesting too deep");
 		for (i = 0; i < nelem(includestack); i++)
 			diag("\t%s", histfile[includestack[i].file]);
 		errorexit();
@@ -1660,7 +1662,7 @@ inithist(Auto *a)
 	// We have a new history.  They are guaranteed to come completely
 	// at the beginning of the compilation unit.
 	if (a->aoffset != 1) {
-		diag("stray 'z' with offset %d", a->aoffset);
+		diag("dwarf: stray 'z' with offset %d", a->aoffset);
 		return 0;
 	}
 
@@ -1915,7 +1917,7 @@ writelines(void)
 			continue;
 
 		if (unitstart < 0) {
-			diag("reachable code before seeing any history: %P", s->text);
+			diag("dwarf: reachable code before seeing any history: %P", s->text);
 			continue;
 		}
 
@@ -1932,7 +1934,7 @@ writelines(void)
 		for(q = s->text; q != P; q = q->link) {
 			lh = searchhist(q->line);
 			if (lh == nil) {
-				diag("corrupt history or bad absolute line: %P", q);
+				diag("dwarf: corrupt history or bad absolute line: %P", q);
 				continue;
 			}
 
@@ -2066,7 +2068,7 @@ writeframes(void)
 	// 4 is to exclude the length field.
 	pad = CIERESERVE + frameo + 4 - cpos();
 	if (pad < 0) {
-		diag("CIERESERVE too small by %lld bytes.", -pad);
+		diag("dwarf: CIERESERVE too small by %lld bytes.", -pad);
 		errorexit();
 	}
 	strnput("", pad);
@@ -2296,6 +2298,9 @@ dwarfemitdebugsections(void)
 	vlong infoe;
 	DWDie* die;
 
+	if(debug['w'])  // disable dwarf
+		return;
+
 	// For diagnostic messages.
 	newattr(&dwtypes, DW_AT_name, DW_CLS_STRING, strlen("dwtypes"), "dwtypes");
 
@@ -2348,11 +2353,11 @@ dwarfemitdebugsections(void)
 		seek(cout, infoo, 0);
 		writeinfo();
 		if (fwdcount > 0) {
-			diag("unresolved references after first dwarf info pass");
+			diag("dwarf: unresolved references after first dwarf info pass");
 			errorexit();
 		}
 		if (infoe != cpos()) {
-			diag("inconsistent second dwarf info pass");
+			diag("dwarf: inconsistent second dwarf info pass");
 			errorexit();
 		}
 	}
@@ -2401,6 +2406,9 @@ vlong elfstrdbg[NElfStrDbg];
 void
 dwarfaddshstrings(Sym *shstrtab)
 {
+	if(debug['w'])  // disable dwarf
+		return;
+
 	elfstrdbg[ElfStrDebugAbbrev]   = addstring(shstrtab, ".debug_abbrev");
 	elfstrdbg[ElfStrDebugAranges]  = addstring(shstrtab, ".debug_aranges");
 	elfstrdbg[ElfStrDebugFrame]    = addstring(shstrtab, ".debug_frame");
@@ -2420,6 +2428,9 @@ dwarfaddelfheaders(void)
 {
 	ElfShdr *sh;
 
+	if(debug['w'])  // disable dwarf
+		return;
+
 	sh = newElfShdr(elfstrdbg[ElfStrDebugAbbrev]);
 	sh->type = SHT_PROGBITS;
 	sh->off = abbrevo;
@@ -2488,6 +2499,9 @@ dwarfaddmachoheaders(void)
 	vlong fakestart;
 	int nsect;
 
+	if(debug['w'])  // disable dwarf
+		return;
+
 	// Zero vsize segments won't be loaded in memory, even so they
 	// have to be page aligned in the file.
 	fakestart = abbrevo & ~0xfff;
@@ -2562,6 +2576,9 @@ dwarfaddmachoheaders(void)
 void
 dwarfaddpeheaders(void)
 {
+	if(debug['w'])  // disable dwarf
+		return;
+
 	newPEDWARFSection(".debug_abbrev", abbrevsize);
 	newPEDWARFSection(".debug_line", linesize);
 	newPEDWARFSection(".debug_frame", framesize);
diff --git a/src/cmd/ld/ldpe.c b/src/cmd/ld/ldpe.c
index d8b0a6f..d6aa267 100644
--- a/src/cmd/ld/ldpe.c
+++ b/src/cmd/ld/ldpe.c
@@ -147,7 +147,7 @@ ldpe(Biobuf *f, char *pkg, int64 len, char *pn)
 			goto bad;
 		obj->sect[i].size = obj->sect[i].sh.SizeOfRawData;
 		obj->sect[i].name = (char*)obj->sect[i].sh.Name;
-		// TODO return error if found .cormeta .rsrc
+		// TODO return error if found .cormeta
 	}
 	// load string table
 	Bseek(f, base+obj->fh.PointerToSymbolTable+18*obj->fh.NumberOfSymbols, 0);
@@ -222,6 +222,8 @@ ldpe(Biobuf *f, char *pkg, int64 len, char *pn)
 			etextp = s;
 		}
 		sect->sym = s;
+		if(strcmp(sect->name, ".rsrc") == 0)
+			setpersrc(sect->sym);
 	}
 	
 	// load relocations
@@ -259,6 +261,7 @@ ldpe(Biobuf *f, char *pkg, int64 len, char *pn)
 					rp->type = D_PCREL;
 					rp->add = 0;
 					break;
+				case IMAGE_REL_I386_DIR32NB:
 				case IMAGE_REL_I386_DIR32:
 					rp->type = D_ADDR;
 					// load addend from image
diff --git a/src/cmd/ld/lib.h b/src/cmd/ld/lib.h
index cd46080..f69f5a3 100644
--- a/src/cmd/ld/lib.h
+++ b/src/cmd/ld/lib.h
@@ -202,6 +202,7 @@ void	addexport(void);
 void	dostkcheck(void);
 void	undef(void);
 void	doweak(void);
+void	setpersrc(Sym*);
 
 int	pathchar(void);
 void*	mal(uint32);
diff --git a/src/cmd/ld/macho.c b/src/cmd/ld/macho.c
index 01349bb..0b12ac1 100644
--- a/src/cmd/ld/macho.c
+++ b/src/cmd/ld/macho.c
@@ -17,6 +17,14 @@ static	MachoSeg	seg[16];
 static	MachoDebug	xdebug[16];
 static	int	nload, mload, nseg, ndebug, nsect;
 
+// Amount of space left for adding load commands
+// that refer to dynamic libraries.  Because these have
+// to go in the Mach-O header, we can't just pick a
+// "big enough" header size.  The initial header is 
+// one page, the non-dynamic library stuff takes
+// up about 1300 bytes; we overestimate that as 2k.
+static	int	load_budget = INITIAL_MACHO_HEADR - 2*1024;
+
 void
 machoinit(void)
 {
@@ -267,6 +275,17 @@ domacho(void)
 void
 machoadddynlib(char *lib)
 {
+	// Will need to store the library name rounded up
+	// and 24 bytes of header metadata.  If not enough
+	// space, grab another page of initial space at the
+	// beginning of the output file.
+	load_budget -= (strlen(lib)+7)/8*8 + 24;
+	if(load_budget < 0) {
+		HEADR += 4096;
+		INITTEXT += 4096;
+		load_budget += 4096;
+	}
+
 	if(ndylib%32 == 0) {
 		dylib = realloc(dylib, (ndylib+32)*sizeof dylib[0]);
 		if(dylib == nil) {
@@ -463,8 +482,8 @@ asmbmacho(void)
 	}
 
 	a = machowrite();
-	if(a > MACHORESERVE)
-		diag("MACHORESERVE too small: %d > %d", a, MACHORESERVE);
+	if(a > HEADR)
+		diag("HEADR too small: %d > %d", a, HEADR);
 }
 
 vlong
diff --git a/src/cmd/ld/macho.h b/src/cmd/ld/macho.h
index 4cc7edc..f551041 100644
--- a/src/cmd/ld/macho.h
+++ b/src/cmd/ld/macho.h
@@ -63,7 +63,7 @@ void	machoinit(void);
  * for Header, PHeaders, and SHeaders.
  * May waste some.
  */
-#define	MACHORESERVE	3*1024
+#define	INITIAL_MACHO_HEADR	4*1024
 
 enum {
 	MACHO_CPU_AMD64 = (1<<24)|7,
diff --git a/src/cmd/ld/pe.c b/src/cmd/ld/pe.c
index 1c0c665..91e15d3 100644
--- a/src/cmd/ld/pe.c
+++ b/src/cmd/ld/pe.c
@@ -34,6 +34,8 @@ static char dosstub[] =
 	0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
 };
 
+static Sym *rsrcsym;
+
 static char symnames[256]; 
 static int  nextsymoff;
 
@@ -459,6 +461,48 @@ addsymtable(void)
 }
 
 void
+setpersrc(Sym *sym)
+{
+	if(rsrcsym != nil)
+		diag("too many .rsrc sections");
+	
+	rsrcsym = sym;
+}
+
+void
+addpersrc(void)
+{
+	IMAGE_SECTION_HEADER *h;
+	uchar *p;
+	uint32 val;
+	Reloc *r;
+
+	if(rsrcsym == nil)
+		return;
+	
+	h = addpesection(".rsrc", rsrcsym->size, rsrcsym->size, 0);
+	h->Characteristics = IMAGE_SCN_MEM_READ|
+		IMAGE_SCN_MEM_WRITE | IMAGE_SCN_CNT_INITIALIZED_DATA;
+	// relocation
+	for(r=rsrcsym->r; r<rsrcsym->r+rsrcsym->nr; r++) {
+		p = rsrcsym->p + r->off;
+		val = h->VirtualAddress + r->add;
+		// 32-bit little-endian
+		p[0] = val;
+		p[1] = val>>8;
+		p[2] = val>>16;
+		p[3] = val>>24;
+	}
+	ewrite(cout, rsrcsym->p, rsrcsym->size);
+	strnput("", h->SizeOfRawData - rsrcsym->size);
+	cflush();
+
+	// update data directory
+	dd[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress = h->VirtualAddress;
+	dd[IMAGE_DIRECTORY_ENTRY_RESOURCE].Size = h->VirtualSize;
+}
+
+void
 asmbpe(void)
 {
 	IMAGE_SECTION_HEADER *t, *d;
@@ -492,7 +536,9 @@ asmbpe(void)
 	addexports(nextfileoff);
 	
 	addsymtable();
-		
+	
+	addpersrc();
+	
 	fh.NumberOfSections = nsect;
 	fh.TimeDateStamp = time(0);
 	fh.Characteristics = IMAGE_FILE_RELOCS_STRIPPED|
diff --git a/src/cmd/ld/pe.h b/src/cmd/ld/pe.h
index 2180fb8..7aa9388 100644
--- a/src/cmd/ld/pe.h
+++ b/src/cmd/ld/pe.h
@@ -175,3 +175,5 @@ typedef struct {
 	uint32 NumberOfRvaAndSizes;
 	IMAGE_DATA_DIRECTORY DataDirectory[16];
 } PE64_IMAGE_OPTIONAL_HEADER;
+
+void setpersrc(Sym *sym);
diff --git a/src/libmach/darwin.c b/src/libmach/darwin.c
index d44fd56..c443a4f 100644
--- a/src/libmach/darwin.c
+++ b/src/libmach/darwin.c
@@ -170,7 +170,7 @@ me(kern_return_t r)
 // handles to tasks (processes), and handles to threads within a
 // process.  All of them are small integers.
 //
-// To accomodate Mach, we employ a clumsy hack: in this interface,
+// To accommodate Mach, we employ a clumsy hack: in this interface,
 // if you pass in a positive number, that's a process id.
 // If you pass in a negative number, that identifies a thread that
 // has been previously returned by procthreadpids (it indexes
diff --git a/src/pkg/Makefile b/src/pkg/Makefile
index c84da57..fc5548e 100644
--- a/src/pkg/Makefile
+++ b/src/pkg/Makefile
@@ -74,7 +74,6 @@ DIRS=\
 	encoding/binary\
 	encoding/git85\
 	encoding/hex\
-	encoding/line\
 	encoding/pem\
 	exec\
 	exp/datafmt\
@@ -117,6 +116,7 @@ DIRS=\
 	io/ioutil\
 	json\
 	log\
+	mail\
 	math\
 	mime\
 	mime/multipart\
diff --git a/src/pkg/asn1/marshal.go b/src/pkg/asn1/marshal.go
index 771ac28..7212c91 100644
--- a/src/pkg/asn1/marshal.go
+++ b/src/pkg/asn1/marshal.go
@@ -458,11 +458,12 @@ func marshalField(out *forkableWriter, v reflect.Value, params fieldParameters)
 		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 rv.Class == 0 && rv.Tag == 0 && len(rv.Bytes) == 0 && params.optional {
-			return
-		}
 		err = marshalTagAndLength(out, tagAndLength{rv.Class, rv.Tag, len(rv.Bytes), rv.IsCompound})
 		if err != nil {
 			return
@@ -471,10 +472,6 @@ func marshalField(out *forkableWriter, v reflect.Value, params fieldParameters)
 		return
 	}
 
-	if params.optional && reflect.DeepEqual(v.Interface(), reflect.Zero(v.Type()).Interface()) {
-		return
-	}
-
 	tag, isCompound, ok := getUniversalType(v.Type())
 	if !ok {
 		err = StructuralError{fmt.Sprintf("unknown Go type: %v", v.Type())}
diff --git a/src/pkg/asn1/marshal_test.go b/src/pkg/asn1/marshal_test.go
index cd165d2..a951763 100644
--- a/src/pkg/asn1/marshal_test.go
+++ b/src/pkg/asn1/marshal_test.go
@@ -45,6 +45,10 @@ type printableStringTest struct {
 	A string "printable"
 }
 
+type optionalRawValueTest struct {
+	A RawValue "optional"
+}
+
 type testSET []int
 
 func setPST(t *time.Time) *time.Time {
@@ -102,6 +106,7 @@ var marshalTests = []marshalTest{
 			"7878787878787878787878787878787878787878787878787878787878787878",
 	},
 	{ia5StringTest{"test"}, "3006160474657374"},
+	{optionalRawValueTest{}, "3000"},
 	{printableStringTest{"test"}, "3006130474657374"},
 	{printableStringTest{"test*"}, "30071305746573742a"},
 	{rawContentsStruct{nil, 64}, "3003020140"},
diff --git a/src/pkg/big/arith.go b/src/pkg/big/arith.go
index df3808f..b9aeea9 100644
--- a/src/pkg/big/arith.go
+++ b/src/pkg/big/arith.go
@@ -188,7 +188,7 @@ func subVW_g(z, x []Word, y Word) (c Word) {
 }
 
 
-func shlVW_g(z, x []Word, s Word) (c Word) {
+func shlVU_g(z, x []Word, s uint) (c Word) {
 	if n := len(z); n > 0 {
 		ŝ := _W - s
 		w1 := x[n-1]
@@ -204,7 +204,7 @@ func shlVW_g(z, x []Word, s Word) (c Word) {
 }
 
 
-func shrVW_g(z, x []Word, s Word) (c Word) {
+func shrVU_g(z, x []Word, s uint) (c Word) {
 	if n := len(z); n > 0 {
 		ŝ := _W - s
 		w1 := x[0]
diff --git a/src/pkg/big/arith_386.s b/src/pkg/big/arith_386.s
index 2152163..07c07b0 100644
--- a/src/pkg/big/arith_386.s
+++ b/src/pkg/big/arith_386.s
@@ -118,8 +118,8 @@ E4:	CMPL BX, BP		// i < n
 	RET
 
 
-// func shlVW(z, x []Word, s Word) (c Word)
-TEXT ·shlVW(SB),7,$0
+// 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)
@@ -153,8 +153,8 @@ X8b:	MOVL $0, c+28(FP)
 	RET
 
 
-// func shrVW(z, x []Word, s Word) (c Word)
-TEXT ·shrVW(SB),7,$0
+// 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)
diff --git a/src/pkg/big/arith_amd64.s b/src/pkg/big/arith_amd64.s
index c740565..89b65f3 100644
--- a/src/pkg/big/arith_amd64.s
+++ b/src/pkg/big/arith_amd64.s
@@ -120,8 +120,8 @@ E4:	CMPQ BX, R11		// i < n
 	RET
 
 
-// func shlVW(z, x []Word, s Word) (c Word)
-TEXT ·shlVW(SB),7,$0
+// 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)
@@ -129,7 +129,7 @@ TEXT ·shlVW(SB),7,$0
 	// n > 0
 	MOVQ z+0(FP), R10
 	MOVQ x+16(FP), R8
-	MOVQ s+32(FP), CX
+	MOVL s+32(FP), CX
 	MOVQ (R8)(BX*8), AX	// w1 = x[n-1]
 	MOVQ $0, DX
 	SHLQ CX, DX:AX		// w1>>ŝ
@@ -155,8 +155,8 @@ X8b:	MOVQ $0, c+40(FP)
 	RET
 
 
-// func shrVW(z, x []Word, s Word) (c Word)
-TEXT ·shrVW(SB),7,$0
+// 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)
@@ -164,7 +164,7 @@ TEXT ·shrVW(SB),7,$0
 	// n > 0
 	MOVQ z+0(FP), R10
 	MOVQ x+16(FP), R8
-	MOVQ s+32(FP), CX
+	MOVL s+32(FP), CX
 	MOVQ (R8), AX		// w1 = x[0]
 	MOVQ $0, DX
 	SHRQ CX, DX:AX		// w1<<ŝ
diff --git a/src/pkg/big/arith_arm.s b/src/pkg/big/arith_arm.s
index e4a9a96..60abe6e 100644
--- a/src/pkg/big/arith_arm.s
+++ b/src/pkg/big/arith_arm.s
@@ -97,6 +97,7 @@ E3:
 	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
@@ -131,8 +132,8 @@ E4:
 	RET
 
 
-// func shlVW(z, x []Word, s Word) (c Word)
-TEXT ·shlVW(SB),7,$0
+// func shlVU(z, x []Word, s uint) (c Word)
+TEXT ·shlVU(SB),7,$0
 	MOVW	n+4(FP), R5
 	CMP	$0, R5
 	BEQ	X7
@@ -180,7 +181,8 @@ X7:
 	RET
 
 
-TEXT ·shrVW(SB),7,$0
+// func shrVU(z, x []Word, s uint) (c Word)
+TEXT ·shrVU(SB),7,$0
 	MOVW	n+4(FP), R5
 	CMP	$0, R5
 	BEQ	X6
@@ -229,6 +231,7 @@ X6:
 	RET
 
 
+// func mulAddVWW(z, x []Word, y, r Word) (c Word)
 TEXT ·mulAddVWW(SB),7,$0
 	MOVW	$0, R0
 	MOVW	z+0(FP), R1
@@ -256,6 +259,7 @@ E8:
 	RET
 
 
+// func addMulVVW(z, x []Word, y Word) (c Word)
 TEXT ·addMulVVW(SB),7,$0
 	MOVW	$0, R0
 	MOVW	z+0(FP), R1
@@ -286,11 +290,13 @@ E9:
 	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)
diff --git a/src/pkg/big/arith_decl.go b/src/pkg/big/arith_decl.go
index c456d5f..95fcd8b 100644
--- a/src/pkg/big/arith_decl.go
+++ b/src/pkg/big/arith_decl.go
@@ -11,8 +11,8 @@ 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 shlVW(z, x []Word, s Word) (c Word)
-func shrVW(z, x []Word, s 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
index 934b302..f3e2d47 100644
--- a/src/pkg/big/arith_test.go
+++ b/src/pkg/big/arith_test.go
@@ -185,6 +185,13 @@ func testFunVW(t *testing.T, msg string, f funVW, a argVW) {
 }
 
 
+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
@@ -196,16 +203,20 @@ func TestFunVW(t *testing.T) {
 		testFunVW(t, "subVW", subVW, arg)
 	}
 
+	shlVW_g := makeFunVW(shlVU_g)
+	shlVW := makeFunVW(shlVU)
 	for _, a := range lshVW {
 		arg := a
-		testFunVW(t, "shlVW_g", shlVW_g, arg)
-		testFunVW(t, "shlVW", shlVW, arg)
+		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, "shrVW_g", shrVW_g, arg)
-		testFunVW(t, "shrVW", shrVW, arg)
+		testFunVW(t, "shrVU_g", shrVW_g, arg)
+		testFunVW(t, "shrVU", shrVW, arg)
 	}
 }
 
diff --git a/src/pkg/big/int.go b/src/pkg/big/int.go
index 74fbef4..e66c34a 100755
--- a/src/pkg/big/int.go
+++ b/src/pkg/big/int.go
@@ -8,8 +8,10 @@ package big
 
 import (
 	"fmt"
+	"io"
 	"os"
 	"rand"
+	"strings"
 )
 
 // An Int represents a signed multi-precision integer.
@@ -325,7 +327,7 @@ func charset(ch int) string {
 		return lowercaseDigits[0:2]
 	case 'o':
 		return lowercaseDigits[0:8]
-	case 'd', 'v':
+	case 'd', 's', 'v':
 		return lowercaseDigits[0:10]
 	case 'x':
 		return lowercaseDigits[0:16]
@@ -374,8 +376,69 @@ func (x *Int) Format(s fmt.State, ch int) {
 }
 
 
-// Int64 returns the int64 representation of z.
-// If z cannot be represented in an int64, the result is undefined.
+// 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 {
+	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.ErrorString("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
@@ -395,32 +458,19 @@ func (x *Int) Int64() int64 {
 // and returns z and a boolean indicating success. If SetString fails,
 // the value of z is undefined.
 //
-// If the base argument 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.
+// 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) {
-	if len(s) == 0 || base < 0 || base == 1 || 16 < base {
+	r := strings.NewReader(s)
+	_, _, err := z.scan(r, base)
+	if err != nil {
 		return z, false
 	}
-
-	neg := s[0] == '-'
-	if neg || s[0] == '+' {
-		s = s[1:]
-		if len(s) == 0 {
-			return z, false
-		}
-	}
-
-	var scanned int
-	z.abs, _, scanned = z.abs.scan(s, base)
-	if scanned != len(s) {
-		return z, false
-	}
-	z.neg = len(z.abs) > 0 && neg // 0 has no sign
-
-	return z, true
+	_, _, err = r.ReadRune()
+	return z, err == os.EOF // err == os.EOF => scan consumed all of s
 }
 
 
@@ -784,11 +834,11 @@ func (z *Int) GobEncode() ([]byte, os.Error) {
 // 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")
+		return os.ErrorString("Int.GobDecode: no data")
 	}
 	b := buf[0]
 	if b>>1 != version {
-		return os.NewError(fmt.Sprintf("Int.GobDecode: encoding version %d not supported", b>>1))
+		return os.ErrorString(fmt.Sprintf("Int.GobDecode: encoding version %d not supported", b>>1))
 	}
 	z.neg = b&1 != 0
 	z.abs = z.abs.setBytes(buf[1:])
diff --git a/src/pkg/big/int_test.go b/src/pkg/big/int_test.go
index 595f049..1a49292 100755
--- a/src/pkg/big/int_test.go
+++ b/src/pkg/big/int_test.go
@@ -397,6 +397,49 @@ func TestFormat(t *testing.T) {
 }
 
 
+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
diff --git a/src/pkg/big/nat.go b/src/pkg/big/nat.go
index c2b95e8..fa09d65 100755
--- a/src/pkg/big/nat.go
+++ b/src/pkg/big/nat.go
@@ -18,7 +18,11 @@ package big
 // These are the building blocks for the operations on signed integers
 // and rationals.
 
-import "rand"
+import (
+	"io"
+	"os"
+	"rand"
+)
 
 
 // An unsigned integer x of the form
@@ -546,9 +550,14 @@ func (z nat) divLarge(u, uIn, v nat) (q, r nat) {
 	u.clear()
 
 	// D1.
-	shift := Word(leadingZeros(v[n-1]))
-	shlVW(v, v, shift)
-	u[len(uIn)] = shlVW(u[0:len(uIn)], uIn, shift)
+	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-- {
@@ -587,8 +596,7 @@ func (z nat) divLarge(u, uIn, v nat) (q, r nat) {
 	}
 
 	q = q.norm()
-	shrVW(u, u, shift)
-	shrVW(v, v, shift)
+	shrVU(u, u, shift)
 	r = u.norm()
 
 	return q, r
@@ -604,68 +612,118 @@ func (x nat) bitLen() int {
 }
 
 
-func hexValue(ch byte) int {
-	var d byte
+// 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 <= 'f':
+	case 'a' <= ch && ch <= 'z':
 		d = ch - 'a' + 10
-	case 'A' <= ch && ch <= 'F':
+	case 'A' <= ch && ch <= 'Z':
 		d = ch - 'A' + 10
-	default:
-		return -1
 	}
-	return int(d)
+	return Word(d)
 }
 
 
-// scan returns the natural number corresponding to the
-// longest possible prefix of s representing a natural number in a
-// given conversion base, the actual conversion base used, and the
-// prefix length. The syntax of natural numbers follows the syntax
-// of unsigned integer literals in Go.
+// 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.
 //
-// If the base argument 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.
+// 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(s string, base int) (nat, int, int) {
+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.ErrorString("illegal number base")
+	}
+
+	// one char look-ahead
+	ch, _, err := r.ReadRune()
+	if err != nil {
+		return z, 0, err
+	}
+
 	// determine base if necessary
-	i, n := 0, len(s)
+	b := Word(base)
 	if base == 0 {
-		base = 10
-		if n > 0 && s[0] == '0' {
-			base, i = 8, 1
-			if n > 1 {
-				switch s[1] {
+		b = 10
+		if ch == '0' {
+			switch ch, _, err = r.ReadRune(); err {
+			case nil:
+				b = 8
+				switch ch {
 				case 'x', 'X':
-					base, i = 16, 2
+					b = 16
 				case 'b', 'B':
-					base, i = 2, 2
+					b = 2
+				}
+				if b == 2 || b == 16 {
+					if ch, _, err = r.ReadRune(); err != nil {
+						return z, 0, err
+					}
 				}
+			case os.EOF:
+				return z, 10, nil
+			default:
+				return z, 10, err
 			}
 		}
 	}
 
-	// reject illegal bases or strings consisting only of prefix
-	if base < 2 || 16 < base || (base != 8 && i >= n) {
-		return z, 0, 0
-	}
-
 	// 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)
-	for ; i < n; i++ {
-		d := hexValue(s[i])
-		if 0 <= d && d < base {
-			z = z.mulAddWW(z, Word(base), Word(d))
+	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
 		}
 	}
 
-	return z.norm(), base, i
+	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.ErrorString("syntax error scanning number")
+	}
+
+	return z.norm(), int(b), nil
 }
 
 
@@ -766,7 +824,7 @@ func (z nat) shl(x nat, s uint) nat {
 
 	n := m + int(s/_W)
 	z = z.make(n + 1)
-	z[n] = shlVW(z[n-m:n], x, Word(s%_W))
+	z[n] = shlVU(z[n-m:n], x, s%_W)
 	z[0 : n-m].clear()
 
 	return z.norm()
@@ -783,7 +841,7 @@ func (z nat) shr(x nat, s uint) nat {
 	// n > 0
 
 	z = z.make(n)
-	shrVW(z, x[m-n:], Word(s%_W))
+	shrVU(z, x[m-n:], s%_W)
 
 	return z.norm()
 }
@@ -914,25 +972,26 @@ func (x nat) modW(d Word) (r Word) {
 }
 
 
-// powersOfTwoDecompose finds q and k such that q * 1<<k = n and q is odd.
-func (n nat) powersOfTwoDecompose() (q nat, k Word) {
-	if len(n) == 0 {
-		return n, 0
+// 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
 	}
 
-	zeroWords := 0
-	for n[zeroWords] == 0 {
-		zeroWords++
+	// 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++
 	}
-	// One of the words must be non-zero by invariant, therefore
-	// zeroWords < len(n).
-	x := trailingZeroBits(n[zeroWords])
+	n := trailingZeroBits(x[i]) // x[i] != 0
 
-	q = q.make(len(n) - zeroWords)
-	shrVW(q, n[zeroWords:], Word(x))
-	q = q.norm()
+	q = make(nat, len(x)-i)
+	shrVU(q, x[i:], uint(n))
 
-	k = Word(_W*zeroWords + x)
+	q = q.norm()
+	k = i*_W + n
 	return
 }
 
@@ -1103,7 +1162,7 @@ NextRandom:
 		if y.cmp(natOne) == 0 || y.cmp(nm1) == 0 {
 			continue
 		}
-		for j := Word(1); j < k; j++ {
+		for j := 1; j < k; j++ {
 			y = y.mul(y, y)
 			quotient, y = quotient.div(y, y, n)
 			if y.cmp(nm1) == 0 {
diff --git a/src/pkg/big/nat_test.go b/src/pkg/big/nat_test.go
index a29843a..50ea469 100755
--- a/src/pkg/big/nat_test.go
+++ b/src/pkg/big/nat_test.go
@@ -4,7 +4,11 @@
 
 package big
 
-import "testing"
+import (
+	"os"
+	"strings"
+	"testing"
+)
 
 var cmpTests = []struct {
 	x, y nat
@@ -180,6 +184,8 @@ var strTests = []struct {
 	{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"},
 }
 
 
@@ -190,20 +196,170 @@ func TestString(t *testing.T) {
 			t.Errorf("string%+v\n\tgot s = %s; want %s", a, s, a.s)
 		}
 
-		x, b, n := nat(nil).scan(a.s, len(a.c))
+		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 n != len(a.s) {
-			t.Errorf("scan%+v\n\tgot n = %d; want %d", a, n, len(a.s))
+		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)
+	}
+}
+
+
 func TestLeadingZeros(t *testing.T) {
 	var x Word = _B >> 1
 	for i := 0; i <= _W; i++ {
@@ -344,14 +500,14 @@ var expNNTests = []struct {
 
 func TestExpNN(t *testing.T) {
 	for i, test := range expNNTests {
-		x, _, _ := nat(nil).scan(test.x, 0)
-		y, _, _ := nat(nil).scan(test.y, 0)
-		out, _, _ := nat(nil).scan(test.out, 0)
+		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(test.m, 0)
+			m, _, _ = nat(nil).scan(strings.NewReader(test.m), 0)
 		}
 
 		z := nat(nil).expNN(x, y, m)
diff --git a/src/pkg/big/rat.go b/src/pkg/big/rat.go
index 2adf316..f11c274 100644
--- a/src/pkg/big/rat.go
+++ b/src/pkg/big/rat.go
@@ -6,7 +6,11 @@
 
 package big
 
-import "strings"
+import (
+	"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.
@@ -209,6 +213,28 @@ func (z *Rat) Set(x *Rat) *Rat {
 }
 
 
+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.ErrorString("Rat.Scan: invalid verb")
+	}
+	if _, ok := z.SetString(string(tok)); !ok {
+		return os.ErrorString("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
@@ -225,8 +251,8 @@ func (z *Rat) SetString(s string) (*Rat, bool) {
 			return z, false
 		}
 		s = s[sep+1:]
-		var n int
-		if z.b, _, n = z.b.scan(s, 10); n != len(s) {
+		var err os.Error
+		if z.b, _, err = z.b.scan(strings.NewReader(s), 10); err != nil {
 			return z, false
 		}
 		return z.norm(), true
diff --git a/src/pkg/big/rat_test.go b/src/pkg/big/rat_test.go
index 8f42949..ae5c7c9 100644
--- a/src/pkg/big/rat_test.go
+++ b/src/pkg/big/rat_test.go
@@ -4,7 +4,11 @@
 
 package big
 
-import "testing"
+import (
+	"bytes"
+	"fmt"
+	"testing"
+)
 
 
 var setStringTests = []struct {
@@ -53,6 +57,29 @@ func TestRatSetString(t *testing.T) {
 }
 
 
+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
diff --git a/src/pkg/compress/flate/deflate.go b/src/pkg/compress/flate/deflate.go
index a02a5e8..b1cee0b 100644
--- a/src/pkg/compress/flate/deflate.go
+++ b/src/pkg/compress/flate/deflate.go
@@ -11,16 +11,18 @@ import (
 )
 
 const (
-	NoCompression        = 0
-	BestSpeed            = 1
-	fastCompression      = 3
-	BestCompression      = 9
-	DefaultCompression   = -1
-	logMaxOffsetSize     = 15  // Standard DEFLATE
-	wideLogMaxOffsetSize = 22  // Wide DEFLATE
-	minMatchLength       = 3   // The smallest match that the compressor looks for
-	maxMatchLength       = 258 // The longest match for the compressor
-	minOffsetSize        = 1   // The shortest offset that makes any sence
+	NoCompression      = 0
+	BestSpeed          = 1
+	fastCompression    = 3
+	BestCompression    = 9
+	DefaultCompression = -1
+	logWindowSize      = 15
+	windowSize         = 1 << logWindowSize
+	windowMask         = windowSize - 1
+	logMaxOffsetSize   = 15  // Standard DEFLATE
+	minMatchLength     = 3   // The smallest match that the compressor looks for
+	maxMatchLength     = 258 // The longest match for the compressor
+	minOffsetSize      = 1   // The shortest offset that makes any sence
 
 	// The maximum number of tokens we put into a single flat block, just too
 	// stop things from getting too large.
@@ -32,22 +34,6 @@ const (
 	hashShift           = (hashBits + minMatchLength - 1) / minMatchLength
 )
 
-type syncPipeReader struct {
-	*io.PipeReader
-	closeChan chan bool
-}
-
-func (sr *syncPipeReader) CloseWithError(err os.Error) os.Error {
-	retErr := sr.PipeReader.CloseWithError(err)
-	sr.closeChan <- true // finish writer close
-	return retErr
-}
-
-type syncPipeWriter struct {
-	*io.PipeWriter
-	closeChan chan bool
-}
-
 type compressionLevel struct {
 	good, lazy, nice, chain, fastSkipHashing int
 }
@@ -68,105 +54,73 @@ var levels = []compressionLevel{
 	{32, 258, 258, 4096, math.MaxInt32},
 }
 
-func (sw *syncPipeWriter) Close() os.Error {
-	err := sw.PipeWriter.Close()
-	<-sw.closeChan // wait for reader close
-	return err
-}
-
-func syncPipe() (*syncPipeReader, *syncPipeWriter) {
-	r, w := io.Pipe()
-	sr := &syncPipeReader{r, make(chan bool, 1)}
-	sw := &syncPipeWriter{w, sr.closeChan}
-	return sr, sw
-}
-
 type compressor struct {
-	level         int
-	logWindowSize uint
-	w             *huffmanBitWriter
-	r             io.Reader
-	// (1 << logWindowSize) - 1.
-	windowMask int
+	compressionLevel
 
-	eof      bool // has eof been reached on input?
-	sync     bool // writer wants to flush
-	syncChan chan os.Error
+	w *huffmanBitWriter
 
-	// hashHead[hashValue] contains the largest inputIndex with the specified hash value
-	hashHead []int
+	// compression algorithm
+	fill func(*compressor, []byte) int // copy data to window
+	step func(*compressor)             // process window
+	sync bool                          // requesting flush
 
+	// Input hash chains
+	// hashHead[hashValue] contains the largest inputIndex with the specified hash value
 	// If hashHead[hashValue] is within the current window, then
 	// hashPrev[hashHead[hashValue] & windowMask] contains the previous index
 	// with the same hash value.
-	hashPrev []int
-
-	// If we find a match of length >= niceMatch, then we don't bother searching
-	// any further.
-	niceMatch int
-
-	// If we find a match of length >= goodMatch, we only do a half-hearted
-	// effort at doing lazy matching starting at the next character
-	goodMatch int
-
-	// The maximum number of chains we look at when finding a match
-	maxChainLength int
-
-	// The sliding window we use for matching
-	window []byte
-
-	// The index just past the last valid character
-	windowEnd int
-
-	// index in "window" at which current block starts
-	blockStart int
-}
-
-func (d *compressor) flush() os.Error {
-	d.w.flush()
-	return d.w.err
+	chainHead int
+	hashHead  []int
+	hashPrev  []int
+
+	// input window: unprocessed data is window[index:windowEnd]
+	index         int
+	window        []byte
+	windowEnd     int
+	blockStart    int  // window index where current tokens start
+	byteAvailable bool // if true, still need to process window[index-1].
+
+	// queued output tokens: tokens[:ti]
+	tokens []token
+	ti     int
+
+	// deflate state
+	length         int
+	offset         int
+	hash           int
+	maxInsertIndex int
+	err            os.Error
 }
 
-func (d *compressor) fillWindow(index int) (int, os.Error) {
-	if d.sync {
-		return index, nil
-	}
-	wSize := d.windowMask + 1
-	if index >= wSize+wSize-(minMatchLength+maxMatchLength) {
-		// shift the window by wSize
-		copy(d.window, d.window[wSize:2*wSize])
-		index -= wSize
-		d.windowEnd -= wSize
-		if d.blockStart >= wSize {
-			d.blockStart -= wSize
+func (d *compressor) fillDeflate(b []byte) int {
+	if d.index >= 2*windowSize-(minMatchLength+maxMatchLength) {
+		// shift the window by windowSize
+		copy(d.window, d.window[windowSize:2*windowSize])
+		d.index -= windowSize
+		d.windowEnd -= windowSize
+		if d.blockStart >= windowSize {
+			d.blockStart -= windowSize
 		} else {
 			d.blockStart = math.MaxInt32
 		}
 		for i, h := range d.hashHead {
-			v := h - wSize
+			v := h - windowSize
 			if v < -1 {
 				v = -1
 			}
 			d.hashHead[i] = v
 		}
 		for i, h := range d.hashPrev {
-			v := -h - wSize
+			v := -h - windowSize
 			if v < -1 {
 				v = -1
 			}
 			d.hashPrev[i] = v
 		}
 	}
-	count, err := d.r.Read(d.window[d.windowEnd:])
-	d.windowEnd += count
-	if count == 0 && err == nil {
-		d.sync = true
-	}
-	if err == os.EOF {
-		d.eof = true
-		err = nil
-	}
-	return index, err
+	n := copy(d.window[d.windowEnd:], b)
+	d.windowEnd += n
+	return n
 }
 
 func (d *compressor) writeBlock(tokens []token, index int, eof bool) os.Error {
@@ -194,21 +148,21 @@ func (d *compressor) findMatch(pos int, prevHead int, prevLength int, lookahead
 
 	// We quit when we get a match that's at least nice long
 	nice := len(win) - pos
-	if d.niceMatch < nice {
-		nice = d.niceMatch
+	if d.nice < nice {
+		nice = d.nice
 	}
 
 	// If we've got a match that's good enough, only look in 1/4 the chain.
-	tries := d.maxChainLength
+	tries := d.chain
 	length = prevLength
-	if length >= d.goodMatch {
+	if length >= d.good {
 		tries >>= 2
 	}
 
 	w0 := win[pos]
 	w1 := win[pos+1]
 	wEnd := win[pos+length]
-	minIndex := pos - (d.windowMask + 1)
+	minIndex := pos - windowSize
 
 	for i := prevHead; tries > 0; tries-- {
 		if w0 == win[i] && w1 == win[i+1] && wEnd == win[i+length] {
@@ -233,7 +187,7 @@ 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&d.windowMask]; i < minIndex || i < 0 {
+		if i = d.hashPrev[i&windowMask]; i < minIndex || i < 0 {
 			break
 		}
 	}
@@ -248,234 +202,224 @@ func (d *compressor) writeStoredBlock(buf []byte) os.Error {
 	return d.w.err
 }
 
-func (d *compressor) storedDeflate() os.Error {
-	buf := make([]byte, maxStoreBlockSize)
-	for {
-		n, err := d.r.Read(buf)
-		if n == 0 && err == nil {
-			d.sync = true
-		}
-		if n > 0 || d.sync {
-			if err := d.writeStoredBlock(buf[0:n]); err != nil {
-				return err
-			}
-			if d.sync {
-				d.syncChan <- nil
-				d.sync = false
-			}
-		}
-		if err != nil {
-			if err == os.EOF {
-				break
-			}
-			return err
-		}
-	}
-	return nil
-}
-
-func (d *compressor) doDeflate() (err os.Error) {
-	// init
-	d.windowMask = 1<<d.logWindowSize - 1
+func (d *compressor) initDeflate() {
 	d.hashHead = make([]int, hashSize)
-	d.hashPrev = make([]int, 1<<d.logWindowSize)
-	d.window = make([]byte, 2<<d.logWindowSize)
+	d.hashPrev = make([]int, windowSize)
+	d.window = make([]byte, 2*windowSize)
 	fillInts(d.hashHead, -1)
-	tokens := make([]token, maxFlateBlockTokens, maxFlateBlockTokens+1)
-	l := levels[d.level]
-	d.goodMatch = l.good
-	d.niceMatch = l.nice
-	d.maxChainLength = l.chain
-	lazyMatch := l.lazy
-	length := minMatchLength - 1
-	offset := 0
-	byteAvailable := false
-	isFastDeflate := l.fastSkipHashing != 0
-	index := 0
-	// run
-	if index, err = d.fillWindow(index); err != nil {
+	d.tokens = make([]token, maxFlateBlockTokens, maxFlateBlockTokens+1)
+	d.length = minMatchLength - 1
+	d.offset = 0
+	d.byteAvailable = false
+	d.index = 0
+	d.ti = 0
+	d.hash = 0
+	d.chainHead = -1
+}
+
+func (d *compressor) deflate() {
+	if d.windowEnd-d.index < minMatchLength+maxMatchLength && !d.sync {
 		return
 	}
-	maxOffset := d.windowMask + 1 // (1 << logWindowSize);
-	// only need to change when you refill the window
-	windowEnd := d.windowEnd
-	maxInsertIndex := windowEnd - (minMatchLength - 1)
-	ti := 0
-
-	hash := int(0)
-	if index < maxInsertIndex {
-		hash = int(d.window[index])<<hashShift + int(d.window[index+1])
+
+	d.maxInsertIndex = d.windowEnd - (minMatchLength - 1)
+	if d.index < d.maxInsertIndex {
+		d.hash = int(d.window[d.index])<<hashShift + int(d.window[d.index+1])
 	}
-	chainHead := -1
+
 Loop:
 	for {
-		if index > windowEnd {
+		if d.index > d.windowEnd {
 			panic("index > windowEnd")
 		}
-		lookahead := windowEnd - index
+		lookahead := d.windowEnd - d.index
 		if lookahead < minMatchLength+maxMatchLength {
-			if index, err = d.fillWindow(index); err != nil {
-				return
+			if !d.sync {
+				break Loop
 			}
-			windowEnd = d.windowEnd
-			if index > windowEnd {
+			if d.index > d.windowEnd {
 				panic("index > windowEnd")
 			}
-			maxInsertIndex = windowEnd - (minMatchLength - 1)
-			lookahead = windowEnd - index
 			if lookahead == 0 {
 				// Flush current output block if any.
-				if byteAvailable {
+				if d.byteAvailable {
 					// There is still one pending token that needs to be flushed
-					tokens[ti] = literalToken(uint32(d.window[index-1]) & 0xFF)
-					ti++
-					byteAvailable = false
+					d.tokens[d.ti] = literalToken(uint32(d.window[d.index-1]))
+					d.ti++
+					d.byteAvailable = false
 				}
-				if ti > 0 {
-					if err = d.writeBlock(tokens[0:ti], index, false); err != nil {
+				if d.ti > 0 {
+					if d.err = d.writeBlock(d.tokens[0:d.ti], d.index, false); d.err != nil {
 						return
 					}
-					ti = 0
-				}
-				if d.sync {
-					d.w.writeStoredHeader(0, false)
-					d.w.flush()
-					d.syncChan <- d.w.err
-					d.sync = false
-				}
-
-				// If this was only a sync (not at EOF) keep going.
-				if !d.eof {
-					continue
+					d.ti = 0
 				}
 				break Loop
 			}
 		}
-		if index < maxInsertIndex {
+		if d.index < d.maxInsertIndex {
 			// Update the hash
-			hash = (hash<<hashShift + int(d.window[index+2])) & hashMask
-			chainHead = d.hashHead[hash]
-			d.hashPrev[index&d.windowMask] = chainHead
-			d.hashHead[hash] = index
+			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
 		}
-		prevLength := length
-		prevOffset := offset
-		length = minMatchLength - 1
-		offset = 0
-		minIndex := index - maxOffset
+		prevLength := d.length
+		prevOffset := d.offset
+		d.length = minMatchLength - 1
+		d.offset = 0
+		minIndex := d.index - windowSize
 		if minIndex < 0 {
 			minIndex = 0
 		}
 
-		if chainHead >= minIndex &&
-			(isFastDeflate && lookahead > minMatchLength-1 ||
-				!isFastDeflate && lookahead > prevLength && prevLength < lazyMatch) {
-			if newLength, newOffset, ok := d.findMatch(index, chainHead, minMatchLength-1, lookahead); ok {
-				length = newLength
-				offset = newOffset
+		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 {
+				d.length = newLength
+				d.offset = newOffset
 			}
 		}
-		if isFastDeflate && length >= minMatchLength ||
-			!isFastDeflate && prevLength >= minMatchLength && length <= prevLength {
+		if d.fastSkipHashing != 0 && d.length >= minMatchLength ||
+			d.fastSkipHashing == 0 && 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 isFastDeflate {
-				tokens[ti] = matchToken(uint32(length-minMatchLength), uint32(offset-minOffsetSize))
+			if d.fastSkipHashing != 0 {
+				d.tokens[d.ti] = matchToken(uint32(d.length-minMatchLength), uint32(d.offset-minOffsetSize))
 			} else {
-				tokens[ti] = matchToken(uint32(prevLength-minMatchLength), uint32(prevOffset-minOffsetSize))
+				d.tokens[d.ti] = matchToken(uint32(prevLength-minMatchLength), uint32(prevOffset-minOffsetSize))
 			}
-			ti++
+			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 length <= l.fastSkipHashing {
+			if d.length <= d.fastSkipHashing {
 				var newIndex int
-				if isFastDeflate {
-					newIndex = index + length
+				if d.fastSkipHashing != 0 {
+					newIndex = d.index + d.length
 				} else {
 					newIndex = prevLength - 1
 				}
-				for index++; index < newIndex; index++ {
-					if index < maxInsertIndex {
-						hash = (hash<<hashShift + int(d.window[index+2])) & hashMask
+				for d.index++; d.index < newIndex; d.index++ {
+					if d.index < d.maxInsertIndex {
+						d.hash = (d.hash<<hashShift + int(d.window[d.index+2])) & hashMask
 						// Get previous value with the same hash.
 						// Our chain should point to the previous value.
-						d.hashPrev[index&d.windowMask] = d.hashHead[hash]
+						d.hashPrev[d.index&windowMask] = d.hashHead[d.hash]
 						// Set the head of the hash chain to us.
-						d.hashHead[hash] = index
+						d.hashHead[d.hash] = d.index
 					}
 				}
-				if !isFastDeflate {
-					byteAvailable = false
-					length = minMatchLength - 1
+				if d.fastSkipHashing == 0 {
+					d.byteAvailable = false
+					d.length = minMatchLength - 1
 				}
 			} else {
 				// For matches this long, we don't bother inserting each individual
 				// item into the table.
-				index += length
-				hash = (int(d.window[index])<<hashShift + int(d.window[index+1]))
+				d.index += d.length
+				d.hash = (int(d.window[d.index])<<hashShift + int(d.window[d.index+1]))
 			}
-			if ti == maxFlateBlockTokens {
+			if d.ti == maxFlateBlockTokens {
 				// The block includes the current character
-				if err = d.writeBlock(tokens, index, false); err != nil {
+				if d.err = d.writeBlock(d.tokens, d.index, false); d.err != nil {
 					return
 				}
-				ti = 0
+				d.ti = 0
 			}
 		} else {
-			if isFastDeflate || byteAvailable {
-				i := index - 1
-				if isFastDeflate {
-					i = index
+			if d.fastSkipHashing != 0 || d.byteAvailable {
+				i := d.index - 1
+				if d.fastSkipHashing != 0 {
+					i = d.index
 				}
-				tokens[ti] = literalToken(uint32(d.window[i]) & 0xFF)
-				ti++
-				if ti == maxFlateBlockTokens {
-					if err = d.writeBlock(tokens, i+1, false); err != nil {
+				d.tokens[d.ti] = literalToken(uint32(d.window[i]))
+				d.ti++
+				if d.ti == maxFlateBlockTokens {
+					if d.err = d.writeBlock(d.tokens, i+1, false); d.err != nil {
 						return
 					}
-					ti = 0
+					d.ti = 0
 				}
 			}
-			index++
-			if !isFastDeflate {
-				byteAvailable = true
+			d.index++
+			if d.fastSkipHashing == 0 {
+				d.byteAvailable = true
 			}
 		}
 	}
-	return
 }
 
-func (d *compressor) compress(r io.Reader, w io.Writer, level int, logWindowSize uint) (err os.Error) {
-	d.r = r
+func (d *compressor) fillStore(b []byte) int {
+	n := copy(d.window[d.windowEnd:], b)
+	d.windowEnd += n
+	return n
+}
+
+func (d *compressor) store() {
+	if d.windowEnd > 0 {
+		d.err = d.writeStoredBlock(d.window[:d.windowEnd])
+	}
+	d.windowEnd = 0
+}
+
+func (d *compressor) write(b []byte) (n int, err os.Error) {
+	n = len(b)
+	b = b[d.fill(d, b):]
+	for len(b) > 0 {
+		d.step(d)
+		b = b[d.fill(d, b):]
+	}
+	return n, d.err
+}
+
+func (d *compressor) syncFlush() os.Error {
+	d.sync = true
+	d.step(d)
+	if d.err == nil {
+		d.w.writeStoredHeader(0, false)
+		d.w.flush()
+		d.err = d.w.err
+	}
+	d.sync = false
+	return d.err
+}
+
+func (d *compressor) init(w io.Writer, level int) (err os.Error) {
 	d.w = newHuffmanBitWriter(w)
-	d.level = level
-	d.logWindowSize = logWindowSize
 
 	switch {
 	case level == NoCompression:
-		err = d.storedDeflate()
+		d.window = make([]byte, maxStoreBlockSize)
+		d.fill = (*compressor).fillStore
+		d.step = (*compressor).store
 	case level == DefaultCompression:
-		d.level = 6
+		level = 6
 		fallthrough
 	case 1 <= level && level <= 9:
-		err = d.doDeflate()
+		d.compressionLevel = levels[level]
+		d.initDeflate()
+		d.fill = (*compressor).fillDeflate
+		d.step = (*compressor).deflate
 	default:
 		return WrongValueError{"level", 0, 9, int32(level)}
 	}
+	return nil
+}
 
-	if d.sync {
-		d.syncChan <- err
-		d.sync = false
-	}
-	if err != nil {
-		return err
+func (d *compressor) close() os.Error {
+	d.sync = true
+	d.step(d)
+	if d.err != nil {
+		return d.err
 	}
 	if d.w.writeStoredHeader(0, true); d.w.err != nil {
 		return d.w.err
 	}
-	return d.flush()
+	d.w.flush()
+	return d.w.err
 }
 
 // NewWriter returns a new Writer compressing
@@ -486,14 +430,9 @@ func (d *compressor) compress(r io.Reader, w io.Writer, level int, logWindowSize
 // compression; it only adds the necessary DEFLATE framing.
 func NewWriter(w io.Writer, level int) *Writer {
 	const logWindowSize = logMaxOffsetSize
-	var d compressor
-	d.syncChan = make(chan os.Error, 1)
-	pr, pw := syncPipe()
-	go func() {
-		err := d.compress(pr, w, level, logWindowSize)
-		pr.CloseWithError(err)
-	}()
-	return &Writer{pw, &d}
+	var dw Writer
+	dw.d.init(w, level)
+	return &dw
 }
 
 // NewWriterDict is like NewWriter but initializes the new
@@ -526,18 +465,13 @@ func (w *dictWriter) Write(b []byte) (n int, err os.Error) {
 // A Writer takes data written to it and writes the compressed
 // form of that data to an underlying writer (see NewWriter).
 type Writer struct {
-	w *syncPipeWriter
-	d *compressor
+	d compressor
 }
 
 // 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) {
-	if len(data) == 0 {
-		// no point, and nil interferes with sync
-		return
-	}
-	return w.w.Write(data)
+	return w.d.write(data)
 }
 
 // Flush flushes any pending compressed data to the underlying writer.
@@ -550,18 +484,10 @@ func (w *Writer) Write(data []byte) (n int, err os.Error) {
 func (w *Writer) Flush() os.Error {
 	// For more about flushing:
 	// http://www.bolet.org/~pornin/deflate-flush.html
-	if w.d.sync {
-		panic("compress/flate: double Flush")
-	}
-	_, err := w.w.Write(nil)
-	err1 := <-w.d.syncChan
-	if err == nil {
-		err = err1
-	}
-	return err
+	return w.d.syncFlush()
 }
 
 // Close flushes and closes the writer.
 func (w *Writer) Close() os.Error {
-	return w.w.Close()
+	return w.d.close()
 }
diff --git a/src/pkg/compress/flate/deflate_test.go b/src/pkg/compress/flate/deflate_test.go
index 650a805..2ac811c 100644
--- a/src/pkg/compress/flate/deflate_test.go
+++ b/src/pkg/compress/flate/deflate_test.go
@@ -57,7 +57,7 @@ var deflateInflateTests = []*deflateInflateTest{
 	&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{getLargeDataChunk()},
+	&deflateInflateTest{largeDataChunk()},
 }
 
 var reverseBitsTests = []*reverseBitsTest{
@@ -71,23 +71,22 @@ var reverseBitsTests = []*reverseBitsTest{
 	&reverseBitsTest{29, 5, 23},
 }
 
-func getLargeDataChunk() []byte {
+func largeDataChunk() []byte {
 	result := make([]byte, 100000)
 	for i := range result {
-		result[i] = byte(int64(i) * int64(i) & 0xFF)
+		result[i] = byte(i * i & 0xFF)
 	}
 	return result
 }
 
 func TestDeflate(t *testing.T) {
 	for _, h := range deflateTests {
-		buffer := bytes.NewBuffer(nil)
-		w := NewWriter(buffer, h.level)
+		var buf bytes.Buffer
+		w := NewWriter(&buf, h.level)
 		w.Write(h.in)
 		w.Close()
-		if bytes.Compare(buffer.Bytes(), h.out) != 0 {
-			t.Errorf("buffer is wrong; level = %v, buffer.Bytes() = %v, expected output = %v",
-				h.level, buffer.Bytes(), h.out)
+		if !bytes.Equal(buf.Bytes(), h.out) {
+			t.Errorf("Deflate(%d, %x) = %x, want %x", h.level, h.in, buf.Bytes(), h.out)
 		}
 	}
 }
diff --git a/src/pkg/compress/flate/huffman_bit_writer.go b/src/pkg/compress/flate/huffman_bit_writer.go
index 5df4510..3981df5 100644
--- a/src/pkg/compress/flate/huffman_bit_writer.go
+++ b/src/pkg/compress/flate/huffman_bit_writer.go
@@ -15,9 +15,6 @@ const (
 	// The largest offset code.
 	offsetCodeCount = 30
 
-	// The largest offset code in the extensions.
-	extendedOffsetCodeCount = 42
-
 	// The special code used to mark the end of a block.
 	endBlockMarker = 256
 
@@ -100,11 +97,11 @@ func newHuffmanBitWriter(w io.Writer) *huffmanBitWriter {
 	return &huffmanBitWriter{
 		w:               w,
 		literalFreq:     make([]int32, maxLit),
-		offsetFreq:      make([]int32, extendedOffsetCodeCount),
-		codegen:         make([]uint8, maxLit+extendedOffsetCodeCount+1),
+		offsetFreq:      make([]int32, offsetCodeCount),
+		codegen:         make([]uint8, maxLit+offsetCodeCount+1),
 		codegenFreq:     make([]int32, codegenCodeCount),
 		literalEncoding: newHuffmanEncoder(maxLit),
-		offsetEncoding:  newHuffmanEncoder(extendedOffsetCodeCount),
+		offsetEncoding:  newHuffmanEncoder(offsetCodeCount),
 		codegenEncoding: newHuffmanEncoder(codegenCodeCount),
 	}
 }
@@ -290,13 +287,7 @@ func (w *huffmanBitWriter) writeDynamicHeader(numLiterals int, numOffsets int, n
 	}
 	w.writeBits(firstBits, 3)
 	w.writeBits(int32(numLiterals-257), 5)
-	if numOffsets > offsetCodeCount {
-		// Extended version of decompressor
-		w.writeBits(int32(offsetCodeCount+((numOffsets-(1+offsetCodeCount))>>3)), 5)
-		w.writeBits(int32((numOffsets-(1+offsetCodeCount))&0x7), 3)
-	} else {
-		w.writeBits(int32(numOffsets-1), 5)
-	}
+	w.writeBits(int32(numOffsets-1), 5)
 	w.writeBits(int32(numCodegens-4), 4)
 
 	for i := 0; i < numCodegens; i++ {
@@ -368,24 +359,17 @@ func (w *huffmanBitWriter) writeBlock(tokens []token, eof bool, input []byte) {
 	tokens = tokens[0 : n+1]
 	tokens[n] = endBlockMarker
 
-	totalLength := -1 // Subtract 1 for endBlock.
 	for _, t := range tokens {
 		switch t.typ() {
 		case literalType:
 			w.literalFreq[t.literal()]++
-			totalLength++
-			break
 		case matchType:
 			length := t.length()
 			offset := t.offset()
-			totalLength += int(length + 3)
 			w.literalFreq[lengthCodesStart+lengthCode(length)]++
 			w.offsetFreq[offsetCode(offset)]++
-			break
 		}
 	}
-	w.literalEncoding.generate(w.literalFreq, 15)
-	w.offsetEncoding.generate(w.offsetFreq, 15)
 
 	// get the number of literals
 	numLiterals := len(w.literalFreq)
@@ -394,15 +378,25 @@ func (w *huffmanBitWriter) writeBlock(tokens []token, eof bool, input []byte) {
 	}
 	// get the number of offsets
 	numOffsets := len(w.offsetFreq)
-	for numOffsets > 1 && w.offsetFreq[numOffsets-1] == 0 {
+	for numOffsets > 0 && w.offsetFreq[numOffsets-1] == 0 {
 		numOffsets--
 	}
+	if numOffsets == 0 {
+		// We haven't found a single match. If we want to go with the dynamic encoding,
+		// we should count at least one offset to be sure that the offset huffman tree could be encoded.
+		w.offsetFreq[0] = 1
+		numOffsets = 1
+	}
+
+	w.literalEncoding.generate(w.literalFreq, 15)
+	w.offsetEncoding.generate(w.offsetFreq, 15)
+
 	storedBytes := 0
 	if input != nil {
 		storedBytes = len(input)
 	}
 	var extraBits int64
-	var storedSize int64
+	var storedSize int64 = math.MaxInt64
 	if storedBytes <= maxStoreBlockSize && input != nil {
 		storedSize = int64((storedBytes + 5) * 8)
 		// We only bother calculating the costs of the extra bits required by
@@ -417,34 +411,29 @@ func (w *huffmanBitWriter) writeBlock(tokens []token, eof bool, input []byte) {
 			// First four offset codes have extra size = 0.
 			extraBits += int64(w.offsetFreq[offsetCode]) * int64(offsetExtraBits[offsetCode])
 		}
-	} else {
-		storedSize = math.MaxInt32
 	}
 
-	// Figure out which generates smaller code, fixed Huffman, dynamic
-	// Huffman, or just storing the data.
-	var fixedSize int64 = math.MaxInt64
-	if numOffsets <= offsetCodeCount {
-		fixedSize = int64(3) +
-			fixedLiteralEncoding.bitLength(w.literalFreq) +
-			fixedOffsetEncoding.bitLength(w.offsetFreq) +
-			extraBits
-	}
+	// Figure out smallest code.
+	// Fixed Huffman baseline.
+	var size = int64(3) +
+		fixedLiteralEncoding.bitLength(w.literalFreq) +
+		fixedOffsetEncoding.bitLength(w.offsetFreq) +
+		extraBits
+	var literalEncoding = fixedLiteralEncoding
+	var offsetEncoding = fixedOffsetEncoding
+
+	// Dynamic Huffman?
+	var numCodegens int
+
 	// Generate codegen and codegenFrequencies, which indicates how to encode
 	// the literalEncoding and the offsetEncoding.
 	w.generateCodegen(numLiterals, numOffsets)
 	w.codegenEncoding.generate(w.codegenFreq, 7)
-	numCodegens := len(w.codegenFreq)
+	numCodegens = len(w.codegenFreq)
 	for numCodegens > 4 && w.codegenFreq[codegenOrder[numCodegens-1]] == 0 {
 		numCodegens--
 	}
-	extensionSummand := 0
-	if numOffsets > offsetCodeCount {
-		extensionSummand = 3
-	}
 	dynamicHeader := int64(3+5+5+4+(3*numCodegens)) +
-		// Following line is an extension.
-		int64(extensionSummand) +
 		w.codegenEncoding.bitLength(w.codegenFreq) +
 		int64(extraBits) +
 		int64(w.codegenFreq[16]*2) +
@@ -454,26 +443,25 @@ func (w *huffmanBitWriter) writeBlock(tokens []token, eof bool, input []byte) {
 		w.literalEncoding.bitLength(w.literalFreq) +
 		w.offsetEncoding.bitLength(w.offsetFreq)
 
-	if storedSize < fixedSize && storedSize < dynamicSize {
+	if dynamicSize < size {
+		size = dynamicSize
+		literalEncoding = w.literalEncoding
+		offsetEncoding = w.offsetEncoding
+	}
+
+	// Stored bytes?
+	if storedSize < size {
 		w.writeStoredHeader(storedBytes, eof)
 		w.writeBytes(input[0:storedBytes])
 		return
 	}
-	var literalEncoding *huffmanEncoder
-	var offsetEncoding *huffmanEncoder
 
-	if fixedSize <= dynamicSize {
+	// Huffman.
+	if literalEncoding == fixedLiteralEncoding {
 		w.writeFixedHeader(eof)
-		literalEncoding = fixedLiteralEncoding
-		offsetEncoding = fixedOffsetEncoding
 	} else {
-		// Write the header.
 		w.writeDynamicHeader(numLiterals, numOffsets, numCodegens, eof)
-		literalEncoding = w.literalEncoding
-		offsetEncoding = w.offsetEncoding
 	}
-
-	// Write the tokens.
 	for _, t := range tokens {
 		switch t.typ() {
 		case literalType:
diff --git a/src/pkg/compress/flate/huffman_code.go b/src/pkg/compress/flate/huffman_code.go
index 6be605f..7ed603a 100644
--- a/src/pkg/compress/flate/huffman_code.go
+++ b/src/pkg/compress/flate/huffman_code.go
@@ -363,7 +363,12 @@ func (s literalNodeSorter) Less(i, j int) bool {
 func (s literalNodeSorter) Swap(i, j int) { s.a[i], s.a[j] = s.a[j], s.a[i] }
 
 func sortByFreq(a []literalNode) {
-	s := &literalNodeSorter{a, func(i, j int) bool { return a[i].freq < a[j].freq }}
+	s := &literalNodeSorter{a, func(i, j int) bool {
+		if a[i].freq == a[j].freq {
+			return a[i].literal < a[j].literal
+		}
+		return a[i].freq < a[j].freq
+	}}
 	sort.Sort(s)
 }
 
diff --git a/src/pkg/compress/flate/inflate.go b/src/pkg/compress/flate/inflate.go
index 320b80d..3845f12 100644
--- a/src/pkg/compress/flate/inflate.go
+++ b/src/pkg/compress/flate/inflate.go
@@ -77,8 +77,6 @@ type huffmanDecoder struct {
 
 // Initialize Huffman decoding tables from array of code lengths.
 func (h *huffmanDecoder) init(bits []int) bool {
-	// TODO(rsc): Return false sometimes.
-
 	// Count number of codes of each length,
 	// compute min and max length.
 	var count [maxCodeLen + 1]int
@@ -197,9 +195,8 @@ type Reader interface {
 
 // Decompress state.
 type decompressor struct {
-	// Input/output sources.
+	// Input source.
 	r       Reader
-	w       io.Writer
 	roffset int64
 	woffset int64
 
@@ -222,38 +219,79 @@ type decompressor struct {
 
 	// Temporary buffer (avoids repeated allocation).
 	buf [4]byte
+
+	// Next step in the decompression,
+	// and decompression state.
+	step     func(*decompressor)
+	final    bool
+	err      os.Error
+	toRead   []byte
+	hl, hd   *huffmanDecoder
+	copyLen  int
+	copyDist int
 }
 
-func (f *decompressor) inflate() (err os.Error) {
-	final := false
-	for err == nil && !final {
-		for f.nb < 1+2 {
-			if err = f.moreBits(); err != nil {
-				return
-			}
+func (f *decompressor) nextBlock() {
+	if f.final {
+		if f.hw != f.hp {
+			f.flush((*decompressor).nextBlock)
+			return
 		}
-		final = f.b&1 == 1
-		f.b >>= 1
-		typ := f.b & 3
-		f.b >>= 2
-		f.nb -= 1 + 2
-		switch typ {
-		case 0:
-			err = f.dataBlock()
-		case 1:
-			// compressed, fixed Huffman tables
-			err = f.decodeBlock(&fixedHuffmanDecoder, nil)
-		case 2:
-			// compressed, dynamic Huffman tables
-			if err = f.readHuffman(); err == nil {
-				err = f.decodeBlock(&f.h1, &f.h2)
-			}
-		default:
-			// 3 is reserved.
-			err = CorruptInputError(f.roffset)
+		f.err = os.EOF
+		return
+	}
+	for f.nb < 1+2 {
+		if f.err = f.moreBits(); f.err != nil {
+			return
+		}
+	}
+	f.final = f.b&1 == 1
+	f.b >>= 1
+	typ := f.b & 3
+	f.b >>= 2
+	f.nb -= 1 + 2
+	switch typ {
+	case 0:
+		f.dataBlock()
+	case 1:
+		// compressed, fixed Huffman tables
+		f.hl = &fixedHuffmanDecoder
+		f.hd = nil
+		f.huffmanBlock()
+	case 2:
+		// compressed, dynamic Huffman tables
+		if f.err = f.readHuffman(); f.err != nil {
+			break
+		}
+		f.hl = &f.h1
+		f.hd = &f.h2
+		f.huffmanBlock()
+	default:
+		// 3 is reserved.
+		f.err = CorruptInputError(f.roffset)
+	}
+}
+
+func (f *decompressor) Read(b []byte) (int, os.Error) {
+	for {
+		if len(f.toRead) > 0 {
+			n := copy(b, f.toRead)
+			f.toRead = f.toRead[n:]
+			return n, nil
+		}
+		if f.err != nil {
+			return 0, f.err
 		}
+		f.step(f)
 	}
-	return
+	panic("unreachable")
+}
+
+func (f *decompressor) Close() os.Error {
+	if f.err == os.EOF {
+		return nil
+	}
+	return f.err
 }
 
 // RFC 1951 section 3.2.7.
@@ -358,11 +396,12 @@ func (f *decompressor) readHuffman() os.Error {
 // hl and hd are the Huffman states for the lit/length values
 // and the distance values, respectively.  If hd == nil, using the
 // fixed distance encoding associated with fixed Huffman blocks.
-func (f *decompressor) decodeBlock(hl, hd *huffmanDecoder) os.Error {
+func (f *decompressor) huffmanBlock() {
 	for {
-		v, err := f.huffSym(hl)
+		v, err := f.huffSym(f.hl)
 		if err != nil {
-			return err
+			f.err = err
+			return
 		}
 		var n uint // number of bits extra
 		var length int
@@ -371,13 +410,15 @@ func (f *decompressor) decodeBlock(hl, hd *huffmanDecoder) os.Error {
 			f.hist[f.hp] = byte(v)
 			f.hp++
 			if f.hp == len(f.hist) {
-				if err = f.flush(); err != nil {
-					return err
-				}
+				// After the flush, continue this loop.
+				f.flush((*decompressor).huffmanBlock)
+				return
 			}
 			continue
 		case v == 256:
-			return nil
+			// Done with huffman block; read next block.
+			f.step = (*decompressor).nextBlock
+			return
 		// otherwise, reference to older data
 		case v < 265:
 			length = v - (257 - 3)
@@ -404,7 +445,8 @@ func (f *decompressor) decodeBlock(hl, hd *huffmanDecoder) os.Error {
 		if n > 0 {
 			for f.nb < n {
 				if err = f.moreBits(); err != nil {
-					return err
+					f.err = err
+					return
 				}
 			}
 			length += int(f.b & uint32(1<<n-1))
@@ -413,18 +455,20 @@ func (f *decompressor) decodeBlock(hl, hd *huffmanDecoder) os.Error {
 		}
 
 		var dist int
-		if hd == nil {
+		if f.hd == nil {
 			for f.nb < 5 {
 				if err = f.moreBits(); err != nil {
-					return err
+					f.err = err
+					return
 				}
 			}
 			dist = int(reverseByte[(f.b&0x1F)<<3])
 			f.b >>= 5
 			f.nb -= 5
 		} else {
-			if dist, err = f.huffSym(hd); err != nil {
-				return err
+			if dist, err = f.huffSym(f.hd); err != nil {
+				f.err = err
+				return
 			}
 		}
 
@@ -432,14 +476,16 @@ func (f *decompressor) decodeBlock(hl, hd *huffmanDecoder) os.Error {
 		case dist < 4:
 			dist++
 		case dist >= 30:
-			return CorruptInputError(f.roffset)
+			f.err = CorruptInputError(f.roffset)
+			return
 		default:
 			nb := uint(dist-2) >> 1
 			// have 1 bit in bottom of dist, need nb more.
 			extra := (dist & 1) << nb
 			for f.nb < nb {
 				if err = f.moreBits(); err != nil {
-					return err
+					f.err = err
+					return
 				}
 			}
 			extra |= int(f.b & uint32(1<<nb-1))
@@ -450,12 +496,14 @@ func (f *decompressor) decodeBlock(hl, hd *huffmanDecoder) os.Error {
 
 		// Copy history[-dist:-dist+length] into output.
 		if dist > len(f.hist) {
-			return InternalError("bad history distance")
+			f.err = InternalError("bad history distance")
+			return
 		}
 
 		// No check on length; encoding can be prescient.
 		if !f.hfull && dist > f.hp {
-			return CorruptInputError(f.roffset)
+			f.err = CorruptInputError(f.roffset)
+			return
 		}
 
 		p := f.hp - dist
@@ -467,9 +515,11 @@ func (f *decompressor) decodeBlock(hl, hd *huffmanDecoder) os.Error {
 			f.hp++
 			p++
 			if f.hp == len(f.hist) {
-				if err = f.flush(); err != nil {
-					return err
-				}
+				// After flush continue copying out of history.
+				f.copyLen = length - (i + 1)
+				f.copyDist = dist
+				f.flush((*decompressor).copyHuff)
+				return
 			}
 			if p == len(f.hist) {
 				p = 0
@@ -479,8 +529,33 @@ func (f *decompressor) decodeBlock(hl, hd *huffmanDecoder) os.Error {
 	panic("unreached")
 }
 
+func (f *decompressor) copyHuff() {
+	length := f.copyLen
+	dist := f.copyDist
+	p := f.hp - dist
+	if p < 0 {
+		p += len(f.hist)
+	}
+	for i := 0; i < length; i++ {
+		f.hist[f.hp] = f.hist[p]
+		f.hp++
+		p++
+		if f.hp == len(f.hist) {
+			f.copyLen = length - (i + 1)
+			f.flush((*decompressor).copyHuff)
+			return
+		}
+		if p == len(f.hist) {
+			p = 0
+		}
+	}
+
+	// Continue processing Huffman block.
+	f.huffmanBlock()
+}
+
 // Copy a single uncompressed data block from input to output.
-func (f *decompressor) dataBlock() os.Error {
+func (f *decompressor) dataBlock() {
 	// Uncompressed.
 	// Discard current half-byte.
 	f.nb = 0
@@ -490,21 +565,30 @@ func (f *decompressor) dataBlock() os.Error {
 	nr, err := io.ReadFull(f.r, f.buf[0:4])
 	f.roffset += int64(nr)
 	if err != nil {
-		return &ReadError{f.roffset, err}
+		f.err = &ReadError{f.roffset, err}
+		return
 	}
 	n := int(f.buf[0]) | int(f.buf[1])<<8
 	nn := int(f.buf[2]) | int(f.buf[3])<<8
 	if uint16(nn) != uint16(^n) {
-		return CorruptInputError(f.roffset)
+		f.err = CorruptInputError(f.roffset)
+		return
 	}
 
 	if n == 0 {
 		// 0-length block means sync
-		return f.flush()
+		f.flush((*decompressor).nextBlock)
+		return
 	}
 
-	// Read len bytes into history,
-	// writing as history fills.
+	f.copyLen = n
+	f.copyData()
+}
+
+func (f *decompressor) copyData() {
+	// Read f.dataLen bytes into history,
+	// pausing for reads as history fills.
+	n := f.copyLen
 	for n > 0 {
 		m := len(f.hist) - f.hp
 		if m > n {
@@ -513,17 +597,18 @@ func (f *decompressor) dataBlock() os.Error {
 		m, err := io.ReadFull(f.r, f.hist[f.hp:f.hp+m])
 		f.roffset += int64(m)
 		if err != nil {
-			return &ReadError{f.roffset, err}
+			f.err = &ReadError{f.roffset, err}
+			return
 		}
 		n -= m
 		f.hp += m
 		if f.hp == len(f.hist) {
-			if err = f.flush(); err != nil {
-				return err
-			}
+			f.copyLen = n
+			f.flush((*decompressor).copyData)
+			return
 		}
 	}
-	return nil
+	f.step = (*decompressor).nextBlock
 }
 
 func (f *decompressor) setDict(dict []byte) {
@@ -579,17 +664,8 @@ func (f *decompressor) huffSym(h *huffmanDecoder) (int, os.Error) {
 }
 
 // Flush any buffered output to the underlying writer.
-func (f *decompressor) flush() os.Error {
-	if f.hw == f.hp {
-		return nil
-	}
-	n, err := f.w.Write(f.hist[f.hw:f.hp])
-	if n != f.hp-f.hw && err == nil {
-		err = io.ErrShortWrite
-	}
-	if err != nil {
-		return &WriteError{f.woffset, err}
-	}
+func (f *decompressor) flush(step func(*decompressor)) {
+	f.toRead = f.hist[f.hw:f.hp]
 	f.woffset += int64(f.hp - f.hw)
 	f.hw = f.hp
 	if f.hp == len(f.hist) {
@@ -597,7 +673,7 @@ func (f *decompressor) flush() os.Error {
 		f.hw = 0
 		f.hfull = true
 	}
-	return nil
+	f.step = step
 }
 
 func makeReader(r io.Reader) Reader {
@@ -607,30 +683,15 @@ func makeReader(r io.Reader) Reader {
 	return bufio.NewReader(r)
 }
 
-// decompress reads DEFLATE-compressed data from r and writes
-// the uncompressed data to w.
-func (f *decompressor) decompress(r io.Reader, w io.Writer) os.Error {
-	f.r = makeReader(r)
-	f.w = w
-	f.woffset = 0
-	if err := f.inflate(); err != nil {
-		return err
-	}
-	if err := f.flush(); err != nil {
-		return err
-	}
-	return nil
-}
-
 // NewReader returns a new ReadCloser that can be used
 // to read the uncompressed version of r.  It is the caller's
 // responsibility to call Close on the ReadCloser when
 // finished reading.
 func NewReader(r io.Reader) io.ReadCloser {
 	var f decompressor
-	pr, pw := io.Pipe()
-	go func() { pw.CloseWithError(f.decompress(r, pw)) }()
-	return pr
+	f.r = makeReader(r)
+	f.step = (*decompressor).nextBlock
+	return &f
 }
 
 // NewReaderDict is like NewReader but initializes the reader
@@ -641,7 +702,7 @@ func NewReader(r io.Reader) io.ReadCloser {
 func NewReaderDict(r io.Reader, dict []byte) io.ReadCloser {
 	var f decompressor
 	f.setDict(dict)
-	pr, pw := io.Pipe()
-	go func() { pw.CloseWithError(f.decompress(r, pw)) }()
-	return pr
+	f.r = makeReader(r)
+	f.step = (*decompressor).nextBlock
+	return &f
 }
diff --git a/src/pkg/compress/zlib/writer_test.go b/src/pkg/compress/zlib/writer_test.go
index a06689e..32f05ab 100644
--- a/src/pkg/compress/zlib/writer_test.go
+++ b/src/pkg/compress/zlib/writer_test.go
@@ -6,6 +6,7 @@ package zlib
 
 import (
 	"bytes"
+	"fmt"
 	"io"
 	"io/ioutil"
 	"os"
@@ -17,15 +18,13 @@ var filenames = []string{
 	"../testdata/pi.txt",
 }
 
+var data = []string{
+	"test a reasonable sized string that can be compressed",
+}
+
 // Tests that compressing and then decompressing the given file at the given compression level and dictionary
 // yields equivalent bytes to the original file.
 func testFileLevelDict(t *testing.T, fn string, level int, d string) {
-	// Read dictionary, if given.
-	var dict []byte
-	if d != "" {
-		dict = []byte(d)
-	}
-
 	// Read the file, as golden output.
 	golden, err := os.Open(fn)
 	if err != nil {
@@ -33,17 +32,25 @@ func testFileLevelDict(t *testing.T, fn string, level int, d string) {
 		return
 	}
 	defer golden.Close()
-
-	// Read the file again, and push it through a pipe that compresses at the write end, and decompresses at the read end.
-	raw, err := os.Open(fn)
-	if err != nil {
-		t.Errorf("%s (level=%d, dict=%q): %v", fn, level, d, err)
+	b0, err0 := ioutil.ReadAll(golden)
+	if err0 != nil {
+		t.Errorf("%s (level=%d, dict=%q): %v", fn, level, d, err0)
 		return
 	}
+	testLevelDict(t, fn, b0, level, d)
+}
+
+func testLevelDict(t *testing.T, fn string, b0 []byte, level int, d string) {
+	// Make dictionary, if given.
+	var dict []byte
+	if d != "" {
+		dict = []byte(d)
+	}
+
+	// Push data through a pipe that compresses at the write end, and decompresses at the read end.
 	piper, pipew := io.Pipe()
 	defer piper.Close()
 	go func() {
-		defer raw.Close()
 		defer pipew.Close()
 		zlibw, err := NewWriterDict(pipew, level, dict)
 		if err != nil {
@@ -51,25 +58,14 @@ func testFileLevelDict(t *testing.T, fn string, level int, d string) {
 			return
 		}
 		defer zlibw.Close()
-		var b [1024]byte
-		for {
-			n, err0 := raw.Read(b[0:])
-			if err0 != nil && err0 != os.EOF {
-				t.Errorf("%s (level=%d, dict=%q): %v", fn, level, d, err0)
-				return
-			}
-			_, err1 := zlibw.Write(b[0: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 (level=%d, dict=%q): %v", fn, level, d, err1)
-				return
-			}
-			if err0 == os.EOF {
-				break
-			}
+		_, 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
 		}
 	}()
 	zlibr, err := NewReaderDict(piper, dict)
@@ -79,13 +75,8 @@ func testFileLevelDict(t *testing.T, fn string, level int, d string) {
 	}
 	defer zlibr.Close()
 
-	// Compare the two.
-	b0, err0 := ioutil.ReadAll(golden)
+	// Compare the decompressed data.
 	b1, err1 := ioutil.ReadAll(zlibr)
-	if err0 != nil {
-		t.Errorf("%s (level=%d, dict=%q): %v", fn, level, d, err0)
-		return
-	}
 	if err1 != nil {
 		t.Errorf("%s (level=%d, dict=%q): %v", fn, level, d, err1)
 		return
@@ -103,6 +94,18 @@ func testFileLevelDict(t *testing.T, fn string, level int, d string) {
 }
 
 func TestWriter(t *testing.T) {
+	for i, s := range data {
+		b := []byte(s)
+		tag := fmt.Sprintf("#%d", i)
+		testLevelDict(t, tag, b, DefaultCompression, "")
+		testLevelDict(t, tag, b, NoCompression, "")
+		for level := BestSpeed; level <= BestCompression; level++ {
+			testLevelDict(t, tag, b, level, "")
+		}
+	}
+}
+
+func TestWriterBig(t *testing.T) {
 	for _, fn := range filenames {
 		testFileLevelDict(t, fn, DefaultCompression, "")
 		testFileLevelDict(t, fn, NoCompression, "")
diff --git a/src/pkg/crypto/cipher/ocfb.go b/src/pkg/crypto/cipher/ocfb.go
index b2d8775..031e74a 100644
--- a/src/pkg/crypto/cipher/ocfb.go
+++ b/src/pkg/crypto/cipher/ocfb.go
@@ -80,9 +80,10 @@ type ocfbDecrypter struct {
 // NewOCFBDecrypter returns a Stream which decrypts data with OpenPGP's cipher
 // feedback mode using the given Block. Prefix must be the first blockSize + 2
 // bytes of the ciphertext, where blockSize is the Block's block size. If an
-// incorrect key is detected then nil is returned. Resync determines if the
-// "resynchronization step" from RFC 4880, 13.9 step 7 is performed. Different
-// parts of OpenPGP vary on this point.
+// incorrect key is detected then nil is returned. On successful exit,
+// blockSize+2 bytes of decrypted data are written into prefix. Resync
+// determines if the "resynchronization step" from RFC 4880, 13.9 step 7 is
+// performed. Different parts of OpenPGP vary on this point.
 func NewOCFBDecrypter(block Block, prefix []byte, resync OCFBResyncOption) Stream {
 	blockSize := block.BlockSize()
 	if len(prefix) != blockSize+2 {
@@ -118,6 +119,7 @@ func NewOCFBDecrypter(block Block, prefix []byte, resync OCFBResyncOption) Strea
 		x.fre[1] = prefix[blockSize+1]
 		x.outUsed = 2
 	}
+	copy(prefix, prefixCopy)
 	return x
 }
 
diff --git a/src/pkg/crypto/openpgp/packet/literal.go b/src/pkg/crypto/openpgp/packet/literal.go
index 04f50e5..9411572 100644
--- a/src/pkg/crypto/openpgp/packet/literal.go
+++ b/src/pkg/crypto/openpgp/packet/literal.go
@@ -51,3 +51,40 @@ func (l *LiteralData) parse(r io.Reader) (err os.Error) {
 	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/packet.go b/src/pkg/crypto/openpgp/packet/packet.go
index e583670..640a5b7 100644
--- a/src/pkg/crypto/openpgp/packet/packet.go
+++ b/src/pkg/crypto/openpgp/packet/packet.go
@@ -92,6 +92,46 @@ func (r *partialLengthReader) Read(p []byte) (n int, err os.Error) {
 	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 {
@@ -195,6 +235,20 @@ func serializeHeader(w io.Writer, ptype packetType, length int) (err os.Error) {
 	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 {
@@ -327,10 +381,10 @@ const (
 type CipherFunction uint8
 
 const (
-	CipherCAST5  = 3
-	CipherAES128 = 7
-	CipherAES192 = 8
-	CipherAES256 = 9
+	CipherCAST5  CipherFunction = 3
+	CipherAES128 CipherFunction = 7
+	CipherAES192 CipherFunction = 8
+	CipherAES256 CipherFunction = 9
 )
 
 // keySize returns the key size, in bytes, of cipher.
diff --git a/src/pkg/crypto/openpgp/packet/packet_test.go b/src/pkg/crypto/openpgp/packet/packet_test.go
index 1a4692c..23d9978 100644
--- a/src/pkg/crypto/openpgp/packet/packet_test.go
+++ b/src/pkg/crypto/openpgp/packet/packet_test.go
@@ -210,3 +210,47 @@ func TestSerializeHeader(t *testing.T) {
 		}
 	}
 }
+
+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/symmetric_key_encrypted.go b/src/pkg/crypto/openpgp/packet/symmetric_key_encrypted.go
index d9010f8..25d264a 100644
--- a/src/pkg/crypto/openpgp/packet/symmetric_key_encrypted.go
+++ b/src/pkg/crypto/openpgp/packet/symmetric_key_encrypted.go
@@ -5,6 +5,7 @@
 package packet
 
 import (
+	"bytes"
 	"crypto/cipher"
 	"crypto/openpgp/error"
 	"crypto/openpgp/s2k"
@@ -27,6 +28,8 @@ type SymmetricKeyEncrypted struct {
 	encryptedKey []byte
 }
 
+const symmetricKeyEncryptedVersion = 4
+
 func (ske *SymmetricKeyEncrypted) parse(r io.Reader) (err os.Error) {
 	// RFC 4880, section 5.3.
 	var buf [2]byte
@@ -34,7 +37,7 @@ func (ske *SymmetricKeyEncrypted) parse(r io.Reader) (err os.Error) {
 	if err != nil {
 		return
 	}
-	if buf[0] != 4 {
+	if buf[0] != symmetricKeyEncryptedVersion {
 		return error.UnsupportedError("SymmetricKeyEncrypted version")
 	}
 	ske.CipherFunc = CipherFunction(buf[1])
@@ -100,3 +103,60 @@ func (ske *SymmetricKeyEncrypted) Decrypt(passphrase []byte) os.Error {
 	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
index 717c8ff..823ec40 100644
--- a/src/pkg/crypto/openpgp/packet/symmetric_key_encrypted_test.go
+++ b/src/pkg/crypto/openpgp/packet/symmetric_key_encrypted_test.go
@@ -6,6 +6,7 @@ package packet
 
 import (
 	"bytes"
+	"crypto/rand"
 	"encoding/hex"
 	"io/ioutil"
 	"os"
@@ -60,3 +61,41 @@ func TestSymmetricKeyEncrypted(t *testing.T) {
 
 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
index fc19ffe..236c367 100644
--- a/src/pkg/crypto/openpgp/packet/symmetrically_encrypted.go
+++ b/src/pkg/crypto/openpgp/packet/symmetrically_encrypted.go
@@ -7,6 +7,7 @@ package packet
 import (
 	"crypto/cipher"
 	"crypto/openpgp/error"
+	"crypto/rand"
 	"crypto/sha1"
 	"crypto/subtle"
 	"hash"
@@ -24,6 +25,8 @@ type SymmetricallyEncrypted struct {
 	prefix   []byte
 }
 
+const symmetricallyEncryptedVersion = 1
+
 func (se *SymmetricallyEncrypted) parse(r io.Reader) os.Error {
 	if se.MDC {
 		// See RFC 4880, section 5.13.
@@ -32,7 +35,7 @@ func (se *SymmetricallyEncrypted) parse(r io.Reader) os.Error {
 		if err != nil {
 			return err
 		}
-		if buf[0] != 1 {
+		if buf[0] != symmetricallyEncryptedVersion {
 			return error.UnsupportedError("unknown SymmetricallyEncrypted version")
 		}
 	}
@@ -174,6 +177,9 @@ func (ser *seMDCReader) Read(buf []byte) (n int, err os.Error) {
 	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")
@@ -191,16 +197,95 @@ func (ser *seMDCReader) Close() os.Error {
 		}
 	}
 
-	// This is a new-format packet tag byte for a type 19 (MDC) packet.
-	const mdcPacketTagByte = byte(0x80) | 0x40 | 19
 	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 {
+	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
index 5543b20..ba5606e 100644
--- a/src/pkg/crypto/openpgp/packet/symmetrically_encrypted_test.go
+++ b/src/pkg/crypto/openpgp/packet/symmetrically_encrypted_test.go
@@ -9,6 +9,7 @@ import (
 	"crypto/openpgp/error"
 	"crypto/sha1"
 	"encoding/hex"
+	"io"
 	"io/ioutil"
 	"os"
 	"testing"
@@ -76,3 +77,48 @@ func testMDCReader(t *testing.T) {
 }
 
 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/s2k/s2k.go b/src/pkg/crypto/openpgp/s2k/s2k.go
index 80b81bd..da926a7 100644
--- a/src/pkg/crypto/openpgp/s2k/s2k.go
+++ b/src/pkg/crypto/openpgp/s2k/s2k.go
@@ -123,6 +123,26 @@ func Parse(r io.Reader) (f func(out, in []byte), err os.Error) {
 	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 {
diff --git a/src/pkg/crypto/openpgp/s2k/s2k_test.go b/src/pkg/crypto/openpgp/s2k/s2k_test.go
index 75bc47e..27d2e9a 100644
--- a/src/pkg/crypto/openpgp/s2k/s2k_test.go
+++ b/src/pkg/crypto/openpgp/s2k/s2k_test.go
@@ -7,6 +7,7 @@ package s2k
 import (
 	"bytes"
 	"crypto/sha1"
+	"crypto/rand"
 	"encoding/hex"
 	"testing"
 )
@@ -95,3 +96,26 @@ func TestParse(t *testing.T) {
 		}
 	}
 }
+
+
+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
index a1ede56..48c86f6 100644
--- a/src/pkg/crypto/openpgp/write.go
+++ b/src/pkg/crypto/openpgp/write.go
@@ -9,6 +9,7 @@ import (
 	"crypto/openpgp/armor"
 	"crypto/openpgp/error"
 	"crypto/openpgp/packet"
+	"crypto/rand"
 	_ "crypto/sha256"
 	"io"
 	"os"
@@ -81,3 +82,36 @@ func detachSign(w io.Writer, signer *Entity, message io.Reader, sigType packet.S
 
 	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)
+}
diff --git a/src/pkg/crypto/openpgp/write_test.go b/src/pkg/crypto/openpgp/write_test.go
index a74a84b..8551aeb 100644
--- a/src/pkg/crypto/openpgp/write_test.go
+++ b/src/pkg/crypto/openpgp/write_test.go
@@ -7,6 +7,8 @@ package openpgp
 import (
 	"bytes"
 	"crypto/rand"
+	"os"
+	"io"
 	"testing"
 	"time"
 )
@@ -85,3 +87,36 @@ func TestNewEntity(t *testing.T) {
 		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)
+	}
+}
diff --git a/src/pkg/crypto/tls/generate_cert.go b/src/pkg/crypto/tls/generate_cert.go
index 5b8c700..f461888 100644
--- a/src/pkg/crypto/tls/generate_cert.go
+++ b/src/pkg/crypto/tls/generate_cert.go
@@ -59,7 +59,7 @@ func main() {
 	certOut.Close()
 	log.Print("written cert.pem\n")
 
-	keyOut, err := os.OpenFile("key.pem", os.O_WRONLY|os.O_CREAT|os.O_TRUNC, 0600)
+	keyOut, err := os.OpenFile("key.pem", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
 	if err != nil {
 		log.Print("failed to open key.pem for writing:", err)
 		return
diff --git a/src/pkg/ebnf/ebnf_test.go b/src/pkg/ebnf/ebnf_test.go
index e77cf64..2055f87 100644
--- a/src/pkg/ebnf/ebnf_test.go
+++ b/src/pkg/ebnf/ebnf_test.go
@@ -22,7 +22,7 @@ var grammars = []string{
 
 	`Program = "a" | "b" "c" .`,
 
-	`Program = "a" ... "z" .`,
+	`Program = "a" … "z" .`,
 
 	`Program = Song .
 	 Song = { Note } .
diff --git a/src/pkg/ebnf/parser.go b/src/pkg/ebnf/parser.go
index 818168e..166412f 100644
--- a/src/pkg/ebnf/parser.go
+++ b/src/pkg/ebnf/parser.go
@@ -95,7 +95,8 @@ func (p *parser) parseTerm() (x Expression) {
 	case token.STRING:
 		tok := p.parseToken()
 		x = tok
-		if p.tok == token.ELLIPSIS {
+		const ellipsis = "…" // U+2026, the horizontal ellipsis character
+		if p.tok == token.ILLEGAL && p.lit == ellipsis {
 			p.next()
 			x = &Range{tok, p.parseToken()}
 		}
@@ -177,7 +178,7 @@ 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, 0)
+	p.scanner.Init(fset.AddFile(filename, fset.Base(), len(src)), src, p, scanner.AllowIllegalChars)
 	p.next() // initializes pos, tok, lit
 
 	grammar := make(Grammar)
diff --git a/src/pkg/encoding/base64/base64.go b/src/pkg/encoding/base64/base64.go
index 4961297..c6b2a13 100644
--- a/src/pkg/encoding/base64/base64.go
+++ b/src/pkg/encoding/base64/base64.go
@@ -106,6 +106,13 @@ func (enc *Encoding) Encode(dst, src []byte) {
 	}
 }
 
+// EncodeToString returns the base64 encoding of src.
+func (enc *Encoding) EncodeToString(src []byte) string {
+	buf := make([]byte, enc.EncodedLen(len(src)))
+	enc.Encode(buf, src)
+	return string(buf)
+}
+
 type encoder struct {
 	err  os.Error
 	enc  *Encoding
@@ -260,6 +267,13 @@ func (enc *Encoding) Decode(dst, src []byte) (n int, err os.Error) {
 	return
 }
 
+// DecodeString returns the bytes represented by the base64 string s.
+func (enc *Encoding) DecodeString(s string) ([]byte, os.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
 	enc    *Encoding
diff --git a/src/pkg/encoding/base64/base64_test.go b/src/pkg/encoding/base64/base64_test.go
index de41e70..c163dae 100644
--- a/src/pkg/encoding/base64/base64_test.go
+++ b/src/pkg/encoding/base64/base64_test.go
@@ -56,9 +56,8 @@ func testEqual(t *testing.T, msg string, args ...interface{}) bool {
 
 func TestEncode(t *testing.T) {
 	for _, p := range pairs {
-		buf := make([]byte, StdEncoding.EncodedLen(len(p.decoded)))
-		StdEncoding.Encode(buf, []byte(p.decoded))
-		testEqual(t, "Encode(%q) = %q, want %q", p.decoded, string(buf), p.encoded)
+		got := StdEncoding.EncodeToString([]byte(p.decoded))
+		testEqual(t, "Encode(%q) = %q, want %q", p.decoded, got, p.encoded)
 	}
 }
 
@@ -102,6 +101,10 @@ func TestDecode(t *testing.T) {
 			testEqual(t, "Decode(%q) = end %v, want %v", p.encoded, end, (p.encoded[len(p.encoded)-1] == '='))
 		}
 		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) = %q, want %q", string(dbuf), p.decoded)
 	}
 }
 
diff --git a/src/pkg/encoding/binary/binary.go b/src/pkg/encoding/binary/binary.go
index a01d0e0..8e55cb2 100644
--- a/src/pkg/encoding/binary/binary.go
+++ b/src/pkg/encoding/binary/binary.go
@@ -125,6 +125,35 @@ func (bigEndian) GoString() string { return "binary.BigEndian" }
 // 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 {
+	// Fast path for basic types.
+	if n := intDestSize(data); n != 0 {
+		var b [8]byte
+		bs := b[:n]
+		if _, err := io.ReadFull(r, bs); err != nil {
+			return err
+		}
+		switch v := data.(type) {
+		case *int8:
+			*v = int8(b[0])
+		case *uint8:
+			*v = b[0]
+		case *int16:
+			*v = int16(order.Uint16(bs))
+		case *uint16:
+			*v = order.Uint16(bs)
+		case *int32:
+			*v = int32(order.Uint32(bs))
+		case *uint32:
+			*v = order.Uint32(bs)
+		case *int64:
+			*v = int64(order.Uint64(bs))
+		case *uint64:
+			*v = order.Uint64(bs)
+		}
+		return nil
+	}
+
+	// Fallback to reflect-based.
 	var v reflect.Value
 	switch d := reflect.ValueOf(data); d.Kind() {
 	case reflect.Ptr:
@@ -155,6 +184,63 @@ func Read(r io.Reader, order ByteOrder, data interface{}) os.Error {
 // 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 {
+	// Fast path for basic types.
+	var b [8]byte
+	var bs []byte
+	switch v := data.(type) {
+	case *int8:
+		bs = b[:1]
+		b[0] = byte(*v)
+	case int8:
+		bs = b[:1]
+		b[0] = byte(v)
+	case *uint8:
+		bs = b[:1]
+		b[0] = *v
+	case uint8:
+		bs = b[:1]
+		b[0] = byte(v)
+	case *int16:
+		bs = b[:2]
+		order.PutUint16(bs, uint16(*v))
+	case int16:
+		bs = b[:2]
+		order.PutUint16(bs, uint16(v))
+	case *uint16:
+		bs = b[:2]
+		order.PutUint16(bs, *v)
+	case uint16:
+		bs = b[:2]
+		order.PutUint16(bs, v)
+	case *int32:
+		bs = b[:4]
+		order.PutUint32(bs, uint32(*v))
+	case int32:
+		bs = b[:4]
+		order.PutUint32(bs, uint32(v))
+	case *uint32:
+		bs = b[:4]
+		order.PutUint32(bs, *v)
+	case uint32:
+		bs = b[:4]
+		order.PutUint32(bs, v)
+	case *int64:
+		bs = b[:8]
+		order.PutUint64(bs, uint64(*v))
+	case int64:
+		bs = b[:8]
+		order.PutUint64(bs, uint64(v))
+	case *uint64:
+		bs = b[:8]
+		order.PutUint64(bs, *v)
+	case uint64:
+		bs = b[:8]
+		order.PutUint64(bs, v)
+	}
+	if bs != nil {
+		_, err := w.Write(bs)
+		return err
+	}
 	v := reflect.Indirect(reflect.ValueOf(data))
 	size := TotalSize(v)
 	if size < 0 {
@@ -394,3 +480,19 @@ func (e *encoder) value(v reflect.Value) {
 		}
 	}
 }
+
+// intDestSize returns the size of the integer that ptrType points to,
+// or 0 if the type is not supported.
+func intDestSize(ptrType interface{}) int {
+	switch ptrType.(type) {
+	case *int8, *uint8:
+		return 1
+	case *int16, *uint16:
+		return 2
+	case *int32, *uint32:
+		return 4
+	case *int64, *uint64:
+		return 8
+	}
+	return 0
+}
diff --git a/src/pkg/encoding/binary/binary_test.go b/src/pkg/encoding/binary/binary_test.go
index 7857c68..b266996 100644
--- a/src/pkg/encoding/binary/binary_test.go
+++ b/src/pkg/encoding/binary/binary_test.go
@@ -5,6 +5,7 @@
 package binary
 
 import (
+	"io"
 	"os"
 	"bytes"
 	"math"
@@ -160,3 +161,75 @@ func TestWriteT(t *testing.T) {
 		}
 	}
 }
+
+type byteSliceReader struct {
+	remain []byte
+}
+
+func (br *byteSliceReader) Read(p []byte) (int, os.Error) {
+	n := copy(p, br.remain)
+	br.remain = br.remain[n:]
+	return n, nil
+}
+
+func BenchmarkRead(b *testing.B) {
+	var ls Struct
+	bsr := &byteSliceReader{}
+	var r io.Reader = bsr
+
+	for i := 0; i < b.N; i++ {
+		bsr.remain = big
+		Read(r, BigEndian, &ls.Int8)
+		Read(r, BigEndian, &ls.Int16)
+		Read(r, BigEndian, &ls.Int32)
+		Read(r, BigEndian, &ls.Int64)
+		Read(r, BigEndian, &ls.Uint8)
+		Read(r, BigEndian, &ls.Uint16)
+		Read(r, BigEndian, &ls.Uint32)
+		Read(r, BigEndian, &ls.Uint64)
+	}
+
+	want := s
+	want.Float32 = 0
+	want.Float64 = 0
+	want.Complex64 = 0
+	want.Complex128 = 0
+	for i := range want.Array {
+		want.Array[i] = 0
+	}
+	if !reflect.DeepEqual(ls, want) {
+		panic("no match")
+	}
+}
+
+func BenchmarkWrite(b *testing.B) {
+	buf := new(bytes.Buffer)
+	var w io.Writer = buf
+
+	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)
+		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)
+	}
+
+	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")
+	}
+}
diff --git a/src/pkg/encoding/hex/hex.go b/src/pkg/encoding/hex/hex.go
index 891de18..47cdedd 100644
--- a/src/pkg/encoding/hex/hex.go
+++ b/src/pkg/encoding/hex/hex.go
@@ -6,6 +6,8 @@
 package hex
 
 import (
+	"bytes"
+	"io"
 	"os"
 	"strconv"
 )
@@ -99,3 +101,117 @@ func DecodeString(s string) ([]byte, os.Error) {
 	}
 	return dst, nil
 }
+
+// Dump returns a string that contains a hex dump of the given data. The format
+// of the hex dump matches the output of `hexdump -C` on the command line.
+func Dump(data []byte) string {
+	buf := bytes.NewBuffer(nil)
+	dumper := Dumper(buf)
+	dumper.Write(data)
+	dumper.Close()
+	return string(buf.Bytes())
+}
+
+// Dumper returns a WriteCloser that writes a hex dump of all written data to
+// w. The format of the dump matches the output of `hexdump -C` on the command
+// line.
+func Dumper(w io.Writer) io.WriteCloser {
+	return &dumper{w: w}
+}
+
+type dumper struct {
+	w          io.Writer
+	rightChars [18]byte
+	buf        [14]byte
+	used       int  // number of bytes in the current line
+	n          uint // number of bytes, total
+}
+
+func toChar(b byte) byte {
+	if b < 32 || b > 126 {
+		return '.'
+	}
+	return b
+}
+
+func (h *dumper) Write(data []byte) (n int, err os.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.
+	for i := range data {
+		if h.used == 0 {
+			// At the beginning of a line we print the current
+			// offset in hex.
+			h.buf[0] = byte(h.n >> 24)
+			h.buf[1] = byte(h.n >> 16)
+			h.buf[2] = byte(h.n >> 8)
+			h.buf[3] = byte(h.n)
+			Encode(h.buf[4:], h.buf[:4])
+			h.buf[12] = ' '
+			h.buf[13] = ' '
+			_, err = h.w.Write(h.buf[4:])
+		}
+		Encode(h.buf[:], data[i:i+1])
+		h.buf[2] = ' '
+		l := 3
+		if h.used == 7 {
+			// There's an additional space after the 8th byte.
+			h.buf[3] = ' '
+			l = 4
+		} else if h.used == 15 {
+			// At the end of the line there's an extra space and
+			// the bar for the right column.
+			h.buf[3] = ' '
+			h.buf[4] = '|'
+			l = 5
+		}
+		_, err = h.w.Write(h.buf[:l])
+		if err != nil {
+			return
+		}
+		n++
+		h.rightChars[h.used] = toChar(data[i])
+		h.used++
+		h.n++
+		if h.used == 16 {
+			h.rightChars[16] = '|'
+			h.rightChars[17] = '\n'
+			_, err = h.w.Write(h.rightChars[:])
+			if err != nil {
+				return
+			}
+			h.used = 0
+		}
+	}
+	return
+}
+
+func (h *dumper) Close() (err os.Error) {
+	// See the comments in Write() for the details of this format.
+	if h.used == 0 {
+		return
+	}
+	h.buf[0] = ' '
+	h.buf[1] = ' '
+	h.buf[2] = ' '
+	h.buf[3] = ' '
+	h.buf[4] = '|'
+	nBytes := h.used
+	for h.used < 16 {
+		l := 3
+		if h.used == 7 {
+			l = 4
+		} else if h.used == 15 {
+			l = 5
+		}
+		_, err = h.w.Write(h.buf[:l])
+		if err != nil {
+			return
+		}
+		h.used++
+	}
+	h.rightChars[nBytes] = '|'
+	h.rightChars[nBytes+1] = '\n'
+	_, err = h.w.Write(h.rightChars[:nBytes+2])
+	return
+}
diff --git a/src/pkg/encoding/hex/hex_test.go b/src/pkg/encoding/hex/hex_test.go
index a14c9d4..8e1838e 100644
--- a/src/pkg/encoding/hex/hex_test.go
+++ b/src/pkg/encoding/hex/hex_test.go
@@ -147,3 +147,46 @@ func TestDecodeString(t *testing.T) {
 		}
 	}
 }
+
+func TestDumper(t *testing.T) {
+	var in [40]byte
+	for i := range in {
+		in[i] = byte(i + 30)
+	}
+
+	for stride := 1; stride < len(in); stride++ {
+		out := bytes.NewBuffer(nil)
+		dumper := Dumper(out)
+		done := 0
+		for done < len(in) {
+			todo := done + stride
+			if todo > len(in) {
+				todo = len(in)
+			}
+			dumper.Write(in[done:todo])
+			done = todo
+		}
+
+		dumper.Close()
+		if !bytes.Equal(out.Bytes(), expectedHexDump) {
+			t.Errorf("stride: %d failed. got:\n%s\nwant:\n%s", stride, out.Bytes(), expectedHexDump)
+		}
+	}
+}
+
+func TestDump(t *testing.T) {
+	var in [40]byte
+	for i := range in {
+		in[i] = byte(i + 30)
+	}
+
+	out := []byte(Dump(in[:]))
+	if !bytes.Equal(out, expectedHexDump) {
+		t.Errorf("got:\n%s\nwant:\n%s", out, expectedHexDump)
+	}
+}
+
+var expectedHexDump = []byte(`00000000  1e 1f 20 21 22 23 24 25  26 27 28 29 2a 2b 2c 2d  |.. !"#$%&'()*+,-|
+00000010  2e 2f 30 31 32 33 34 35  36 37 38 39 3a 3b 3c 3d  |./0123456789:;<=|
+00000020  3e 3f 40 41 42 43 44 45                           |>?@ABCDE|
+`)
diff --git a/src/pkg/encoding/line/Makefile b/src/pkg/encoding/line/Makefile
deleted file mode 100644
index 1af355c..0000000
--- a/src/pkg/encoding/line/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=encoding/line
-GOFILES=\
-	line.go\
-
-include ../../../Make.pkg
diff --git a/src/pkg/encoding/line/line.go b/src/pkg/encoding/line/line.go
deleted file mode 100644
index 123962b..0000000
--- a/src/pkg/encoding/line/line.go
+++ /dev/null
@@ -1,115 +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 line implements a Reader that reads lines delimited by '\n' or
-// ' \r\n'.
-package line
-
-import (
-	"io"
-	"os"
-)
-
-// Reader reads lines, delimited by '\n' or \r\n', from an io.Reader.
-type Reader struct {
-	buf      []byte
-	consumed int
-	in       io.Reader
-	err      os.Error
-}
-
-// NewReader returns a new Reader that will read successive
-// lines from the input Reader.
-func NewReader(input io.Reader, maxLineLength int) *Reader {
-	return &Reader{
-		buf:      make([]byte, 0, maxLineLength),
-		consumed: 0,
-		in:       input,
-	}
-}
-
-// Read reads from any buffered data past the last line read, or from the underlying
-// io.Reader if the buffer is empty.
-func (l *Reader) Read(p []byte) (n int, err os.Error) {
-	l.removeConsumedFromBuffer()
-	if len(l.buf) > 0 {
-		n = copy(p, l.buf)
-		l.consumed += n
-		return
-	}
-	return l.in.Read(p)
-}
-
-func (l *Reader) removeConsumedFromBuffer() {
-	if l.consumed > 0 {
-		n := copy(l.buf, l.buf[l.consumed:])
-		l.buf = l.buf[:n]
-		l.consumed = 0
-	}
-}
-
-// ReadLine tries to return a single line, not including the end-of-line bytes.
-// If the line was found to be longer than the maximum length then isPrefix is
-// set and the beginning of the line is returned. The rest of the line will be
-// returned from future calls. isPrefix will be false when returning the last
-// fragment of the line.  The returned buffer points into the internal state of
-// the Reader and is only valid until the next call to ReadLine. ReadLine
-// either returns a non-nil line or it returns an error, never both.
-func (l *Reader) ReadLine() (line []byte, isPrefix bool, err os.Error) {
-	l.removeConsumedFromBuffer()
-
-	if len(l.buf) == 0 && l.err != nil {
-		err = l.err
-		return
-	}
-
-	scannedTo := 0
-
-	for {
-		i := scannedTo
-		for ; i < len(l.buf); i++ {
-			if l.buf[i] == '\r' && len(l.buf) > i+1 && l.buf[i+1] == '\n' {
-				line = l.buf[:i]
-				l.consumed = i + 2
-				return
-			} else if l.buf[i] == '\n' {
-				line = l.buf[:i]
-				l.consumed = i + 1
-				return
-			}
-		}
-
-		if i == cap(l.buf) {
-			line = l.buf[:i]
-			l.consumed = i
-			isPrefix = true
-			return
-		}
-
-		if l.err != nil {
-			line = l.buf
-			l.consumed = i
-			return
-		}
-
-		// We don't want to rescan the input that we just scanned.
-		// However, we need to back up one byte because the last byte
-		// could have been a '\r' and we do need to rescan that.
-		scannedTo = i
-		if scannedTo > 0 {
-			scannedTo--
-		}
-		oldLen := len(l.buf)
-		l.buf = l.buf[:cap(l.buf)]
-		n, readErr := l.in.Read(l.buf[oldLen:])
-		l.buf = l.buf[:oldLen+n]
-		if readErr != nil {
-			l.err = readErr
-			if len(l.buf) == 0 {
-				return nil, false, readErr
-			}
-		}
-	}
-	panic("unreachable")
-}
diff --git a/src/pkg/encoding/line/line_test.go b/src/pkg/encoding/line/line_test.go
deleted file mode 100644
index ff3d516..0000000
--- a/src/pkg/encoding/line/line_test.go
+++ /dev/null
@@ -1,133 +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 line
-
-import (
-	"bytes"
-	"io"
-	"io/ioutil"
-	"os"
-	"testing"
-)
-
-var testOutput = []byte("0123456789abcdefghijklmnopqrstuvwxy")
-var testInput = []byte("012\n345\n678\n9ab\ncde\nfgh\nijk\nlmn\nopq\nrst\nuvw\nxy")
-var testInputrn = []byte("012\r\n345\r\n678\r\n9ab\r\ncde\r\nfgh\r\nijk\r\nlmn\r\nopq\r\nrst\r\nuvw\r\nxy\r\n\n\r\n")
-
-// 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 testLineReader(t *testing.T, input []byte) {
-	for stride := 1; stride < len(input); stride++ {
-		done := 0
-		reader := testReader{input, stride}
-		l := NewReader(&reader, len(input)+1)
-		for {
-			line, isPrefix, err := l.ReadLine()
-			if len(line) > 0 && err != nil {
-				t.Errorf("ReadLine returned both data and error: %s", err)
-			}
-			if isPrefix {
-				t.Errorf("ReadLine returned prefix")
-			}
-			if err != nil {
-				if err != os.EOF {
-					t.Fatalf("Got unknown error: %s", err)
-				}
-				break
-			}
-			if want := testOutput[done : done+len(line)]; !bytes.Equal(want, line) {
-				t.Errorf("Bad line at stride %d: want: %x got: %x", stride, want, line)
-			}
-			done += len(line)
-		}
-		if done != len(testOutput) {
-			t.Error("ReadLine didn't return everything")
-		}
-	}
-}
-
-func TestReader(t *testing.T) {
-	testLineReader(t, testInput)
-	testLineReader(t, testInputrn)
-}
-
-func TestLineTooLong(t *testing.T) {
-	buf := bytes.NewBuffer([]byte("aaabbbcc\n"))
-	l := NewReader(buf, 3)
-	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)
-	}
-	line, isPrefix, err = l.ReadLine()
-	if !isPrefix || !bytes.Equal(line, []byte("bbb")) || err != nil {
-		t.Errorf("bad result for second line: %x", line)
-	}
-	line, isPrefix, err = l.ReadLine()
-	if isPrefix || !bytes.Equal(line, []byte("cc")) || err != nil {
-		t.Errorf("bad result for third line: %x", line)
-	}
-}
-
-func TestReadAfterLines(t *testing.T) {
-	line1 := "line1"
-	restData := "line2\nline 3\n"
-	inbuf := bytes.NewBuffer([]byte(line1 + "\n" + restData))
-	outbuf := new(bytes.Buffer)
-	maxLineLength := len(line1) + len(restData)/2
-	l := NewReader(inbuf, maxLineLength)
-	line, isPrefix, err := l.ReadLine()
-	if isPrefix || err != nil || string(line) != line1 {
-		t.Errorf("bad result for first line: isPrefix=%v err=%v line=%q", isPrefix, err, string(line))
-	}
-	n, err := io.Copy(outbuf, l)
-	if int(n) != len(restData) || err != nil {
-		t.Errorf("bad result for Read: n=%d err=%v", n, err)
-	}
-	if outbuf.String() != restData {
-		t.Errorf("bad result for Read: got %q; expected %q", outbuf.String(), restData)
-	}
-}
-
-func TestReadEmptyBuffer(t *testing.T) {
-	l := NewReader(bytes.NewBuffer(nil), 10)
-	line, isPrefix, err := l.ReadLine()
-	if err != os.EOF {
-		t.Errorf("expected EOF from ReadLine, got '%s' %t %s", line, isPrefix, err)
-	}
-}
-
-func TestLinesAfterRead(t *testing.T) {
-	l := NewReader(bytes.NewBuffer([]byte("foo")), 10)
-	_, err := ioutil.ReadAll(l)
-	if err != nil {
-		t.Error(err)
-		return
-	}
-
-	line, isPrefix, err := l.ReadLine()
-	if err != os.EOF {
-		t.Errorf("expected EOF from ReadLine, got '%s' %t %s", line, isPrefix, err)
-	}
-}
diff --git a/src/pkg/exec/exec.go b/src/pkg/exec/exec.go
index 043f847..c6a5e06 100644
--- a/src/pkg/exec/exec.go
+++ b/src/pkg/exec/exec.go
@@ -7,198 +7,361 @@
 // adjustments.
 package exec
 
-// BUG(r): This package should be made even easier to use or merged into os.
-
 import (
+	"bytes"
+	"io"
 	"os"
 	"strconv"
 )
 
-// Arguments to Run.
-const (
-	DevNull = iota
-	PassThrough
-	Pipe
-	MergeWithStdout
-)
+// 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
+}
 
-// A Cmd represents a running command.
-// Stdin, Stdout, and Stderr are Files representing pipes
-// connected to the running command's standard input, output, and error,
-// or else nil, depending on the arguments to Run.
-// Process represents the underlying operating system process.
+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 {
-	Stdin   *os.File
-	Stdout  *os.File
-	Stderr  *os.File
-	Process *os.Process
+	// 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
+
+	err             os.Error // last error (from LookPath, stdin, stdout, stderr)
+	process         *os.Process
+	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,
+	}
 }
 
-// PathError records the name of a binary that was not
-// found on the current $PATH.
-type PathError struct {
-	Name string
+// 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 (e *PathError) String() string {
-	return "command " + strconv.Quote(e.Name) + " not found in $PATH"
+func (c *Cmd) envv() []string {
+	if c.Env != nil {
+		return c.Env
+	}
+	return os.Environ()
 }
 
-// Given mode (DevNull, etc), return file for child
-// and file to record in Cmd structure.
-func modeToFiles(mode, fd int) (*os.File, *os.File, os.Error) {
-	switch mode {
-	case DevNull:
-		rw := os.O_WRONLY
-		if fd == 0 {
-			rw = os.O_RDONLY
-		}
-		f, err := os.OpenFile(os.DevNull, rw, 0)
-		return f, nil, err
-	case PassThrough:
-		switch fd {
-		case 0:
-			return os.Stdin, nil, nil
-		case 1:
-			return os.Stdout, nil, nil
-		case 2:
-			return os.Stderr, nil, nil
+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
 		}
-	case Pipe:
-		r, w, err := os.Pipe()
+		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 nil, nil, err
-		}
-		if fd == 0 {
-			return r, w, nil
+			return err
 		}
-		return w, r, nil
+		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(),
+	})
+	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, nil, os.EINVAL
+
+	return nil
 }
 
-// Run starts the named binary running with
-// arguments argv and environment envv.
-// If the dir argument is not empty, the child changes
-// into the directory before executing the binary.
-// It returns a pointer to a new Cmd representing
-// the command or an error.
+// Wait waits for the command to exit.
+// It must have been started by Start.
 //
-// The arguments stdin, stdout, and stderr
-// specify how to handle standard input, output, and error.
-// The choices are DevNull (connect to /dev/null),
-// PassThrough (connect to the current process's standard stream),
-// Pipe (connect to an operating system pipe), and
-// MergeWithStdout (only for standard error; use the same
-// file descriptor as was used for standard output).
-// If an argument is Pipe, then the corresponding field (Stdin, Stdout, Stderr)
-// of the returned Cmd is the other end of the pipe.
-// Otherwise the field in Cmd is nil.
-func Run(name string, argv, envv []string, dir string, stdin, stdout, stderr int) (c *Cmd, err os.Error) {
-	c = new(Cmd)
-	var fd [3]*os.File
-
-	if fd[0], c.Stdin, err = modeToFiles(stdin, 0); err != nil {
-		goto Error
-	}
-	if fd[1], c.Stdout, err = modeToFiles(stdout, 1); err != nil {
-		goto Error
-	}
-	if stderr == MergeWithStdout {
-		fd[2] = fd[1]
-	} else if fd[2], c.Stderr, err = modeToFiles(stderr, 2); err != nil {
-		goto Error
-	}
-
-	// Run command.
-	c.Process, err = os.StartProcess(name, argv, &os.ProcAttr{Dir: dir, Files: fd[:], Env: envv})
-	if err != nil {
-		goto Error
+// 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 fd[0] != os.Stdin {
-		fd[0].Close()
+	if c.finished {
+		return os.NewError("exec: Wait was already called")
 	}
-	if fd[1] != os.Stdout {
-		fd[1].Close()
+	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
+		}
 	}
-	if fd[2] != os.Stderr && fd[2] != fd[1] {
-		fd[2].Close()
+
+	for _, fd := range c.closeAfterWait {
+		fd.Close()
 	}
-	return c, nil
 
-Error:
-	if fd[0] != os.Stdin && fd[0] != nil {
-		fd[0].Close()
+	if err != nil {
+		return err
+	} else if !msg.Exited() || msg.ExitStatus() != 0 {
+		return msg
 	}
-	if fd[1] != os.Stdout && fd[1] != nil {
-		fd[1].Close()
+
+	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")
 	}
-	if fd[2] != os.Stderr && fd[2] != nil && fd[2] != fd[1] {
-		fd[2].Close()
+	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 {
-		c.Stdin.Close()
+		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.closeAfterStart, pw)
+	return pw, nil
+}
+
+// StdoutPipe returns a pipe that will be connected to the command's
+// standard output when the command starts.
+func (c *Cmd) StdoutPipe() (io.Reader, os.Error) {
 	if c.Stdout != nil {
-		c.Stdout.Close()
+		return nil, os.NewError("exec: Stdout already set")
 	}
-	if c.Stderr != nil {
-		c.Stderr.Close()
-	}
-	if c.Process != nil {
-		c.Process.Release()
-	}
-	return nil, err
-}
-
-// Wait waits for the running command c,
-// returning the Waitmsg returned when the process exits.
-// The options are passed to the process's Wait method.
-// Setting options to 0 waits for c to exit;
-// other options cause Wait to return for other
-// process events; see package os for details.
-func (c *Cmd) Wait(options int) (*os.Waitmsg, os.Error) {
-	if c.Process == nil {
-		return nil, os.ErrorString("exec: invalid use of Cmd.Wait")
-	}
-	w, err := c.Process.Wait(options)
-	if w != nil && (w.Exited() || w.Signaled()) {
-		c.Process.Release()
-		c.Process = nil
-	}
-	return w, err
-}
-
-// Close waits for the running command c to exit,
-// if it hasn't already, and then closes the non-nil file descriptors
-// c.Stdin, c.Stdout, and c.Stderr.
-func (c *Cmd) Close() os.Error {
-	if c.Process != nil {
-		// Loop on interrupt, but
-		// ignore other errors -- maybe
-		// caller has already waited for pid.
-		_, err := c.Wait(0)
-		for err == os.EINTR {
-			_, err = c.Wait(0)
-		}
+	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.closeAfterStart, pr)
+	return pr, nil
+}
 
-	// Close the FDs that are still open.
-	var err os.Error
-	if c.Stdin != nil && c.Stdin.Fd() >= 0 {
-		if err1 := c.Stdin.Close(); err1 != nil {
-			err = err1
-		}
+// StderrPipe returns a pipe that will be connected to the command's
+// standard error when the command starts.
+func (c *Cmd) StderrPipe() (io.Reader, os.Error) {
+	if c.Stderr != nil {
+		return nil, os.NewError("exec: Stderr already set")
 	}
-	if c.Stdout != nil && c.Stdout.Fd() >= 0 {
-		if err1 := c.Stdout.Close(); err1 != nil && err != nil {
-			err = err1
-		}
+	if c.process != nil {
+		return nil, os.NewError("exec: StderrPipe after process started")
 	}
-	if c.Stderr != nil && c.Stderr != c.Stdout && c.Stderr.Fd() >= 0 {
-		if err1 := c.Stderr.Close(); err1 != nil && err != nil {
-			err = err1
-		}
+	pr, pw, err := os.Pipe()
+	if err != nil {
+		return nil, err
 	}
-	return err
+	c.Stderr = pw
+	c.closeAfterStart = append(c.closeAfterStart, pw)
+	c.closeAfterWait = append(c.closeAfterStart, pr)
+	return pr, nil
 }
diff --git a/src/pkg/exec/exec_test.go b/src/pkg/exec/exec_test.go
index eb8cd5f..c45a7d7 100644
--- a/src/pkg/exec/exec_test.go
+++ b/src/pkg/exec/exec_test.go
@@ -5,163 +5,211 @@
 package exec
 
 import (
+	"bufio"
+	"bytes"
+	"fmt"
 	"io"
-	"io/ioutil"
 	"testing"
 	"os"
+	"strconv"
+	"strings"
 )
 
-func run(argv []string, stdin, stdout, stderr int) (p *Cmd, err os.Error) {
-	exe, err := LookPath(argv[0])
-	if err != nil {
-		return nil, err
-	}
-	return Run(exe, argv, nil, "", stdin, stdout, stderr)
+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 TestRunCat(t *testing.T) {
-	cmd, err := run([]string{"cat"}, Pipe, Pipe, DevNull)
+func TestEcho(t *testing.T) {
+	bs, err := helperCommand("echo", "foo bar", "baz").Output()
 	if err != nil {
-		t.Fatal("run:", err)
-	}
-	io.WriteString(cmd.Stdin, "hello, world\n")
-	cmd.Stdin.Close()
-	buf, err := ioutil.ReadAll(cmd.Stdout)
-	if err != nil {
-		t.Fatal("read:", err)
-	}
-	if string(buf) != "hello, world\n" {
-		t.Fatalf("read: got %q", buf)
+		t.Errorf("echo: %v", err)
 	}
-	if err = cmd.Close(); err != nil {
-		t.Fatal("close:", err)
+	if g, e := string(bs), "foo bar baz\n"; g != e {
+		t.Errorf("echo: want %q, got %q", e, g)
 	}
 }
 
-func TestRunEcho(t *testing.T) {
-	cmd, err := run([]string{"sh", "-c", "echo hello world"},
-		DevNull, Pipe, DevNull)
+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.Fatal("run:", err)
+		t.Errorf("cat: %v", err)
 	}
-	buf, err := ioutil.ReadAll(cmd.Stdout)
-	if err != nil {
-		t.Fatal("read:", err)
-	}
-	if string(buf) != "hello world\n" {
-		t.Fatalf("read: got %q", buf)
-	}
-	if err = cmd.Close(); err != nil {
-		t.Fatal("close:", err)
+	s := string(bs)
+	if s != input {
+		t.Errorf("cat: want %q, got %q", input, s)
 	}
 }
 
-func TestStderr(t *testing.T) {
-	cmd, err := run([]string{"sh", "-c", "echo hello world 1>&2"},
-		DevNull, DevNull, Pipe)
-	if err != nil {
-		t.Fatal("run:", err)
+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)
 	}
-	buf, err := ioutil.ReadAll(cmd.Stderr)
-	if err != nil {
-		t.Fatal("read:", err)
+	s := string(bs)
+	sp := strings.Split(s, "\n", 2)
+	if len(sp) != 2 {
+		t.Fatalf("expected two lines from cat; got %q", s)
 	}
-	if string(buf) != "hello world\n" {
-		t.Fatalf("read: got %q", buf)
+	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 err = cmd.Close(); err != nil {
-		t.Fatal("close:", err)
+	if !strings.Contains(body, "func TestHelperProcess(t *testing.T)") {
+		t.Errorf("expected test code; got %q (len %d)", body, len(body))
 	}
 }
 
-func TestMergeWithStdout(t *testing.T) {
-	cmd, err := run([]string{"sh", "-c", "echo hello world 1>&2"},
-		DevNull, Pipe, MergeWithStdout)
-	if err != nil {
-		t.Fatal("run:", err)
-	}
-	buf, err := ioutil.ReadAll(cmd.Stdout)
-	if err != nil {
-		t.Fatal("read:", err)
-	}
-	if string(buf) != "hello world\n" {
-		t.Fatalf("read: got %q", buf)
+
+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")
 	}
-	if err = cmd.Close(); err != nil {
-		t.Fatal("close:", err)
+}
+
+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 TestAddEnvVar(t *testing.T) {
-	err := os.Setenv("NEWVAR", "hello world")
-	if err != nil {
-		t.Fatal("setenv:", err)
+func TestPipes(t *testing.T) {
+	check := func(what string, err os.Error) {
+		if err != nil {
+			t.Fatalf("%s: %v", what, err)
+		}
 	}
-	cmd, err := run([]string{"sh", "-c", "echo $NEWVAR"},
-		DevNull, Pipe, DevNull)
-	if err != nil {
-		t.Fatal("run:", 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)
 	}
-	buf, err := ioutil.ReadAll(cmd.Stdout)
-	if err != nil {
-		t.Fatal("read:", err)
+
+	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)
 	}
-	if string(buf) != "hello world\n" {
-		t.Fatalf("read: got %q", buf)
+
+	_, 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)
 	}
-	if err = cmd.Close(); err != nil {
-		t.Fatal("close:", err)
+
+	_, 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)
 	}
-}
 
-var tryargs = []string{
-	`2`,
-	`2 `,
-	"2 \t",
-	`2" "`,
-	`2 ab `,
-	`2 "ab" `,
-	`2 \ `,
-	`2 \\ `,
-	`2 \" `,
-	`2 \`,
-	`2\`,
-	`2"`,
-	`2\"`,
-	`2 "`,
-	`2 \"`,
-	``,
-	`2 ^ `,
-	`2 \^`,
+	stdin.Close()
+	err = c.Wait()
+	check("Wait", err)
 }
 
-func TestArgs(t *testing.T) {
-	for _, a := range tryargs {
-		argv := []string{
-			"awk",
-			`BEGIN{printf("%s|%s|%s",ARGV[1],ARGV[2],ARGV[3])}`,
-			"/dev/null",
-			a,
-			"EOF",
-		}
-		exe, err := LookPath(argv[0])
-		if err != nil {
-			t.Fatal("run:", 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
 		}
-		cmd, err := Run(exe, argv, nil, "", DevNull, Pipe, DevNull)
-		if err != nil {
-			t.Fatal("run:", err)
+		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)
 		}
-		buf, err := ioutil.ReadAll(cmd.Stdout)
-		if err != nil {
-			t.Fatal("read:", err)
+		fmt.Println(iargs...)
+	case "cat":
+		if len(args) == 0 {
+			io.Copy(os.Stdout, os.Stdin)
+			return
 		}
-		expect := "/dev/null|" + a + "|EOF"
-		if string(buf) != expect {
-			t.Errorf("read: got %q expect %q", buf, expect)
+		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)
+			}
 		}
-		if err = cmd.Close(); err != nil {
-			t.Fatal("close:", err)
+		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_test.go b/src/pkg/exec/lp_test.go
index 5408177..77d8e84 100644
--- a/src/pkg/exec/lp_test.go
+++ b/src/pkg/exec/lp_test.go
@@ -22,12 +22,12 @@ func TestLookPathNotFound(t *testing.T) {
 		if path != "" {
 			t.Fatalf("LookPath path == %q when err != nil", path)
 		}
-		perr, ok := err.(*PathError)
+		perr, ok := err.(*Error)
 		if !ok {
-			t.Fatal("LookPath error is not a PathError")
+			t.Fatal("LookPath error is not an exec.Error")
 		}
 		if perr.Name != name {
-			t.Fatalf("want PathError name %q, got %q", name, perr.Name)
+			t.Fatalf("want Error name %q, got %q", name, perr.Name)
 		}
 	}
 }
diff --git a/src/pkg/exec/lp_unix.go b/src/pkg/exec/lp_unix.go
index 44f8434..3fc3be8 100644
--- a/src/pkg/exec/lp_unix.go
+++ b/src/pkg/exec/lp_unix.go
@@ -9,12 +9,18 @@ import (
 	"strings"
 )
 
-func canExec(file string) bool {
+// ErrNotFound is the error resulting if a path search failed to find an executable file.
+var ErrNotFound = os.ErrorString("executable file not found in $PATH")
+
+func findExecutable(file string) os.Error {
 	d, err := os.Stat(file)
 	if err != nil {
-		return false
+		return err
+	}
+	if d.IsRegular() && d.Permission()&0111 != 0 {
+		return nil
 	}
-	return d.IsRegular() && d.Permission()&0111 != 0
+	return os.EPERM
 }
 
 // LookPath searches for an executable binary named file
@@ -26,10 +32,11 @@ func LookPath(file string) (string, os.Error) {
 	// but that would not match all the Unix shells.
 
 	if strings.Contains(file, "/") {
-		if canExec(file) {
+		err := findExecutable(file)
+		if err == nil {
 			return file, nil
 		}
-		return "", &PathError{file}
+		return "", &Error{file, err}
 	}
 	pathenv := os.Getenv("PATH")
 	for _, dir := range strings.Split(pathenv, ":", -1) {
@@ -37,9 +44,9 @@ func LookPath(file string) (string, os.Error) {
 			// Unix shell semantics: path element "" means "."
 			dir = "."
 		}
-		if canExec(dir + "/" + file) {
+		if err := findExecutable(dir + "/" + file); err == nil {
 			return dir + "/" + file, nil
 		}
 	}
-	return "", &PathError{file}
+	return "", &Error{file, ErrNotFound}
 }
diff --git a/src/pkg/exec/lp_windows.go b/src/pkg/exec/lp_windows.go
index d357575..7588610 100644
--- a/src/pkg/exec/lp_windows.go
+++ b/src/pkg/exec/lp_windows.go
@@ -9,15 +9,21 @@ import (
 	"strings"
 )
 
-func chkStat(file string) bool {
+// ErrNotFound is the error resulting if a path search failed to find an executable file.
+var ErrNotFound = os.ErrorString("executable file not found in %PATH%")
+
+func chkStat(file string) os.Error {
 	d, err := os.Stat(file)
 	if err != nil {
-		return false
+		return err
+	}
+	if d.IsRegular() {
+		return nil
 	}
-	return d.IsRegular()
+	return os.EPERM
 }
 
-func canExec(file string, exts []string) (string, bool) {
+func findExecutable(file string, exts []string) (string, os.Error) {
 	if len(exts) == 0 {
 		return file, chkStat(file)
 	}
@@ -28,14 +34,14 @@ func canExec(file string, exts []string) (string, bool) {
 		}
 	}
 	for _, e := range exts {
-		if f := file + e; chkStat(f) {
-			return f, true
+		if f := file + e; chkStat(f) == nil {
+			return f, nil
 		}
 	}
-	return ``, false
+	return ``, ErrNotFound
 }
 
-func LookPath(file string) (string, os.Error) {
+func LookPath(file string) (f string, err os.Error) {
 	exts := []string{}
 	if x := os.Getenv(`PATHEXT`); x != `` {
 		exts = strings.Split(strings.ToLower(x), `;`, -1)
@@ -46,21 +52,21 @@ func LookPath(file string) (string, os.Error) {
 		}
 	}
 	if strings.Contains(file, `\`) || strings.Contains(file, `/`) {
-		if f, ok := canExec(file, exts); ok {
-			return f, nil
+		if f, err = findExecutable(file, exts); err == nil {
+			return
 		}
-		return ``, &PathError{file}
+		return ``, &Error{file, err}
 	}
 	if pathenv := os.Getenv(`PATH`); pathenv == `` {
-		if f, ok := canExec(`.\`+file, exts); ok {
-			return f, nil
+		if f, err = findExecutable(`.\`+file, exts); err == nil {
+			return
 		}
 	} else {
 		for _, dir := range strings.Split(pathenv, `;`, -1) {
-			if f, ok := canExec(dir+`\`+file, exts); ok {
-				return f, nil
+			if f, err = findExecutable(dir+`\`+file, exts); err == nil {
+				return
 			}
 		}
 	}
-	return ``, &PathError{file}
+	return ``, &Error{file, ErrNotFound}
 }
diff --git a/src/pkg/exp/eval/gen.go b/src/pkg/exp/eval/gen.go
index de98a5d..1e00bdc 100644
--- a/src/pkg/exp/eval/gen.go
+++ b/src/pkg/exp/eval/gen.go
@@ -366,10 +366,10 @@ func main() {
 	t.SetDelims("«", "»")
 	err := t.Parse(templateStr)
 	if err != nil {
-		log.Exit(err)
+		log.Fatal(err)
 	}
 	err = t.Execute(os.Stdout, data)
 	if err != nil {
-		log.Exit(err)
+		log.Fatal(err)
 	}
 }
diff --git a/src/pkg/fmt/doc.go b/src/pkg/fmt/doc.go
index 08609ca..79fe575 100644
--- a/src/pkg/fmt/doc.go
+++ b/src/pkg/fmt/doc.go
@@ -25,6 +25,7 @@
 		%c	the character represented by the corresponding Unicode code point
 		%d	base 10
 		%o	base 8
+		%q	a single-quoted character literal safely escaped with Go syntax.
 		%x	base 16, with lower-case letters for a-f
 		%X	base 16, with upper-case letters for A-F
 		%U	Unicode format: U+1234; same as "U+%04X"
diff --git a/src/pkg/fmt/fmt_test.go b/src/pkg/fmt/fmt_test.go
index b3c0c5a..caecb6f 100644
--- a/src/pkg/fmt/fmt_test.go
+++ b/src/pkg/fmt/fmt_test.go
@@ -135,6 +135,17 @@ var fmttests = []struct {
 	{"%q", "\u263a", `"\u263a"`},
 	{"%q", "\U0010ffff", `"\U0010ffff"`},
 
+	// escaped characters
+	{"%q", 'x', `'x'`},
+	{"%q", 0, `'\x00'`},
+	{"%q", '\n', `'\n'`},
+	{"%q", '\u1234', `'\u1234'`},
+	{"%q", '\U00012345', `'\U00012345'`},
+	{"%q", int64(0x7FFFFFFF), `%!q(int64=2147483647)`},
+	{"%q", uint64(0xFFFFFFFF), `%!q(uint64=4294967295)`},
+	{"%q", '"', `'"'`},
+	{"%q", '\'', `'\''`},
+
 	// width
 	{"%5s", "abc", "  abc"},
 	{"%2s", "\u263a", " \u263a"},
diff --git a/src/pkg/fmt/format.go b/src/pkg/fmt/format.go
index f9d2b4f..5dcfb96 100644
--- a/src/pkg/fmt/format.go
+++ b/src/pkg/fmt/format.go
@@ -296,6 +296,13 @@ func (f *fmt) fmt_q(s string) {
 	f.padString(quoted)
 }
 
+// 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) {
+	quoted := strconv.QuoteRune(int(c))
+	f.padString(quoted)
+}
+
 // floating-point
 
 func doPrec(f *fmt, def int) int {
diff --git a/src/pkg/fmt/print.go b/src/pkg/fmt/print.go
index 8885ceb..c18a8ea 100644
--- a/src/pkg/fmt/print.go
+++ b/src/pkg/fmt/print.go
@@ -9,6 +9,7 @@ import (
 	"io"
 	"os"
 	"reflect"
+	"unicode"
 	"utf8"
 )
 
@@ -332,6 +333,12 @@ func (p *pp) fmtInt64(v int64, verb int, value interface{}) {
 		p.fmt.integer(v, 10, signed, ldigits)
 	case 'o':
 		p.fmt.integer(v, 8, signed, ldigits)
+	case 'q':
+		if 0 <= v && v <= unicode.MaxRune {
+			p.fmt.fmt_qc(v)
+		} else {
+			p.badVerb(verb, value)
+		}
 	case 'x':
 		p.fmt.integer(v, 16, signed, ldigits)
 	case 'U':
@@ -385,6 +392,12 @@ func (p *pp) fmtUint64(v uint64, verb int, goSyntax bool, value interface{}) {
 		}
 	case 'o':
 		p.fmt.integer(int64(v), 8, unsigned, ldigits)
+	case 'q':
+		if 0 <= v && v <= unicode.MaxRune {
+			p.fmt.fmt_qc(int64(v))
+		} else {
+			p.badVerb(verb, value)
+		}
 	case 'x':
 		p.fmt.integer(int64(v), 16, unsigned, ldigits)
 	case 'X':
diff --git a/src/pkg/fmt/scan.go b/src/pkg/fmt/scan.go
index 42bc52c..dd8548c 100644
--- a/src/pkg/fmt/scan.go
+++ b/src/pkg/fmt/scan.go
@@ -231,6 +231,7 @@ func (s *ss) UnreadRune() os.Error {
 	} else {
 		s.peekRune = s.prevRune
 	}
+	s.prevRune = -1
 	s.count--
 	return nil
 }
@@ -457,6 +458,14 @@ func (s *ss) peek(ok string) bool {
 	return strings.IndexRune(ok, rune) >= 0
 }
 
+func (s *ss) notEOF() {
+	// Guarantee there is data to be read.
+	if rune := s.getRune(); rune == eof {
+		panic(os.EOF)
+	}
+	s.UnreadRune()
+}
+
 // accept checks the next rune in the input.  If it's a byte (sic) in the string, it puts it in the
 // buffer and returns true. Otherwise it return false.
 func (s *ss) accept(ok string) bool {
@@ -476,11 +485,13 @@ 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 {
+	s.skipSpace(false)
+	s.notEOF()
 	if !s.okVerb(verb, "tv", "boolean") {
 		return false
 	}
 	// Syntax-checking a boolean is annoying.  We're not fastidious about case.
-	switch s.mustReadRune() {
+	switch s.getRune() {
 	case '0':
 		return false
 	case '1':
@@ -531,6 +542,7 @@ func (s *ss) getBase(verb int) (base int, digits string) {
 
 // scanNumber returns the numerical string with specified digits starting here.
 func (s *ss) scanNumber(digits string, haveDigits bool) string {
+	s.notEOF()
 	if !haveDigits && !s.accept(digits) {
 		s.errorString("expected integer")
 	}
@@ -541,7 +553,8 @@ 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 {
-	rune := int64(s.mustReadRune())
+	s.notEOF()
+	rune := int64(s.getRune())
 	n := uint(bitSize)
 	x := (rune << (64 - n)) >> (64 - n)
 	if x != rune {
@@ -575,6 +588,7 @@ func (s *ss) scanInt(verb int, bitSize int) int64 {
 		return s.scanRune(bitSize)
 	}
 	s.skipSpace(false)
+	s.notEOF()
 	base, digits := s.getBase(verb)
 	haveDigits := false
 	if verb == 'U' {
@@ -607,6 +621,7 @@ func (s *ss) scanUint(verb int, bitSize int) uint64 {
 		return uint64(s.scanRune(bitSize))
 	}
 	s.skipSpace(false)
+	s.notEOF()
 	base, digits := s.getBase(verb)
 	haveDigits := false
 	if verb == 'U' {
@@ -727,6 +742,7 @@ func (s *ss) scanComplex(verb int, n int) complex128 {
 		return 0
 	}
 	s.skipSpace(false)
+	s.notEOF()
 	sreal, simag := s.complexTokens()
 	real := s.convertFloat(sreal, n/2)
 	imag := s.convertFloat(simag, n/2)
@@ -740,6 +756,7 @@ func (s *ss) convertString(verb int) (str string) {
 		return ""
 	}
 	s.skipSpace(false)
+	s.notEOF()
 	switch verb {
 	case 'q':
 		str = s.quotedString()
@@ -748,16 +765,13 @@ func (s *ss) convertString(verb int) (str string) {
 	default:
 		str = string(s.token(true, notSpace)) // %s and %v just return the next word
 	}
-	// Empty strings other than with %q are not OK.
-	if len(str) == 0 && verb != 'q' && s.maxWid > 0 {
-		s.errorString("Scan: no data for string")
-	}
 	return
 }
 
 // quotedString returns the double- or back-quoted string represented by the next input characters.
 func (s *ss) quotedString() string {
-	quote := s.mustReadRune()
+	s.notEOF()
+	quote := s.getRune()
 	switch quote {
 	case '`':
 		// Back-quoted: Anything goes until EOF or back quote.
@@ -827,6 +841,7 @@ func (s *ss) hexByte() (b byte, ok bool) {
 
 // hexString returns the space-delimited hexpair-encoded string.
 func (s *ss) hexString() string {
+	s.notEOF()
 	for {
 		b, ok := s.hexByte()
 		if !ok {
@@ -860,6 +875,7 @@ func (s *ss) scanOne(verb int, field interface{}) {
 		}
 		return
 	}
+
 	switch v := field.(type) {
 	case *bool:
 		*v = s.scanBool(verb)
@@ -894,11 +910,13 @@ func (s *ss) scanOne(verb int, field interface{}) {
 	case *float32:
 		if s.okVerb(verb, floatVerbs, "float32") {
 			s.skipSpace(false)
+			s.notEOF()
 			*v = float32(s.convertFloat(s.floatToken(), 32))
 		}
 	case *float64:
 		if s.okVerb(verb, floatVerbs, "float64") {
 			s.skipSpace(false)
+			s.notEOF()
 			*v = s.convertFloat(s.floatToken(), 64)
 		}
 	case *string:
@@ -936,6 +954,7 @@ func (s *ss) scanOne(verb int, field interface{}) {
 			}
 		case reflect.Float32, reflect.Float64:
 			s.skipSpace(false)
+			s.notEOF()
 			v.SetFloat(s.convertFloat(s.floatToken(), v.Type().Bits()))
 		case reflect.Complex64, reflect.Complex128:
 			v.SetComplex(s.scanComplex(verb, v.Type().Bits()))
@@ -946,13 +965,13 @@ func (s *ss) scanOne(verb int, field interface{}) {
 	}
 }
 
-// errorHandler turns local panics into error returns.  EOFs are benign.
+// errorHandler turns local panics into error returns.
 func errorHandler(errp *os.Error) {
 	if e := recover(); e != nil {
 		if se, ok := e.(scanError); ok { // catch local error
-			if se.err != os.EOF {
-				*errp = se.err
-			}
+			*errp = se.err
+		} else if eof, ok := e.(os.Error); ok && eof == os.EOF { // out of input
+			*errp = eof
 		} else {
 			panic(e)
 		}
diff --git a/src/pkg/fmt/scan_test.go b/src/pkg/fmt/scan_test.go
index da13eb2..a4de8ad 100644
--- a/src/pkg/fmt/scan_test.go
+++ b/src/pkg/fmt/scan_test.go
@@ -660,6 +660,68 @@ func TestEOF(t *testing.T) {
 	}
 }
 
+// Verify that we see an EOF error if we run out of input.
+// This was a buglet: we used to get "expected integer".
+func TestEOFAtEndOfInput(t *testing.T) {
+	var i, j int
+	n, err := Sscanf("23", "%d %d", &i, &j)
+	if n != 1 || i != 23 {
+		t.Errorf("Sscanf expected one value of 23; got %d %d", n, i)
+	}
+	if err != os.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 {
+		t.Errorf("Sscan expected EOF; got %q", err)
+	}
+	// Trailing space is tougher.
+	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 {
+		t.Errorf("Sscan expected EOF; got %q", err)
+	}
+}
+
+var eofTests = []struct {
+	format string
+	v      interface{}
+}{
+	{"%s", &stringVal},
+	{"%q", &stringVal},
+	{"%x", &stringVal},
+	{"%v", &stringVal},
+	{"%v", &bytesVal},
+	{"%v", &intVal},
+	{"%v", &uintVal},
+	{"%v", &boolVal},
+	{"%v", &float32Val},
+	{"%v", &complex64Val},
+	{"%v", &renamedStringVal},
+	{"%v", &renamedBytesVal},
+	{"%v", &renamedIntVal},
+	{"%v", &renamedUintVal},
+	{"%v", &renamedBoolVal},
+	{"%v", &renamedFloat32Val},
+	{"%v", &renamedComplex64Val},
+}
+
+func TestEOFAllTypes(t *testing.T) {
+	for i, test := range eofTests {
+		if _, err := Sscanf("", test.format, test.v); err != os.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 {
+			t.Errorf("#%d: %s %T not eof on trailing blanks: %s", i, test.format, test.v, err)
+		}
+	}
+}
+
 // Verify that, at least when using bufio, successive calls to Fscan do not lose runes.
 func TestUnreadRuneWithBufio(t *testing.T) {
 	r := bufio.NewReader(strings.NewReader("123αb"))
diff --git a/src/pkg/go/scanner/scanner.go b/src/pkg/go/scanner/scanner.go
index 07b7454..509abec 100644
--- a/src/pkg/go/scanner/scanner.go
+++ b/src/pkg/go/scanner/scanner.go
@@ -134,36 +134,6 @@ func (S *Scanner) Init(file *token.File, src []byte, err ErrorHandler, mode uint
 }
 
 
-func charString(ch int) string {
-	var s string
-	switch ch {
-	case -1:
-		return `EOF`
-	case '\a':
-		s = `\a`
-	case '\b':
-		s = `\b`
-	case '\f':
-		s = `\f`
-	case '\n':
-		s = `\n`
-	case '\r':
-		s = `\r`
-	case '\t':
-		s = `\t`
-	case '\v':
-		s = `\v`
-	case '\\':
-		s = `\\`
-	case '\'':
-		s = `\'`
-	default:
-		s = string(ch)
-	}
-	return "'" + s + "' (U+" + strconv.Itob(ch, 16) + ")"
-}
-
-
 func (S *Scanner) error(offs int, msg string) {
 	if S.err != nil {
 		S.err.Error(S.file.Position(S.file.Pos(offs)), msg)
@@ -327,6 +297,10 @@ func (S *Scanner) scanNumber(seenDecimalPoint bool) token.Token {
 			// hexadecimal int
 			S.next()
 			S.scanMantissa(16)
+			if S.offset-offs <= 2 {
+				// only scanned "0x" or "0X"
+				S.error(offs, "illegal hexadecimal number")
+			}
 		} else {
 			// octal int or float
 			seenDecimalDigit := false
@@ -700,7 +674,7 @@ scanAgain:
 			tok = S.switch3(token.OR, token.OR_ASSIGN, '|', token.LOR)
 		default:
 			if S.mode&AllowIllegalChars == 0 {
-				S.error(offs, "illegal character "+charString(ch))
+				S.error(offs, "illegal character "+strconv.QuoteRune(ch))
 			}
 			insertSemi = S.insertSemi // preserve insertSemi info
 		}
diff --git a/src/pkg/go/scanner/scanner_test.go b/src/pkg/go/scanner/scanner_test.go
index 2d56bfb..8af9728 100644
--- a/src/pkg/go/scanner/scanner_test.go
+++ b/src/pkg/go/scanner/scanner_test.go
@@ -650,7 +650,9 @@ var errors = []struct {
 	pos int
 	err string
 }{
-	{`#`, token.ILLEGAL, 0, "illegal character '#' (U+23)"},
+	{"\a", token.ILLEGAL, 0, "illegal character '\\a'"},
+	{`#`, token.ILLEGAL, 0, "illegal character '#'"},
+	{`…`, token.ILLEGAL, 0, "illegal character '\\u2026'"},
 	{`' '`, token.CHAR, 0, ""},
 	{`''`, token.CHAR, 0, "illegal character literal"},
 	{`'\8'`, token.CHAR, 2, "unknown escape sequence"},
@@ -670,6 +672,8 @@ var errors = []struct {
 	{"078e0", token.FLOAT, 0, ""},
 	{"078", token.INT, 0, "illegal octal number"},
 	{"07800000009", token.INT, 0, "illegal octal number"},
+	{"0x", token.INT, 0, "illegal hexadecimal number"},
+	{"0X", token.INT, 0, "illegal hexadecimal number"},
 	{"\"abc\x00def\"", token.STRING, 4, "illegal character NUL"},
 	{"\"abc\x80def\"", token.STRING, 4, "illegal UTF-8 encoding"},
 }
diff --git a/src/pkg/go/types/gcimporter_test.go b/src/pkg/go/types/gcimporter_test.go
index 50e70f2..10240ad 100644
--- a/src/pkg/go/types/gcimporter_test.go
+++ b/src/pkg/go/types/gcimporter_test.go
@@ -37,24 +37,14 @@ func init() {
 
 
 func compile(t *testing.T, dirname, filename string) {
-	cmd, err := exec.Run(gcPath, []string{gcPath, filename}, nil, dirname, exec.DevNull, exec.Pipe, exec.MergeWithStdout)
+	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
 	}
-	defer cmd.Close()
-
-	msg, err := cmd.Wait(0)
-	if err != nil {
-		t.Errorf("%s %s failed: %s", gcName, filename, err)
-		return
-	}
-
-	if !msg.Exited() || msg.ExitStatus() != 0 {
-		t.Errorf("%s %s failed: exit status = %d", gcName, filename, msg.ExitStatus())
-		output, _ := ioutil.ReadAll(cmd.Stdout)
-		t.Log(string(output))
-	}
+	t.Logf("%s", string(out))
 }
 
 
diff --git a/src/pkg/gob/decoder.go b/src/pkg/gob/decoder.go
index ea2f62e..b83904a 100644
--- a/src/pkg/gob/decoder.go
+++ b/src/pkg/gob/decoder.go
@@ -155,8 +155,8 @@ func (dec *Decoder) decodeTypeSequence(isInterface bool) typeId {
 // 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 either be the correct type for the next
-// data item received, and must be a pointer.
+// 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{})
diff --git a/src/pkg/http/cgi/host.go b/src/pkg/http/cgi/host.go
index 7e4ccf8..7ab3f92 100644
--- a/src/pkg/http/cgi/host.go
+++ b/src/pkg/http/cgi/host.go
@@ -156,34 +156,35 @@ func (h *Handler) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
 		cwd = "."
 	}
 
-	args := []string{h.Path}
-	args = append(args, h.Args...)
-
-	cmd, err := exec.Run(
-		pathBase,
-		args,
-		env,
-		cwd,
-		exec.Pipe,        // stdin
-		exec.Pipe,        // stdout
-		exec.PassThrough, // stderr (for now)
-	)
-	if err != nil {
+	internalError := func(err os.Error) {
 		rw.WriteHeader(http.StatusInternalServerError)
 		h.printf("CGI error: %v", err)
-		return
 	}
-	defer func() {
-		cmd.Stdin.Close()
-		cmd.Stdout.Close()
-		cmd.Wait(0) // no zombies
-	}()
 
+	cmd := &exec.Cmd{
+		Path:   pathBase,
+		Args:   append([]string{h.Path}, h.Args...),
+		Dir:    cwd,
+		Env:    env,
+		Stderr: os.Stderr, // for now
+	}
 	if req.ContentLength != 0 {
-		go io.Copy(cmd.Stdin, req.Body)
+		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()
 
-	linebody, _ := bufio.NewReaderSize(cmd.Stdout, 1024)
+	linebody, _ := bufio.NewReaderSize(stdoutRead, 1024)
 	headers := make(http.Header)
 	statusCode := 0
 	for {
diff --git a/src/pkg/http/cgi/host_test.go b/src/pkg/http/cgi/host_test.go
index 9ac085f..bbdb715 100644
--- a/src/pkg/http/cgi/host_test.go
+++ b/src/pkg/http/cgi/host_test.go
@@ -17,20 +17,6 @@ import (
 	"testing"
 )
 
-var cgiScriptWorks = canRun("./testdata/test.cgi")
-
-func canRun(s string) bool {
-	c, err := exec.Run(s, []string{s}, nil, ".", exec.DevNull, exec.DevNull, exec.DevNull)
-	if err != nil {
-		return false
-	}
-	w, err := c.Wait(0)
-	if err != nil {
-		return false
-	}
-	return w.Exited() && w.ExitStatus() == 0
-}
-
 func newRequest(httpreq string) *http.Request {
 	buf := bufio.NewReader(strings.NewReader(httpreq))
 	req, err := http.ReadRequest(buf)
@@ -76,8 +62,15 @@ readlines:
 	return rw
 }
 
+var cgiTested = false
+var cgiWorks bool
+
 func skipTest(t *testing.T) bool {
-	if !cgiScriptWorks {
+	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.")
diff --git a/src/pkg/http/client.go b/src/pkg/http/client.go
index ac7ff18..7e1d65d 100644
--- a/src/pkg/http/client.go
+++ b/src/pkg/http/client.go
@@ -11,9 +11,7 @@ import (
 	"encoding/base64"
 	"fmt"
 	"io"
-	"io/ioutil"
 	"os"
-	"strconv"
 	"strings"
 )
 
@@ -100,13 +98,10 @@ func send(req *Request, t RoundTripper) (resp *Response, err os.Error) {
 
 	info := req.URL.RawUserinfo
 	if len(info) > 0 {
-		enc := base64.URLEncoding
-		encoded := make([]byte, enc.EncodedLen(len(info)))
-		enc.Encode(encoded, []byte(info))
 		if req.Header == nil {
 			req.Header = make(Header)
 		}
-		req.Header.Set("Authorization", "Basic "+string(encoded))
+		req.Header.Set("Authorization", "Basic "+base64.URLEncoding.EncodeToString([]byte(info)))
 	}
 	return t.RoundTrip(req)
 }
@@ -231,23 +226,12 @@ func Post(url string, bodyType string, body io.Reader) (r *Response, err os.Erro
 //
 // 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) {
-	var req Request
-	req.Method = "POST"
-	req.ProtoMajor = 1
-	req.ProtoMinor = 1
-	req.Close = true
-	req.Body = ioutil.NopCloser(body)
-	req.Header = Header{
-		"Content-Type": {bodyType},
-	}
-	req.TransferEncoding = []string{"chunked"}
-
-	req.URL, err = ParseURL(url)
+	req, err := NewRequest("POST", url, body)
 	if err != nil {
 		return nil, err
 	}
-
-	return send(&req, c.Transport)
+	req.Header.Set("Content-Type", bodyType)
+	return send(req, c.Transport)
 }
 
 // PostForm issues a POST to the specified URL, 
@@ -265,25 +249,7 @@ func PostForm(url string, data map[string]string) (r *Response, err os.Error) {
 //
 // Caller should close r.Body when done reading from it.
 func (c *Client) PostForm(url string, data map[string]string) (r *Response, err os.Error) {
-	var req Request
-	req.Method = "POST"
-	req.ProtoMajor = 1
-	req.ProtoMinor = 1
-	req.Close = true
-	body := urlencode(data)
-	req.Body = ioutil.NopCloser(body)
-	req.Header = Header{
-		"Content-Type":   {"application/x-www-form-urlencoded"},
-		"Content-Length": {strconv.Itoa(body.Len())},
-	}
-	req.ContentLength = int64(body.Len())
-
-	req.URL, err = ParseURL(url)
-	if err != nil {
-		return nil, err
-	}
-
-	return send(&req, c.Transport)
+	return c.Post(url, "application/x-www-form-urlencoded", urlencode(data))
 }
 
 // TODO: remove this function when PostForm takes a multimap.
diff --git a/src/pkg/http/client_test.go b/src/pkg/http/client_test.go
index 0869015..822a888 100644
--- a/src/pkg/http/client_test.go
+++ b/src/pkg/http/client_test.go
@@ -10,6 +10,7 @@ import (
 	"fmt"
 	. "http"
 	"http/httptest"
+	"io"
 	"io/ioutil"
 	"os"
 	"strconv"
@@ -77,6 +78,61 @@ func TestGetRequestFormat(t *testing.T) {
 	}
 }
 
+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}
+
+	url := "http://dummy.faketld/"
+	form := map[string]string{"foo": "bar"}
+	client.PostForm(url, 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() != 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 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")
+	}
+	if g, e := tr.req.ContentLength, int64(len("foo=bar")); g != e {
+		t.Errorf("got ContentLength %d, want %d", g, e)
+	}
+
+}
+
 func TestRedirects(t *testing.T) {
 	var ts *httptest.Server
 	ts = httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
@@ -139,3 +195,41 @@ func TestRedirects(t *testing.T) {
 		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)
+	}
+}
diff --git a/src/pkg/http/cookie.go b/src/pkg/http/cookie.go
index 5add1cc..eb61a70 100644
--- a/src/pkg/http/cookie.go
+++ b/src/pkg/http/cookie.go
@@ -81,12 +81,17 @@ func readSetCookies(h Header) []*Cookie {
 			if j := strings.Index(attr, "="); j >= 0 {
 				attr, val = attr[:j], attr[j+1:]
 			}
-			val, success = parseCookieValue(val)
+			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 strings.ToLower(attr) {
+			switch lowerAttr {
 			case "secure":
 				c.Secure = true
 				continue
@@ -112,8 +117,11 @@ func readSetCookies(h Header) []*Cookie {
 				c.RawExpires = val
 				exptime, err := time.Parse(time.RFC1123, val)
 				if err != nil {
-					c.Expires = time.Time{}
-					break
+					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
@@ -272,7 +280,7 @@ func unquoteCookieValue(v string) string {
 }
 
 func isCookieByte(c byte) bool {
-	switch true {
+	switch {
 	case c == 0x21, 0x23 <= c && c <= 0x2b, 0x2d <= c && c <= 0x3a,
 		0x3c <= c && c <= 0x5b, 0x5d <= c && c <= 0x7e:
 		return true
@@ -280,10 +288,22 @@ func isCookieByte(c byte) bool {
 	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 !isCookieByte(raw[i]) {
+		if !validByte(raw[i]) {
 			return "", false
 		}
 	}
diff --git a/src/pkg/http/cookie_test.go b/src/pkg/http/cookie_test.go
index 13c9fff..02e4222 100644
--- a/src/pkg/http/cookie_test.go
+++ b/src/pkg/http/cookie_test.go
@@ -11,9 +11,9 @@ import (
 	"os"
 	"reflect"
 	"testing"
+	"time"
 )
 
-
 var writeSetCookiesTests = []struct {
 	Cookies []*Cookie
 	Raw     string
@@ -115,6 +115,19 @@ var readSetCookiesTests = []struct {
 		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, Weekday: 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 {
diff --git a/src/pkg/http/fs.go b/src/pkg/http/fs.go
index 17d5297..28a0c51 100644
--- a/src/pkg/http/fs.go
+++ b/src/pkg/http/fs.go
@@ -175,7 +175,9 @@ func serveFile(w ResponseWriter, r *Request, name string, redirect bool) {
 	}
 
 	w.Header().Set("Accept-Ranges", "bytes")
-	w.Header().Set("Content-Length", strconv.Itoa64(size))
+	if w.Header().Get("Content-Encoding") == "" {
+		w.Header().Set("Content-Length", strconv.Itoa64(size))
+	}
 
 	w.WriteHeader(code)
 
diff --git a/src/pkg/http/fs_test.go b/src/pkg/http/fs_test.go
index b941962..5540534 100644
--- a/src/pkg/http/fs_test.go
+++ b/src/pkg/http/fs_test.go
@@ -101,7 +101,7 @@ func TestServeFileContentType(t *testing.T) {
 			t.Fatal(err)
 		}
 		if h := resp.Header.Get("Content-Type"); h != want {
-			t.Errorf("Content-Type mismatch: got %q, want %q", h, want)
+			t.Errorf("Content-Type mismatch: got %d, want %d", h, want)
 		}
 	}
 	get("text/plain; charset=utf-8")
@@ -109,6 +109,21 @@ func TestServeFileContentType(t *testing.T) {
 	get(ctype)
 }
 
+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 %q, want %q", g, e)
+	}
+}
+
 func getBody(t *testing.T, req Request) (*Response, []byte) {
 	r, err := DefaultClient.Do(&req)
 	if err != nil {
diff --git a/src/pkg/http/request.go b/src/pkg/http/request.go
index 05d4892..2f6b651 100644
--- a/src/pkg/http/request.go
+++ b/src/pkg/http/request.go
@@ -10,6 +10,7 @@ package http
 
 import (
 	"bufio"
+	"bytes"
 	"crypto/tls"
 	"container/vector"
 	"encoding/base64"
@@ -231,7 +232,7 @@ const defaultUserAgent = "Go http package"
 //	Method (defaults to "GET")
 //	UserAgent (defaults to defaultUserAgent)
 //	Referer
-//	Header
+//	Header (only keys not already in this list)
 //	Cookie
 //	ContentLength
 //	TransferEncoding
@@ -256,6 +257,9 @@ func (req *Request) WriteProxy(w io.Writer) os.Error {
 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
 	}
 
@@ -475,6 +479,17 @@ func NewRequest(method, url string, body io.Reader) (*Request, os.Error) {
 		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())
+		default:
+			req.ContentLength = -1 // chunked
+		}
+	}
+
 	return req, nil
 }
 
@@ -485,9 +500,7 @@ func NewRequest(method, url string, body io.Reader) (*Request, os.Error) {
 // are not encrypted.
 func (r *Request) SetBasicAuth(username, password string) {
 	s := username + ":" + password
-	buf := make([]byte, base64.StdEncoding.EncodedLen(len(s)))
-	base64.StdEncoding.Encode(buf, []byte(s))
-	r.Header.Set("Authorization", "Basic "+string(buf))
+	r.Header.Set("Authorization", "Basic "+base64.StdEncoding.EncodeToString([]byte(s)))
 }
 
 // ReadRequest reads and parses a request from b.
diff --git a/src/pkg/http/requestwrite_test.go b/src/pkg/http/requestwrite_test.go
index beb51fb..2889048 100644
--- a/src/pkg/http/requestwrite_test.go
+++ b/src/pkg/http/requestwrite_test.go
@@ -175,6 +175,35 @@ var reqWriteTests = []reqWriteTest{
 			"abcdef",
 	},
 
+	// HTTP/1.1 POST with Content-Length in headers
+	{
+		Request{
+			Method: "POST",
+			RawURL: "http://example.com/",
+			Host:   "example.com",
+			Header: Header{
+				"Content-Length": []string{"10"}, // ignored
+			},
+			ContentLength: 6,
+		},
+
+		[]byte("abcdef"),
+
+		"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",
+
+		"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
 	{
 		Request{
diff --git a/src/pkg/http/reverseproxy.go b/src/pkg/http/reverseproxy.go
index e4ce1e3..9a9e215 100644
--- a/src/pkg/http/reverseproxy.go
+++ b/src/pkg/http/reverseproxy.go
@@ -92,6 +92,10 @@ func (p *ReverseProxy) ServeHTTP(rw ResponseWriter, req *Request) {
 		}
 	}
 
+	for _, cookie := range res.SetCookie {
+		SetCookie(rw, cookie)
+	}
+
 	rw.WriteHeader(res.StatusCode)
 
 	if res.Body != nil {
diff --git a/src/pkg/http/reverseproxy_test.go b/src/pkg/http/reverseproxy_test.go
index 162000e..d7bcde9 100644
--- a/src/pkg/http/reverseproxy_test.go
+++ b/src/pkg/http/reverseproxy_test.go
@@ -20,7 +20,11 @@ func TestReverseProxy(t *testing.T) {
 		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))
 	}))
@@ -33,7 +37,9 @@ func TestReverseProxy(t *testing.T) {
 	frontend := httptest.NewServer(proxyHandler)
 	defer frontend.Close()
 
-	res, err := Get(frontend.URL)
+	getReq, _ := NewRequest("GET", frontend.URL, nil)
+	getReq.Host = "some-name"
+	res, err := DefaultClient.Do(getReq)
 	if err != nil {
 		t.Fatalf("Get: %v", err)
 	}
@@ -43,6 +49,12 @@ func TestReverseProxy(t *testing.T) {
 	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.SetCookie), 1; g != e {
+		t.Fatalf("got %d SetCookies, want %d", g, e)
+	}
+	if cookie := res.SetCookie[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
index 120a026..c923c8a 100644
--- a/src/pkg/http/serve_test.go
+++ b/src/pkg/http/serve_test.go
@@ -13,6 +13,7 @@ import (
 	. "http"
 	"http/httptest"
 	"io/ioutil"
+	"log"
 	"os"
 	"net"
 	"reflect"
@@ -432,6 +433,9 @@ func TestSetsRemoteAddr(t *testing.T) {
 }
 
 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.")
@@ -754,3 +758,43 @@ func TestZeroLengthPostAndResponse(t *testing.T) {
 		}
 	}
 }
+
+func TestHandlerPanic(t *testing.T) {
+	log.SetOutput(ioutil.Discard) // is noisy otherwise
+	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")
+	}
+}
+
+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
index eb5a3a3..93d9d2f 100644
--- a/src/pkg/http/server.go
+++ b/src/pkg/http/server.go
@@ -6,12 +6,12 @@
 
 // TODO(rsc):
 //	logging
-//	post support
 
 package http
 
 import (
 	"bufio"
+	"bytes"
 	"crypto/rand"
 	"crypto/tls"
 	"fmt"
@@ -20,6 +20,7 @@ import (
 	"net"
 	"os"
 	"path"
+	"runtime"
 	"strconv"
 	"strings"
 	"sync"
@@ -119,6 +120,27 @@ type response struct {
 	closeAfterReply bool
 }
 
+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 {
+		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)
+}
+
 // Create new connection from rwc.
 func newConn(rwc net.Conn, handler Handler) (c *conn, err os.Error) {
 	c = new(conn)
@@ -454,6 +476,33 @@ func (c *conn) close() {
 
 // Serve a new connection.
 func (c *conn) serve() {
+	defer func() {
+		err := recover()
+		if err == nil {
+			return
+		}
+		c.rwc.Close()
+
+		// TODO(rsc,bradfitz): this is boilerplate. move it to runtime.Stack()
+		var buf bytes.Buffer
+		fmt.Fprintf(&buf, "http: panic serving %v: %v\n", c.remoteAddr, err)
+		for i := 1; i < 20; i++ {
+			pc, file, line, ok := runtime.Caller(i)
+			if !ok {
+				break
+			}
+			var name string
+			f := runtime.FuncForPC(pc)
+			if f != nil {
+				name = f.Name()
+			} else {
+				name = fmt.Sprintf("%#x", pc)
+			}
+			fmt.Fprintf(&buf, "  %s %s:%d\n", name, file, line)
+		}
+		log.Print(buf.String())
+	}()
+
 	for {
 		w, err := c.readRequest()
 		if err != nil {
diff --git a/src/pkg/http/spdy/Makefile b/src/pkg/http/spdy/Makefile
index ff70d04..3bec220 100644
--- a/src/pkg/http/spdy/Makefile
+++ b/src/pkg/http/spdy/Makefile
@@ -6,6 +6,8 @@ include ../../../Make.inc
 
 TARG=http/spdy
 GOFILES=\
-	protocol.go\
+	read.go\
+	types.go\
+	write.go\
 
 include ../../../Make.pkg
diff --git a/src/pkg/http/spdy/protocol.go b/src/pkg/http/spdy/protocol.go
deleted file mode 100644
index ad9aa63..0000000
--- a/src/pkg/http/spdy/protocol.go
+++ /dev/null
@@ -1,367 +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 is an incomplete implementation of the SPDY protocol.
-//
-// The implementation follows draft 2 of the spec:
-// https://sites.google.com/a/chromium.org/dev/spdy/spdy-protocol/spdy-protocol-draft2
-package spdy
-
-import (
-	"bytes"
-	"compress/zlib"
-	"encoding/binary"
-	"http"
-	"io"
-	"os"
-	"strconv"
-	"strings"
-	"sync"
-)
-
-// 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
-)
-
-func (t ControlFrameType) String() string {
-	switch t {
-	case TypeSynStream:
-		return "SYN_STREAM"
-	case TypeSynReply:
-		return "SYN_REPLY"
-	case TypeRstStream:
-		return "RST_STREAM"
-	case TypeSettings:
-		return "SETTINGS"
-	case TypeNoop:
-		return "NOOP"
-	case TypePing:
-		return "PING"
-	case TypeGoaway:
-		return "GOAWAY"
-	case TypeHeaders:
-		return "HEADERS"
-	case TypeWindowUpdate:
-		return "WINDOW_UPDATE"
-	}
-	return "Type(" + strconv.Itoa(int(t)) + ")"
-}
-
-type FrameFlags uint8
-
-// Stream frame flags
-const (
-	FlagFin            FrameFlags = 0x01
-	FlagUnidirectional            = 0x02
-)
-
-// SETTINGS frame flags
-const (
-	FlagClearPreviouslyPersistedSettings FrameFlags = 0x01
-)
-
-// MaxDataLength is the maximum number of bytes that can be stored in one frame.
-const MaxDataLength = 1<<24 - 1
-
-// A Frame is a framed message as sent between clients and servers.
-// There are two types of frames: control frames and data frames.
-type Frame struct {
-	Header [4]byte
-	Flags  FrameFlags
-	Data   []byte
-}
-
-// ControlFrame creates a control frame with the given information.
-func ControlFrame(t ControlFrameType, f FrameFlags, data []byte) Frame {
-	return Frame{
-		Header: [4]byte{
-			(Version&0xff00)>>8 | 0x80,
-			(Version & 0x00ff),
-			byte((t & 0xff00) >> 8),
-			byte((t & 0x00ff) >> 0),
-		},
-		Flags: f,
-		Data:  data,
-	}
-}
-
-// DataFrame creates a data frame with the given information.
-func DataFrame(streamId uint32, f FrameFlags, data []byte) Frame {
-	return Frame{
-		Header: [4]byte{
-			byte(streamId & 0x7f000000 >> 24),
-			byte(streamId & 0x00ff0000 >> 16),
-			byte(streamId & 0x0000ff00 >> 8),
-			byte(streamId & 0x000000ff >> 0),
-		},
-		Flags: f,
-		Data:  data,
-	}
-}
-
-// ReadFrame reads an entire frame into memory.
-func ReadFrame(r io.Reader) (f Frame, err os.Error) {
-	_, err = io.ReadFull(r, f.Header[:])
-	if err != nil {
-		return
-	}
-	err = binary.Read(r, binary.BigEndian, &f.Flags)
-	if err != nil {
-		return
-	}
-	var lengthField [3]byte
-	_, err = io.ReadFull(r, lengthField[:])
-	if err != nil {
-		if err == os.EOF {
-			err = io.ErrUnexpectedEOF
-		}
-		return
-	}
-	var length uint32
-	length |= uint32(lengthField[0]) << 16
-	length |= uint32(lengthField[1]) << 8
-	length |= uint32(lengthField[2]) << 0
-	if length > 0 {
-		f.Data = make([]byte, int(length))
-		_, err = io.ReadFull(r, f.Data)
-		if err == os.EOF {
-			err = io.ErrUnexpectedEOF
-		}
-	} else {
-		f.Data = []byte{}
-	}
-	return
-}
-
-// IsControl returns whether the frame holds a control frame.
-func (f Frame) IsControl() bool {
-	return f.Header[0]&0x80 != 0
-}
-
-// Type obtains the type field if the frame is a control frame, otherwise it returns zero.
-func (f Frame) Type() ControlFrameType {
-	if !f.IsControl() {
-		return 0
-	}
-	return (ControlFrameType(f.Header[2])<<8 | ControlFrameType(f.Header[3]))
-}
-
-// StreamId returns the stream ID field if the frame is a data frame, otherwise it returns zero.
-func (f Frame) StreamId() (id uint32) {
-	if f.IsControl() {
-		return 0
-	}
-	id |= uint32(f.Header[0]) << 24
-	id |= uint32(f.Header[1]) << 16
-	id |= uint32(f.Header[2]) << 8
-	id |= uint32(f.Header[3]) << 0
-	return
-}
-
-// WriteTo writes the frame in the SPDY format.
-func (f Frame) WriteTo(w io.Writer) (n int64, err os.Error) {
-	var nn int
-	// Header
-	nn, err = w.Write(f.Header[:])
-	n += int64(nn)
-	if err != nil {
-		return
-	}
-	// Flags
-	nn, err = w.Write([]byte{byte(f.Flags)})
-	n += int64(nn)
-	if err != nil {
-		return
-	}
-	// Length
-	nn, err = w.Write([]byte{
-		byte(len(f.Data) & 0x00ff0000 >> 16),
-		byte(len(f.Data) & 0x0000ff00 >> 8),
-		byte(len(f.Data) & 0x000000ff),
-	})
-	n += int64(nn)
-	if err != nil {
-		return
-	}
-	// Data
-	if len(f.Data) > 0 {
-		nn, err = w.Write(f.Data)
-		n += int64(nn)
-	}
-	return
-}
-
-// 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"
-
-// hrSource is a reader that passes through reads from another reader.
-// When the underlying reader reaches EOF, Read will block until another reader is added via change.
-type hrSource struct {
-	r io.Reader
-	m sync.RWMutex
-	c *sync.Cond
-}
-
-func (src *hrSource) Read(p []byte) (n int, err os.Error) {
-	src.m.RLock()
-	for src.r == nil {
-		src.c.Wait()
-	}
-	n, err = src.r.Read(p)
-	src.m.RUnlock()
-	if err == os.EOF {
-		src.change(nil)
-		err = nil
-	}
-	return
-}
-
-func (src *hrSource) change(r io.Reader) {
-	src.m.Lock()
-	defer src.m.Unlock()
-	src.r = r
-	src.c.Broadcast()
-}
-
-// A HeaderReader reads zlib-compressed headers.
-type HeaderReader struct {
-	source       hrSource
-	decompressor io.ReadCloser
-}
-
-// NewHeaderReader creates a HeaderReader with the initial dictionary.
-func NewHeaderReader() (hr *HeaderReader) {
-	hr = new(HeaderReader)
-	hr.source.c = sync.NewCond(hr.source.m.RLocker())
-	return
-}
-
-// ReadHeader reads a set of headers from a reader.
-func (hr *HeaderReader) ReadHeader(r io.Reader) (h http.Header, err os.Error) {
-	hr.source.change(r)
-	h, err = hr.read()
-	return
-}
-
-// Decode reads a set of headers from a block of bytes.
-func (hr *HeaderReader) Decode(data []byte) (h http.Header, err os.Error) {
-	hr.source.change(bytes.NewBuffer(data))
-	h, err = hr.read()
-	return
-}
-
-func (hr *HeaderReader) read() (h http.Header, err os.Error) {
-	var count uint16
-	if hr.decompressor == nil {
-		hr.decompressor, err = zlib.NewReaderDict(&hr.source, []byte(headerDictionary))
-		if err != nil {
-			return
-		}
-	}
-	err = binary.Read(hr.decompressor, binary.BigEndian, &count)
-	if err != nil {
-		return
-	}
-	h = make(http.Header, int(count))
-	for i := 0; i < int(count); i++ {
-		var name, value string
-		name, err = readHeaderString(hr.decompressor)
-		if err != nil {
-			return
-		}
-		value, err = readHeaderString(hr.decompressor)
-		if err != nil {
-			return
-		}
-		valueList := strings.Split(string(value), "\x00", -1)
-		for _, v := range valueList {
-			h.Add(name, v)
-		}
-	}
-	return
-}
-
-func readHeaderString(r io.Reader) (s string, err os.Error) {
-	var length uint16
-	err = binary.Read(r, binary.BigEndian, &length)
-	if err != nil {
-		return
-	}
-	data := make([]byte, int(length))
-	_, err = io.ReadFull(r, data)
-	if err != nil {
-		return
-	}
-	return string(data), nil
-}
-
-// HeaderWriter will write zlib-compressed headers on different streams.
-type HeaderWriter struct {
-	compressor *zlib.Writer
-	buffer     *bytes.Buffer
-}
-
-// NewHeaderWriter creates a HeaderWriter ready to compress headers.
-func NewHeaderWriter(level int) (hw *HeaderWriter) {
-	hw = &HeaderWriter{buffer: new(bytes.Buffer)}
-	hw.compressor, _ = zlib.NewWriterDict(hw.buffer, level, []byte(headerDictionary))
-	return
-}
-
-// WriteHeader writes a header block directly to an output.
-func (hw *HeaderWriter) WriteHeader(w io.Writer, h http.Header) (err os.Error) {
-	hw.write(h)
-	_, err = io.Copy(w, hw.buffer)
-	hw.buffer.Reset()
-	return
-}
-
-// Encode returns a compressed header block.
-func (hw *HeaderWriter) Encode(h http.Header) (data []byte) {
-	hw.write(h)
-	data = make([]byte, hw.buffer.Len())
-	hw.buffer.Read(data)
-	return
-}
-
-func (hw *HeaderWriter) write(h http.Header) {
-	binary.Write(hw.compressor, binary.BigEndian, uint16(len(h)))
-	for k, vals := range h {
-		k = strings.ToLower(k)
-		binary.Write(hw.compressor, binary.BigEndian, uint16(len(k)))
-		binary.Write(hw.compressor, binary.BigEndian, []byte(k))
-		v := strings.Join(vals, "\x00")
-		binary.Write(hw.compressor, binary.BigEndian, uint16(len(v)))
-		binary.Write(hw.compressor, binary.BigEndian, []byte(v))
-	}
-	hw.compressor.Flush()
-}
diff --git a/src/pkg/http/spdy/protocol_test.go b/src/pkg/http/spdy/protocol_test.go
deleted file mode 100644
index 998ff99..0000000
--- a/src/pkg/http/spdy/protocol_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 spdy
-
-import (
-	"bytes"
-	"compress/zlib"
-	"http"
-	"os"
-	"testing"
-)
-
-type frameIoTest struct {
-	desc      string
-	data      []byte
-	frame     Frame
-	readError os.Error
-	readOnly  bool
-}
-
-var frameIoTests = []frameIoTest{
-	{
-		"noop frame",
-		[]byte{
-			0x80, 0x02, 0x00, 0x05,
-			0x00, 0x00, 0x00, 0x00,
-		},
-		ControlFrame(
-			TypeNoop,
-			0x00,
-			[]byte{},
-		),
-		nil,
-		false,
-	},
-	{
-		"ping frame",
-		[]byte{
-			0x80, 0x02, 0x00, 0x06,
-			0x00, 0x00, 0x00, 0x04,
-			0x00, 0x00, 0x00, 0x01,
-		},
-		ControlFrame(
-			TypePing,
-			0x00,
-			[]byte{0x00, 0x00, 0x00, 0x01},
-		),
-		nil,
-		false,
-	},
-	{
-		"syn_stream frame",
-		[]byte{
-			0x80, 0x02, 0x00, 0x01,
-			0x01, 0x00, 0x00, 0x53,
-			0x00, 0x00, 0x00, 0x01,
-			0x00, 0x00, 0x00, 0x00,
-			0x00, 0x00, 0x78, 0xbb,
-			0xdf, 0xa2, 0x51, 0xb2,
-			0x62, 0x60, 0x66, 0x60,
-			0xcb, 0x4d, 0x2d, 0xc9,
-			0xc8, 0x4f, 0x61, 0x60,
-			0x4e, 0x4f, 0x2d, 0x61,
-			0x60, 0x2e, 0x2d, 0xca,
-			0x61, 0x10, 0xcb, 0x28,
-			0x29, 0x29, 0xb0, 0xd2,
-			0xd7, 0x2f, 0x2f, 0x2f,
-			0xd7, 0x4b, 0xcf, 0xcf,
-			0x4f, 0xcf, 0x49, 0xd5,
-			0x4b, 0xce, 0xcf, 0xd5,
-			0x67, 0x60, 0x2f, 0x4b,
-			0x2d, 0x2a, 0xce, 0xcc,
-			0xcf, 0x63, 0xe0, 0x00,
-			0x29, 0xd0, 0x37, 0xd4,
-			0x33, 0x04, 0x00, 0x00,
-			0x00, 0xff, 0xff,
-		},
-		ControlFrame(
-			TypeSynStream,
-			0x01,
-			[]byte{
-				0x00, 0x00, 0x00, 0x01,
-				0x00, 0x00, 0x00, 0x00,
-				0x00, 0x00, 0x78, 0xbb,
-				0xdf, 0xa2, 0x51, 0xb2,
-				0x62, 0x60, 0x66, 0x60,
-				0xcb, 0x4d, 0x2d, 0xc9,
-				0xc8, 0x4f, 0x61, 0x60,
-				0x4e, 0x4f, 0x2d, 0x61,
-				0x60, 0x2e, 0x2d, 0xca,
-				0x61, 0x10, 0xcb, 0x28,
-				0x29, 0x29, 0xb0, 0xd2,
-				0xd7, 0x2f, 0x2f, 0x2f,
-				0xd7, 0x4b, 0xcf, 0xcf,
-				0x4f, 0xcf, 0x49, 0xd5,
-				0x4b, 0xce, 0xcf, 0xd5,
-				0x67, 0x60, 0x2f, 0x4b,
-				0x2d, 0x2a, 0xce, 0xcc,
-				0xcf, 0x63, 0xe0, 0x00,
-				0x29, 0xd0, 0x37, 0xd4,
-				0x33, 0x04, 0x00, 0x00,
-				0x00, 0xff, 0xff,
-			},
-		),
-		nil,
-		false,
-	},
-	{
-		"data frame",
-		[]byte{
-			0x00, 0x00, 0x00, 0x05,
-			0x01, 0x00, 0x00, 0x04,
-			0x01, 0x02, 0x03, 0x04,
-		},
-		DataFrame(
-			5,
-			0x01,
-			[]byte{0x01, 0x02, 0x03, 0x04},
-		),
-		nil,
-		false,
-	},
-	{
-		"too much data",
-		[]byte{
-			0x00, 0x00, 0x00, 0x05,
-			0x01, 0x00, 0x00, 0x04,
-			0x01, 0x02, 0x03, 0x04,
-			0x05, 0x06, 0x07, 0x08,
-		},
-		DataFrame(
-			5,
-			0x01,
-			[]byte{0x01, 0x02, 0x03, 0x04},
-		),
-		nil,
-		true,
-	},
-	{
-		"not enough data",
-		[]byte{
-			0x00, 0x00, 0x00, 0x05,
-		},
-		Frame{},
-		os.EOF,
-		true,
-	},
-}
-
-func TestReadFrame(t *testing.T) {
-	for _, tt := range frameIoTests {
-		f, err := ReadFrame(bytes.NewBuffer(tt.data))
-		if err != tt.readError {
-			t.Errorf("%s: ReadFrame: %s", tt.desc, err)
-			continue
-		}
-		if err == nil {
-			if !bytes.Equal(f.Header[:], tt.frame.Header[:]) {
-				t.Errorf("%s: header %q != %q", tt.desc, string(f.Header[:]), string(tt.frame.Header[:]))
-			}
-			if f.Flags != tt.frame.Flags {
-				t.Errorf("%s: flags %#02x != %#02x", tt.desc, f.Flags, tt.frame.Flags)
-			}
-			if !bytes.Equal(f.Data, tt.frame.Data) {
-				t.Errorf("%s: data %q != %q", tt.desc, string(f.Data), string(tt.frame.Data))
-			}
-		}
-	}
-}
-
-func TestWriteTo(t *testing.T) {
-	for _, tt := range frameIoTests {
-		if tt.readOnly {
-			continue
-		}
-		b := new(bytes.Buffer)
-		_, err := tt.frame.WriteTo(b)
-		if err != nil {
-			t.Errorf("%s: WriteTo: %s", tt.desc, err)
-		}
-		if !bytes.Equal(b.Bytes(), tt.data) {
-			t.Errorf("%s: data %q != %q", tt.desc, string(b.Bytes()), string(tt.data))
-		}
-	}
-}
-
-var headerDataTest = []byte{
-	0x78, 0xbb, 0xdf, 0xa2,
-	0x51, 0xb2, 0x62, 0x60,
-	0x66, 0x60, 0xcb, 0x4d,
-	0x2d, 0xc9, 0xc8, 0x4f,
-	0x61, 0x60, 0x4e, 0x4f,
-	0x2d, 0x61, 0x60, 0x2e,
-	0x2d, 0xca, 0x61, 0x10,
-	0xcb, 0x28, 0x29, 0x29,
-	0xb0, 0xd2, 0xd7, 0x2f,
-	0x2f, 0x2f, 0xd7, 0x4b,
-	0xcf, 0xcf, 0x4f, 0xcf,
-	0x49, 0xd5, 0x4b, 0xce,
-	0xcf, 0xd5, 0x67, 0x60,
-	0x2f, 0x4b, 0x2d, 0x2a,
-	0xce, 0xcc, 0xcf, 0x63,
-	0xe0, 0x00, 0x29, 0xd0,
-	0x37, 0xd4, 0x33, 0x04,
-	0x00, 0x00, 0x00, 0xff,
-	0xff,
-}
-
-func TestReadHeader(t *testing.T) {
-	r := NewHeaderReader()
-	h, err := r.Decode(headerDataTest)
-	if err != nil {
-		t.Fatalf("Error: %v", err)
-		return
-	}
-	if len(h) != 3 {
-		t.Errorf("Header count = %d (expected 3)", len(h))
-	}
-	if h.Get("Url") != "http://www.google.com/" {
-		t.Errorf("Url: %q != %q", h.Get("Url"), "http://www.google.com/")
-	}
-	if h.Get("Method") != "get" {
-		t.Errorf("Method: %q != %q", h.Get("Method"), "get")
-	}
-	if h.Get("Version") != "http/1.1" {
-		t.Errorf("Version: %q != %q", h.Get("Version"), "http/1.1")
-	}
-}
-
-func TestWriteHeader(t *testing.T) {
-	for level := zlib.NoCompression; level <= zlib.BestCompression; level++ {
-		r := NewHeaderReader()
-		w := NewHeaderWriter(level)
-		for i := 0; i < 100; i++ {
-			b := new(bytes.Buffer)
-			gold := http.Header{
-				"Url":     []string{"http://www.google.com/"},
-				"Method":  []string{"get"},
-				"Version": []string{"http/1.1"},
-			}
-			w.WriteHeader(b, gold)
-			h, err := r.Decode(b.Bytes())
-			if err != nil {
-				t.Errorf("(level=%d i=%d) Error: %v", level, i, err)
-				return
-			}
-			if len(h) != len(gold) {
-				t.Errorf("(level=%d i=%d) Header count = %d (expected %d)", level, i, len(h), len(gold))
-			}
-			for k, _ := range h {
-				if h.Get(k) != gold.Get(k) {
-					t.Errorf("(level=%d i=%d) %s: %q != %q", level, i, k, h.Get(k), gold.Get(k))
-				}
-			}
-		}
-	}
-}
diff --git a/src/pkg/http/spdy/read.go b/src/pkg/http/spdy/read.go
new file mode 100644
index 0000000..159dbc5
--- /dev/null
+++ b/src/pkg/http/spdy/read.go
@@ -0,0 +1,287 @@
+// Copyright 2011 The Go Authors. 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, 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
+}
+
+type corkedReader struct {
+	r  io.Reader
+	ch chan int
+	n  int
+}
+
+func (cr *corkedReader) Read(p []byte) (int, os.Error) {
+	if cr.n == 0 {
+		cr.n = <-cr.ch
+	}
+	if len(p) > cr.n {
+		p = p[:cr.n]
+	}
+	n, err := cr.r.Read(p)
+	cr.n -= n
+	return n, err
+}
+
+func (f *Framer) uncorkHeaderDecompressor(payloadSize int) os.Error {
+	if f.headerDecompressor != nil {
+		f.headerReader.ch <- payloadSize
+		return nil
+	}
+	f.headerReader = corkedReader{r: f.r, ch: make(chan int, 1), 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) (http.Header, os.Error) {
+	var numHeaders uint16
+	if err := binary.Read(r, binary.BigEndian, &numHeaders); err != nil {
+		return nil, err
+	}
+	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) {
+			return nil, UnlowercasedHeaderName
+		}
+		if h[name] != nil {
+			return nil, DuplicateHeaders
+		}
+		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", -1)
+		for _, v := range valueList {
+			h.Add(name, v)
+		}
+	}
+	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(int(h.length - 10))
+		reader = f.headerDecompressor
+	}
+
+	frame.Headers, err = parseHeaderValueBlock(reader)
+	if err != nil {
+		return err
+	}
+	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(int(h.length - 6))
+		reader = f.headerDecompressor
+	}
+	frame.Headers, err = parseHeaderValueBlock(reader)
+	if err != nil {
+		return err
+	}
+	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(int(h.length - 6))
+		reader = f.headerDecompressor
+	}
+	frame.Headers, err = parseHeaderValueBlock(reader)
+	if err != nil {
+		return err
+	}
+	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)
+	// TODO(willchan): Support compressed data frames.
+	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
new file mode 100644
index 0000000..9100e1e
--- /dev/null
+++ b/src/pkg/http/spdy/spdy_test.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.
+
+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)
+
+	newHeaders, err := parseHeaderValueBlock(&headerValueBlockBuf)
+	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
new file mode 100644
index 0000000..5a665f0
--- /dev/null
+++ b/src/pkg/http/spdy/types.go
@@ -0,0 +1,363 @@
+// Copyright 2011 The Go Authors. 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"
+	"strconv"
+)
+
+//  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"
+
+type FramerError int
+
+const (
+	Internal FramerError = iota
+	InvalidControlFrame
+	UnlowercasedHeaderName
+	DuplicateHeaders
+	UnknownFrameType
+	InvalidDataFrame
+)
+
+func (e FramerError) String() string {
+	switch e {
+	case Internal:
+		return "Internal"
+	case InvalidControlFrame:
+		return "InvalidControlFrame"
+	case UnlowercasedHeaderName:
+		return "UnlowercasedHeaderName"
+	case DuplicateHeaders:
+		return "DuplicateHeaders"
+	case UnknownFrameType:
+		return "UnknownFrameType"
+	case InvalidDataFrame:
+		return "InvalidDataFrame"
+	}
+	return "Error(" + strconv.Itoa(int(e)) + ")"
+}
+
+// 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              corkedReader
+	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
new file mode 100644
index 0000000..aa1679f
--- /dev/null
+++ b/src/pkg/http/spdy/write.go
@@ -0,0 +1,287 @@
+// Copyright 2011 The Go Authors. 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 InvalidDataFrame
+	}
+
+	// TODO(willchan): Support data compression.
+	// 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/transport.go b/src/pkg/http/transport.go
index 34bfbdd..c907d85 100644
--- a/src/pkg/http/transport.go
+++ b/src/pkg/http/transport.go
@@ -36,17 +36,23 @@ const DefaultMaxIdleConnsPerHost = 2
 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 optionally 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 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, 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)
+
 	DisableKeepAlives  bool
 	DisableCompression bool
 
@@ -97,7 +103,16 @@ func (t *Transport) RoundTrip(req *Request) (resp *Response, err os.Error) {
 		}
 	}
 	if req.URL.Scheme != "http" && req.URL.Scheme != "https" {
-		return nil, &badStringError{"unsupported protocol scheme", req.URL.Scheme}
+		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)
@@ -117,6 +132,27 @@ func (t *Transport) RoundTrip(req *Request) (resp *Response, err os.Error) {
 	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
@@ -169,10 +205,7 @@ func (cm *connectMethod) proxyAuth() string {
 	}
 	proxyInfo := cm.proxyURL.RawUserinfo
 	if proxyInfo != "" {
-		enc := base64.URLEncoding
-		encoded := make([]byte, enc.EncodedLen(len(proxyInfo)))
-		enc.Encode(encoded, []byte(proxyInfo))
-		return "Basic " + string(encoded)
+		return "Basic " + base64.URLEncoding.EncodeToString([]byte(proxyInfo))
 	}
 	return ""
 }
@@ -227,6 +260,13 @@ func (t *Transport) getIdleConn(cm *connectMethod) (pconn *persistConn) {
 	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
@@ -236,7 +276,7 @@ func (t *Transport) getConn(cm *connectMethod) (*persistConn, os.Error) {
 		return pc, nil
 	}
 
-	conn, err := net.Dial("tcp", cm.addr())
+	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)
diff --git a/src/pkg/http/transport_test.go b/src/pkg/http/transport_test.go
index 9cd18ff..76e9764 100644
--- a/src/pkg/http/transport_test.go
+++ b/src/pkg/http/transport_test.go
@@ -17,6 +17,7 @@ import (
 	"io/ioutil"
 	"os"
 	"strconv"
+	"strings"
 	"testing"
 	"time"
 )
@@ -531,6 +532,36 @@ func TestTransportGzipRecursive(t *testing.T) {
 	}
 }
 
+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,
diff --git a/src/pkg/image/gif/reader.go b/src/pkg/image/gif/reader.go
index 5dd4040..9f7296a 100644
--- a/src/pkg/image/gif/reader.go
+++ b/src/pkg/image/gif/reader.go
@@ -94,28 +94,26 @@ type blockReader struct {
 	tmp   [256]byte
 }
 
-func (b *blockReader) Read(p []byte) (n int, err os.Error) {
+func (b *blockReader) Read(p []byte) (int, os.Error) {
 	if len(p) == 0 {
-		return
-	}
-	if len(b.slice) > 0 {
-		n = copy(p, b.slice)
-		b.slice = b.slice[n:]
-		return
-	}
-	var blockLen uint8
-	blockLen, err = b.r.ReadByte()
-	if err != nil {
-		return
+		return 0, nil
 	}
-	if blockLen == 0 {
-		return 0, os.EOF
-	}
-	b.slice = b.tmp[0:blockLen]
-	if _, err = io.ReadFull(b.r, b.slice); err != nil {
-		return
+	if len(b.slice) == 0 {
+		blockLen, err := b.r.ReadByte()
+		if err != nil {
+			return 0, err
+		}
+		if blockLen == 0 {
+			return 0, os.EOF
+		}
+		b.slice = b.tmp[0:blockLen]
+		if _, err = io.ReadFull(b.r, b.slice); err != nil {
+			return 0, err
+		}
 	}
-	return b.Read(p)
+	n := copy(p, b.slice)
+	b.slice = b.slice[n:]
+	return n, nil
 }
 
 // decode reads a GIF image from r and stores the result in d.
@@ -364,7 +362,7 @@ func (d *decoder) uninterlace(m *image.Paletted) {
 	dx := d.width
 	dy := d.height
 	nPix = make([]uint8, dx*dy)
-	offset := 0 // steps through the input by sequentical scan lines.
+	offset := 0 // steps through the input by sequential scan lines.
 	for _, pass := range interlacing {
 		nOffset := pass.start * dx // steps through the output as defined by pass.
 		for y := pass.start; y < dy; y += pass.skip {
diff --git a/src/pkg/image/image.go b/src/pkg/image/image.go
index 4350acc..1bdac36 100644
--- a/src/pkg/image/image.go
+++ b/src/pkg/image/image.go
@@ -58,6 +58,16 @@ func (p *RGBA) SetRGBA(x, y int, c RGBAColor) {
 	p.Pix[y*p.Stride+x] = c
 }
 
+// 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 *RGBA) SubImage(r Rectangle) Image {
+	return &RGBA{
+		Pix:    p.Pix,
+		Stride: p.Stride,
+		Rect:   p.Rect.Intersect(r),
+	}
+}
+
 // Opaque scans the entire image and returns whether or not it is fully opaque.
 func (p *RGBA) Opaque() bool {
 	if p.Rect.Empty() {
@@ -117,6 +127,16 @@ func (p *RGBA64) SetRGBA64(x, y int, c RGBA64Color) {
 	p.Pix[y*p.Stride+x] = c
 }
 
+// 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 *RGBA64) SubImage(r Rectangle) Image {
+	return &RGBA64{
+		Pix:    p.Pix,
+		Stride: p.Stride,
+		Rect:   p.Rect.Intersect(r),
+	}
+}
+
 // Opaque scans the entire image and returns whether or not it is fully opaque.
 func (p *RGBA64) Opaque() bool {
 	if p.Rect.Empty() {
@@ -176,6 +196,16 @@ func (p *NRGBA) SetNRGBA(x, y int, c NRGBAColor) {
 	p.Pix[y*p.Stride+x] = c
 }
 
+// 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 *NRGBA) SubImage(r Rectangle) Image {
+	return &NRGBA{
+		Pix:    p.Pix,
+		Stride: p.Stride,
+		Rect:   p.Rect.Intersect(r),
+	}
+}
+
 // Opaque scans the entire image and returns whether or not it is fully opaque.
 func (p *NRGBA) Opaque() bool {
 	if p.Rect.Empty() {
@@ -235,6 +265,16 @@ func (p *NRGBA64) SetNRGBA64(x, y int, c NRGBA64Color) {
 	p.Pix[y*p.Stride+x] = c
 }
 
+// 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 *NRGBA64) SubImage(r Rectangle) Image {
+	return &NRGBA64{
+		Pix:    p.Pix,
+		Stride: p.Stride,
+		Rect:   p.Rect.Intersect(r),
+	}
+}
+
 // Opaque scans the entire image and returns whether or not it is fully opaque.
 func (p *NRGBA64) Opaque() bool {
 	if p.Rect.Empty() {
@@ -294,6 +334,16 @@ func (p *Alpha) SetAlpha(x, y int, c AlphaColor) {
 	p.Pix[y*p.Stride+x] = c
 }
 
+// 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 *Alpha) SubImage(r Rectangle) Image {
+	return &Alpha{
+		Pix:    p.Pix,
+		Stride: p.Stride,
+		Rect:   p.Rect.Intersect(r),
+	}
+}
+
 // Opaque scans the entire image and returns whether or not it is fully opaque.
 func (p *Alpha) Opaque() bool {
 	if p.Rect.Empty() {
@@ -353,6 +403,16 @@ func (p *Alpha16) SetAlpha16(x, y int, c Alpha16Color) {
 	p.Pix[y*p.Stride+x] = c
 }
 
+// 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 *Alpha16) SubImage(r Rectangle) Image {
+	return &Alpha16{
+		Pix:    p.Pix,
+		Stride: p.Stride,
+		Rect:   p.Rect.Intersect(r),
+	}
+}
+
 // Opaque scans the entire image and returns whether or not it is fully opaque.
 func (p *Alpha16) Opaque() bool {
 	if p.Rect.Empty() {
@@ -412,6 +472,16 @@ func (p *Gray) SetGray(x, y int, c GrayColor) {
 	p.Pix[y*p.Stride+x] = c
 }
 
+// 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 *Gray) SubImage(r Rectangle) Image {
+	return &Gray{
+		Pix:    p.Pix,
+		Stride: p.Stride,
+		Rect:   p.Rect.Intersect(r),
+	}
+}
+
 // Opaque scans the entire image and returns whether or not it is fully opaque.
 func (p *Gray) Opaque() bool {
 	return true
@@ -457,6 +527,16 @@ func (p *Gray16) SetGray16(x, y int, c Gray16Color) {
 	p.Pix[y*p.Stride+x] = c
 }
 
+// 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 *Gray16) SubImage(r Rectangle) Image {
+	return &Gray16{
+		Pix:    p.Pix,
+		Stride: p.Stride,
+		Rect:   p.Rect.Intersect(r),
+	}
+}
+
 // Opaque scans the entire image and returns whether or not it is fully opaque.
 func (p *Gray16) Opaque() bool {
 	return true
@@ -544,6 +624,17 @@ func (p *Paletted) SetColorIndex(x, y int, index uint8) {
 	p.Pix[y*p.Stride+x] = index
 }
 
+// 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 *Paletted) SubImage(r Rectangle) Image {
+	return &Paletted{
+		Pix:     p.Pix,
+		Stride:  p.Stride,
+		Rect:    p.Rect.Intersect(r),
+		Palette: p.Palette,
+	}
+}
+
 // Opaque scans the entire image and returns whether or not it is fully opaque.
 func (p *Paletted) Opaque() bool {
 	for _, c := range p.Palette {
diff --git a/src/pkg/image/png/writer.go b/src/pkg/image/png/writer.go
index a27586f..d770cfa 100644
--- a/src/pkg/image/png/writer.go
+++ b/src/pkg/image/png/writer.go
@@ -174,7 +174,7 @@ func (e *encoder) Write(b []byte) (int, os.Error) {
 
 // Chooses the filter to use for encoding the current row, and applies it.
 // The return value is the index of the filter and also of the row in cr that has had it applied.
-func filter(cr [][]byte, pr []byte, bpp int) int {
+func filter(cr *[nFilter][]byte, pr []byte, bpp int) int {
 	// We try all five filter types, and pick the one that minimizes the sum of absolute differences.
 	// This is the same heuristic that libpng uses, although the filters are attempted in order of
 	// estimated most likely to be minimal (ftUp, ftPaeth, ftNone, ftSub, ftAverage), rather than
@@ -304,7 +304,7 @@ func writeImage(w io.Writer, m image.Image, cb int) os.Error {
 	// The +1 is for the per-row filter type, which is at cr[*][0].
 	b := m.Bounds()
 	var cr [nFilter][]uint8
-	for i := 0; i < len(cr); i++ {
+	for i := range cr {
 		cr[i] = make([]uint8, 1+bpp*b.Dx())
 		cr[i][0] = uint8(i)
 	}
@@ -312,78 +312,84 @@ func writeImage(w io.Writer, m image.Image, cb int) os.Error {
 
 	for y := b.Min.Y; y < b.Max.Y; y++ {
 		// Convert from colors to bytes.
+		i := 1
 		switch cb {
 		case cbG8:
 			for x := b.Min.X; x < b.Max.X; x++ {
 				c := image.GrayColorModel.Convert(m.At(x, y)).(image.GrayColor)
-				cr[0][x+1] = c.Y
+				cr[0][i] = c.Y
+				i++
 			}
 		case cbTC8:
 			// We have previously verified that the alpha value is fully opaque.
 			cr0 := cr[0]
 			if rgba != nil {
 				yoff := y * rgba.Stride
-				xoff := 3*b.Min.X + 1
 				for _, color := range rgba.Pix[yoff+b.Min.X : yoff+b.Max.X] {
-					cr0[xoff] = color.R
-					cr0[xoff+1] = color.G
-					cr0[xoff+2] = color.B
-					xoff += 3
+					cr0[i+0] = color.R
+					cr0[i+1] = color.G
+					cr0[i+2] = color.B
+					i += 3
 				}
 			} else {
 				for x := b.Min.X; x < b.Max.X; x++ {
 					r, g, b, _ := m.At(x, y).RGBA()
-					cr0[3*x+1] = uint8(r >> 8)
-					cr0[3*x+2] = uint8(g >> 8)
-					cr0[3*x+3] = uint8(b >> 8)
+					cr0[i+0] = uint8(r >> 8)
+					cr0[i+1] = uint8(g >> 8)
+					cr0[i+2] = uint8(b >> 8)
+					i += 3
 				}
 			}
 		case cbP8:
 			rowOffset := y * paletted.Stride
-			copy(cr[0][b.Min.X+1:], paletted.Pix[rowOffset+b.Min.X:rowOffset+b.Max.X])
+			copy(cr[0][1:], paletted.Pix[rowOffset+b.Min.X:rowOffset+b.Max.X])
 		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)
-				cr[0][4*x+1] = c.R
-				cr[0][4*x+2] = c.G
-				cr[0][4*x+3] = c.B
-				cr[0][4*x+4] = c.A
+				cr[0][i+0] = c.R
+				cr[0][i+1] = c.G
+				cr[0][i+2] = c.B
+				cr[0][i+3] = c.A
+				i += 4
 			}
 		case cbG16:
 			for x := b.Min.X; x < b.Max.X; x++ {
 				c := image.Gray16ColorModel.Convert(m.At(x, y)).(image.Gray16Color)
-				cr[0][2*x+1] = uint8(c.Y >> 8)
-				cr[0][2*x+2] = uint8(c.Y)
+				cr[0][i+0] = uint8(c.Y >> 8)
+				cr[0][i+1] = uint8(c.Y)
+				i += 2
 			}
 		case cbTC16:
+			// We have previously verified that the alpha value is fully opaque.
 			for x := b.Min.X; x < b.Max.X; x++ {
-				// We have previously verified that the alpha value is fully opaque.
 				r, g, b, _ := m.At(x, y).RGBA()
-				cr[0][6*x+1] = uint8(r >> 8)
-				cr[0][6*x+2] = uint8(r)
-				cr[0][6*x+3] = uint8(g >> 8)
-				cr[0][6*x+4] = uint8(g)
-				cr[0][6*x+5] = uint8(b >> 8)
-				cr[0][6*x+6] = uint8(b)
+				cr[0][i+0] = uint8(r >> 8)
+				cr[0][i+1] = uint8(r)
+				cr[0][i+2] = uint8(g >> 8)
+				cr[0][i+3] = uint8(g)
+				cr[0][i+4] = uint8(b >> 8)
+				cr[0][i+5] = uint8(b)
+				i += 6
 			}
 		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)
-				cr[0][8*x+1] = uint8(c.R >> 8)
-				cr[0][8*x+2] = uint8(c.R)
-				cr[0][8*x+3] = uint8(c.G >> 8)
-				cr[0][8*x+4] = uint8(c.G)
-				cr[0][8*x+5] = uint8(c.B >> 8)
-				cr[0][8*x+6] = uint8(c.B)
-				cr[0][8*x+7] = uint8(c.A >> 8)
-				cr[0][8*x+8] = uint8(c.A)
+				cr[0][i+0] = uint8(c.R >> 8)
+				cr[0][i+1] = uint8(c.R)
+				cr[0][i+2] = uint8(c.G >> 8)
+				cr[0][i+3] = uint8(c.G)
+				cr[0][i+4] = uint8(c.B >> 8)
+				cr[0][i+5] = uint8(c.B)
+				cr[0][i+6] = uint8(c.A >> 8)
+				cr[0][i+7] = uint8(c.A)
+				i += 8
 			}
 		}
 
 		// Apply the filter.
-		f := filter(cr[0:nFilter], pr, bpp)
+		f := filter(&cr, pr, bpp)
 
 		// Write the compressed bytes.
 		_, err = zw.Write(cr[f])
diff --git a/src/pkg/image/png/writer_test.go b/src/pkg/image/png/writer_test.go
index 6b054aa..271519a 100644
--- a/src/pkg/image/png/writer_test.go
+++ b/src/pkg/image/png/writer_test.go
@@ -5,9 +5,9 @@
 package png
 
 import (
+	"bytes"
 	"fmt"
 	"image"
-	"io"
 	"io/ioutil"
 	"os"
 	"testing"
@@ -15,21 +15,38 @@ import (
 
 func diff(m0, m1 image.Image) os.Error {
 	b0, b1 := m0.Bounds(), m1.Bounds()
-	if !b0.Eq(b1) {
+	if !b0.Size().Eq(b1.Size()) {
 		return fmt.Errorf("dimensions differ: %v vs %v", b0, b1)
 	}
+	dx := b1.Min.X - b0.Min.X
+	dy := b1.Min.Y - b0.Min.Y
 	for y := b0.Min.Y; y < b0.Max.Y; y++ {
 		for x := b0.Min.X; x < b0.Max.X; x++ {
-			r0, g0, b0, a0 := m0.At(x, y).RGBA()
-			r1, g1, b1, a1 := m1.At(x, y).RGBA()
+			c0 := m0.At(x, y)
+			c1 := m1.At(x+dx, y+dy)
+			r0, g0, b0, a0 := c0.RGBA()
+			r1, g1, b1, a1 := c1.RGBA()
 			if r0 != r1 || g0 != g1 || b0 != b1 || a0 != a1 {
-				return fmt.Errorf("colors differ at (%d, %d): %v vs %v", x, y, m0.At(x, y), m1.At(x, y))
+				return fmt.Errorf("colors differ at (%d, %d): %v vs %v", x, y, c0, c1)
 			}
 		}
 	}
 	return nil
 }
 
+func encodeDecode(m image.Image) (image.Image, os.Error) {
+	b := bytes.NewBuffer(nil)
+	err := Encode(b, m)
+	if err != nil {
+		return nil, err
+	}
+	m, err = Decode(b)
+	if err != nil {
+		return nil, err
+	}
+	return m, nil
+}
+
 func TestWriter(t *testing.T) {
 	// The filenames variable is declared in reader_test.go.
 	names := filenames
@@ -44,26 +61,16 @@ func TestWriter(t *testing.T) {
 			t.Error(fn, err)
 			continue
 		}
-		// Read the image again, and push it through a pipe that encodes at the write end, and decodes at the read end.
-		pr, pw := io.Pipe()
-		defer pr.Close()
-		go func() {
-			defer pw.Close()
-			m1, err := readPng(qfn)
-			if err != nil {
-				t.Error(fn, err)
-				return
-			}
-			err = Encode(pw, m1)
-			if err != nil {
-				t.Error(fn, err)
-				return
-			}
-		}()
-		m2, err := Decode(pr)
+		// Read the image again, encode it, and decode it.
+		m1, err := readPng(qfn)
 		if err != nil {
 			t.Error(fn, err)
-			continue
+			return
+		}
+		m2, err := encodeDecode(m1)
+		if err != nil {
+			t.Error(fn, err)
+			return
 		}
 		// Compare the two.
 		err = diff(m0, m2)
@@ -74,6 +81,26 @@ func TestWriter(t *testing.T) {
 	}
 }
 
+func TestSubimage(t *testing.T) {
+	m0 := image.NewRGBA(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.Rect = image.Rect(50, 30, 250, 130)
+	m1, err := encodeDecode(m0)
+	if err != nil {
+		t.Error(err)
+		return
+	}
+	err = diff(m0, m1)
+	if err != nil {
+		t.Error(err)
+		return
+	}
+}
+
 func BenchmarkEncodePaletted(b *testing.B) {
 	b.StopTimer()
 	img := image.NewPaletted(640, 480,
diff --git a/src/pkg/image/ycbcr/ycbcr.go b/src/pkg/image/ycbcr/ycbcr.go
index cda4599..c1c58b7 100644
--- a/src/pkg/image/ycbcr/ycbcr.go
+++ b/src/pkg/image/ycbcr/ycbcr.go
@@ -169,6 +169,15 @@ func (p *YCbCr) At(x, y int) image.Color {
 	}
 }
 
+// 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/index/suffixarray/suffixarray_test.go b/src/pkg/index/suffixarray/suffixarray_test.go
index e85267f..b149902 100644
--- a/src/pkg/index/suffixarray/suffixarray_test.go
+++ b/src/pkg/index/suffixarray/suffixarray_test.go
@@ -108,7 +108,7 @@ var testCases = []testCase{
 }
 
 
-// find all occurrences of s in source; report at most n occurences
+// find all occurrences of s in source; report at most n occurrences
 func find(src, s string, n int) []int {
 	var res vector.IntVector
 	if s != "" && n != 0 {
diff --git a/src/pkg/io/io.go b/src/pkg/io/io.go
index 0bc73d6..846dcac 100644
--- a/src/pkg/io/io.go
+++ b/src/pkg/io/io.go
@@ -162,6 +162,18 @@ type ByteReader interface {
 	ReadByte() (c byte, err os.Error)
 }
 
+// ByteScanner is the interface that adds the UnreadByte method to the
+// basic ReadByte method.
+//
+// UnreadByte causes the next call to ReadByte to return the same byte
+// as the previous call to ReadByte.
+// It may be an error to call UnreadByte twice without an intervening
+// call to ReadByte.
+type ByteScanner interface {
+	ByteReader
+	UnreadByte() os.Error
+}
+
 // RuneReader is the interface that wraps the ReadRune method.
 //
 // ReadRune reads a single UTF-8 encoded Unicode character
@@ -171,6 +183,18 @@ type RuneReader interface {
 	ReadRune() (rune int, size int, err os.Error)
 }
 
+// RuneScanner is the interface that adds the UnreadRune method to the
+// basic ReadRune method.
+//
+// UnreadRune causes the next call to ReadRune to return the same rune
+// as the previous call to ReadRune.
+// It may be an error to call UnreadRune twice without an intervening
+// call to ReadRune.
+type RuneScanner interface {
+	RuneReader
+	UnreadRune() os.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) {
 	return w.Write([]byte(s))
@@ -303,22 +327,26 @@ 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.
-func LimitReader(r Reader, n int64) Reader { return &limitedReader{r, n} }
-
-type limitedReader struct {
-	r Reader
-	n int64
+// The underlying implementation is a *LimitedReader.
+func LimitReader(r Reader, n int64) Reader { return &LimitedReader{r, n} }
+
+// A LimitedReader reads from R but limits the amount of
+// data returned to just N bytes. Each call to Read
+// updates N to reflect the new amount remaining.
+type LimitedReader struct {
+	R Reader // underlying reader
+	N int64  // max bytes remaining
 }
 
-func (l *limitedReader) Read(p []byte) (n int, err os.Error) {
-	if l.n <= 0 {
+func (l *LimitedReader) 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]
+	if int64(len(p)) > l.N {
+		p = p[0:l.N]
 	}
-	n, err = l.r.Read(p)
-	l.n -= int64(n)
+	n, err = l.R.Read(p)
+	l.N -= int64(n)
 	return
 }
 
diff --git a/src/pkg/mail/Makefile b/src/pkg/mail/Makefile
new file mode 100644
index 0000000..e4de542
--- /dev/null
+++ b/src/pkg/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=mail
+GOFILES=\
+	message.go\
+
+include ../../Make.pkg
diff --git a/src/pkg/mail/message.go b/src/pkg/mail/message.go
new file mode 100644
index 0000000..9723863
--- /dev/null
+++ b/src/pkg/mail/message.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 mail implements parsing of mail messages according to RFC 5322.
+package mail
+
+import (
+	"bufio"
+	"io"
+	"net/textproto"
+	"os"
+	"time"
+)
+
+// 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.ErrorString("mail: header could not be parsed")
+}
+
+// TODO(dsymonds): Parsers for more specific headers such as To, From, etc.
+
+// 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.ErrorString("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)
+}
diff --git a/src/pkg/mail/message_test.go b/src/pkg/mail/message_test.go
new file mode 100644
index 0000000..1d1c635
--- /dev/null
+++ b/src/pkg/mail/message_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 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,
+				Weekday:    5, // Fri
+				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)
+		}
+	}
+}
diff --git a/src/pkg/math/log.go b/src/pkg/math/log.go
index 39d9451..a786c8c 100644
--- a/src/pkg/math/log.go
+++ b/src/pkg/math/log.go
@@ -23,7 +23,7 @@ package math
 // ====================================================
 //
 // __ieee754_log(x)
-// Return the logrithm of x
+// Return the logarithm of x
 //
 // Method :
 //   1. Argument Reduction: find k and f such that
diff --git a/src/pkg/math/sqrt_port.go b/src/pkg/math/sqrt_port.go
index 6f35a38..83af255 100644
--- a/src/pkg/math/sqrt_port.go
+++ b/src/pkg/math/sqrt_port.go
@@ -50,7 +50,7 @@ package math
 //      If (2) is false, then q   = q ; otherwise q   = q  + 2      .
 //                             i+1   i             i+1   i
 //
-//      With some algebric manipulation, it is not difficult to see
+//      With some algebraic manipulation, it is not difficult to see
 //      that (2) is equivalent to
 //                             -(i+1)
 //                      s  +  2       <= y                       (3)
diff --git a/src/pkg/mime/multipart/multipart_test.go b/src/pkg/mime/multipart/multipart_test.go
index ec564b1..4ec3d30 100644
--- a/src/pkg/mime/multipart/multipart_test.go
+++ b/src/pkg/mime/multipart/multipart_test.go
@@ -203,7 +203,7 @@ func testMultipart(t *testing.T, r io.Reader) {
 		t.Error("Didn't expect a fifth part.")
 	}
 	if err != os.EOF {
-		t.Errorf("On  fifth part expected os.EOF; got %v", err)
+		t.Errorf("On fifth part expected os.EOF; got %v", err)
 	}
 }
 
diff --git a/src/pkg/mime/multipart/writer.go b/src/pkg/mime/multipart/writer.go
index 74aa7be..b436dd0 100644
--- a/src/pkg/mime/multipart/writer.go
+++ b/src/pkg/mime/multipart/writer.go
@@ -6,24 +6,18 @@ package multipart
 
 import (
 	"bytes"
+	"crypto/rand"
 	"fmt"
 	"io"
 	"net/textproto"
 	"os"
-	"rand"
 	"strings"
 )
 
-// Writer is used to generate multipart messages.
+// A Writer generates multipart messages.
 type Writer struct {
-	// Boundary is the random boundary string between
-	// parts. NewWriter will generate this but it must
-	// not be changed after a part has been created.
-	// Setting this to an invalid value will generate
-	// malformed messages.
-	Boundary string
-
 	w        io.Writer
+	boundary string
 	lastpart *part
 }
 
@@ -32,38 +26,42 @@ type Writer struct {
 func NewWriter(w io.Writer) *Writer {
 	return &Writer{
 		w:        w,
-		Boundary: randomBoundary(),
+		boundary: randomBoundary(),
 	}
 }
 
+// Boundary returns the Writer's randomly selected boundary string.
+func (w *Writer) Boundary() string {
+	return w.boundary
+}
+
 // FormDataContentType returns the Content-Type for an HTTP
 // multipart/form-data with this Writer's Boundary.
 func (w *Writer) FormDataContentType() string {
-	return "multipart/form-data; boundary=" + w.Boundary
+	return "multipart/form-data; boundary=" + w.boundary
 }
 
-const randChars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
-
 func randomBoundary() string {
-	var buf [60]byte
-	for i := range buf {
-		buf[i] = randChars[rand.Intn(len(randChars))]
+	var buf [30]byte
+	_, err := io.ReadFull(rand.Reader, buf[:])
+	if err != nil {
+		panic(err)
 	}
-	return string(buf[:])
+	return fmt.Sprintf("%x", buf[:])
 }
 
 // CreatePart creates a new multipart section with the provided
-// header. The previous part, if still open, is closed. The body of
-// the part should be written to the returned WriteCloser. Closing the
-// returned WriteCloser after writing is optional.
-func (w *Writer) CreatePart(header textproto.MIMEHeader) (io.WriteCloser, os.Error) {
+// 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) {
 	if w.lastpart != nil {
-		if err := w.lastpart.Close(); err != nil {
+		if err := w.lastpart.close(); err != nil {
 			return nil, err
 		}
 	}
 	var b bytes.Buffer
-	fmt.Fprintf(&b, "\r\n--%s\r\n", w.Boundary)
+	fmt.Fprintf(&b, "\r\n--%s\r\n", w.boundary)
 	// TODO(bradfitz): move this to textproto.MimeHeader.Write(w), have it sort
 	// and clean, like http.Header.Write(w) does.
 	for k, vv := range header {
@@ -91,7 +89,7 @@ func escapeQuotes(s string) string {
 
 // 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.WriteCloser, os.Error) {
+func (w *Writer) CreateFormFile(fieldname, filename string) (io.Writer, os.Error) {
 	h := make(textproto.MIMEHeader)
 	h.Set("Content-Disposition",
 		fmt.Sprintf(`form-data; name="%s"; filename="%s"`,
@@ -100,40 +98,35 @@ func (w *Writer) CreateFormFile(fieldname, filename string) (io.WriteCloser, os.
 	return w.CreatePart(h)
 }
 
-// CreateFormField is a convenience wrapper around CreatePart. It creates
-// a new form-data header with the provided field name.
-func (w *Writer) CreateFormField(fieldname string) (io.WriteCloser, os.Error) {
+// CreateFormField calls CreatePart with a header using the
+// given field name.
+func (w *Writer) CreateFormField(fieldname string) (io.Writer, os.Error) {
 	h := make(textproto.MIMEHeader)
 	h.Set("Content-Disposition",
 		fmt.Sprintf(`form-data; name="%s"`, escapeQuotes(fieldname)))
 	return w.CreatePart(h)
 }
 
-// WriteField is a convenience wrapper around CreateFormField. It creates and
-// writes a part with the provided name and value.
+// WriteField calls CreateFormField and then writes the given value.
 func (w *Writer) WriteField(fieldname, value string) os.Error {
 	p, err := w.CreateFormField(fieldname)
 	if err != nil {
 		return err
 	}
 	_, err = p.Write([]byte(value))
-	if err != nil {
-		return err
-	}
-	return p.Close()
+	return err
 }
 
-// Close finishes the multipart message. It closes the previous part,
-// if still open, and writes the trailing boundary end line to the
-// output.
+// Close finishes the multipart message and writes the trailing
+// boundary end line to the output.
 func (w *Writer) Close() os.Error {
 	if w.lastpart != nil {
-		if err := w.lastpart.Close(); err != nil {
+		if err := w.lastpart.close(); err != nil {
 			return err
 		}
 		w.lastpart = nil
 	}
-	_, err := fmt.Fprintf(w.w, "\r\n--%s--\r\n", w.Boundary)
+	_, err := fmt.Fprintf(w.w, "\r\n--%s--\r\n", w.boundary)
 	return err
 }
 
@@ -143,14 +136,14 @@ type part struct {
 	we     os.Error // last error that occurred writing
 }
 
-func (p *part) Close() os.Error {
+func (p *part) close() os.Error {
 	p.closed = true
 	return p.we
 }
 
 func (p *part) Write(d []byte) (n int, err os.Error) {
 	if p.closed {
-		return 0, os.NewError("multipart: Write after Close")
+		return 0, os.NewError("multipart: can't write to finished part")
 	}
 	n, err = p.mw.w.Write(d)
 	if err != nil {
diff --git a/src/pkg/mime/multipart/writer_test.go b/src/pkg/mime/multipart/writer_test.go
index b85fbf8..e6a04c3 100644
--- a/src/pkg/mime/multipart/writer_test.go
+++ b/src/pkg/mime/multipart/writer_test.go
@@ -23,7 +23,7 @@ func TestWriter(t *testing.T) {
 		part.Write(fileContents)
 		err = w.WriteField("key", "val")
 		if err != nil {
-			t.Fatalf("CreateFormFieldValue: %v", err)
+			t.Fatalf("WriteField: %v", err)
 		}
 		part.Write([]byte("val"))
 		err = w.Close()
@@ -32,7 +32,7 @@ func TestWriter(t *testing.T) {
 		}
 	}
 
-	r := NewReader(&b, w.Boundary)
+	r := NewReader(&b, w.Boundary())
 
 	part, err := r.NextPart()
 	if err != nil {
diff --git a/src/pkg/net/Makefile b/src/pkg/net/Makefile
index 376e9c6..d4adbff 100644
--- a/src/pkg/net/Makefile
+++ b/src/pkg/net/Makefile
@@ -23,12 +23,13 @@ GOFILES=\
 	unixsock.go\
 
 GOFILES_freebsd=\
-	newpollserver.go\
+	dnsclient.go\
+	dnsconfig.go\
 	fd.go\
 	file.go\
-	dnsconfig.go\
-	dnsclient.go\
+	newpollserver.go\
 	port.go\
+	sendfile_stub.go\
 	sock_bsd.go\
 
 CGOFILES_freebsd=\
@@ -36,27 +37,32 @@ CGOFILES_freebsd=\
 	cgo_unix.go\
 
 GOFILES_darwin=\
-	newpollserver.go\
+	dnsclient.go\
+	dnsconfig.go\
 	fd.go\
 	file.go\
-	dnsconfig.go\
-	dnsclient.go\
+	newpollserver.go\
 	port.go\
+	sendfile_stub.go\
 	sock_bsd.go\
 
 CGOFILES_darwin=\
 	cgo_bsd.go\
 	cgo_unix.go\
-	
+
 GOFILES_linux=\
-	newpollserver.go\
+	dnsclient.go\
+	dnsconfig.go\
 	fd.go\
 	file.go\
-	dnsconfig.go\
-	dnsclient.go\
+	newpollserver.go\
 	port.go\
+	sendfile_linux.go\
 	sock_linux.go\
 
+GOFILES_plan9=\
+	sendfile_stub.go\
+
 ifeq ($(GOARCH),arm)
 # ARM has no cgo, so use the stubs.
 GOFILES_linux+=cgo_stub.go
@@ -68,8 +74,9 @@ endif
 
 GOFILES_windows=\
 	cgo_stub.go\
-	resolv_windows.go\
 	file_windows.go\
+	resolv_windows.go\
+	sendfile_stub.go\
 	sock_windows.go\
 
 GOFILES+=$(GOFILES_$(GOOS))
diff --git a/src/pkg/net/fd_linux.go b/src/pkg/net/fd_linux.go
index dcf65c0..70fc344 100644
--- a/src/pkg/net/fd_linux.go
+++ b/src/pkg/net/fd_linux.go
@@ -117,6 +117,17 @@ func (p *pollster) DelFD(fd int, mode int) {
 	} else {
 		p.StopWaiting(fd, writeFlags)
 	}
+
+	// Discard any queued up events.
+	i := 0
+	for i < len(p.waitEvents) {
+		if fd == int(p.waitEvents[i].Fd) {
+			copy(p.waitEvents[i:], p.waitEvents[i+1:])
+			p.waitEvents = p.waitEvents[:len(p.waitEvents)-1]
+		} else {
+			i++
+		}
+	}
 }
 
 func (p *pollster) WaitFD(s *pollServer, nsec int64) (fd int, mode int, err os.Error) {
diff --git a/src/pkg/net/fd_windows.go b/src/pkg/net/fd_windows.go
index c2f736c..9ed7801 100644
--- a/src/pkg/net/fd_windows.go
+++ b/src/pkg/net/fd_windows.go
@@ -84,7 +84,7 @@ func (o *bufOp) Init(fd *netFD, buf []byte) {
 	}
 }
 
-// resultSrv will retreive all io completion results from
+// resultSrv will retrieve all io completion results from
 // iocp and send them to the correspondent waiting client
 // goroutine via channel supplied in the request.
 type resultSrv struct {
@@ -513,7 +513,7 @@ func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (nfd *netFD, err os.
 	return nfd, nil
 }
 
-// Not implemeted functions.
+// Unimplemented functions.
 
 func (fd *netFD) dup() (f *os.File, err os.Error) {
 	// TODO: Implement this
diff --git a/src/pkg/net/ip.go b/src/pkg/net/ip.go
index a3000af..b0e2c42 100644
--- a/src/pkg/net/ip.go
+++ b/src/pkg/net/ip.go
@@ -113,7 +113,7 @@ func (ip IP) IsInterfaceLocalMulticast() bool {
 	return len(ip) == IPv6len && ip[0] == 0xff && ip[1]&0x0f == 0x01
 }
 
-// IsLinkLinkLocalMulticast returns true if ip is a link-local
+// IsLinkLocalMulticast returns true if ip is a link-local
 // multicast address.
 func (ip IP) IsLinkLocalMulticast() bool {
 	if ip4 := ip.To4(); ip4 != nil && ip4[0] == 224 && ip4[1] == 0 && ip4[2] == 0 {
@@ -122,7 +122,7 @@ func (ip IP) IsLinkLocalMulticast() bool {
 	return ip[0] == 0xff && ip[1]&0x0f == 0x02
 }
 
-// IsLinkLinkLocalUnicast returns true if ip is a link-local
+// IsLinkLocalUnicast returns true if ip is a link-local
 // unicast address.
 func (ip IP) IsLinkLocalUnicast() bool {
 	if ip4 := ip.To4(); ip4 != nil && ip4[0] == 169 && ip4[1] == 254 {
diff --git a/src/pkg/net/ipsock.go b/src/pkg/net/ipsock.go
index b83284d..0b8c388 100644
--- a/src/pkg/net/ipsock.go
+++ b/src/pkg/net/ipsock.go
@@ -62,7 +62,7 @@ var supportsIPv6, supportsIPv4map = probeIPv6Stack()
 // favoriteAddrFamily returns the appropriate address family to
 // the given net, raddr, laddr and mode.  At first it figures
 // address family out from the net.  If mode indicates "listen"
-// and laddr.(type).IP is nil, it assuumes that the user wants to
+// and laddr.(type).IP is nil, it assumes that the user wants to
 // make a passive connection with wildcard address family, both
 // INET and INET6, and wildcard address.  Otherwise guess: if the
 // addresses are IPv4 then returns INET, or else returns INET6.
@@ -145,7 +145,7 @@ func ipv6only(x IP) IP {
 	return nil
 }
 
-// TODO(rsc): if syscall.OS == "linux", we're supposd to read
+// 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 }
diff --git a/src/pkg/net/sendfile_linux.go b/src/pkg/net/sendfile_linux.go
new file mode 100644
index 0000000..6a5a06c
--- /dev/null
+++ b/src/pkg/net/sendfile_linux.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.
+
+package net
+
+import (
+	"io"
+	"os"
+	"syscall"
+)
+
+// maxSendfileSize is the largest chunk size we ask the kernel to copy
+// at a time.
+const maxSendfileSize int = 4 << 20
+
+// sendFile copies the contents of r to c using the sendfile
+// system call to minimize copies.
+//
+// if handled == true, sendFile returns the number of bytes copied and any
+// non-EOF error.
+//
+// if handled == false, sendFile performed no work.
+func sendFile(c *netFD, r io.Reader) (written int64, err os.Error, handled bool) {
+	var remain int64 = 1 << 62 // by default, copy until EOF
+
+	lr, ok := r.(*io.LimitedReader)
+	if ok {
+		remain, r = lr.N, lr.R
+		if remain <= 0 {
+			return 0, nil, true
+		}
+	}
+	f, ok := r.(*os.File)
+	if !ok {
+		return 0, nil, false
+	}
+
+	c.wio.Lock()
+	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()
+	for remain > 0 {
+		n := maxSendfileSize
+		if int64(n) > remain {
+			n = int(remain)
+		}
+		n, errno := syscall.Sendfile(dst, src, nil, n)
+		if n > 0 {
+			written += int64(n)
+			remain -= int64(n)
+		}
+		if n == 0 && errno == 0 {
+			break
+		}
+		if errno == syscall.EAGAIN && c.wdeadline >= 0 {
+			pollserver.WaitWrite(c)
+			continue
+		}
+		if errno != 0 {
+			// 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)}
+			break
+		}
+	}
+	if lr != nil {
+		lr.N = remain
+	}
+	return written, err, written > 0
+}
diff --git a/src/pkg/net/sendfile_stub.go b/src/pkg/net/sendfile_stub.go
new file mode 100644
index 0000000..43e8104
--- /dev/null
+++ b/src/pkg/net/sendfile_stub.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.
+
+package net
+
+import (
+	"io"
+	"os"
+)
+
+func sendFile(c *netFD, r io.Reader) (n int64, err os.Error, handled bool) {
+	return 0, nil, false
+}
diff --git a/src/pkg/net/server_test.go b/src/pkg/net/server_test.go
index 107de3e..36780d7 100644
--- a/src/pkg/net/server_test.go
+++ b/src/pkg/net/server_test.go
@@ -92,10 +92,13 @@ func connect(t *testing.T, network, addr string, isEmpty bool) {
 }
 
 func doTest(t *testing.T, network, listenaddr, dialaddr string) {
-	if listenaddr == "" {
-		t.Logf("Test %s %s %s\n", network, "<nil>", dialaddr)
-	} else {
-		t.Logf("Test %s %s %s\n", network, listenaddr, dialaddr)
+	t.Logf("Test %q %q %q\n", network, listenaddr, dialaddr)
+	switch listenaddr {
+	case "", "0.0.0.0", "[::]", "[::ffff:0.0.0.0]":
+		if testing.Short() || avoidMacFirewall {
+			t.Logf("skip wildcard listen during short test")
+			return
+		}
 	}
 	listening := make(chan string)
 	done := make(chan int)
diff --git a/src/pkg/net/sock.go b/src/pkg/net/sock.go
index 5c47e4f..eae7f37 100644
--- a/src/pkg/net/sock.go
+++ b/src/pkg/net/sock.go
@@ -7,6 +7,7 @@
 package net
 
 import (
+	"io"
 	"os"
 	"reflect"
 	"syscall"
@@ -153,3 +154,14 @@ type UnknownSocketError struct {
 func (e *UnknownSocketError) String() string {
 	return "unknown socket address type " + reflect.TypeOf(e.sa).String()
 }
+
+type writerOnly struct {
+	io.Writer
+}
+
+// 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) {
+	// Use wrapper to hide existing r.ReadFrom from io.Copy.
+	return io.Copy(writerOnly{w}, r)
+}
diff --git a/src/pkg/net/tcpsock.go b/src/pkg/net/tcpsock.go
index 8aeed48..9ee6c14 100644
--- a/src/pkg/net/tcpsock.go
+++ b/src/pkg/net/tcpsock.go
@@ -7,6 +7,7 @@
 package net
 
 import (
+	"io"
 	"os"
 	"syscall"
 )
@@ -95,6 +96,14 @@ func (c *TCPConn) Read(b []byte) (n int, err os.Error) {
 	return c.fd.Read(b)
 }
 
+// ReadFrom implements the io.ReaderFrom ReadFrom method.
+func (c *TCPConn) ReadFrom(r io.Reader) (int64, os.Error) {
+	if n, err, handled := sendFile(c.fd, r); handled {
+		return n, err
+	}
+	return genericReadFrom(c, r)
+}
+
 // Write implements the net.Conn Write method.
 func (c *TCPConn) Write(b []byte) (n int, err os.Error) {
 	if !c.ok() {
diff --git a/src/pkg/net/textproto/reader.go b/src/pkg/net/textproto/reader.go
index ac12786..e653749 100644
--- a/src/pkg/net/textproto/reader.go
+++ b/src/pkg/net/textproto/reader.go
@@ -237,7 +237,7 @@ func (r *Reader) ReadResponse(expectCode int) (code int, message string, err os.
 // to a method on r.
 //
 // Dot encoding is a common framing used for data blocks
-// in text protcols like SMTP.  The data consists of a sequence
+// in text protocols such as SMTP.  The data consists of a sequence
 // of lines, each of which ends in "\r\n".  The sequence itself
 // ends at a line containing just a dot: ".\r\n".  Lines beginning
 // with a dot are escaped with an additional dot to avoid
diff --git a/src/pkg/net/udpsock.go b/src/pkg/net/udpsock.go
index 4093556..5469acf 100644
--- a/src/pkg/net/udpsock.go
+++ b/src/pkg/net/udpsock.go
@@ -293,10 +293,10 @@ func (c *UDPConn) JoinGroup(addr IP) os.Error {
 	if ip == nil {
 		return &OpError{"joingroup", "udp", &IPAddr{ip}, errInvalidMulticast}
 	}
-	mreq := &syscall.IpMreq{
+	mreq := &syscall.IPMreq{
 		Multiaddr: [4]byte{ip[0], ip[1], ip[2], ip[3]},
 	}
-	err := os.NewSyscallError("setsockopt", syscall.SetsockoptIpMreq(c.fd.sysfd, syscall.IPPROTO_IP, syscall.IP_ADD_MEMBERSHIP, mreq))
+	err := os.NewSyscallError("setsockopt", syscall.SetsockoptIPMreq(c.fd.sysfd, syscall.IPPROTO_IP, syscall.IP_ADD_MEMBERSHIP, mreq))
 	if err != nil {
 		return &OpError{"joingroup", "udp", &IPAddr{ip}, err}
 	}
@@ -312,10 +312,10 @@ func (c *UDPConn) LeaveGroup(addr IP) os.Error {
 	if ip == nil {
 		return &OpError{"leavegroup", "udp", &IPAddr{ip}, errInvalidMulticast}
 	}
-	mreq := &syscall.IpMreq{
+	mreq := &syscall.IPMreq{
 		Multiaddr: [4]byte{ip[0], ip[1], ip[2], ip[3]},
 	}
-	err := os.NewSyscallError("setsockopt", syscall.SetsockoptIpMreq(c.fd.sysfd, syscall.IPPROTO_IP, syscall.IP_DROP_MEMBERSHIP, mreq))
+	err := os.NewSyscallError("setsockopt", syscall.SetsockoptIPMreq(c.fd.sysfd, syscall.IPPROTO_IP, syscall.IP_DROP_MEMBERSHIP, mreq))
 	if err != nil {
 		return &OpError{"leavegroup", "udp", &IPAddr{ip}, err}
 	}
diff --git a/src/pkg/os/Makefile b/src/pkg/os/Makefile
index cd92840..c781df7 100644
--- a/src/pkg/os/Makefile
+++ b/src/pkg/os/Makefile
@@ -23,6 +23,7 @@ GOFILES_freebsd=\
 	env_unix.go\
 	file_posix.go\
 	file_unix.go\
+	path_unix.go\
 	sys_bsd.go\
 	exec_posix.go\
 	exec_unix.go\
@@ -33,6 +34,7 @@ GOFILES_darwin=\
 	env_unix.go\
 	file_posix.go\
 	file_unix.go\
+	path_unix.go\
 	sys_bsd.go\
 	exec_posix.go\
 	exec_unix.go\
@@ -43,6 +45,7 @@ GOFILES_linux=\
 	env_unix.go\
 	file_posix.go\
 	file_unix.go\
+	path_unix.go\
 	sys_linux.go\
 	exec_posix.go\
 	exec_unix.go\
@@ -53,6 +56,7 @@ GOFILES_windows=\
 	env_windows.go\
 	file_posix.go\
 	file_windows.go\
+	path_windows.go\
 	sys_windows.go\
 	exec_posix.go\
 	exec_windows.go\
@@ -62,6 +66,7 @@ GOFILES_plan9=\
 	error_plan9.go\
 	env_plan9.go\
 	file_plan9.go\
+	path_plan9.go\
 	sys_plan9.go\
 	exec_plan9.go\
 
diff --git a/src/pkg/os/dir_plan9.go b/src/pkg/os/dir_plan9.go
index d951419..bbc2cb6 100644
--- a/src/pkg/os/dir_plan9.go
+++ b/src/pkg/os/dir_plan9.go
@@ -9,35 +9,46 @@ import (
 )
 
 // Readdir reads the contents of the directory associated with file and
-// returns an array of up to count FileInfo structures, in directory order. 
-// Subsequent calls on the same file will yield further FileInfos.
-// A negative count means to read until EOF.
-// Readdir returns the array and an Error, if any.
-func (file *File) Readdir(count int) (fi []FileInfo, err Error) {
+// 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) {
 	// If this file has no dirinfo, create one.
 	if file.dirinfo == nil {
 		file.dirinfo = new(dirInfo)
 	}
 	d := file.dirinfo
-	size := count
-	if size < 0 {
+	size := n
+	if size <= 0 {
 		size = 100
+		n = -1
 	}
 	result := make([]FileInfo, 0, size) // Empty with room to grow.
-	for count != 0 {
+	for n != 0 {
 		// Refill the buffer if necessary
 		if d.bufp >= d.nbuf {
 			d.bufp = 0
 			var e Error
 			d.nbuf, e = file.Read(d.buf[:])
 			if e != nil && e != EOF {
-				return nil, &PathError{"readdir", file.name, e}
+				return result, &PathError{"readdir", file.name, e}
 			}
 			if e == EOF {
 				break
 			}
 			if d.nbuf < syscall.STATFIXLEN {
-				return nil, &PathError{"readdir", file.name, Eshortstat}
+				return result, &PathError{"readdir", file.name, Eshortstat}
 			}
 		}
 
@@ -45,39 +56,44 @@ func (file *File) Readdir(count int) (fi []FileInfo, err Error) {
 		m, _ := gbit16(d.buf[d.bufp:])
 		m += 2
 		if m < syscall.STATFIXLEN {
-			return nil, &PathError{"readdir", file.name, Eshortstat}
+			return result, &PathError{"readdir", file.name, Eshortstat}
 		}
 		dir, e := UnmarshalDir(d.buf[d.bufp : d.bufp+int(m)])
 		if e != nil {
-			return nil, &PathError{"readdir", file.name, e}
+			return result, &PathError{"readdir", file.name, e}
 		}
 		var f FileInfo
 		fileInfoFromStat(&f, dir)
 		result = append(result, f)
 
 		d.bufp += int(m)
-		count--
+		n--
 	}
-	return result, nil
-}
 
-// Readdirnames returns an array of up to count file names residing in the 
-// directory associated with file. A negative count will return all of them.
-// Readdir returns the array and an Error, if any.
-func (file *File) Readdirnames(count int) (names []string, err Error) {
-	fi, e := file.Readdir(count)
-
-	if e != nil {
-		return []string{}, e
+	if n >= 0 && len(result) == 0 {
+		return result, 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) {
+	fi, err := file.Readdir(n)
 	names = make([]string, len(fi))
-	err = nil
-
 	for i := range fi {
 		names[i] = fi[i].Name
 	}
-
 	return
 }
 
@@ -142,7 +158,7 @@ func pdir(b []byte, d *Dir) []byte {
 	return b
 }
 
-// UnmarshalDir reads a 9P Stat message from a 9P protocol message strored in b,
+// 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) {
 	n := uint16(0)
@@ -172,7 +188,7 @@ func UnmarshalDir(b []byte) (d *Dir, err Error) {
 	return d, nil
 }
 
-// gqid reads the qid part of a 9P Stat message from a 9P protocol message strored in b,
+// gqid reads the qid part of a 9P Stat message from a 9P protocol message stored in b,
 // returning the corresponding Qid struct and the remaining slice of b.
 func gqid(b []byte) (Qid, []byte) {
 	var q Qid
@@ -190,25 +206,25 @@ func pqid(b []byte, q Qid) []byte {
 	return b
 }
 
-// gbit8 reads a byte-sized numeric value from a 9P protocol message strored in b,
+// gbit8 reads a byte-sized numeric value from a 9P protocol message stored in b,
 // returning the value and the remaining slice of b.
 func gbit8(b []byte) (uint8, []byte) {
 	return uint8(b[0]), b[1:]
 }
 
-// gbit16 reads a 16-bit numeric value from a 9P protocol message strored in b,
+// gbit16 reads a 16-bit numeric value from a 9P protocol message stored in b,
 // returning the value and the remaining slice of b.
 func gbit16(b []byte) (uint16, []byte) {
 	return uint16(b[0]) | uint16(b[1])<<8, b[2:]
 }
 
-// gbit32 reads a 32-bit numeric value from a 9P protocol message strored in b,
+// gbit32 reads a 32-bit numeric value from a 9P protocol message stored in b,
 // returning the value and the remaining slice of b.
 func gbit32(b []byte) (uint32, []byte) {
 	return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24, b[4:]
 }
 
-// gbit64 reads a 64-bit numeric value from a 9P protocol message strored in b,
+// gbit64 reads a 64-bit numeric value from a 9P protocol message stored in b,
 // returning the value and the remaining slice of b.
 func gbit64(b []byte) (uint64, []byte) {
 	lo, b := gbit32(b)
@@ -216,7 +232,7 @@ func gbit64(b []byte) (uint64, []byte) {
 	return uint64(hi)<<32 | uint64(lo), b
 }
 
-// gstring reads a string from a 9P protocol message strored in b,
+// gstring reads a string from a 9P protocol message stored in b,
 // returning the value as a Go string and the remaining slice of b.
 func gstring(b []byte) (string, []byte) {
 	n, b := gbit16(b)
diff --git a/src/pkg/os/dir_unix.go b/src/pkg/os/dir_unix.go
index 9c54383..7835ed5 100644
--- a/src/pkg/os/dir_unix.go
+++ b/src/pkg/os/dir_unix.go
@@ -32,11 +32,11 @@ func (f *File) Readdirnames(n int) (names []string, err Error) {
 		f.dirinfo.buf = make([]byte, blockSize)
 	}
 	d := f.dirinfo
-	wantAll := n < 0
 
 	size := n
-	if size < 0 {
+	if size <= 0 {
 		size = 100
+		n = -1
 	}
 
 	names = make([]string, 0, size) // Empty with room to grow.
@@ -60,7 +60,7 @@ func (f *File) Readdirnames(n int) (names []string, err Error) {
 		d.bufp += nb
 		n -= nc
 	}
-	if !wantAll && len(names) == 0 {
+	if n >= 0 && len(names) == 0 {
 		return names, EOF
 	}
 	return names, nil
diff --git a/src/pkg/os/dir_windows.go b/src/pkg/os/dir_windows.go
index a4df9d3..d76e88f 100644
--- a/src/pkg/os/dir_windows.go
+++ b/src/pkg/os/dir_windows.go
@@ -6,11 +6,6 @@ package os
 
 func (file *File) Readdirnames(n int) (names []string, err Error) {
 	fis, err := file.Readdir(n)
-	// If n > 0 and we get an error, we return now.
-	// If n < 0, we return whatever we got + any error.
-	if n > 0 && err != nil {
-		return nil, err
-	}
 	names = make([]string, len(fis))
 	for i, fi := range fis {
 		names[i] = fi.Name
diff --git a/src/pkg/os/file_unix.go b/src/pkg/os/file_unix.go
index c65c5b3..def9b3b 100644
--- a/src/pkg/os/file_unix.go
+++ b/src/pkg/os/file_unix.go
@@ -69,12 +69,12 @@ func (file *File) Stat() (fi *FileInfo, err Error) {
 }
 
 // Readdir reads the contents of the directory associated with file and
-// returns an array of up to count FileInfo structures, as would be returned
+// 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 names. In this case, if
-// Readdirnames returns an empty slice, it will return a non-nil error
+// 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
@@ -89,11 +89,7 @@ func (file *File) Readdir(n int) (fi []FileInfo, err Error) {
 		dirname = "."
 	}
 	dirname += "/"
-	wantAll := n < 0
-	names, namesErr := file.Readdirnames(n)
-	if namesErr != nil && !wantAll {
-		return nil, namesErr
-	}
+	names, err := file.Readdirnames(n)
 	fi = make([]FileInfo, len(names))
 	for i, filename := range names {
 		fip, err := Lstat(dirname + filename)
@@ -103,9 +99,6 @@ func (file *File) Readdir(n int) (fi []FileInfo, err Error) {
 			fi[i] = *fip
 		}
 	}
-	if !wantAll && namesErr != EOF {
-		err = namesErr
-	}
 	return
 }
 
diff --git a/src/pkg/os/file_windows.go b/src/pkg/os/file_windows.go
index 74ff3eb..80886f6 100644
--- a/src/pkg/os/file_windows.go
+++ b/src/pkg/os/file_windows.go
@@ -123,12 +123,12 @@ func (file *File) Stat() (fi *FileInfo, err Error) {
 }
 
 // Readdir reads the contents of the directory associated with file and
-// returns an array of up to count FileInfo structures, as would be returned
+// 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 names. In this case, if
-// Readdirnames returns an empty slice, it will return a non-nil error
+// 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
@@ -145,9 +145,10 @@ func (file *File) Readdir(n int) (fi []FileInfo, err Error) {
 		return nil, &PathError{"Readdir", file.name, ENOTDIR}
 	}
 	di := file.dirinfo
-	wantAll := n < 0
+	wantAll := n <= 0
 	size := n
-	if size < 0 {
+	if wantAll {
+		n = -1
 		size = 100
 	}
 	fi = make([]FileInfo, 0, size) // Empty with room to grow.
diff --git a/src/pkg/os/os_test.go b/src/pkg/os/os_test.go
index b06d57b..8eabdee 100644
--- a/src/pkg/os/os_test.go
+++ b/src/pkg/os/os_test.go
@@ -286,6 +286,78 @@ func TestReaddirnamesOneAtATime(t *testing.T) {
 	}
 }
 
+func TestReaddirNValues(t *testing.T) {
+	if testing.Short() {
+		t.Logf("test.short; skipping")
+		return
+	}
+	dir, err := ioutil.TempDir("", "")
+	if err != nil {
+		t.Fatalf("TempDir: %v", err)
+	}
+	defer RemoveAll(dir)
+	for i := 1; i <= 105; i++ {
+		f, err := Create(filepath.Join(dir, fmt.Sprintf("%d", i)))
+		if err != nil {
+			t.Fatalf("Create: %v", err)
+		}
+		f.Write([]byte(strings.Repeat("X", i)))
+		f.Close()
+	}
+
+	var d *File
+	openDir := func() {
+		var err Error
+		d, err = Open(dir)
+		if err != nil {
+			t.Fatalf("Open directory: %v", err)
+		}
+	}
+
+	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)
+		}
+		if g, e := len(fi), want; g != e {
+			t.Errorf("Readdir of %d got %d files, want %d", n, g, e)
+		}
+	}
+
+	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)
+		}
+		if g, e := len(fi), want; g != e {
+			t.Errorf("Readdirnames of %d got %d files, want %d", n, g, e)
+		}
+	}
+
+	for _, fn := range []func(int, int, Error){readDirExpect, readDirNamesExpect} {
+		// Test the slurp case
+		openDir()
+		fn(0, 105, nil)
+		fn(0, 0, nil)
+		d.Close()
+
+		// Slurp with -1 instead
+		openDir()
+		fn(-1, 105, nil)
+		fn(-2, 0, nil)
+		fn(0, 0, nil)
+		d.Close()
+
+		// Test the bounded case
+		openDir()
+		fn(1, 1, nil)
+		fn(2, 2, nil)
+		fn(105, 102, nil) // and tests buffer >100 case
+		fn(3, 0, EOF)
+		d.Close()
+	}
+}
+
 func TestHardLink(t *testing.T) {
 	// Hardlinks are not supported under windows.
 	if syscall.OS == "windows" {
@@ -442,7 +514,8 @@ func exec(t *testing.T, dir, cmd string, args []string, expect string) {
 	var b bytes.Buffer
 	io.Copy(&b, r)
 	output := b.String()
-	if output != expect {
+	// Accept /usr prefix because Solaris /bin is symlinked to /usr/bin.
+	if output != expect && output != "/usr"+expect {
 		t.Errorf("exec %q returned %q wanted %q",
 			strings.Join(append([]string{cmd}, args...), " "), output, expect)
 	}
@@ -917,7 +990,15 @@ func TestAppend(t *testing.T) {
 	}
 	s = writeFile(t, f, O_CREATE|O_APPEND|O_RDWR, "new&append")
 	if s != "new&append" {
-		t.Fatalf("writeFile: have %q want %q", s, "new&append")
+		t.Fatalf("writeFile: after append have %q want %q", s, "new&append")
+	}
+	s = writeFile(t, f, O_CREATE|O_RDWR, "old")
+	if s != "old&append" {
+		t.Fatalf("writeFile: after create have %q want %q", s, "old&append")
+	}
+	s = writeFile(t, f, O_CREATE|O_TRUNC|O_RDWR, "new")
+	if s != "new" {
+		t.Fatalf("writeFile: after truncate have %q want %q", s, "new")
 	}
 }
 
diff --git a/src/pkg/os/path.go b/src/pkg/os/path.go
index 5565aaa..7b93036 100644
--- a/src/pkg/os/path.go
+++ b/src/pkg/os/path.go
@@ -24,12 +24,12 @@ func MkdirAll(path string, perm uint32) Error {
 
 	// Doesn't already exist; make sure parent does.
 	i := len(path)
-	for i > 0 && path[i-1] == '/' { // Skip trailing slashes.
+	for i > 0 && IsPathSeparator(path[i-1]) { // Skip trailing path separator.
 		i--
 	}
 
 	j := i
-	for j > 0 && path[j-1] != '/' { // Scan backward over element.
+	for j > 0 && !IsPathSeparator(path[j-1]) { // Scan backward over element.
 		j--
 	}
 
@@ -90,7 +90,7 @@ func RemoveAll(path string) Error {
 	for {
 		names, err1 := fd.Readdirnames(100)
 		for _, name := range names {
-			err1 := RemoveAll(path + "/" + name)
+			err1 := RemoveAll(path + string(PathSeparator) + name)
 			if err == nil {
 				err = err1
 			}
diff --git a/src/pkg/os/path_plan9.go b/src/pkg/os/path_plan9.go
new file mode 100644
index 0000000..3121b7b
--- /dev/null
+++ b/src/pkg/os/path_plan9.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 os
+
+const (
+	PathSeparator     = '/' // OS-specific path separator
+	PathListSeparator = 0   // OS-specific path list separator
+)
+
+// IsPathSeparator returns true if c is a directory separator character.
+func IsPathSeparator(c uint8) bool {
+	return PathSeparator == c
+}
diff --git a/src/pkg/os/path_test.go b/src/pkg/os/path_test.go
index 483bb63..d58945a 100644
--- a/src/pkg/os/path_test.go
+++ b/src/pkg/os/path_test.go
@@ -6,6 +6,7 @@ package os_test
 
 import (
 	. "os"
+	"path/filepath"
 	"testing"
 	"runtime"
 	"syscall"
@@ -29,10 +30,11 @@ func TestMkdirAll(t *testing.T) {
 
 	// Make file.
 	fpath := path + "/file"
-	_, err = Create(fpath)
+	f, err := Create(fpath)
 	if err != nil {
 		t.Fatalf("create %q: %s", fpath, err)
 	}
+	defer f.Close()
 
 	// Can't make directory named after file.
 	err = MkdirAll(fpath, 0777)
@@ -43,8 +45,8 @@ func TestMkdirAll(t *testing.T) {
 	if !ok {
 		t.Fatalf("MkdirAll %q returned %T, not *PathError", fpath, err)
 	}
-	if perr.Path != fpath {
-		t.Fatalf("MkdirAll %q returned wrong error path: %q not %q", fpath, perr.Path, fpath)
+	if filepath.Clean(perr.Path) != filepath.Clean(fpath) {
+		t.Fatalf("MkdirAll %q returned wrong error path: %q not %q", fpath, filepath.Clean(perr.Path), filepath.Clean(fpath))
 	}
 
 	// Can't make subdirectory of file.
@@ -57,8 +59,16 @@ func TestMkdirAll(t *testing.T) {
 	if !ok {
 		t.Fatalf("MkdirAll %q returned %T, not *PathError", ffpath, err)
 	}
-	if perr.Path != fpath {
-		t.Fatalf("MkdirAll %q returned wrong error path: %q not %q", ffpath, perr.Path, fpath)
+	if filepath.Clean(perr.Path) != filepath.Clean(fpath) {
+		t.Fatalf("MkdirAll %q returned wrong error path: %q not %q", ffpath, filepath.Clean(perr.Path), filepath.Clean(fpath))
+	}
+
+	if syscall.OS == "windows" {
+		path := `_test\_TestMkdirAll_\dir\.\dir2\`
+		err := MkdirAll(path, 0777)
+		if err != nil {
+			t.Fatalf("MkdirAll %q: %s", path, err)
+		}
 	}
 }
 
diff --git a/src/pkg/os/path_unix.go b/src/pkg/os/path_unix.go
new file mode 100644
index 0000000..0d327cd
--- /dev/null
+++ b/src/pkg/os/path_unix.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 os
+
+const (
+	PathSeparator     = '/' // OS-specific path separator
+	PathListSeparator = ':' // OS-specific path list separator
+)
+
+// IsPathSeparator returns true if c is a directory separator character.
+func IsPathSeparator(c uint8) bool {
+	return PathSeparator == c
+}
diff --git a/src/pkg/os/path_windows.go b/src/pkg/os/path_windows.go
new file mode 100644
index 0000000..8740a9e
--- /dev/null
+++ b/src/pkg/os/path_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 os
+
+const (
+	PathSeparator     = '\\' // OS-specific path separator
+	PathListSeparator = ':'  // OS-specific path list separator
+)
+
+// IsPathSeparator returns true if c is a directory separator character.
+func IsPathSeparator(c uint8) bool {
+	// NOTE: Windows accept / as path separator.
+	return c == '\\' || c == '/'
+}
diff --git a/src/pkg/path/filepath/match.go b/src/pkg/path/filepath/match.go
index a05bb5f..9c34430 100644
--- a/src/pkg/path/filepath/match.go
+++ b/src/pkg/path/filepath/match.go
@@ -124,9 +124,8 @@ func matchChunk(chunk, s string) (rest string, ok bool, err os.Error) {
 			s = s[n:]
 			chunk = chunk[1:]
 			// possibly negated
-			notNegated := true
-			if len(chunk) > 0 && chunk[0] == '^' {
-				notNegated = false
+			negated := chunk[0] == '^'
+			if negated {
 				chunk = chunk[1:]
 			}
 			// parse all ranges
@@ -152,7 +151,7 @@ func matchChunk(chunk, s string) (rest string, ok bool, err os.Error) {
 				}
 				nrange++
 			}
-			if match != notNegated {
+			if match == negated {
 				return
 			}
 
diff --git a/src/pkg/path/filepath/match_test.go b/src/pkg/path/filepath/match_test.go
index 43e1c1c..a1c8333 100644
--- a/src/pkg/path/filepath/match_test.go
+++ b/src/pkg/path/filepath/match_test.go
@@ -69,6 +69,13 @@ var matchTests = []MatchTest{
 	{"*x", "xxx", true, nil},
 }
 
+func errp(e os.Error) string {
+	if e == nil {
+		return "<nil>"
+	}
+	return e.String()
+}
+
 func TestMatch(t *testing.T) {
 	if runtime.GOOS == "windows" {
 		// XXX: Don't pass for windows.
@@ -77,7 +84,7 @@ func TestMatch(t *testing.T) {
 	for _, tt := range matchTests {
 		ok, err := Match(tt.pattern, tt.s)
 		if ok != tt.match || err != tt.err {
-			t.Errorf("Match(%#q, %#q) = %v, %v want %v, nil", tt.pattern, tt.s, ok, err, tt.match)
+			t.Errorf("Match(%#q, %#q) = %v, %q want %v, %q", tt.pattern, tt.s, ok, errp(err), tt.match, errp(tt.err))
 		}
 	}
 }
diff --git a/src/pkg/path/filepath/path.go b/src/pkg/path/filepath/path.go
index 6917218..dcd8017 100644
--- a/src/pkg/path/filepath/path.go
+++ b/src/pkg/path/filepath/path.go
@@ -15,8 +15,8 @@ import (
 )
 
 const (
-	SeparatorString     = string(Separator)
-	ListSeparatorString = string(ListSeparator)
+	Separator     = os.PathSeparator
+	ListSeparator = os.PathListSeparator
 )
 
 // Clean returns the shortest path name equivalent to path
@@ -61,20 +61,20 @@ func Clean(path string) string {
 
 	for r < n {
 		switch {
-		case isSeparator(path[r]):
+		case os.IsPathSeparator(path[r]):
 			// empty path element
 			r++
-		case path[r] == '.' && (r+1 == n || isSeparator(path[r+1])):
+		case path[r] == '.' && (r+1 == n || os.IsPathSeparator(path[r+1])):
 			// . element
 			r++
-		case path[r] == '.' && path[r+1] == '.' && (r+2 == n || isSeparator(path[r+2])):
+		case path[r] == '.' && path[r+1] == '.' && (r+2 == n || os.IsPathSeparator(path[r+2])):
 			// .. element: remove to last separator
 			r += 2
 			switch {
 			case w > dotdot:
 				// can backtrack
 				w--
-				for w > dotdot && !isSeparator(buf[w]) {
+				for w > dotdot && !os.IsPathSeparator(buf[w]) {
 					w--
 				}
 			case !rooted:
@@ -97,7 +97,7 @@ func Clean(path string) string {
 				w++
 			}
 			// copy element
-			for ; r < n && !isSeparator(path[r]); r++ {
+			for ; r < n && !os.IsPathSeparator(path[r]); r++ {
 				buf[w] = path[r]
 				w++
 			}
@@ -119,7 +119,7 @@ func ToSlash(path string) string {
 	if Separator == '/' {
 		return path
 	}
-	return strings.Replace(path, SeparatorString, "/", -1)
+	return strings.Replace(path, string(Separator), "/", -1)
 }
 
 // FromSlash returns the result of replacing each slash ('/') character
@@ -128,7 +128,7 @@ func FromSlash(path string) string {
 	if Separator == '/' {
 		return path
 	}
-	return strings.Replace(path, "/", SeparatorString, -1)
+	return strings.Replace(path, "/", string(Separator), -1)
 }
 
 // SplitList splits a list of paths joined by the OS-specific ListSeparator.
@@ -136,7 +136,7 @@ func SplitList(path string) []string {
 	if path == "" {
 		return []string{}
 	}
-	return strings.Split(path, ListSeparatorString, -1)
+	return strings.Split(path, string(ListSeparator), -1)
 }
 
 // Split splits path immediately following the final Separator,
@@ -145,7 +145,7 @@ func SplitList(path string) []string {
 // and file set to path.
 func Split(path string) (dir, file string) {
 	i := len(path) - 1
-	for i >= 0 && !isSeparator(path[i]) {
+	for i >= 0 && !os.IsPathSeparator(path[i]) {
 		i--
 	}
 	return path[:i+1], path[i+1:]
@@ -156,7 +156,7 @@ func Split(path string) (dir, file string) {
 func Join(elem ...string) string {
 	for i, e := range elem {
 		if e != "" {
-			return Clean(strings.Join(elem[i:], SeparatorString))
+			return Clean(strings.Join(elem[i:], string(Separator)))
 		}
 	}
 	return ""
@@ -167,7 +167,7 @@ func Join(elem ...string) string {
 // in the final element of path; it is empty if there is
 // no dot.
 func Ext(path string) string {
-	for i := len(path) - 1; i >= 0 && !isSeparator(path[i]); i-- {
+	for i := len(path) - 1; i >= 0 && !os.IsPathSeparator(path[i]); i-- {
 		if path[i] == '.' {
 			return path[i:]
 		}
@@ -234,7 +234,7 @@ func EvalSymlinks(path string) (string, os.Error) {
 		if IsAbs(dest) {
 			b.Reset()
 		}
-		path = dest + SeparatorString + path
+		path = dest + string(Separator) + path
 	}
 	return Clean(b.String()), nil
 }
@@ -245,7 +245,7 @@ func EvalSymlinks(path string) (string, os.Error) {
 // path name for a given file is not guaranteed to be unique.
 func Abs(path string) (string, os.Error) {
 	if IsAbs(path) {
-		return path, nil
+		return Clean(path), nil
 	}
 	wd, err := os.Getwd()
 	if err != nil {
@@ -339,12 +339,12 @@ func Base(path string) string {
 		return "."
 	}
 	// Strip trailing slashes.
-	for len(path) > 0 && isSeparator(path[len(path)-1]) {
+	for len(path) > 0 && os.IsPathSeparator(path[len(path)-1]) {
 		path = path[0 : len(path)-1]
 	}
 	// Find the last element
 	i := len(path) - 1
-	for i >= 0 && !isSeparator(path[i]) {
+	for i >= 0 && !os.IsPathSeparator(path[i]) {
 		i--
 	}
 	if i >= 0 {
@@ -352,7 +352,7 @@ func Base(path string) string {
 	}
 	// If empty now, it had only slashes.
 	if path == "" {
-		return SeparatorString
+		return string(Separator)
 	}
 	return path
 }
diff --git a/src/pkg/path/filepath/path_plan9.go b/src/pkg/path/filepath/path_plan9.go
index e400083..47990e0 100644
--- a/src/pkg/path/filepath/path_plan9.go
+++ b/src/pkg/path/filepath/path_plan9.go
@@ -6,16 +6,6 @@ package filepath
 
 import "strings"
 
-const (
-	Separator     = '/' // OS-specific path separator
-	ListSeparator = 0   // OS-specific path list separator
-)
-
-// isSeparator returns true if c is a directory separator character.
-func isSeparator(c uint8) bool {
-	return Separator == c
-}
-
 // IsAbs returns true if the path is absolute.
 func IsAbs(path string) bool {
 	return strings.HasPrefix(path, "/") || strings.HasPrefix(path, "#")
diff --git a/src/pkg/path/filepath/path_test.go b/src/pkg/path/filepath/path_test.go
index b147349..6a5dd5b 100644
--- a/src/pkg/path/filepath/path_test.go
+++ b/src/pkg/path/filepath/path_test.go
@@ -315,7 +315,10 @@ func TestWalk(t *testing.T) {
 	}
 	checkMarks(t)
 
-	if os.Getuid() > 0 {
+	// Test permission errors.  Only possible if we're not root
+	// and only on some file systems (AFS, FAT).  To avoid errors during
+	// all.bash on those file systems, skip during gotest -short.
+	if os.Getuid() > 0 && !testing.Short() {
 		// introduce 2 errors: chmod top-level directories to 0
 		os.Chmod(filepath.Join(tree.name, tree.entries[1].name), 0)
 		os.Chmod(filepath.Join(tree.name, tree.entries[3].name), 0)
@@ -509,6 +512,7 @@ var abstests = []string{
 
 	// Already absolute
 	"$GOROOT/src/Make.pkg",
+	"$GOROOT/src/../src/Make.pkg",
 }
 
 func TestAbs(t *testing.T) {
@@ -537,5 +541,8 @@ func TestAbs(t *testing.T) {
 		if !filepath.IsAbs(abspath) {
 			t.Errorf("Abs(%q)=%q, not an absolute path", path, abspath)
 		}
+		if filepath.IsAbs(path) && abspath != filepath.Clean(path) {
+			t.Errorf("Abs(%q)=%q, isn't clean", path, abspath)
+		}
 	}
 }
diff --git a/src/pkg/path/filepath/path_unix.go b/src/pkg/path/filepath/path_unix.go
index f8ac248..ea555fc 100644
--- a/src/pkg/path/filepath/path_unix.go
+++ b/src/pkg/path/filepath/path_unix.go
@@ -6,16 +6,6 @@ package filepath
 
 import "strings"
 
-const (
-	Separator     = '/' // OS-specific path separator
-	ListSeparator = ':' // OS-specific path list separator
-)
-
-// isSeparator returns true if c is a directory separator character.
-func isSeparator(c uint8) bool {
-	return Separator == c
-}
-
 // IsAbs returns true if the path is absolute.
 func IsAbs(path string) bool {
 	return strings.HasPrefix(path, "/")
diff --git a/src/pkg/path/filepath/path_windows.go b/src/pkg/path/filepath/path_windows.go
index dbd1c1e..35302eb 100644
--- a/src/pkg/path/filepath/path_windows.go
+++ b/src/pkg/path/filepath/path_windows.go
@@ -4,20 +4,11 @@
 
 package filepath
 
-const (
-	Separator     = '\\' // OS-specific path separator
-	ListSeparator = ':'  // OS-specific path list separator
-)
-
-// isSeparator returns true if c is a directory separator character.
-func isSeparator(c uint8) bool {
-	// NOTE: Windows accept / as path separator.
-	return c == '\\' || c == '/'
-}
+import "os"
 
 // IsAbs returns true if the path is absolute.
 func IsAbs(path string) bool {
-	return path != "" && (volumeName(path) != "" || isSeparator(path[0]))
+	return path != "" && (volumeName(path) != "" || os.IsPathSeparator(path[0]))
 }
 
 // volumeName return leading volume name.  
@@ -28,7 +19,7 @@ func volumeName(path string) string {
 	}
 	// with drive letter
 	c := path[0]
-	if len(path) > 2 && path[1] == ':' && isSeparator(path[2]) &&
+	if len(path) > 2 && path[1] == ':' && os.IsPathSeparator(path[2]) &&
 		('0' <= c && c <= '9' || 'a' <= c && c <= 'z' ||
 			'A' <= c && c <= 'Z') {
 		return path[0:2]
diff --git a/src/pkg/reflect/value.go b/src/pkg/reflect/value.go
index 2c2158a..3abe13e 100644
--- a/src/pkg/reflect/value.go
+++ b/src/pkg/reflect/value.go
@@ -173,7 +173,7 @@ type nonEmptyInterface struct {
 // 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 whcih one cannot
+// 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
diff --git a/src/pkg/regexp/all_test.go b/src/pkg/regexp/all_test.go
index c7ee4c8..71edc4d 100644
--- a/src/pkg/regexp/all_test.go
+++ b/src/pkg/regexp/all_test.go
@@ -356,7 +356,7 @@ func BenchmarkMatchClass(b *testing.B) {
 
 func BenchmarkMatchClass_InRange(b *testing.B) {
 	b.StopTimer()
-	// 'b' is betwen 'a' and 'c', so the charclass
+	// 'b' is between 'a' and 'c', so the charclass
 	// range checking is no help here.
 	x := strings.Repeat("bbbb", 20) + "c"
 	re := MustCompile("[ac]")
diff --git a/src/pkg/runtime/arm/vlop.s b/src/pkg/runtime/arm/vlop.s
index 2c5d7eb..fc679f0 100644
--- a/src/pkg/runtime/arm/vlop.s
+++ b/src/pkg/runtime/arm/vlop.s
@@ -105,7 +105,7 @@ loop:
 
 /*
  * compare numerator to denominator
- * if less, subtract and set quotent bit
+ * if less, subtract and set quotient bit
  */
 	CMP	R(D), R(N)
 	ORR.HS  $1, R(Q)
diff --git a/src/pkg/runtime/closure_test.go b/src/pkg/runtime/closure_test.go
new file mode 100644
index 0000000..ea65fbd
--- /dev/null
+++ b/src/pkg/runtime/closure_test.go
@@ -0,0 +1,53 @@
+// Copyright 2011 The Go Authors. 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 "testing"
+
+var s int
+
+func BenchmarkCallClosure(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		s += func(ii int) int { return 2 * ii }(i)
+	}
+}
+
+func BenchmarkCallClosure1(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		j := i
+		s += func(ii int) int { return 2*ii + j }(i)
+	}
+}
+
+var ss *int
+
+func BenchmarkCallClosure2(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		j := i
+		s += func() int {
+			ss = &j
+			return 2
+		}()
+	}
+}
+
+func addr1(x int) *int {
+	return func() *int { return &x }()
+}
+
+func BenchmarkCallClosure3(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		ss = addr1(i)
+	}
+}
+
+func addr2() (x int, p *int) {
+	return 0, func() *int { return &x }()
+}
+
+func BenchmarkCallClosure4(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		_, ss = addr2()
+	}
+}
diff --git a/src/pkg/runtime/linux/mem.c b/src/pkg/runtime/linux/mem.c
index ce1a8aa..02f7987 100644
--- a/src/pkg/runtime/linux/mem.c
+++ b/src/pkg/runtime/linux/mem.c
@@ -39,13 +39,19 @@ runtime·SysFree(void *v, uintptr 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;
 	
-	return runtime·mmap(v, n, PROT_NONE, MAP_ANON|MAP_PRIVATE, -1, 0);
+	p = runtime·mmap(v, n, PROT_NONE, MAP_ANON|MAP_PRIVATE, -1, 0);
+	if(p < (void*)4096) {
+		return nil;
+	}
+	return p;
 }
 
 enum
@@ -63,6 +69,8 @@ runtime·SysMap(void *v, uintptr 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");
@@ -71,7 +79,7 @@ runtime·SysMap(void *v, uintptr n)
 	}
 
 	p = runtime·mmap(v, n, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANON|MAP_FIXED|MAP_PRIVATE, -1, 0);
-	if(p == (void*)-ENOMEM)
+	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/thread.c b/src/pkg/runtime/linux/thread.c
index 6c50623..7c7ca7b 100644
--- a/src/pkg/runtime/linux/thread.c
+++ b/src/pkg/runtime/linux/thread.c
@@ -116,7 +116,7 @@ again:
 	//
 	// We only really care that (v&1) == 1 (the lock is held),
 	// and in fact there is a futex variant that could
-	// accomodate that check, but let's not get carried away.)
+	// accommodate that check, but let's not get carried away.)
 	futexsleep(&l->key, v+2);
 
 	// We're awake: remove ourselves from the count.
diff --git a/src/pkg/runtime/mprof.goc b/src/pkg/runtime/mprof.goc
index aae3d18..517f96a 100644
--- a/src/pkg/runtime/mprof.goc
+++ b/src/pkg/runtime/mprof.goc
@@ -113,7 +113,7 @@ static uintptr addrmem;
 // hashMultiplier is the bottom 32 bits of int((sqrt(5)-1)/2 * (1<<32)).
 // This is a good multiplier as suggested in CLR, Knuth.  The hash
 // value is taken to be the top AddrHashBits bits of the bottom 32 bits
-// of the muliplied value.
+// of the multiplied value.
 enum {
 	HashMultiplier = 2654435769U
 };
diff --git a/src/pkg/runtime/proc_test.go b/src/pkg/runtime/proc_test.go
index a15b2d8..cac4f9e 100644
--- a/src/pkg/runtime/proc_test.go
+++ b/src/pkg/runtime/proc_test.go
@@ -24,20 +24,23 @@ func TestStopTheWorldDeadlock(t *testing.T) {
 		t.Logf("skipping during short test")
 		return
 	}
-	runtime.GOMAXPROCS(3)
-	compl := make(chan int, 1)
+	maxprocs := runtime.GOMAXPROCS(3)
+	compl := make(chan bool, 2)
 	go func() {
 		for i := 0; i != 1000; i += 1 {
 			runtime.GC()
 		}
-		compl <- 0
+		compl <- true
 	}()
 	go func() {
 		for i := 0; i != 1000; i += 1 {
 			runtime.GOMAXPROCS(3)
 		}
+		compl <- true
 	}()
 	go perpetuumMobile()
 	<-compl
+	<-compl
 	stop <- true
+	runtime.GOMAXPROCS(maxprocs)
 }
diff --git a/src/pkg/runtime/runtime-gdb.py b/src/pkg/runtime/runtime-gdb.py
index 3f767fb..a96f3f3 100644
--- a/src/pkg/runtime/runtime-gdb.py
+++ b/src/pkg/runtime/runtime-gdb.py
@@ -2,7 +2,7 @@
 # Use of this source code is governed by a BSD-style
 # license that can be found in the LICENSE file.
 
-"""GDB Pretty printers and convencience functions for Go's runtime structures.
+"""GDB Pretty printers and convenience functions for Go's runtime structures.
 
 This script is loaded by GDB when it finds a .debug_gdb_scripts
 section in the compiled binary.  The [68]l linkers emit this with a
@@ -393,7 +393,7 @@ class GoIfaceCmd(gdb.Command):
 # so Itype will start with a commontype which has kind = interface
 
 #
-# Register all convience functions and CLI commands
+# Register all convenience functions and CLI commands
 #
 for k in vars().values():
 	if hasattr(k, 'invoke'):
diff --git a/src/pkg/runtime/runtime.h b/src/pkg/runtime/runtime.h
index f2f8dcd..2b2b34a 100644
--- a/src/pkg/runtime/runtime.h
+++ b/src/pkg/runtime/runtime.h
@@ -306,7 +306,7 @@ enum {
 
 /*
  * defined macros
- *    you need super-goru privilege
+ *    you need super-gopher-guru privilege
  *    to add this list.
  */
 #define	nelem(x)	(sizeof(x)/sizeof((x)[0]))
diff --git a/src/pkg/runtime/windows/386/sys.s b/src/pkg/runtime/windows/386/sys.s
index 15f7f95..d384050 100644
--- a/src/pkg/runtime/windows/386/sys.s
+++ b/src/pkg/runtime/windows/386/sys.s
@@ -59,15 +59,21 @@ TEXT runtime·setlasterror(SB),7,$0
 
 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-28
+TEXT runtime·sigtramp1(SB),0,$16-40
 	// unwinding?
-	MOVL	info+12(FP), BX
+	MOVL	info+24(FP), BX
 	MOVL	4(BX), CX		// exception flags
 	ANDL	$6, CX
 	MOVL	$1, AX
@@ -75,15 +81,15 @@ TEXT runtime·sigtramp1(SB),0,$16-28
 
 	// place ourselves at the top of the SEH chain to
 	// ensure SEH frames lie within thread stack bounds
-	MOVL	frame+16(FP), CX	// our SEH frame
+	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+20(FP), BX
+	MOVL	context+32(FP), BX
 	MOVL	BX, 8(SP)
-	MOVL	dispatcher+24(FP), BX
+	MOVL	dispatcher+36(FP), BX
 	MOVL	BX, 12(SP)
 
 	CALL	runtime·sighandler(SB)
diff --git a/src/pkg/runtime/windows/thread.c b/src/pkg/runtime/windows/thread.c
index 2ce92dc..2ce8fae 100644
--- a/src/pkg/runtime/windows/thread.c
+++ b/src/pkg/runtime/windows/thread.c
@@ -324,13 +324,31 @@ runtime·ctrlhandler1(uint32 type)
 	return 0;
 }
 
+// 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)
 {
 	Func *f;
 	int32 argsize, n;
-	byte *ret, *p;
+	byte *p;
+	Callback *c;
 
 	if(fn.type->kind != KindFunc)
 		runtime·panicstring("not a function");
@@ -348,7 +366,23 @@ runtime·compilecallback(Eface fn, bool cleanstack)
 	if(cleanstack)
 		n += 2;		// ... argsize
 
-	ret = p = runtime·mal(n);
+	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 >= 20)
+		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;
@@ -376,7 +410,7 @@ runtime·compilecallback(Eface fn, bool cleanstack)
 	} else
 		*p = 0xc3;
 
-	return ret;
+	return &c->asmbody;
 }
 
 void
diff --git a/src/pkg/smtp/smtp.go b/src/pkg/smtp/smtp.go
index 3f89af1..d716df5 100644
--- a/src/pkg/smtp/smtp.go
+++ b/src/pkg/smtp/smtp.go
@@ -151,8 +151,7 @@ func (c *Client) Auth(a Auth) os.Error {
 		var msg []byte
 		switch code {
 		case 334:
-			msg = make([]byte, encoding.DecodedLen(len(msg64)))
-			_, err = encoding.Decode(msg, []byte(msg64))
+			msg, err = encoding.DecodeString(msg64)
 		case 235:
 			// the last message isn't base64 because it isn't a challenge
 			msg = []byte(msg64)
diff --git a/src/pkg/strconv/decimal.go b/src/pkg/strconv/decimal.go
index 3a5cf1b..783065b 100644
--- a/src/pkg/strconv/decimal.go
+++ b/src/pkg/strconv/decimal.go
@@ -108,7 +108,7 @@ func newDecimal(i uint64) *decimal {
 }
 
 // Maximum shift that we can do in one pass without overflow.
-// Signed int has 31 bits, and we have to be able to accomodate 9<<k.
+// Signed int has 31 bits, and we have to be able to accommodate 9<<k.
 const maxShift = 27
 
 // Binary shift right (* 2) by k bits.  k <= maxShift to avoid overflow.
diff --git a/src/pkg/strconv/quote.go b/src/pkg/strconv/quote.go
index ed58897..bbc0b26 100644
--- a/src/pkg/strconv/quote.go
+++ b/src/pkg/strconv/quote.go
@@ -14,17 +14,14 @@ import (
 
 const lowerhex = "0123456789abcdef"
 
-// Quote returns a double-quoted Go string literal
-// representing s.  The returned string s uses Go escape
-// sequences (\t, \n, \xFF, \u0100) for control characters
-// and non-ASCII characters.
-func Quote(s string) string {
+func quoteWith(s string, quote byte) string {
 	var buf bytes.Buffer
-	buf.WriteByte('"')
+	buf.WriteByte(quote)
 	for ; len(s) > 0; s = s[1:] {
 		switch c := s[0]; {
-		case c == '"':
-			buf.WriteString(`\"`)
+		case c == quote:
+			buf.WriteByte('\\')
+			buf.WriteByte(quote)
 		case c == '\\':
 			buf.WriteString(`\\`)
 		case ' ' <= c && c <= '~':
@@ -69,8 +66,26 @@ func Quote(s string) string {
 			buf.WriteByte(lowerhex[c&0xF])
 		}
 	}
-	buf.WriteByte('"')
+	buf.WriteByte(quote)
 	return buf.String()
+
+}
+
+// Quote returns a double-quoted Go string literal
+// representing s.  The returned string uses Go escape
+// sequences (\t, \n, \xFF, \u0100) for control characters
+// and non-ASCII characters.
+func Quote(s string) string {
+	return quoteWith(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-ASCII characters.
+func QuoteRune(rune int) string {
+	// TODO: avoid the allocation here.
+	return quoteWith(string(rune), '\'')
 }
 
 // CanBackquote returns whether the string s would be
diff --git a/src/pkg/strconv/quote_test.go b/src/pkg/strconv/quote_test.go
index 1235fcb..3232d61 100644
--- a/src/pkg/strconv/quote_test.go
+++ b/src/pkg/strconv/quote_test.go
@@ -25,14 +25,37 @@ var quotetests = []quoteTest{
 }
 
 func TestQuote(t *testing.T) {
-	for i := 0; i < len(quotetests); i++ {
-		tt := quotetests[i]
+	for _, tt := range quotetests {
 		if out := Quote(tt.in); out != tt.out {
 			t.Errorf("Quote(%s) = %s, want %s", tt.in, out, tt.out)
 		}
 	}
 }
 
+type quoteRuneTest struct {
+	in  int
+	out string
+}
+
+var quoterunetests = []quoteRuneTest{
+	{'a', `'a'`},
+	{'\a', `'\a'`},
+	{'\\', `'\\'`},
+	{0xFF, `'\u00ff'`},
+	{0x263a, `'\u263a'`},
+	{0x0010ffff, `'\U0010ffff'`},
+	{0x0010ffff + 1, `'\ufffd'`},
+	{0x04, `'\x04'`},
+}
+
+func TestQuoteRune(t *testing.T) {
+	for _, tt := range quoterunetests {
+		if out := QuoteRune(tt.in); out != tt.out {
+			t.Errorf("QuoteRune(%U) = %s, want %s", tt.in, out, tt.out)
+		}
+	}
+}
+
 type canBackquoteTest struct {
 	in  string
 	out bool
@@ -80,8 +103,7 @@ var canbackquotetests = []canBackquoteTest{
 }
 
 func TestCanBackquote(t *testing.T) {
-	for i := 0; i < len(canbackquotetests); i++ {
-		tt := canbackquotetests[i]
+	for _, tt := range canbackquotetests {
 		if out := CanBackquote(tt.in); out != tt.out {
 			t.Errorf("CanBackquote(%q) = %v, want %v", tt.in, out, tt.out)
 		}
@@ -146,23 +168,20 @@ var misquoted = []string{
 }
 
 func TestUnquote(t *testing.T) {
-	for i := 0; i < len(unquotetests); i++ {
-		tt := unquotetests[i]
+	for _, tt := range unquotetests {
 		if out, err := Unquote(tt.in); err != nil && out != tt.out {
 			t.Errorf("Unquote(%#q) = %q, %v want %q, nil", tt.in, out, err, tt.out)
 		}
 	}
 
 	// run the quote tests too, backward
-	for i := 0; i < len(quotetests); i++ {
-		tt := quotetests[i]
+	for _, tt := range quotetests {
 		if in, err := Unquote(tt.out); in != tt.in {
 			t.Errorf("Unquote(%#q) = %q, %v, want %q, nil", tt.out, in, err, tt.in)
 		}
 	}
 
-	for i := 0; i < len(misquoted); i++ {
-		s := misquoted[i]
+	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)
 		}
diff --git a/src/pkg/strings/reader.go b/src/pkg/strings/reader.go
index 4eae90e..10b0278 100644
--- a/src/pkg/strings/reader.go
+++ b/src/pkg/strings/reader.go
@@ -9,50 +9,84 @@ import (
 	"utf8"
 )
 
-// A Reader satisfies calls to Read, ReadByte, and ReadRune by
-// reading from a string.
-type Reader string
+// A Reader implements the io.Reader, io.ByteScanner, and
+// io.RuneScanner interfaces by reading from a string.
+type Reader struct {
+	s        string
+	i        int // current reading index
+	prevRune int // index of previous rune; or < 0
+}
+
+// Len returns the number of bytes of the unread portion of the
+// string.
+func (r *Reader) Len() int {
+	return len(r.s) - r.i
+}
 
 func (r *Reader) Read(b []byte) (n int, err os.Error) {
-	s := *r
-	if len(s) == 0 {
+	if r.i >= len(r.s) {
 		return 0, os.EOF
 	}
-	n = copy(b, s)
-	*r = s[n:]
+	n = copy(b, r.s[r.i:])
+	r.i += n
+	r.prevRune = -1
 	return
 }
 
 func (r *Reader) ReadByte() (b byte, err os.Error) {
-	s := *r
-	if len(s) == 0 {
+	if r.i >= len(r.s) {
 		return 0, os.EOF
 	}
-	b = s[0]
-	*r = s[1:]
+	b = r.s[r.i]
+	r.i++
+	r.prevRune = -1
 	return
 }
 
+
+// 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 {
+	if r.i <= 0 {
+		return os.ErrorString("strings.Reader: at beginning of string")
+	}
+	r.i--
+	r.prevRune = -1
+	return nil
+}
+
 // 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 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) {
-	s := *r
-	if len(s) == 0 {
+	if r.i >= len(r.s) {
 		return 0, 0, os.EOF
 	}
-	c := s[0]
-	if c < utf8.RuneSelf {
-		*r = s[1:]
+	r.prevRune = r.i
+	if c := r.s[r.i]; c < utf8.RuneSelf {
+		r.i++
 		return int(c), 1, nil
 	}
-	rune, size = utf8.DecodeRuneInString(string(s))
-	*r = s[size:]
+	rune, size = utf8.DecodeRuneInString(r.s[r.i:])
+	r.i += size
 	return
 }
 
+// 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 {
+	if r.prevRune < 0 {
+		return os.ErrorString("strings.Reader: previous operation was not ReadRune")
+	}
+	r.i = r.prevRune
+	r.prevRune = -1
+	return nil
+}
+
 // NewReader returns a new Reader reading from s.
 // It is similar to bytes.NewBufferString but more efficient and read-only.
-func NewReader(s string) *Reader { return (*Reader)(&s) }
+func NewReader(s string) *Reader { return &Reader{s, 0, -1} }
diff --git a/src/pkg/strings/strings_test.go b/src/pkg/strings/strings_test.go
index c45b148..a1a635d 100644
--- a/src/pkg/strings/strings_test.go
+++ b/src/pkg/strings/strings_test.go
@@ -5,6 +5,7 @@
 package strings_test
 
 import (
+	"bytes"
 	"os"
 	"reflect"
 	"strconv"
@@ -751,13 +752,56 @@ func TestRunes(t *testing.T) {
 	}
 }
 
+func TestReadByte(t *testing.T) {
+	testStrings := []string{"", abcd, faces, commas}
+	for _, s := range testStrings {
+		reader := NewReader(s)
+		if e := reader.UnreadByte(); e == nil {
+			t.Errorf("Unreading %q at beginning: expected error", s)
+		}
+		var res bytes.Buffer
+		for {
+			b, e := reader.ReadByte()
+			if e == os.EOF {
+				break
+			}
+			if e != nil {
+				t.Errorf("Reading %q: %s", s, e)
+				break
+			}
+			res.WriteByte(b)
+			// unread and read again
+			e = reader.UnreadByte()
+			if e != nil {
+				t.Errorf("Unreading %q: %s", s, e)
+				break
+			}
+			b1, e := reader.ReadByte()
+			if e != nil {
+				t.Errorf("Reading %q after unreading: %s", s, e)
+				break
+			}
+			if b1 != b {
+				t.Errorf("Reading %q after unreading: want byte %q, got %q", s, b, b1)
+				break
+			}
+		}
+		if res.String() != s {
+			t.Errorf("Reader(%q).ReadByte() produced %q", s, res.String())
+		}
+	}
+}
+
 func TestReadRune(t *testing.T) {
 	testStrings := []string{"", abcd, faces, commas}
 	for _, s := range testStrings {
 		reader := NewReader(s)
+		if e := reader.UnreadRune(); e == nil {
+			t.Errorf("Unreading %q at beginning: expected error", s)
+		}
 		res := ""
 		for {
-			r, _, e := reader.ReadRune()
+			r, z, e := reader.ReadRune()
 			if e == os.EOF {
 				break
 			}
@@ -766,6 +810,25 @@ func TestReadRune(t *testing.T) {
 				break
 			}
 			res += string(r)
+			// unread and read again
+			e = reader.UnreadRune()
+			if e != nil {
+				t.Errorf("Unreading %q: %s", s, e)
+				break
+			}
+			r1, z1, e := reader.ReadRune()
+			if e != nil {
+				t.Errorf("Reading %q after unreading: %s", s, e)
+				break
+			}
+			if r1 != r {
+				t.Errorf("Reading %q after unreading: want rune %q, got %q", s, r, r1)
+				break
+			}
+			if z1 != z {
+				t.Errorf("Reading %q after unreading: want size %d, got %d", s, z, z1)
+				break
+			}
 		}
 		if res != s {
 			t.Errorf("Reader(%q).ReadRune() produced %q", s, res)
diff --git a/src/pkg/sync/atomic/asm_arm.s b/src/pkg/sync/atomic/asm_arm.s
index 3363bbc..448a98a 100644
--- a/src/pkg/sync/atomic/asm_arm.s
+++ b/src/pkg/sync/atomic/asm_arm.s
@@ -87,11 +87,14 @@ add64loop:
 // which will make uses of the 64-bit atomic operations loop forever.
 // If things are working, set okLDREXD to avoid future checks.
 // https://bugs.launchpad.net/qemu/+bug/670883.
-TEXT	check64<>(SB),7,$8
+TEXT	check64<>(SB),7,$16
 	MOVW	$10, R1
+	// 8-aligned stack address scratch space.
+	MOVW	$8(SP), R3
+	AND	$~7, R3
 loop:
-	LDREXD	(SP), R2
-	STREXD	R2, (SP), R0
+	LDREXD	(R3), R2
+	STREXD	R2, (R3), R0
 	CMP	$0, R0
 	BEQ	ok
 	SUB	$1, R1
diff --git a/src/pkg/sync/cond.go b/src/pkg/sync/cond.go
index ea48f2e..75494b5 100644
--- a/src/pkg/sync/cond.go
+++ b/src/pkg/sync/cond.go
@@ -14,10 +14,26 @@ import "runtime"
 // which must be held when changing the condition and
 // when calling the Wait method.
 type Cond struct {
-	L       Locker // held while observing or changing the condition
-	m       Mutex  // held to avoid internal races
-	waiters int    // number of goroutines blocked on Wait
-	sema    *uint32
+	L Locker // held while observing or changing the condition
+	m Mutex  // held to avoid internal races
+
+	// We must be careful to make sure that when Signal
+	// releases a semaphore, the corresponding acquire is
+	// executed by a goroutine that was already waiting at
+	// the time of the call to Signal, not one that arrived later.
+	// To ensure this, we segment waiting goroutines into
+	// generations punctuated by calls to Signal.  Each call to
+	// Signal begins another generation if there are no goroutines
+	// left in older generations for it to wake.  Because of this
+	// optimization (only begin another generation if there
+	// are no older goroutines left), we only need to keep track
+	// of the two most recent generations, which we call old
+	// and new.
+	oldWaiters int     // number of waiters in old generation...
+	oldSema    *uint32 // ... waiting on this semaphore
+
+	newWaiters int     // number of waiters in new generation...
+	newSema    *uint32 // ... waiting on this semaphore
 }
 
 // NewCond returns a new Cond with Locker l.
@@ -42,11 +58,11 @@ func NewCond(l Locker) *Cond {
 //
 func (c *Cond) Wait() {
 	c.m.Lock()
-	if c.sema == nil {
-		c.sema = new(uint32)
+	if c.newSema == nil {
+		c.newSema = new(uint32)
 	}
-	s := c.sema
-	c.waiters++
+	s := c.newSema
+	c.newWaiters++
 	c.m.Unlock()
 	c.L.Unlock()
 	runtime.Semacquire(s)
@@ -59,9 +75,16 @@ func (c *Cond) Wait() {
 // during the call.
 func (c *Cond) Signal() {
 	c.m.Lock()
-	if c.waiters > 0 {
-		c.waiters--
-		runtime.Semrelease(c.sema)
+	if c.oldWaiters == 0 && c.newWaiters > 0 {
+		// Retire old generation; rename new to old.
+		c.oldWaiters = c.newWaiters
+		c.oldSema = c.newSema
+		c.newWaiters = 0
+		c.newSema = nil
+	}
+	if c.oldWaiters > 0 {
+		c.oldWaiters--
+		runtime.Semrelease(c.oldSema)
 	}
 	c.m.Unlock()
 }
@@ -72,19 +95,19 @@ func (c *Cond) Signal() {
 // during the call.
 func (c *Cond) Broadcast() {
 	c.m.Lock()
-	if c.waiters > 0 {
-		s := c.sema
-		n := c.waiters
-		for i := 0; i < n; i++ {
-			runtime.Semrelease(s)
+	// Wake both generations.
+	if c.oldWaiters > 0 {
+		for i := 0; i < c.oldWaiters; i++ {
+			runtime.Semrelease(c.oldSema)
+		}
+		c.oldWaiters = 0
+	}
+	if c.newWaiters > 0 {
+		for i := 0; i < c.newWaiters; i++ {
+			runtime.Semrelease(c.newSema)
 		}
-		// We just issued n wakeups via the semaphore s.
-		// To ensure that they wake up the existing waiters
-		// and not waiters that arrive after Broadcast returns,
-		// clear c.sema.  The next operation will allocate
-		// a new one.
-		c.sema = nil
-		c.waiters = 0
+		c.newWaiters = 0
+		c.newSema = nil
 	}
 	c.m.Unlock()
 }
diff --git a/src/pkg/sync/cond_test.go b/src/pkg/sync/cond_test.go
index 846f98b..cefacb1 100644
--- a/src/pkg/sync/cond_test.go
+++ b/src/pkg/sync/cond_test.go
@@ -46,6 +46,33 @@ func TestCondSignal(t *testing.T) {
 	c.Signal()
 }
 
+func TestCondSignalGenerations(t *testing.T) {
+	var m Mutex
+	c := NewCond(&m)
+	n := 100
+	running := make(chan bool, n)
+	awake := make(chan int, n)
+	for i := 0; i < n; i++ {
+		go func(i int) {
+			m.Lock()
+			running <- true
+			c.Wait()
+			awake <- i
+			m.Unlock()
+		}(i)
+		if i > 0 {
+			a := <-awake
+			if a != i-1 {
+				t.Fatalf("wrong goroutine woke up: want %d, got %d", i-1, a)
+			}
+		}
+		<-running
+		m.Lock()
+		c.Signal()
+		m.Unlock()
+	}
+}
+
 func TestCondBroadcast(t *testing.T) {
 	var m Mutex
 	c := NewCond(&m)
diff --git a/src/pkg/syscall/Makefile b/src/pkg/syscall/Makefile
index 978bc94..9284fcc 100644
--- a/src/pkg/syscall/Makefile
+++ b/src/pkg/syscall/Makefile
@@ -17,24 +17,27 @@ GOFILES=\
 	ztypes_$(GOOS)_$(GOARCH).go\
 
 GOFILES_freebsd=\
+	exec_unix.go\
+	route_bsd.go\
 	syscall_bsd.go\
 	syscall_unix.go\
-	exec_unix.go\
 
 GOFILES_darwin=\
+	exec_unix.go\
+	route_bsd.go\
 	syscall_bsd.go\
 	syscall_unix.go\
-	exec_unix.go\
 
 GOFILES_linux=\
-	syscall_unix.go\
 	exec_unix.go\
+	netlink_linux.go\
+	syscall_unix.go\
 
 GOFILES_windows=\
-	exec_windows.go
-	
+	exec_windows.go\
+
 GOFILES_plan9=\
-	exec_plan9.go
+	exec_plan9.go\
 
 OFILES=\
 	asm_$(GOOS)_$(GOARCH).$O\
diff --git a/src/pkg/syscall/exec_windows.go b/src/pkg/syscall/exec_windows.go
index 85b1c2e..b25f4a6 100644
--- a/src/pkg/syscall/exec_windows.go
+++ b/src/pkg/syscall/exec_windows.go
@@ -14,7 +14,7 @@ import (
 
 var ForkLock sync.RWMutex
 
-// escape rewrites command line argument s as prescribed
+// EscapeArg rewrites command line argument s as prescribed
 // in http://msdn.microsoft.com/en-us/library/ms880421.
 // This function returns "" (2 double quotes) if s is empty.
 // Alternatively, these transformations are done:
@@ -23,7 +23,7 @@ var ForkLock sync.RWMutex
 // - every double quote (") is escaped by back slash (\);
 // - finally, s is wrapped with double quotes (arg -> "arg"),
 //   but only if there is space or tab inside s.
-func escape(s string) string {
+func EscapeArg(s string) string {
 	if len(s) == 0 {
 		return "\"\""
 	}
@@ -89,7 +89,7 @@ func makeCmdLine(args []string) string {
 		if s != "" {
 			s += " "
 		}
-		s += escape(v)
+		s += EscapeArg(v)
 	}
 	return s
 }
@@ -222,6 +222,7 @@ type ProcAttr struct {
 	Env        []string
 	Files      []int
 	HideWindow bool
+	CmdLine    string // used if non-empty, else the windows command line is built by escaping the arguments passed to StartProcess
 }
 
 var zeroAttributes ProcAttr
@@ -252,10 +253,19 @@ func StartProcess(argv0 string, argv []string, attr *ProcAttr) (pid, handle int,
 	}
 	argv0p := StringToUTF16Ptr(argv0)
 
+	var cmdline string
+	// Windows CreateProcess takes the command line as a single string:
+	// use attr.CmdLine if set, else build the command line by escaping
+	// and joining each argument with spaces
+	if attr.CmdLine != "" {
+		cmdline = attr.CmdLine
+	} else {
+		cmdline = makeCmdLine(argv)
+	}
+
 	var argvp *uint16
-	s := makeCmdLine(argv)
-	if len(s) != 0 {
-		argvp = StringToUTF16Ptr(s)
+	if len(cmdline) != 0 {
+		argvp = StringToUTF16Ptr(cmdline)
 	}
 
 	var dirp *uint16
diff --git a/src/pkg/syscall/mkerrors.sh b/src/pkg/syscall/mkerrors.sh
index 3916174..1949ebf 100755
--- a/src/pkg/syscall/mkerrors.sh
+++ b/src/pkg/syscall/mkerrors.sh
@@ -37,6 +37,7 @@ includes_Linux='
 #include <linux/ptrace.h>
 #include <linux/wait.h>
 #include <net/if.h>
+#include <net/if_arp.h>
 #include <netpacket/packet.h>
 '
 
@@ -53,6 +54,7 @@ includes_Darwin='
 #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>
@@ -68,6 +70,7 @@ includes_FreeBSD='
 #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>
@@ -137,9 +140,9 @@ done
 		$2 ~ /^LINUX_REBOOT_CMD_/ ||
 		$2 ~ /^LINUX_REBOOT_MAGIC[12]$/ ||
 		$2 !~ "NLA_TYPE_MASK" &&
-		$2 ~ /^(NETLINK|NLM|NLMSG|NLA|IFA|RTM)_/ ||
+		$2 ~ /^(NETLINK|NLM|NLMSG|NLA|IFA|RTM|RTN|RTPROT|RTA|RTAX|RTNH|ARPHRD)_/ ||
 		$2 ~ /^SIOC/ ||
-		$2 ~ /^(IFF|NET_RT|RTM|RTF|RTV|RTA|RTAX)_/ ||
+		$2 ~ /^(IFF|IFT|NET_RT|RTM|RTF|RTV|RTA|RTAX)_/ ||
 		$2 ~ /^BIOC/ ||
 		$2 !~ /^(BPF_TIMEVAL)$/ &&
 		$2 ~ /^(BPF|DLT)_/ ||
diff --git a/src/pkg/syscall/netlink_linux.go b/src/pkg/syscall/netlink_linux.go
new file mode 100644
index 0000000..681027a
--- /dev/null
+++ b/src/pkg/syscall/netlink_linux.go
@@ -0,0 +1,227 @@
+// Copyright 2011 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Netlink sockets and messages
+
+package syscall
+
+import (
+	"unsafe"
+)
+
+// Round the length of a netlink message up to align it properly.
+func nlmAlignOf(msglen int) int {
+	return (msglen + NLMSG_ALIGNTO - 1) & ^(NLMSG_ALIGNTO - 1)
+}
+
+// Round the length of a netlink route attribute up to align it
+// properly.
+func rtaAlignOf(attrlen int) int {
+	return (attrlen + RTA_ALIGNTO - 1) & ^(RTA_ALIGNTO - 1)
+}
+
+// NetlinkRouteRequest represents the request message to receive
+// routing and link states from the kernel.
+type NetlinkRouteRequest struct {
+	Header NlMsghdr
+	Data   RtGenmsg
+}
+
+func (rr *NetlinkRouteRequest) toWireFormat() []byte {
+	b := make([]byte, rr.Header.Len)
+	b[0] = byte(rr.Header.Len)
+	b[1] = byte(rr.Header.Len >> 8)
+	b[2] = byte(rr.Header.Len >> 16)
+	b[3] = byte(rr.Header.Len >> 24)
+	b[4] = byte(rr.Header.Type)
+	b[5] = byte(rr.Header.Type >> 8)
+	b[6] = byte(rr.Header.Flags)
+	b[7] = byte(rr.Header.Flags >> 8)
+	b[8] = byte(rr.Header.Seq)
+	b[9] = byte(rr.Header.Seq >> 8)
+	b[10] = byte(rr.Header.Seq >> 16)
+	b[11] = byte(rr.Header.Seq >> 24)
+	b[12] = byte(rr.Header.Pid)
+	b[13] = byte(rr.Header.Pid >> 8)
+	b[14] = byte(rr.Header.Pid >> 16)
+	b[15] = byte(rr.Header.Pid >> 24)
+	b[16] = byte(rr.Data.Family)
+	return b
+}
+
+func newNetlinkRouteRequest(proto, seq, family int) []byte {
+	rr := &NetlinkRouteRequest{}
+	rr.Header.Len = NLMSG_HDRLEN + SizeofRtGenmsg
+	rr.Header.Type = uint16(proto)
+	rr.Header.Flags = NLM_F_DUMP | NLM_F_REQUEST
+	rr.Header.Seq = uint32(seq)
+	rr.Data.Family = uint8(family)
+	return rr.toWireFormat()
+}
+
+// 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) {
+	var (
+		s     int
+		e     int
+		lsanl SockaddrNetlink
+		seq   int
+		tab   []byte
+	)
+
+	s, e = Socket(AF_NETLINK, SOCK_RAW, 0)
+	if e != 0 {
+		return nil, e
+	}
+	defer Close(s)
+
+	lsanl.Family = AF_NETLINK
+	e = Bind(s, &lsanl)
+	if e != 0 {
+		return nil, e
+	}
+
+	seq++
+	wb := newNetlinkRouteRequest(proto, seq, family)
+	e = Sendto(s, wb, 0, &lsanl)
+	if e != 0 {
+		return nil, e
+	}
+
+	for {
+		var (
+			rb  []byte
+			nr  int
+			lsa Sockaddr
+		)
+
+		rb = make([]byte, Getpagesize())
+		nr, _, e = Recvfrom(s, rb, 0)
+		if e != 0 {
+			return nil, e
+		}
+		if nr < NLMSG_HDRLEN {
+			return nil, EINVAL
+		}
+		rb = rb[:nr]
+		tab = append(tab, rb...)
+
+		msgs, _ := ParseNetlinkMessage(rb)
+		for _, m := range msgs {
+			if lsa, e = Getsockname(s); e != 0 {
+				return nil, e
+			}
+			switch v := lsa.(type) {
+			case *SockaddrNetlink:
+				if m.Header.Seq != uint32(seq) || m.Header.Pid != v.Pid {
+					return nil, EINVAL
+				}
+			default:
+				return nil, EINVAL
+			}
+			if m.Header.Type == NLMSG_DONE {
+				goto done
+			}
+			if m.Header.Type == NLMSG_ERROR {
+				return nil, EINVAL
+			}
+		}
+	}
+
+done:
+	return tab, 0
+}
+
+// NetlinkMessage represents the netlink message.
+type NetlinkMessage struct {
+	Header NlMsghdr
+	Data   []byte
+}
+
+// ParseNetlinkMessage parses buf as netlink messages and returns
+// the slice containing the NetlinkMessage structs.
+func ParseNetlinkMessage(buf []byte) ([]NetlinkMessage, int) {
+	var (
+		h    *NlMsghdr
+		dbuf []byte
+		dlen int
+		e    int
+		msgs []NetlinkMessage
+	)
+
+	for len(buf) >= NLMSG_HDRLEN {
+		h, dbuf, dlen, e = netlinkMessageHeaderAndData(buf)
+		if e != 0 {
+			break
+		}
+		m := NetlinkMessage{}
+		m.Header = *h
+		m.Data = dbuf[:h.Len-NLMSG_HDRLEN]
+		msgs = append(msgs, m)
+		buf = buf[dlen:]
+	}
+
+	return msgs, e
+}
+
+func netlinkMessageHeaderAndData(buf []byte) (*NlMsghdr, []byte, int, int) {
+	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
+}
+
+// NetlinkRouteAttr represents the netlink route attribute.
+type NetlinkRouteAttr struct {
+	Attr  RtAttr
+	Value []byte
+}
+
+// ParseNetlinkRouteAttr parses msg's payload as netlink route
+// attributes and returns the slice containing the NetlinkRouteAttr
+// structs.
+func ParseNetlinkRouteAttr(msg *NetlinkMessage) ([]NetlinkRouteAttr, int) {
+	var (
+		buf   []byte
+		a     *RtAttr
+		alen  int
+		vbuf  []byte
+		e     int
+		attrs []NetlinkRouteAttr
+	)
+
+	switch msg.Header.Type {
+	case RTM_NEWLINK:
+		buf = msg.Data[SizeofIfInfomsg:]
+	case RTM_NEWADDR:
+		buf = msg.Data[SizeofIfAddrmsg:]
+	default:
+		return nil, EINVAL
+	}
+
+	for len(buf) >= SizeofRtAttr {
+		a, vbuf, alen, e = netlinkRouteAttrAndValue(buf)
+		if e != 0 {
+			break
+		}
+		ra := NetlinkRouteAttr{}
+		ra.Attr = *a
+		ra.Value = vbuf[:a.Len-SizeofRtAttr]
+		attrs = append(attrs, ra)
+		buf = buf[alen:]
+	}
+
+	return attrs, 0
+}
+
+func netlinkRouteAttrAndValue(buf []byte) (*RtAttr, []byte, int, int) {
+	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
+}
diff --git a/src/pkg/syscall/route_bsd.go b/src/pkg/syscall/route_bsd.go
new file mode 100644
index 0000000..79a8793
--- /dev/null
+++ b/src/pkg/syscall/route_bsd.go
@@ -0,0 +1,180 @@
+// Copyright 2011 The Go 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
+
+package syscall
+
+import (
+	"unsafe"
+)
+
+const darwinAMD64 = OS == "darwin" && ARCH == "amd64"
+
+// Round the length of a raw sockaddr up to align it properly.
+func rsaAlignOf(salen int) int {
+	salign := sizeofPtr
+	// NOTE: It seems like 64-bit Darwin kernel still requires 32-bit
+	// aligned access to BSD subsystem.
+	if darwinAMD64 {
+		salign = 4
+	}
+	if salen == 0 {
+		return salign
+	}
+	return (salen + salign - 1) & ^(salign - 1)
+}
+
+// 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
+	)
+
+	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 n == 0 {
+		return nil, 0
+	}
+
+	tab = make([]byte, n)
+	if e = sysctl(mib, &tab[0], &n, nil, 0); e != 0 {
+		return nil, e
+	}
+
+	return tab[:n], 0
+}
+
+// RoutingMessage represents a routing message.
+type RoutingMessage interface {
+	sockaddr() []Sockaddr
+}
+
+const anyMessageLen = unsafe.Sizeof(anyMessage{})
+
+type anyMessage struct {
+	Msglen  uint16
+	Version uint8
+	Type    uint8
+}
+
+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
+	case RTM_NEWMADDR, RTM_DELMADDR:
+		// TODO: implement this in the near future
+	}
+	return nil
+}
+
+// RouteMessage represents a routing message containing routing
+// entries.
+type RouteMessage struct {
+	Header RtMsghdr
+	Data   []byte
+}
+
+func (m *RouteMessage) sockaddr() (sas []Sockaddr) {
+	// TODO: implement this in the near future
+	return nil
+}
+
+// InterfaceMessage represents a routing message containing
+// network interface entries.
+type InterfaceMessage struct {
+	Header IfMsghdr
+	Data   []byte
+}
+
+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 {
+		return nil
+	}
+	return append(sas, sa)
+}
+
+// InterfaceAddrMessage represents a routing message containing
+// network interface address entries.
+type InterfaceAddrMessage struct {
+	Header IfaMsghdr
+	Data   []byte
+}
+
+const rtaMask = RTA_IFA | RTA_NETMASK | RTA_BRD
+
+func (m *InterfaceAddrMessage) sockaddr() (sas []Sockaddr) {
+	if m.Header.Addrs&rtaMask == 0 {
+		return nil
+	}
+
+	buf := m.Data[:]
+	for i := uint(0); i < RTAX_MAX; i++ {
+		if m.Header.Addrs&rtaMask&(1<<i) == 0 {
+			continue
+		}
+		rsa := (*RawSockaddr)(unsafe.Pointer(&buf[0]))
+		switch i {
+		case RTAX_IFA:
+			sa, e := anyToSockaddr((*RawSockaddrAny)(unsafe.Pointer(rsa)))
+			if e != 0 {
+				return nil
+			}
+			sas = append(sas, sa)
+		case RTAX_NETMASK, RTAX_BRD:
+			// nothing to do
+		}
+		buf = buf[rsaAlignOf(int(rsa.Len)):]
+	}
+
+	return sas
+}
+
+// ParseRoutingMessage parses buf as routing messages and returns
+// the slice containing the RoutingMessage interfaces.
+func ParseRoutingMessage(buf []byte) (msgs []RoutingMessage, errno int) {
+	for len(buf) >= anyMessageLen {
+		any := (*anyMessage)(unsafe.Pointer(&buf[0]))
+		if any.Version != RTM_VERSION {
+			return nil, EINVAL
+		}
+		msgs = append(msgs, any.toRoutingMessage(buf))
+		buf = buf[any.Msglen:]
+	}
+	return msgs, 0
+}
+
+// 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
+}
diff --git a/src/pkg/syscall/syscall_bsd.go b/src/pkg/syscall/syscall_bsd.go
index 766a56d..89bcc7f 100644
--- a/src/pkg/syscall/syscall_bsd.go
+++ b/src/pkg/syscall/syscall_bsd.go
@@ -22,7 +22,6 @@ const ImplementsGetwd = false
 
 func Getwd() (string, int) { return "", ENOTSUP }
 
-
 /*
  * Wrapped
  */
@@ -392,7 +391,11 @@ func SetsockoptLinger(fd, level, opt int, l *Linger) (errno int) {
 	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) (errno int) {
+	return setsockopt(fd, level, opt, uintptr(unsafe.Pointer(mreq)), unsafe.Sizeof(*mreq))
+}
+
+func SetsockoptIPv6Mreq(fd, level, opt int, mreq *IPv6Mreq) (errno int) {
 	return setsockopt(fd, level, opt, uintptr(unsafe.Pointer(mreq)), unsafe.Sizeof(*mreq))
 }
 
@@ -519,27 +522,6 @@ func SysctlUint32(name string) (value uint32, errno int) {
 	return *(*uint32)(unsafe.Pointer(&buf[0])), 0
 }
 
-func SysctlNetRoute(fourth, fifth, sixth int) (value []byte, errno int) {
-	mib := []_C_int{CTL_NET, AF_ROUTE, 0, _C_int(fourth), _C_int(fifth), _C_int(sixth)}
-
-	// Find size.
-	n := uintptr(0)
-	if errno = sysctl(mib, nil, &n, nil, 0); errno != 0 {
-		return nil, errno
-	}
-	if n == 0 {
-		return nil, 0
-	}
-
-	// Read into buffer of that size.
-	b := make([]byte, n)
-	if errno = sysctl(mib, &b[0], &n, nil, 0); errno != 0 {
-		return nil, errno
-	}
-
-	return b[0:n], 0
-}
-
 //sys	utimes(path string, timeval *[2]Timeval) (errno int)
 func Utimes(path string, tv []Timeval) (errno int) {
 	if len(tv) != 2 {
diff --git a/src/pkg/syscall/syscall_linux.go b/src/pkg/syscall/syscall_linux.go
index 9e9037e..63682d2 100644
--- a/src/pkg/syscall/syscall_linux.go
+++ b/src/pkg/syscall/syscall_linux.go
@@ -463,7 +463,11 @@ func SetsockoptLinger(fd, level, opt int, l *Linger) (errno int) {
 	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) (errno int) {
+	return setsockopt(fd, level, opt, uintptr(unsafe.Pointer(mreq)), unsafe.Sizeof(*mreq))
+}
+
+func SetsockoptIPv6Mreq(fd, level, opt int, mreq *IPv6Mreq) (errno int) {
 	return setsockopt(fd, level, opt, uintptr(unsafe.Pointer(mreq)), unsafe.Sizeof(*mreq))
 }
 
diff --git a/src/pkg/syscall/syscall_windows.go b/src/pkg/syscall/syscall_windows.go
index 6ba031f..bb93533 100644
--- a/src/pkg/syscall/syscall_windows.go
+++ b/src/pkg/syscall/syscall_windows.go
@@ -230,16 +230,13 @@ func Open(path string, mode int, perm uint32) (fd int, errno int) {
 	}
 	var createmode uint32
 	switch {
-	case mode&O_CREAT != 0:
-		switch {
-		case mode&O_EXCL != 0:
-			createmode = CREATE_NEW
-		case mode&O_APPEND != 0:
-			createmode = OPEN_ALWAYS
-		default:
-			createmode = CREATE_ALWAYS
-		}
-	case mode&O_TRUNC != 0:
+	case mode&(O_CREAT|O_EXCL) == (O_CREAT | O_EXCL):
+		createmode = CREATE_NEW
+	case mode&(O_CREAT|O_TRUNC) == (O_CREAT | O_TRUNC):
+		createmode = CREATE_ALWAYS
+	case mode&O_CREAT == O_CREAT:
+		createmode = OPEN_ALWAYS
+	case mode&O_TRUNC == O_TRUNC:
 		createmode = TRUNCATE_EXISTING
 	default:
 		createmode = OPEN_EXISTING
@@ -683,14 +680,20 @@ const (
 	IP_DROP_MEMBERSHIP
 )
 
-type IpMreq struct {
+type IPMreq struct {
 	Multiaddr [4]byte /* in_addr */
 	Interface [4]byte /* in_addr */
 }
 
-func SetsockoptLinger(fd, level, opt int, l *Linger) (errno int)    { return EWINDOWS }
-func SetsockoptIpMreq(fd, level, opt int, mreq *IpMreq) (errno int) { return EWINDOWS }
-func BindToDevice(fd int, device string) (errno int)                { return EWINDOWS }
+type IPv6Mreq struct {
+	Multiaddr [16]byte /* in6_addr */
+	Interface uint32
+}
+
+func SetsockoptLinger(fd, level, opt int, l *Linger) (errno int)        { return EWINDOWS }
+func SetsockoptIPMreq(fd, level, opt int, mreq *IPMreq) (errno int)     { return EWINDOWS }
+func SetsockoptIPv6Mreq(fd, level, opt int, mreq *IPv6Mreq) (errno int) { return EWINDOWS }
+func BindToDevice(fd int, device string) (errno int)                    { return EWINDOWS }
 
 // TODO(brainman): fix all needed for os
 
diff --git a/src/pkg/syscall/types_darwin.c b/src/pkg/syscall/types_darwin.c
index 666923a..ecccd5b 100644
--- a/src/pkg/syscall/types_darwin.c
+++ b/src/pkg/syscall/types_darwin.c
@@ -39,8 +39,7 @@ Input to godefs.  See also mkerrors.sh and mkall.sh
 
 // Machine characteristics; for internal use.
 
-enum
-{
+enum {
 	$sizeofPtr = sizeof(void*),
 	$sizeofShort = sizeof(short),
 	$sizeofInt = sizeof(int),
@@ -48,7 +47,6 @@ enum
 	$sizeofLongLong = sizeof(long long),
 };
 
-
 // Basic types
 
 typedef short $_C_short;
@@ -71,8 +69,7 @@ typedef gid_t $_Gid_t;
 
 // Files
 
-enum
-{
+enum {
 	$O_CLOEXEC = 0,	// not supported
 };
 
@@ -86,8 +83,6 @@ typedef struct log2phys $Log2phys_t;
 
 typedef struct dirent $Dirent;
 
-// Wait status.
-
 // Sockets
 
 union sockaddr_all {
@@ -112,9 +107,11 @@ typedef struct sockaddr_any $RawSockaddrAny;
 typedef socklen_t $_Socklen;
 typedef struct linger $Linger;
 typedef struct iovec $Iovec;
-typedef struct ip_mreq $IpMreq;
+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),
@@ -123,19 +120,21 @@ enum {
 	$SizeofSockaddrUnix = sizeof(struct sockaddr_un),
 	$SizeofSockaddrDatalink = sizeof(struct sockaddr_dl),
 	$SizeofLinger = sizeof(struct linger),
-	$SizeofIpMreq = sizeof(struct ip_mreq),
+	$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;
diff --git a/src/pkg/syscall/types_freebsd.c b/src/pkg/syscall/types_freebsd.c
index 9d65683..9763655 100644
--- a/src/pkg/syscall/types_freebsd.c
+++ b/src/pkg/syscall/types_freebsd.c
@@ -35,8 +35,7 @@ Input to godefs.  See also mkerrors.sh and mkall.sh
 
 // Machine characteristics; for internal use.
 
-enum
-{
+enum {
 	$sizeofPtr = sizeof(void*),
 	$sizeofShort = sizeof(short),
 	$sizeofInt = sizeof(int),
@@ -44,7 +43,6 @@ enum
 	$sizeofLongLong = sizeof(long long),
 };
 
-
 // Basic types
 
 typedef short $_C_short;
@@ -66,13 +64,11 @@ typedef gid_t $_Gid_t;
 
 // Files
 
-enum
-{
+enum {
 	$O_CLOEXEC = 0,	// not supported
 };
 
-enum
-{	// Directory mode bits
+enum {	// Directory mode bits
 	$S_IFMT = S_IFMT,
 	$S_IFIFO = S_IFIFO,
 	$S_IFCHR = S_IFCHR,
@@ -95,8 +91,6 @@ typedef struct flock $Flock_t;
 
 typedef struct dirent $Dirent;
 
-// Wait status.
-
 // Sockets
 
 union sockaddr_all {
@@ -121,9 +115,11 @@ typedef struct sockaddr_any $RawSockaddrAny;
 typedef socklen_t $_Socklen;
 typedef struct linger $Linger;
 typedef struct iovec $Iovec;
-typedef struct ip_mreq $IpMreq;
+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),
@@ -132,19 +128,21 @@ enum {
 	$SizeofSockaddrUnix = sizeof(struct sockaddr_un),
 	$SizeofSockaddrDatalink = sizeof(struct sockaddr_dl),
 	$SizeofLinger = sizeof(struct linger),
-	$SizeofIpMreq = sizeof(struct ip_mreq),
+	$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;
diff --git a/src/pkg/syscall/types_linux.c b/src/pkg/syscall/types_linux.c
index 1eaa582..ce7f967 100644
--- a/src/pkg/syscall/types_linux.c
+++ b/src/pkg/syscall/types_linux.c
@@ -47,8 +47,7 @@ Input to godefs.  See also mkerrors.sh and mkall.sh
 
 // Machine characteristics; for internal use.
 
-enum
-{
+enum {
 	$sizeofPtr = sizeof(void*),
 	$sizeofShort = sizeof(short),
 	$sizeofInt = sizeof(int),
@@ -113,9 +112,11 @@ typedef struct sockaddr_any $RawSockaddrAny;
 typedef socklen_t $_Socklen;
 typedef struct linger $Linger;
 typedef struct iovec $Iovec;
-typedef struct ip_mreq $IpMreq;
+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 {
@@ -126,9 +127,11 @@ enum {
 	$SizeofSockaddrLinklayer = sizeof(struct sockaddr_ll),
 	$SizeofSockaddrNetlink = sizeof(struct sockaddr_nl),
 	$SizeofLinger = sizeof(struct linger),
-	$SizeofIpMreq = sizeof(struct ip_mreq),	
+	$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),
 };
 
@@ -165,6 +168,42 @@ enum {
 	$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),
@@ -173,6 +212,7 @@ enum {
 	$SizeofIfInfomsg = sizeof(struct ifinfomsg),
 	$SizeofIfAddrmsg = sizeof(struct ifaddrmsg),
 	$SizeofRtmsg = sizeof(struct rtmsg),
+	$SizeofRtNexthop = sizeof(struct rtnexthop),
 };
 
 typedef struct nlmsghdr $NlMsghdr;
@@ -183,6 +223,7 @@ typedef struct rtattr $RtAttr;
 typedef struct ifinfomsg $IfInfomsg;
 typedef struct ifaddrmsg $IfAddrmsg;
 typedef struct rtmsg $RtMsg;
+typedef struct rtnexthop $RtNexthop;
 
 // Inotify
 
diff --git a/src/pkg/syscall/zerrors_darwin_386.go b/src/pkg/syscall/zerrors_darwin_386.go
index 7bc1280..5ee64ee 100644
--- a/src/pkg/syscall/zerrors_darwin_386.go
+++ b/src/pkg/syscall/zerrors_darwin_386.go
@@ -339,6 +339,72 @@ const (
 	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
diff --git a/src/pkg/syscall/zerrors_darwin_amd64.go b/src/pkg/syscall/zerrors_darwin_amd64.go
index d76f092..65a48d6 100644
--- a/src/pkg/syscall/zerrors_darwin_amd64.go
+++ b/src/pkg/syscall/zerrors_darwin_amd64.go
@@ -339,6 +339,72 @@ const (
 	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
diff --git a/src/pkg/syscall/zerrors_freebsd_386.go b/src/pkg/syscall/zerrors_freebsd_386.go
index 9c21c71..52e4248 100644
--- a/src/pkg/syscall/zerrors_freebsd_386.go
+++ b/src/pkg/syscall/zerrors_freebsd_386.go
@@ -9,1013 +9,1228 @@ package syscall
 
 // Constants
 const (
-	AF_APPLETALK                   = 0x10
-	AF_ARP                         = 0x23
-	AF_ATM                         = 0x1e
-	AF_BLUETOOTH                   = 0x24
-	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_HYLINK                      = 0xf
-	AF_IEEE80211                   = 0x25
-	AF_IMPLINK                     = 0x3
-	AF_INET                        = 0x2
-	AF_INET6                       = 0x1c
-	AF_IPX                         = 0x17
-	AF_ISDN                        = 0x1a
-	AF_ISO                         = 0x7
-	AF_LAT                         = 0xe
-	AF_LINK                        = 0x12
-	AF_LOCAL                       = 0x1
-	AF_MAX                         = 0x26
-	AF_NATM                        = 0x1d
-	AF_NETBIOS                     = 0x6
-	AF_NETGRAPH                    = 0x20
-	AF_OSI                         = 0x7
-	AF_PUP                         = 0x4
-	AF_ROUTE                       = 0x11
-	AF_SCLUSTER                    = 0x22
-	AF_SIP                         = 0x18
-	AF_SLOW                        = 0x21
-	AF_SNA                         = 0xb
-	AF_UNIX                        = 0x1
-	AF_UNSPEC                      = 0
-	AF_VENDOR00                    = 0x27
-	AF_VENDOR01                    = 0x29
-	AF_VENDOR02                    = 0x2b
-	AF_VENDOR03                    = 0x2d
-	AF_VENDOR04                    = 0x2f
-	AF_VENDOR05                    = 0x31
-	AF_VENDOR06                    = 0x33
-	AF_VENDOR07                    = 0x35
-	AF_VENDOR08                    = 0x37
-	AF_VENDOR09                    = 0x39
-	AF_VENDOR10                    = 0x3b
-	AF_VENDOR11                    = 0x3d
-	AF_VENDOR12                    = 0x3f
-	AF_VENDOR13                    = 0x41
-	AF_VENDOR14                    = 0x43
-	AF_VENDOR15                    = 0x45
-	AF_VENDOR16                    = 0x47
-	AF_VENDOR17                    = 0x49
-	AF_VENDOR18                    = 0x4b
-	AF_VENDOR19                    = 0x4d
-	AF_VENDOR20                    = 0x4f
-	AF_VENDOR21                    = 0x51
-	AF_VENDOR22                    = 0x53
-	AF_VENDOR23                    = 0x55
-	AF_VENDOR24                    = 0x57
-	AF_VENDOR25                    = 0x59
-	AF_VENDOR26                    = 0x5b
-	AF_VENDOR27                    = 0x5d
-	AF_VENDOR28                    = 0x5f
-	AF_VENDOR29                    = 0x61
-	AF_VENDOR30                    = 0x63
-	AF_VENDOR31                    = 0x65
-	AF_VENDOR32                    = 0x67
-	AF_VENDOR33                    = 0x69
-	AF_VENDOR34                    = 0x6b
-	AF_VENDOR35                    = 0x6d
-	AF_VENDOR36                    = 0x6f
-	AF_VENDOR37                    = 0x71
-	AF_VENDOR38                    = 0x73
-	AF_VENDOR39                    = 0x75
-	AF_VENDOR40                    = 0x77
-	AF_VENDOR41                    = 0x79
-	AF_VENDOR42                    = 0x7b
-	AF_VENDOR43                    = 0x7d
-	AF_VENDOR44                    = 0x7f
-	AF_VENDOR45                    = 0x81
-	AF_VENDOR46                    = 0x83
-	AF_VENDOR47                    = 0x85
-	BIOCFEEDBACK                   = 0x8004427c
-	BIOCFLUSH                      = 0x20004268
-	BIOCGBLEN                      = 0x40044266
-	BIOCGDIRECTION                 = 0x40044276
-	BIOCGDLT                       = 0x4004426a
-	BIOCGDLTLIST                   = 0xc0084279
-	BIOCGETBUFMODE                 = 0x4004427d
-	BIOCGETIF                      = 0x4020426b
-	BIOCGETZMAX                    = 0x4004427f
-	BIOCGHDRCMPLT                  = 0x40044274
-	BIOCGRSIG                      = 0x40044272
-	BIOCGRTIMEOUT                  = 0x4008426e
-	BIOCGSEESENT                   = 0x40044276
-	BIOCGSTATS                     = 0x4008426f
-	BIOCIMMEDIATE                  = 0x80044270
-	BIOCLOCK                       = 0x2000427a
-	BIOCPROMISC                    = 0x20004269
-	BIOCROTZBUF                    = 0x400c4280
-	BIOCSBLEN                      = 0xc0044266
-	BIOCSDIRECTION                 = 0x80044277
-	BIOCSDLT                       = 0x80044278
-	BIOCSETBUFMODE                 = 0x8004427e
-	BIOCSETF                       = 0x80084267
-	BIOCSETFNR                     = 0x80084282
-	BIOCSETIF                      = 0x8020426c
-	BIOCSETWF                      = 0x8008427b
-	BIOCSETZBUF                    = 0x800c4281
-	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_BUFMODE_BUFFER             = 0x1
-	BPF_BUFMODE_ZBUF               = 0x2
-	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                    = 0x18
-	CTL_NET                        = 0x4
-	DLT_A429                       = 0xb8
-	DLT_A653_ICM                   = 0xb9
-	DLT_AIRONET_HEADER             = 0x78
-	DLT_APPLE_IP_OVER_IEEE1394     = 0x8a
-	DLT_ARCNET                     = 0x7
-	DLT_ARCNET_LINUX               = 0x81
-	DLT_ATM_CLIP                   = 0x13
-	DLT_ATM_RFC1483                = 0xb
-	DLT_AURORA                     = 0x7e
-	DLT_AX25                       = 0x3
-	DLT_AX25_KISS                  = 0xca
-	DLT_BACNET_MS_TP               = 0xa5
-	DLT_BLUETOOTH_HCI_H4           = 0xbb
-	DLT_BLUETOOTH_HCI_H4_WITH_PHDR = 0xc9
-	DLT_CAN20B                     = 0xbe
-	DLT_CHAOS                      = 0x5
-	DLT_CHDLC                      = 0x68
-	DLT_CISCO_IOS                  = 0x76
-	DLT_C_HDLC                     = 0x68
-	DLT_C_HDLC_WITH_DIR            = 0xcd
-	DLT_DOCSIS                     = 0x8f
-	DLT_ECONET                     = 0x73
-	DLT_EN10MB                     = 0x1
-	DLT_EN3MB                      = 0x2
-	DLT_ENC                        = 0x6d
-	DLT_ERF                        = 0xc5
-	DLT_ERF_ETH                    = 0xaf
-	DLT_ERF_POS                    = 0xb0
-	DLT_FDDI                       = 0xa
-	DLT_FLEXRAY                    = 0xd2
-	DLT_FRELAY                     = 0x6b
-	DLT_FRELAY_WITH_DIR            = 0xce
-	DLT_GCOM_SERIAL                = 0xad
-	DLT_GCOM_T1E1                  = 0xac
-	DLT_GPF_F                      = 0xab
-	DLT_GPF_T                      = 0xaa
-	DLT_GPRS_LLC                   = 0xa9
-	DLT_HHDLC                      = 0x79
-	DLT_IBM_SN                     = 0x92
-	DLT_IBM_SP                     = 0x91
-	DLT_IEEE802                    = 0x6
-	DLT_IEEE802_11                 = 0x69
-	DLT_IEEE802_11_RADIO           = 0x7f
-	DLT_IEEE802_11_RADIO_AVS       = 0xa3
-	DLT_IEEE802_15_4               = 0xc3
-	DLT_IEEE802_15_4_LINUX         = 0xbf
-	DLT_IEEE802_15_4_NONASK_PHY    = 0xd7
-	DLT_IEEE802_16_MAC_CPS         = 0xbc
-	DLT_IEEE802_16_MAC_CPS_RADIO   = 0xc1
-	DLT_IPFILTER                   = 0x74
-	DLT_IPMB                       = 0xc7
-	DLT_IPMB_LINUX                 = 0xd1
-	DLT_IP_OVER_FC                 = 0x7a
-	DLT_JUNIPER_ATM1               = 0x89
-	DLT_JUNIPER_ATM2               = 0x87
-	DLT_JUNIPER_CHDLC              = 0xb5
-	DLT_JUNIPER_ES                 = 0x84
-	DLT_JUNIPER_ETHER              = 0xb2
-	DLT_JUNIPER_FRELAY             = 0xb4
-	DLT_JUNIPER_GGSN               = 0x85
-	DLT_JUNIPER_ISM                = 0xc2
-	DLT_JUNIPER_MFR                = 0x86
-	DLT_JUNIPER_MLFR               = 0x83
-	DLT_JUNIPER_MLPPP              = 0x82
-	DLT_JUNIPER_MONITOR            = 0xa4
-	DLT_JUNIPER_PIC_PEER           = 0xae
-	DLT_JUNIPER_PPP                = 0xb3
-	DLT_JUNIPER_PPPOE              = 0xa7
-	DLT_JUNIPER_PPPOE_ATM          = 0xa8
-	DLT_JUNIPER_SERVICES           = 0x88
-	DLT_JUNIPER_ST                 = 0xc8
-	DLT_JUNIPER_VP                 = 0xb7
-	DLT_LAPB_WITH_DIR              = 0xcf
-	DLT_LAPD                       = 0xcb
-	DLT_LIN                        = 0xd4
-	DLT_LINUX_IRDA                 = 0x90
-	DLT_LINUX_LAPD                 = 0xb1
-	DLT_LINUX_PPP_WITHDIRECTION    = 0xa6
-	DLT_LINUX_SLL                  = 0x71
-	DLT_LOOP                       = 0x6c
-	DLT_LTALK                      = 0x72
-	DLT_MFR                        = 0xb6
-	DLT_MOST                       = 0xd3
-	DLT_MTP2                       = 0x8c
-	DLT_MTP2_WITH_PHDR             = 0x8b
-	DLT_MTP3                       = 0x8d
-	DLT_NULL                       = 0
-	DLT_PCI_EXP                    = 0x7d
-	DLT_PFLOG                      = 0x75
-	DLT_PFSYNC                     = 0x79
-	DLT_PPI                        = 0xc0
-	DLT_PPP                        = 0x9
-	DLT_PPP_BSDOS                  = 0x10
-	DLT_PPP_ETHER                  = 0x33
-	DLT_PPP_PPPD                   = 0xa6
-	DLT_PPP_SERIAL                 = 0x32
-	DLT_PPP_WITH_DIR               = 0xcc
-	DLT_PPP_WITH_DIRECTION         = 0xa6
-	DLT_PRISM_HEADER               = 0x77
-	DLT_PRONET                     = 0x4
-	DLT_RAIF1                      = 0xc6
-	DLT_RAW                        = 0xc
-	DLT_RIO                        = 0x7c
-	DLT_SCCP                       = 0x8e
-	DLT_SITA                       = 0xc4
-	DLT_SLIP                       = 0x8
-	DLT_SLIP_BSDOS                 = 0xf
-	DLT_SUNATM                     = 0x7b
-	DLT_SYMANTEC_FIREWALL          = 0x63
-	DLT_TZSP                       = 0x80
-	DLT_USB                        = 0xba
-	DLT_USB_LINUX                  = 0xbd
-	DLT_USER0                      = 0x93
-	DLT_USER1                      = 0x94
-	DLT_USER10                     = 0x9d
-	DLT_USER11                     = 0x9e
-	DLT_USER12                     = 0x9f
-	DLT_USER13                     = 0xa0
-	DLT_USER14                     = 0xa1
-	DLT_USER15                     = 0xa2
-	DLT_USER2                      = 0x95
-	DLT_USER3                      = 0x96
-	DLT_USER4                      = 0x97
-	DLT_USER5                      = 0x98
-	DLT_USER6                      = 0x99
-	DLT_USER7                      = 0x9a
-	DLT_USER8                      = 0x9b
-	DLT_USER9                      = 0x9c
-	DLT_X2E_SERIAL                 = 0xd5
-	DLT_X2E_XORAYA                 = 0xd6
-	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
-	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
-	EVFILT_PROC                    = -0x5
-	EVFILT_READ                    = -0x1
-	EVFILT_SIGNAL                  = -0x6
-	EVFILT_SYSCOUNT                = 0xb
-	EVFILT_TIMER                   = -0x7
-	EVFILT_USER                    = -0xb
-	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_FLAG1                       = 0x2000
-	EV_ONESHOT                     = 0x10
-	EV_RECEIPT                     = 0x40
-	EV_SYSFLAGS                    = 0xf000
-	EWOULDBLOCK                    = 0x23
-	EXDEV                          = 0x12
-	FD_CLOEXEC                     = 0x1
-	FD_SETSIZE                     = 0x400
-	F_CANCEL                       = 0x5
-	F_DUP2FD                       = 0xa
-	F_DUPFD                        = 0
-	F_GETFD                        = 0x1
-	F_GETFL                        = 0x3
-	F_GETLK                        = 0xb
-	F_GETOWN                       = 0x5
-	F_OGETLK                       = 0x7
-	F_OSETLK                       = 0x8
-	F_OSETLKW                      = 0x9
-	F_RDAHEAD                      = 0x10
-	F_RDLCK                        = 0x1
-	F_READAHEAD                    = 0xf
-	F_SETFD                        = 0x2
-	F_SETFL                        = 0x4
-	F_SETLK                        = 0xc
-	F_SETLKW                       = 0xd
-	F_SETLK_REMOTE                 = 0xe
-	F_SETOWN                       = 0x6
-	F_UNLCK                        = 0x2
-	F_UNLCKSYS                     = 0x4
-	F_WRLCK                        = 0x3
-	IFF_ALLMULTI                   = 0x200
-	IFF_ALTPHYS                    = 0x4000
-	IFF_BROADCAST                  = 0x2
-	IFF_CANTCHANGE                 = 0x208f72
-	IFF_DEBUG                      = 0x4
-	IFF_DRV_OACTIVE                = 0x400
-	IFF_DRV_RUNNING                = 0x40
-	IFF_DYING                      = 0x200000
-	IFF_LINK0                      = 0x1000
-	IFF_LINK1                      = 0x2000
-	IFF_LINK2                      = 0x4000
-	IFF_LOOPBACK                   = 0x8
-	IFF_MONITOR                    = 0x40000
-	IFF_MULTICAST                  = 0x8000
-	IFF_NOARP                      = 0x80
-	IFF_OACTIVE                    = 0x400
-	IFF_POINTOPOINT                = 0x10
-	IFF_PPROMISC                   = 0x20000
-	IFF_PROMISC                    = 0x100
-	IFF_RENAMING                   = 0x400000
-	IFF_RUNNING                    = 0x40
-	IFF_SIMPLEX                    = 0x800
-	IFF_SMART                      = 0x20
-	IFF_STATICARP                  = 0x80000
-	IFF_UP                         = 0x1
-	IFNAMSIZ                       = 0x10
-	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
-	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_CARP                   = 0x70
-	IPPROTO_CFTP                   = 0x3e
-	IPPROTO_CHAOS                  = 0x10
-	IPPROTO_CMTP                   = 0x26
-	IPPROTO_CPHB                   = 0x49
-	IPPROTO_CPNX                   = 0x48
-	IPPROTO_DDP                    = 0x25
-	IPPROTO_DGP                    = 0x56
-	IPPROTO_DIVERT                 = 0x102
-	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_MOBILE                 = 0x37
-	IPPROTO_MTP                    = 0x5c
-	IPPROTO_MUX                    = 0x12
-	IPPROTO_ND                     = 0x4d
-	IPPROTO_NHRP                   = 0x36
-	IPPROTO_NONE                   = 0x3b
-	IPPROTO_NSP                    = 0x1f
-	IPPROTO_NVPII                  = 0xb
-	IPPROTO_OLD_DIVERT             = 0xfe
-	IPPROTO_OSPFIGP                = 0x59
-	IPPROTO_PFSYNC                 = 0xf0
-	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_SKIP                   = 0x39
-	IPPROTO_SPACER                 = 0x7fff
-	IPPROTO_SRPC                   = 0x5a
-	IPPROTO_ST                     = 0x7
-	IPPROTO_SVMTP                  = 0x52
-	IPPROTO_SWIPE                  = 0x35
-	IPPROTO_TCF                    = 0x57
-	IPPROTO_TCP                    = 0x6
-	IPPROTO_TLSP                   = 0x38
-	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_AUTOFLOWLABEL             = 0x3b
-	IPV6_BINDANY                   = 0x40
-	IPV6_BINDV6ONLY                = 0x1b
-	IPV6_CHECKSUM                  = 0x1a
-	IPV6_DEFAULT_MULTICAST_HOPS    = 0x1
-	IPV6_DEFAULT_MULTICAST_LOOP    = 0x1
-	IPV6_DEFHLIM                   = 0x40
-	IPV6_DONTFRAG                  = 0x3e
-	IPV6_DSTOPTS                   = 0x32
-	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                  = 0x2f
-	IPV6_HOPOPTS                   = 0x31
-	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_MSFILTER                  = 0x4a
-	IPV6_MULTICAST_HOPS            = 0xa
-	IPV6_MULTICAST_IF              = 0x9
-	IPV6_MULTICAST_LOOP            = 0xb
-	IPV6_NEXTHOP                   = 0x30
-	IPV6_PATHMTU                   = 0x2c
-	IPV6_PKTINFO                   = 0x2e
-	IPV6_PORTRANGE                 = 0xe
-	IPV6_PORTRANGE_DEFAULT         = 0
-	IPV6_PORTRANGE_HIGH            = 0x1
-	IPV6_PORTRANGE_LOW             = 0x2
-	IPV6_PREFER_TEMPADDR           = 0x3f
-	IPV6_RECVDSTOPTS               = 0x28
-	IPV6_RECVHOPLIMIT              = 0x25
-	IPV6_RECVHOPOPTS               = 0x27
-	IPV6_RECVPATHMTU               = 0x2b
-	IPV6_RECVPKTINFO               = 0x24
-	IPV6_RECVRTHDR                 = 0x26
-	IPV6_RECVTCLASS                = 0x39
-	IPV6_RTHDR                     = 0x33
-	IPV6_RTHDRDSTOPTS              = 0x23
-	IPV6_RTHDR_LOOSE               = 0
-	IPV6_RTHDR_STRICT              = 0x1
-	IPV6_RTHDR_TYPE_0              = 0
-	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_ADD_SOURCE_MEMBERSHIP       = 0x46
-	IP_BINDANY                     = 0x18
-	IP_BLOCK_SOURCE                = 0x48
-	IP_DEFAULT_MULTICAST_LOOP      = 0x1
-	IP_DEFAULT_MULTICAST_TTL       = 0x1
-	IP_DF                          = 0x4000
-	IP_DONTFRAG                    = 0x43
-	IP_DROP_MEMBERSHIP             = 0xd
-	IP_DROP_SOURCE_MEMBERSHIP      = 0x47
-	IP_DUMMYNET3                   = 0x31
-	IP_DUMMYNET_CONFIGURE          = 0x3c
-	IP_DUMMYNET_DEL                = 0x3d
-	IP_DUMMYNET_FLUSH              = 0x3e
-	IP_DUMMYNET_GET                = 0x40
-	IP_FAITH                       = 0x16
-	IP_FW3                         = 0x30
-	IP_FW_ADD                      = 0x32
-	IP_FW_DEL                      = 0x33
-	IP_FW_FLUSH                    = 0x34
-	IP_FW_GET                      = 0x36
-	IP_FW_NAT_CFG                  = 0x38
-	IP_FW_NAT_DEL                  = 0x39
-	IP_FW_NAT_GET_CONFIG           = 0x3a
-	IP_FW_NAT_GET_LOG              = 0x3b
-	IP_FW_RESETLOG                 = 0x37
-	IP_FW_TABLE_ADD                = 0x28
-	IP_FW_TABLE_DEL                = 0x29
-	IP_FW_TABLE_FLUSH              = 0x2a
-	IP_FW_TABLE_GETSIZE            = 0x2b
-	IP_FW_TABLE_LIST               = 0x2c
-	IP_FW_ZERO                     = 0x35
-	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_MAX_SOURCE_FILTER           = 0x400
-	IP_MF                          = 0x2000
-	IP_MINTTL                      = 0x42
-	IP_MIN_MEMBERSHIPS             = 0x1f
-	IP_MSFILTER                    = 0x4a
-	IP_MSS                         = 0x240
-	IP_MULTICAST_IF                = 0x9
-	IP_MULTICAST_LOOP              = 0xb
-	IP_MULTICAST_TTL               = 0xa
-	IP_MULTICAST_VIF               = 0xe
-	IP_OFFMASK                     = 0x1fff
-	IP_ONESBCAST                   = 0x17
-	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                     = 0x41
-	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_SENDSRCADDR                 = 0x7
-	IP_TOS                         = 0x3
-	IP_TTL                         = 0x4
-	IP_UNBLOCK_SOURCE              = 0x49
-	MSG_COMPAT                     = 0x8000
-	MSG_CTRUNC                     = 0x20
-	MSG_DONTROUTE                  = 0x4
-	MSG_DONTWAIT                   = 0x80
-	MSG_EOF                        = 0x100
-	MSG_EOR                        = 0x8
-	MSG_NBIO                       = 0x4000
-	MSG_NOSIGNAL                   = 0x20000
-	MSG_NOTIFICATION               = 0x2000
-	MSG_OOB                        = 0x1
-	MSG_PEEK                       = 0x2
-	MSG_TRUNC                      = 0x10
-	MSG_WAITALL                    = 0x40
-	NET_RT_DUMP                    = 0x1
-	NET_RT_FLAGS                   = 0x2
-	NET_RT_IFLIST                  = 0x3
-	NET_RT_IFMALIST                = 0x4
-	NET_RT_MAXID                   = 0x5
-	O_ACCMODE                      = 0x3
-	O_APPEND                       = 0x8
-	O_ASYNC                        = 0x40
-	O_CREAT                        = 0x200
-	O_DIRECT                       = 0x10000
-	O_DIRECTORY                    = 0x20000
-	O_EXCL                         = 0x800
-	O_EXEC                         = 0x40000
-	O_EXLOCK                       = 0x20
-	O_FSYNC                        = 0x80
-	O_NDELAY                       = 0x4
-	O_NOCTTY                       = 0x8000
-	O_NOFOLLOW                     = 0x100
-	O_NONBLOCK                     = 0x4
-	O_RDONLY                       = 0
-	O_RDWR                         = 0x2
-	O_SHLOCK                       = 0x10
-	O_SYNC                         = 0x80
-	O_TRUNC                        = 0x400
-	O_TTY_INIT                     = 0x80000
-	O_WRONLY                       = 0x1
-	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_DONE                       = 0x40
-	RTF_DYNAMIC                    = 0x10
-	RTF_FMASK                      = 0x1004d808
-	RTF_GATEWAY                    = 0x2
-	RTF_HOST                       = 0x4
-	RTF_LLDATA                     = 0x400
-	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_RNH_LOCKED                 = 0x40000000
-	RTF_STATIC                     = 0x800
-	RTF_STICKY                     = 0x10000000
-	RTF_UP                         = 0x1
-	RTF_XRESOLVE                   = 0x200
-	RTM_ADD                        = 0x1
-	RTM_CHANGE                     = 0x3
-	RTM_DELADDR                    = 0xd
-	RTM_DELETE                     = 0x2
-	RTM_DELMADDR                   = 0x10
-	RTM_GET                        = 0x4
-	RTM_IEEE80211                  = 0x12
-	RTM_IFANNOUNCE                 = 0x11
-	RTM_IFINFO                     = 0xe
-	RTM_LOCK                       = 0x8
-	RTM_LOSING                     = 0x5
-	RTM_MISS                       = 0x7
-	RTM_NEWADDR                    = 0xc
-	RTM_NEWMADDR                   = 0xf
-	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
-	RTV_WEIGHT                     = 0x100
-	SCM_BINTIME                    = 0x4
-	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
-	SIGLWP                         = 0x20
-	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
-	SIOCADDRT                      = 0x8030720a
-	SIOCAIFADDR                    = 0x8040691a
-	SIOCAIFGROUP                   = 0x80246987
-	SIOCALIFADDR                   = 0x8118691b
-	SIOCATMARK                     = 0x40047307
-	SIOCDELMULTI                   = 0x80206932
-	SIOCDELRT                      = 0x8030720b
-	SIOCDIFADDR                    = 0x80206919
-	SIOCDIFGROUP                   = 0x80246989
-	SIOCDIFPHYADDR                 = 0x80206949
-	SIOCDLIFADDR                   = 0x8118691d
-	SIOCGDRVSPEC                   = 0xc01c697b
-	SIOCGETSGCNT                   = 0xc0147210
-	SIOCGETVIFCNT                  = 0xc014720f
-	SIOCGHIWAT                     = 0x40047301
-	SIOCGIFADDR                    = 0xc0206921
-	SIOCGIFBRDADDR                 = 0xc0206923
-	SIOCGIFCAP                     = 0xc020691f
-	SIOCGIFCONF                    = 0xc0086924
-	SIOCGIFDESCR                   = 0xc020692a
-	SIOCGIFDSTADDR                 = 0xc0206922
-	SIOCGIFFLAGS                   = 0xc0206911
-	SIOCGIFGENERIC                 = 0xc020693a
-	SIOCGIFGMEMB                   = 0xc024698a
-	SIOCGIFGROUP                   = 0xc0246988
-	SIOCGIFINDEX                   = 0xc0206920
-	SIOCGIFMAC                     = 0xc0206926
-	SIOCGIFMEDIA                   = 0xc0286938
-	SIOCGIFMETRIC                  = 0xc0206917
-	SIOCGIFMTU                     = 0xc0206933
-	SIOCGIFNETMASK                 = 0xc0206925
-	SIOCGIFPDSTADDR                = 0xc0206948
-	SIOCGIFPHYS                    = 0xc0206935
-	SIOCGIFPSRCADDR                = 0xc0206947
-	SIOCGIFSTATUS                  = 0xc331693b
-	SIOCGLIFADDR                   = 0xc118691c
-	SIOCGLIFPHYADDR                = 0xc118694b
-	SIOCGLOWAT                     = 0x40047303
-	SIOCGPGRP                      = 0x40047309
-	SIOCGPRIVATE_0                 = 0xc0206950
-	SIOCGPRIVATE_1                 = 0xc0206951
-	SIOCIFCREATE                   = 0xc020697a
-	SIOCIFCREATE2                  = 0xc020697c
-	SIOCIFDESTROY                  = 0x80206979
-	SIOCIFGCLONERS                 = 0xc00c6978
-	SIOCSDRVSPEC                   = 0x801c697b
-	SIOCSHIWAT                     = 0x80047300
-	SIOCSIFADDR                    = 0x8020690c
-	SIOCSIFBRDADDR                 = 0x80206913
-	SIOCSIFCAP                     = 0x8020691e
-	SIOCSIFDESCR                   = 0x80206929
-	SIOCSIFDSTADDR                 = 0x8020690e
-	SIOCSIFFLAGS                   = 0x80206910
-	SIOCSIFGENERIC                 = 0x80206939
-	SIOCSIFLLADDR                  = 0x8020693c
-	SIOCSIFMAC                     = 0x80206927
-	SIOCSIFMEDIA                   = 0xc0206937
-	SIOCSIFMETRIC                  = 0x80206918
-	SIOCSIFMTU                     = 0x80206934
-	SIOCSIFNAME                    = 0x80206928
-	SIOCSIFNETMASK                 = 0x80206916
-	SIOCSIFPHYADDR                 = 0x80406946
-	SIOCSIFPHYS                    = 0x80206936
-	SIOCSIFRVNET                   = 0xc020695b
-	SIOCSIFVNET                    = 0xc020695a
-	SIOCSLIFPHYADDR                = 0x8118694a
-	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_ACCEPTFILTER                = 0x1000
-	SO_BINTIME                     = 0x2000
-	SO_BROADCAST                   = 0x20
-	SO_DEBUG                       = 0x1
-	SO_DONTROUTE                   = 0x10
-	SO_ERROR                       = 0x1007
-	SO_KEEPALIVE                   = 0x8
-	SO_LABEL                       = 0x1009
-	SO_LINGER                      = 0x80
-	SO_LISTENINCQLEN               = 0x1013
-	SO_LISTENQLEN                  = 0x1012
-	SO_LISTENQLIMIT                = 0x1011
-	SO_NOSIGPIPE                   = 0x800
-	SO_NO_DDP                      = 0x8000
-	SO_NO_OFFLOAD                  = 0x4000
-	SO_OOBINLINE                   = 0x100
-	SO_PEERLABEL                   = 0x1010
-	SO_RCVBUF                      = 0x1002
-	SO_RCVLOWAT                    = 0x1004
-	SO_RCVTIMEO                    = 0x1006
-	SO_REUSEADDR                   = 0x4
-	SO_REUSEPORT                   = 0x200
-	SO_SETFIB                      = 0x1014
-	SO_SNDBUF                      = 0x1001
-	SO_SNDLOWAT                    = 0x1003
-	SO_SNDTIMEO                    = 0x1005
-	SO_TIMESTAMP                   = 0x400
-	SO_TYPE                        = 0x1008
-	SO_USELOOPBACK                 = 0x40
-	TCP_CA_NAME_MAX                = 0x10
-	TCP_CONGESTION                 = 0x40
-	TCP_INFO                       = 0x20
-	TCP_MAXBURST                   = 0x4
-	TCP_MAXHLEN                    = 0x3c
-	TCP_MAXOLEN                    = 0x28
-	TCP_MAXSEG                     = 0x2
-	TCP_MAXWIN                     = 0xffff
-	TCP_MAX_SACK                   = 0x4
-	TCP_MAX_WINSHIFT               = 0xe
-	TCP_MD5SIG                     = 0x10
-	TCP_MINMSS                     = 0xd8
-	TCP_MSS                        = 0x200
-	TCP_NODELAY                    = 0x1
-	TCP_NOOPT                      = 0x8
-	TCP_NOPUSH                     = 0x4
-	WCONTINUED                     = 0x4
-	WCOREFLAG                      = 0x80
-	WLINUXCLONE                    = 0x80000000
-	WNOHANG                        = 0x1
-	WNOWAIT                        = 0x8
-	WSTOPPED                       = 0x2
-	WUNTRACED                      = 0x2
+	AF_APPLETALK                      = 0x10
+	AF_ARP                            = 0x23
+	AF_ATM                            = 0x1e
+	AF_BLUETOOTH                      = 0x24
+	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_HYLINK                         = 0xf
+	AF_IEEE80211                      = 0x25
+	AF_IMPLINK                        = 0x3
+	AF_INET                           = 0x2
+	AF_INET6                          = 0x1c
+	AF_IPX                            = 0x17
+	AF_ISDN                           = 0x1a
+	AF_ISO                            = 0x7
+	AF_LAT                            = 0xe
+	AF_LINK                           = 0x12
+	AF_LOCAL                          = 0x1
+	AF_MAX                            = 0x26
+	AF_NATM                           = 0x1d
+	AF_NETBIOS                        = 0x6
+	AF_NETGRAPH                       = 0x20
+	AF_OSI                            = 0x7
+	AF_PUP                            = 0x4
+	AF_ROUTE                          = 0x11
+	AF_SCLUSTER                       = 0x22
+	AF_SIP                            = 0x18
+	AF_SLOW                           = 0x21
+	AF_SNA                            = 0xb
+	AF_UNIX                           = 0x1
+	AF_UNSPEC                         = 0
+	AF_VENDOR00                       = 0x27
+	AF_VENDOR01                       = 0x29
+	AF_VENDOR02                       = 0x2b
+	AF_VENDOR03                       = 0x2d
+	AF_VENDOR04                       = 0x2f
+	AF_VENDOR05                       = 0x31
+	AF_VENDOR06                       = 0x33
+	AF_VENDOR07                       = 0x35
+	AF_VENDOR08                       = 0x37
+	AF_VENDOR09                       = 0x39
+	AF_VENDOR10                       = 0x3b
+	AF_VENDOR11                       = 0x3d
+	AF_VENDOR12                       = 0x3f
+	AF_VENDOR13                       = 0x41
+	AF_VENDOR14                       = 0x43
+	AF_VENDOR15                       = 0x45
+	AF_VENDOR16                       = 0x47
+	AF_VENDOR17                       = 0x49
+	AF_VENDOR18                       = 0x4b
+	AF_VENDOR19                       = 0x4d
+	AF_VENDOR20                       = 0x4f
+	AF_VENDOR21                       = 0x51
+	AF_VENDOR22                       = 0x53
+	AF_VENDOR23                       = 0x55
+	AF_VENDOR24                       = 0x57
+	AF_VENDOR25                       = 0x59
+	AF_VENDOR26                       = 0x5b
+	AF_VENDOR27                       = 0x5d
+	AF_VENDOR28                       = 0x5f
+	AF_VENDOR29                       = 0x61
+	AF_VENDOR30                       = 0x63
+	AF_VENDOR31                       = 0x65
+	AF_VENDOR32                       = 0x67
+	AF_VENDOR33                       = 0x69
+	AF_VENDOR34                       = 0x6b
+	AF_VENDOR35                       = 0x6d
+	AF_VENDOR36                       = 0x6f
+	AF_VENDOR37                       = 0x71
+	AF_VENDOR38                       = 0x73
+	AF_VENDOR39                       = 0x75
+	AF_VENDOR40                       = 0x77
+	AF_VENDOR41                       = 0x79
+	AF_VENDOR42                       = 0x7b
+	AF_VENDOR43                       = 0x7d
+	AF_VENDOR44                       = 0x7f
+	AF_VENDOR45                       = 0x81
+	AF_VENDOR46                       = 0x83
+	AF_VENDOR47                       = 0x85
+	BIOCFEEDBACK                      = 0x8004427c
+	BIOCFLUSH                         = 0x20004268
+	BIOCGBLEN                         = 0x40044266
+	BIOCGDIRECTION                    = 0x40044276
+	BIOCGDLT                          = 0x4004426a
+	BIOCGDLTLIST                      = 0xc0084279
+	BIOCGETBUFMODE                    = 0x4004427d
+	BIOCGETIF                         = 0x4020426b
+	BIOCGETZMAX                       = 0x4004427f
+	BIOCGHDRCMPLT                     = 0x40044274
+	BIOCGRSIG                         = 0x40044272
+	BIOCGRTIMEOUT                     = 0x4008426e
+	BIOCGSEESENT                      = 0x40044276
+	BIOCGSTATS                        = 0x4008426f
+	BIOCIMMEDIATE                     = 0x80044270
+	BIOCLOCK                          = 0x2000427a
+	BIOCPROMISC                       = 0x20004269
+	BIOCROTZBUF                       = 0x400c4280
+	BIOCSBLEN                         = 0xc0044266
+	BIOCSDIRECTION                    = 0x80044277
+	BIOCSDLT                          = 0x80044278
+	BIOCSETBUFMODE                    = 0x8004427e
+	BIOCSETF                          = 0x80084267
+	BIOCSETFNR                        = 0x80084282
+	BIOCSETIF                         = 0x8020426c
+	BIOCSETWF                         = 0x8008427b
+	BIOCSETZBUF                       = 0x800c4281
+	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_BUFMODE_BUFFER                = 0x1
+	BPF_BUFMODE_ZBUF                  = 0x2
+	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                       = 0x18
+	CTL_NET                           = 0x4
+	DLT_A429                          = 0xb8
+	DLT_A653_ICM                      = 0xb9
+	DLT_AIRONET_HEADER                = 0x78
+	DLT_APPLE_IP_OVER_IEEE1394        = 0x8a
+	DLT_ARCNET                        = 0x7
+	DLT_ARCNET_LINUX                  = 0x81
+	DLT_ATM_CLIP                      = 0x13
+	DLT_ATM_RFC1483                   = 0xb
+	DLT_AURORA                        = 0x7e
+	DLT_AX25                          = 0x3
+	DLT_AX25_KISS                     = 0xca
+	DLT_BACNET_MS_TP                  = 0xa5
+	DLT_BLUETOOTH_HCI_H4              = 0xbb
+	DLT_BLUETOOTH_HCI_H4_WITH_PHDR    = 0xc9
+	DLT_CAN20B                        = 0xbe
+	DLT_CHAOS                         = 0x5
+	DLT_CHDLC                         = 0x68
+	DLT_CISCO_IOS                     = 0x76
+	DLT_C_HDLC                        = 0x68
+	DLT_C_HDLC_WITH_DIR               = 0xcd
+	DLT_DOCSIS                        = 0x8f
+	DLT_ECONET                        = 0x73
+	DLT_EN10MB                        = 0x1
+	DLT_EN3MB                         = 0x2
+	DLT_ENC                           = 0x6d
+	DLT_ERF                           = 0xc5
+	DLT_ERF_ETH                       = 0xaf
+	DLT_ERF_POS                       = 0xb0
+	DLT_FDDI                          = 0xa
+	DLT_FLEXRAY                       = 0xd2
+	DLT_FRELAY                        = 0x6b
+	DLT_FRELAY_WITH_DIR               = 0xce
+	DLT_GCOM_SERIAL                   = 0xad
+	DLT_GCOM_T1E1                     = 0xac
+	DLT_GPF_F                         = 0xab
+	DLT_GPF_T                         = 0xaa
+	DLT_GPRS_LLC                      = 0xa9
+	DLT_HHDLC                         = 0x79
+	DLT_IBM_SN                        = 0x92
+	DLT_IBM_SP                        = 0x91
+	DLT_IEEE802                       = 0x6
+	DLT_IEEE802_11                    = 0x69
+	DLT_IEEE802_11_RADIO              = 0x7f
+	DLT_IEEE802_11_RADIO_AVS          = 0xa3
+	DLT_IEEE802_15_4                  = 0xc3
+	DLT_IEEE802_15_4_LINUX            = 0xbf
+	DLT_IEEE802_15_4_NONASK_PHY       = 0xd7
+	DLT_IEEE802_16_MAC_CPS            = 0xbc
+	DLT_IEEE802_16_MAC_CPS_RADIO      = 0xc1
+	DLT_IPFILTER                      = 0x74
+	DLT_IPMB                          = 0xc7
+	DLT_IPMB_LINUX                    = 0xd1
+	DLT_IP_OVER_FC                    = 0x7a
+	DLT_JUNIPER_ATM1                  = 0x89
+	DLT_JUNIPER_ATM2                  = 0x87
+	DLT_JUNIPER_CHDLC                 = 0xb5
+	DLT_JUNIPER_ES                    = 0x84
+	DLT_JUNIPER_ETHER                 = 0xb2
+	DLT_JUNIPER_FRELAY                = 0xb4
+	DLT_JUNIPER_GGSN                  = 0x85
+	DLT_JUNIPER_ISM                   = 0xc2
+	DLT_JUNIPER_MFR                   = 0x86
+	DLT_JUNIPER_MLFR                  = 0x83
+	DLT_JUNIPER_MLPPP                 = 0x82
+	DLT_JUNIPER_MONITOR               = 0xa4
+	DLT_JUNIPER_PIC_PEER              = 0xae
+	DLT_JUNIPER_PPP                   = 0xb3
+	DLT_JUNIPER_PPPOE                 = 0xa7
+	DLT_JUNIPER_PPPOE_ATM             = 0xa8
+	DLT_JUNIPER_SERVICES              = 0x88
+	DLT_JUNIPER_ST                    = 0xc8
+	DLT_JUNIPER_VP                    = 0xb7
+	DLT_LAPB_WITH_DIR                 = 0xcf
+	DLT_LAPD                          = 0xcb
+	DLT_LIN                           = 0xd4
+	DLT_LINUX_IRDA                    = 0x90
+	DLT_LINUX_LAPD                    = 0xb1
+	DLT_LINUX_PPP_WITHDIRECTION       = 0xa6
+	DLT_LINUX_SLL                     = 0x71
+	DLT_LOOP                          = 0x6c
+	DLT_LTALK                         = 0x72
+	DLT_MFR                           = 0xb6
+	DLT_MOST                          = 0xd3
+	DLT_MTP2                          = 0x8c
+	DLT_MTP2_WITH_PHDR                = 0x8b
+	DLT_MTP3                          = 0x8d
+	DLT_NULL                          = 0
+	DLT_PCI_EXP                       = 0x7d
+	DLT_PFLOG                         = 0x75
+	DLT_PFSYNC                        = 0x79
+	DLT_PPI                           = 0xc0
+	DLT_PPP                           = 0x9
+	DLT_PPP_BSDOS                     = 0x10
+	DLT_PPP_ETHER                     = 0x33
+	DLT_PPP_PPPD                      = 0xa6
+	DLT_PPP_SERIAL                    = 0x32
+	DLT_PPP_WITH_DIR                  = 0xcc
+	DLT_PPP_WITH_DIRECTION            = 0xa6
+	DLT_PRISM_HEADER                  = 0x77
+	DLT_PRONET                        = 0x4
+	DLT_RAIF1                         = 0xc6
+	DLT_RAW                           = 0xc
+	DLT_RIO                           = 0x7c
+	DLT_SCCP                          = 0x8e
+	DLT_SITA                          = 0xc4
+	DLT_SLIP                          = 0x8
+	DLT_SLIP_BSDOS                    = 0xf
+	DLT_SUNATM                        = 0x7b
+	DLT_SYMANTEC_FIREWALL             = 0x63
+	DLT_TZSP                          = 0x80
+	DLT_USB                           = 0xba
+	DLT_USB_LINUX                     = 0xbd
+	DLT_USER0                         = 0x93
+	DLT_USER1                         = 0x94
+	DLT_USER10                        = 0x9d
+	DLT_USER11                        = 0x9e
+	DLT_USER12                        = 0x9f
+	DLT_USER13                        = 0xa0
+	DLT_USER14                        = 0xa1
+	DLT_USER15                        = 0xa2
+	DLT_USER2                         = 0x95
+	DLT_USER3                         = 0x96
+	DLT_USER4                         = 0x97
+	DLT_USER5                         = 0x98
+	DLT_USER6                         = 0x99
+	DLT_USER7                         = 0x9a
+	DLT_USER8                         = 0x9b
+	DLT_USER9                         = 0x9c
+	DLT_X2E_SERIAL                    = 0xd5
+	DLT_X2E_XORAYA                    = 0xd6
+	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
+	EBADF                             = 0x9
+	EBADMSG                           = 0x59
+	EBADRPC                           = 0x48
+	EBUSY                             = 0x10
+	ECANCELED                         = 0x55
+	ECHILD                            = 0xa
+	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
+	EVFILT_PROC                       = -0x5
+	EVFILT_READ                       = -0x1
+	EVFILT_SIGNAL                     = -0x6
+	EVFILT_SYSCOUNT                   = 0xb
+	EVFILT_TIMER                      = -0x7
+	EVFILT_USER                       = -0xb
+	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_FLAG1                          = 0x2000
+	EV_ONESHOT                        = 0x10
+	EV_RECEIPT                        = 0x40
+	EV_SYSFLAGS                       = 0xf000
+	EWOULDBLOCK                       = 0x23
+	EXDEV                             = 0x12
+	FD_CLOEXEC                        = 0x1
+	FD_SETSIZE                        = 0x400
+	F_CANCEL                          = 0x5
+	F_DUP2FD                          = 0xa
+	F_DUPFD                           = 0
+	F_GETFD                           = 0x1
+	F_GETFL                           = 0x3
+	F_GETLK                           = 0xb
+	F_GETOWN                          = 0x5
+	F_OGETLK                          = 0x7
+	F_OSETLK                          = 0x8
+	F_OSETLKW                         = 0x9
+	F_RDAHEAD                         = 0x10
+	F_RDLCK                           = 0x1
+	F_READAHEAD                       = 0xf
+	F_SETFD                           = 0x2
+	F_SETFL                           = 0x4
+	F_SETLK                           = 0xc
+	F_SETLKW                          = 0xd
+	F_SETLK_REMOTE                    = 0xe
+	F_SETOWN                          = 0x6
+	F_UNLCK                           = 0x2
+	F_UNLCKSYS                        = 0x4
+	F_WRLCK                           = 0x3
+	IFF_ALLMULTI                      = 0x200
+	IFF_ALTPHYS                       = 0x4000
+	IFF_BROADCAST                     = 0x2
+	IFF_CANTCHANGE                    = 0x208f72
+	IFF_DEBUG                         = 0x4
+	IFF_DRV_OACTIVE                   = 0x400
+	IFF_DRV_RUNNING                   = 0x40
+	IFF_DYING                         = 0x200000
+	IFF_LINK0                         = 0x1000
+	IFF_LINK1                         = 0x2000
+	IFF_LINK2                         = 0x4000
+	IFF_LOOPBACK                      = 0x8
+	IFF_MONITOR                       = 0x40000
+	IFF_MULTICAST                     = 0x8000
+	IFF_NOARP                         = 0x80
+	IFF_OACTIVE                       = 0x400
+	IFF_POINTOPOINT                   = 0x10
+	IFF_PPROMISC                      = 0x20000
+	IFF_PROMISC                       = 0x100
+	IFF_RENAMING                      = 0x400000
+	IFF_RUNNING                       = 0x40
+	IFF_SIMPLEX                       = 0x800
+	IFF_SMART                         = 0x20
+	IFF_STATICARP                     = 0x80000
+	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_BRIDGE                        = 0xd1
+	IFT_BSC                           = 0x53
+	IFT_CARP                          = 0xf8
+	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_DS0                           = 0x51
+	IFT_DS0BUNDLE                     = 0x52
+	IFT_DS1FDL                        = 0xaa
+	IFT_DS3                           = 0x1e
+	IFT_DTM                           = 0x8c
+	IFT_DVBASILN                      = 0xac
+	IFT_DVBASIOUT                     = 0xad
+	IFT_DVBRCCDOWNSTREAM              = 0x93
+	IFT_DVBRCCMACLAYER                = 0x92
+	IFT_DVBRCCUPSTREAM                = 0x94
+	IFT_ENC                           = 0xf4
+	IFT_EON                           = 0x19
+	IFT_EPLRS                         = 0x57
+	IFT_ESCON                         = 0x49
+	IFT_ETHER                         = 0x6
+	IFT_FAITH                         = 0xf2
+	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_INTERLEAVE                    = 0x7c
+	IFT_IP                            = 0x7e
+	IFT_IPFORWARD                     = 0x8e
+	IFT_IPOVERATM                     = 0x72
+	IFT_IPOVERCDLC                    = 0x6d
+	IFT_IPOVERCLAW                    = 0x6e
+	IFT_IPSWITCH                      = 0x4e
+	IFT_IPXIP                         = 0xf9
+	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_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                         = 0xf6
+	IFT_PFSYNC                        = 0xf7
+	IFT_PLC                           = 0xae
+	IFT_POS                           = 0xab
+	IFT_PPP                           = 0x17
+	IFT_PPPMULTILINKBUNDLE            = 0x6c
+	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                           = 0xf1
+	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_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_STF                           = 0xd7
+	IFT_T1                            = 0x12
+	IFT_TDLC                          = 0x74
+	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_VOICEEM                       = 0x64
+	IFT_VOICEENCAP                    = 0x67
+	IFT_VOICEFXO                      = 0x65
+	IFT_VOICEFXS                      = 0x66
+	IFT_VOICEOVERATM                  = 0x98
+	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
+	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_CARP                      = 0x70
+	IPPROTO_CFTP                      = 0x3e
+	IPPROTO_CHAOS                     = 0x10
+	IPPROTO_CMTP                      = 0x26
+	IPPROTO_CPHB                      = 0x49
+	IPPROTO_CPNX                      = 0x48
+	IPPROTO_DDP                       = 0x25
+	IPPROTO_DGP                       = 0x56
+	IPPROTO_DIVERT                    = 0x102
+	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_MOBILE                    = 0x37
+	IPPROTO_MTP                       = 0x5c
+	IPPROTO_MUX                       = 0x12
+	IPPROTO_ND                        = 0x4d
+	IPPROTO_NHRP                      = 0x36
+	IPPROTO_NONE                      = 0x3b
+	IPPROTO_NSP                       = 0x1f
+	IPPROTO_NVPII                     = 0xb
+	IPPROTO_OLD_DIVERT                = 0xfe
+	IPPROTO_OSPFIGP                   = 0x59
+	IPPROTO_PFSYNC                    = 0xf0
+	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_SKIP                      = 0x39
+	IPPROTO_SPACER                    = 0x7fff
+	IPPROTO_SRPC                      = 0x5a
+	IPPROTO_ST                        = 0x7
+	IPPROTO_SVMTP                     = 0x52
+	IPPROTO_SWIPE                     = 0x35
+	IPPROTO_TCF                       = 0x57
+	IPPROTO_TCP                       = 0x6
+	IPPROTO_TLSP                      = 0x38
+	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_AUTOFLOWLABEL                = 0x3b
+	IPV6_BINDANY                      = 0x40
+	IPV6_BINDV6ONLY                   = 0x1b
+	IPV6_CHECKSUM                     = 0x1a
+	IPV6_DEFAULT_MULTICAST_HOPS       = 0x1
+	IPV6_DEFAULT_MULTICAST_LOOP       = 0x1
+	IPV6_DEFHLIM                      = 0x40
+	IPV6_DONTFRAG                     = 0x3e
+	IPV6_DSTOPTS                      = 0x32
+	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                     = 0x2f
+	IPV6_HOPOPTS                      = 0x31
+	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_MSFILTER                     = 0x4a
+	IPV6_MULTICAST_HOPS               = 0xa
+	IPV6_MULTICAST_IF                 = 0x9
+	IPV6_MULTICAST_LOOP               = 0xb
+	IPV6_NEXTHOP                      = 0x30
+	IPV6_PATHMTU                      = 0x2c
+	IPV6_PKTINFO                      = 0x2e
+	IPV6_PORTRANGE                    = 0xe
+	IPV6_PORTRANGE_DEFAULT            = 0
+	IPV6_PORTRANGE_HIGH               = 0x1
+	IPV6_PORTRANGE_LOW                = 0x2
+	IPV6_PREFER_TEMPADDR              = 0x3f
+	IPV6_RECVDSTOPTS                  = 0x28
+	IPV6_RECVHOPLIMIT                 = 0x25
+	IPV6_RECVHOPOPTS                  = 0x27
+	IPV6_RECVPATHMTU                  = 0x2b
+	IPV6_RECVPKTINFO                  = 0x24
+	IPV6_RECVRTHDR                    = 0x26
+	IPV6_RECVTCLASS                   = 0x39
+	IPV6_RTHDR                        = 0x33
+	IPV6_RTHDRDSTOPTS                 = 0x23
+	IPV6_RTHDR_LOOSE                  = 0
+	IPV6_RTHDR_STRICT                 = 0x1
+	IPV6_RTHDR_TYPE_0                 = 0
+	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_ADD_SOURCE_MEMBERSHIP          = 0x46
+	IP_BINDANY                        = 0x18
+	IP_BLOCK_SOURCE                   = 0x48
+	IP_DEFAULT_MULTICAST_LOOP         = 0x1
+	IP_DEFAULT_MULTICAST_TTL          = 0x1
+	IP_DF                             = 0x4000
+	IP_DONTFRAG                       = 0x43
+	IP_DROP_MEMBERSHIP                = 0xd
+	IP_DROP_SOURCE_MEMBERSHIP         = 0x47
+	IP_DUMMYNET3                      = 0x31
+	IP_DUMMYNET_CONFIGURE             = 0x3c
+	IP_DUMMYNET_DEL                   = 0x3d
+	IP_DUMMYNET_FLUSH                 = 0x3e
+	IP_DUMMYNET_GET                   = 0x40
+	IP_FAITH                          = 0x16
+	IP_FW3                            = 0x30
+	IP_FW_ADD                         = 0x32
+	IP_FW_DEL                         = 0x33
+	IP_FW_FLUSH                       = 0x34
+	IP_FW_GET                         = 0x36
+	IP_FW_NAT_CFG                     = 0x38
+	IP_FW_NAT_DEL                     = 0x39
+	IP_FW_NAT_GET_CONFIG              = 0x3a
+	IP_FW_NAT_GET_LOG                 = 0x3b
+	IP_FW_RESETLOG                    = 0x37
+	IP_FW_TABLE_ADD                   = 0x28
+	IP_FW_TABLE_DEL                   = 0x29
+	IP_FW_TABLE_FLUSH                 = 0x2a
+	IP_FW_TABLE_GETSIZE               = 0x2b
+	IP_FW_TABLE_LIST                  = 0x2c
+	IP_FW_ZERO                        = 0x35
+	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_MAX_SOURCE_FILTER              = 0x400
+	IP_MF                             = 0x2000
+	IP_MINTTL                         = 0x42
+	IP_MIN_MEMBERSHIPS                = 0x1f
+	IP_MSFILTER                       = 0x4a
+	IP_MSS                            = 0x240
+	IP_MULTICAST_IF                   = 0x9
+	IP_MULTICAST_LOOP                 = 0xb
+	IP_MULTICAST_TTL                  = 0xa
+	IP_MULTICAST_VIF                  = 0xe
+	IP_OFFMASK                        = 0x1fff
+	IP_ONESBCAST                      = 0x17
+	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                        = 0x41
+	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_SENDSRCADDR                    = 0x7
+	IP_TOS                            = 0x3
+	IP_TTL                            = 0x4
+	IP_UNBLOCK_SOURCE                 = 0x49
+	MSG_COMPAT                        = 0x8000
+	MSG_CTRUNC                        = 0x20
+	MSG_DONTROUTE                     = 0x4
+	MSG_DONTWAIT                      = 0x80
+	MSG_EOF                           = 0x100
+	MSG_EOR                           = 0x8
+	MSG_NBIO                          = 0x4000
+	MSG_NOSIGNAL                      = 0x20000
+	MSG_NOTIFICATION                  = 0x2000
+	MSG_OOB                           = 0x1
+	MSG_PEEK                          = 0x2
+	MSG_TRUNC                         = 0x10
+	MSG_WAITALL                       = 0x40
+	NET_RT_DUMP                       = 0x1
+	NET_RT_FLAGS                      = 0x2
+	NET_RT_IFLIST                     = 0x3
+	NET_RT_IFMALIST                   = 0x4
+	NET_RT_MAXID                      = 0x5
+	O_ACCMODE                         = 0x3
+	O_APPEND                          = 0x8
+	O_ASYNC                           = 0x40
+	O_CREAT                           = 0x200
+	O_DIRECT                          = 0x10000
+	O_DIRECTORY                       = 0x20000
+	O_EXCL                            = 0x800
+	O_EXEC                            = 0x40000
+	O_EXLOCK                          = 0x20
+	O_FSYNC                           = 0x80
+	O_NDELAY                          = 0x4
+	O_NOCTTY                          = 0x8000
+	O_NOFOLLOW                        = 0x100
+	O_NONBLOCK                        = 0x4
+	O_RDONLY                          = 0
+	O_RDWR                            = 0x2
+	O_SHLOCK                          = 0x10
+	O_SYNC                            = 0x80
+	O_TRUNC                           = 0x400
+	O_TTY_INIT                        = 0x80000
+	O_WRONLY                          = 0x1
+	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_DONE                          = 0x40
+	RTF_DYNAMIC                       = 0x10
+	RTF_FMASK                         = 0x1004d808
+	RTF_GATEWAY                       = 0x2
+	RTF_HOST                          = 0x4
+	RTF_LLDATA                        = 0x400
+	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_RNH_LOCKED                    = 0x40000000
+	RTF_STATIC                        = 0x800
+	RTF_STICKY                        = 0x10000000
+	RTF_UP                            = 0x1
+	RTF_XRESOLVE                      = 0x200
+	RTM_ADD                           = 0x1
+	RTM_CHANGE                        = 0x3
+	RTM_DELADDR                       = 0xd
+	RTM_DELETE                        = 0x2
+	RTM_DELMADDR                      = 0x10
+	RTM_GET                           = 0x4
+	RTM_IEEE80211                     = 0x12
+	RTM_IFANNOUNCE                    = 0x11
+	RTM_IFINFO                        = 0xe
+	RTM_LOCK                          = 0x8
+	RTM_LOSING                        = 0x5
+	RTM_MISS                          = 0x7
+	RTM_NEWADDR                       = 0xc
+	RTM_NEWMADDR                      = 0xf
+	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
+	RTV_WEIGHT                        = 0x100
+	SCM_BINTIME                       = 0x4
+	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
+	SIGLWP                            = 0x20
+	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
+	SIOCADDRT                         = 0x8030720a
+	SIOCAIFADDR                       = 0x8040691a
+	SIOCAIFGROUP                      = 0x80246987
+	SIOCALIFADDR                      = 0x8118691b
+	SIOCATMARK                        = 0x40047307
+	SIOCDELMULTI                      = 0x80206932
+	SIOCDELRT                         = 0x8030720b
+	SIOCDIFADDR                       = 0x80206919
+	SIOCDIFGROUP                      = 0x80246989
+	SIOCDIFPHYADDR                    = 0x80206949
+	SIOCDLIFADDR                      = 0x8118691d
+	SIOCGDRVSPEC                      = 0xc01c697b
+	SIOCGETSGCNT                      = 0xc0147210
+	SIOCGETVIFCNT                     = 0xc014720f
+	SIOCGHIWAT                        = 0x40047301
+	SIOCGIFADDR                       = 0xc0206921
+	SIOCGIFBRDADDR                    = 0xc0206923
+	SIOCGIFCAP                        = 0xc020691f
+	SIOCGIFCONF                       = 0xc0086924
+	SIOCGIFDESCR                      = 0xc020692a
+	SIOCGIFDSTADDR                    = 0xc0206922
+	SIOCGIFFLAGS                      = 0xc0206911
+	SIOCGIFGENERIC                    = 0xc020693a
+	SIOCGIFGMEMB                      = 0xc024698a
+	SIOCGIFGROUP                      = 0xc0246988
+	SIOCGIFINDEX                      = 0xc0206920
+	SIOCGIFMAC                        = 0xc0206926
+	SIOCGIFMEDIA                      = 0xc0286938
+	SIOCGIFMETRIC                     = 0xc0206917
+	SIOCGIFMTU                        = 0xc0206933
+	SIOCGIFNETMASK                    = 0xc0206925
+	SIOCGIFPDSTADDR                   = 0xc0206948
+	SIOCGIFPHYS                       = 0xc0206935
+	SIOCGIFPSRCADDR                   = 0xc0206947
+	SIOCGIFSTATUS                     = 0xc331693b
+	SIOCGLIFADDR                      = 0xc118691c
+	SIOCGLIFPHYADDR                   = 0xc118694b
+	SIOCGLOWAT                        = 0x40047303
+	SIOCGPGRP                         = 0x40047309
+	SIOCGPRIVATE_0                    = 0xc0206950
+	SIOCGPRIVATE_1                    = 0xc0206951
+	SIOCIFCREATE                      = 0xc020697a
+	SIOCIFCREATE2                     = 0xc020697c
+	SIOCIFDESTROY                     = 0x80206979
+	SIOCIFGCLONERS                    = 0xc00c6978
+	SIOCSDRVSPEC                      = 0x801c697b
+	SIOCSHIWAT                        = 0x80047300
+	SIOCSIFADDR                       = 0x8020690c
+	SIOCSIFBRDADDR                    = 0x80206913
+	SIOCSIFCAP                        = 0x8020691e
+	SIOCSIFDESCR                      = 0x80206929
+	SIOCSIFDSTADDR                    = 0x8020690e
+	SIOCSIFFLAGS                      = 0x80206910
+	SIOCSIFGENERIC                    = 0x80206939
+	SIOCSIFLLADDR                     = 0x8020693c
+	SIOCSIFMAC                        = 0x80206927
+	SIOCSIFMEDIA                      = 0xc0206937
+	SIOCSIFMETRIC                     = 0x80206918
+	SIOCSIFMTU                        = 0x80206934
+	SIOCSIFNAME                       = 0x80206928
+	SIOCSIFNETMASK                    = 0x80206916
+	SIOCSIFPHYADDR                    = 0x80406946
+	SIOCSIFPHYS                       = 0x80206936
+	SIOCSIFRVNET                      = 0xc020695b
+	SIOCSIFVNET                       = 0xc020695a
+	SIOCSLIFPHYADDR                   = 0x8118694a
+	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_ACCEPTFILTER                   = 0x1000
+	SO_BINTIME                        = 0x2000
+	SO_BROADCAST                      = 0x20
+	SO_DEBUG                          = 0x1
+	SO_DONTROUTE                      = 0x10
+	SO_ERROR                          = 0x1007
+	SO_KEEPALIVE                      = 0x8
+	SO_LABEL                          = 0x1009
+	SO_LINGER                         = 0x80
+	SO_LISTENINCQLEN                  = 0x1013
+	SO_LISTENQLEN                     = 0x1012
+	SO_LISTENQLIMIT                   = 0x1011
+	SO_NOSIGPIPE                      = 0x800
+	SO_NO_DDP                         = 0x8000
+	SO_NO_OFFLOAD                     = 0x4000
+	SO_OOBINLINE                      = 0x100
+	SO_PEERLABEL                      = 0x1010
+	SO_RCVBUF                         = 0x1002
+	SO_RCVLOWAT                       = 0x1004
+	SO_RCVTIMEO                       = 0x1006
+	SO_REUSEADDR                      = 0x4
+	SO_REUSEPORT                      = 0x200
+	SO_SETFIB                         = 0x1014
+	SO_SNDBUF                         = 0x1001
+	SO_SNDLOWAT                       = 0x1003
+	SO_SNDTIMEO                       = 0x1005
+	SO_TIMESTAMP                      = 0x400
+	SO_TYPE                           = 0x1008
+	SO_USELOOPBACK                    = 0x40
+	TCP_CA_NAME_MAX                   = 0x10
+	TCP_CONGESTION                    = 0x40
+	TCP_INFO                          = 0x20
+	TCP_MAXBURST                      = 0x4
+	TCP_MAXHLEN                       = 0x3c
+	TCP_MAXOLEN                       = 0x28
+	TCP_MAXSEG                        = 0x2
+	TCP_MAXWIN                        = 0xffff
+	TCP_MAX_SACK                      = 0x4
+	TCP_MAX_WINSHIFT                  = 0xe
+	TCP_MD5SIG                        = 0x10
+	TCP_MINMSS                        = 0xd8
+	TCP_MSS                           = 0x200
+	TCP_NODELAY                       = 0x1
+	TCP_NOOPT                         = 0x8
+	TCP_NOPUSH                        = 0x4
+	WCONTINUED                        = 0x4
+	WCOREFLAG                         = 0x80
+	WLINUXCLONE                       = 0x80000000
+	WNOHANG                           = 0x1
+	WNOWAIT                           = 0x8
+	WSTOPPED                          = 0x2
+	WUNTRACED                         = 0x2
 )
 
 // Types
diff --git a/src/pkg/syscall/zerrors_freebsd_amd64.go b/src/pkg/syscall/zerrors_freebsd_amd64.go
index 33fd3de..9b632ba 100644
--- a/src/pkg/syscall/zerrors_freebsd_amd64.go
+++ b/src/pkg/syscall/zerrors_freebsd_amd64.go
@@ -9,1013 +9,1228 @@ package syscall
 
 // Constants
 const (
-	AF_APPLETALK                   = 0x10
-	AF_ARP                         = 0x23
-	AF_ATM                         = 0x1e
-	AF_BLUETOOTH                   = 0x24
-	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_HYLINK                      = 0xf
-	AF_IEEE80211                   = 0x25
-	AF_IMPLINK                     = 0x3
-	AF_INET                        = 0x2
-	AF_INET6                       = 0x1c
-	AF_IPX                         = 0x17
-	AF_ISDN                        = 0x1a
-	AF_ISO                         = 0x7
-	AF_LAT                         = 0xe
-	AF_LINK                        = 0x12
-	AF_LOCAL                       = 0x1
-	AF_MAX                         = 0x26
-	AF_NATM                        = 0x1d
-	AF_NETBIOS                     = 0x6
-	AF_NETGRAPH                    = 0x20
-	AF_OSI                         = 0x7
-	AF_PUP                         = 0x4
-	AF_ROUTE                       = 0x11
-	AF_SCLUSTER                    = 0x22
-	AF_SIP                         = 0x18
-	AF_SLOW                        = 0x21
-	AF_SNA                         = 0xb
-	AF_UNIX                        = 0x1
-	AF_UNSPEC                      = 0
-	AF_VENDOR00                    = 0x27
-	AF_VENDOR01                    = 0x29
-	AF_VENDOR02                    = 0x2b
-	AF_VENDOR03                    = 0x2d
-	AF_VENDOR04                    = 0x2f
-	AF_VENDOR05                    = 0x31
-	AF_VENDOR06                    = 0x33
-	AF_VENDOR07                    = 0x35
-	AF_VENDOR08                    = 0x37
-	AF_VENDOR09                    = 0x39
-	AF_VENDOR10                    = 0x3b
-	AF_VENDOR11                    = 0x3d
-	AF_VENDOR12                    = 0x3f
-	AF_VENDOR13                    = 0x41
-	AF_VENDOR14                    = 0x43
-	AF_VENDOR15                    = 0x45
-	AF_VENDOR16                    = 0x47
-	AF_VENDOR17                    = 0x49
-	AF_VENDOR18                    = 0x4b
-	AF_VENDOR19                    = 0x4d
-	AF_VENDOR20                    = 0x4f
-	AF_VENDOR21                    = 0x51
-	AF_VENDOR22                    = 0x53
-	AF_VENDOR23                    = 0x55
-	AF_VENDOR24                    = 0x57
-	AF_VENDOR25                    = 0x59
-	AF_VENDOR26                    = 0x5b
-	AF_VENDOR27                    = 0x5d
-	AF_VENDOR28                    = 0x5f
-	AF_VENDOR29                    = 0x61
-	AF_VENDOR30                    = 0x63
-	AF_VENDOR31                    = 0x65
-	AF_VENDOR32                    = 0x67
-	AF_VENDOR33                    = 0x69
-	AF_VENDOR34                    = 0x6b
-	AF_VENDOR35                    = 0x6d
-	AF_VENDOR36                    = 0x6f
-	AF_VENDOR37                    = 0x71
-	AF_VENDOR38                    = 0x73
-	AF_VENDOR39                    = 0x75
-	AF_VENDOR40                    = 0x77
-	AF_VENDOR41                    = 0x79
-	AF_VENDOR42                    = 0x7b
-	AF_VENDOR43                    = 0x7d
-	AF_VENDOR44                    = 0x7f
-	AF_VENDOR45                    = 0x81
-	AF_VENDOR46                    = 0x83
-	AF_VENDOR47                    = 0x85
-	BIOCFEEDBACK                   = 0x8004427c
-	BIOCFLUSH                      = 0x20004268
-	BIOCGBLEN                      = 0x40044266
-	BIOCGDIRECTION                 = 0x40044276
-	BIOCGDLT                       = 0x4004426a
-	BIOCGDLTLIST                   = 0xc0104279
-	BIOCGETBUFMODE                 = 0x4004427d
-	BIOCGETIF                      = 0x4020426b
-	BIOCGETZMAX                    = 0x4008427f
-	BIOCGHDRCMPLT                  = 0x40044274
-	BIOCGRSIG                      = 0x40044272
-	BIOCGRTIMEOUT                  = 0x4010426e
-	BIOCGSEESENT                   = 0x40044276
-	BIOCGSTATS                     = 0x4008426f
-	BIOCIMMEDIATE                  = 0x80044270
-	BIOCLOCK                       = 0x2000427a
-	BIOCPROMISC                    = 0x20004269
-	BIOCROTZBUF                    = 0x40184280
-	BIOCSBLEN                      = 0xc0044266
-	BIOCSDIRECTION                 = 0x80044277
-	BIOCSDLT                       = 0x80044278
-	BIOCSETBUFMODE                 = 0x8004427e
-	BIOCSETF                       = 0x80104267
-	BIOCSETFNR                     = 0x80104282
-	BIOCSETIF                      = 0x8020426c
-	BIOCSETWF                      = 0x8010427b
-	BIOCSETZBUF                    = 0x80184281
-	BIOCSHDRCMPLT                  = 0x80044275
-	BIOCSRSIG                      = 0x80044273
-	BIOCSRTIMEOUT                  = 0x8010426d
-	BIOCSSEESENT                   = 0x80044277
-	BIOCVERSION                    = 0x40044271
-	BPF_A                          = 0x10
-	BPF_ABS                        = 0x20
-	BPF_ADD                        = 0
-	BPF_ALIGNMENT                  = 0x8
-	BPF_ALU                        = 0x4
-	BPF_AND                        = 0x50
-	BPF_B                          = 0x10
-	BPF_BUFMODE_BUFFER             = 0x1
-	BPF_BUFMODE_ZBUF               = 0x2
-	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                    = 0x18
-	CTL_NET                        = 0x4
-	DLT_A429                       = 0xb8
-	DLT_A653_ICM                   = 0xb9
-	DLT_AIRONET_HEADER             = 0x78
-	DLT_APPLE_IP_OVER_IEEE1394     = 0x8a
-	DLT_ARCNET                     = 0x7
-	DLT_ARCNET_LINUX               = 0x81
-	DLT_ATM_CLIP                   = 0x13
-	DLT_ATM_RFC1483                = 0xb
-	DLT_AURORA                     = 0x7e
-	DLT_AX25                       = 0x3
-	DLT_AX25_KISS                  = 0xca
-	DLT_BACNET_MS_TP               = 0xa5
-	DLT_BLUETOOTH_HCI_H4           = 0xbb
-	DLT_BLUETOOTH_HCI_H4_WITH_PHDR = 0xc9
-	DLT_CAN20B                     = 0xbe
-	DLT_CHAOS                      = 0x5
-	DLT_CHDLC                      = 0x68
-	DLT_CISCO_IOS                  = 0x76
-	DLT_C_HDLC                     = 0x68
-	DLT_C_HDLC_WITH_DIR            = 0xcd
-	DLT_DOCSIS                     = 0x8f
-	DLT_ECONET                     = 0x73
-	DLT_EN10MB                     = 0x1
-	DLT_EN3MB                      = 0x2
-	DLT_ENC                        = 0x6d
-	DLT_ERF                        = 0xc5
-	DLT_ERF_ETH                    = 0xaf
-	DLT_ERF_POS                    = 0xb0
-	DLT_FDDI                       = 0xa
-	DLT_FLEXRAY                    = 0xd2
-	DLT_FRELAY                     = 0x6b
-	DLT_FRELAY_WITH_DIR            = 0xce
-	DLT_GCOM_SERIAL                = 0xad
-	DLT_GCOM_T1E1                  = 0xac
-	DLT_GPF_F                      = 0xab
-	DLT_GPF_T                      = 0xaa
-	DLT_GPRS_LLC                   = 0xa9
-	DLT_HHDLC                      = 0x79
-	DLT_IBM_SN                     = 0x92
-	DLT_IBM_SP                     = 0x91
-	DLT_IEEE802                    = 0x6
-	DLT_IEEE802_11                 = 0x69
-	DLT_IEEE802_11_RADIO           = 0x7f
-	DLT_IEEE802_11_RADIO_AVS       = 0xa3
-	DLT_IEEE802_15_4               = 0xc3
-	DLT_IEEE802_15_4_LINUX         = 0xbf
-	DLT_IEEE802_15_4_NONASK_PHY    = 0xd7
-	DLT_IEEE802_16_MAC_CPS         = 0xbc
-	DLT_IEEE802_16_MAC_CPS_RADIO   = 0xc1
-	DLT_IPFILTER                   = 0x74
-	DLT_IPMB                       = 0xc7
-	DLT_IPMB_LINUX                 = 0xd1
-	DLT_IP_OVER_FC                 = 0x7a
-	DLT_JUNIPER_ATM1               = 0x89
-	DLT_JUNIPER_ATM2               = 0x87
-	DLT_JUNIPER_CHDLC              = 0xb5
-	DLT_JUNIPER_ES                 = 0x84
-	DLT_JUNIPER_ETHER              = 0xb2
-	DLT_JUNIPER_FRELAY             = 0xb4
-	DLT_JUNIPER_GGSN               = 0x85
-	DLT_JUNIPER_ISM                = 0xc2
-	DLT_JUNIPER_MFR                = 0x86
-	DLT_JUNIPER_MLFR               = 0x83
-	DLT_JUNIPER_MLPPP              = 0x82
-	DLT_JUNIPER_MONITOR            = 0xa4
-	DLT_JUNIPER_PIC_PEER           = 0xae
-	DLT_JUNIPER_PPP                = 0xb3
-	DLT_JUNIPER_PPPOE              = 0xa7
-	DLT_JUNIPER_PPPOE_ATM          = 0xa8
-	DLT_JUNIPER_SERVICES           = 0x88
-	DLT_JUNIPER_ST                 = 0xc8
-	DLT_JUNIPER_VP                 = 0xb7
-	DLT_LAPB_WITH_DIR              = 0xcf
-	DLT_LAPD                       = 0xcb
-	DLT_LIN                        = 0xd4
-	DLT_LINUX_IRDA                 = 0x90
-	DLT_LINUX_LAPD                 = 0xb1
-	DLT_LINUX_PPP_WITHDIRECTION    = 0xa6
-	DLT_LINUX_SLL                  = 0x71
-	DLT_LOOP                       = 0x6c
-	DLT_LTALK                      = 0x72
-	DLT_MFR                        = 0xb6
-	DLT_MOST                       = 0xd3
-	DLT_MTP2                       = 0x8c
-	DLT_MTP2_WITH_PHDR             = 0x8b
-	DLT_MTP3                       = 0x8d
-	DLT_NULL                       = 0
-	DLT_PCI_EXP                    = 0x7d
-	DLT_PFLOG                      = 0x75
-	DLT_PFSYNC                     = 0x79
-	DLT_PPI                        = 0xc0
-	DLT_PPP                        = 0x9
-	DLT_PPP_BSDOS                  = 0x10
-	DLT_PPP_ETHER                  = 0x33
-	DLT_PPP_PPPD                   = 0xa6
-	DLT_PPP_SERIAL                 = 0x32
-	DLT_PPP_WITH_DIR               = 0xcc
-	DLT_PPP_WITH_DIRECTION         = 0xa6
-	DLT_PRISM_HEADER               = 0x77
-	DLT_PRONET                     = 0x4
-	DLT_RAIF1                      = 0xc6
-	DLT_RAW                        = 0xc
-	DLT_RIO                        = 0x7c
-	DLT_SCCP                       = 0x8e
-	DLT_SITA                       = 0xc4
-	DLT_SLIP                       = 0x8
-	DLT_SLIP_BSDOS                 = 0xf
-	DLT_SUNATM                     = 0x7b
-	DLT_SYMANTEC_FIREWALL          = 0x63
-	DLT_TZSP                       = 0x80
-	DLT_USB                        = 0xba
-	DLT_USB_LINUX                  = 0xbd
-	DLT_USER0                      = 0x93
-	DLT_USER1                      = 0x94
-	DLT_USER10                     = 0x9d
-	DLT_USER11                     = 0x9e
-	DLT_USER12                     = 0x9f
-	DLT_USER13                     = 0xa0
-	DLT_USER14                     = 0xa1
-	DLT_USER15                     = 0xa2
-	DLT_USER2                      = 0x95
-	DLT_USER3                      = 0x96
-	DLT_USER4                      = 0x97
-	DLT_USER5                      = 0x98
-	DLT_USER6                      = 0x99
-	DLT_USER7                      = 0x9a
-	DLT_USER8                      = 0x9b
-	DLT_USER9                      = 0x9c
-	DLT_X2E_SERIAL                 = 0xd5
-	DLT_X2E_XORAYA                 = 0xd6
-	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
-	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
-	EVFILT_PROC                    = -0x5
-	EVFILT_READ                    = -0x1
-	EVFILT_SIGNAL                  = -0x6
-	EVFILT_SYSCOUNT                = 0xb
-	EVFILT_TIMER                   = -0x7
-	EVFILT_USER                    = -0xb
-	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_FLAG1                       = 0x2000
-	EV_ONESHOT                     = 0x10
-	EV_RECEIPT                     = 0x40
-	EV_SYSFLAGS                    = 0xf000
-	EWOULDBLOCK                    = 0x23
-	EXDEV                          = 0x12
-	FD_CLOEXEC                     = 0x1
-	FD_SETSIZE                     = 0x400
-	F_CANCEL                       = 0x5
-	F_DUP2FD                       = 0xa
-	F_DUPFD                        = 0
-	F_GETFD                        = 0x1
-	F_GETFL                        = 0x3
-	F_GETLK                        = 0xb
-	F_GETOWN                       = 0x5
-	F_OGETLK                       = 0x7
-	F_OSETLK                       = 0x8
-	F_OSETLKW                      = 0x9
-	F_RDAHEAD                      = 0x10
-	F_RDLCK                        = 0x1
-	F_READAHEAD                    = 0xf
-	F_SETFD                        = 0x2
-	F_SETFL                        = 0x4
-	F_SETLK                        = 0xc
-	F_SETLKW                       = 0xd
-	F_SETLK_REMOTE                 = 0xe
-	F_SETOWN                       = 0x6
-	F_UNLCK                        = 0x2
-	F_UNLCKSYS                     = 0x4
-	F_WRLCK                        = 0x3
-	IFF_ALLMULTI                   = 0x200
-	IFF_ALTPHYS                    = 0x4000
-	IFF_BROADCAST                  = 0x2
-	IFF_CANTCHANGE                 = 0x208f72
-	IFF_DEBUG                      = 0x4
-	IFF_DRV_OACTIVE                = 0x400
-	IFF_DRV_RUNNING                = 0x40
-	IFF_DYING                      = 0x200000
-	IFF_LINK0                      = 0x1000
-	IFF_LINK1                      = 0x2000
-	IFF_LINK2                      = 0x4000
-	IFF_LOOPBACK                   = 0x8
-	IFF_MONITOR                    = 0x40000
-	IFF_MULTICAST                  = 0x8000
-	IFF_NOARP                      = 0x80
-	IFF_OACTIVE                    = 0x400
-	IFF_POINTOPOINT                = 0x10
-	IFF_PPROMISC                   = 0x20000
-	IFF_PROMISC                    = 0x100
-	IFF_RENAMING                   = 0x400000
-	IFF_RUNNING                    = 0x40
-	IFF_SIMPLEX                    = 0x800
-	IFF_SMART                      = 0x20
-	IFF_STATICARP                  = 0x80000
-	IFF_UP                         = 0x1
-	IFNAMSIZ                       = 0x10
-	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
-	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_CARP                   = 0x70
-	IPPROTO_CFTP                   = 0x3e
-	IPPROTO_CHAOS                  = 0x10
-	IPPROTO_CMTP                   = 0x26
-	IPPROTO_CPHB                   = 0x49
-	IPPROTO_CPNX                   = 0x48
-	IPPROTO_DDP                    = 0x25
-	IPPROTO_DGP                    = 0x56
-	IPPROTO_DIVERT                 = 0x102
-	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_MOBILE                 = 0x37
-	IPPROTO_MTP                    = 0x5c
-	IPPROTO_MUX                    = 0x12
-	IPPROTO_ND                     = 0x4d
-	IPPROTO_NHRP                   = 0x36
-	IPPROTO_NONE                   = 0x3b
-	IPPROTO_NSP                    = 0x1f
-	IPPROTO_NVPII                  = 0xb
-	IPPROTO_OLD_DIVERT             = 0xfe
-	IPPROTO_OSPFIGP                = 0x59
-	IPPROTO_PFSYNC                 = 0xf0
-	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_SKIP                   = 0x39
-	IPPROTO_SPACER                 = 0x7fff
-	IPPROTO_SRPC                   = 0x5a
-	IPPROTO_ST                     = 0x7
-	IPPROTO_SVMTP                  = 0x52
-	IPPROTO_SWIPE                  = 0x35
-	IPPROTO_TCF                    = 0x57
-	IPPROTO_TCP                    = 0x6
-	IPPROTO_TLSP                   = 0x38
-	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_AUTOFLOWLABEL             = 0x3b
-	IPV6_BINDANY                   = 0x40
-	IPV6_BINDV6ONLY                = 0x1b
-	IPV6_CHECKSUM                  = 0x1a
-	IPV6_DEFAULT_MULTICAST_HOPS    = 0x1
-	IPV6_DEFAULT_MULTICAST_LOOP    = 0x1
-	IPV6_DEFHLIM                   = 0x40
-	IPV6_DONTFRAG                  = 0x3e
-	IPV6_DSTOPTS                   = 0x32
-	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                  = 0x2f
-	IPV6_HOPOPTS                   = 0x31
-	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_MSFILTER                  = 0x4a
-	IPV6_MULTICAST_HOPS            = 0xa
-	IPV6_MULTICAST_IF              = 0x9
-	IPV6_MULTICAST_LOOP            = 0xb
-	IPV6_NEXTHOP                   = 0x30
-	IPV6_PATHMTU                   = 0x2c
-	IPV6_PKTINFO                   = 0x2e
-	IPV6_PORTRANGE                 = 0xe
-	IPV6_PORTRANGE_DEFAULT         = 0
-	IPV6_PORTRANGE_HIGH            = 0x1
-	IPV6_PORTRANGE_LOW             = 0x2
-	IPV6_PREFER_TEMPADDR           = 0x3f
-	IPV6_RECVDSTOPTS               = 0x28
-	IPV6_RECVHOPLIMIT              = 0x25
-	IPV6_RECVHOPOPTS               = 0x27
-	IPV6_RECVPATHMTU               = 0x2b
-	IPV6_RECVPKTINFO               = 0x24
-	IPV6_RECVRTHDR                 = 0x26
-	IPV6_RECVTCLASS                = 0x39
-	IPV6_RTHDR                     = 0x33
-	IPV6_RTHDRDSTOPTS              = 0x23
-	IPV6_RTHDR_LOOSE               = 0
-	IPV6_RTHDR_STRICT              = 0x1
-	IPV6_RTHDR_TYPE_0              = 0
-	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_ADD_SOURCE_MEMBERSHIP       = 0x46
-	IP_BINDANY                     = 0x18
-	IP_BLOCK_SOURCE                = 0x48
-	IP_DEFAULT_MULTICAST_LOOP      = 0x1
-	IP_DEFAULT_MULTICAST_TTL       = 0x1
-	IP_DF                          = 0x4000
-	IP_DONTFRAG                    = 0x43
-	IP_DROP_MEMBERSHIP             = 0xd
-	IP_DROP_SOURCE_MEMBERSHIP      = 0x47
-	IP_DUMMYNET3                   = 0x31
-	IP_DUMMYNET_CONFIGURE          = 0x3c
-	IP_DUMMYNET_DEL                = 0x3d
-	IP_DUMMYNET_FLUSH              = 0x3e
-	IP_DUMMYNET_GET                = 0x40
-	IP_FAITH                       = 0x16
-	IP_FW3                         = 0x30
-	IP_FW_ADD                      = 0x32
-	IP_FW_DEL                      = 0x33
-	IP_FW_FLUSH                    = 0x34
-	IP_FW_GET                      = 0x36
-	IP_FW_NAT_CFG                  = 0x38
-	IP_FW_NAT_DEL                  = 0x39
-	IP_FW_NAT_GET_CONFIG           = 0x3a
-	IP_FW_NAT_GET_LOG              = 0x3b
-	IP_FW_RESETLOG                 = 0x37
-	IP_FW_TABLE_ADD                = 0x28
-	IP_FW_TABLE_DEL                = 0x29
-	IP_FW_TABLE_FLUSH              = 0x2a
-	IP_FW_TABLE_GETSIZE            = 0x2b
-	IP_FW_TABLE_LIST               = 0x2c
-	IP_FW_ZERO                     = 0x35
-	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_MAX_SOURCE_FILTER           = 0x400
-	IP_MF                          = 0x2000
-	IP_MINTTL                      = 0x42
-	IP_MIN_MEMBERSHIPS             = 0x1f
-	IP_MSFILTER                    = 0x4a
-	IP_MSS                         = 0x240
-	IP_MULTICAST_IF                = 0x9
-	IP_MULTICAST_LOOP              = 0xb
-	IP_MULTICAST_TTL               = 0xa
-	IP_MULTICAST_VIF               = 0xe
-	IP_OFFMASK                     = 0x1fff
-	IP_ONESBCAST                   = 0x17
-	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                     = 0x41
-	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_SENDSRCADDR                 = 0x7
-	IP_TOS                         = 0x3
-	IP_TTL                         = 0x4
-	IP_UNBLOCK_SOURCE              = 0x49
-	MSG_COMPAT                     = 0x8000
-	MSG_CTRUNC                     = 0x20
-	MSG_DONTROUTE                  = 0x4
-	MSG_DONTWAIT                   = 0x80
-	MSG_EOF                        = 0x100
-	MSG_EOR                        = 0x8
-	MSG_NBIO                       = 0x4000
-	MSG_NOSIGNAL                   = 0x20000
-	MSG_NOTIFICATION               = 0x2000
-	MSG_OOB                        = 0x1
-	MSG_PEEK                       = 0x2
-	MSG_TRUNC                      = 0x10
-	MSG_WAITALL                    = 0x40
-	NET_RT_DUMP                    = 0x1
-	NET_RT_FLAGS                   = 0x2
-	NET_RT_IFLIST                  = 0x3
-	NET_RT_IFMALIST                = 0x4
-	NET_RT_MAXID                   = 0x5
-	O_ACCMODE                      = 0x3
-	O_APPEND                       = 0x8
-	O_ASYNC                        = 0x40
-	O_CREAT                        = 0x200
-	O_DIRECT                       = 0x10000
-	O_DIRECTORY                    = 0x20000
-	O_EXCL                         = 0x800
-	O_EXEC                         = 0x40000
-	O_EXLOCK                       = 0x20
-	O_FSYNC                        = 0x80
-	O_NDELAY                       = 0x4
-	O_NOCTTY                       = 0x8000
-	O_NOFOLLOW                     = 0x100
-	O_NONBLOCK                     = 0x4
-	O_RDONLY                       = 0
-	O_RDWR                         = 0x2
-	O_SHLOCK                       = 0x10
-	O_SYNC                         = 0x80
-	O_TRUNC                        = 0x400
-	O_TTY_INIT                     = 0x80000
-	O_WRONLY                       = 0x1
-	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_DONE                       = 0x40
-	RTF_DYNAMIC                    = 0x10
-	RTF_FMASK                      = 0x1004d808
-	RTF_GATEWAY                    = 0x2
-	RTF_HOST                       = 0x4
-	RTF_LLDATA                     = 0x400
-	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_RNH_LOCKED                 = 0x40000000
-	RTF_STATIC                     = 0x800
-	RTF_STICKY                     = 0x10000000
-	RTF_UP                         = 0x1
-	RTF_XRESOLVE                   = 0x200
-	RTM_ADD                        = 0x1
-	RTM_CHANGE                     = 0x3
-	RTM_DELADDR                    = 0xd
-	RTM_DELETE                     = 0x2
-	RTM_DELMADDR                   = 0x10
-	RTM_GET                        = 0x4
-	RTM_IEEE80211                  = 0x12
-	RTM_IFANNOUNCE                 = 0x11
-	RTM_IFINFO                     = 0xe
-	RTM_LOCK                       = 0x8
-	RTM_LOSING                     = 0x5
-	RTM_MISS                       = 0x7
-	RTM_NEWADDR                    = 0xc
-	RTM_NEWMADDR                   = 0xf
-	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
-	RTV_WEIGHT                     = 0x100
-	SCM_BINTIME                    = 0x4
-	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
-	SIGLWP                         = 0x20
-	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
-	SIOCADDRT                      = 0x8040720a
-	SIOCAIFADDR                    = 0x8040691a
-	SIOCAIFGROUP                   = 0x80286987
-	SIOCALIFADDR                   = 0x8118691b
-	SIOCATMARK                     = 0x40047307
-	SIOCDELMULTI                   = 0x80206932
-	SIOCDELRT                      = 0x8040720b
-	SIOCDIFADDR                    = 0x80206919
-	SIOCDIFGROUP                   = 0x80286989
-	SIOCDIFPHYADDR                 = 0x80206949
-	SIOCDLIFADDR                   = 0x8118691d
-	SIOCGDRVSPEC                   = 0xc028697b
-	SIOCGETSGCNT                   = 0xc0207210
-	SIOCGETVIFCNT                  = 0xc028720f
-	SIOCGHIWAT                     = 0x40047301
-	SIOCGIFADDR                    = 0xc0206921
-	SIOCGIFBRDADDR                 = 0xc0206923
-	SIOCGIFCAP                     = 0xc020691f
-	SIOCGIFCONF                    = 0xc0106924
-	SIOCGIFDESCR                   = 0xc020692a
-	SIOCGIFDSTADDR                 = 0xc0206922
-	SIOCGIFFLAGS                   = 0xc0206911
-	SIOCGIFGENERIC                 = 0xc020693a
-	SIOCGIFGMEMB                   = 0xc028698a
-	SIOCGIFGROUP                   = 0xc0286988
-	SIOCGIFINDEX                   = 0xc0206920
-	SIOCGIFMAC                     = 0xc0206926
-	SIOCGIFMEDIA                   = 0xc0306938
-	SIOCGIFMETRIC                  = 0xc0206917
-	SIOCGIFMTU                     = 0xc0206933
-	SIOCGIFNETMASK                 = 0xc0206925
-	SIOCGIFPDSTADDR                = 0xc0206948
-	SIOCGIFPHYS                    = 0xc0206935
-	SIOCGIFPSRCADDR                = 0xc0206947
-	SIOCGIFSTATUS                  = 0xc331693b
-	SIOCGLIFADDR                   = 0xc118691c
-	SIOCGLIFPHYADDR                = 0xc118694b
-	SIOCGLOWAT                     = 0x40047303
-	SIOCGPGRP                      = 0x40047309
-	SIOCGPRIVATE_0                 = 0xc0206950
-	SIOCGPRIVATE_1                 = 0xc0206951
-	SIOCIFCREATE                   = 0xc020697a
-	SIOCIFCREATE2                  = 0xc020697c
-	SIOCIFDESTROY                  = 0x80206979
-	SIOCIFGCLONERS                 = 0xc0106978
-	SIOCSDRVSPEC                   = 0x8028697b
-	SIOCSHIWAT                     = 0x80047300
-	SIOCSIFADDR                    = 0x8020690c
-	SIOCSIFBRDADDR                 = 0x80206913
-	SIOCSIFCAP                     = 0x8020691e
-	SIOCSIFDESCR                   = 0x80206929
-	SIOCSIFDSTADDR                 = 0x8020690e
-	SIOCSIFFLAGS                   = 0x80206910
-	SIOCSIFGENERIC                 = 0x80206939
-	SIOCSIFLLADDR                  = 0x8020693c
-	SIOCSIFMAC                     = 0x80206927
-	SIOCSIFMEDIA                   = 0xc0206937
-	SIOCSIFMETRIC                  = 0x80206918
-	SIOCSIFMTU                     = 0x80206934
-	SIOCSIFNAME                    = 0x80206928
-	SIOCSIFNETMASK                 = 0x80206916
-	SIOCSIFPHYADDR                 = 0x80406946
-	SIOCSIFPHYS                    = 0x80206936
-	SIOCSIFRVNET                   = 0xc020695b
-	SIOCSIFVNET                    = 0xc020695a
-	SIOCSLIFPHYADDR                = 0x8118694a
-	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_ACCEPTFILTER                = 0x1000
-	SO_BINTIME                     = 0x2000
-	SO_BROADCAST                   = 0x20
-	SO_DEBUG                       = 0x1
-	SO_DONTROUTE                   = 0x10
-	SO_ERROR                       = 0x1007
-	SO_KEEPALIVE                   = 0x8
-	SO_LABEL                       = 0x1009
-	SO_LINGER                      = 0x80
-	SO_LISTENINCQLEN               = 0x1013
-	SO_LISTENQLEN                  = 0x1012
-	SO_LISTENQLIMIT                = 0x1011
-	SO_NOSIGPIPE                   = 0x800
-	SO_NO_DDP                      = 0x8000
-	SO_NO_OFFLOAD                  = 0x4000
-	SO_OOBINLINE                   = 0x100
-	SO_PEERLABEL                   = 0x1010
-	SO_RCVBUF                      = 0x1002
-	SO_RCVLOWAT                    = 0x1004
-	SO_RCVTIMEO                    = 0x1006
-	SO_REUSEADDR                   = 0x4
-	SO_REUSEPORT                   = 0x200
-	SO_SETFIB                      = 0x1014
-	SO_SNDBUF                      = 0x1001
-	SO_SNDLOWAT                    = 0x1003
-	SO_SNDTIMEO                    = 0x1005
-	SO_TIMESTAMP                   = 0x400
-	SO_TYPE                        = 0x1008
-	SO_USELOOPBACK                 = 0x40
-	TCP_CA_NAME_MAX                = 0x10
-	TCP_CONGESTION                 = 0x40
-	TCP_INFO                       = 0x20
-	TCP_MAXBURST                   = 0x4
-	TCP_MAXHLEN                    = 0x3c
-	TCP_MAXOLEN                    = 0x28
-	TCP_MAXSEG                     = 0x2
-	TCP_MAXWIN                     = 0xffff
-	TCP_MAX_SACK                   = 0x4
-	TCP_MAX_WINSHIFT               = 0xe
-	TCP_MD5SIG                     = 0x10
-	TCP_MINMSS                     = 0xd8
-	TCP_MSS                        = 0x200
-	TCP_NODELAY                    = 0x1
-	TCP_NOOPT                      = 0x8
-	TCP_NOPUSH                     = 0x4
-	WCONTINUED                     = 0x4
-	WCOREFLAG                      = 0x80
-	WLINUXCLONE                    = 0x80000000
-	WNOHANG                        = 0x1
-	WNOWAIT                        = 0x8
-	WSTOPPED                       = 0x2
-	WUNTRACED                      = 0x2
+	AF_APPLETALK                      = 0x10
+	AF_ARP                            = 0x23
+	AF_ATM                            = 0x1e
+	AF_BLUETOOTH                      = 0x24
+	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_HYLINK                         = 0xf
+	AF_IEEE80211                      = 0x25
+	AF_IMPLINK                        = 0x3
+	AF_INET                           = 0x2
+	AF_INET6                          = 0x1c
+	AF_IPX                            = 0x17
+	AF_ISDN                           = 0x1a
+	AF_ISO                            = 0x7
+	AF_LAT                            = 0xe
+	AF_LINK                           = 0x12
+	AF_LOCAL                          = 0x1
+	AF_MAX                            = 0x26
+	AF_NATM                           = 0x1d
+	AF_NETBIOS                        = 0x6
+	AF_NETGRAPH                       = 0x20
+	AF_OSI                            = 0x7
+	AF_PUP                            = 0x4
+	AF_ROUTE                          = 0x11
+	AF_SCLUSTER                       = 0x22
+	AF_SIP                            = 0x18
+	AF_SLOW                           = 0x21
+	AF_SNA                            = 0xb
+	AF_UNIX                           = 0x1
+	AF_UNSPEC                         = 0
+	AF_VENDOR00                       = 0x27
+	AF_VENDOR01                       = 0x29
+	AF_VENDOR02                       = 0x2b
+	AF_VENDOR03                       = 0x2d
+	AF_VENDOR04                       = 0x2f
+	AF_VENDOR05                       = 0x31
+	AF_VENDOR06                       = 0x33
+	AF_VENDOR07                       = 0x35
+	AF_VENDOR08                       = 0x37
+	AF_VENDOR09                       = 0x39
+	AF_VENDOR10                       = 0x3b
+	AF_VENDOR11                       = 0x3d
+	AF_VENDOR12                       = 0x3f
+	AF_VENDOR13                       = 0x41
+	AF_VENDOR14                       = 0x43
+	AF_VENDOR15                       = 0x45
+	AF_VENDOR16                       = 0x47
+	AF_VENDOR17                       = 0x49
+	AF_VENDOR18                       = 0x4b
+	AF_VENDOR19                       = 0x4d
+	AF_VENDOR20                       = 0x4f
+	AF_VENDOR21                       = 0x51
+	AF_VENDOR22                       = 0x53
+	AF_VENDOR23                       = 0x55
+	AF_VENDOR24                       = 0x57
+	AF_VENDOR25                       = 0x59
+	AF_VENDOR26                       = 0x5b
+	AF_VENDOR27                       = 0x5d
+	AF_VENDOR28                       = 0x5f
+	AF_VENDOR29                       = 0x61
+	AF_VENDOR30                       = 0x63
+	AF_VENDOR31                       = 0x65
+	AF_VENDOR32                       = 0x67
+	AF_VENDOR33                       = 0x69
+	AF_VENDOR34                       = 0x6b
+	AF_VENDOR35                       = 0x6d
+	AF_VENDOR36                       = 0x6f
+	AF_VENDOR37                       = 0x71
+	AF_VENDOR38                       = 0x73
+	AF_VENDOR39                       = 0x75
+	AF_VENDOR40                       = 0x77
+	AF_VENDOR41                       = 0x79
+	AF_VENDOR42                       = 0x7b
+	AF_VENDOR43                       = 0x7d
+	AF_VENDOR44                       = 0x7f
+	AF_VENDOR45                       = 0x81
+	AF_VENDOR46                       = 0x83
+	AF_VENDOR47                       = 0x85
+	BIOCFEEDBACK                      = 0x8004427c
+	BIOCFLUSH                         = 0x20004268
+	BIOCGBLEN                         = 0x40044266
+	BIOCGDIRECTION                    = 0x40044276
+	BIOCGDLT                          = 0x4004426a
+	BIOCGDLTLIST                      = 0xc0104279
+	BIOCGETBUFMODE                    = 0x4004427d
+	BIOCGETIF                         = 0x4020426b
+	BIOCGETZMAX                       = 0x4008427f
+	BIOCGHDRCMPLT                     = 0x40044274
+	BIOCGRSIG                         = 0x40044272
+	BIOCGRTIMEOUT                     = 0x4010426e
+	BIOCGSEESENT                      = 0x40044276
+	BIOCGSTATS                        = 0x4008426f
+	BIOCIMMEDIATE                     = 0x80044270
+	BIOCLOCK                          = 0x2000427a
+	BIOCPROMISC                       = 0x20004269
+	BIOCROTZBUF                       = 0x40184280
+	BIOCSBLEN                         = 0xc0044266
+	BIOCSDIRECTION                    = 0x80044277
+	BIOCSDLT                          = 0x80044278
+	BIOCSETBUFMODE                    = 0x8004427e
+	BIOCSETF                          = 0x80104267
+	BIOCSETFNR                        = 0x80104282
+	BIOCSETIF                         = 0x8020426c
+	BIOCSETWF                         = 0x8010427b
+	BIOCSETZBUF                       = 0x80184281
+	BIOCSHDRCMPLT                     = 0x80044275
+	BIOCSRSIG                         = 0x80044273
+	BIOCSRTIMEOUT                     = 0x8010426d
+	BIOCSSEESENT                      = 0x80044277
+	BIOCVERSION                       = 0x40044271
+	BPF_A                             = 0x10
+	BPF_ABS                           = 0x20
+	BPF_ADD                           = 0
+	BPF_ALIGNMENT                     = 0x8
+	BPF_ALU                           = 0x4
+	BPF_AND                           = 0x50
+	BPF_B                             = 0x10
+	BPF_BUFMODE_BUFFER                = 0x1
+	BPF_BUFMODE_ZBUF                  = 0x2
+	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                       = 0x18
+	CTL_NET                           = 0x4
+	DLT_A429                          = 0xb8
+	DLT_A653_ICM                      = 0xb9
+	DLT_AIRONET_HEADER                = 0x78
+	DLT_APPLE_IP_OVER_IEEE1394        = 0x8a
+	DLT_ARCNET                        = 0x7
+	DLT_ARCNET_LINUX                  = 0x81
+	DLT_ATM_CLIP                      = 0x13
+	DLT_ATM_RFC1483                   = 0xb
+	DLT_AURORA                        = 0x7e
+	DLT_AX25                          = 0x3
+	DLT_AX25_KISS                     = 0xca
+	DLT_BACNET_MS_TP                  = 0xa5
+	DLT_BLUETOOTH_HCI_H4              = 0xbb
+	DLT_BLUETOOTH_HCI_H4_WITH_PHDR    = 0xc9
+	DLT_CAN20B                        = 0xbe
+	DLT_CHAOS                         = 0x5
+	DLT_CHDLC                         = 0x68
+	DLT_CISCO_IOS                     = 0x76
+	DLT_C_HDLC                        = 0x68
+	DLT_C_HDLC_WITH_DIR               = 0xcd
+	DLT_DOCSIS                        = 0x8f
+	DLT_ECONET                        = 0x73
+	DLT_EN10MB                        = 0x1
+	DLT_EN3MB                         = 0x2
+	DLT_ENC                           = 0x6d
+	DLT_ERF                           = 0xc5
+	DLT_ERF_ETH                       = 0xaf
+	DLT_ERF_POS                       = 0xb0
+	DLT_FDDI                          = 0xa
+	DLT_FLEXRAY                       = 0xd2
+	DLT_FRELAY                        = 0x6b
+	DLT_FRELAY_WITH_DIR               = 0xce
+	DLT_GCOM_SERIAL                   = 0xad
+	DLT_GCOM_T1E1                     = 0xac
+	DLT_GPF_F                         = 0xab
+	DLT_GPF_T                         = 0xaa
+	DLT_GPRS_LLC                      = 0xa9
+	DLT_HHDLC                         = 0x79
+	DLT_IBM_SN                        = 0x92
+	DLT_IBM_SP                        = 0x91
+	DLT_IEEE802                       = 0x6
+	DLT_IEEE802_11                    = 0x69
+	DLT_IEEE802_11_RADIO              = 0x7f
+	DLT_IEEE802_11_RADIO_AVS          = 0xa3
+	DLT_IEEE802_15_4                  = 0xc3
+	DLT_IEEE802_15_4_LINUX            = 0xbf
+	DLT_IEEE802_15_4_NONASK_PHY       = 0xd7
+	DLT_IEEE802_16_MAC_CPS            = 0xbc
+	DLT_IEEE802_16_MAC_CPS_RADIO      = 0xc1
+	DLT_IPFILTER                      = 0x74
+	DLT_IPMB                          = 0xc7
+	DLT_IPMB_LINUX                    = 0xd1
+	DLT_IP_OVER_FC                    = 0x7a
+	DLT_JUNIPER_ATM1                  = 0x89
+	DLT_JUNIPER_ATM2                  = 0x87
+	DLT_JUNIPER_CHDLC                 = 0xb5
+	DLT_JUNIPER_ES                    = 0x84
+	DLT_JUNIPER_ETHER                 = 0xb2
+	DLT_JUNIPER_FRELAY                = 0xb4
+	DLT_JUNIPER_GGSN                  = 0x85
+	DLT_JUNIPER_ISM                   = 0xc2
+	DLT_JUNIPER_MFR                   = 0x86
+	DLT_JUNIPER_MLFR                  = 0x83
+	DLT_JUNIPER_MLPPP                 = 0x82
+	DLT_JUNIPER_MONITOR               = 0xa4
+	DLT_JUNIPER_PIC_PEER              = 0xae
+	DLT_JUNIPER_PPP                   = 0xb3
+	DLT_JUNIPER_PPPOE                 = 0xa7
+	DLT_JUNIPER_PPPOE_ATM             = 0xa8
+	DLT_JUNIPER_SERVICES              = 0x88
+	DLT_JUNIPER_ST                    = 0xc8
+	DLT_JUNIPER_VP                    = 0xb7
+	DLT_LAPB_WITH_DIR                 = 0xcf
+	DLT_LAPD                          = 0xcb
+	DLT_LIN                           = 0xd4
+	DLT_LINUX_IRDA                    = 0x90
+	DLT_LINUX_LAPD                    = 0xb1
+	DLT_LINUX_PPP_WITHDIRECTION       = 0xa6
+	DLT_LINUX_SLL                     = 0x71
+	DLT_LOOP                          = 0x6c
+	DLT_LTALK                         = 0x72
+	DLT_MFR                           = 0xb6
+	DLT_MOST                          = 0xd3
+	DLT_MTP2                          = 0x8c
+	DLT_MTP2_WITH_PHDR                = 0x8b
+	DLT_MTP3                          = 0x8d
+	DLT_NULL                          = 0
+	DLT_PCI_EXP                       = 0x7d
+	DLT_PFLOG                         = 0x75
+	DLT_PFSYNC                        = 0x79
+	DLT_PPI                           = 0xc0
+	DLT_PPP                           = 0x9
+	DLT_PPP_BSDOS                     = 0x10
+	DLT_PPP_ETHER                     = 0x33
+	DLT_PPP_PPPD                      = 0xa6
+	DLT_PPP_SERIAL                    = 0x32
+	DLT_PPP_WITH_DIR                  = 0xcc
+	DLT_PPP_WITH_DIRECTION            = 0xa6
+	DLT_PRISM_HEADER                  = 0x77
+	DLT_PRONET                        = 0x4
+	DLT_RAIF1                         = 0xc6
+	DLT_RAW                           = 0xc
+	DLT_RIO                           = 0x7c
+	DLT_SCCP                          = 0x8e
+	DLT_SITA                          = 0xc4
+	DLT_SLIP                          = 0x8
+	DLT_SLIP_BSDOS                    = 0xf
+	DLT_SUNATM                        = 0x7b
+	DLT_SYMANTEC_FIREWALL             = 0x63
+	DLT_TZSP                          = 0x80
+	DLT_USB                           = 0xba
+	DLT_USB_LINUX                     = 0xbd
+	DLT_USER0                         = 0x93
+	DLT_USER1                         = 0x94
+	DLT_USER10                        = 0x9d
+	DLT_USER11                        = 0x9e
+	DLT_USER12                        = 0x9f
+	DLT_USER13                        = 0xa0
+	DLT_USER14                        = 0xa1
+	DLT_USER15                        = 0xa2
+	DLT_USER2                         = 0x95
+	DLT_USER3                         = 0x96
+	DLT_USER4                         = 0x97
+	DLT_USER5                         = 0x98
+	DLT_USER6                         = 0x99
+	DLT_USER7                         = 0x9a
+	DLT_USER8                         = 0x9b
+	DLT_USER9                         = 0x9c
+	DLT_X2E_SERIAL                    = 0xd5
+	DLT_X2E_XORAYA                    = 0xd6
+	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
+	EBADF                             = 0x9
+	EBADMSG                           = 0x59
+	EBADRPC                           = 0x48
+	EBUSY                             = 0x10
+	ECANCELED                         = 0x55
+	ECHILD                            = 0xa
+	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
+	EVFILT_PROC                       = -0x5
+	EVFILT_READ                       = -0x1
+	EVFILT_SIGNAL                     = -0x6
+	EVFILT_SYSCOUNT                   = 0xb
+	EVFILT_TIMER                      = -0x7
+	EVFILT_USER                       = -0xb
+	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_FLAG1                          = 0x2000
+	EV_ONESHOT                        = 0x10
+	EV_RECEIPT                        = 0x40
+	EV_SYSFLAGS                       = 0xf000
+	EWOULDBLOCK                       = 0x23
+	EXDEV                             = 0x12
+	FD_CLOEXEC                        = 0x1
+	FD_SETSIZE                        = 0x400
+	F_CANCEL                          = 0x5
+	F_DUP2FD                          = 0xa
+	F_DUPFD                           = 0
+	F_GETFD                           = 0x1
+	F_GETFL                           = 0x3
+	F_GETLK                           = 0xb
+	F_GETOWN                          = 0x5
+	F_OGETLK                          = 0x7
+	F_OSETLK                          = 0x8
+	F_OSETLKW                         = 0x9
+	F_RDAHEAD                         = 0x10
+	F_RDLCK                           = 0x1
+	F_READAHEAD                       = 0xf
+	F_SETFD                           = 0x2
+	F_SETFL                           = 0x4
+	F_SETLK                           = 0xc
+	F_SETLKW                          = 0xd
+	F_SETLK_REMOTE                    = 0xe
+	F_SETOWN                          = 0x6
+	F_UNLCK                           = 0x2
+	F_UNLCKSYS                        = 0x4
+	F_WRLCK                           = 0x3
+	IFF_ALLMULTI                      = 0x200
+	IFF_ALTPHYS                       = 0x4000
+	IFF_BROADCAST                     = 0x2
+	IFF_CANTCHANGE                    = 0x208f72
+	IFF_DEBUG                         = 0x4
+	IFF_DRV_OACTIVE                   = 0x400
+	IFF_DRV_RUNNING                   = 0x40
+	IFF_DYING                         = 0x200000
+	IFF_LINK0                         = 0x1000
+	IFF_LINK1                         = 0x2000
+	IFF_LINK2                         = 0x4000
+	IFF_LOOPBACK                      = 0x8
+	IFF_MONITOR                       = 0x40000
+	IFF_MULTICAST                     = 0x8000
+	IFF_NOARP                         = 0x80
+	IFF_OACTIVE                       = 0x400
+	IFF_POINTOPOINT                   = 0x10
+	IFF_PPROMISC                      = 0x20000
+	IFF_PROMISC                       = 0x100
+	IFF_RENAMING                      = 0x400000
+	IFF_RUNNING                       = 0x40
+	IFF_SIMPLEX                       = 0x800
+	IFF_SMART                         = 0x20
+	IFF_STATICARP                     = 0x80000
+	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_BRIDGE                        = 0xd1
+	IFT_BSC                           = 0x53
+	IFT_CARP                          = 0xf8
+	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_DS0                           = 0x51
+	IFT_DS0BUNDLE                     = 0x52
+	IFT_DS1FDL                        = 0xaa
+	IFT_DS3                           = 0x1e
+	IFT_DTM                           = 0x8c
+	IFT_DVBASILN                      = 0xac
+	IFT_DVBASIOUT                     = 0xad
+	IFT_DVBRCCDOWNSTREAM              = 0x93
+	IFT_DVBRCCMACLAYER                = 0x92
+	IFT_DVBRCCUPSTREAM                = 0x94
+	IFT_ENC                           = 0xf4
+	IFT_EON                           = 0x19
+	IFT_EPLRS                         = 0x57
+	IFT_ESCON                         = 0x49
+	IFT_ETHER                         = 0x6
+	IFT_FAITH                         = 0xf2
+	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_INTERLEAVE                    = 0x7c
+	IFT_IP                            = 0x7e
+	IFT_IPFORWARD                     = 0x8e
+	IFT_IPOVERATM                     = 0x72
+	IFT_IPOVERCDLC                    = 0x6d
+	IFT_IPOVERCLAW                    = 0x6e
+	IFT_IPSWITCH                      = 0x4e
+	IFT_IPXIP                         = 0xf9
+	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_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                         = 0xf6
+	IFT_PFSYNC                        = 0xf7
+	IFT_PLC                           = 0xae
+	IFT_POS                           = 0xab
+	IFT_PPP                           = 0x17
+	IFT_PPPMULTILINKBUNDLE            = 0x6c
+	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                           = 0xf1
+	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_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_STF                           = 0xd7
+	IFT_T1                            = 0x12
+	IFT_TDLC                          = 0x74
+	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_VOICEEM                       = 0x64
+	IFT_VOICEENCAP                    = 0x67
+	IFT_VOICEFXO                      = 0x65
+	IFT_VOICEFXS                      = 0x66
+	IFT_VOICEOVERATM                  = 0x98
+	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
+	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_CARP                      = 0x70
+	IPPROTO_CFTP                      = 0x3e
+	IPPROTO_CHAOS                     = 0x10
+	IPPROTO_CMTP                      = 0x26
+	IPPROTO_CPHB                      = 0x49
+	IPPROTO_CPNX                      = 0x48
+	IPPROTO_DDP                       = 0x25
+	IPPROTO_DGP                       = 0x56
+	IPPROTO_DIVERT                    = 0x102
+	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_MOBILE                    = 0x37
+	IPPROTO_MTP                       = 0x5c
+	IPPROTO_MUX                       = 0x12
+	IPPROTO_ND                        = 0x4d
+	IPPROTO_NHRP                      = 0x36
+	IPPROTO_NONE                      = 0x3b
+	IPPROTO_NSP                       = 0x1f
+	IPPROTO_NVPII                     = 0xb
+	IPPROTO_OLD_DIVERT                = 0xfe
+	IPPROTO_OSPFIGP                   = 0x59
+	IPPROTO_PFSYNC                    = 0xf0
+	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_SKIP                      = 0x39
+	IPPROTO_SPACER                    = 0x7fff
+	IPPROTO_SRPC                      = 0x5a
+	IPPROTO_ST                        = 0x7
+	IPPROTO_SVMTP                     = 0x52
+	IPPROTO_SWIPE                     = 0x35
+	IPPROTO_TCF                       = 0x57
+	IPPROTO_TCP                       = 0x6
+	IPPROTO_TLSP                      = 0x38
+	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_AUTOFLOWLABEL                = 0x3b
+	IPV6_BINDANY                      = 0x40
+	IPV6_BINDV6ONLY                   = 0x1b
+	IPV6_CHECKSUM                     = 0x1a
+	IPV6_DEFAULT_MULTICAST_HOPS       = 0x1
+	IPV6_DEFAULT_MULTICAST_LOOP       = 0x1
+	IPV6_DEFHLIM                      = 0x40
+	IPV6_DONTFRAG                     = 0x3e
+	IPV6_DSTOPTS                      = 0x32
+	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                     = 0x2f
+	IPV6_HOPOPTS                      = 0x31
+	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_MSFILTER                     = 0x4a
+	IPV6_MULTICAST_HOPS               = 0xa
+	IPV6_MULTICAST_IF                 = 0x9
+	IPV6_MULTICAST_LOOP               = 0xb
+	IPV6_NEXTHOP                      = 0x30
+	IPV6_PATHMTU                      = 0x2c
+	IPV6_PKTINFO                      = 0x2e
+	IPV6_PORTRANGE                    = 0xe
+	IPV6_PORTRANGE_DEFAULT            = 0
+	IPV6_PORTRANGE_HIGH               = 0x1
+	IPV6_PORTRANGE_LOW                = 0x2
+	IPV6_PREFER_TEMPADDR              = 0x3f
+	IPV6_RECVDSTOPTS                  = 0x28
+	IPV6_RECVHOPLIMIT                 = 0x25
+	IPV6_RECVHOPOPTS                  = 0x27
+	IPV6_RECVPATHMTU                  = 0x2b
+	IPV6_RECVPKTINFO                  = 0x24
+	IPV6_RECVRTHDR                    = 0x26
+	IPV6_RECVTCLASS                   = 0x39
+	IPV6_RTHDR                        = 0x33
+	IPV6_RTHDRDSTOPTS                 = 0x23
+	IPV6_RTHDR_LOOSE                  = 0
+	IPV6_RTHDR_STRICT                 = 0x1
+	IPV6_RTHDR_TYPE_0                 = 0
+	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_ADD_SOURCE_MEMBERSHIP          = 0x46
+	IP_BINDANY                        = 0x18
+	IP_BLOCK_SOURCE                   = 0x48
+	IP_DEFAULT_MULTICAST_LOOP         = 0x1
+	IP_DEFAULT_MULTICAST_TTL          = 0x1
+	IP_DF                             = 0x4000
+	IP_DONTFRAG                       = 0x43
+	IP_DROP_MEMBERSHIP                = 0xd
+	IP_DROP_SOURCE_MEMBERSHIP         = 0x47
+	IP_DUMMYNET3                      = 0x31
+	IP_DUMMYNET_CONFIGURE             = 0x3c
+	IP_DUMMYNET_DEL                   = 0x3d
+	IP_DUMMYNET_FLUSH                 = 0x3e
+	IP_DUMMYNET_GET                   = 0x40
+	IP_FAITH                          = 0x16
+	IP_FW3                            = 0x30
+	IP_FW_ADD                         = 0x32
+	IP_FW_DEL                         = 0x33
+	IP_FW_FLUSH                       = 0x34
+	IP_FW_GET                         = 0x36
+	IP_FW_NAT_CFG                     = 0x38
+	IP_FW_NAT_DEL                     = 0x39
+	IP_FW_NAT_GET_CONFIG              = 0x3a
+	IP_FW_NAT_GET_LOG                 = 0x3b
+	IP_FW_RESETLOG                    = 0x37
+	IP_FW_TABLE_ADD                   = 0x28
+	IP_FW_TABLE_DEL                   = 0x29
+	IP_FW_TABLE_FLUSH                 = 0x2a
+	IP_FW_TABLE_GETSIZE               = 0x2b
+	IP_FW_TABLE_LIST                  = 0x2c
+	IP_FW_ZERO                        = 0x35
+	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_MAX_SOURCE_FILTER              = 0x400
+	IP_MF                             = 0x2000
+	IP_MINTTL                         = 0x42
+	IP_MIN_MEMBERSHIPS                = 0x1f
+	IP_MSFILTER                       = 0x4a
+	IP_MSS                            = 0x240
+	IP_MULTICAST_IF                   = 0x9
+	IP_MULTICAST_LOOP                 = 0xb
+	IP_MULTICAST_TTL                  = 0xa
+	IP_MULTICAST_VIF                  = 0xe
+	IP_OFFMASK                        = 0x1fff
+	IP_ONESBCAST                      = 0x17
+	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                        = 0x41
+	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_SENDSRCADDR                    = 0x7
+	IP_TOS                            = 0x3
+	IP_TTL                            = 0x4
+	IP_UNBLOCK_SOURCE                 = 0x49
+	MSG_COMPAT                        = 0x8000
+	MSG_CTRUNC                        = 0x20
+	MSG_DONTROUTE                     = 0x4
+	MSG_DONTWAIT                      = 0x80
+	MSG_EOF                           = 0x100
+	MSG_EOR                           = 0x8
+	MSG_NBIO                          = 0x4000
+	MSG_NOSIGNAL                      = 0x20000
+	MSG_NOTIFICATION                  = 0x2000
+	MSG_OOB                           = 0x1
+	MSG_PEEK                          = 0x2
+	MSG_TRUNC                         = 0x10
+	MSG_WAITALL                       = 0x40
+	NET_RT_DUMP                       = 0x1
+	NET_RT_FLAGS                      = 0x2
+	NET_RT_IFLIST                     = 0x3
+	NET_RT_IFMALIST                   = 0x4
+	NET_RT_MAXID                      = 0x5
+	O_ACCMODE                         = 0x3
+	O_APPEND                          = 0x8
+	O_ASYNC                           = 0x40
+	O_CREAT                           = 0x200
+	O_DIRECT                          = 0x10000
+	O_DIRECTORY                       = 0x20000
+	O_EXCL                            = 0x800
+	O_EXEC                            = 0x40000
+	O_EXLOCK                          = 0x20
+	O_FSYNC                           = 0x80
+	O_NDELAY                          = 0x4
+	O_NOCTTY                          = 0x8000
+	O_NOFOLLOW                        = 0x100
+	O_NONBLOCK                        = 0x4
+	O_RDONLY                          = 0
+	O_RDWR                            = 0x2
+	O_SHLOCK                          = 0x10
+	O_SYNC                            = 0x80
+	O_TRUNC                           = 0x400
+	O_TTY_INIT                        = 0x80000
+	O_WRONLY                          = 0x1
+	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_DONE                          = 0x40
+	RTF_DYNAMIC                       = 0x10
+	RTF_FMASK                         = 0x1004d808
+	RTF_GATEWAY                       = 0x2
+	RTF_HOST                          = 0x4
+	RTF_LLDATA                        = 0x400
+	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_RNH_LOCKED                    = 0x40000000
+	RTF_STATIC                        = 0x800
+	RTF_STICKY                        = 0x10000000
+	RTF_UP                            = 0x1
+	RTF_XRESOLVE                      = 0x200
+	RTM_ADD                           = 0x1
+	RTM_CHANGE                        = 0x3
+	RTM_DELADDR                       = 0xd
+	RTM_DELETE                        = 0x2
+	RTM_DELMADDR                      = 0x10
+	RTM_GET                           = 0x4
+	RTM_IEEE80211                     = 0x12
+	RTM_IFANNOUNCE                    = 0x11
+	RTM_IFINFO                        = 0xe
+	RTM_LOCK                          = 0x8
+	RTM_LOSING                        = 0x5
+	RTM_MISS                          = 0x7
+	RTM_NEWADDR                       = 0xc
+	RTM_NEWMADDR                      = 0xf
+	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
+	RTV_WEIGHT                        = 0x100
+	SCM_BINTIME                       = 0x4
+	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
+	SIGLWP                            = 0x20
+	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
+	SIOCADDRT                         = 0x8040720a
+	SIOCAIFADDR                       = 0x8040691a
+	SIOCAIFGROUP                      = 0x80286987
+	SIOCALIFADDR                      = 0x8118691b
+	SIOCATMARK                        = 0x40047307
+	SIOCDELMULTI                      = 0x80206932
+	SIOCDELRT                         = 0x8040720b
+	SIOCDIFADDR                       = 0x80206919
+	SIOCDIFGROUP                      = 0x80286989
+	SIOCDIFPHYADDR                    = 0x80206949
+	SIOCDLIFADDR                      = 0x8118691d
+	SIOCGDRVSPEC                      = 0xc028697b
+	SIOCGETSGCNT                      = 0xc0207210
+	SIOCGETVIFCNT                     = 0xc028720f
+	SIOCGHIWAT                        = 0x40047301
+	SIOCGIFADDR                       = 0xc0206921
+	SIOCGIFBRDADDR                    = 0xc0206923
+	SIOCGIFCAP                        = 0xc020691f
+	SIOCGIFCONF                       = 0xc0106924
+	SIOCGIFDESCR                      = 0xc020692a
+	SIOCGIFDSTADDR                    = 0xc0206922
+	SIOCGIFFLAGS                      = 0xc0206911
+	SIOCGIFGENERIC                    = 0xc020693a
+	SIOCGIFGMEMB                      = 0xc028698a
+	SIOCGIFGROUP                      = 0xc0286988
+	SIOCGIFINDEX                      = 0xc0206920
+	SIOCGIFMAC                        = 0xc0206926
+	SIOCGIFMEDIA                      = 0xc0306938
+	SIOCGIFMETRIC                     = 0xc0206917
+	SIOCGIFMTU                        = 0xc0206933
+	SIOCGIFNETMASK                    = 0xc0206925
+	SIOCGIFPDSTADDR                   = 0xc0206948
+	SIOCGIFPHYS                       = 0xc0206935
+	SIOCGIFPSRCADDR                   = 0xc0206947
+	SIOCGIFSTATUS                     = 0xc331693b
+	SIOCGLIFADDR                      = 0xc118691c
+	SIOCGLIFPHYADDR                   = 0xc118694b
+	SIOCGLOWAT                        = 0x40047303
+	SIOCGPGRP                         = 0x40047309
+	SIOCGPRIVATE_0                    = 0xc0206950
+	SIOCGPRIVATE_1                    = 0xc0206951
+	SIOCIFCREATE                      = 0xc020697a
+	SIOCIFCREATE2                     = 0xc020697c
+	SIOCIFDESTROY                     = 0x80206979
+	SIOCIFGCLONERS                    = 0xc0106978
+	SIOCSDRVSPEC                      = 0x8028697b
+	SIOCSHIWAT                        = 0x80047300
+	SIOCSIFADDR                       = 0x8020690c
+	SIOCSIFBRDADDR                    = 0x80206913
+	SIOCSIFCAP                        = 0x8020691e
+	SIOCSIFDESCR                      = 0x80206929
+	SIOCSIFDSTADDR                    = 0x8020690e
+	SIOCSIFFLAGS                      = 0x80206910
+	SIOCSIFGENERIC                    = 0x80206939
+	SIOCSIFLLADDR                     = 0x8020693c
+	SIOCSIFMAC                        = 0x80206927
+	SIOCSIFMEDIA                      = 0xc0206937
+	SIOCSIFMETRIC                     = 0x80206918
+	SIOCSIFMTU                        = 0x80206934
+	SIOCSIFNAME                       = 0x80206928
+	SIOCSIFNETMASK                    = 0x80206916
+	SIOCSIFPHYADDR                    = 0x80406946
+	SIOCSIFPHYS                       = 0x80206936
+	SIOCSIFRVNET                      = 0xc020695b
+	SIOCSIFVNET                       = 0xc020695a
+	SIOCSLIFPHYADDR                   = 0x8118694a
+	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_ACCEPTFILTER                   = 0x1000
+	SO_BINTIME                        = 0x2000
+	SO_BROADCAST                      = 0x20
+	SO_DEBUG                          = 0x1
+	SO_DONTROUTE                      = 0x10
+	SO_ERROR                          = 0x1007
+	SO_KEEPALIVE                      = 0x8
+	SO_LABEL                          = 0x1009
+	SO_LINGER                         = 0x80
+	SO_LISTENINCQLEN                  = 0x1013
+	SO_LISTENQLEN                     = 0x1012
+	SO_LISTENQLIMIT                   = 0x1011
+	SO_NOSIGPIPE                      = 0x800
+	SO_NO_DDP                         = 0x8000
+	SO_NO_OFFLOAD                     = 0x4000
+	SO_OOBINLINE                      = 0x100
+	SO_PEERLABEL                      = 0x1010
+	SO_RCVBUF                         = 0x1002
+	SO_RCVLOWAT                       = 0x1004
+	SO_RCVTIMEO                       = 0x1006
+	SO_REUSEADDR                      = 0x4
+	SO_REUSEPORT                      = 0x200
+	SO_SETFIB                         = 0x1014
+	SO_SNDBUF                         = 0x1001
+	SO_SNDLOWAT                       = 0x1003
+	SO_SNDTIMEO                       = 0x1005
+	SO_TIMESTAMP                      = 0x400
+	SO_TYPE                           = 0x1008
+	SO_USELOOPBACK                    = 0x40
+	TCP_CA_NAME_MAX                   = 0x10
+	TCP_CONGESTION                    = 0x40
+	TCP_INFO                          = 0x20
+	TCP_MAXBURST                      = 0x4
+	TCP_MAXHLEN                       = 0x3c
+	TCP_MAXOLEN                       = 0x28
+	TCP_MAXSEG                        = 0x2
+	TCP_MAXWIN                        = 0xffff
+	TCP_MAX_SACK                      = 0x4
+	TCP_MAX_WINSHIFT                  = 0xe
+	TCP_MD5SIG                        = 0x10
+	TCP_MINMSS                        = 0xd8
+	TCP_MSS                           = 0x200
+	TCP_NODELAY                       = 0x1
+	TCP_NOOPT                         = 0x8
+	TCP_NOPUSH                        = 0x4
+	WCONTINUED                        = 0x4
+	WCOREFLAG                         = 0x80
+	WLINUXCLONE                       = 0x80000000
+	WNOHANG                           = 0x1
+	WNOWAIT                           = 0x8
+	WSTOPPED                          = 0x2
+	WUNTRACED                         = 0x2
 )
 
 // Types
diff --git a/src/pkg/syscall/zerrors_linux_386.go b/src/pkg/syscall/zerrors_linux_386.go
index 3fba3ae..73caed4 100644
--- a/src/pkg/syscall/zerrors_linux_386.go
+++ b/src/pkg/syscall/zerrors_linux_386.go
@@ -48,6 +48,64 @@ const (
 	AF_UNSPEC                        = 0
 	AF_WANPIPE                       = 0x19
 	AF_X25                           = 0x9
+	ARPHRD_ADAPT                     = 0x108
+	ARPHRD_APPLETLK                  = 0x8
+	ARPHRD_ARCNET                    = 0x7
+	ARPHRD_ASH                       = 0x30d
+	ARPHRD_ATM                       = 0x13
+	ARPHRD_AX25                      = 0x3
+	ARPHRD_BIF                       = 0x307
+	ARPHRD_CHAOS                     = 0x5
+	ARPHRD_CISCO                     = 0x201
+	ARPHRD_CSLIP                     = 0x101
+	ARPHRD_CSLIP6                    = 0x103
+	ARPHRD_DDCMP                     = 0x205
+	ARPHRD_DLCI                      = 0xf
+	ARPHRD_ECONET                    = 0x30e
+	ARPHRD_EETHER                    = 0x2
+	ARPHRD_ETHER                     = 0x1
+	ARPHRD_EUI64                     = 0x1b
+	ARPHRD_FCAL                      = 0x311
+	ARPHRD_FCFABRIC                  = 0x313
+	ARPHRD_FCPL                      = 0x312
+	ARPHRD_FCPP                      = 0x310
+	ARPHRD_FDDI                      = 0x306
+	ARPHRD_FRAD                      = 0x302
+	ARPHRD_HDLC                      = 0x201
+	ARPHRD_HIPPI                     = 0x30c
+	ARPHRD_HWX25                     = 0x110
+	ARPHRD_IEEE1394                  = 0x18
+	ARPHRD_IEEE802                   = 0x6
+	ARPHRD_IEEE80211                 = 0x321
+	ARPHRD_IEEE80211_PRISM           = 0x322
+	ARPHRD_IEEE80211_RADIOTAP        = 0x323
+	ARPHRD_IEEE802154                = 0x324
+	ARPHRD_IEEE802154_PHY            = 0x325
+	ARPHRD_IEEE802_TR                = 0x320
+	ARPHRD_INFINIBAND                = 0x20
+	ARPHRD_IPDDP                     = 0x309
+	ARPHRD_IPGRE                     = 0x30a
+	ARPHRD_IRDA                      = 0x30f
+	ARPHRD_LAPB                      = 0x204
+	ARPHRD_LOCALTLK                  = 0x305
+	ARPHRD_LOOPBACK                  = 0x304
+	ARPHRD_METRICOM                  = 0x17
+	ARPHRD_NETROM                    = 0
+	ARPHRD_NONE                      = 0xfffe
+	ARPHRD_PIMREG                    = 0x30b
+	ARPHRD_PPP                       = 0x200
+	ARPHRD_PRONET                    = 0x4
+	ARPHRD_RAWHDLC                   = 0x206
+	ARPHRD_ROSE                      = 0x10e
+	ARPHRD_RSRVD                     = 0x104
+	ARPHRD_SIT                       = 0x308
+	ARPHRD_SKIP                      = 0x303
+	ARPHRD_SLIP                      = 0x100
+	ARPHRD_SLIP6                     = 0x102
+	ARPHRD_TUNNEL                    = 0x300
+	ARPHRD_TUNNEL6                   = 0x301
+	ARPHRD_VOID                      = 0xffff
+	ARPHRD_X25                       = 0x10f
 	DT_BLK                           = 0x6
 	DT_CHR                           = 0x2
 	DT_DIR                           = 0x4
@@ -716,6 +774,25 @@ const (
 	RTM_SETDCB                       = 0x4f
 	RTM_SETLINK                      = 0x13
 	RTM_SETNEIGHTBL                  = 0x43
+	RTNH_ALIGNTO                     = 0x4
+	RTNH_F_DEAD                      = 0x1
+	RTNH_F_ONLINK                    = 0x4
+	RTNH_F_PERVASIVE                 = 0x2
+	RTN_MAX                          = 0xb
+	RTPROT_BIRD                      = 0xc
+	RTPROT_BOOT                      = 0x3
+	RTPROT_DHCP                      = 0x10
+	RTPROT_DNROUTED                  = 0xd
+	RTPROT_GATED                     = 0x8
+	RTPROT_KERNEL                    = 0x2
+	RTPROT_MRT                       = 0xa
+	RTPROT_NTK                       = 0xf
+	RTPROT_RA                        = 0x9
+	RTPROT_REDIRECT                  = 0x1
+	RTPROT_STATIC                    = 0x4
+	RTPROT_UNSPEC                    = 0
+	RTPROT_XORP                      = 0xe
+	RTPROT_ZEBRA                     = 0xb
 	SCM_CREDENTIALS                  = 0x2
 	SCM_RIGHTS                       = 0x1
 	SCM_TIMESTAMP                    = 0x1d
diff --git a/src/pkg/syscall/zerrors_linux_amd64.go b/src/pkg/syscall/zerrors_linux_amd64.go
index 0e57b93..8926074 100644
--- a/src/pkg/syscall/zerrors_linux_amd64.go
+++ b/src/pkg/syscall/zerrors_linux_amd64.go
@@ -48,6 +48,64 @@ const (
 	AF_UNSPEC                        = 0
 	AF_WANPIPE                       = 0x19
 	AF_X25                           = 0x9
+	ARPHRD_ADAPT                     = 0x108
+	ARPHRD_APPLETLK                  = 0x8
+	ARPHRD_ARCNET                    = 0x7
+	ARPHRD_ASH                       = 0x30d
+	ARPHRD_ATM                       = 0x13
+	ARPHRD_AX25                      = 0x3
+	ARPHRD_BIF                       = 0x307
+	ARPHRD_CHAOS                     = 0x5
+	ARPHRD_CISCO                     = 0x201
+	ARPHRD_CSLIP                     = 0x101
+	ARPHRD_CSLIP6                    = 0x103
+	ARPHRD_DDCMP                     = 0x205
+	ARPHRD_DLCI                      = 0xf
+	ARPHRD_ECONET                    = 0x30e
+	ARPHRD_EETHER                    = 0x2
+	ARPHRD_ETHER                     = 0x1
+	ARPHRD_EUI64                     = 0x1b
+	ARPHRD_FCAL                      = 0x311
+	ARPHRD_FCFABRIC                  = 0x313
+	ARPHRD_FCPL                      = 0x312
+	ARPHRD_FCPP                      = 0x310
+	ARPHRD_FDDI                      = 0x306
+	ARPHRD_FRAD                      = 0x302
+	ARPHRD_HDLC                      = 0x201
+	ARPHRD_HIPPI                     = 0x30c
+	ARPHRD_HWX25                     = 0x110
+	ARPHRD_IEEE1394                  = 0x18
+	ARPHRD_IEEE802                   = 0x6
+	ARPHRD_IEEE80211                 = 0x321
+	ARPHRD_IEEE80211_PRISM           = 0x322
+	ARPHRD_IEEE80211_RADIOTAP        = 0x323
+	ARPHRD_IEEE802154                = 0x324
+	ARPHRD_IEEE802154_PHY            = 0x325
+	ARPHRD_IEEE802_TR                = 0x320
+	ARPHRD_INFINIBAND                = 0x20
+	ARPHRD_IPDDP                     = 0x309
+	ARPHRD_IPGRE                     = 0x30a
+	ARPHRD_IRDA                      = 0x30f
+	ARPHRD_LAPB                      = 0x204
+	ARPHRD_LOCALTLK                  = 0x305
+	ARPHRD_LOOPBACK                  = 0x304
+	ARPHRD_METRICOM                  = 0x17
+	ARPHRD_NETROM                    = 0
+	ARPHRD_NONE                      = 0xfffe
+	ARPHRD_PIMREG                    = 0x30b
+	ARPHRD_PPP                       = 0x200
+	ARPHRD_PRONET                    = 0x4
+	ARPHRD_RAWHDLC                   = 0x206
+	ARPHRD_ROSE                      = 0x10e
+	ARPHRD_RSRVD                     = 0x104
+	ARPHRD_SIT                       = 0x308
+	ARPHRD_SKIP                      = 0x303
+	ARPHRD_SLIP                      = 0x100
+	ARPHRD_SLIP6                     = 0x102
+	ARPHRD_TUNNEL                    = 0x300
+	ARPHRD_TUNNEL6                   = 0x301
+	ARPHRD_VOID                      = 0xffff
+	ARPHRD_X25                       = 0x10f
 	DT_BLK                           = 0x6
 	DT_CHR                           = 0x2
 	DT_DIR                           = 0x4
@@ -717,6 +775,25 @@ const (
 	RTM_SETDCB                       = 0x4f
 	RTM_SETLINK                      = 0x13
 	RTM_SETNEIGHTBL                  = 0x43
+	RTNH_ALIGNTO                     = 0x4
+	RTNH_F_DEAD                      = 0x1
+	RTNH_F_ONLINK                    = 0x4
+	RTNH_F_PERVASIVE                 = 0x2
+	RTN_MAX                          = 0xb
+	RTPROT_BIRD                      = 0xc
+	RTPROT_BOOT                      = 0x3
+	RTPROT_DHCP                      = 0x10
+	RTPROT_DNROUTED                  = 0xd
+	RTPROT_GATED                     = 0x8
+	RTPROT_KERNEL                    = 0x2
+	RTPROT_MRT                       = 0xa
+	RTPROT_NTK                       = 0xf
+	RTPROT_RA                        = 0x9
+	RTPROT_REDIRECT                  = 0x1
+	RTPROT_STATIC                    = 0x4
+	RTPROT_UNSPEC                    = 0
+	RTPROT_XORP                      = 0xe
+	RTPROT_ZEBRA                     = 0xb
 	SCM_CREDENTIALS                  = 0x2
 	SCM_RIGHTS                       = 0x1
 	SCM_TIMESTAMP                    = 0x1d
diff --git a/src/pkg/syscall/zerrors_linux_arm.go b/src/pkg/syscall/zerrors_linux_arm.go
index 5be8bfa..50cdaf1 100644
--- a/src/pkg/syscall/zerrors_linux_arm.go
+++ b/src/pkg/syscall/zerrors_linux_arm.go
@@ -48,6 +48,64 @@ const (
 	AF_UNSPEC                        = 0
 	AF_WANPIPE                       = 0x19
 	AF_X25                           = 0x9
+	ARPHRD_ADAPT                     = 0x108
+	ARPHRD_APPLETLK                  = 0x8
+	ARPHRD_ARCNET                    = 0x7
+	ARPHRD_ASH                       = 0x30d
+	ARPHRD_ATM                       = 0x13
+	ARPHRD_AX25                      = 0x3
+	ARPHRD_BIF                       = 0x307
+	ARPHRD_CHAOS                     = 0x5
+	ARPHRD_CISCO                     = 0x201
+	ARPHRD_CSLIP                     = 0x101
+	ARPHRD_CSLIP6                    = 0x103
+	ARPHRD_DDCMP                     = 0x205
+	ARPHRD_DLCI                      = 0xf
+	ARPHRD_ECONET                    = 0x30e
+	ARPHRD_EETHER                    = 0x2
+	ARPHRD_ETHER                     = 0x1
+	ARPHRD_EUI64                     = 0x1b
+	ARPHRD_FCAL                      = 0x311
+	ARPHRD_FCFABRIC                  = 0x313
+	ARPHRD_FCPL                      = 0x312
+	ARPHRD_FCPP                      = 0x310
+	ARPHRD_FDDI                      = 0x306
+	ARPHRD_FRAD                      = 0x302
+	ARPHRD_HDLC                      = 0x201
+	ARPHRD_HIPPI                     = 0x30c
+	ARPHRD_HWX25                     = 0x110
+	ARPHRD_IEEE1394                  = 0x18
+	ARPHRD_IEEE802                   = 0x6
+	ARPHRD_IEEE80211                 = 0x321
+	ARPHRD_IEEE80211_PRISM           = 0x322
+	ARPHRD_IEEE80211_RADIOTAP        = 0x323
+	ARPHRD_IEEE802154                = 0x324
+	ARPHRD_IEEE802154_PHY            = 0x325
+	ARPHRD_IEEE802_TR                = 0x320
+	ARPHRD_INFINIBAND                = 0x20
+	ARPHRD_IPDDP                     = 0x309
+	ARPHRD_IPGRE                     = 0x30a
+	ARPHRD_IRDA                      = 0x30f
+	ARPHRD_LAPB                      = 0x204
+	ARPHRD_LOCALTLK                  = 0x305
+	ARPHRD_LOOPBACK                  = 0x304
+	ARPHRD_METRICOM                  = 0x17
+	ARPHRD_NETROM                    = 0
+	ARPHRD_NONE                      = 0xfffe
+	ARPHRD_PIMREG                    = 0x30b
+	ARPHRD_PPP                       = 0x200
+	ARPHRD_PRONET                    = 0x4
+	ARPHRD_RAWHDLC                   = 0x206
+	ARPHRD_ROSE                      = 0x10e
+	ARPHRD_RSRVD                     = 0x104
+	ARPHRD_SIT                       = 0x308
+	ARPHRD_SKIP                      = 0x303
+	ARPHRD_SLIP                      = 0x100
+	ARPHRD_SLIP6                     = 0x102
+	ARPHRD_TUNNEL                    = 0x300
+	ARPHRD_TUNNEL6                   = 0x301
+	ARPHRD_VOID                      = 0xffff
+	ARPHRD_X25                       = 0x10f
 	DT_BLK                           = 0x6
 	DT_CHR                           = 0x2
 	DT_DIR                           = 0x4
@@ -707,6 +765,25 @@ const (
 	RTM_SETDCB                       = 0x4f
 	RTM_SETLINK                      = 0x13
 	RTM_SETNEIGHTBL                  = 0x43
+	RTNH_ALIGNTO                     = 0x4
+	RTNH_F_DEAD                      = 0x1
+	RTNH_F_ONLINK                    = 0x4
+	RTNH_F_PERVASIVE                 = 0x2
+	RTN_MAX                          = 0xb
+	RTPROT_BIRD                      = 0xc
+	RTPROT_BOOT                      = 0x3
+	RTPROT_DHCP                      = 0x10
+	RTPROT_DNROUTED                  = 0xd
+	RTPROT_GATED                     = 0x8
+	RTPROT_KERNEL                    = 0x2
+	RTPROT_MRT                       = 0xa
+	RTPROT_NTK                       = 0xf
+	RTPROT_RA                        = 0x9
+	RTPROT_REDIRECT                  = 0x1
+	RTPROT_STATIC                    = 0x4
+	RTPROT_UNSPEC                    = 0
+	RTPROT_XORP                      = 0xe
+	RTPROT_ZEBRA                     = 0xb
 	SCM_CREDENTIALS                  = 0x2
 	SCM_RIGHTS                       = 0x1
 	SCM_TIMESTAMP                    = 0x1d
diff --git a/src/pkg/syscall/ztypes_darwin_386.go b/src/pkg/syscall/ztypes_darwin_386.go
index 1f37842..2dec017 100644
--- a/src/pkg/syscall/ztypes_darwin_386.go
+++ b/src/pkg/syscall/ztypes_darwin_386.go
@@ -22,9 +22,11 @@ const (
 	SizeofSockaddrUnix     = 0x6a
 	SizeofSockaddrDatalink = 0x14
 	SizeofLinger           = 0x8
-	SizeofIpMreq           = 0x8
+	SizeofIPMreq           = 0x8
+	SizeofIPv6Mreq         = 0x14
 	SizeofMsghdr           = 0x1c
 	SizeofCmsghdr          = 0xc
+	SizeofInet6Pktinfo     = 0x14
 	PTRACE_TRACEME         = 0
 	PTRACE_CONT            = 0x7
 	PTRACE_KILL            = 0x8
@@ -226,11 +228,16 @@ type Iovec struct {
 	Len  uint32
 }
 
-type IpMreq struct {
+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
@@ -247,6 +254,11 @@ type Cmsghdr struct {
 	Type  int32
 }
 
+type Inet6Pktinfo struct {
+	Addr    [16]byte /* in6_addr */
+	Ifindex uint32
+}
+
 type Kevent_t struct {
 	Ident  uint32
 	Filter int16
diff --git a/src/pkg/syscall/ztypes_darwin_amd64.go b/src/pkg/syscall/ztypes_darwin_amd64.go
index 5fa27bd..96500d7 100644
--- a/src/pkg/syscall/ztypes_darwin_amd64.go
+++ b/src/pkg/syscall/ztypes_darwin_amd64.go
@@ -22,9 +22,11 @@ const (
 	SizeofSockaddrUnix     = 0x6a
 	SizeofSockaddrDatalink = 0x14
 	SizeofLinger           = 0x8
-	SizeofIpMreq           = 0x8
+	SizeofIPMreq           = 0x8
+	SizeofIPv6Mreq         = 0x14
 	SizeofMsghdr           = 0x30
 	SizeofCmsghdr          = 0xc
+	SizeofInet6Pktinfo     = 0x14
 	PTRACE_TRACEME         = 0
 	PTRACE_CONT            = 0x7
 	PTRACE_KILL            = 0x8
@@ -234,11 +236,16 @@ type Iovec struct {
 	Len  uint64
 }
 
-type IpMreq struct {
+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
@@ -257,6 +264,11 @@ type Cmsghdr struct {
 	Type  int32
 }
 
+type Inet6Pktinfo struct {
+	Addr    [16]byte /* in6_addr */
+	Ifindex uint32
+}
+
 type Kevent_t struct {
 	Ident  uint64
 	Filter int16
diff --git a/src/pkg/syscall/ztypes_freebsd_386.go b/src/pkg/syscall/ztypes_freebsd_386.go
index f4d256f..6304d3b 100644
--- a/src/pkg/syscall/ztypes_freebsd_386.go
+++ b/src/pkg/syscall/ztypes_freebsd_386.go
@@ -32,9 +32,11 @@ const (
 	SizeofSockaddrUnix     = 0x6a
 	SizeofSockaddrDatalink = 0x36
 	SizeofLinger           = 0x8
-	SizeofIpMreq           = 0x8
+	SizeofIPMreq           = 0x8
+	SizeofIPv6Mreq         = 0x14
 	SizeofMsghdr           = 0x1c
 	SizeofCmsghdr          = 0xc
+	SizeofInet6Pktinfo     = 0x14
 	PTRACE_TRACEME         = 0
 	PTRACE_CONT            = 0x7
 	PTRACE_KILL            = 0x8
@@ -219,11 +221,16 @@ type Iovec struct {
 	Len  uint32
 }
 
-type IpMreq struct {
+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
@@ -240,6 +247,11 @@ type Cmsghdr struct {
 	Type  int32
 }
 
+type Inet6Pktinfo struct {
+	Addr    [16]byte /* in6_addr */
+	Ifindex uint32
+}
+
 type Kevent_t struct {
 	Ident  uint32
 	Filter int16
diff --git a/src/pkg/syscall/ztypes_freebsd_amd64.go b/src/pkg/syscall/ztypes_freebsd_amd64.go
index cf6355c..ef5a51c 100644
--- a/src/pkg/syscall/ztypes_freebsd_amd64.go
+++ b/src/pkg/syscall/ztypes_freebsd_amd64.go
@@ -32,9 +32,11 @@ const (
 	SizeofSockaddrUnix     = 0x6a
 	SizeofSockaddrDatalink = 0x36
 	SizeofLinger           = 0x8
-	SizeofIpMreq           = 0x8
+	SizeofIPMreq           = 0x8
+	SizeofIPv6Mreq         = 0x14
 	SizeofMsghdr           = 0x30
 	SizeofCmsghdr          = 0xc
+	SizeofInet6Pktinfo     = 0x14
 	PTRACE_TRACEME         = 0
 	PTRACE_CONT            = 0x7
 	PTRACE_KILL            = 0x8
@@ -220,11 +222,16 @@ type Iovec struct {
 	Len  uint64
 }
 
-type IpMreq struct {
+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
@@ -243,6 +250,11 @@ type Cmsghdr struct {
 	Type  int32
 }
 
+type Inet6Pktinfo struct {
+	Addr    [16]byte /* in6_addr */
+	Ifindex uint32
+}
+
 type Kevent_t struct {
 	Ident  uint64
 	Filter int16
diff --git a/src/pkg/syscall/ztypes_linux_386.go b/src/pkg/syscall/ztypes_linux_386.go
index 0409027..65c8b87 100644
--- a/src/pkg/syscall/ztypes_linux_386.go
+++ b/src/pkg/syscall/ztypes_linux_386.go
@@ -19,9 +19,11 @@ const (
 	SizeofSockaddrLinklayer = 0x14
 	SizeofSockaddrNetlink   = 0xc
 	SizeofLinger            = 0x8
-	SizeofIpMreq            = 0x8
+	SizeofIPMreq            = 0x8
+	SizeofIPv6Mreq          = 0x14
 	SizeofMsghdr            = 0x1c
 	SizeofCmsghdr           = 0xc
+	SizeofInet6Pktinfo      = 0x14
 	SizeofUcred             = 0xc
 	IFA_UNSPEC              = 0
 	IFA_ADDRESS             = 0x1
@@ -53,6 +55,42 @@ const (
 	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
@@ -61,6 +99,7 @@ const (
 	SizeofIfInfomsg         = 0x10
 	SizeofIfAddrmsg         = 0x8
 	SizeofRtmsg             = 0xc
+	SizeofRtNexthop         = 0x8
 	SizeofInotifyEvent      = 0x10
 )
 
@@ -261,11 +300,16 @@ type Iovec struct {
 	Len  uint32
 }
 
-type IpMreq struct {
+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
@@ -282,6 +326,11 @@ type Cmsghdr struct {
 	Type  int32
 }
 
+type Inet6Pktinfo struct {
+	Addr    [16]byte /* in6_addr */
+	Ifindex uint32
+}
+
 type Ucred struct {
 	Pid int32
 	Uid uint32
@@ -344,6 +393,13 @@ type RtMsg struct {
 	Flags    uint32
 }
 
+type RtNexthop struct {
+	Len     uint16
+	Flags   uint8
+	Hops    uint8
+	Ifindex int32
+}
+
 type InotifyEvent struct {
 	Wd     int32
 	Mask   uint32
diff --git a/src/pkg/syscall/ztypes_linux_amd64.go b/src/pkg/syscall/ztypes_linux_amd64.go
index 1d375e0..e26b6bf 100644
--- a/src/pkg/syscall/ztypes_linux_amd64.go
+++ b/src/pkg/syscall/ztypes_linux_amd64.go
@@ -19,9 +19,11 @@ const (
 	SizeofSockaddrLinklayer = 0x14
 	SizeofSockaddrNetlink   = 0xc
 	SizeofLinger            = 0x8
-	SizeofIpMreq            = 0x8
+	SizeofIPMreq            = 0x8
+	SizeofIPv6Mreq          = 0x14
 	SizeofMsghdr            = 0x38
 	SizeofCmsghdr           = 0x10
+	SizeofInet6Pktinfo      = 0x14
 	SizeofUcred             = 0xc
 	IFA_UNSPEC              = 0
 	IFA_ADDRESS             = 0x1
@@ -53,6 +55,42 @@ const (
 	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
@@ -61,6 +99,7 @@ const (
 	SizeofIfInfomsg         = 0x10
 	SizeofIfAddrmsg         = 0x8
 	SizeofRtmsg             = 0xc
+	SizeofRtNexthop         = 0x8
 	SizeofInotifyEvent      = 0x10
 )
 
@@ -261,11 +300,16 @@ type Iovec struct {
 	Len  uint64
 }
 
-type IpMreq struct {
+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
@@ -284,6 +328,11 @@ type Cmsghdr struct {
 	Type  int32
 }
 
+type Inet6Pktinfo struct {
+	Addr    [16]byte /* in6_addr */
+	Ifindex uint32
+}
+
 type Ucred struct {
 	Pid int32
 	Uid uint32
@@ -346,6 +395,13 @@ type RtMsg struct {
 	Flags    uint32
 }
 
+type RtNexthop struct {
+	Len     uint16
+	Flags   uint8
+	Hops    uint8
+	Ifindex int32
+}
+
 type InotifyEvent struct {
 	Wd     int32
 	Mask   uint32
diff --git a/src/pkg/syscall/ztypes_linux_arm.go b/src/pkg/syscall/ztypes_linux_arm.go
index 5f2cde3..ebd5379 100644
--- a/src/pkg/syscall/ztypes_linux_arm.go
+++ b/src/pkg/syscall/ztypes_linux_arm.go
@@ -24,9 +24,11 @@ const (
 	SizeofSockaddrLinklayer = 0x14
 	SizeofSockaddrNetlink   = 0xc
 	SizeofLinger            = 0x8
-	SizeofIpMreq            = 0x8
+	SizeofIPMreq            = 0x8
+	SizeofIPv6Mreq          = 0x14
 	SizeofMsghdr            = 0x1c
 	SizeofCmsghdr           = 0xc
+	SizeofInet6Pktinfo      = 0x14
 	SizeofUcred             = 0xc
 	IFA_UNSPEC              = 0
 	IFA_ADDRESS             = 0x1
@@ -58,6 +60,42 @@ const (
 	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
@@ -66,6 +104,7 @@ const (
 	SizeofIfInfomsg         = 0x10
 	SizeofIfAddrmsg         = 0x8
 	SizeofRtmsg             = 0xc
+	SizeofRtNexthop         = 0x8
 	SizeofInotifyEvent      = 0x10
 )
 
@@ -268,11 +307,16 @@ type Iovec struct {
 	Len  uint32
 }
 
-type IpMreq struct {
+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
@@ -289,6 +333,11 @@ type Cmsghdr struct {
 	Type  int32
 }
 
+type Inet6Pktinfo struct {
+	Addr    [16]byte /* in6_addr */
+	Ifindex uint32
+}
+
 type Ucred struct {
 	Pid int32
 	Uid uint32
@@ -351,6 +400,13 @@ type RtMsg struct {
 	Flags    uint32
 }
 
+type RtNexthop struct {
+	Len     uint16
+	Flags   uint8
+	Hops    uint8
+	Ifindex int32
+}
+
 type InotifyEvent struct {
 	Wd     int32
 	Mask   uint32
diff --git a/src/pkg/tabwriter/tabwriter.go b/src/pkg/tabwriter/tabwriter.go
index d91a07d..b84c6ec 100644
--- a/src/pkg/tabwriter/tabwriter.go
+++ b/src/pkg/tabwriter/tabwriter.go
@@ -158,7 +158,7 @@ const (
 	TabIndent
 
 	// Print a vertical bar ('|') between columns (after formatting).
-	// Discarded colums appear as zero-width columns ("||").
+	// Discarded columns appear as zero-width columns ("||").
 	Debug
 )
 
diff --git a/src/pkg/template/template.go b/src/pkg/template/template.go
index c00f72a..f481cbd 100644
--- a/src/pkg/template/template.go
+++ b/src/pkg/template/template.go
@@ -17,12 +17,15 @@
 	Data items may be values or pointers; the interface hides the
 	indirection.
 
-	In the following, 'field' is one of several things, according to the data.
+	In the following, 'Field' is one of several things, according to the data.
 
-		- The name of a field of a struct (result = data.field),
-		- The value stored in a map under that key (result = data[field]), or
+		- The name of a field of a struct (result = data.Field),
+		- The value stored in a map under that key (result = data["Field"]), or
 		- The result of invoking a niladic single-valued method with that name
-		  (result = data.field())
+		  (result = data.Field())
+
+	If Field is a struct field or method name, it must be an exported
+	(capitalized) name.
 
 	Major constructs ({} are the default delimiters for template actions;
 	[] are the notation in this comment for optional elements):
@@ -236,8 +239,8 @@ func isExported(name string) bool {
 
 // -- Lexical analysis
 
-// Is c a white space character?
-func white(c uint8) bool { return c == ' ' || c == '\t' || c == '\r' || c == '\n' }
+// Is c a space character?
+func isSpace(c uint8) bool { return c == ' ' || c == '\t' || c == '\r' || c == '\n' }
 
 // Safely, does s[n:n+len(t)] == t?
 func equal(s []byte, n int, t []byte) bool {
@@ -292,9 +295,9 @@ func (t *Template) nextItem() []byte {
 		t.linenum++
 		i++
 	}
-	// Leading white space up to but not including newline
+	// Leading space up to but not including newline
 	for i = start; i < len(t.buf); i++ {
-		if t.buf[i] == '\n' || !white(t.buf[i]) {
+		if t.buf[i] == '\n' || !isSpace(t.buf[i]) {
 			break
 		}
 	}
@@ -339,7 +342,7 @@ func (t *Template) nextItem() []byte {
 			firstChar := t.buf[left+len(t.ldelim)]
 			if firstChar == '.' || firstChar == '#' {
 				// It's special and the first thing on the line. Is it the last?
-				for j := right; j < len(t.buf) && white(t.buf[j]); j++ {
+				for j := right; j < len(t.buf) && isSpace(t.buf[j]); j++ {
 					if t.buf[j] == '\n' {
 						// Yes it is. Drop the surrounding space and return the {.foo}
 						t.linenum++
@@ -351,7 +354,7 @@ func (t *Template) nextItem() []byte {
 		}
 		// No it's not. If there's leading space, return that.
 		if leadingSpace {
-			// not trimming space: return leading white space if there is some.
+			// not trimming space: return leading space if there is some.
 			t.p = left
 			return t.buf[start:left]
 		}
@@ -374,13 +377,13 @@ func (t *Template) nextItem() []byte {
 	return item
 }
 
-// Turn a byte array into a white-space-split array of strings,
+// Turn a byte array into a space-split array of strings,
 // taking into account quoted strings.
 func words(buf []byte) []string {
 	s := make([]string, 0, 5)
 	for i := 0; i < len(buf); {
 		// One word per loop
-		for i < len(buf) && white(buf[i]) {
+		for i < len(buf) && isSpace(buf[i]) {
 			i++
 		}
 		if i == len(buf) {
@@ -395,10 +398,11 @@ func words(buf []byte) []string {
 			} else {
 				i++
 			}
-		} else {
-			for i < len(buf) && !white(buf[i]) {
-				i++
-			}
+		}
+		// Even with quotes, break on space only.  This handles input
+		// such as {""|} and catches quoting mistakes.
+		for i < len(buf) && !isSpace(buf[i]) {
+			i++
 		}
 		s = append(s, string(buf[start:i]))
 	}
@@ -490,20 +494,9 @@ func (t *Template) formatter(name string) func(io.Writer, string, ...interface{}
 
 // -- Parsing
 
-// Allocate a new variable-evaluation element.
+// newVariable allocates a new variable-evaluation element.
 func (t *Template) newVariable(words []string) *variableElement {
-	// After the final space-separated argument, formatters may be specified separated
-	// by pipe symbols, for example: {a b c|d|e}
-
-	// Until we learn otherwise, formatters contains a single name: "", the default formatter.
-	formatters := []string{""}
-	lastWord := words[len(words)-1]
-	bar := strings.IndexRune(lastWord, '|')
-	if bar >= 0 {
-		words[len(words)-1] = lastWord[0:bar]
-		formatters = strings.Split(lastWord[bar+1:], "|", -1)
-	}
-
+	formatters := extractFormatters(words)
 	args := make([]interface{}, len(words))
 
 	// Build argument list, processing any literals
@@ -549,6 +542,38 @@ func (t *Template) newVariable(words []string) *variableElement {
 	return &variableElement{t.linenum, args, formatters}
 }
 
+// extractFormatters extracts a list of formatters from words.
+// After the final space-separated argument in a variable, formatters may be
+// specified separated by pipe symbols. For example: {a b c|d|e}
+// The words parameter still has the formatters joined by '|' in the last word.
+// extractFormatters splits formatters, replaces the last word with the content
+// found before the first '|' within it, and returns the formatters obtained.
+// If no formatters are found in words, the default formatter is returned.
+func extractFormatters(words []string) (formatters []string) {
+	// "" is the default formatter.
+	formatters = []string{""}
+	if len(words) == 0 {
+		return
+	}
+	var bar int
+	lastWord := words[len(words)-1]
+	if isQuote(lastWord[0]) {
+		end := endQuote([]byte(lastWord), 0)
+		if end < 0 || end+1 == len(lastWord) || lastWord[end+1] != '|' {
+			return
+		}
+		bar = end + 1
+	} else {
+		bar = strings.IndexRune(lastWord, '|')
+		if bar < 0 {
+			return
+		}
+	}
+	words[len(words)-1] = lastWord[0:bar]
+	formatters = strings.Split(lastWord[bar+1:], "|", -1)
+	return
+}
+
 // Grab the next item.  If it's simple, just append it to the template.
 // Otherwise return its details.
 func (t *Template) parseSimple(item []byte) (done bool, tok int, w []string) {
@@ -1012,13 +1037,13 @@ func (t *Template) executeRepeated(r *repeatedElement, st *state) {
 	}
 }
 
-// A valid delimiter must contain no white space and be non-empty.
+// A valid delimiter must contain no space and be non-empty.
 func validDelim(d []byte) bool {
 	if len(d) == 0 {
 		return false
 	}
 	for _, c := range d {
-		if white(c) {
+		if isSpace(c) {
 			return false
 		}
 	}
diff --git a/src/pkg/template/template_test.go b/src/pkg/template/template_test.go
index a5e6a4e..99b23c2 100644
--- a/src/pkg/template/template_test.go
+++ b/src/pkg/template/template_test.go
@@ -144,21 +144,21 @@ var tests = []*Test{
 	},
 
 	&Test{
-		in: `{"Strings" ":"} {""} {"\t\u0123 \x23\\"} {"\"}{\\"}`,
+		in: `{"Strings" ":"} {""} {"|"} {"\t\u0123 \x23\\"} {"\"}{\\"}`,
 
-		out: "Strings:  \t\u0123 \x23\\ \"}{\\",
+		out: "Strings:  | \t\u0123 \x23\\ \"}{\\",
 	},
 
 	&Test{
-		in: "{`Raw strings` `:`} {``} {`\\t\\u0123 \\x23\\`} {`}{\\`}",
+		in: "{`Raw strings` `:`} {``} {`|`} {`\\t\\u0123 \\x23\\`} {`}{\\`}",
 
-		out: "Raw strings:  \\t\\u0123 \\x23\\ }{\\",
+		out: "Raw strings:  | \\t\\u0123 \\x23\\ }{\\",
 	},
 
 	&Test{
-		in: "Characters: {'a'} {'\\u0123'} {' '} {'}'} {'{'}",
+		in: "Characters: {'a'} {'\\u0123'} {' '} {'{'} {'|'} {'}'}",
 
-		out: "Characters: 97 291 32 125 123",
+		out: "Characters: 97 291 32 123 124 125",
 	},
 
 	&Test{
@@ -762,6 +762,10 @@ var formatterTests = []Test{
 		in:  `{"%.02f 0x%02X" 1.1 10|printf}`,
 		out: "1.10 0x0A",
 	},
+	{
+		in:  `{""|}{""||}{""|printf}`, // Issue #1896.
+		out: "",
+	},
 }
 
 func TestFormatters(t *testing.T) {
diff --git a/src/pkg/testing/benchmark.go b/src/pkg/testing/benchmark.go
index cf73e2b..db4c659 100644
--- a/src/pkg/testing/benchmark.go
+++ b/src/pkg/testing/benchmark.go
@@ -150,7 +150,7 @@ func (b *B) run() BenchmarkResult {
 type BenchmarkResult struct {
 	N     int   // The number of iterations.
 	Ns    int64 // The total time taken.
-	Bytes int64 // The total number of bytes processed.
+	Bytes int64 // Bytes processed in one iteration.
 }
 
 func (r BenchmarkResult) NsPerOp() int64 {
@@ -160,13 +160,20 @@ func (r BenchmarkResult) NsPerOp() int64 {
 	return r.Ns / int64(r.N)
 }
 
+func (r BenchmarkResult) mbPerSec() float64 {
+	if r.Bytes <= 0 || r.Ns <= 0 || r.N <= 0 {
+		return 0
+	}
+	return float64(r.Bytes) * float64(r.N) / float64(r.Ns) * 1e3
+}
+
 func (r BenchmarkResult) String() string {
-	ns := r.NsPerOp()
+	mbs := r.mbPerSec()
 	mb := ""
-	if ns > 0 && r.Bytes > 0 {
-		mb = fmt.Sprintf("\t%7.2f MB/s", (float64(r.Bytes)/1e6)/(float64(ns)/1e9))
+	if mbs != 0 {
+		mb = fmt.Sprintf("\t%7.2f MB/s", mbs)
 	}
-	return fmt.Sprintf("%8d\t%10d ns/op%s", r.N, ns, mb)
+	return fmt.Sprintf("%8d\t%10d ns/op%s", r.N, r.NsPerOp(), mb)
 }
 
 // An internal function but exported because it is cross-package; part of the implementation
diff --git a/src/pkg/time/format.go b/src/pkg/time/format.go
index 7b5a8f3..47d7363 100644
--- a/src/pkg/time/format.go
+++ b/src/pkg/time/format.go
@@ -272,9 +272,19 @@ func (t *Time) Format(layout string) string {
 		case stdHour:
 			p = zeroPad(t.Hour)
 		case stdHour12:
-			p = strconv.Itoa(t.Hour % 12)
+			// Noon is 12PM, midnight is 12AM.
+			hr := t.Hour % 12
+			if hr == 0 {
+				hr = 12
+			}
+			p = strconv.Itoa(hr)
 		case stdZeroHour12:
-			p = zeroPad(t.Hour % 12)
+			// Noon is 12PM, midnight is 12AM.
+			hr := t.Hour % 12
+			if hr == 0 {
+				hr = 12
+			}
+			p = zeroPad(hr)
 		case stdMinute:
 			p = strconv.Itoa(t.Minute)
 		case stdZeroMinute:
@@ -429,6 +439,7 @@ func skip(value, prefix string) (string, os.Error) {
 func Parse(alayout, avalue string) (*Time, os.Error) {
 	var t Time
 	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
 	// Each iteration processes one std value.
@@ -558,9 +569,12 @@ func Parse(alayout, avalue string) (*Time, os.Error) {
 				break
 			}
 			p, value = value[0:2], value[2:]
-			if p == "PM" {
+			switch p {
+			case "PM":
 				pmSet = true
-			} else if p != "AM" {
+			case "AM":
+				amSet = true
+			default:
 				err = errBad
 			}
 		case stdpm:
@@ -569,9 +583,12 @@ func Parse(alayout, avalue string) (*Time, os.Error) {
 				break
 			}
 			p, value = value[0:2], value[2:]
-			if p == "pm" {
+			switch p {
+			case "pm":
 				pmSet = true
-			} else if p != "am" {
+			case "am":
+				amSet = true
+			default:
 				err = errBad
 			}
 		case stdTZ:
@@ -613,6 +630,8 @@ func Parse(alayout, avalue string) (*Time, os.Error) {
 	}
 	if pmSet && t.Hour < 12 {
 		t.Hour += 12
+	} else if amSet && t.Hour == 12 {
+		t.Hour = 0
 	}
 	return &t, nil
 }
diff --git a/src/pkg/time/sleep.go b/src/pkg/time/sleep.go
index 3bc253c..314622d 100644
--- a/src/pkg/time/sleep.go
+++ b/src/pkg/time/sleep.go
@@ -91,7 +91,7 @@ func (e *Timer) Stop() (ok bool) {
 // It assumes that f will not block.
 func after(ns int64, f func(int64)) (e *Timer) {
 	now := Nanoseconds()
-	t := Nanoseconds() + ns
+	t := now + ns
 	if ns > 0 && t < now {
 		panic("time: time overflow")
 	}
diff --git a/src/pkg/time/tick.go b/src/pkg/time/tick.go
index 6c21bf1..dde1800 100644
--- a/src/pkg/time/tick.go
+++ b/src/pkg/time/tick.go
@@ -88,7 +88,7 @@ func wakeLoop(wakeMeAt chan int64, wakeUp chan bool) {
 
 // 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,
-// signalling a time to wake up one or more Tickers.
+// signaling a time to wake up one or more Tickers.
 func tickerLoop() {
 	// Represents the next alarm to be delivered.
 	var alarm alarmer
diff --git a/src/pkg/time/time_test.go b/src/pkg/time/time_test.go
index 1d83291..eb676bf 100644
--- a/src/pkg/time/time_test.go
+++ b/src/pkg/time/time_test.go
@@ -302,6 +302,66 @@ func TestParseErrors(t *testing.T) {
 	}
 }
 
+func TestNoonIs12PM(t *testing.T) {
+	noon := Time{Hour: 12}
+	const expect = "12:00PM"
+	got := noon.Format("3:04PM")
+	if got != expect {
+		t.Errorf("got %q; expect %q", got, expect)
+	}
+	got = noon.Format("03:04PM")
+	if got != expect {
+		t.Errorf("got %q; expect %q", got, expect)
+	}
+}
+
+func TestMidnightIs12AM(t *testing.T) {
+	midnight := Time{Hour: 0}
+	expect := "12:00AM"
+	got := midnight.Format("3:04PM")
+	if got != expect {
+		t.Errorf("got %q; expect %q", got, expect)
+	}
+	got = midnight.Format("03:04PM")
+	if got != expect {
+		t.Errorf("got %q; expect %q", got, expect)
+	}
+}
+
+func Test12PMIsNoon(t *testing.T) {
+	noon, err := Parse("3:04PM", "12:00PM")
+	if err != nil {
+		t.Fatal("error parsing date:", err)
+	}
+	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)
+	}
+}
+
+func Test12AMIsMidnight(t *testing.T) {
+	midnight, err := Parse("3:04PM", "12:00AM")
+	if err != nil {
+		t.Fatal("error parsing date:", err)
+	}
+	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)
+	}
+}
+
 // Check that a time without a Zone still produces a (numeric) time zone
 // when formatted with MST as a requested zone.
 func TestMissingZone(t *testing.T) {
diff --git a/src/pkg/time/zoneinfo_windows.go b/src/pkg/time/zoneinfo_windows.go
index c357eec..83afdfb 100644
--- a/src/pkg/time/zoneinfo_windows.go
+++ b/src/pkg/time/zoneinfo_windows.go
@@ -14,7 +14,7 @@ import (
 // this year's rules for daylight savings time apply to all previous
 // and future years as well.
 
-// TODO(brainman): use GetDynamicTimeZoneInformation, whenever posible (Vista and up),
+// TODO(brainman): use GetDynamicTimeZoneInformation, whenever possible (Vista and up),
 // to improve on situation described in the bug above.
 
 type zone struct {
@@ -46,7 +46,7 @@ func (z *zone) populate(bias, biasdelta int32, d *syscall.Systemtime, name []uin
 	return
 }
 
-// Pre-calculte cutoff time in seconds since the Unix epoch, if data is supplied in "absolute" format.
+// 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 {
 		z.abssec = (&Time{z.year, int(z.month), int(z.day), int(z.hour), int(z.minute), int(z.second), 0, 0, ""}).Seconds()
@@ -55,7 +55,7 @@ func (z *zone) preCalculateAbsSec() {
 	}
 }
 
-// Convert zone cutoff time to sec in number of seconds since the Unix epoch, given particualar year.
+// Convert zone cutoff time to sec in number of seconds since the Unix epoch, given particular year.
 func (z *zone) cutoffSeconds(year int64) int64 {
 	// Windows specifies daylight savings information in "day in month" format:
 	// z.month is month number (1-12)
@@ -96,7 +96,7 @@ func (z *zone) isBeforeCutoff(t *Time) bool {
 }
 
 type zoneinfo struct {
-	disabled         bool // daylight saving time is not used localy
+	disabled         bool // daylight saving time is not used locally
 	offsetIfDisabled int
 	januaryIsStd     bool // is january 1 standard time?
 	std, dst         zone
diff --git a/src/pkg/unicode/letter.go b/src/pkg/unicode/letter.go
index 382c6eb..047bef1 100644
--- a/src/pkg/unicode/letter.go
+++ b/src/pkg/unicode/letter.go
@@ -11,13 +11,31 @@ const (
 	ReplacementChar = 0xFFFD   // Represents invalid code points.
 )
 
+// RangeTable defines a set of Unicode code points by listing the ranges of
+// code points within the set. The ranges are listed in two slices
+// to save space: a slice of 16-bit ranges and a slice of 32-bit ranges.
+// The two slices must be in sorted order and non-overlapping.
+// Also, R32 should contain only values >= 0x10000 (1<<16).
+type RangeTable struct {
+	R16 []Range16
+	R32 []Range32
+}
 
-// The representation of a range of Unicode code points.  The range runs from Lo to Hi
+// Range16 represents of a range of 16-bit Unicode code points.  The range runs from Lo to Hi
 // inclusive and has the specified stride.
-type Range struct {
-	Lo     int
-	Hi     int
-	Stride int
+type Range16 struct {
+	Lo     uint16
+	Hi     uint16
+	Stride uint16
+}
+
+// Range32 represents of a range of Unicode code points and is used when one or
+//  more of the values will not fit in 16 bits.  The range runs from Lo to Hi
+// inclusive and has the specified stride. Lo and Hi must always be >= 1<<16.
+type Range32 struct {
+	Lo     uint32
+	Hi     uint32
+	Stride uint32
 }
 
 // CaseRange represents a range of Unicode code points for simple (one
@@ -31,8 +49,8 @@ type Range struct {
 //	{UpperLower, UpperLower, UpperLower}
 // The constant UpperLower has an otherwise impossible delta value.
 type CaseRange struct {
-	Lo    int
-	Hi    int
+	Lo    uint32
+	Hi    uint32
 	Delta d
 }
 
@@ -60,22 +78,28 @@ const (
 	UpperLower = MaxRune + 1 // (Cannot be a valid delta.)
 )
 
-// Is tests whether rune is in the specified table of ranges.
-func Is(ranges []Range, rune int) bool {
-	// common case: rune is ASCII or Latin-1
-	if rune < 0x100 {
-		for _, r := range ranges {
-			if rune > r.Hi {
-				continue
-			}
-			if rune < r.Lo {
-				return false
-			}
+// is16 uses binary search to test whether rune is in the specified slice of 16-bit ranges.
+func is16(ranges []Range16, rune 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
 		}
-		return false
+		if rune < r.Lo {
+			hi = m
+		} else {
+			lo = m + 1
+		}
 	}
+	return false
+}
 
+// is32 uses binary search to test whether rune is in the specified slice of 32-bit ranges.
+func is32(ranges []Range32, rune uint32) bool {
 	// binary search over ranges
 	lo := 0
 	hi := len(ranges)
@@ -94,6 +118,34 @@ func Is(ranges []Range, rune int) bool {
 	return false
 }
 
+// Is tests whether rune is in the specified table of ranges.
+func Is(rangeTab *RangeTable, rune int) bool {
+	// common case: rune is ASCII or Latin-1.
+	if rune < 0x100 {
+		// Only need to check R16, since R32 is always >= 1<<16.
+		r16 := uint16(rune)
+		for _, r := range rangeTab.R16 {
+			if r16 > r.Hi {
+				continue
+			}
+			if r16 < r.Lo {
+				return false
+			}
+			return (r16-r.Lo)%r.Stride == 0
+		}
+		return false
+	}
+	r16 := rangeTab.R16
+	if len(r16) > 0 && rune <= int(r16[len(r16)-1].Hi) {
+		return is16(r16, uint16(rune))
+	}
+	r32 := rangeTab.R32
+	if len(r32) > 0 && rune >= int(r32[0].Lo) {
+		return is32(r32, uint32(rune))
+	}
+	return false
+}
+
 // IsUpper reports whether the rune is an upper case letter.
 func IsUpper(rune int) bool {
 	if rune < 0x80 { // quick ASCII check
@@ -150,7 +202,7 @@ func to(_case int, rune int, caseRange []CaseRange) int {
 	for lo < hi {
 		m := lo + (hi-lo)/2
 		r := caseRange[m]
-		if r.Lo <= rune && rune <= r.Hi {
+		if int(r.Lo) <= rune && rune <= int(r.Hi) {
 			delta := int(r.Delta[_case])
 			if delta > MaxRune {
 				// In an Upper-Lower sequence, which always starts with
@@ -163,11 +215,11 @@ 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 r.Lo + ((rune-r.Lo)&^1 | _case&1)
+				return int(r.Lo) + ((rune-int(r.Lo))&^1 | _case&1)
 			}
 			return rune + delta
 		}
-		if rune < r.Lo {
+		if rune < int(r.Lo) {
 			hi = m
 		} else {
 			lo = m + 1
diff --git a/src/pkg/unicode/maketables.go b/src/pkg/unicode/maketables.go
index 33a8268..c3cf32b 100644
--- a/src/pkg/unicode/maketables.go
+++ b/src/pkg/unicode/maketables.go
@@ -28,6 +28,7 @@ func main() {
 	printScriptOrProperty(false)
 	printScriptOrProperty(true)
 	printCases()
+	printSizes()
 }
 
 var dataURL = flag.String("data", "", "full URL for UnicodeData.txt; defaults to --url/UnicodeData.txt")
@@ -278,16 +279,16 @@ func loadChars() {
 		switch parseCategory(line[0 : len(line)-1]) {
 		case SNormal:
 			if first != 0 {
-				logger.Fatalf("bad state normal at U+%04X", lastChar)
+				logger.Fatalf("bad state normal at %U", lastChar)
 			}
 		case SFirst:
 			if first != 0 {
-				logger.Fatalf("bad state first at U+%04X", lastChar)
+				logger.Fatalf("bad state first at %U", lastChar)
 			}
 			first = lastChar
 		case SLast:
 			if first == 0 {
-				logger.Fatalf("bad state last at U+%04X", lastChar)
+				logger.Fatalf("bad state last at %U", lastChar)
 			}
 			for i := first + 1; i <= lastChar; i++ {
 				chars[i] = chars[first]
@@ -299,6 +300,15 @@ func loadChars() {
 	resp.Body.Close()
 }
 
+const progHeader = `// Generated by running
+//	maketables --tables=%s --data=%s
+// DO NOT EDIT
+
+package unicode
+
+`
+
+
 func printCategories() {
 	if *tablelist == "" {
 		return
@@ -312,20 +322,14 @@ func printCategories() {
 		fullCategoryTest(list)
 		return
 	}
-	fmt.Printf(
-		"// Generated by running\n"+
-			"//	maketables --tables=%s --data=%s\n"+
-			"// DO NOT EDIT\n\n"+
-			"package unicode\n\n",
-		*tablelist,
-		*dataURL)
+	fmt.Printf(progHeader, *tablelist, *dataURL)
 
 	fmt.Println("// Version is the Unicode edition from which the tables are derived.")
 	fmt.Printf("const Version = %q\n\n", version())
 
 	if *tablelist == "all" {
 		fmt.Println("// Categories is the set of Unicode data tables.")
-		fmt.Println("var Categories = map[string] []Range {")
+		fmt.Println("var Categories = map[string] *RangeTable {")
 		for k := range category {
 			fmt.Printf("\t%q: %s,\n", k, k)
 		}
@@ -364,12 +368,12 @@ func printCategories() {
 		ndecl++
 		if name == "letter" { // special case
 			dumpRange(
-				"var letter = []Range {\n",
+				"var letter = &RangeTable{\n",
 				letterOp)
 			continue
 		}
 		dumpRange(
-			fmt.Sprintf("var _%s = []Range {\n", name),
+			fmt.Sprintf("var _%s = &RangeTable{\n", name),
 			func(code int) bool { return chars[code].category == name })
 	}
 	decl.Sort()
@@ -382,12 +386,15 @@ func printCategories() {
 
 type Op func(code int) bool
 
-const format = "\t{0x%04x, 0x%04x, %d},\n"
+const format = "\t\t{0x%04x, 0x%04x, %d},\n"
 
 func dumpRange(header string, inCategory Op) {
 	fmt.Print(header)
 	next := 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) {
@@ -427,13 +434,38 @@ func dumpRange(header string, inCategory Op) {
 				break
 			}
 		}
-		fmt.Printf(format, lo, hi, stride)
+		size, count = printRange(uint32(lo), uint32(hi), uint32(stride), size, count)
 		// next range: start looking where this range ends
 		next = hi + 1
 	}
+	fmt.Print("\t},\n")
 	fmt.Print("}\n\n")
 }
 
+func printRange(lo, hi, stride uint32, size int, count *int) (int, *int) {
+	if size == 16 && hi >= 1<<16 {
+		if lo < 1<<16 {
+			if lo+stride != hi {
+				log.Fatalf("unexpected straddle: %U %U %d", lo, hi, stride)
+			}
+			// No range contains U+FFFF as an instance, so split
+			// the range into two entries. That way we can maintain
+			// the invariant that R32 contains only >= 1<<16.
+			fmt.Printf(format, lo, lo, 1)
+			lo = hi
+			stride = 1
+			*count++
+		}
+		fmt.Print("\t},\n")
+		fmt.Print("\tR32: []Range32{\n")
+		size = 32
+		count = &range32Count
+	}
+	fmt.Printf(format, lo, hi, stride)
+	*count++
+	return size, count
+}
+
 func fullCategoryTest(list []string) {
 	for _, name := range list {
 		if _, ok := category[name]; !ok {
@@ -454,12 +486,12 @@ func fullCategoryTest(list []string) {
 	}
 }
 
-func verifyRange(name string, inCategory Op, table []unicode.Range) {
+func verifyRange(name string, inCategory Op, table *unicode.RangeTable) {
 	for i := range chars {
 		web := inCategory(i)
 		pkg := unicode.Is(table, i)
 		if web != pkg {
-			fmt.Fprintf(os.Stderr, "%s: U+%04X: web=%t pkg=%t\n", name, i, web, pkg)
+			fmt.Fprintf(os.Stderr, "%s: %U: web=%t pkg=%t\n", name, i, web, pkg)
 		}
 	}
 }
@@ -497,22 +529,22 @@ func parseScript(line string, scripts map[string][]Script) {
 }
 
 // The script tables have a lot of adjacent elements. Fold them together.
-func foldAdjacent(r []Script) []unicode.Range {
-	s := make([]unicode.Range, 0, len(r))
+func foldAdjacent(r []Script) []unicode.Range32 {
+	s := make([]unicode.Range32, 0, len(r))
 	j := 0
 	for i := 0; i < len(r); i++ {
-		if j > 0 && int(r[i].lo) == s[j-1].Hi+1 {
-			s[j-1].Hi = int(r[i].hi)
+		if j > 0 && r[i].lo == s[j-1].Hi+1 {
+			s[j-1].Hi = r[i].hi
 		} else {
 			s = s[0 : j+1]
-			s[j] = unicode.Range{int(r[i].lo), int(r[i].hi), 1}
+			s[j] = unicode.Range32{uint32(r[i].lo), uint32(r[i].hi), 1}
 			j++
 		}
 	}
 	return s
 }
 
-func fullScriptTest(list []string, installed map[string][]unicode.Range, scripts map[string][]Script) {
+func fullScriptTest(list []string, installed map[string]*unicode.RangeTable, scripts map[string][]Script) {
 	for _, name := range list {
 		if _, ok := scripts[name]; !ok {
 			logger.Fatal("unknown script", name)
@@ -524,7 +556,7 @@ func fullScriptTest(list []string, installed map[string][]unicode.Range, scripts
 		for _, script := range scripts[name] {
 			for r := script.lo; r <= script.hi; r++ {
 				if !unicode.Is(installed[name], int(r)) {
-					fmt.Fprintf(os.Stderr, "U+%04X: not in script %s\n", r, name)
+					fmt.Fprintf(os.Stderr, "%U: not in script %s\n", r, name)
 				}
 			}
 		}
@@ -589,10 +621,10 @@ func printScriptOrProperty(doProps bool) {
 	if flaglist == "all" {
 		if doProps {
 			fmt.Println("// Properties is the set of Unicode property tables.")
-			fmt.Println("var Properties = map[string] []Range {")
+			fmt.Println("var Properties = map[string] *RangeTable{")
 		} else {
 			fmt.Println("// Scripts is the set of Unicode script tables.")
-			fmt.Println("var Scripts = map[string] []Range {")
+			fmt.Println("var Scripts = map[string] *RangeTable{")
 		}
 		for k := range table {
 			fmt.Printf("\t%q: %s,\n", k, k)
@@ -613,11 +645,15 @@ func printScriptOrProperty(doProps bool) {
 				name, name, name, name)
 		}
 		ndecl++
-		fmt.Printf("var _%s = []Range {\n", name)
+		fmt.Printf("var _%s = &RangeTable {\n", name)
+		fmt.Print("\tR16: []Range16{\n")
 		ranges := foldAdjacent(table[name])
+		size := 16
+		count := &range16Count
 		for _, s := range ranges {
-			fmt.Printf(format, s.Lo, s.Hi, s.Stride)
+			size, count = printRange(s.Lo, s.Hi, s.Stride, size, count)
 		}
+		fmt.Print("\t},\n")
 		fmt.Print("}\n\n")
 	}
 	decl.Sort()
@@ -808,7 +844,7 @@ func printCaseRange(lo, hi *caseState) {
 		fmt.Printf("\t{0x%04X, 0x%04X, d{UpperLower, UpperLower, UpperLower}},\n",
 			lo.point, hi.point)
 	case hi.point > lo.point && lo.isLowerUpper():
-		logger.Fatalf("LowerUpper sequence: should not happen: U+%04X.  If it's real, need to fix To()", lo.point)
+		logger.Fatalf("LowerUpper sequence: should not happen: %U.  If it's real, need to fix To()", lo.point)
 		fmt.Printf("\t{0x%04X, 0x%04X, d{LowerUpper, LowerUpper, LowerUpper}},\n",
 			lo.point, hi.point)
 	default:
@@ -831,17 +867,31 @@ func fullCaseTest() {
 		lower := unicode.ToLower(i)
 		want := caseIt(i, c.lowerCase)
 		if lower != want {
-			fmt.Fprintf(os.Stderr, "lower U+%04X should be U+%04X is U+%04X\n", i, want, lower)
+			fmt.Fprintf(os.Stderr, "lower %U should be %U is %U\n", i, want, lower)
 		}
 		upper := unicode.ToUpper(i)
 		want = caseIt(i, c.upperCase)
 		if upper != want {
-			fmt.Fprintf(os.Stderr, "upper U+%04X should be U+%04X is U+%04X\n", i, want, upper)
+			fmt.Fprintf(os.Stderr, "upper %U should be %U is %U\n", i, want, upper)
 		}
 		title := unicode.ToTitle(i)
 		want = caseIt(i, c.titleCase)
 		if title != want {
-			fmt.Fprintf(os.Stderr, "title U+%04X should be U+%04X is U+%04X\n", i, want, title)
+			fmt.Fprintf(os.Stderr, "title %U should be %U is %U\n", i, want, title)
 		}
 	}
 }
+
+var range16Count = 0 // Number of entries in the 16-bit range tables.
+var range32Count = 0 // Number of entries in the 32-bit range tables.
+
+func printSizes() {
+	if *test {
+		return
+	}
+	fmt.Println()
+	fmt.Printf("// Range entries: %d 16-bit, %d 32-bit, %d total.\n", range16Count, range32Count, range16Count+range32Count)
+	range16Bytes := range16Count * 3 * 2
+	range32Bytes := range32Count * 3 * 4
+	fmt.Printf("// Range bytes: %d 16-bit, %d 32-bit, %d total.\n", range16Bytes, range32Bytes, range16Bytes+range32Bytes)
+}
diff --git a/src/pkg/unicode/tables.go b/src/pkg/unicode/tables.go
index 89fd994..fc2bdd8 100644
--- a/src/pkg/unicode/tables.go
+++ b/src/pkg/unicode/tables.go
@@ -8,7 +8,7 @@ package unicode
 const Version = "6.0.0"
 
 // Categories is the set of Unicode data tables.
-var Categories = map[string][]Range{
+var Categories = map[string]*RangeTable{
 	"Lm":     Lm,
 	"Ll":     Ll,
 	"Me":     Me,
@@ -41,1939 +41,2030 @@ var Categories = map[string][]Range{
 	"Lo":     Lo,
 }
 
-var _Lm = []Range{
-	{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 = []Range{
-	{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},
-	{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 _Me = []Range{
-	{0x0488, 0x0489, 1},
-	{0x20dd, 0x20e0, 1},
-	{0x20e2, 0x20e4, 1},
-	{0xa670, 0xa672, 1},
-}
-
-var _Mc = []Range{
-	{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, 0x11000, 25620},
-	{0x11002, 0x11082, 128},
-	{0x110b0, 0x110b2, 1},
-	{0x110b7, 0x110b8, 1},
-	{0x1d165, 0x1d166, 1},
-	{0x1d16d, 0x1d172, 1},
-}
-
-var _Mn = []Range{
-	{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},
-	{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 = []Range{
-	{0x2028, 0x2028, 1},
-}
-
-var letter = []Range{
-	{0x0041, 0x005a, 1},
-	{0x0061, 0x007a, 1},
-	{0x00aa, 0x00b5, 11},
-	{0x00ba, 0x00c0, 6},
-	{0x00c1, 0x00d6, 1},
-	{0x00d8, 0x00f6, 1},
-	{0x00f8, 0x02c1, 1},
-	{0x02c6, 0x02d1, 1},
-	{0x02e0, 0x02e4, 1},
-	{0x02ec, 0x02ee, 2},
-	{0x0370, 0x0374, 1},
-	{0x0376, 0x0377, 1},
-	{0x037a, 0x037d, 1},
-	{0x0386, 0x0388, 2},
-	{0x0389, 0x038a, 1},
-	{0x038c, 0x038e, 2},
-	{0x038f, 0x03a1, 1},
-	{0x03a3, 0x03f5, 1},
-	{0x03f7, 0x0481, 1},
-	{0x048a, 0x0527, 1},
-	{0x0531, 0x0556, 1},
-	{0x0559, 0x0561, 8},
-	{0x0562, 0x0587, 1},
-	{0x05d0, 0x05ea, 1},
-	{0x05f0, 0x05f2, 1},
-	{0x0620, 0x064a, 1},
-	{0x066e, 0x066f, 1},
-	{0x0671, 0x06d3, 1},
-	{0x06d5, 0x06e5, 16},
-	{0x06e6, 0x06ee, 8},
-	{0x06ef, 0x06fa, 11},
-	{0x06fb, 0x06fc, 1},
-	{0x06ff, 0x0710, 17},
-	{0x0712, 0x072f, 1},
-	{0x074d, 0x07a5, 1},
-	{0x07b1, 0x07ca, 25},
-	{0x07cb, 0x07ea, 1},
-	{0x07f4, 0x07f5, 1},
-	{0x07fa, 0x0800, 6},
-	{0x0801, 0x0815, 1},
-	{0x081a, 0x0824, 10},
-	{0x0828, 0x0840, 24},
-	{0x0841, 0x0858, 1},
-	{0x0904, 0x0939, 1},
-	{0x093d, 0x0950, 19},
-	{0x0958, 0x0961, 1},
-	{0x0971, 0x0977, 1},
-	{0x0979, 0x097f, 1},
-	{0x0985, 0x098c, 1},
-	{0x098f, 0x0990, 1},
-	{0x0993, 0x09a8, 1},
-	{0x09aa, 0x09b0, 1},
-	{0x09b2, 0x09b6, 4},
-	{0x09b7, 0x09b9, 1},
-	{0x09bd, 0x09ce, 17},
-	{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, 0x0a72, 20},
-	{0x0a73, 0x0a74, 1},
-	{0x0a85, 0x0a8d, 1},
-	{0x0a8f, 0x0a91, 1},
-	{0x0a93, 0x0aa8, 1},
-	{0x0aaa, 0x0ab0, 1},
-	{0x0ab2, 0x0ab3, 1},
-	{0x0ab5, 0x0ab9, 1},
-	{0x0abd, 0x0ad0, 19},
-	{0x0ae0, 0x0ae1, 1},
-	{0x0b05, 0x0b0c, 1},
-	{0x0b0f, 0x0b10, 1},
-	{0x0b13, 0x0b28, 1},
-	{0x0b2a, 0x0b30, 1},
-	{0x0b32, 0x0b33, 1},
-	{0x0b35, 0x0b39, 1},
-	{0x0b3d, 0x0b5c, 31},
-	{0x0b5d, 0x0b5f, 2},
-	{0x0b60, 0x0b61, 1},
-	{0x0b71, 0x0b83, 18},
-	{0x0b85, 0x0b8a, 1},
-	{0x0b8e, 0x0b90, 1},
-	{0x0b92, 0x0b95, 1},
-	{0x0b99, 0x0b9a, 1},
-	{0x0b9c, 0x0b9e, 2},
-	{0x0b9f, 0x0ba3, 4},
-	{0x0ba4, 0x0ba8, 4},
-	{0x0ba9, 0x0baa, 1},
-	{0x0bae, 0x0bb9, 1},
-	{0x0bd0, 0x0c05, 53},
-	{0x0c06, 0x0c0c, 1},
-	{0x0c0e, 0x0c10, 1},
-	{0x0c12, 0x0c28, 1},
-	{0x0c2a, 0x0c33, 1},
-	{0x0c35, 0x0c39, 1},
-	{0x0c3d, 0x0c58, 27},
-	{0x0c59, 0x0c60, 7},
-	{0x0c61, 0x0c85, 36},
-	{0x0c86, 0x0c8c, 1},
-	{0x0c8e, 0x0c90, 1},
-	{0x0c92, 0x0ca8, 1},
-	{0x0caa, 0x0cb3, 1},
-	{0x0cb5, 0x0cb9, 1},
-	{0x0cbd, 0x0cde, 33},
-	{0x0ce0, 0x0ce1, 1},
-	{0x0cf1, 0x0cf2, 1},
-	{0x0d05, 0x0d0c, 1},
-	{0x0d0e, 0x0d10, 1},
-	{0x0d12, 0x0d3a, 1},
-	{0x0d3d, 0x0d4e, 17},
-	{0x0d60, 0x0d61, 1},
-	{0x0d7a, 0x0d7f, 1},
-	{0x0d85, 0x0d96, 1},
-	{0x0d9a, 0x0db1, 1},
-	{0x0db3, 0x0dbb, 1},
-	{0x0dbd, 0x0dc0, 3},
-	{0x0dc1, 0x0dc6, 1},
-	{0x0e01, 0x0e30, 1},
-	{0x0e32, 0x0e33, 1},
-	{0x0e40, 0x0e46, 1},
-	{0x0e81, 0x0e82, 1},
-	{0x0e84, 0x0e87, 3},
-	{0x0e88, 0x0e8a, 2},
-	{0x0e8d, 0x0e94, 7},
-	{0x0e95, 0x0e97, 1},
-	{0x0e99, 0x0e9f, 1},
-	{0x0ea1, 0x0ea3, 1},
-	{0x0ea5, 0x0ea7, 2},
-	{0x0eaa, 0x0eab, 1},
-	{0x0ead, 0x0eb0, 1},
-	{0x0eb2, 0x0eb3, 1},
-	{0x0ebd, 0x0ec0, 3},
-	{0x0ec1, 0x0ec4, 1},
-	{0x0ec6, 0x0edc, 22},
-	{0x0edd, 0x0f00, 35},
-	{0x0f40, 0x0f47, 1},
-	{0x0f49, 0x0f6c, 1},
-	{0x0f88, 0x0f8c, 1},
-	{0x1000, 0x102a, 1},
-	{0x103f, 0x1050, 17},
-	{0x1051, 0x1055, 1},
-	{0x105a, 0x105d, 1},
-	{0x1061, 0x1065, 4},
-	{0x1066, 0x106e, 8},
-	{0x106f, 0x1070, 1},
-	{0x1075, 0x1081, 1},
-	{0x108e, 0x10a0, 18},
-	{0x10a1, 0x10c5, 1},
-	{0x10d0, 0x10fa, 1},
-	{0x10fc, 0x1100, 4},
-	{0x1101, 0x1248, 1},
-	{0x124a, 0x124d, 1},
-	{0x1250, 0x1256, 1},
-	{0x1258, 0x125a, 2},
-	{0x125b, 0x125d, 1},
-	{0x1260, 0x1288, 1},
-	{0x128a, 0x128d, 1},
-	{0x1290, 0x12b0, 1},
-	{0x12b2, 0x12b5, 1},
-	{0x12b8, 0x12be, 1},
-	{0x12c0, 0x12c2, 2},
-	{0x12c3, 0x12c5, 1},
-	{0x12c8, 0x12d6, 1},
-	{0x12d8, 0x1310, 1},
-	{0x1312, 0x1315, 1},
-	{0x1318, 0x135a, 1},
-	{0x1380, 0x138f, 1},
-	{0x13a0, 0x13f4, 1},
-	{0x1401, 0x166c, 1},
-	{0x166f, 0x167f, 1},
-	{0x1681, 0x169a, 1},
-	{0x16a0, 0x16ea, 1},
-	{0x1700, 0x170c, 1},
-	{0x170e, 0x1711, 1},
-	{0x1720, 0x1731, 1},
-	{0x1740, 0x1751, 1},
-	{0x1760, 0x176c, 1},
-	{0x176e, 0x1770, 1},
-	{0x1780, 0x17b3, 1},
-	{0x17d7, 0x17dc, 5},
-	{0x1820, 0x1877, 1},
-	{0x1880, 0x18a8, 1},
-	{0x18aa, 0x18b0, 6},
-	{0x18b1, 0x18f5, 1},
-	{0x1900, 0x191c, 1},
-	{0x1950, 0x196d, 1},
-	{0x1970, 0x1974, 1},
-	{0x1980, 0x19ab, 1},
-	{0x19c1, 0x19c7, 1},
-	{0x1a00, 0x1a16, 1},
-	{0x1a20, 0x1a54, 1},
-	{0x1aa7, 0x1b05, 94},
-	{0x1b06, 0x1b33, 1},
-	{0x1b45, 0x1b4b, 1},
-	{0x1b83, 0x1ba0, 1},
-	{0x1bae, 0x1baf, 1},
-	{0x1bc0, 0x1be5, 1},
-	{0x1c00, 0x1c23, 1},
-	{0x1c4d, 0x1c4f, 1},
-	{0x1c5a, 0x1c7d, 1},
-	{0x1ce9, 0x1cec, 1},
-	{0x1cee, 0x1cf1, 1},
-	{0x1d00, 0x1dbf, 1},
-	{0x1e00, 0x1f15, 1},
-	{0x1f18, 0x1f1d, 1},
-	{0x1f20, 0x1f45, 1},
-	{0x1f48, 0x1f4d, 1},
-	{0x1f50, 0x1f57, 1},
-	{0x1f59, 0x1f5f, 2},
-	{0x1f60, 0x1f7d, 1},
-	{0x1f80, 0x1fb4, 1},
-	{0x1fb6, 0x1fbc, 1},
-	{0x1fbe, 0x1fc2, 4},
-	{0x1fc3, 0x1fc4, 1},
-	{0x1fc6, 0x1fcc, 1},
-	{0x1fd0, 0x1fd3, 1},
-	{0x1fd6, 0x1fdb, 1},
-	{0x1fe0, 0x1fec, 1},
-	{0x1ff2, 0x1ff4, 1},
-	{0x1ff6, 0x1ffc, 1},
-	{0x2071, 0x207f, 14},
-	{0x2090, 0x209c, 1},
-	{0x2102, 0x2107, 5},
-	{0x210a, 0x2113, 1},
-	{0x2115, 0x2119, 4},
-	{0x211a, 0x211d, 1},
-	{0x2124, 0x212a, 2},
-	{0x212b, 0x212d, 1},
-	{0x212f, 0x2139, 1},
-	{0x213c, 0x213f, 1},
-	{0x2145, 0x2149, 1},
-	{0x214e, 0x2183, 53},
-	{0x2184, 0x2c00, 2684},
-	{0x2c01, 0x2c2e, 1},
-	{0x2c30, 0x2c5e, 1},
-	{0x2c60, 0x2ce4, 1},
-	{0x2ceb, 0x2cee, 1},
-	{0x2d00, 0x2d25, 1},
-	{0x2d30, 0x2d65, 1},
-	{0x2d6f, 0x2d80, 17},
-	{0x2d81, 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},
-	{0x2e2f, 0x3005, 470},
-	{0x3006, 0x3031, 43},
-	{0x3032, 0x3035, 1},
-	{0x303b, 0x303c, 1},
-	{0x3041, 0x3096, 1},
-	{0x309d, 0x309f, 1},
-	{0x30a1, 0x30fa, 1},
-	{0x30fc, 0x30ff, 1},
-	{0x3105, 0x312d, 1},
-	{0x3131, 0x318e, 1},
-	{0x31a0, 0x31ba, 1},
-	{0x31f0, 0x31ff, 1},
-	{0x3400, 0x4db5, 1},
-	{0x4e00, 0x9fcb, 1},
-	{0xa000, 0xa48c, 1},
-	{0xa4d0, 0xa4fd, 1},
-	{0xa500, 0xa60c, 1},
-	{0xa610, 0xa61f, 1},
-	{0xa62a, 0xa62b, 1},
-	{0xa640, 0xa66e, 1},
-	{0xa67f, 0xa697, 1},
-	{0xa6a0, 0xa6e5, 1},
-	{0xa717, 0xa71f, 1},
-	{0xa722, 0xa788, 1},
-	{0xa78b, 0xa78e, 1},
-	{0xa790, 0xa791, 1},
-	{0xa7a0, 0xa7a9, 1},
-	{0xa7fa, 0xa801, 1},
-	{0xa803, 0xa805, 1},
-	{0xa807, 0xa80a, 1},
-	{0xa80c, 0xa822, 1},
-	{0xa840, 0xa873, 1},
-	{0xa882, 0xa8b3, 1},
-	{0xa8f2, 0xa8f7, 1},
-	{0xa8fb, 0xa90a, 15},
-	{0xa90b, 0xa925, 1},
-	{0xa930, 0xa946, 1},
-	{0xa960, 0xa97c, 1},
-	{0xa984, 0xa9b2, 1},
-	{0xa9cf, 0xaa00, 49},
-	{0xaa01, 0xaa28, 1},
-	{0xaa40, 0xaa42, 1},
-	{0xaa44, 0xaa4b, 1},
-	{0xaa60, 0xaa76, 1},
-	{0xaa7a, 0xaa80, 6},
-	{0xaa81, 0xaaaf, 1},
-	{0xaab1, 0xaab5, 4},
-	{0xaab6, 0xaab9, 3},
-	{0xaaba, 0xaabd, 1},
-	{0xaac0, 0xaac2, 2},
-	{0xaadb, 0xaadd, 1},
-	{0xab01, 0xab06, 1},
-	{0xab09, 0xab0e, 1},
-	{0xab11, 0xab16, 1},
-	{0xab20, 0xab26, 1},
-	{0xab28, 0xab2e, 1},
-	{0xabc0, 0xabe2, 1},
-	{0xac00, 0xd7a3, 1},
-	{0xd7b0, 0xd7c6, 1},
-	{0xd7cb, 0xd7fb, 1},
-	{0xf900, 0xfa2d, 1},
-	{0xfa30, 0xfa6d, 1},
-	{0xfa70, 0xfad9, 1},
-	{0xfb00, 0xfb06, 1},
-	{0xfb13, 0xfb17, 1},
-	{0xfb1d, 0xfb1f, 2},
-	{0xfb20, 0xfb28, 1},
-	{0xfb2a, 0xfb36, 1},
-	{0xfb38, 0xfb3c, 1},
-	{0xfb3e, 0xfb40, 2},
-	{0xfb41, 0xfb43, 2},
-	{0xfb44, 0xfb46, 2},
-	{0xfb47, 0xfbb1, 1},
-	{0xfbd3, 0xfd3d, 1},
-	{0xfd50, 0xfd8f, 1},
-	{0xfd92, 0xfdc7, 1},
-	{0xfdf0, 0xfdfb, 1},
-	{0xfe70, 0xfe74, 1},
-	{0xfe76, 0xfefc, 1},
-	{0xff21, 0xff3a, 1},
-	{0xff41, 0xff5a, 1},
-	{0xff66, 0xffbe, 1},
-	{0xffc2, 0xffc7, 1},
-	{0xffca, 0xffcf, 1},
-	{0xffd2, 0xffd7, 1},
-	{0xffda, 0xffdc, 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},
-	{0x10400, 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},
-	{0x1d400, 0x1d454, 1},
-	{0x1d456, 0x1d49c, 1},
-	{0x1d49e, 0x1d49f, 1},
-	{0x1d4a2, 0x1d4a5, 3},
-	{0x1d4a6, 0x1d4a9, 3},
-	{0x1d4aa, 0x1d4ac, 1},
-	{0x1d4ae, 0x1d4b9, 1},
-	{0x1d4bb, 0x1d4bd, 2},
-	{0x1d4be, 0x1d4c3, 1},
-	{0x1d4c5, 0x1d505, 1},
-	{0x1d507, 0x1d50a, 1},
-	{0x1d50d, 0x1d514, 1},
-	{0x1d516, 0x1d51c, 1},
-	{0x1d51e, 0x1d539, 1},
-	{0x1d53b, 0x1d53e, 1},
-	{0x1d540, 0x1d544, 1},
-	{0x1d546, 0x1d54a, 4},
-	{0x1d54b, 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},
-	{0x20000, 0x2a6d6, 1},
-	{0x2a700, 0x2b734, 1},
-	{0x2b740, 0x2b81d, 1},
-	{0x2f800, 0x2fa1d, 1},
-}
-
-var _Zp = []Range{
-	{0x2029, 0x2029, 1},
-}
-
-var _Zs = []Range{
-	{0x0020, 0x00a0, 128},
-	{0x1680, 0x180e, 398},
-	{0x2000, 0x200a, 1},
-	{0x202f, 0x205f, 48},
-	{0x3000, 0x3000, 1},
-}
-
-var _Cs = []Range{
-	{0xd800, 0xdfff, 1},
-}
-
-var _Co = []Range{
-	{0xe000, 0xf8ff, 1},
-	{0xf0000, 0xffffd, 1},
-	{0x100000, 0x10fffd, 1},
-}
-
-var _Cf = []Range{
-	{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},
-	{0x110bd, 0x1d173, 49334},
-	{0x1d174, 0x1d17a, 1},
-	{0xe0001, 0xe0020, 31},
-	{0xe0021, 0xe007f, 1},
-}
-
-var _Cc = []Range{
-	{0x0001, 0x001f, 1},
-	{0x007f, 0x009f, 1},
-}
-
-var _Po = []Range{
-	{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, 0x10100, 411},
-	{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 = []Range{
-	{0x00ab, 0x2018, 8045},
-	{0x201b, 0x201c, 1},
-	{0x201f, 0x2039, 26},
-	{0x2e02, 0x2e04, 2},
-	{0x2e09, 0x2e0c, 3},
-	{0x2e1c, 0x2e20, 4},
-}
-
-var _Pf = []Range{
-	{0x00bb, 0x2019, 8030},
-	{0x201d, 0x203a, 29},
-	{0x2e03, 0x2e05, 2},
-	{0x2e0a, 0x2e0d, 3},
-	{0x2e1d, 0x2e21, 4},
-}
-
-var _Pe = []Range{
-	{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 = []Range{
-	{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 = []Range{
-	{0x005f, 0x203f, 8160},
-	{0x2040, 0x2054, 20},
-	{0xfe33, 0xfe34, 1},
-	{0xfe4d, 0xfe4f, 1},
-	{0xff3f, 0xff3f, 1},
-}
-
-var _Ps = []Range{
-	{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 = []Range{
-	{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},
-	{0x104a0, 0x104a9, 1},
-	{0x11066, 0x1106f, 1},
-	{0x1d7ce, 0x1d7ff, 1},
-}
-
-var _Nl = []Range{
-	{0x16ee, 0x16f0, 1},
-	{0x2160, 0x2182, 1},
-	{0x2185, 0x2188, 1},
-	{0x3007, 0x3021, 26},
-	{0x3022, 0x3029, 1},
-	{0x3038, 0x303a, 1},
-	{0xa6e6, 0xa6ef, 1},
-	{0x10140, 0x10174, 1},
-	{0x10341, 0x1034a, 9},
-	{0x103d1, 0x103d5, 1},
-	{0x12400, 0x12462, 1},
-}
-
-var _No = []Range{
-	{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},
-	{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 = []Range{
-	{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, 0x10102, 261},
-	{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 = []Range{
-	{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},
-	{0x1d6c1, 0x1d6db, 26},
-	{0x1d6fb, 0x1d715, 26},
-	{0x1d735, 0x1d74f, 26},
-	{0x1d76f, 0x1d789, 26},
-	{0x1d7a9, 0x1d7c3, 26},
-}
-
-var _Sk = []Range{
-	{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 = []Range{
-	{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 = []Range{
-	{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},
-	{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 = []Range{
-	{0x01c5, 0x01cb, 3},
-	{0x01f2, 0x1f88, 7574},
-	{0x1f89, 0x1f8f, 1},
-	{0x1f98, 0x1f9f, 1},
-	{0x1fa8, 0x1faf, 1},
-	{0x1fbc, 0x1fcc, 16},
-	{0x1ffc, 0x1ffc, 1},
-}
-
-var _Lo = []Range{
-	{0x01bb, 0x01c0, 5},
-	{0x01c1, 0x01c3, 1},
-	{0x0294, 0x05d0, 828},
-	{0x05d1, 0x05ea, 1},
-	{0x05f0, 0x05f2, 1},
-	{0x0620, 0x063f, 1},
-	{0x0641, 0x064a, 1},
-	{0x066e, 0x066f, 1},
-	{0x0671, 0x06d3, 1},
-	{0x06d5, 0x06ee, 25},
-	{0x06ef, 0x06fa, 11},
-	{0x06fb, 0x06fc, 1},
-	{0x06ff, 0x0710, 17},
-	{0x0712, 0x072f, 1},
-	{0x074d, 0x07a5, 1},
-	{0x07b1, 0x07ca, 25},
-	{0x07cb, 0x07ea, 1},
-	{0x0800, 0x0815, 1},
-	{0x0840, 0x0858, 1},
-	{0x0904, 0x0939, 1},
-	{0x093d, 0x0950, 19},
-	{0x0958, 0x0961, 1},
-	{0x0972, 0x0977, 1},
-	{0x0979, 0x097f, 1},
-	{0x0985, 0x098c, 1},
-	{0x098f, 0x0990, 1},
-	{0x0993, 0x09a8, 1},
-	{0x09aa, 0x09b0, 1},
-	{0x09b2, 0x09b6, 4},
-	{0x09b7, 0x09b9, 1},
-	{0x09bd, 0x09ce, 17},
-	{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, 0x0a72, 20},
-	{0x0a73, 0x0a74, 1},
-	{0x0a85, 0x0a8d, 1},
-	{0x0a8f, 0x0a91, 1},
-	{0x0a93, 0x0aa8, 1},
-	{0x0aaa, 0x0ab0, 1},
-	{0x0ab2, 0x0ab3, 1},
-	{0x0ab5, 0x0ab9, 1},
-	{0x0abd, 0x0ad0, 19},
-	{0x0ae0, 0x0ae1, 1},
-	{0x0b05, 0x0b0c, 1},
-	{0x0b0f, 0x0b10, 1},
-	{0x0b13, 0x0b28, 1},
-	{0x0b2a, 0x0b30, 1},
-	{0x0b32, 0x0b33, 1},
-	{0x0b35, 0x0b39, 1},
-	{0x0b3d, 0x0b5c, 31},
-	{0x0b5d, 0x0b5f, 2},
-	{0x0b60, 0x0b61, 1},
-	{0x0b71, 0x0b83, 18},
-	{0x0b85, 0x0b8a, 1},
-	{0x0b8e, 0x0b90, 1},
-	{0x0b92, 0x0b95, 1},
-	{0x0b99, 0x0b9a, 1},
-	{0x0b9c, 0x0b9e, 2},
-	{0x0b9f, 0x0ba3, 4},
-	{0x0ba4, 0x0ba8, 4},
-	{0x0ba9, 0x0baa, 1},
-	{0x0bae, 0x0bb9, 1},
-	{0x0bd0, 0x0c05, 53},
-	{0x0c06, 0x0c0c, 1},
-	{0x0c0e, 0x0c10, 1},
-	{0x0c12, 0x0c28, 1},
-	{0x0c2a, 0x0c33, 1},
-	{0x0c35, 0x0c39, 1},
-	{0x0c3d, 0x0c58, 27},
-	{0x0c59, 0x0c60, 7},
-	{0x0c61, 0x0c85, 36},
-	{0x0c86, 0x0c8c, 1},
-	{0x0c8e, 0x0c90, 1},
-	{0x0c92, 0x0ca8, 1},
-	{0x0caa, 0x0cb3, 1},
-	{0x0cb5, 0x0cb9, 1},
-	{0x0cbd, 0x0cde, 33},
-	{0x0ce0, 0x0ce1, 1},
-	{0x0cf1, 0x0cf2, 1},
-	{0x0d05, 0x0d0c, 1},
-	{0x0d0e, 0x0d10, 1},
-	{0x0d12, 0x0d3a, 1},
-	{0x0d3d, 0x0d4e, 17},
-	{0x0d60, 0x0d61, 1},
-	{0x0d7a, 0x0d7f, 1},
-	{0x0d85, 0x0d96, 1},
-	{0x0d9a, 0x0db1, 1},
-	{0x0db3, 0x0dbb, 1},
-	{0x0dbd, 0x0dc0, 3},
-	{0x0dc1, 0x0dc6, 1},
-	{0x0e01, 0x0e30, 1},
-	{0x0e32, 0x0e33, 1},
-	{0x0e40, 0x0e45, 1},
-	{0x0e81, 0x0e82, 1},
-	{0x0e84, 0x0e87, 3},
-	{0x0e88, 0x0e8a, 2},
-	{0x0e8d, 0x0e94, 7},
-	{0x0e95, 0x0e97, 1},
-	{0x0e99, 0x0e9f, 1},
-	{0x0ea1, 0x0ea3, 1},
-	{0x0ea5, 0x0ea7, 2},
-	{0x0eaa, 0x0eab, 1},
-	{0x0ead, 0x0eb0, 1},
-	{0x0eb2, 0x0eb3, 1},
-	{0x0ebd, 0x0ec0, 3},
-	{0x0ec1, 0x0ec4, 1},
-	{0x0edc, 0x0edd, 1},
-	{0x0f00, 0x0f40, 64},
-	{0x0f41, 0x0f47, 1},
-	{0x0f49, 0x0f6c, 1},
-	{0x0f88, 0x0f8c, 1},
-	{0x1000, 0x102a, 1},
-	{0x103f, 0x1050, 17},
-	{0x1051, 0x1055, 1},
-	{0x105a, 0x105d, 1},
-	{0x1061, 0x1065, 4},
-	{0x1066, 0x106e, 8},
-	{0x106f, 0x1070, 1},
-	{0x1075, 0x1081, 1},
-	{0x108e, 0x10d0, 66},
-	{0x10d1, 0x10fa, 1},
-	{0x1100, 0x1248, 1},
-	{0x124a, 0x124d, 1},
-	{0x1250, 0x1256, 1},
-	{0x1258, 0x125a, 2},
-	{0x125b, 0x125d, 1},
-	{0x1260, 0x1288, 1},
-	{0x128a, 0x128d, 1},
-	{0x1290, 0x12b0, 1},
-	{0x12b2, 0x12b5, 1},
-	{0x12b8, 0x12be, 1},
-	{0x12c0, 0x12c2, 2},
-	{0x12c3, 0x12c5, 1},
-	{0x12c8, 0x12d6, 1},
-	{0x12d8, 0x1310, 1},
-	{0x1312, 0x1315, 1},
-	{0x1318, 0x135a, 1},
-	{0x1380, 0x138f, 1},
-	{0x13a0, 0x13f4, 1},
-	{0x1401, 0x166c, 1},
-	{0x166f, 0x167f, 1},
-	{0x1681, 0x169a, 1},
-	{0x16a0, 0x16ea, 1},
-	{0x1700, 0x170c, 1},
-	{0x170e, 0x1711, 1},
-	{0x1720, 0x1731, 1},
-	{0x1740, 0x1751, 1},
-	{0x1760, 0x176c, 1},
-	{0x176e, 0x1770, 1},
-	{0x1780, 0x17b3, 1},
-	{0x17dc, 0x1820, 68},
-	{0x1821, 0x1842, 1},
-	{0x1844, 0x1877, 1},
-	{0x1880, 0x18a8, 1},
-	{0x18aa, 0x18b0, 6},
-	{0x18b1, 0x18f5, 1},
-	{0x1900, 0x191c, 1},
-	{0x1950, 0x196d, 1},
-	{0x1970, 0x1974, 1},
-	{0x1980, 0x19ab, 1},
-	{0x19c1, 0x19c7, 1},
-	{0x1a00, 0x1a16, 1},
-	{0x1a20, 0x1a54, 1},
-	{0x1b05, 0x1b33, 1},
-	{0x1b45, 0x1b4b, 1},
-	{0x1b83, 0x1ba0, 1},
-	{0x1bae, 0x1baf, 1},
-	{0x1bc0, 0x1be5, 1},
-	{0x1c00, 0x1c23, 1},
-	{0x1c4d, 0x1c4f, 1},
-	{0x1c5a, 0x1c77, 1},
-	{0x1ce9, 0x1cec, 1},
-	{0x1cee, 0x1cf1, 1},
-	{0x2135, 0x2138, 1},
-	{0x2d30, 0x2d65, 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},
-	{0x3006, 0x303c, 54},
-	{0x3041, 0x3096, 1},
-	{0x309f, 0x30a1, 2},
-	{0x30a2, 0x30fa, 1},
-	{0x30ff, 0x3105, 6},
-	{0x3106, 0x312d, 1},
-	{0x3131, 0x318e, 1},
-	{0x31a0, 0x31ba, 1},
-	{0x31f0, 0x31ff, 1},
-	{0x3400, 0x4db5, 1},
-	{0x4e00, 0x9fcb, 1},
-	{0xa000, 0xa014, 1},
-	{0xa016, 0xa48c, 1},
-	{0xa4d0, 0xa4f7, 1},
-	{0xa500, 0xa60b, 1},
-	{0xa610, 0xa61f, 1},
-	{0xa62a, 0xa62b, 1},
-	{0xa66e, 0xa6a0, 50},
-	{0xa6a1, 0xa6e5, 1},
-	{0xa7fb, 0xa801, 1},
-	{0xa803, 0xa805, 1},
-	{0xa807, 0xa80a, 1},
-	{0xa80c, 0xa822, 1},
-	{0xa840, 0xa873, 1},
-	{0xa882, 0xa8b3, 1},
-	{0xa8f2, 0xa8f7, 1},
-	{0xa8fb, 0xa90a, 15},
-	{0xa90b, 0xa925, 1},
-	{0xa930, 0xa946, 1},
-	{0xa960, 0xa97c, 1},
-	{0xa984, 0xa9b2, 1},
-	{0xaa00, 0xaa28, 1},
-	{0xaa40, 0xaa42, 1},
-	{0xaa44, 0xaa4b, 1},
-	{0xaa60, 0xaa6f, 1},
-	{0xaa71, 0xaa76, 1},
-	{0xaa7a, 0xaa80, 6},
-	{0xaa81, 0xaaaf, 1},
-	{0xaab1, 0xaab5, 4},
-	{0xaab6, 0xaab9, 3},
-	{0xaaba, 0xaabd, 1},
-	{0xaac0, 0xaac2, 2},
-	{0xaadb, 0xaadc, 1},
-	{0xab01, 0xab06, 1},
-	{0xab09, 0xab0e, 1},
-	{0xab11, 0xab16, 1},
-	{0xab20, 0xab26, 1},
-	{0xab28, 0xab2e, 1},
-	{0xabc0, 0xabe2, 1},
-	{0xac00, 0xd7a3, 1},
-	{0xd7b0, 0xd7c6, 1},
-	{0xd7cb, 0xd7fb, 1},
-	{0xf900, 0xfa2d, 1},
-	{0xfa30, 0xfa6d, 1},
-	{0xfa70, 0xfad9, 1},
-	{0xfb1d, 0xfb1f, 2},
-	{0xfb20, 0xfb28, 1},
-	{0xfb2a, 0xfb36, 1},
-	{0xfb38, 0xfb3c, 1},
-	{0xfb3e, 0xfb40, 2},
-	{0xfb41, 0xfb43, 2},
-	{0xfb44, 0xfb46, 2},
-	{0xfb47, 0xfbb1, 1},
-	{0xfbd3, 0xfd3d, 1},
-	{0xfd50, 0xfd8f, 1},
-	{0xfd92, 0xfdc7, 1},
-	{0xfdf0, 0xfdfb, 1},
-	{0xfe70, 0xfe74, 1},
-	{0xfe76, 0xfefc, 1},
-	{0xff66, 0xff6f, 1},
-	{0xff71, 0xff9d, 1},
-	{0xffa0, 0xffbe, 1},
-	{0xffc2, 0xffc7, 1},
-	{0xffca, 0xffcf, 1},
-	{0xffd2, 0xffd7, 1},
-	{0xffda, 0xffdc, 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 _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 _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 letter = &RangeTable{
+	R16: []Range16{
+		{0x0041, 0x005a, 1},
+		{0x0061, 0x007a, 1},
+		{0x00aa, 0x00b5, 11},
+		{0x00ba, 0x00c0, 6},
+		{0x00c1, 0x00d6, 1},
+		{0x00d8, 0x00f6, 1},
+		{0x00f8, 0x02c1, 1},
+		{0x02c6, 0x02d1, 1},
+		{0x02e0, 0x02e4, 1},
+		{0x02ec, 0x02ee, 2},
+		{0x0370, 0x0374, 1},
+		{0x0376, 0x0377, 1},
+		{0x037a, 0x037d, 1},
+		{0x0386, 0x0388, 2},
+		{0x0389, 0x038a, 1},
+		{0x038c, 0x038e, 2},
+		{0x038f, 0x03a1, 1},
+		{0x03a3, 0x03f5, 1},
+		{0x03f7, 0x0481, 1},
+		{0x048a, 0x0527, 1},
+		{0x0531, 0x0556, 1},
+		{0x0559, 0x0561, 8},
+		{0x0562, 0x0587, 1},
+		{0x05d0, 0x05ea, 1},
+		{0x05f0, 0x05f2, 1},
+		{0x0620, 0x064a, 1},
+		{0x066e, 0x066f, 1},
+		{0x0671, 0x06d3, 1},
+		{0x06d5, 0x06e5, 16},
+		{0x06e6, 0x06ee, 8},
+		{0x06ef, 0x06fa, 11},
+		{0x06fb, 0x06fc, 1},
+		{0x06ff, 0x0710, 17},
+		{0x0712, 0x072f, 1},
+		{0x074d, 0x07a5, 1},
+		{0x07b1, 0x07ca, 25},
+		{0x07cb, 0x07ea, 1},
+		{0x07f4, 0x07f5, 1},
+		{0x07fa, 0x0800, 6},
+		{0x0801, 0x0815, 1},
+		{0x081a, 0x0824, 10},
+		{0x0828, 0x0840, 24},
+		{0x0841, 0x0858, 1},
+		{0x0904, 0x0939, 1},
+		{0x093d, 0x0950, 19},
+		{0x0958, 0x0961, 1},
+		{0x0971, 0x0977, 1},
+		{0x0979, 0x097f, 1},
+		{0x0985, 0x098c, 1},
+		{0x098f, 0x0990, 1},
+		{0x0993, 0x09a8, 1},
+		{0x09aa, 0x09b0, 1},
+		{0x09b2, 0x09b6, 4},
+		{0x09b7, 0x09b9, 1},
+		{0x09bd, 0x09ce, 17},
+		{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, 0x0a72, 20},
+		{0x0a73, 0x0a74, 1},
+		{0x0a85, 0x0a8d, 1},
+		{0x0a8f, 0x0a91, 1},
+		{0x0a93, 0x0aa8, 1},
+		{0x0aaa, 0x0ab0, 1},
+		{0x0ab2, 0x0ab3, 1},
+		{0x0ab5, 0x0ab9, 1},
+		{0x0abd, 0x0ad0, 19},
+		{0x0ae0, 0x0ae1, 1},
+		{0x0b05, 0x0b0c, 1},
+		{0x0b0f, 0x0b10, 1},
+		{0x0b13, 0x0b28, 1},
+		{0x0b2a, 0x0b30, 1},
+		{0x0b32, 0x0b33, 1},
+		{0x0b35, 0x0b39, 1},
+		{0x0b3d, 0x0b5c, 31},
+		{0x0b5d, 0x0b5f, 2},
+		{0x0b60, 0x0b61, 1},
+		{0x0b71, 0x0b83, 18},
+		{0x0b85, 0x0b8a, 1},
+		{0x0b8e, 0x0b90, 1},
+		{0x0b92, 0x0b95, 1},
+		{0x0b99, 0x0b9a, 1},
+		{0x0b9c, 0x0b9e, 2},
+		{0x0b9f, 0x0ba3, 4},
+		{0x0ba4, 0x0ba8, 4},
+		{0x0ba9, 0x0baa, 1},
+		{0x0bae, 0x0bb9, 1},
+		{0x0bd0, 0x0c05, 53},
+		{0x0c06, 0x0c0c, 1},
+		{0x0c0e, 0x0c10, 1},
+		{0x0c12, 0x0c28, 1},
+		{0x0c2a, 0x0c33, 1},
+		{0x0c35, 0x0c39, 1},
+		{0x0c3d, 0x0c58, 27},
+		{0x0c59, 0x0c60, 7},
+		{0x0c61, 0x0c85, 36},
+		{0x0c86, 0x0c8c, 1},
+		{0x0c8e, 0x0c90, 1},
+		{0x0c92, 0x0ca8, 1},
+		{0x0caa, 0x0cb3, 1},
+		{0x0cb5, 0x0cb9, 1},
+		{0x0cbd, 0x0cde, 33},
+		{0x0ce0, 0x0ce1, 1},
+		{0x0cf1, 0x0cf2, 1},
+		{0x0d05, 0x0d0c, 1},
+		{0x0d0e, 0x0d10, 1},
+		{0x0d12, 0x0d3a, 1},
+		{0x0d3d, 0x0d4e, 17},
+		{0x0d60, 0x0d61, 1},
+		{0x0d7a, 0x0d7f, 1},
+		{0x0d85, 0x0d96, 1},
+		{0x0d9a, 0x0db1, 1},
+		{0x0db3, 0x0dbb, 1},
+		{0x0dbd, 0x0dc0, 3},
+		{0x0dc1, 0x0dc6, 1},
+		{0x0e01, 0x0e30, 1},
+		{0x0e32, 0x0e33, 1},
+		{0x0e40, 0x0e46, 1},
+		{0x0e81, 0x0e82, 1},
+		{0x0e84, 0x0e87, 3},
+		{0x0e88, 0x0e8a, 2},
+		{0x0e8d, 0x0e94, 7},
+		{0x0e95, 0x0e97, 1},
+		{0x0e99, 0x0e9f, 1},
+		{0x0ea1, 0x0ea3, 1},
+		{0x0ea5, 0x0ea7, 2},
+		{0x0eaa, 0x0eab, 1},
+		{0x0ead, 0x0eb0, 1},
+		{0x0eb2, 0x0eb3, 1},
+		{0x0ebd, 0x0ec0, 3},
+		{0x0ec1, 0x0ec4, 1},
+		{0x0ec6, 0x0edc, 22},
+		{0x0edd, 0x0f00, 35},
+		{0x0f40, 0x0f47, 1},
+		{0x0f49, 0x0f6c, 1},
+		{0x0f88, 0x0f8c, 1},
+		{0x1000, 0x102a, 1},
+		{0x103f, 0x1050, 17},
+		{0x1051, 0x1055, 1},
+		{0x105a, 0x105d, 1},
+		{0x1061, 0x1065, 4},
+		{0x1066, 0x106e, 8},
+		{0x106f, 0x1070, 1},
+		{0x1075, 0x1081, 1},
+		{0x108e, 0x10a0, 18},
+		{0x10a1, 0x10c5, 1},
+		{0x10d0, 0x10fa, 1},
+		{0x10fc, 0x1100, 4},
+		{0x1101, 0x1248, 1},
+		{0x124a, 0x124d, 1},
+		{0x1250, 0x1256, 1},
+		{0x1258, 0x125a, 2},
+		{0x125b, 0x125d, 1},
+		{0x1260, 0x1288, 1},
+		{0x128a, 0x128d, 1},
+		{0x1290, 0x12b0, 1},
+		{0x12b2, 0x12b5, 1},
+		{0x12b8, 0x12be, 1},
+		{0x12c0, 0x12c2, 2},
+		{0x12c3, 0x12c5, 1},
+		{0x12c8, 0x12d6, 1},
+		{0x12d8, 0x1310, 1},
+		{0x1312, 0x1315, 1},
+		{0x1318, 0x135a, 1},
+		{0x1380, 0x138f, 1},
+		{0x13a0, 0x13f4, 1},
+		{0x1401, 0x166c, 1},
+		{0x166f, 0x167f, 1},
+		{0x1681, 0x169a, 1},
+		{0x16a0, 0x16ea, 1},
+		{0x1700, 0x170c, 1},
+		{0x170e, 0x1711, 1},
+		{0x1720, 0x1731, 1},
+		{0x1740, 0x1751, 1},
+		{0x1760, 0x176c, 1},
+		{0x176e, 0x1770, 1},
+		{0x1780, 0x17b3, 1},
+		{0x17d7, 0x17dc, 5},
+		{0x1820, 0x1877, 1},
+		{0x1880, 0x18a8, 1},
+		{0x18aa, 0x18b0, 6},
+		{0x18b1, 0x18f5, 1},
+		{0x1900, 0x191c, 1},
+		{0x1950, 0x196d, 1},
+		{0x1970, 0x1974, 1},
+		{0x1980, 0x19ab, 1},
+		{0x19c1, 0x19c7, 1},
+		{0x1a00, 0x1a16, 1},
+		{0x1a20, 0x1a54, 1},
+		{0x1aa7, 0x1b05, 94},
+		{0x1b06, 0x1b33, 1},
+		{0x1b45, 0x1b4b, 1},
+		{0x1b83, 0x1ba0, 1},
+		{0x1bae, 0x1baf, 1},
+		{0x1bc0, 0x1be5, 1},
+		{0x1c00, 0x1c23, 1},
+		{0x1c4d, 0x1c4f, 1},
+		{0x1c5a, 0x1c7d, 1},
+		{0x1ce9, 0x1cec, 1},
+		{0x1cee, 0x1cf1, 1},
+		{0x1d00, 0x1dbf, 1},
+		{0x1e00, 0x1f15, 1},
+		{0x1f18, 0x1f1d, 1},
+		{0x1f20, 0x1f45, 1},
+		{0x1f48, 0x1f4d, 1},
+		{0x1f50, 0x1f57, 1},
+		{0x1f59, 0x1f5f, 2},
+		{0x1f60, 0x1f7d, 1},
+		{0x1f80, 0x1fb4, 1},
+		{0x1fb6, 0x1fbc, 1},
+		{0x1fbe, 0x1fc2, 4},
+		{0x1fc3, 0x1fc4, 1},
+		{0x1fc6, 0x1fcc, 1},
+		{0x1fd0, 0x1fd3, 1},
+		{0x1fd6, 0x1fdb, 1},
+		{0x1fe0, 0x1fec, 1},
+		{0x1ff2, 0x1ff4, 1},
+		{0x1ff6, 0x1ffc, 1},
+		{0x2071, 0x207f, 14},
+		{0x2090, 0x209c, 1},
+		{0x2102, 0x2107, 5},
+		{0x210a, 0x2113, 1},
+		{0x2115, 0x2119, 4},
+		{0x211a, 0x211d, 1},
+		{0x2124, 0x212a, 2},
+		{0x212b, 0x212d, 1},
+		{0x212f, 0x2139, 1},
+		{0x213c, 0x213f, 1},
+		{0x2145, 0x2149, 1},
+		{0x214e, 0x2183, 53},
+		{0x2184, 0x2c00, 2684},
+		{0x2c01, 0x2c2e, 1},
+		{0x2c30, 0x2c5e, 1},
+		{0x2c60, 0x2ce4, 1},
+		{0x2ceb, 0x2cee, 1},
+		{0x2d00, 0x2d25, 1},
+		{0x2d30, 0x2d65, 1},
+		{0x2d6f, 0x2d80, 17},
+		{0x2d81, 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},
+		{0x2e2f, 0x3005, 470},
+		{0x3006, 0x3031, 43},
+		{0x3032, 0x3035, 1},
+		{0x303b, 0x303c, 1},
+		{0x3041, 0x3096, 1},
+		{0x309d, 0x309f, 1},
+		{0x30a1, 0x30fa, 1},
+		{0x30fc, 0x30ff, 1},
+		{0x3105, 0x312d, 1},
+		{0x3131, 0x318e, 1},
+		{0x31a0, 0x31ba, 1},
+		{0x31f0, 0x31ff, 1},
+		{0x3400, 0x4db5, 1},
+		{0x4e00, 0x9fcb, 1},
+		{0xa000, 0xa48c, 1},
+		{0xa4d0, 0xa4fd, 1},
+		{0xa500, 0xa60c, 1},
+		{0xa610, 0xa61f, 1},
+		{0xa62a, 0xa62b, 1},
+		{0xa640, 0xa66e, 1},
+		{0xa67f, 0xa697, 1},
+		{0xa6a0, 0xa6e5, 1},
+		{0xa717, 0xa71f, 1},
+		{0xa722, 0xa788, 1},
+		{0xa78b, 0xa78e, 1},
+		{0xa790, 0xa791, 1},
+		{0xa7a0, 0xa7a9, 1},
+		{0xa7fa, 0xa801, 1},
+		{0xa803, 0xa805, 1},
+		{0xa807, 0xa80a, 1},
+		{0xa80c, 0xa822, 1},
+		{0xa840, 0xa873, 1},
+		{0xa882, 0xa8b3, 1},
+		{0xa8f2, 0xa8f7, 1},
+		{0xa8fb, 0xa90a, 15},
+		{0xa90b, 0xa925, 1},
+		{0xa930, 0xa946, 1},
+		{0xa960, 0xa97c, 1},
+		{0xa984, 0xa9b2, 1},
+		{0xa9cf, 0xaa00, 49},
+		{0xaa01, 0xaa28, 1},
+		{0xaa40, 0xaa42, 1},
+		{0xaa44, 0xaa4b, 1},
+		{0xaa60, 0xaa76, 1},
+		{0xaa7a, 0xaa80, 6},
+		{0xaa81, 0xaaaf, 1},
+		{0xaab1, 0xaab5, 4},
+		{0xaab6, 0xaab9, 3},
+		{0xaaba, 0xaabd, 1},
+		{0xaac0, 0xaac2, 2},
+		{0xaadb, 0xaadd, 1},
+		{0xab01, 0xab06, 1},
+		{0xab09, 0xab0e, 1},
+		{0xab11, 0xab16, 1},
+		{0xab20, 0xab26, 1},
+		{0xab28, 0xab2e, 1},
+		{0xabc0, 0xabe2, 1},
+		{0xac00, 0xd7a3, 1},
+		{0xd7b0, 0xd7c6, 1},
+		{0xd7cb, 0xd7fb, 1},
+		{0xf900, 0xfa2d, 1},
+		{0xfa30, 0xfa6d, 1},
+		{0xfa70, 0xfad9, 1},
+		{0xfb00, 0xfb06, 1},
+		{0xfb13, 0xfb17, 1},
+		{0xfb1d, 0xfb1f, 2},
+		{0xfb20, 0xfb28, 1},
+		{0xfb2a, 0xfb36, 1},
+		{0xfb38, 0xfb3c, 1},
+		{0xfb3e, 0xfb40, 2},
+		{0xfb41, 0xfb43, 2},
+		{0xfb44, 0xfb46, 2},
+		{0xfb47, 0xfbb1, 1},
+		{0xfbd3, 0xfd3d, 1},
+		{0xfd50, 0xfd8f, 1},
+		{0xfd92, 0xfdc7, 1},
+		{0xfdf0, 0xfdfb, 1},
+		{0xfe70, 0xfe74, 1},
+		{0xfe76, 0xfefc, 1},
+		{0xff21, 0xff3a, 1},
+		{0xff41, 0xff5a, 1},
+		{0xff66, 0xffbe, 1},
+		{0xffc2, 0xffc7, 1},
+		{0xffca, 0xffcf, 1},
+		{0xffd2, 0xffd7, 1},
+		{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},
+		{0x10400, 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},
+		{0x1d400, 0x1d454, 1},
+		{0x1d456, 0x1d49c, 1},
+		{0x1d49e, 0x1d49f, 1},
+		{0x1d4a2, 0x1d4a5, 3},
+		{0x1d4a6, 0x1d4a9, 3},
+		{0x1d4aa, 0x1d4ac, 1},
+		{0x1d4ae, 0x1d4b9, 1},
+		{0x1d4bb, 0x1d4bd, 2},
+		{0x1d4be, 0x1d4c3, 1},
+		{0x1d4c5, 0x1d505, 1},
+		{0x1d507, 0x1d50a, 1},
+		{0x1d50d, 0x1d514, 1},
+		{0x1d516, 0x1d51c, 1},
+		{0x1d51e, 0x1d539, 1},
+		{0x1d53b, 0x1d53e, 1},
+		{0x1d540, 0x1d544, 1},
+		{0x1d546, 0x1d54a, 4},
+		{0x1d54b, 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},
+		{0x20000, 0x2a6d6, 1},
+		{0x2a700, 0x2b734, 1},
+		{0x2b740, 0x2b81d, 1},
+		{0x2f800, 0x2fa1d, 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{
+	R16: []Range16{
+		{0x01bb, 0x01c0, 5},
+		{0x01c1, 0x01c3, 1},
+		{0x0294, 0x05d0, 828},
+		{0x05d1, 0x05ea, 1},
+		{0x05f0, 0x05f2, 1},
+		{0x0620, 0x063f, 1},
+		{0x0641, 0x064a, 1},
+		{0x066e, 0x066f, 1},
+		{0x0671, 0x06d3, 1},
+		{0x06d5, 0x06ee, 25},
+		{0x06ef, 0x06fa, 11},
+		{0x06fb, 0x06fc, 1},
+		{0x06ff, 0x0710, 17},
+		{0x0712, 0x072f, 1},
+		{0x074d, 0x07a5, 1},
+		{0x07b1, 0x07ca, 25},
+		{0x07cb, 0x07ea, 1},
+		{0x0800, 0x0815, 1},
+		{0x0840, 0x0858, 1},
+		{0x0904, 0x0939, 1},
+		{0x093d, 0x0950, 19},
+		{0x0958, 0x0961, 1},
+		{0x0972, 0x0977, 1},
+		{0x0979, 0x097f, 1},
+		{0x0985, 0x098c, 1},
+		{0x098f, 0x0990, 1},
+		{0x0993, 0x09a8, 1},
+		{0x09aa, 0x09b0, 1},
+		{0x09b2, 0x09b6, 4},
+		{0x09b7, 0x09b9, 1},
+		{0x09bd, 0x09ce, 17},
+		{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, 0x0a72, 20},
+		{0x0a73, 0x0a74, 1},
+		{0x0a85, 0x0a8d, 1},
+		{0x0a8f, 0x0a91, 1},
+		{0x0a93, 0x0aa8, 1},
+		{0x0aaa, 0x0ab0, 1},
+		{0x0ab2, 0x0ab3, 1},
+		{0x0ab5, 0x0ab9, 1},
+		{0x0abd, 0x0ad0, 19},
+		{0x0ae0, 0x0ae1, 1},
+		{0x0b05, 0x0b0c, 1},
+		{0x0b0f, 0x0b10, 1},
+		{0x0b13, 0x0b28, 1},
+		{0x0b2a, 0x0b30, 1},
+		{0x0b32, 0x0b33, 1},
+		{0x0b35, 0x0b39, 1},
+		{0x0b3d, 0x0b5c, 31},
+		{0x0b5d, 0x0b5f, 2},
+		{0x0b60, 0x0b61, 1},
+		{0x0b71, 0x0b83, 18},
+		{0x0b85, 0x0b8a, 1},
+		{0x0b8e, 0x0b90, 1},
+		{0x0b92, 0x0b95, 1},
+		{0x0b99, 0x0b9a, 1},
+		{0x0b9c, 0x0b9e, 2},
+		{0x0b9f, 0x0ba3, 4},
+		{0x0ba4, 0x0ba8, 4},
+		{0x0ba9, 0x0baa, 1},
+		{0x0bae, 0x0bb9, 1},
+		{0x0bd0, 0x0c05, 53},
+		{0x0c06, 0x0c0c, 1},
+		{0x0c0e, 0x0c10, 1},
+		{0x0c12, 0x0c28, 1},
+		{0x0c2a, 0x0c33, 1},
+		{0x0c35, 0x0c39, 1},
+		{0x0c3d, 0x0c58, 27},
+		{0x0c59, 0x0c60, 7},
+		{0x0c61, 0x0c85, 36},
+		{0x0c86, 0x0c8c, 1},
+		{0x0c8e, 0x0c90, 1},
+		{0x0c92, 0x0ca8, 1},
+		{0x0caa, 0x0cb3, 1},
+		{0x0cb5, 0x0cb9, 1},
+		{0x0cbd, 0x0cde, 33},
+		{0x0ce0, 0x0ce1, 1},
+		{0x0cf1, 0x0cf2, 1},
+		{0x0d05, 0x0d0c, 1},
+		{0x0d0e, 0x0d10, 1},
+		{0x0d12, 0x0d3a, 1},
+		{0x0d3d, 0x0d4e, 17},
+		{0x0d60, 0x0d61, 1},
+		{0x0d7a, 0x0d7f, 1},
+		{0x0d85, 0x0d96, 1},
+		{0x0d9a, 0x0db1, 1},
+		{0x0db3, 0x0dbb, 1},
+		{0x0dbd, 0x0dc0, 3},
+		{0x0dc1, 0x0dc6, 1},
+		{0x0e01, 0x0e30, 1},
+		{0x0e32, 0x0e33, 1},
+		{0x0e40, 0x0e45, 1},
+		{0x0e81, 0x0e82, 1},
+		{0x0e84, 0x0e87, 3},
+		{0x0e88, 0x0e8a, 2},
+		{0x0e8d, 0x0e94, 7},
+		{0x0e95, 0x0e97, 1},
+		{0x0e99, 0x0e9f, 1},
+		{0x0ea1, 0x0ea3, 1},
+		{0x0ea5, 0x0ea7, 2},
+		{0x0eaa, 0x0eab, 1},
+		{0x0ead, 0x0eb0, 1},
+		{0x0eb2, 0x0eb3, 1},
+		{0x0ebd, 0x0ec0, 3},
+		{0x0ec1, 0x0ec4, 1},
+		{0x0edc, 0x0edd, 1},
+		{0x0f00, 0x0f40, 64},
+		{0x0f41, 0x0f47, 1},
+		{0x0f49, 0x0f6c, 1},
+		{0x0f88, 0x0f8c, 1},
+		{0x1000, 0x102a, 1},
+		{0x103f, 0x1050, 17},
+		{0x1051, 0x1055, 1},
+		{0x105a, 0x105d, 1},
+		{0x1061, 0x1065, 4},
+		{0x1066, 0x106e, 8},
+		{0x106f, 0x1070, 1},
+		{0x1075, 0x1081, 1},
+		{0x108e, 0x10d0, 66},
+		{0x10d1, 0x10fa, 1},
+		{0x1100, 0x1248, 1},
+		{0x124a, 0x124d, 1},
+		{0x1250, 0x1256, 1},
+		{0x1258, 0x125a, 2},
+		{0x125b, 0x125d, 1},
+		{0x1260, 0x1288, 1},
+		{0x128a, 0x128d, 1},
+		{0x1290, 0x12b0, 1},
+		{0x12b2, 0x12b5, 1},
+		{0x12b8, 0x12be, 1},
+		{0x12c0, 0x12c2, 2},
+		{0x12c3, 0x12c5, 1},
+		{0x12c8, 0x12d6, 1},
+		{0x12d8, 0x1310, 1},
+		{0x1312, 0x1315, 1},
+		{0x1318, 0x135a, 1},
+		{0x1380, 0x138f, 1},
+		{0x13a0, 0x13f4, 1},
+		{0x1401, 0x166c, 1},
+		{0x166f, 0x167f, 1},
+		{0x1681, 0x169a, 1},
+		{0x16a0, 0x16ea, 1},
+		{0x1700, 0x170c, 1},
+		{0x170e, 0x1711, 1},
+		{0x1720, 0x1731, 1},
+		{0x1740, 0x1751, 1},
+		{0x1760, 0x176c, 1},
+		{0x176e, 0x1770, 1},
+		{0x1780, 0x17b3, 1},
+		{0x17dc, 0x1820, 68},
+		{0x1821, 0x1842, 1},
+		{0x1844, 0x1877, 1},
+		{0x1880, 0x18a8, 1},
+		{0x18aa, 0x18b0, 6},
+		{0x18b1, 0x18f5, 1},
+		{0x1900, 0x191c, 1},
+		{0x1950, 0x196d, 1},
+		{0x1970, 0x1974, 1},
+		{0x1980, 0x19ab, 1},
+		{0x19c1, 0x19c7, 1},
+		{0x1a00, 0x1a16, 1},
+		{0x1a20, 0x1a54, 1},
+		{0x1b05, 0x1b33, 1},
+		{0x1b45, 0x1b4b, 1},
+		{0x1b83, 0x1ba0, 1},
+		{0x1bae, 0x1baf, 1},
+		{0x1bc0, 0x1be5, 1},
+		{0x1c00, 0x1c23, 1},
+		{0x1c4d, 0x1c4f, 1},
+		{0x1c5a, 0x1c77, 1},
+		{0x1ce9, 0x1cec, 1},
+		{0x1cee, 0x1cf1, 1},
+		{0x2135, 0x2138, 1},
+		{0x2d30, 0x2d65, 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},
+		{0x3006, 0x303c, 54},
+		{0x3041, 0x3096, 1},
+		{0x309f, 0x30a1, 2},
+		{0x30a2, 0x30fa, 1},
+		{0x30ff, 0x3105, 6},
+		{0x3106, 0x312d, 1},
+		{0x3131, 0x318e, 1},
+		{0x31a0, 0x31ba, 1},
+		{0x31f0, 0x31ff, 1},
+		{0x3400, 0x4db5, 1},
+		{0x4e00, 0x9fcb, 1},
+		{0xa000, 0xa014, 1},
+		{0xa016, 0xa48c, 1},
+		{0xa4d0, 0xa4f7, 1},
+		{0xa500, 0xa60b, 1},
+		{0xa610, 0xa61f, 1},
+		{0xa62a, 0xa62b, 1},
+		{0xa66e, 0xa6a0, 50},
+		{0xa6a1, 0xa6e5, 1},
+		{0xa7fb, 0xa801, 1},
+		{0xa803, 0xa805, 1},
+		{0xa807, 0xa80a, 1},
+		{0xa80c, 0xa822, 1},
+		{0xa840, 0xa873, 1},
+		{0xa882, 0xa8b3, 1},
+		{0xa8f2, 0xa8f7, 1},
+		{0xa8fb, 0xa90a, 15},
+		{0xa90b, 0xa925, 1},
+		{0xa930, 0xa946, 1},
+		{0xa960, 0xa97c, 1},
+		{0xa984, 0xa9b2, 1},
+		{0xaa00, 0xaa28, 1},
+		{0xaa40, 0xaa42, 1},
+		{0xaa44, 0xaa4b, 1},
+		{0xaa60, 0xaa6f, 1},
+		{0xaa71, 0xaa76, 1},
+		{0xaa7a, 0xaa80, 6},
+		{0xaa81, 0xaaaf, 1},
+		{0xaab1, 0xaab5, 4},
+		{0xaab6, 0xaab9, 3},
+		{0xaaba, 0xaabd, 1},
+		{0xaac0, 0xaac2, 2},
+		{0xaadb, 0xaadc, 1},
+		{0xab01, 0xab06, 1},
+		{0xab09, 0xab0e, 1},
+		{0xab11, 0xab16, 1},
+		{0xab20, 0xab26, 1},
+		{0xab28, 0xab2e, 1},
+		{0xabc0, 0xabe2, 1},
+		{0xac00, 0xd7a3, 1},
+		{0xd7b0, 0xd7c6, 1},
+		{0xd7cb, 0xd7fb, 1},
+		{0xf900, 0xfa2d, 1},
+		{0xfa30, 0xfa6d, 1},
+		{0xfa70, 0xfad9, 1},
+		{0xfb1d, 0xfb1f, 2},
+		{0xfb20, 0xfb28, 1},
+		{0xfb2a, 0xfb36, 1},
+		{0xfb38, 0xfb3c, 1},
+		{0xfb3e, 0xfb40, 2},
+		{0xfb41, 0xfb43, 2},
+		{0xfb44, 0xfb46, 2},
+		{0xfb47, 0xfbb1, 1},
+		{0xfbd3, 0xfd3d, 1},
+		{0xfd50, 0xfd8f, 1},
+		{0xfd92, 0xfdc7, 1},
+		{0xfdf0, 0xfdfb, 1},
+		{0xfe70, 0xfe74, 1},
+		{0xfe76, 0xfefc, 1},
+		{0xff66, 0xff6f, 1},
+		{0xff71, 0xff9d, 1},
+		{0xffa0, 0xffbe, 1},
+		{0xffc2, 0xffc7, 1},
+		{0xffca, 0xffcf, 1},
+		{0xffd2, 0xffd7, 1},
+		{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},
+	},
 }
 
 var (
@@ -2018,7 +2109,7 @@ var (
 // DO NOT EDIT
 
 // Scripts is the set of Unicode script tables.
-var Scripts = map[string][]Range{
+var Scripts = map[string]*RangeTable{
 	"Katakana":               Katakana,
 	"Malayalam":              Malayalam,
 	"Phags_Pa":               Phags_Pa,
@@ -2116,973 +2207,1203 @@ var Scripts = map[string][]Range{
 	"Gothic":                 Gothic,
 }
 
-var _Katakana = []Range{
-	{0x30a1, 0x30fa, 1},
-	{0x30fd, 0x30ff, 1},
-	{0x31f0, 0x31ff, 1},
-	{0x32d0, 0x32fe, 1},
-	{0x3300, 0x3357, 1},
-	{0xff66, 0xff6f, 1},
-	{0xff71, 0xff9d, 1},
-	{0x1b000, 0x1b000, 1},
-}
-
-var _Malayalam = []Range{
-	{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 _Phags_Pa = []Range{
-	{0xa840, 0xa877, 1},
-}
-
-var _Inscriptional_Parthian = []Range{
-	{0x10b40, 0x10b55, 1},
-	{0x10b58, 0x10b5f, 1},
-}
-
-var _Latin = []Range{
-	{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 = []Range{
-	{0x10b60, 0x10b72, 1},
-	{0x10b78, 0x10b7f, 1},
-}
-
-var _Osmanya = []Range{
-	{0x10480, 0x1049d, 1},
-	{0x104a0, 0x104a9, 1},
-}
-
-var _Khmer = []Range{
-	{0x1780, 0x17dd, 1},
-	{0x17e0, 0x17e9, 1},
-	{0x17f0, 0x17f9, 1},
-	{0x19e0, 0x19ff, 1},
-}
-
-var _Inherited = []Range{
-	{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},
-	{0x101fd, 0x101fd, 1},
-	{0x1d167, 0x1d169, 1},
-	{0x1d17b, 0x1d182, 1},
-	{0x1d185, 0x1d18b, 1},
-	{0x1d1aa, 0x1d1ad, 1},
-	{0xe0100, 0xe01ef, 1},
-}
-
-var _Telugu = []Range{
-	{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 _Samaritan = []Range{
-	{0x0800, 0x082d, 1},
-	{0x0830, 0x083e, 1},
-}
-
-var _Bopomofo = []Range{
-	{0x02ea, 0x02eb, 1},
-	{0x3105, 0x312d, 1},
-	{0x31a0, 0x31ba, 1},
-}
-
-var _Imperial_Aramaic = []Range{
-	{0x10840, 0x10855, 1},
-	{0x10857, 0x1085f, 1},
-}
-
-var _Kaithi = []Range{
-	{0x11080, 0x110c1, 1},
-}
-
-var _Mandaic = []Range{
-	{0x0840, 0x085b, 1},
-	{0x085e, 0x085e, 1},
-}
-
-var _Old_South_Arabian = []Range{
-	{0x10a60, 0x10a7f, 1},
-}
-
-var _Kayah_Li = []Range{
-	{0xa900, 0xa92f, 1},
-}
-
-var _New_Tai_Lue = []Range{
-	{0x1980, 0x19ab, 1},
-	{0x19b0, 0x19c9, 1},
-	{0x19d0, 0x19da, 1},
-	{0x19de, 0x19df, 1},
-}
-
-var _Tai_Le = []Range{
-	{0x1950, 0x196d, 1},
-	{0x1970, 0x1974, 1},
-}
-
-var _Kharoshthi = []Range{
-	{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 _Common = []Range{
-	{0x0000, 0x0040, 1},
-	{0x005b, 0x0060, 1},
-	{0x007b, 0x00a9, 1},
-	{0x00ab, 0x00b9, 1},
-	{0x00bb, 0x00bf, 1},
-	{0x00d7, 0x00d7, 1},
-	{0x00f7, 0x00f7, 1},
-	{0x02b9, 0x02df, 1},
-	{0x02e5, 0x02e9, 1},
-	{0x02ec, 0x02ff, 1},
-	{0x0374, 0x0374, 1},
-	{0x037e, 0x037e, 1},
-	{0x0385, 0x0385, 1},
-	{0x0387, 0x0387, 1},
-	{0x0589, 0x0589, 1},
-	{0x060c, 0x060c, 1},
-	{0x061b, 0x061b, 1},
-	{0x061f, 0x061f, 1},
-	{0x0640, 0x0640, 1},
-	{0x0660, 0x0669, 1},
-	{0x06dd, 0x06dd, 1},
-	{0x0964, 0x0965, 1},
-	{0x0970, 0x0970, 1},
-	{0x0e3f, 0x0e3f, 1},
-	{0x0fd5, 0x0fd8, 1},
-	{0x10fb, 0x10fb, 1},
-	{0x16eb, 0x16ed, 1},
-	{0x1735, 0x1736, 1},
-	{0x1802, 0x1803, 1},
-	{0x1805, 0x1805, 1},
-	{0x1cd3, 0x1cd3, 1},
-	{0x1ce1, 0x1ce1, 1},
-	{0x1ce9, 0x1cec, 1},
-	{0x1cee, 0x1cf2, 1},
-	{0x2000, 0x200b, 1},
-	{0x200e, 0x2064, 1},
-	{0x206a, 0x2070, 1},
-	{0x2074, 0x207e, 1},
-	{0x2080, 0x208e, 1},
-	{0x20a0, 0x20b9, 1},
-	{0x2100, 0x2125, 1},
-	{0x2127, 0x2129, 1},
-	{0x212c, 0x2131, 1},
-	{0x2133, 0x214d, 1},
-	{0x214f, 0x215f, 1},
-	{0x2189, 0x2189, 1},
-	{0x2190, 0x23f3, 1},
-	{0x2400, 0x2426, 1},
-	{0x2440, 0x244a, 1},
-	{0x2460, 0x26ff, 1},
-	{0x2701, 0x27ca, 1},
-	{0x27cc, 0x27cc, 1},
-	{0x27ce, 0x27ff, 1},
-	{0x2900, 0x2b4c, 1},
-	{0x2b50, 0x2b59, 1},
-	{0x2e00, 0x2e31, 1},
-	{0x2ff0, 0x2ffb, 1},
-	{0x3000, 0x3004, 1},
-	{0x3006, 0x3006, 1},
-	{0x3008, 0x3020, 1},
-	{0x3030, 0x3037, 1},
-	{0x303c, 0x303f, 1},
-	{0x309b, 0x309c, 1},
-	{0x30a0, 0x30a0, 1},
-	{0x30fb, 0x30fc, 1},
-	{0x3190, 0x319f, 1},
-	{0x31c0, 0x31e3, 1},
-	{0x3220, 0x325f, 1},
-	{0x327f, 0x32cf, 1},
-	{0x3358, 0x33ff, 1},
-	{0x4dc0, 0x4dff, 1},
-	{0xa700, 0xa721, 1},
-	{0xa788, 0xa78a, 1},
-	{0xa830, 0xa839, 1},
-	{0xfd3e, 0xfd3f, 1},
-	{0xfdfd, 0xfdfd, 1},
-	{0xfe10, 0xfe19, 1},
-	{0xfe30, 0xfe52, 1},
-	{0xfe54, 0xfe66, 1},
-	{0xfe68, 0xfe6b, 1},
-	{0xfeff, 0xfeff, 1},
-	{0xff01, 0xff20, 1},
-	{0xff3b, 0xff40, 1},
-	{0xff5b, 0xff65, 1},
-	{0xff70, 0xff70, 1},
-	{0xff9e, 0xff9f, 1},
-	{0xffe0, 0xffe6, 1},
-	{0xffe8, 0xffee, 1},
-	{0xfff9, 0xfffd, 1},
-	{0x10100, 0x10102, 1},
-	{0x10107, 0x10133, 1},
-	{0x10137, 0x1013f, 1},
-	{0x10190, 0x1019b, 1},
-	{0x101d0, 0x101fc, 1},
-	{0x1d000, 0x1d0f5, 1},
-	{0x1d100, 0x1d126, 1},
-	{0x1d129, 0x1d166, 1},
-	{0x1d16a, 0x1d17a, 1},
-	{0x1d183, 0x1d184, 1},
-	{0x1d18c, 0x1d1a9, 1},
-	{0x1d1ae, 0x1d1dd, 1},
-	{0x1d300, 0x1d356, 1},
-	{0x1d360, 0x1d371, 1},
-	{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, 0x1d7cb, 1},
-	{0x1d7ce, 0x1d7ff, 1},
-	{0x1f000, 0x1f02b, 1},
-	{0x1f030, 0x1f093, 1},
-	{0x1f0a0, 0x1f0ae, 1},
-	{0x1f0b1, 0x1f0be, 1},
-	{0x1f0c1, 0x1f0cf, 1},
-	{0x1f0d1, 0x1f0df, 1},
-	{0x1f100, 0x1f10a, 1},
-	{0x1f110, 0x1f12e, 1},
-	{0x1f130, 0x1f169, 1},
-	{0x1f170, 0x1f19a, 1},
-	{0x1f1e6, 0x1f1ff, 1},
-	{0x1f201, 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, 0x1f440, 1},
-	{0x1f442, 0x1f4f7, 1},
-	{0x1f4f9, 0x1f4fc, 1},
-	{0x1f500, 0x1f53d, 1},
-	{0x1f550, 0x1f567, 1},
-	{0x1f5fb, 0x1f5ff, 1},
-	{0x1f601, 0x1f610, 1},
-	{0x1f612, 0x1f614, 1},
-	{0x1f616, 0x1f616, 1},
-	{0x1f618, 0x1f618, 1},
-	{0x1f61a, 0x1f61a, 1},
-	{0x1f61c, 0x1f61e, 1},
-	{0x1f620, 0x1f625, 1},
-	{0x1f628, 0x1f62b, 1},
-	{0x1f62d, 0x1f62d, 1},
-	{0x1f630, 0x1f633, 1},
-	{0x1f635, 0x1f640, 1},
-	{0x1f645, 0x1f64f, 1},
-	{0x1f680, 0x1f6c5, 1},
-	{0x1f700, 0x1f773, 1},
-	{0xe0001, 0xe0001, 1},
-	{0xe0020, 0xe007f, 1},
-}
-
-var _Kannada = []Range{
-	{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 _Old_Turkic = []Range{
-	{0x10c00, 0x10c48, 1},
-}
-
-var _Tamil = []Range{
-	{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 = []Range{
-	{0x1700, 0x170c, 1},
-	{0x170e, 0x1714, 1},
-}
-
-var _Brahmi = []Range{
-	{0x11000, 0x1104d, 1},
-	{0x11052, 0x1106f, 1},
-}
-
-var _Arabic = []Range{
-	{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},
-	{0x10e60, 0x10e7e, 1},
-}
-
-var _Tagbanwa = []Range{
-	{0x1760, 0x176c, 1},
-	{0x176e, 0x1770, 1},
-	{0x1772, 0x1773, 1},
-}
-
-var _Canadian_Aboriginal = []Range{
-	{0x1400, 0x167f, 1},
-	{0x18b0, 0x18f5, 1},
-}
-
-var _Tibetan = []Range{
-	{0x0f00, 0x0f47, 1},
-	{0x0f49, 0x0f6c, 1},
-	{0x0f71, 0x0f97, 1},
-	{0x0f99, 0x0fbc, 1},
-	{0x0fbe, 0x0fcc, 1},
-	{0x0fce, 0x0fd4, 1},
-	{0x0fd9, 0x0fda, 1},
-}
-
-var _Coptic = []Range{
-	{0x03e2, 0x03ef, 1},
-	{0x2c80, 0x2cf1, 1},
-	{0x2cf9, 0x2cff, 1},
-}
-
-var _Hiragana = []Range{
-	{0x3041, 0x3096, 1},
-	{0x309d, 0x309f, 1},
-	{0x1b001, 0x1b001, 1},
-	{0x1f200, 0x1f200, 1},
-}
-
-var _Limbu = []Range{
-	{0x1900, 0x191c, 1},
-	{0x1920, 0x192b, 1},
-	{0x1930, 0x193b, 1},
-	{0x1940, 0x1940, 1},
-	{0x1944, 0x194f, 1},
-}
-
-var _Egyptian_Hieroglyphs = []Range{
-	{0x13000, 0x1342e, 1},
-}
-
-var _Avestan = []Range{
-	{0x10b00, 0x10b35, 1},
-	{0x10b39, 0x10b3f, 1},
-}
-
-var _Myanmar = []Range{
-	{0x1000, 0x109f, 1},
-	{0xaa60, 0xaa7b, 1},
-}
-
-var _Armenian = []Range{
-	{0x0531, 0x0556, 1},
-	{0x0559, 0x055f, 1},
-	{0x0561, 0x0587, 1},
-	{0x058a, 0x058a, 1},
-	{0xfb13, 0xfb17, 1},
-}
-
-var _Sinhala = []Range{
-	{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 _Bengali = []Range{
-	{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 _Greek = []Range{
-	{0x0370, 0x0373, 1},
-	{0x0375, 0x0377, 1},
-	{0x037a, 0x037d, 1},
-	{0x0384, 0x0384, 1},
-	{0x0386, 0x0386, 1},
-	{0x0388, 0x038a, 1},
-	{0x038c, 0x038c, 1},
-	{0x038e, 0x03a1, 1},
-	{0x03a3, 0x03e1, 1},
-	{0x03f0, 0x03ff, 1},
-	{0x1d26, 0x1d2a, 1},
-	{0x1d5d, 0x1d61, 1},
-	{0x1d66, 0x1d6a, 1},
-	{0x1dbf, 0x1dbf, 1},
-	{0x1f00, 0x1f15, 1},
-	{0x1f18, 0x1f1d, 1},
-	{0x1f20, 0x1f45, 1},
-	{0x1f48, 0x1f4d, 1},
-	{0x1f50, 0x1f57, 1},
-	{0x1f59, 0x1f59, 1},
-	{0x1f5b, 0x1f5b, 1},
-	{0x1f5d, 0x1f5d, 1},
-	{0x1f5f, 0x1f7d, 1},
-	{0x1f80, 0x1fb4, 1},
-	{0x1fb6, 0x1fc4, 1},
-	{0x1fc6, 0x1fd3, 1},
-	{0x1fd6, 0x1fdb, 1},
-	{0x1fdd, 0x1fef, 1},
-	{0x1ff2, 0x1ff4, 1},
-	{0x1ff6, 0x1ffe, 1},
-	{0x2126, 0x2126, 1},
-	{0x10140, 0x1018a, 1},
-	{0x1d200, 0x1d245, 1},
-}
-
-var _Cham = []Range{
-	{0xaa00, 0xaa36, 1},
-	{0xaa40, 0xaa4d, 1},
-	{0xaa50, 0xaa59, 1},
-	{0xaa5c, 0xaa5f, 1},
-}
-
-var _Hebrew = []Range{
-	{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 _Meetei_Mayek = []Range{
-	{0xabc0, 0xabed, 1},
-	{0xabf0, 0xabf9, 1},
-}
-
-var _Saurashtra = []Range{
-	{0xa880, 0xa8c4, 1},
-	{0xa8ce, 0xa8d9, 1},
-}
-
-var _Hangul = []Range{
-	{0x1100, 0x11ff, 1},
-	{0x302e, 0x302f, 1},
-	{0x3131, 0x318e, 1},
-	{0x3200, 0x321e, 1},
-	{0x3260, 0x327e, 1},
-	{0xa960, 0xa97c, 1},
-	{0xac00, 0xd7a3, 1},
-	{0xd7b0, 0xd7c6, 1},
-	{0xd7cb, 0xd7fb, 1},
-	{0xffa0, 0xffbe, 1},
-	{0xffc2, 0xffc7, 1},
-	{0xffca, 0xffcf, 1},
-	{0xffd2, 0xffd7, 1},
-	{0xffda, 0xffdc, 1},
-}
-
-var _Runic = []Range{
-	{0x16a0, 0x16ea, 1},
-	{0x16ee, 0x16f0, 1},
-}
-
-var _Deseret = []Range{
-	{0x10400, 0x1044f, 1},
-}
-
-var _Lisu = []Range{
-	{0xa4d0, 0xa4ff, 1},
-}
-
-var _Sundanese = []Range{
-	{0x1b80, 0x1baa, 1},
-	{0x1bae, 0x1bb9, 1},
-}
-
-var _Glagolitic = []Range{
-	{0x2c00, 0x2c2e, 1},
-	{0x2c30, 0x2c5e, 1},
-}
-
-var _Oriya = []Range{
-	{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 _Buhid = []Range{
-	{0x1740, 0x1753, 1},
-}
-
-var _Ethiopic = []Range{
-	{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 _Javanese = []Range{
-	{0xa980, 0xa9cd, 1},
-	{0xa9cf, 0xa9d9, 1},
-	{0xa9de, 0xa9df, 1},
-}
-
-var _Syloti_Nagri = []Range{
-	{0xa800, 0xa82b, 1},
-}
-
-var _Vai = []Range{
-	{0xa500, 0xa62b, 1},
-}
-
-var _Cherokee = []Range{
-	{0x13a0, 0x13f4, 1},
-}
-
-var _Ogham = []Range{
-	{0x1680, 0x169c, 1},
-}
-
-var _Batak = []Range{
-	{0x1bc0, 0x1bf3, 1},
-	{0x1bfc, 0x1bff, 1},
-}
-
-var _Syriac = []Range{
-	{0x0700, 0x070d, 1},
-	{0x070f, 0x074a, 1},
-	{0x074d, 0x074f, 1},
-}
-
-var _Gurmukhi = []Range{
-	{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 _Tai_Tham = []Range{
-	{0x1a20, 0x1a5e, 1},
-	{0x1a60, 0x1a7c, 1},
-	{0x1a7f, 0x1a89, 1},
-	{0x1a90, 0x1a99, 1},
-	{0x1aa0, 0x1aad, 1},
-}
-
-var _Ol_Chiki = []Range{
-	{0x1c50, 0x1c7f, 1},
-}
-
-var _Mongolian = []Range{
-	{0x1800, 0x1801, 1},
-	{0x1804, 0x1804, 1},
-	{0x1806, 0x180e, 1},
-	{0x1810, 0x1819, 1},
-	{0x1820, 0x1877, 1},
-	{0x1880, 0x18aa, 1},
-}
-
-var _Hanunoo = []Range{
-	{0x1720, 0x1734, 1},
-}
-
-var _Cypriot = []Range{
-	{0x10800, 0x10805, 1},
-	{0x10808, 0x10808, 1},
-	{0x1080a, 0x10835, 1},
-	{0x10837, 0x10838, 1},
-	{0x1083c, 0x1083c, 1},
-	{0x1083f, 0x1083f, 1},
-}
-
-var _Buginese = []Range{
-	{0x1a00, 0x1a1b, 1},
-	{0x1a1e, 0x1a1f, 1},
-}
-
-var _Bamum = []Range{
-	{0xa6a0, 0xa6f7, 1},
-	{0x16800, 0x16a38, 1},
-}
-
-var _Lepcha = []Range{
-	{0x1c00, 0x1c37, 1},
-	{0x1c3b, 0x1c49, 1},
-	{0x1c4d, 0x1c4f, 1},
-}
-
-var _Thaana = []Range{
-	{0x0780, 0x07b1, 1},
-}
-
-var _Old_Persian = []Range{
-	{0x103a0, 0x103c3, 1},
-	{0x103c8, 0x103d5, 1},
-}
-
-var _Cuneiform = []Range{
-	{0x12000, 0x1236e, 1},
-	{0x12400, 0x12462, 1},
-	{0x12470, 0x12473, 1},
-}
-
-var _Rejang = []Range{
-	{0xa930, 0xa953, 1},
-	{0xa95f, 0xa95f, 1},
-}
-
-var _Georgian = []Range{
-	{0x10a0, 0x10c5, 1},
-	{0x10d0, 0x10fa, 1},
-	{0x10fc, 0x10fc, 1},
-	{0x2d00, 0x2d25, 1},
-}
-
-var _Shavian = []Range{
-	{0x10450, 0x1047f, 1},
-}
-
-var _Lycian = []Range{
-	{0x10280, 0x1029c, 1},
-}
-
-var _Nko = []Range{
-	{0x07c0, 0x07fa, 1},
-}
-
-var _Yi = []Range{
-	{0xa000, 0xa48c, 1},
-	{0xa490, 0xa4c6, 1},
-}
-
-var _Lao = []Range{
-	{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 = []Range{
-	{0x10000, 0x1000b, 1},
-	{0x1000d, 0x10026, 1},
-	{0x10028, 0x1003a, 1},
-	{0x1003c, 0x1003d, 1},
-	{0x1003f, 0x1004d, 1},
-	{0x10050, 0x1005d, 1},
-	{0x10080, 0x100fa, 1},
-}
-
-var _Old_Italic = []Range{
-	{0x10300, 0x1031e, 1},
-	{0x10320, 0x10323, 1},
-}
-
-var _Tai_Viet = []Range{
-	{0xaa80, 0xaac2, 1},
-	{0xaadb, 0xaadf, 1},
-}
-
-var _Devanagari = []Range{
-	{0x0900, 0x0950, 1},
-	{0x0953, 0x0963, 1},
-	{0x0966, 0x096f, 1},
-	{0x0971, 0x0977, 1},
-	{0x0979, 0x097f, 1},
-	{0xa8e0, 0xa8fb, 1},
-}
-
-var _Lydian = []Range{
-	{0x10920, 0x10939, 1},
-	{0x1093f, 0x1093f, 1},
-}
-
-var _Tifinagh = []Range{
-	{0x2d30, 0x2d65, 1},
-	{0x2d6f, 0x2d70, 1},
-	{0x2d7f, 0x2d7f, 1},
-}
-
-var _Ugaritic = []Range{
-	{0x10380, 0x1039d, 1},
-	{0x1039f, 0x1039f, 1},
-}
-
-var _Thai = []Range{
-	{0x0e01, 0x0e3a, 1},
-	{0x0e40, 0x0e5b, 1},
-}
-
-var _Cyrillic = []Range{
-	{0x0400, 0x0484, 1},
-	{0x0487, 0x0527, 1},
-	{0x1d2b, 0x1d2b, 1},
-	{0x1d78, 0x1d78, 1},
-	{0x2de0, 0x2dff, 1},
-	{0xa640, 0xa673, 1},
-	{0xa67c, 0xa697, 1},
-}
-
-var _Gujarati = []Range{
-	{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 _Carian = []Range{
-	{0x102a0, 0x102d0, 1},
-}
-
-var _Phoenician = []Range{
-	{0x10900, 0x1091b, 1},
-	{0x1091f, 0x1091f, 1},
-}
-
-var _Balinese = []Range{
-	{0x1b00, 0x1b4b, 1},
-	{0x1b50, 0x1b7c, 1},
-}
-
-var _Braille = []Range{
-	{0x2800, 0x28ff, 1},
-}
-
-var _Han = []Range{
-	{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},
-	{0x20000, 0x2a6d6, 1},
-	{0x2a700, 0x2b734, 1},
-	{0x2b740, 0x2b81d, 1},
-	{0x2f800, 0x2fa1d, 1},
-}
-
-var _Gothic = []Range{
-	{0x10330, 0x1034a, 1},
+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},
+	},
+}
+
+var _Phags_Pa = &RangeTable{
+	R16: []Range16{
+		{0xa840, 0xa877, 1},
+	},
+}
+
+var _Inscriptional_Parthian = &RangeTable{
+	R16: []Range16{},
+	R32: []Range32{
+		{0x10b40, 0x10b55, 1},
+		{0x10b58, 0x10b5f, 1},
+	},
+}
+
+var _Latin = &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},
+	},
+}
+
+var _Osmanya = &RangeTable{
+	R16: []Range16{},
+	R32: []Range32{
+		{0x10480, 0x1049d, 1},
+		{0x104a0, 0x104a9, 1},
+	},
+}
+
+var _Khmer = &RangeTable{
+	R16: []Range16{
+		{0x1780, 0x17dd, 1},
+		{0x17e0, 0x17e9, 1},
+		{0x17f0, 0x17f9, 1},
+		{0x19e0, 0x19ff, 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 _Telugu = &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},
+	},
+}
+
+var _Samaritan = &RangeTable{
+	R16: []Range16{
+		{0x0800, 0x082d, 1},
+		{0x0830, 0x083e, 1},
+	},
+}
+
+var _Bopomofo = &RangeTable{
+	R16: []Range16{
+		{0x02ea, 0x02eb, 1},
+		{0x3105, 0x312d, 1},
+		{0x31a0, 0x31ba, 1},
+	},
+}
+
+var _Imperial_Aramaic = &RangeTable{
+	R16: []Range16{},
+	R32: []Range32{
+		{0x10840, 0x10855, 1},
+		{0x10857, 0x1085f, 1},
+	},
+}
+
+var _Kaithi = &RangeTable{
+	R16: []Range16{},
+	R32: []Range32{
+		{0x11080, 0x110c1, 1},
+	},
+}
+
+var _Mandaic = &RangeTable{
+	R16: []Range16{
+		{0x0840, 0x085b, 1},
+		{0x085e, 0x085e, 1},
+	},
+}
+
+var _Old_South_Arabian = &RangeTable{
+	R16: []Range16{},
+	R32: []Range32{
+		{0x10a60, 0x10a7f, 1},
+	},
+}
+
+var _Kayah_Li = &RangeTable{
+	R16: []Range16{
+		{0xa900, 0xa92f, 1},
+	},
+}
+
+var _New_Tai_Lue = &RangeTable{
+	R16: []Range16{
+		{0x1980, 0x19ab, 1},
+		{0x19b0, 0x19c9, 1},
+		{0x19d0, 0x19da, 1},
+		{0x19de, 0x19df, 1},
+	},
+}
+
+var _Tai_Le = &RangeTable{
+	R16: []Range16{
+		{0x1950, 0x196d, 1},
+		{0x1970, 0x1974, 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 _Common = &RangeTable{
+	R16: []Range16{
+		{0x0000, 0x0040, 1},
+		{0x005b, 0x0060, 1},
+		{0x007b, 0x00a9, 1},
+		{0x00ab, 0x00b9, 1},
+		{0x00bb, 0x00bf, 1},
+		{0x00d7, 0x00d7, 1},
+		{0x00f7, 0x00f7, 1},
+		{0x02b9, 0x02df, 1},
+		{0x02e5, 0x02e9, 1},
+		{0x02ec, 0x02ff, 1},
+		{0x0374, 0x0374, 1},
+		{0x037e, 0x037e, 1},
+		{0x0385, 0x0385, 1},
+		{0x0387, 0x0387, 1},
+		{0x0589, 0x0589, 1},
+		{0x060c, 0x060c, 1},
+		{0x061b, 0x061b, 1},
+		{0x061f, 0x061f, 1},
+		{0x0640, 0x0640, 1},
+		{0x0660, 0x0669, 1},
+		{0x06dd, 0x06dd, 1},
+		{0x0964, 0x0965, 1},
+		{0x0970, 0x0970, 1},
+		{0x0e3f, 0x0e3f, 1},
+		{0x0fd5, 0x0fd8, 1},
+		{0x10fb, 0x10fb, 1},
+		{0x16eb, 0x16ed, 1},
+		{0x1735, 0x1736, 1},
+		{0x1802, 0x1803, 1},
+		{0x1805, 0x1805, 1},
+		{0x1cd3, 0x1cd3, 1},
+		{0x1ce1, 0x1ce1, 1},
+		{0x1ce9, 0x1cec, 1},
+		{0x1cee, 0x1cf2, 1},
+		{0x2000, 0x200b, 1},
+		{0x200e, 0x2064, 1},
+		{0x206a, 0x2070, 1},
+		{0x2074, 0x207e, 1},
+		{0x2080, 0x208e, 1},
+		{0x20a0, 0x20b9, 1},
+		{0x2100, 0x2125, 1},
+		{0x2127, 0x2129, 1},
+		{0x212c, 0x2131, 1},
+		{0x2133, 0x214d, 1},
+		{0x214f, 0x215f, 1},
+		{0x2189, 0x2189, 1},
+		{0x2190, 0x23f3, 1},
+		{0x2400, 0x2426, 1},
+		{0x2440, 0x244a, 1},
+		{0x2460, 0x26ff, 1},
+		{0x2701, 0x27ca, 1},
+		{0x27cc, 0x27cc, 1},
+		{0x27ce, 0x27ff, 1},
+		{0x2900, 0x2b4c, 1},
+		{0x2b50, 0x2b59, 1},
+		{0x2e00, 0x2e31, 1},
+		{0x2ff0, 0x2ffb, 1},
+		{0x3000, 0x3004, 1},
+		{0x3006, 0x3006, 1},
+		{0x3008, 0x3020, 1},
+		{0x3030, 0x3037, 1},
+		{0x303c, 0x303f, 1},
+		{0x309b, 0x309c, 1},
+		{0x30a0, 0x30a0, 1},
+		{0x30fb, 0x30fc, 1},
+		{0x3190, 0x319f, 1},
+		{0x31c0, 0x31e3, 1},
+		{0x3220, 0x325f, 1},
+		{0x327f, 0x32cf, 1},
+		{0x3358, 0x33ff, 1},
+		{0x4dc0, 0x4dff, 1},
+		{0xa700, 0xa721, 1},
+		{0xa788, 0xa78a, 1},
+		{0xa830, 0xa839, 1},
+		{0xfd3e, 0xfd3f, 1},
+		{0xfdfd, 0xfdfd, 1},
+		{0xfe10, 0xfe19, 1},
+		{0xfe30, 0xfe52, 1},
+		{0xfe54, 0xfe66, 1},
+		{0xfe68, 0xfe6b, 1},
+		{0xfeff, 0xfeff, 1},
+		{0xff01, 0xff20, 1},
+		{0xff3b, 0xff40, 1},
+		{0xff5b, 0xff65, 1},
+		{0xff70, 0xff70, 1},
+		{0xff9e, 0xff9f, 1},
+		{0xffe0, 0xffe6, 1},
+		{0xffe8, 0xffee, 1},
+		{0xfff9, 0xfffd, 1},
+	},
+	R32: []Range32{
+		{0x10100, 0x10102, 1},
+		{0x10107, 0x10133, 1},
+		{0x10137, 0x1013f, 1},
+		{0x10190, 0x1019b, 1},
+		{0x101d0, 0x101fc, 1},
+		{0x1d000, 0x1d0f5, 1},
+		{0x1d100, 0x1d126, 1},
+		{0x1d129, 0x1d166, 1},
+		{0x1d16a, 0x1d17a, 1},
+		{0x1d183, 0x1d184, 1},
+		{0x1d18c, 0x1d1a9, 1},
+		{0x1d1ae, 0x1d1dd, 1},
+		{0x1d300, 0x1d356, 1},
+		{0x1d360, 0x1d371, 1},
+		{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, 0x1d7cb, 1},
+		{0x1d7ce, 0x1d7ff, 1},
+		{0x1f000, 0x1f02b, 1},
+		{0x1f030, 0x1f093, 1},
+		{0x1f0a0, 0x1f0ae, 1},
+		{0x1f0b1, 0x1f0be, 1},
+		{0x1f0c1, 0x1f0cf, 1},
+		{0x1f0d1, 0x1f0df, 1},
+		{0x1f100, 0x1f10a, 1},
+		{0x1f110, 0x1f12e, 1},
+		{0x1f130, 0x1f169, 1},
+		{0x1f170, 0x1f19a, 1},
+		{0x1f1e6, 0x1f1ff, 1},
+		{0x1f201, 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, 0x1f440, 1},
+		{0x1f442, 0x1f4f7, 1},
+		{0x1f4f9, 0x1f4fc, 1},
+		{0x1f500, 0x1f53d, 1},
+		{0x1f550, 0x1f567, 1},
+		{0x1f5fb, 0x1f5ff, 1},
+		{0x1f601, 0x1f610, 1},
+		{0x1f612, 0x1f614, 1},
+		{0x1f616, 0x1f616, 1},
+		{0x1f618, 0x1f618, 1},
+		{0x1f61a, 0x1f61a, 1},
+		{0x1f61c, 0x1f61e, 1},
+		{0x1f620, 0x1f625, 1},
+		{0x1f628, 0x1f62b, 1},
+		{0x1f62d, 0x1f62d, 1},
+		{0x1f630, 0x1f633, 1},
+		{0x1f635, 0x1f640, 1},
+		{0x1f645, 0x1f64f, 1},
+		{0x1f680, 0x1f6c5, 1},
+		{0x1f700, 0x1f773, 1},
+		{0xe0001, 0xe0001, 1},
+		{0xe0020, 0xe007f, 1},
+	},
+}
+
+var _Kannada = &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},
+	},
+}
+
+var _Old_Turkic = &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},
+	},
+}
+
+var _Brahmi = &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},
+	},
+}
+
+var _Coptic = &RangeTable{
+	R16: []Range16{
+		{0x03e2, 0x03ef, 1},
+		{0x2c80, 0x2cf1, 1},
+		{0x2cf9, 0x2cff, 1},
+	},
+}
+
+var _Hiragana = &RangeTable{
+	R16: []Range16{
+		{0x3041, 0x3096, 1},
+		{0x309d, 0x309f, 1},
+	},
+	R32: []Range32{
+		{0x1b001, 0x1b001, 1},
+		{0x1f200, 0x1f200, 1},
+	},
+}
+
+var _Limbu = &RangeTable{
+	R16: []Range16{
+		{0x1900, 0x191c, 1},
+		{0x1920, 0x192b, 1},
+		{0x1930, 0x193b, 1},
+		{0x1940, 0x1940, 1},
+		{0x1944, 0x194f, 1},
+	},
+}
+
+var _Egyptian_Hieroglyphs = &RangeTable{
+	R16: []Range16{},
+	R32: []Range32{
+		{0x13000, 0x1342e, 1},
+	},
+}
+
+var _Avestan = &RangeTable{
+	R16: []Range16{},
+	R32: []Range32{
+		{0x10b00, 0x10b35, 1},
+		{0x10b39, 0x10b3f, 1},
+	},
+}
+
+var _Myanmar = &RangeTable{
+	R16: []Range16{
+		{0x1000, 0x109f, 1},
+		{0xaa60, 0xaa7b, 1},
+	},
+}
+
+var _Armenian = &RangeTable{
+	R16: []Range16{
+		{0x0531, 0x0556, 1},
+		{0x0559, 0x055f, 1},
+		{0x0561, 0x0587, 1},
+		{0x058a, 0x058a, 1},
+		{0xfb13, 0xfb17, 1},
+	},
+}
+
+var _Sinhala = &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},
+	},
+}
+
+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 _Greek = &RangeTable{
+	R16: []Range16{
+		{0x0370, 0x0373, 1},
+		{0x0375, 0x0377, 1},
+		{0x037a, 0x037d, 1},
+		{0x0384, 0x0384, 1},
+		{0x0386, 0x0386, 1},
+		{0x0388, 0x038a, 1},
+		{0x038c, 0x038c, 1},
+		{0x038e, 0x03a1, 1},
+		{0x03a3, 0x03e1, 1},
+		{0x03f0, 0x03ff, 1},
+		{0x1d26, 0x1d2a, 1},
+		{0x1d5d, 0x1d61, 1},
+		{0x1d66, 0x1d6a, 1},
+		{0x1dbf, 0x1dbf, 1},
+		{0x1f00, 0x1f15, 1},
+		{0x1f18, 0x1f1d, 1},
+		{0x1f20, 0x1f45, 1},
+		{0x1f48, 0x1f4d, 1},
+		{0x1f50, 0x1f57, 1},
+		{0x1f59, 0x1f59, 1},
+		{0x1f5b, 0x1f5b, 1},
+		{0x1f5d, 0x1f5d, 1},
+		{0x1f5f, 0x1f7d, 1},
+		{0x1f80, 0x1fb4, 1},
+		{0x1fb6, 0x1fc4, 1},
+		{0x1fc6, 0x1fd3, 1},
+		{0x1fd6, 0x1fdb, 1},
+		{0x1fdd, 0x1fef, 1},
+		{0x1ff2, 0x1ff4, 1},
+		{0x1ff6, 0x1ffe, 1},
+		{0x2126, 0x2126, 1},
+	},
+	R32: []Range32{
+		{0x10140, 0x1018a, 1},
+		{0x1d200, 0x1d245, 1},
+	},
+}
+
+var _Cham = &RangeTable{
+	R16: []Range16{
+		{0xaa00, 0xaa36, 1},
+		{0xaa40, 0xaa4d, 1},
+		{0xaa50, 0xaa59, 1},
+		{0xaa5c, 0xaa5f, 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 _Meetei_Mayek = &RangeTable{
+	R16: []Range16{
+		{0xabc0, 0xabed, 1},
+		{0xabf0, 0xabf9, 1},
+	},
+}
+
+var _Saurashtra = &RangeTable{
+	R16: []Range16{
+		{0xa880, 0xa8c4, 1},
+		{0xa8ce, 0xa8d9, 1},
+	},
+}
+
+var _Hangul = &RangeTable{
+	R16: []Range16{
+		{0x1100, 0x11ff, 1},
+		{0x302e, 0x302f, 1},
+		{0x3131, 0x318e, 1},
+		{0x3200, 0x321e, 1},
+		{0x3260, 0x327e, 1},
+		{0xa960, 0xa97c, 1},
+		{0xac00, 0xd7a3, 1},
+		{0xd7b0, 0xd7c6, 1},
+		{0xd7cb, 0xd7fb, 1},
+		{0xffa0, 0xffbe, 1},
+		{0xffc2, 0xffc7, 1},
+		{0xffca, 0xffcf, 1},
+		{0xffd2, 0xffd7, 1},
+		{0xffda, 0xffdc, 1},
+	},
+}
+
+var _Runic = &RangeTable{
+	R16: []Range16{
+		{0x16a0, 0x16ea, 1},
+		{0x16ee, 0x16f0, 1},
+	},
+}
+
+var _Deseret = &RangeTable{
+	R16: []Range16{},
+	R32: []Range32{
+		{0x10400, 0x1044f, 1},
+	},
+}
+
+var _Lisu = &RangeTable{
+	R16: []Range16{
+		{0xa4d0, 0xa4ff, 1},
+	},
+}
+
+var _Sundanese = &RangeTable{
+	R16: []Range16{
+		{0x1b80, 0x1baa, 1},
+		{0x1bae, 0x1bb9, 1},
+	},
+}
+
+var _Glagolitic = &RangeTable{
+	R16: []Range16{
+		{0x2c00, 0x2c2e, 1},
+		{0x2c30, 0x2c5e, 1},
+	},
+}
+
+var _Oriya = &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},
+	},
+}
+
+var _Buhid = &RangeTable{
+	R16: []Range16{
+		{0x1740, 0x1753, 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 _Javanese = &RangeTable{
+	R16: []Range16{
+		{0xa980, 0xa9cd, 1},
+		{0xa9cf, 0xa9d9, 1},
+		{0xa9de, 0xa9df, 1},
+	},
+}
+
+var _Syloti_Nagri = &RangeTable{
+	R16: []Range16{
+		{0xa800, 0xa82b, 1},
+	},
+}
+
+var _Vai = &RangeTable{
+	R16: []Range16{
+		{0xa500, 0xa62b, 1},
+	},
+}
+
+var _Cherokee = &RangeTable{
+	R16: []Range16{
+		{0x13a0, 0x13f4, 1},
+	},
+}
+
+var _Ogham = &RangeTable{
+	R16: []Range16{
+		{0x1680, 0x169c, 1},
+	},
+}
+
+var _Batak = &RangeTable{
+	R16: []Range16{
+		{0x1bc0, 0x1bf3, 1},
+		{0x1bfc, 0x1bff, 1},
+	},
+}
+
+var _Syriac = &RangeTable{
+	R16: []Range16{
+		{0x0700, 0x070d, 1},
+		{0x070f, 0x074a, 1},
+		{0x074d, 0x074f, 1},
+	},
+}
+
+var _Gurmukhi = &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},
+	},
+}
+
+var _Tai_Tham = &RangeTable{
+	R16: []Range16{
+		{0x1a20, 0x1a5e, 1},
+		{0x1a60, 0x1a7c, 1},
+		{0x1a7f, 0x1a89, 1},
+		{0x1a90, 0x1a99, 1},
+		{0x1aa0, 0x1aad, 1},
+	},
+}
+
+var _Ol_Chiki = &RangeTable{
+	R16: []Range16{
+		{0x1c50, 0x1c7f, 1},
+	},
+}
+
+var _Mongolian = &RangeTable{
+	R16: []Range16{
+		{0x1800, 0x1801, 1},
+		{0x1804, 0x1804, 1},
+		{0x1806, 0x180e, 1},
+		{0x1810, 0x1819, 1},
+		{0x1820, 0x1877, 1},
+		{0x1880, 0x18aa, 1},
+	},
+}
+
+var _Hanunoo = &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},
+	},
+}
+
+var _Buginese = &RangeTable{
+	R16: []Range16{
+		{0x1a00, 0x1a1b, 1},
+		{0x1a1e, 0x1a1f, 1},
+	},
+}
+
+var _Bamum = &RangeTable{
+	R16: []Range16{
+		{0xa6a0, 0xa6f7, 1},
+	},
+	R32: []Range32{
+		{0x16800, 0x16a38, 1},
+	},
+}
+
+var _Lepcha = &RangeTable{
+	R16: []Range16{
+		{0x1c00, 0x1c37, 1},
+		{0x1c3b, 0x1c49, 1},
+		{0x1c4d, 0x1c4f, 1},
+	},
+}
+
+var _Thaana = &RangeTable{
+	R16: []Range16{
+		{0x0780, 0x07b1, 1},
+	},
+}
+
+var _Old_Persian = &RangeTable{
+	R16: []Range16{},
+	R32: []Range32{
+		{0x103a0, 0x103c3, 1},
+		{0x103c8, 0x103d5, 1},
+	},
+}
+
+var _Cuneiform = &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},
+	},
+}
+
+var _Shavian = &RangeTable{
+	R16: []Range16{},
+	R32: []Range32{
+		{0x10450, 0x1047f, 1},
+	},
+}
+
+var _Lycian = &RangeTable{
+	R16: []Range16{},
+	R32: []Range32{
+		{0x10280, 0x1029c, 1},
+	},
+}
+
+var _Nko = &RangeTable{
+	R16: []Range16{
+		{0x07c0, 0x07fa, 1},
+	},
+}
+
+var _Yi = &RangeTable{
+	R16: []Range16{
+		{0xa000, 0xa48c, 1},
+		{0xa490, 0xa4c6, 1},
+	},
+}
+
+var _Lao = &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},
+	},
+}
+
+var _Old_Italic = &RangeTable{
+	R16: []Range16{},
+	R32: []Range32{
+		{0x10300, 0x1031e, 1},
+		{0x10320, 0x10323, 1},
+	},
+}
+
+var _Tai_Viet = &RangeTable{
+	R16: []Range16{
+		{0xaa80, 0xaac2, 1},
+		{0xaadb, 0xaadf, 1},
+	},
+}
+
+var _Devanagari = &RangeTable{
+	R16: []Range16{
+		{0x0900, 0x0950, 1},
+		{0x0953, 0x0963, 1},
+		{0x0966, 0x096f, 1},
+		{0x0971, 0x0977, 1},
+		{0x0979, 0x097f, 1},
+		{0xa8e0, 0xa8fb, 1},
+	},
+}
+
+var _Lydian = &RangeTable{
+	R16: []Range16{},
+	R32: []Range32{
+		{0x10920, 0x10939, 1},
+		{0x1093f, 0x1093f, 1},
+	},
+}
+
+var _Tifinagh = &RangeTable{
+	R16: []Range16{
+		{0x2d30, 0x2d65, 1},
+		{0x2d6f, 0x2d70, 1},
+		{0x2d7f, 0x2d7f, 1},
+	},
+}
+
+var _Ugaritic = &RangeTable{
+	R16: []Range16{},
+	R32: []Range32{
+		{0x10380, 0x1039d, 1},
+		{0x1039f, 0x1039f, 1},
+	},
+}
+
+var _Thai = &RangeTable{
+	R16: []Range16{
+		{0x0e01, 0x0e3a, 1},
+		{0x0e40, 0x0e5b, 1},
+	},
+}
+
+var _Cyrillic = &RangeTable{
+	R16: []Range16{
+		{0x0400, 0x0484, 1},
+		{0x0487, 0x0527, 1},
+		{0x1d2b, 0x1d2b, 1},
+		{0x1d78, 0x1d78, 1},
+		{0x2de0, 0x2dff, 1},
+		{0xa640, 0xa673, 1},
+		{0xa67c, 0xa697, 1},
+	},
+}
+
+var _Gujarati = &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},
+	},
+}
+
+var _Carian = &RangeTable{
+	R16: []Range16{},
+	R32: []Range32{
+		{0x102a0, 0x102d0, 1},
+	},
+}
+
+var _Phoenician = &RangeTable{
+	R16: []Range16{},
+	R32: []Range32{
+		{0x10900, 0x1091b, 1},
+		{0x1091f, 0x1091f, 1},
+	},
+}
+
+var _Balinese = &RangeTable{
+	R16: []Range16{
+		{0x1b00, 0x1b4b, 1},
+		{0x1b50, 0x1b7c, 1},
+	},
+}
+
+var _Braille = &RangeTable{
+	R16: []Range16{
+		{0x2800, 0x28ff, 1},
+	},
+}
+
+var _Han = &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},
+	},
+}
+
+var _Gothic = &RangeTable{
+	R16: []Range16{},
+	R32: []Range32{
+		{0x10330, 0x1034a, 1},
+	},
 }
 
 var (
@@ -3188,7 +3509,7 @@ var (
 // DO NOT EDIT
 
 // Properties is the set of Unicode property tables.
-var Properties = map[string][]Range{
+var Properties = map[string]*RangeTable{
 	"Pattern_Syntax":                     Pattern_Syntax,
 	"Other_ID_Start":                     Other_ID_Start,
 	"Pattern_White_Space":                Pattern_White_Space,
@@ -3223,837 +3544,927 @@ var Properties = map[string][]Range{
 	"White_Space":                        White_Space,
 }
 
-var _Pattern_Syntax = []Range{
-	{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 _Other_ID_Start = []Range{
-	{0x2118, 0x2118, 1},
-	{0x212e, 0x212e, 1},
-	{0x309b, 0x309c, 1},
-}
-
-var _Pattern_White_Space = []Range{
-	{0x0009, 0x000d, 1},
-	{0x0020, 0x0020, 1},
-	{0x0085, 0x0085, 1},
-	{0x200e, 0x200f, 1},
-	{0x2028, 0x2029, 1},
-}
-
-var _Other_Lowercase = []Range{
-	{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 _Soft_Dotted = []Range{
-	{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},
-	{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 _Hex_Digit = []Range{
-	{0x0030, 0x0039, 1},
-	{0x0041, 0x0046, 1},
-	{0x0061, 0x0066, 1},
-	{0xff10, 0xff19, 1},
-	{0xff21, 0xff26, 1},
-	{0xff41, 0xff46, 1},
-}
-
-var _ASCII_Hex_Digit = []Range{
-	{0x0030, 0x0039, 1},
-	{0x0041, 0x0046, 1},
-	{0x0061, 0x0066, 1},
-}
-
-var _Deprecated = []Range{
-	{0x0149, 0x0149, 1},
-	{0x0673, 0x0673, 1},
-	{0x0f77, 0x0f77, 1},
-	{0x0f79, 0x0f79, 1},
-	{0x17a3, 0x17a4, 1},
-	{0x206a, 0x206f, 1},
-	{0x2329, 0x232a, 1},
-	{0xe0001, 0xe0001, 1},
-	{0xe0020, 0xe007f, 1},
-}
-
-var _Terminal_Punctuation = []Range{
-	{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},
-	{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 _Quotation_Mark = []Range{
-	{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 _Other_ID_Continue = []Range{
-	{0x00b7, 0x00b7, 1},
-	{0x0387, 0x0387, 1},
-	{0x1369, 0x1371, 1},
-	{0x19da, 0x19da, 1},
-}
-
-var _Bidi_Control = []Range{
-	{0x200e, 0x200f, 1},
-	{0x202a, 0x202e, 1},
-}
-
-var _Variation_Selector = []Range{
-	{0x180b, 0x180d, 1},
-	{0xfe00, 0xfe0f, 1},
-	{0xe0100, 0xe01ef, 1},
-}
-
-var _Noncharacter_Code_Point = []Range{
-	{0xfdd0, 0xfdef, 1},
-	{0xfffe, 0xffff, 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},
-}
-
-var _Other_Math = []Range{
-	{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},
-	{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 _Unified_Ideograph = []Range{
-	{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},
-	{0x20000, 0x2a6d6, 1},
-	{0x2a700, 0x2b734, 1},
-	{0x2b740, 0x2b81d, 1},
-}
-
-var _Hyphen = []Range{
-	{0x002d, 0x002d, 1},
-	{0x00ad, 0x00ad, 1},
-	{0x058a, 0x058a, 1},
-	{0x1806, 0x1806, 1},
-	{0x2010, 0x2011, 1},
-	{0x2e17, 0x2e17, 1},
-	{0x30fb, 0x30fb, 1},
-	{0xfe63, 0xfe63, 1},
-	{0xff0d, 0xff0d, 1},
-	{0xff65, 0xff65, 1},
-}
-
-var _IDS_Binary_Operator = []Range{
-	{0x2ff0, 0x2ff1, 1},
-	{0x2ff4, 0x2ffb, 1},
-}
-
-var _Logical_Order_Exception = []Range{
-	{0x0e40, 0x0e44, 1},
-	{0x0ec0, 0x0ec4, 1},
-	{0xaab5, 0xaab6, 1},
-	{0xaab9, 0xaab9, 1},
-	{0xaabb, 0xaabc, 1},
-}
-
-var _Radical = []Range{
-	{0x2e80, 0x2e99, 1},
-	{0x2e9b, 0x2ef3, 1},
-	{0x2f00, 0x2fd5, 1},
-}
-
-var _Other_Uppercase = []Range{
-	{0x2160, 0x216f, 1},
-	{0x24b6, 0x24cf, 1},
-}
-
-var _STerm = []Range{
-	{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},
-	{0x10a56, 0x10a57, 1},
-	{0x11047, 0x11048, 1},
-	{0x110be, 0x110c1, 1},
-}
-
-var _Other_Alphabetic = []Range{
-	{0x0345, 0x0345, 1},
-	{0x05b0, 0x05bd, 1},
-	{0x05bf, 0x05bf, 1},
-	{0x05c1, 0x05c2, 1},
-	{0x05c4, 0x05c5, 1},
-	{0x05c7, 0x05c7, 1},
-	{0x0610, 0x061a, 1},
-	{0x064b, 0x0657, 1},
-	{0x0659, 0x065f, 1},
-	{0x0670, 0x0670, 1},
-	{0x06d6, 0x06dc, 1},
-	{0x06e1, 0x06e4, 1},
-	{0x06e7, 0x06e8, 1},
-	{0x06ed, 0x06ed, 1},
-	{0x0711, 0x0711, 1},
-	{0x0730, 0x073f, 1},
-	{0x07a6, 0x07b0, 1},
-	{0x0816, 0x0817, 1},
-	{0x081b, 0x0823, 1},
-	{0x0825, 0x0827, 1},
-	{0x0829, 0x082c, 1},
-	{0x0900, 0x0903, 1},
-	{0x093a, 0x093b, 1},
-	{0x093e, 0x094c, 1},
-	{0x094e, 0x094f, 1},
-	{0x0955, 0x0957, 1},
-	{0x0962, 0x0963, 1},
-	{0x0981, 0x0983, 1},
-	{0x09be, 0x09c4, 1},
-	{0x09c7, 0x09c8, 1},
-	{0x09cb, 0x09cc, 1},
-	{0x09d7, 0x09d7, 1},
-	{0x09e2, 0x09e3, 1},
-	{0x0a01, 0x0a03, 1},
-	{0x0a3e, 0x0a42, 1},
-	{0x0a47, 0x0a48, 1},
-	{0x0a4b, 0x0a4c, 1},
-	{0x0a51, 0x0a51, 1},
-	{0x0a70, 0x0a71, 1},
-	{0x0a75, 0x0a75, 1},
-	{0x0a81, 0x0a83, 1},
-	{0x0abe, 0x0ac5, 1},
-	{0x0ac7, 0x0ac9, 1},
-	{0x0acb, 0x0acc, 1},
-	{0x0ae2, 0x0ae3, 1},
-	{0x0b01, 0x0b03, 1},
-	{0x0b3e, 0x0b44, 1},
-	{0x0b47, 0x0b48, 1},
-	{0x0b4b, 0x0b4c, 1},
-	{0x0b56, 0x0b57, 1},
-	{0x0b62, 0x0b63, 1},
-	{0x0b82, 0x0b82, 1},
-	{0x0bbe, 0x0bc2, 1},
-	{0x0bc6, 0x0bc8, 1},
-	{0x0bca, 0x0bcc, 1},
-	{0x0bd7, 0x0bd7, 1},
-	{0x0c01, 0x0c03, 1},
-	{0x0c3e, 0x0c44, 1},
-	{0x0c46, 0x0c48, 1},
-	{0x0c4a, 0x0c4c, 1},
-	{0x0c55, 0x0c56, 1},
-	{0x0c62, 0x0c63, 1},
-	{0x0c82, 0x0c83, 1},
-	{0x0cbe, 0x0cc4, 1},
-	{0x0cc6, 0x0cc8, 1},
-	{0x0cca, 0x0ccc, 1},
-	{0x0cd5, 0x0cd6, 1},
-	{0x0ce2, 0x0ce3, 1},
-	{0x0d02, 0x0d03, 1},
-	{0x0d3e, 0x0d44, 1},
-	{0x0d46, 0x0d48, 1},
-	{0x0d4a, 0x0d4c, 1},
-	{0x0d57, 0x0d57, 1},
-	{0x0d62, 0x0d63, 1},
-	{0x0d82, 0x0d83, 1},
-	{0x0dcf, 0x0dd4, 1},
-	{0x0dd6, 0x0dd6, 1},
-	{0x0dd8, 0x0ddf, 1},
-	{0x0df2, 0x0df3, 1},
-	{0x0e31, 0x0e31, 1},
-	{0x0e34, 0x0e3a, 1},
-	{0x0e4d, 0x0e4d, 1},
-	{0x0eb1, 0x0eb1, 1},
-	{0x0eb4, 0x0eb9, 1},
-	{0x0ebb, 0x0ebc, 1},
-	{0x0ecd, 0x0ecd, 1},
-	{0x0f71, 0x0f81, 1},
-	{0x0f8d, 0x0f97, 1},
-	{0x0f99, 0x0fbc, 1},
-	{0x102b, 0x1036, 1},
-	{0x1038, 0x1038, 1},
-	{0x103b, 0x103e, 1},
-	{0x1056, 0x1059, 1},
-	{0x105e, 0x1060, 1},
-	{0x1062, 0x1062, 1},
-	{0x1067, 0x1068, 1},
-	{0x1071, 0x1074, 1},
-	{0x1082, 0x1086, 1},
-	{0x109c, 0x109d, 1},
-	{0x135f, 0x135f, 1},
-	{0x1712, 0x1713, 1},
-	{0x1732, 0x1733, 1},
-	{0x1752, 0x1753, 1},
-	{0x1772, 0x1773, 1},
-	{0x17b6, 0x17c8, 1},
-	{0x18a9, 0x18a9, 1},
-	{0x1920, 0x192b, 1},
-	{0x1930, 0x1938, 1},
-	{0x19b0, 0x19c0, 1},
-	{0x19c8, 0x19c9, 1},
-	{0x1a17, 0x1a1b, 1},
-	{0x1a55, 0x1a5e, 1},
-	{0x1a61, 0x1a74, 1},
-	{0x1b00, 0x1b04, 1},
-	{0x1b35, 0x1b43, 1},
-	{0x1b80, 0x1b82, 1},
-	{0x1ba1, 0x1ba9, 1},
-	{0x1be7, 0x1bf1, 1},
-	{0x1c24, 0x1c35, 1},
-	{0x1cf2, 0x1cf2, 1},
-	{0x24b6, 0x24e9, 1},
-	{0x2de0, 0x2dff, 1},
-	{0xa823, 0xa827, 1},
-	{0xa880, 0xa881, 1},
-	{0xa8b4, 0xa8c3, 1},
-	{0xa926, 0xa92a, 1},
-	{0xa947, 0xa952, 1},
-	{0xa980, 0xa983, 1},
-	{0xa9b4, 0xa9bf, 1},
-	{0xaa29, 0xaa36, 1},
-	{0xaa43, 0xaa43, 1},
-	{0xaa4c, 0xaa4d, 1},
-	{0xaab0, 0xaab0, 1},
-	{0xaab2, 0xaab4, 1},
-	{0xaab7, 0xaab8, 1},
-	{0xaabe, 0xaabe, 1},
-	{0xabe3, 0xabea, 1},
-	{0xfb1e, 0xfb1e, 1},
-	{0x10a01, 0x10a03, 1},
-	{0x10a05, 0x10a06, 1},
-	{0x10a0c, 0x10a0f, 1},
-	{0x11000, 0x11002, 1},
-	{0x11038, 0x11045, 1},
-	{0x11082, 0x11082, 1},
-	{0x110b0, 0x110b8, 1},
-}
-
-var _Diacritic = []Range{
-	{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},
-	{0x110b9, 0x110ba, 1},
-	{0x1d167, 0x1d169, 1},
-	{0x1d16d, 0x1d172, 1},
-	{0x1d17b, 0x1d182, 1},
-	{0x1d185, 0x1d18b, 1},
-	{0x1d1aa, 0x1d1ad, 1},
-}
-
-var _Extender = []Range{
-	{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 = []Range{
-	{0x200c, 0x200d, 1},
-}
-
-var _Ideographic = []Range{
-	{0x3006, 0x3007, 1},
-	{0x3021, 0x3029, 1},
-	{0x3038, 0x303a, 1},
-	{0x3400, 0x4db5, 1},
-	{0x4e00, 0x9fcb, 1},
-	{0xf900, 0xfa2d, 1},
-	{0xfa30, 0xfa6d, 1},
-	{0xfa70, 0xfad9, 1},
-	{0x20000, 0x2a6d6, 1},
-	{0x2a700, 0x2b734, 1},
-	{0x2b740, 0x2b81d, 1},
-	{0x2f800, 0x2fa1d, 1},
-}
-
-var _Dash = []Range{
-	{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 = []Range{
-	{0x2ff2, 0x2ff3, 1},
-}
-
-var _Other_Grapheme_Extend = []Range{
-	{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},
-	{0x1d165, 0x1d165, 1},
-	{0x1d16e, 0x1d172, 1},
-}
-
-var _Other_Default_Ignorable_Code_Point = []Range{
-	{0x034f, 0x034f, 1},
-	{0x115f, 0x1160, 1},
-	{0x2065, 0x2069, 1},
-	{0x3164, 0x3164, 1},
-	{0xffa0, 0xffa0, 1},
-	{0xfff0, 0xfff8, 1},
-	{0xe0000, 0xe0000, 1},
-	{0xe0002, 0xe001f, 1},
-	{0xe0080, 0xe00ff, 1},
-	{0xe01f0, 0xe0fff, 1},
-}
-
-var _White_Space = []Range{
-	{0x0009, 0x000d, 1},
-	{0x0020, 0x0020, 1},
-	{0x0085, 0x0085, 1},
-	{0x00a0, 0x00a0, 1},
-	{0x1680, 0x1680, 1},
-	{0x180e, 0x180e, 1},
-	{0x2000, 0x200a, 1},
-	{0x2028, 0x2029, 1},
-	{0x202f, 0x202f, 1},
-	{0x205f, 0x205f, 1},
-	{0x3000, 0x3000, 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 _Other_ID_Start = &RangeTable{
+	R16: []Range16{
+		{0x2118, 0x2118, 1},
+		{0x212e, 0x212e, 1},
+		{0x309b, 0x309c, 1},
+	},
+}
+
+var _Pattern_White_Space = &RangeTable{
+	R16: []Range16{
+		{0x0009, 0x000d, 1},
+		{0x0020, 0x0020, 1},
+		{0x0085, 0x0085, 1},
+		{0x200e, 0x200f, 1},
+		{0x2028, 0x2029, 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 _Soft_Dotted = &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},
+	},
+}
+
+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 _ASCII_Hex_Digit = &RangeTable{
+	R16: []Range16{
+		{0x0030, 0x0039, 1},
+		{0x0041, 0x0046, 1},
+		{0x0061, 0x0066, 1},
+	},
+}
+
+var _Deprecated = &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},
+	},
+}
+
+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 _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 _Other_ID_Continue = &RangeTable{
+	R16: []Range16{
+		{0x00b7, 0x00b7, 1},
+		{0x0387, 0x0387, 1},
+		{0x1369, 0x1371, 1},
+		{0x19da, 0x19da, 1},
+	},
+}
+
+var _Bidi_Control = &RangeTable{
+	R16: []Range16{
+		{0x200e, 0x200f, 1},
+		{0x202a, 0x202e, 1},
+	},
+}
+
+var _Variation_Selector = &RangeTable{
+	R16: []Range16{
+		{0x180b, 0x180d, 1},
+		{0xfe00, 0xfe0f, 1},
+	},
+	R32: []Range32{
+		{0xe0100, 0xe01ef, 1},
+	},
+}
+
+var _Noncharacter_Code_Point = &RangeTable{
+	R16: []Range16{
+		{0xfdd0, 0xfdef, 1},
+		{0xfffe, 0xffff, 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},
+	},
+}
+
+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 _Unified_Ideograph = &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},
+	},
+	R32: []Range32{
+		{0x20000, 0x2a6d6, 1},
+		{0x2a700, 0x2b734, 1},
+		{0x2b740, 0x2b81d, 1},
+	},
+}
+
+var _Hyphen = &RangeTable{
+	R16: []Range16{
+		{0x002d, 0x002d, 1},
+		{0x00ad, 0x00ad, 1},
+		{0x058a, 0x058a, 1},
+		{0x1806, 0x1806, 1},
+		{0x2010, 0x2011, 1},
+		{0x2e17, 0x2e17, 1},
+		{0x30fb, 0x30fb, 1},
+		{0xfe63, 0xfe63, 1},
+		{0xff0d, 0xff0d, 1},
+		{0xff65, 0xff65, 1},
+	},
+}
+
+var _IDS_Binary_Operator = &RangeTable{
+	R16: []Range16{
+		{0x2ff0, 0x2ff1, 1},
+		{0x2ff4, 0x2ffb, 1},
+	},
+}
+
+var _Logical_Order_Exception = &RangeTable{
+	R16: []Range16{
+		{0x0e40, 0x0e44, 1},
+		{0x0ec0, 0x0ec4, 1},
+		{0xaab5, 0xaab6, 1},
+		{0xaab9, 0xaab9, 1},
+		{0xaabb, 0xaabc, 1},
+	},
+}
+
+var _Radical = &RangeTable{
+	R16: []Range16{
+		{0x2e80, 0x2e99, 1},
+		{0x2e9b, 0x2ef3, 1},
+		{0x2f00, 0x2fd5, 1},
+	},
+}
+
+var _Other_Uppercase = &RangeTable{
+	R16: []Range16{
+		{0x2160, 0x216f, 1},
+		{0x24b6, 0x24cf, 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 _Other_Alphabetic = &RangeTable{
+	R16: []Range16{
+		{0x0345, 0x0345, 1},
+		{0x05b0, 0x05bd, 1},
+		{0x05bf, 0x05bf, 1},
+		{0x05c1, 0x05c2, 1},
+		{0x05c4, 0x05c5, 1},
+		{0x05c7, 0x05c7, 1},
+		{0x0610, 0x061a, 1},
+		{0x064b, 0x0657, 1},
+		{0x0659, 0x065f, 1},
+		{0x0670, 0x0670, 1},
+		{0x06d6, 0x06dc, 1},
+		{0x06e1, 0x06e4, 1},
+		{0x06e7, 0x06e8, 1},
+		{0x06ed, 0x06ed, 1},
+		{0x0711, 0x0711, 1},
+		{0x0730, 0x073f, 1},
+		{0x07a6, 0x07b0, 1},
+		{0x0816, 0x0817, 1},
+		{0x081b, 0x0823, 1},
+		{0x0825, 0x0827, 1},
+		{0x0829, 0x082c, 1},
+		{0x0900, 0x0903, 1},
+		{0x093a, 0x093b, 1},
+		{0x093e, 0x094c, 1},
+		{0x094e, 0x094f, 1},
+		{0x0955, 0x0957, 1},
+		{0x0962, 0x0963, 1},
+		{0x0981, 0x0983, 1},
+		{0x09be, 0x09c4, 1},
+		{0x09c7, 0x09c8, 1},
+		{0x09cb, 0x09cc, 1},
+		{0x09d7, 0x09d7, 1},
+		{0x09e2, 0x09e3, 1},
+		{0x0a01, 0x0a03, 1},
+		{0x0a3e, 0x0a42, 1},
+		{0x0a47, 0x0a48, 1},
+		{0x0a4b, 0x0a4c, 1},
+		{0x0a51, 0x0a51, 1},
+		{0x0a70, 0x0a71, 1},
+		{0x0a75, 0x0a75, 1},
+		{0x0a81, 0x0a83, 1},
+		{0x0abe, 0x0ac5, 1},
+		{0x0ac7, 0x0ac9, 1},
+		{0x0acb, 0x0acc, 1},
+		{0x0ae2, 0x0ae3, 1},
+		{0x0b01, 0x0b03, 1},
+		{0x0b3e, 0x0b44, 1},
+		{0x0b47, 0x0b48, 1},
+		{0x0b4b, 0x0b4c, 1},
+		{0x0b56, 0x0b57, 1},
+		{0x0b62, 0x0b63, 1},
+		{0x0b82, 0x0b82, 1},
+		{0x0bbe, 0x0bc2, 1},
+		{0x0bc6, 0x0bc8, 1},
+		{0x0bca, 0x0bcc, 1},
+		{0x0bd7, 0x0bd7, 1},
+		{0x0c01, 0x0c03, 1},
+		{0x0c3e, 0x0c44, 1},
+		{0x0c46, 0x0c48, 1},
+		{0x0c4a, 0x0c4c, 1},
+		{0x0c55, 0x0c56, 1},
+		{0x0c62, 0x0c63, 1},
+		{0x0c82, 0x0c83, 1},
+		{0x0cbe, 0x0cc4, 1},
+		{0x0cc6, 0x0cc8, 1},
+		{0x0cca, 0x0ccc, 1},
+		{0x0cd5, 0x0cd6, 1},
+		{0x0ce2, 0x0ce3, 1},
+		{0x0d02, 0x0d03, 1},
+		{0x0d3e, 0x0d44, 1},
+		{0x0d46, 0x0d48, 1},
+		{0x0d4a, 0x0d4c, 1},
+		{0x0d57, 0x0d57, 1},
+		{0x0d62, 0x0d63, 1},
+		{0x0d82, 0x0d83, 1},
+		{0x0dcf, 0x0dd4, 1},
+		{0x0dd6, 0x0dd6, 1},
+		{0x0dd8, 0x0ddf, 1},
+		{0x0df2, 0x0df3, 1},
+		{0x0e31, 0x0e31, 1},
+		{0x0e34, 0x0e3a, 1},
+		{0x0e4d, 0x0e4d, 1},
+		{0x0eb1, 0x0eb1, 1},
+		{0x0eb4, 0x0eb9, 1},
+		{0x0ebb, 0x0ebc, 1},
+		{0x0ecd, 0x0ecd, 1},
+		{0x0f71, 0x0f81, 1},
+		{0x0f8d, 0x0f97, 1},
+		{0x0f99, 0x0fbc, 1},
+		{0x102b, 0x1036, 1},
+		{0x1038, 0x1038, 1},
+		{0x103b, 0x103e, 1},
+		{0x1056, 0x1059, 1},
+		{0x105e, 0x1060, 1},
+		{0x1062, 0x1062, 1},
+		{0x1067, 0x1068, 1},
+		{0x1071, 0x1074, 1},
+		{0x1082, 0x1086, 1},
+		{0x109c, 0x109d, 1},
+		{0x135f, 0x135f, 1},
+		{0x1712, 0x1713, 1},
+		{0x1732, 0x1733, 1},
+		{0x1752, 0x1753, 1},
+		{0x1772, 0x1773, 1},
+		{0x17b6, 0x17c8, 1},
+		{0x18a9, 0x18a9, 1},
+		{0x1920, 0x192b, 1},
+		{0x1930, 0x1938, 1},
+		{0x19b0, 0x19c0, 1},
+		{0x19c8, 0x19c9, 1},
+		{0x1a17, 0x1a1b, 1},
+		{0x1a55, 0x1a5e, 1},
+		{0x1a61, 0x1a74, 1},
+		{0x1b00, 0x1b04, 1},
+		{0x1b35, 0x1b43, 1},
+		{0x1b80, 0x1b82, 1},
+		{0x1ba1, 0x1ba9, 1},
+		{0x1be7, 0x1bf1, 1},
+		{0x1c24, 0x1c35, 1},
+		{0x1cf2, 0x1cf2, 1},
+		{0x24b6, 0x24e9, 1},
+		{0x2de0, 0x2dff, 1},
+		{0xa823, 0xa827, 1},
+		{0xa880, 0xa881, 1},
+		{0xa8b4, 0xa8c3, 1},
+		{0xa926, 0xa92a, 1},
+		{0xa947, 0xa952, 1},
+		{0xa980, 0xa983, 1},
+		{0xa9b4, 0xa9bf, 1},
+		{0xaa29, 0xaa36, 1},
+		{0xaa43, 0xaa43, 1},
+		{0xaa4c, 0xaa4d, 1},
+		{0xaab0, 0xaab0, 1},
+		{0xaab2, 0xaab4, 1},
+		{0xaab7, 0xaab8, 1},
+		{0xaabe, 0xaabe, 1},
+		{0xabe3, 0xabea, 1},
+		{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},
+	},
+}
+
+var _Diacritic = &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},
+	},
+	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},
+	},
+}
+
+var _Ideographic = &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},
+	},
+	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{
+	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 _White_Space = &RangeTable{
+	R16: []Range16{
+		{0x0009, 0x000d, 1},
+		{0x0020, 0x0020, 1},
+		{0x0085, 0x0085, 1},
+		{0x00a0, 0x00a0, 1},
+		{0x1680, 0x1680, 1},
+		{0x180e, 0x180e, 1},
+		{0x2000, 0x200a, 1},
+		{0x2028, 0x2029, 1},
+		{0x202f, 0x202f, 1},
+		{0x205f, 0x205f, 1},
+		{0x3000, 0x3000, 1},
+	},
 }
 
 var (
@@ -4353,3 +4764,6 @@ var _CaseRanges = []CaseRange{
 	{0x10400, 0x10427, d{0, 40, 0}},
 	{0x10428, 0x1044F, d{-40, 0, -40}},
 }
+
+// Range entries: 2715 16-bit, 545 32-bit, 3260 total.
+// Range bytes: 16290 16-bit, 6540 32-bit, 22830 total.
diff --git a/src/pkg/websocket/client.go b/src/pkg/websocket/client.go
index 3712c2d..e283821 100644
--- a/src/pkg/websocket/client.go
+++ b/src/pkg/websocket/client.go
@@ -29,7 +29,7 @@ var (
 	ErrBadWebSocketOrigin   = &ProtocolError{"missing or bad WebSocket-Origin"}
 	ErrBadWebSocketLocation = &ProtocolError{"missing or bad WebSocket-Location"}
 	ErrBadWebSocketProtocol = &ProtocolError{"missing or bad WebSocket-Protocol"}
-	ErrChallengeResponse    = &ProtocolError{"mismatch challange/response"}
+	ErrChallengeResponse    = &ProtocolError{"mismatch challenge/response"}
 	secKeyRandomChars       [0x30 - 0x21 + 0x7F - 0x3A]byte
 )
 
@@ -226,7 +226,7 @@ func handshake(resourceName, host, origin, location, protocol string, br *bufio.
 	// Step 25. send CRLF.
 	bw.WriteString("\r\n")
 
-	// Step 26. genearte 8 bytes random key.
+	// Step 26. generate 8 bytes random key.
 	key3 := generateKey3()
 	// Step 27. send it out.
 	bw.Write(key3)
@@ -262,7 +262,7 @@ func handshake(resourceName, host, origin, location, protocol string, br *bufio.
 		return ErrBadWebSocketProtocol
 	}
 
-	// Step 42-43. get expected data from challange data.
+	// Step 42-43. get expected data from challenge data.
 	expected, err := getChallengeResponse(number1, number2, key3)
 	if err != nil {
 		return err
@@ -283,7 +283,7 @@ func handshake(resourceName, host, origin, location, protocol string, br *bufio.
 }
 
 /*
-Handhake described in (soon obsolete)
+Handshake described in (soon obsolete)
 draft-hixie-thewebsocket-protocol-75.
 */
 func draft75handshake(resourceName, host, origin, location, protocol string, br *bufio.Reader, bw *bufio.Writer) (err os.Error) {
diff --git a/src/pkg/websocket/server.go b/src/pkg/websocket/server.go
index 3762652..165cbff 100644
--- a/src/pkg/websocket/server.go
+++ b/src/pkg/websocket/server.go
@@ -124,7 +124,7 @@ func (f Handler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
 	part1 := keyNumber1 / space1
 	part2 := keyNumber2 / space2
 
-	// Step 8. let challenge to be concatination of part1, part2 and key3.
+	// Step 8. let challenge be concatenation of part1, part2 and key3.
 	// Step 9. get MD5 fingerprint of challenge.
 	response, err := getChallengeResponse(part1, part2, key3)
 	if err != nil {
diff --git a/src/pkg/websocket/websocket.go b/src/pkg/websocket/websocket.go
index edde61b..7447cf8 100644
--- a/src/pkg/websocket/websocket.go
+++ b/src/pkg/websocket/websocket.go
@@ -158,7 +158,7 @@ func (ws *Conn) SetReadTimeout(nsec int64) os.Error {
 	return os.EINVAL
 }
 
-// SetWritetTimeout sets the connection's network write timeout in nanoseconds.
+// 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)
diff --git a/src/pkg/xml/xml.go b/src/pkg/xml/xml.go
index 42d8b98..2cebbce 100644
--- a/src/pkg/xml/xml.go
+++ b/src/pkg/xml/xml.go
@@ -1028,312 +1028,316 @@ func isNameByte(c byte) bool {
 // and then reformatting.  First corresponds to (Letter | '_' | ':')
 // and second corresponds to NameChar.
 
-var first = []unicode.Range{
-	{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 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.Range{
-	{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},
+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
diff --git a/src/quietgcc.bash b/src/quietgcc.bash
index e29ee4f..c99305e 100755
--- a/src/quietgcc.bash
+++ b/src/quietgcc.bash
@@ -4,7 +4,7 @@
 # license that can be found in the LICENSE file.
 
 # The master for this file is $GOROOT/src/quietgcc.bash
-# Changes made to $GOBIN/quietgcc will be overridden.
+# Changes made to $GOBIN/quietgcc will be overwritten.
 
 # Gcc output that we don't care to see.
 ignore=': error: .Each undeclared identifier'
@@ -32,7 +32,7 @@ case "$(uname -m -p)-$GOHOSTARCH" in
 esac
 
 # Run gcc, save error status, redisplay output without noise, exit with gcc status.
-tmp=/tmp/qcc.$$.$USER.out
+tmp=${TMPDIR:-/tmp}/quietgcc.$$.$USER.out
 $gcc -Wall -Wno-sign-compare -Wno-missing-braces \
 	-Wno-parentheses -Wno-unknown-pragmas -Wno-switch -Wno-comment \
 	-Werror \
diff --git a/test/bugs/bug322.dir/main.go b/test/bugs/bug322.dir/main.go
deleted file mode 100644
index 0ab5b32..0000000
--- a/test/bugs/bug322.dir/main.go
+++ /dev/null
@@ -1,47 +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 "./lib"
-
-type I interface {
-	M()
-}
-
-type PI interface {
-	PM()
-}
-
-func main() {
-	var t lib.T
-	t.M()
-	t.PM()
-
-	// This is still an error.
-	// var i1 I = t
-	// i1.M()
-	
-	// This combination is illegal because
-	// PM requires a pointer receiver.
-	// var pi1 PI = t
-	// pi1.PM()
-
-	var pt = &t
-	pt.M()
-	pt.PM()
-
-	var i2 I = pt
-	i2.M()
-
-	var pi2 PI = pt
-	pi2.PM()
-}
-
-/*
-These should not be errors anymore:
-
-bug322.dir/main.go:19: implicit assignment of unexported field 'x' of lib.T in method receiver
-bug322.dir/main.go:32: implicit assignment of unexported field 'x' of lib.T in method receiver
-*/
diff --git a/test/ddd1.go b/test/ddd1.go
index a0bc738..96a358e 100644
--- a/test/ddd1.go
+++ b/test/ddd1.go
@@ -43,4 +43,5 @@ func bad(args ...int) {
 	var x int
 	_ = unsafe.Pointer(&x...)	// ERROR "[.][.][.]"
 	_ = unsafe.Sizeof(x...)	// ERROR "[.][.][.]"
+	_ = [...]byte("foo") // ERROR "[.][.][.]"
 }
diff --git a/test/fixedbugs/bug226.dir/y.go b/test/fixedbugs/bug226.dir/y.go
index 01e8b7b..c66d592 100644
--- a/test/fixedbugs/bug226.dir/y.go
+++ b/test/fixedbugs/bug226.dir/y.go
@@ -15,7 +15,7 @@ func f() {
 	_ = x.T{};
 	_ = x.T{Y:2};
 	
-	ok1.M();	// ERROR "assignment.*T"
+	ok1.M();
 	bad1 := *ok;	// ERROR "assignment.*T"
 	bad2 := ok1;	// ERROR "assignment.*T"
 	*ok4 = ok1;	// ERROR "assignment.*T"
diff --git a/test/bugs/bug322.dir/lib.go b/test/fixedbugs/bug322.dir/lib.go
similarity index 100%
rename from test/bugs/bug322.dir/lib.go
rename to test/fixedbugs/bug322.dir/lib.go
diff --git a/test/fixedbugs/bug322.dir/main.go b/test/fixedbugs/bug322.dir/main.go
new file mode 100644
index 0000000..f403c7d
--- /dev/null
+++ b/test/fixedbugs/bug322.dir/main.go
@@ -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.
+
+package main
+
+import "./lib"
+
+type I interface {
+	M()
+}
+
+type PI interface {
+	PM()
+}
+
+func main() {
+	var t lib.T
+	t.M()
+	t.PM()
+
+	// This is still an error.
+	// var i1 I = t
+	// i1.M()
+	
+	// This combination is illegal because
+	// PM requires a pointer receiver.
+	// var pi1 PI = t
+	// pi1.PM()
+
+	var pt = &t
+	pt.M()
+	pt.PM()
+
+	var i2 I = pt
+	i2.M()
+
+	var pi2 PI = pt
+	pi2.PM()
+}
diff --git a/test/bugs/bug322.go b/test/fixedbugs/bug322.go
similarity index 100%
rename from test/bugs/bug322.go
rename to test/fixedbugs/bug322.go
diff --git a/test/fixedbugs/bug342.go b/test/fixedbugs/bug342.go
new file mode 100644
index 0000000..0852cdd
--- /dev/null
+++ b/test/fixedbugs/bug342.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 1871.
+
+package p
+
+type a interface {
+	foo(x int) (x int) // ERROR "redeclared|redefinition"
+}
+
+var b interface {
+	bar(y int) (y int) // ERROR "redeclared|redefinition"
+}
+
+/*
+Previously:
+
+bug.go:1 x redclared in this block
+    previous declaration at bug.go:1
+*/
diff --git a/test/fixedbugs/bug343.go b/test/fixedbugs/bug343.go
new file mode 100644
index 0000000..efc87e3
--- /dev/null
+++ b/test/fixedbugs/bug343.go
@@ -0,0 +1,33 @@
+// $G $D/$F.go && $L $F.$A && ./$A.out || echo BUG: bug343
+
+// Copyright 2011 The Go 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 1900
+
+package main
+
+func getArgs(data map[string]interface{}, keys ...string) map[string]string {
+       ret := map[string]string{}
+       var ok bool
+       for _, k := range keys {
+               ret[k], ok = data[k].(string)
+               if !ok {}
+       }
+       return ret
+}
+
+func main() {
+	x := getArgs(map[string]interface{}{"x":"y"}, "x")
+	if x["x"] != "y" {
+		println("BUG bug343", x)
+	}
+}
+	
+
+/*
+typecheck [1008592b0]
+.   INDREG a(1) l(15) x(24) tc(2) runtime.ret G0 string
+bug343.go:15: internal compiler error: typecheck INDREG
+*/
diff --git a/test/golden.out b/test/golden.out
index 725e8de..4400e41 100644
--- a/test/golden.out
+++ b/test/golden.out
@@ -161,8 +161,3 @@ panic: interface conversion: interface is main.T, not main.T
 0x0
 
 == bugs/
-
-=========== bugs/bug322.go
-bugs/bug322.dir/main.go:19: implicit assignment of unexported field 'x' of lib.T in method receiver
-bugs/bug322.dir/main.go:32: implicit assignment of unexported field 'x' of lib.T in method receiver
-BUG: fails incorrectly
diff --git a/test/shift1.go b/test/shift1.go
new file mode 100644
index 0000000..8fa48a0
--- /dev/null
+++ b/test/shift1.go
@@ -0,0 +1,36 @@
+// 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 1708, illegal cases.
+
+package p
+
+func f(x int) int         { return 0 }
+func g(x interface{}) int { return 0 }
+func h(x float64) int     { return 0 }
+
+// from the spec
+var (
+	s uint    = 33
+	u         = 1.0 << s // ERROR "invalid operation"
+	v float32 = 1 << s   // ERROR "invalid operation"
+)
+
+// non-constant shift expressions
+var (
+	e1       = g(2.0 << s) // ERROR "invalid operation"
+	f1       = h(2 << s)   // ERROR "invalid operation"
+	g1 int64 = 1.1 << s    // ERROR "truncated"
+)
+
+// constant shift expressions
+const c uint = 65
+
+var (
+	a2 int = 1.0 << c    // ERROR "overflow"
+	b2     = 1.0 << c    // ERROR "overflow"
+	d2     = f(1.0 << c) // ERROR "overflow"
+)
diff --git a/test/shift2.go b/test/shift2.go
new file mode 100644
index 0000000..ec4c7ad
--- /dev/null
+++ b/test/shift2.go
@@ -0,0 +1,42 @@
+// $G $D/$F.go || echo BUG: shift2
+
+// Copyright 2011 The Go 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 1708, legal cases.
+
+package p
+
+func f(x int) int         { return 0 }
+func g(x interface{}) int { return 0 }
+func h(x float64) int     { return 0 }
+
+// from the spec
+var (
+	s uint  = 33
+	i       = 1 << s         // 1 has type int
+	j int32 = 1 << s         // 1 has type int32; j == 0
+	k       = uint64(1 << s) // 1 has type uint64; k == 1<<33
+	m int   = 1.0 << s       // legal: 1.0 has type int
+	w int64 = 1.0 << 33      // legal: 1.0<<33 is a constant shift expression
+)
+
+// non-constant shift expressions
+var (
+	a1 int = 2.0 << s    // typeof(2.0) is int in this context => legal shift
+	d1     = f(2.0 << s) // typeof(2.0) is int in this context => legal shift
+)
+
+// constant shift expressions
+const c uint = 5
+
+var (
+	a2 int     = 2.0 << c    // a2 == 64 (type int)
+	b2         = 2.0 << c    // b2 == 64 (untyped integer)
+	_          = f(b2)       // verify b2 has type int
+	c2 float64 = 2 << c      // c2 == 64.0 (type float64)
+	d2         = f(2.0 << c) // == f(64)
+	e2         = g(2.0 << c) // == g(int(64))
+	f2         = h(2 << c)   // == h(float64(64.0))
+)

-- 
Packaging for Google Go



More information about the Pkg-google-commits mailing list