merge in studio-1.4-release history after reset to studio-master-dev
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..d2f212e
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,10 @@
+# Treat all files in this repo as binary, with no git magic updating
+# line endings. Windows users contributing to Go will need to use a
+# modern version of git and editors capable of LF line endings.
+#
+# We'll prevent accidental CRLF line endings from entering the repo
+# via the git-review gofmt checks.
+#
+# See golang.org/issue/9281
+
+* -text
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..5a9d62e
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+# Add no patterns to .gitignore except for files generated by the build.
+last-change
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 0000000..15167cd
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1,3 @@
+# This source code refers to The Go Authors for copyright purposes.
+# The master list of authors is in the main Go distribution,
+# visible at http://tip.golang.org/AUTHORS.
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 0000000..88dff59
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,31 @@
+# Contributing to Go
+
+Go is an open source project.
+
+It is the work of hundreds of contributors. We appreciate your help!
+
+
+## Filing issues
+
+When [filing an issue](https://golang.org/issue/new), make sure to answer these five questions:
+
+1. What version of Go are you using (`go version`)?
+2. What operating system and processor architecture are you using?
+3. What did you do?
+4. What did you expect to see?
+5. What did you see instead?
+
+General questions should go to the [golang-nuts mailing list](https://groups.google.com/group/golang-nuts) instead of the issue tracker.
+The gophers there will answer or ask you to file an issue if you've tripped over a bug.
+
+## Contributing code
+
+Please read the [Contribution Guidelines](https://golang.org/doc/contribute.html)
+before sending patches.
+
+**We do not accept GitHub pull requests**
+(we use [Gerrit](https://code.google.com/p/gerrit/) instead for code review).
+
+Unless otherwise noted, the Go source files are distributed under
+the BSD-style license found in the LICENSE file.
+
diff --git a/CONTRIBUTORS b/CONTRIBUTORS
new file mode 100644
index 0000000..1c4577e
--- /dev/null
+++ b/CONTRIBUTORS
@@ -0,0 +1,3 @@
+# This source code was written by the Go contributors.
+# The master list of contributors is in the main Go distribution,
+# visible at http://tip.golang.org/CONTRIBUTORS.
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..6a66aea
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,27 @@
+Copyright (c) 2009 The Go Authors. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+   * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+   * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+   * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/PATENTS b/PATENTS
new file mode 100644
index 0000000..7330990
--- /dev/null
+++ b/PATENTS
@@ -0,0 +1,22 @@
+Additional IP Rights Grant (Patents)
+
+"This implementation" means the copyrightable works distributed by
+Google as part of the Go project.
+
+Google hereby grants to You a perpetual, worldwide, non-exclusive,
+no-charge, royalty-free, irrevocable (except as stated in this section)
+patent license to make, have made, use, offer to sell, sell, import,
+transfer and otherwise run, modify and propagate the contents of this
+implementation of Go, where such license applies only to those patent
+claims, both currently owned or controlled by Google and acquired in
+the future, licensable by Google that are necessarily infringed by this
+implementation of Go.  This grant does not include claims that would be
+infringed only as a consequence of further modification of this
+implementation.  If you or your agent or exclusive licensee institute or
+order or agree to the institution of patent litigation against any
+entity (including a cross-claim or counterclaim in a lawsuit) alleging
+that this implementation of Go or any code incorporated within this
+implementation of Go constitutes direct or contributory patent
+infringement, or inducement of patent infringement, then any patent
+rights granted to you under this License for this implementation of Go
+shall terminate as of the date such litigation is filed.
diff --git a/README b/README
new file mode 100644
index 0000000..916ae2e
--- /dev/null
+++ b/README
@@ -0,0 +1,10 @@
+This subrepository holds the source for various packages and tools that support
+the Go programming language.
+
+Some of the tools, godoc and vet for example, are included in binary Go distributions.
+Others, including the Go oracle and the test coverage tool, can be fetched with "go get".
+
+Packages include a type-checker for Go and an implementation of the
+Static Single Assignment form (SSA) representation for Go programs.
+
+To submit changes to this repository, see http://golang.org/doc/contribute.html.
diff --git a/benchmark/parse/parse.go b/benchmark/parse/parse.go
new file mode 100644
index 0000000..b37e6f0
--- /dev/null
+++ b/benchmark/parse/parse.go
@@ -0,0 +1,131 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package parse provides support for parsing benchmark results as
+// generated by 'go test -bench'.
+package parse // import "golang.org/x/tools/benchmark/parse"
+
+import (
+	"bufio"
+	"bytes"
+	"fmt"
+	"io"
+	"strconv"
+	"strings"
+)
+
+// Flags used by Benchmark.Measured to indicate
+// which measurements a Benchmark contains.
+const (
+	NsPerOp = 1 << iota
+	MBPerS
+	AllocedBytesPerOp
+	AllocsPerOp
+)
+
+// Benchmark is one run of a single benchmark.
+type Benchmark struct {
+	Name              string  // benchmark name
+	N                 int     // number of iterations
+	NsPerOp           float64 // nanoseconds per iteration
+	AllocedBytesPerOp uint64  // bytes allocated per iteration
+	AllocsPerOp       uint64  // allocs per iteration
+	MBPerS            float64 // MB processed per second
+	Measured          int     // which measurements were recorded
+	Ord               int     // ordinal position within a benchmark run
+}
+
+// ParseLine extracts a Benchmark from a single line of testing.B
+// output.
+func ParseLine(line string) (*Benchmark, error) {
+	fields := strings.Fields(line)
+
+	// Two required, positional fields: Name and iterations.
+	if len(fields) < 2 {
+		return nil, fmt.Errorf("two fields required, have %d", len(fields))
+	}
+	if !strings.HasPrefix(fields[0], "Benchmark") {
+		return nil, fmt.Errorf(`first field does not start with "Benchmark"`)
+	}
+	n, err := strconv.Atoi(fields[1])
+	if err != nil {
+		return nil, err
+	}
+	b := &Benchmark{Name: fields[0], N: n}
+
+	// Parse any remaining pairs of fields; we've parsed one pair already.
+	for i := 1; i < len(fields)/2; i++ {
+		b.parseMeasurement(fields[i*2], fields[i*2+1])
+	}
+	return b, nil
+}
+
+func (b *Benchmark) parseMeasurement(quant string, unit string) {
+	switch unit {
+	case "ns/op":
+		if f, err := strconv.ParseFloat(quant, 64); err == nil {
+			b.NsPerOp = f
+			b.Measured |= NsPerOp
+		}
+	case "MB/s":
+		if f, err := strconv.ParseFloat(quant, 64); err == nil {
+			b.MBPerS = f
+			b.Measured |= MBPerS
+		}
+	case "B/op":
+		if i, err := strconv.ParseUint(quant, 10, 64); err == nil {
+			b.AllocedBytesPerOp = i
+			b.Measured |= AllocedBytesPerOp
+		}
+	case "allocs/op":
+		if i, err := strconv.ParseUint(quant, 10, 64); err == nil {
+			b.AllocsPerOp = i
+			b.Measured |= AllocsPerOp
+		}
+	}
+}
+
+func (b *Benchmark) String() string {
+	buf := new(bytes.Buffer)
+	fmt.Fprintf(buf, "%s %d", b.Name, b.N)
+	if (b.Measured & NsPerOp) != 0 {
+		fmt.Fprintf(buf, " %.2f ns/op", b.NsPerOp)
+	}
+	if (b.Measured & MBPerS) != 0 {
+		fmt.Fprintf(buf, " %.2f MB/s", b.MBPerS)
+	}
+	if (b.Measured & AllocedBytesPerOp) != 0 {
+		fmt.Fprintf(buf, " %d B/op", b.AllocedBytesPerOp)
+	}
+	if (b.Measured & AllocsPerOp) != 0 {
+		fmt.Fprintf(buf, " %d allocs/op", b.AllocsPerOp)
+	}
+	return buf.String()
+}
+
+// Set is a collection of benchmarks from one
+// testing.B run, keyed by name to facilitate comparison.
+type Set map[string][]*Benchmark
+
+// ParseSet extracts a Set from testing.B output.
+// ParseSet preserves the order of benchmarks that have identical
+// names.
+func ParseSet(r io.Reader) (Set, error) {
+	bb := make(Set)
+	scan := bufio.NewScanner(r)
+	ord := 0
+	for scan.Scan() {
+		if b, err := ParseLine(scan.Text()); err == nil {
+			b.Ord = ord
+			ord++
+			bb[b.Name] = append(bb[b.Name], b)
+		}
+	}
+
+	if err := scan.Err(); err != nil {
+		return nil, err
+	}
+
+	return bb, nil
+}
diff --git a/benchmark/parse/parse_test.go b/benchmark/parse/parse_test.go
new file mode 100644
index 0000000..06db848
--- /dev/null
+++ b/benchmark/parse/parse_test.go
@@ -0,0 +1,154 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package parse
+
+import (
+	"reflect"
+	"strings"
+	"testing"
+)
+
+func TestParseLine(t *testing.T) {
+	cases := []struct {
+		line string
+		want *Benchmark
+		err  bool // expect an error
+	}{
+		{
+			line: "BenchmarkEncrypt	100000000	        19.6 ns/op",
+			want: &Benchmark{
+				Name: "BenchmarkEncrypt",
+				N:    100000000, NsPerOp: 19.6,
+				Measured: NsPerOp,
+			},
+		},
+		{
+			line: "BenchmarkEncrypt	100000000	        19.6 ns/op	 817.77 MB/s",
+			want: &Benchmark{
+				Name: "BenchmarkEncrypt",
+				N:    100000000, NsPerOp: 19.6, MBPerS: 817.77,
+				Measured: NsPerOp | MBPerS,
+			},
+		},
+		{
+			line: "BenchmarkEncrypt	100000000	        19.6 ns/op	 817.77",
+			want: &Benchmark{
+				Name: "BenchmarkEncrypt",
+				N:    100000000, NsPerOp: 19.6,
+				Measured: NsPerOp,
+			},
+		},
+		{
+			line: "BenchmarkEncrypt	100000000	        19.6 ns/op	 817.77 MB/s	       5 allocs/op",
+			want: &Benchmark{
+				Name: "BenchmarkEncrypt",
+				N:    100000000, NsPerOp: 19.6, MBPerS: 817.77, AllocsPerOp: 5,
+				Measured: NsPerOp | MBPerS | AllocsPerOp,
+			},
+		},
+		{
+			line: "BenchmarkEncrypt	100000000	        19.6 ns/op	 817.77 MB/s	       3 B/op	       5 allocs/op",
+			want: &Benchmark{
+				Name: "BenchmarkEncrypt",
+				N:    100000000, NsPerOp: 19.6, MBPerS: 817.77, AllocedBytesPerOp: 3, AllocsPerOp: 5,
+				Measured: NsPerOp | MBPerS | AllocedBytesPerOp | AllocsPerOp,
+			},
+		},
+		// error handling cases
+		{
+			line: "BenchPress	100	        19.6 ns/op", // non-benchmark
+			err: true,
+		},
+		{
+			line: "BenchmarkEncrypt	lots	        19.6 ns/op", // non-int iterations
+			err: true,
+		},
+		{
+			line: "BenchmarkBridge	100000000	        19.6 smoots", // unknown unit
+			want: &Benchmark{
+				Name: "BenchmarkBridge",
+				N:    100000000,
+			},
+		},
+		{
+			line: "PASS",
+			err:  true,
+		},
+	}
+
+	for _, tt := range cases {
+		have, err := ParseLine(tt.line)
+		if tt.err && err == nil {
+			t.Errorf("parsing line %q should have failed", tt.line)
+			continue
+		}
+		if !reflect.DeepEqual(have, tt.want) {
+			t.Errorf("parsed line %q incorrectly, want %v have %v", tt.line, tt.want, have)
+		}
+	}
+}
+
+func TestParseSet(t *testing.T) {
+	// Test two things:
+	// 1. The noise that can accompany testing.B output gets ignored.
+	// 2. Benchmarks with the same name have their order preserved.
+	in := `
+		?   	crypto	[no test files]
+		PASS
+				pem_decrypt_test.go:17: test 4. %!s(x509.PEMCipher=5)
+			... [output truncated]
+
+		BenchmarkEncrypt	100000000	        19.6 ns/op
+		BenchmarkEncrypt	 5000000	       517 ns/op
+		=== RUN TestChunk
+		--- PASS: TestChunk (0.00 seconds)
+		--- SKIP: TestLinuxSendfile (0.00 seconds)
+			fs_test.go:716: skipping; linux-only test
+		BenchmarkReadRequestApachebench	 1000000	      2960 ns/op	  27.70 MB/s	     839 B/op	       9 allocs/op
+		BenchmarkClientServerParallel64	   50000	     59192 ns/op	    7028 B/op	      60 allocs/op
+		ok  	net/http	95.783s
+	`
+
+	want := Set{
+		"BenchmarkReadRequestApachebench": []*Benchmark{
+			{
+				Name: "BenchmarkReadRequestApachebench",
+				N:    1000000, NsPerOp: 2960, MBPerS: 27.70, AllocedBytesPerOp: 839, AllocsPerOp: 9,
+				Measured: NsPerOp | MBPerS | AllocedBytesPerOp | AllocsPerOp,
+				Ord:      2,
+			},
+		},
+		"BenchmarkClientServerParallel64": []*Benchmark{
+			{
+				Name: "BenchmarkClientServerParallel64",
+				N:    50000, NsPerOp: 59192, AllocedBytesPerOp: 7028, AllocsPerOp: 60,
+				Measured: NsPerOp | AllocedBytesPerOp | AllocsPerOp,
+				Ord:      3,
+			},
+		},
+		"BenchmarkEncrypt": []*Benchmark{
+			{
+				Name: "BenchmarkEncrypt",
+				N:    100000000, NsPerOp: 19.6,
+				Measured: NsPerOp,
+				Ord:      0,
+			},
+			{
+				Name: "BenchmarkEncrypt",
+				N:    5000000, NsPerOp: 517,
+				Measured: NsPerOp,
+				Ord:      1,
+			},
+		},
+	}
+
+	have, err := ParseSet(strings.NewReader(in))
+	if err != nil {
+		t.Fatalf("unexpected err during ParseSet: %v", err)
+	}
+	if !reflect.DeepEqual(want, have) {
+		t.Errorf("parsed bench set incorrectly, want %v have %v", want, have)
+	}
+}
diff --git a/blog/atom/atom.go b/blog/atom/atom.go
new file mode 100644
index 0000000..f12c31d
--- /dev/null
+++ b/blog/atom/atom.go
@@ -0,0 +1,57 @@
+// Copyright 2009 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Adapted from encoding/xml/read_test.go.
+
+// Package atom defines XML data structures for an Atom feed.
+package atom // import "golang.org/x/tools/blog/atom"
+
+import (
+	"encoding/xml"
+	"time"
+)
+
+type Feed struct {
+	XMLName xml.Name `xml:"http://www.w3.org/2005/Atom feed"`
+	Title   string   `xml:"title"`
+	ID      string   `xml:"id"`
+	Link    []Link   `xml:"link"`
+	Updated TimeStr  `xml:"updated"`
+	Author  *Person  `xml:"author"`
+	Entry   []*Entry `xml:"entry"`
+}
+
+type Entry struct {
+	Title     string  `xml:"title"`
+	ID        string  `xml:"id"`
+	Link      []Link  `xml:"link"`
+	Published TimeStr `xml:"published"`
+	Updated   TimeStr `xml:"updated"`
+	Author    *Person `xml:"author"`
+	Summary   *Text   `xml:"summary"`
+	Content   *Text   `xml:"content"`
+}
+
+type Link struct {
+	Rel  string `xml:"rel,attr"`
+	Href string `xml:"href,attr"`
+}
+
+type Person struct {
+	Name     string `xml:"name"`
+	URI      string `xml:"uri,omitempty"`
+	Email    string `xml:"email,omitempty"`
+	InnerXML string `xml:",innerxml"`
+}
+
+type Text struct {
+	Type string `xml:"type,attr"`
+	Body string `xml:",chardata"`
+}
+
+type TimeStr string
+
+func Time(t time.Time) TimeStr {
+	return TimeStr(t.Format("2006-01-02T15:04:05-07:00"))
+}
diff --git a/blog/blog.go b/blog/blog.go
new file mode 100644
index 0000000..23c8dc6
--- /dev/null
+++ b/blog/blog.go
@@ -0,0 +1,424 @@
+// Copyright 2013 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package blog implements a web server for articles written in present format.
+package blog // import "golang.org/x/tools/blog"
+
+import (
+	"bytes"
+	"encoding/json"
+	"encoding/xml"
+	"fmt"
+	"html/template"
+	"log"
+	"net/http"
+	"os"
+	"path/filepath"
+	"regexp"
+	"sort"
+	"strings"
+	"time"
+
+	"golang.org/x/tools/blog/atom"
+	"golang.org/x/tools/present"
+)
+
+var validJSONPFunc = regexp.MustCompile(`(?i)^[a-z_][a-z0-9_.]*$`)
+
+// Config specifies Server configuration values.
+type Config struct {
+	ContentPath  string // Relative or absolute location of article files and related content.
+	TemplatePath string // Relative or absolute location of template files.
+
+	BaseURL  string // Absolute base URL (for permalinks; no trailing slash).
+	BasePath string // Base URL path relative to server root (no trailing slash).
+	GodocURL string // The base URL of godoc (for menu bar; no trailing slash).
+	Hostname string // Server host name, used for rendering ATOM feeds.
+
+	HomeArticles int    // Articles to display on the home page.
+	FeedArticles int    // Articles to include in Atom and JSON feeds.
+	FeedTitle    string // The title of the Atom XML feed
+
+	PlayEnabled bool
+}
+
+// Doc represents an article adorned with presentation data.
+type Doc struct {
+	*present.Doc
+	Permalink string        // Canonical URL for this document.
+	Path      string        // Path relative to server root (including base).
+	HTML      template.HTML // rendered article
+
+	Related      []*Doc
+	Newer, Older *Doc
+}
+
+// Server implements an http.Handler that serves blog articles.
+type Server struct {
+	cfg      Config
+	docs     []*Doc
+	tags     []string
+	docPaths map[string]*Doc // key is path without BasePath.
+	docTags  map[string][]*Doc
+	template struct {
+		home, index, article, doc *template.Template
+	}
+	atomFeed []byte // pre-rendered Atom feed
+	jsonFeed []byte // pre-rendered JSON feed
+	content  http.Handler
+}
+
+// NewServer constructs a new Server using the specified config.
+func NewServer(cfg Config) (*Server, error) {
+	present.PlayEnabled = cfg.PlayEnabled
+
+	root := filepath.Join(cfg.TemplatePath, "root.tmpl")
+	parse := func(name string) (*template.Template, error) {
+		t := template.New("").Funcs(funcMap)
+		return t.ParseFiles(root, filepath.Join(cfg.TemplatePath, name))
+	}
+
+	s := &Server{cfg: cfg}
+
+	// Parse templates.
+	var err error
+	s.template.home, err = parse("home.tmpl")
+	if err != nil {
+		return nil, err
+	}
+	s.template.index, err = parse("index.tmpl")
+	if err != nil {
+		return nil, err
+	}
+	s.template.article, err = parse("article.tmpl")
+	if err != nil {
+		return nil, err
+	}
+	p := present.Template().Funcs(funcMap)
+	s.template.doc, err = p.ParseFiles(filepath.Join(cfg.TemplatePath, "doc.tmpl"))
+	if err != nil {
+		return nil, err
+	}
+
+	// Load content.
+	err = s.loadDocs(filepath.Clean(cfg.ContentPath))
+	if err != nil {
+		return nil, err
+	}
+
+	err = s.renderAtomFeed()
+	if err != nil {
+		return nil, err
+	}
+
+	err = s.renderJSONFeed()
+	if err != nil {
+		return nil, err
+	}
+
+	// Set up content file server.
+	s.content = http.StripPrefix(s.cfg.BasePath, http.FileServer(http.Dir(cfg.ContentPath)))
+
+	return s, nil
+}
+
+var funcMap = template.FuncMap{
+	"sectioned": sectioned,
+	"authors":   authors,
+}
+
+// sectioned returns true if the provided Doc contains more than one section.
+// This is used to control whether to display the table of contents and headings.
+func sectioned(d *present.Doc) bool {
+	return len(d.Sections) > 1
+}
+
+// authors returns a comma-separated list of author names.
+func authors(authors []present.Author) string {
+	var b bytes.Buffer
+	last := len(authors) - 1
+	for i, a := range authors {
+		if i > 0 {
+			if i == last {
+				b.WriteString(" and ")
+			} else {
+				b.WriteString(", ")
+			}
+		}
+		b.WriteString(authorName(a))
+	}
+	return b.String()
+}
+
+// authorName returns the first line of the Author text: the author's name.
+func authorName(a present.Author) string {
+	el := a.TextElem()
+	if len(el) == 0 {
+		return ""
+	}
+	text, ok := el[0].(present.Text)
+	if !ok || len(text.Lines) == 0 {
+		return ""
+	}
+	return text.Lines[0]
+}
+
+// loadDocs reads all content from the provided file system root, renders all
+// the articles it finds, adds them to the Server's docs field, computes the
+// denormalized docPaths, docTags, and tags fields, and populates the various
+// helper fields (Next, Previous, Related) for each Doc.
+func (s *Server) loadDocs(root string) error {
+	// Read content into docs field.
+	const ext = ".article"
+	fn := func(p string, info os.FileInfo, err error) error {
+		if filepath.Ext(p) != ext {
+			return nil
+		}
+		f, err := os.Open(p)
+		if err != nil {
+			return err
+		}
+		defer f.Close()
+		d, err := present.Parse(f, p, 0)
+		if err != nil {
+			return err
+		}
+		html := new(bytes.Buffer)
+		err = d.Render(html, s.template.doc)
+		if err != nil {
+			return err
+		}
+		p = p[len(root) : len(p)-len(ext)] // trim root and extension
+		p = filepath.ToSlash(p)
+		s.docs = append(s.docs, &Doc{
+			Doc:       d,
+			Path:      s.cfg.BasePath + p,
+			Permalink: s.cfg.BaseURL + p,
+			HTML:      template.HTML(html.String()),
+		})
+		return nil
+	}
+	err := filepath.Walk(root, fn)
+	if err != nil {
+		return err
+	}
+	sort.Sort(docsByTime(s.docs))
+
+	// Pull out doc paths and tags and put in reverse-associating maps.
+	s.docPaths = make(map[string]*Doc)
+	s.docTags = make(map[string][]*Doc)
+	for _, d := range s.docs {
+		s.docPaths[strings.TrimPrefix(d.Path, s.cfg.BasePath)] = d
+		for _, t := range d.Tags {
+			s.docTags[t] = append(s.docTags[t], d)
+		}
+	}
+
+	// Pull out unique sorted list of tags.
+	for t := range s.docTags {
+		s.tags = append(s.tags, t)
+	}
+	sort.Strings(s.tags)
+
+	// Set up presentation-related fields, Newer, Older, and Related.
+	for _, doc := range s.docs {
+		// Newer, Older: docs adjacent to doc
+		for i := range s.docs {
+			if s.docs[i] != doc {
+				continue
+			}
+			if i > 0 {
+				doc.Newer = s.docs[i-1]
+			}
+			if i+1 < len(s.docs) {
+				doc.Older = s.docs[i+1]
+			}
+			break
+		}
+
+		// Related: all docs that share tags with doc.
+		related := make(map[*Doc]bool)
+		for _, t := range doc.Tags {
+			for _, d := range s.docTags[t] {
+				if d != doc {
+					related[d] = true
+				}
+			}
+		}
+		for d := range related {
+			doc.Related = append(doc.Related, d)
+		}
+		sort.Sort(docsByTime(doc.Related))
+	}
+
+	return nil
+}
+
+// renderAtomFeed generates an XML Atom feed and stores it in the Server's
+// atomFeed field.
+func (s *Server) renderAtomFeed() error {
+	var updated time.Time
+	if len(s.docs) > 0 {
+		updated = s.docs[0].Time
+	}
+	feed := atom.Feed{
+		Title:   s.cfg.FeedTitle,
+		ID:      "tag:" + s.cfg.Hostname + ",2013:" + s.cfg.Hostname,
+		Updated: atom.Time(updated),
+		Link: []atom.Link{{
+			Rel:  "self",
+			Href: s.cfg.BaseURL + "/feed.atom",
+		}},
+	}
+	for i, doc := range s.docs {
+		if i >= s.cfg.FeedArticles {
+			break
+		}
+		e := &atom.Entry{
+			Title: doc.Title,
+			ID:    feed.ID + doc.Path,
+			Link: []atom.Link{{
+				Rel:  "alternate",
+				Href: doc.Permalink,
+			}},
+			Published: atom.Time(doc.Time),
+			Updated:   atom.Time(doc.Time),
+			Summary: &atom.Text{
+				Type: "html",
+				Body: summary(doc),
+			},
+			Content: &atom.Text{
+				Type: "html",
+				Body: string(doc.HTML),
+			},
+			Author: &atom.Person{
+				Name: authors(doc.Authors),
+			},
+		}
+		feed.Entry = append(feed.Entry, e)
+	}
+	data, err := xml.Marshal(&feed)
+	if err != nil {
+		return err
+	}
+	s.atomFeed = data
+	return nil
+}
+
+type jsonItem struct {
+	Title   string
+	Link    string
+	Time    time.Time
+	Summary string
+	Content string
+	Author  string
+}
+
+// renderJSONFeed generates a JSON feed and stores it in the Server's jsonFeed
+// field.
+func (s *Server) renderJSONFeed() error {
+	var feed []jsonItem
+	for i, doc := range s.docs {
+		if i >= s.cfg.FeedArticles {
+			break
+		}
+		item := jsonItem{
+			Title:   doc.Title,
+			Link:    doc.Permalink,
+			Time:    doc.Time,
+			Summary: summary(doc),
+			Content: string(doc.HTML),
+			Author:  authors(doc.Authors),
+		}
+		feed = append(feed, item)
+	}
+	data, err := json.Marshal(feed)
+	if err != nil {
+		return err
+	}
+	s.jsonFeed = data
+	return nil
+}
+
+// summary returns the first paragraph of text from the provided Doc.
+func summary(d *Doc) string {
+	if len(d.Sections) == 0 {
+		return ""
+	}
+	for _, elem := range d.Sections[0].Elem {
+		text, ok := elem.(present.Text)
+		if !ok || text.Pre {
+			// skip everything but non-text elements
+			continue
+		}
+		var buf bytes.Buffer
+		for _, s := range text.Lines {
+			buf.WriteString(string(present.Style(s)))
+			buf.WriteByte('\n')
+		}
+		return buf.String()
+	}
+	return ""
+}
+
+// rootData encapsulates data destined for the root template.
+type rootData struct {
+	Doc      *Doc
+	BasePath string
+	GodocURL string
+	Data     interface{}
+}
+
+// ServeHTTP serves the front, index, and article pages
+// as well as the ATOM and JSON feeds.
+func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+	var (
+		d = rootData{BasePath: s.cfg.BasePath, GodocURL: s.cfg.GodocURL}
+		t *template.Template
+	)
+	switch p := strings.TrimPrefix(r.URL.Path, s.cfg.BasePath); p {
+	case "/":
+		d.Data = s.docs
+		if len(s.docs) > s.cfg.HomeArticles {
+			d.Data = s.docs[:s.cfg.HomeArticles]
+		}
+		t = s.template.home
+	case "/index":
+		d.Data = s.docs
+		t = s.template.index
+	case "/feed.atom", "/feeds/posts/default":
+		w.Header().Set("Content-type", "application/atom+xml; charset=utf-8")
+		w.Write(s.atomFeed)
+		return
+	case "/.json":
+		if p := r.FormValue("jsonp"); validJSONPFunc.MatchString(p) {
+			w.Header().Set("Content-type", "application/javascript; charset=utf-8")
+			fmt.Fprintf(w, "%v(%s)", p, s.jsonFeed)
+			return
+		}
+		w.Header().Set("Content-type", "application/json; charset=utf-8")
+		w.Write(s.jsonFeed)
+		return
+	default:
+		doc, ok := s.docPaths[p]
+		if !ok {
+			// Not a doc; try to just serve static content.
+			s.content.ServeHTTP(w, r)
+			return
+		}
+		d.Doc = doc
+		t = s.template.article
+	}
+	err := t.ExecuteTemplate(w, "root", d)
+	if err != nil {
+		log.Println(err)
+	}
+}
+
+// docsByTime implements sort.Interface, sorting Docs by their Time field.
+type docsByTime []*Doc
+
+func (s docsByTime) Len() int           { return len(s) }
+func (s docsByTime) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }
+func (s docsByTime) Less(i, j int) bool { return s[i].Time.After(s[j].Time) }
diff --git a/cmd/benchcmp/benchcmp.go b/cmd/benchcmp/benchcmp.go
new file mode 100644
index 0000000..32f3a1c
--- /dev/null
+++ b/cmd/benchcmp/benchcmp.go
@@ -0,0 +1,184 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+	"flag"
+	"fmt"
+	"os"
+	"sort"
+	"strconv"
+	"text/tabwriter"
+
+	"golang.org/x/tools/benchmark/parse"
+)
+
+var (
+	changedOnly = flag.Bool("changed", false, "show only benchmarks that have changed")
+	magSort     = flag.Bool("mag", false, "sort benchmarks by magnitude of change")
+	best        = flag.Bool("best", false, "compare best times from old and new")
+)
+
+const usageFooter = `
+Each input file should be from:
+	go test -run=NONE -bench=. > [old,new].txt
+
+Benchcmp compares old and new for each benchmark.
+
+If -test.benchmem=true is added to the "go test" command
+benchcmp will also compare memory allocations.
+`
+
+func main() {
+	flag.Usage = func() {
+		fmt.Fprintf(os.Stderr, "usage: %s old.txt new.txt\n\n", os.Args[0])
+		flag.PrintDefaults()
+		fmt.Fprint(os.Stderr, usageFooter)
+		os.Exit(2)
+	}
+	flag.Parse()
+	if flag.NArg() != 2 {
+		flag.Usage()
+	}
+
+	before := parseFile(flag.Arg(0))
+	after := parseFile(flag.Arg(1))
+
+	cmps, warnings := Correlate(before, after)
+
+	for _, warn := range warnings {
+		fmt.Fprintln(os.Stderr, warn)
+	}
+
+	if len(cmps) == 0 {
+		fatal("benchcmp: no repeated benchmarks")
+	}
+
+	w := new(tabwriter.Writer)
+	w.Init(os.Stdout, 0, 0, 5, ' ', 0)
+	defer w.Flush()
+
+	var header bool // Has the header has been displayed yet for a given block?
+
+	if *magSort {
+		sort.Sort(ByDeltaNsPerOp(cmps))
+	} else {
+		sort.Sort(ByParseOrder(cmps))
+	}
+	for _, cmp := range cmps {
+		if !cmp.Measured(parse.NsPerOp) {
+			continue
+		}
+		if delta := cmp.DeltaNsPerOp(); !*changedOnly || delta.Changed() {
+			if !header {
+				fmt.Fprint(w, "benchmark\told ns/op\tnew ns/op\tdelta\n")
+				header = true
+			}
+			fmt.Fprintf(w, "%s\t%s\t%s\t%s\n", cmp.Name(), formatNs(cmp.Before.NsPerOp), formatNs(cmp.After.NsPerOp), delta.Percent())
+		}
+	}
+
+	header = false
+	if *magSort {
+		sort.Sort(ByDeltaMBPerS(cmps))
+	}
+	for _, cmp := range cmps {
+		if !cmp.Measured(parse.MBPerS) {
+			continue
+		}
+		if delta := cmp.DeltaMBPerS(); !*changedOnly || delta.Changed() {
+			if !header {
+				fmt.Fprint(w, "\nbenchmark\told MB/s\tnew MB/s\tspeedup\n")
+				header = true
+			}
+			fmt.Fprintf(w, "%s\t%.2f\t%.2f\t%s\n", cmp.Name(), cmp.Before.MBPerS, cmp.After.MBPerS, delta.Multiple())
+		}
+	}
+
+	header = false
+	if *magSort {
+		sort.Sort(ByDeltaAllocsPerOp(cmps))
+	}
+	for _, cmp := range cmps {
+		if !cmp.Measured(parse.AllocsPerOp) {
+			continue
+		}
+		if delta := cmp.DeltaAllocsPerOp(); !*changedOnly || delta.Changed() {
+			if !header {
+				fmt.Fprint(w, "\nbenchmark\told allocs\tnew allocs\tdelta\n")
+				header = true
+			}
+			fmt.Fprintf(w, "%s\t%d\t%d\t%s\n", cmp.Name(), cmp.Before.AllocsPerOp, cmp.After.AllocsPerOp, delta.Percent())
+		}
+	}
+
+	header = false
+	if *magSort {
+		sort.Sort(ByDeltaAllocedBytesPerOp(cmps))
+	}
+	for _, cmp := range cmps {
+		if !cmp.Measured(parse.AllocedBytesPerOp) {
+			continue
+		}
+		if delta := cmp.DeltaAllocedBytesPerOp(); !*changedOnly || delta.Changed() {
+			if !header {
+				fmt.Fprint(w, "\nbenchmark\told bytes\tnew bytes\tdelta\n")
+				header = true
+			}
+			fmt.Fprintf(w, "%s\t%d\t%d\t%s\n", cmp.Name(), cmp.Before.AllocedBytesPerOp, cmp.After.AllocedBytesPerOp, cmp.DeltaAllocedBytesPerOp().Percent())
+		}
+	}
+}
+
+func fatal(msg interface{}) {
+	fmt.Fprintln(os.Stderr, msg)
+	os.Exit(1)
+}
+
+func parseFile(path string) parse.Set {
+	f, err := os.Open(path)
+	if err != nil {
+		fatal(err)
+	}
+	defer f.Close()
+	bb, err := parse.ParseSet(f)
+	if err != nil {
+		fatal(err)
+	}
+	if *best {
+		selectBest(bb)
+	}
+	return bb
+}
+
+func selectBest(bs parse.Set) {
+	for name, bb := range bs {
+		if len(bb) < 2 {
+			continue
+		}
+		ord := bb[0].Ord
+		best := bb[0]
+		for _, b := range bb {
+			if b.NsPerOp < best.NsPerOp {
+				b.Ord = ord
+				best = b
+			}
+		}
+		bs[name] = []*parse.Benchmark{best}
+	}
+}
+
+// formatNs formats ns measurements to expose a useful amount of
+// precision. It mirrors the ns precision logic of testing.B.
+func formatNs(ns float64) string {
+	prec := 0
+	switch {
+	case ns < 10:
+		prec = 2
+	case ns < 100:
+		prec = 1
+	}
+	return strconv.FormatFloat(ns, 'f', prec, 64)
+}
diff --git a/cmd/benchcmp/benchcmp_test.go b/cmd/benchcmp/benchcmp_test.go
new file mode 100644
index 0000000..2226079
--- /dev/null
+++ b/cmd/benchcmp/benchcmp_test.go
@@ -0,0 +1,59 @@
+package main
+
+import (
+	"reflect"
+	"testing"
+
+	"golang.org/x/tools/benchmark/parse"
+)
+
+func TestSelectBest(t *testing.T) {
+	have := parse.Set{
+		"Benchmark1": []*parse.Benchmark{
+			{
+				Name: "Benchmark1",
+				N:    10, NsPerOp: 100, Measured: parse.NsPerOp,
+				Ord: 0,
+			},
+			{
+				Name: "Benchmark1",
+				N:    10, NsPerOp: 50, Measured: parse.NsPerOp,
+				Ord: 3,
+			},
+		},
+		"Benchmark2": []*parse.Benchmark{
+			{
+				Name: "Benchmark2",
+				N:    10, NsPerOp: 60, Measured: parse.NsPerOp,
+				Ord: 1,
+			},
+			{
+				Name: "Benchmark2",
+				N:    10, NsPerOp: 500, Measured: parse.NsPerOp,
+				Ord: 2,
+			},
+		},
+	}
+
+	want := parse.Set{
+		"Benchmark1": []*parse.Benchmark{
+			{
+				Name: "Benchmark1",
+				N:    10, NsPerOp: 50, Measured: parse.NsPerOp,
+				Ord: 0,
+			},
+		},
+		"Benchmark2": []*parse.Benchmark{
+			{
+				Name: "Benchmark2",
+				N:    10, NsPerOp: 60, Measured: parse.NsPerOp,
+				Ord: 1,
+			},
+		},
+	}
+
+	selectBest(have)
+	if !reflect.DeepEqual(want, have) {
+		t.Errorf("filtered bench set incorrectly, want %v have %v", want, have)
+	}
+}
diff --git a/cmd/benchcmp/compare.go b/cmd/benchcmp/compare.go
new file mode 100644
index 0000000..c3f5e89
--- /dev/null
+++ b/cmd/benchcmp/compare.go
@@ -0,0 +1,156 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+	"fmt"
+	"math"
+
+	"golang.org/x/tools/benchmark/parse"
+)
+
+// BenchCmp is a pair of benchmarks.
+type BenchCmp struct {
+	Before *parse.Benchmark
+	After  *parse.Benchmark
+}
+
+// Correlate correlates benchmarks from two BenchSets.
+func Correlate(before, after parse.Set) (cmps []BenchCmp, warnings []string) {
+	cmps = make([]BenchCmp, 0, len(after))
+	for name, beforebb := range before {
+		afterbb := after[name]
+		if len(beforebb) != len(afterbb) {
+			warnings = append(warnings, fmt.Sprintf("ignoring %s: before has %d instances, after has %d", name, len(beforebb), len(afterbb)))
+			continue
+		}
+		for i, beforeb := range beforebb {
+			afterb := afterbb[i]
+			cmps = append(cmps, BenchCmp{beforeb, afterb})
+		}
+	}
+	return
+}
+
+func (c BenchCmp) Name() string           { return c.Before.Name }
+func (c BenchCmp) String() string         { return fmt.Sprintf("<%s, %s>", c.Before, c.After) }
+func (c BenchCmp) Measured(flag int) bool { return (c.Before.Measured & c.After.Measured & flag) != 0 }
+func (c BenchCmp) DeltaNsPerOp() Delta    { return Delta{c.Before.NsPerOp, c.After.NsPerOp} }
+func (c BenchCmp) DeltaMBPerS() Delta     { return Delta{c.Before.MBPerS, c.After.MBPerS} }
+func (c BenchCmp) DeltaAllocedBytesPerOp() Delta {
+	return Delta{float64(c.Before.AllocedBytesPerOp), float64(c.After.AllocedBytesPerOp)}
+}
+func (c BenchCmp) DeltaAllocsPerOp() Delta {
+	return Delta{float64(c.Before.AllocsPerOp), float64(c.After.AllocsPerOp)}
+}
+
+// Delta is the before and after value for a benchmark measurement.
+// Both must be non-negative.
+type Delta struct {
+	Before float64
+	After  float64
+}
+
+// mag calculates the magnitude of a change, regardless of the direction of
+// the change. mag is intended for sorting and has no independent meaning.
+func (d Delta) mag() float64 {
+	switch {
+	case d.Before != 0 && d.After != 0 && d.Before >= d.After:
+		return d.After / d.Before
+	case d.Before != 0 && d.After != 0 && d.Before < d.After:
+		return d.Before / d.After
+	case d.Before == 0 && d.After == 0:
+		return 1
+	default:
+		// 0 -> 1 or 1 -> 0
+		// These are significant changes and worth surfacing.
+		return math.Inf(1)
+	}
+}
+
+// Changed reports whether the benchmark quantities are different.
+func (d Delta) Changed() bool { return d.Before != d.After }
+
+// Float64 returns After / Before. If Before is 0, Float64 returns
+// 1 if After is also 0, and +Inf otherwise.
+func (d Delta) Float64() float64 {
+	switch {
+	case d.Before != 0:
+		return d.After / d.Before
+	case d.After == 0:
+		return 1
+	default:
+		return math.Inf(1)
+	}
+}
+
+// Percent formats a Delta as a percent change, ranging from -100% up.
+func (d Delta) Percent() string {
+	return fmt.Sprintf("%+.2f%%", 100*d.Float64()-100)
+}
+
+// Multiple formats a Delta as a multiplier, ranging from 0.00x up.
+func (d Delta) Multiple() string {
+	return fmt.Sprintf("%.2fx", d.Float64())
+}
+
+func (d Delta) String() string {
+	return fmt.Sprintf("Δ(%f, %f)", d.Before, d.After)
+}
+
+// ByParseOrder sorts BenchCmps to match the order in
+// which the Before benchmarks were presented to Parse.
+type ByParseOrder []BenchCmp
+
+func (x ByParseOrder) Len() int           { return len(x) }
+func (x ByParseOrder) Swap(i, j int)      { x[i], x[j] = x[j], x[i] }
+func (x ByParseOrder) Less(i, j int) bool { return x[i].Before.Ord < x[j].Before.Ord }
+
+// lessByDelta provides lexicographic ordering:
+//   * largest delta by magnitude
+//   * alphabetic by name
+func lessByDelta(i, j BenchCmp, calcDelta func(BenchCmp) Delta) bool {
+	iDelta, jDelta := calcDelta(i).mag(), calcDelta(j).mag()
+	if iDelta != jDelta {
+		return iDelta < jDelta
+	}
+	return i.Name() < j.Name()
+}
+
+// ByDeltaNsPerOp sorts BenchCmps lexicographically by change
+// in ns/op, descending, then by benchmark name.
+type ByDeltaNsPerOp []BenchCmp
+
+func (x ByDeltaNsPerOp) Len() int           { return len(x) }
+func (x ByDeltaNsPerOp) Swap(i, j int)      { x[i], x[j] = x[j], x[i] }
+func (x ByDeltaNsPerOp) Less(i, j int) bool { return lessByDelta(x[i], x[j], BenchCmp.DeltaNsPerOp) }
+
+// ByDeltaMBPerS sorts BenchCmps lexicographically by change
+// in MB/s, descending, then by benchmark name.
+type ByDeltaMBPerS []BenchCmp
+
+func (x ByDeltaMBPerS) Len() int           { return len(x) }
+func (x ByDeltaMBPerS) Swap(i, j int)      { x[i], x[j] = x[j], x[i] }
+func (x ByDeltaMBPerS) Less(i, j int) bool { return lessByDelta(x[i], x[j], BenchCmp.DeltaMBPerS) }
+
+// ByDeltaAllocedBytesPerOp sorts BenchCmps lexicographically by change
+// in B/op, descending, then by benchmark name.
+type ByDeltaAllocedBytesPerOp []BenchCmp
+
+func (x ByDeltaAllocedBytesPerOp) Len() int      { return len(x) }
+func (x ByDeltaAllocedBytesPerOp) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
+func (x ByDeltaAllocedBytesPerOp) Less(i, j int) bool {
+	return lessByDelta(x[i], x[j], BenchCmp.DeltaAllocedBytesPerOp)
+}
+
+// ByDeltaAllocsPerOp sorts BenchCmps lexicographically by change
+// in allocs/op, descending, then by benchmark name.
+type ByDeltaAllocsPerOp []BenchCmp
+
+func (x ByDeltaAllocsPerOp) Len() int      { return len(x) }
+func (x ByDeltaAllocsPerOp) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
+func (x ByDeltaAllocsPerOp) Less(i, j int) bool {
+	return lessByDelta(x[i], x[j], BenchCmp.DeltaAllocsPerOp)
+}
diff --git a/cmd/benchcmp/compare_test.go b/cmd/benchcmp/compare_test.go
new file mode 100644
index 0000000..3403796
--- /dev/null
+++ b/cmd/benchcmp/compare_test.go
@@ -0,0 +1,133 @@
+// Copyright 2014 The Go Authors. 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 (
+	"math"
+	"reflect"
+	"sort"
+	"testing"
+
+	"golang.org/x/tools/benchmark/parse"
+)
+
+func TestDelta(t *testing.T) {
+	cases := []struct {
+		before  float64
+		after   float64
+		mag     float64
+		f       float64
+		changed bool
+		pct     string
+		mult    string
+	}{
+		{before: 1, after: 1, mag: 1, f: 1, changed: false, pct: "+0.00%", mult: "1.00x"},
+		{before: 1, after: 2, mag: 0.5, f: 2, changed: true, pct: "+100.00%", mult: "2.00x"},
+		{before: 2, after: 1, mag: 0.5, f: 0.5, changed: true, pct: "-50.00%", mult: "0.50x"},
+		{before: 0, after: 0, mag: 1, f: 1, changed: false, pct: "+0.00%", mult: "1.00x"},
+		{before: 1, after: 0, mag: math.Inf(1), f: 0, changed: true, pct: "-100.00%", mult: "0.00x"},
+		{before: 0, after: 1, mag: math.Inf(1), f: math.Inf(1), changed: true, pct: "+Inf%", mult: "+Infx"},
+	}
+	for _, tt := range cases {
+		d := Delta{tt.before, tt.after}
+		if want, have := tt.mag, d.mag(); want != have {
+			t.Errorf("%s.mag(): want %f have %f", d, want, have)
+		}
+		if want, have := tt.f, d.Float64(); want != have {
+			t.Errorf("%s.Float64(): want %f have %f", d, want, have)
+		}
+		if want, have := tt.changed, d.Changed(); want != have {
+			t.Errorf("%s.Changed(): want %t have %t", d, want, have)
+		}
+		if want, have := tt.pct, d.Percent(); want != have {
+			t.Errorf("%s.Percent(): want %q have %q", d, want, have)
+		}
+		if want, have := tt.mult, d.Multiple(); want != have {
+			t.Errorf("%s.Multiple(): want %q have %q", d, want, have)
+		}
+	}
+}
+
+func TestCorrelate(t *testing.T) {
+	// Benches that are going to be successfully correlated get N thus:
+	//   0x<counter><num benches><b = before | a = after>
+	// Read this: "<counter> of <num benches>, from <before|after>".
+	before := parse.Set{
+		"BenchmarkOneEach":   []*parse.Benchmark{{Name: "BenchmarkOneEach", N: 0x11b}},
+		"BenchmarkOneToNone": []*parse.Benchmark{{Name: "BenchmarkOneToNone"}},
+		"BenchmarkOneToTwo":  []*parse.Benchmark{{Name: "BenchmarkOneToTwo"}},
+		"BenchmarkTwoToOne": []*parse.Benchmark{
+			{Name: "BenchmarkTwoToOne"},
+			{Name: "BenchmarkTwoToOne"},
+		},
+		"BenchmarkTwoEach": []*parse.Benchmark{
+			{Name: "BenchmarkTwoEach", N: 0x12b},
+			{Name: "BenchmarkTwoEach", N: 0x22b},
+		},
+	}
+
+	after := parse.Set{
+		"BenchmarkOneEach":   []*parse.Benchmark{{Name: "BenchmarkOneEach", N: 0x11a}},
+		"BenchmarkNoneToOne": []*parse.Benchmark{{Name: "BenchmarkNoneToOne"}},
+		"BenchmarkTwoToOne":  []*parse.Benchmark{{Name: "BenchmarkTwoToOne"}},
+		"BenchmarkOneToTwo": []*parse.Benchmark{
+			{Name: "BenchmarkOneToTwo"},
+			{Name: "BenchmarkOneToTwo"},
+		},
+		"BenchmarkTwoEach": []*parse.Benchmark{
+			{Name: "BenchmarkTwoEach", N: 0x12a},
+			{Name: "BenchmarkTwoEach", N: 0x22a},
+		},
+	}
+
+	pairs, errs := Correlate(before, after)
+
+	// Fail to match: BenchmarkOneToNone, BenchmarkOneToTwo, BenchmarkTwoToOne.
+	// Correlate does not notice BenchmarkNoneToOne.
+	if len(errs) != 3 {
+		t.Errorf("Correlated expected 4 errors, got %d: %v", len(errs), errs)
+	}
+
+	// Want three correlated pairs: one BenchmarkOneEach, two BenchmarkTwoEach.
+	if len(pairs) != 3 {
+		t.Fatalf("Correlated expected 3 pairs, got %v", pairs)
+	}
+
+	for _, pair := range pairs {
+		if pair.Before.N&0xF != 0xb {
+			t.Errorf("unexpected Before in pair %s", pair)
+		}
+		if pair.After.N&0xF != 0xa {
+			t.Errorf("unexpected After in pair %s", pair)
+		}
+		if pair.Before.N>>4 != pair.After.N>>4 {
+			t.Errorf("mismatched pair %s", pair)
+		}
+	}
+}
+
+func TestBenchCmpSorting(t *testing.T) {
+	c := []BenchCmp{
+		{&parse.Benchmark{Name: "BenchmarkMuchFaster", NsPerOp: 10, Ord: 3}, &parse.Benchmark{Name: "BenchmarkMuchFaster", NsPerOp: 1}},
+		{&parse.Benchmark{Name: "BenchmarkSameB", NsPerOp: 5, Ord: 1}, &parse.Benchmark{Name: "BenchmarkSameB", NsPerOp: 5}},
+		{&parse.Benchmark{Name: "BenchmarkSameA", NsPerOp: 5, Ord: 2}, &parse.Benchmark{Name: "BenchmarkSameA", NsPerOp: 5}},
+		{&parse.Benchmark{Name: "BenchmarkSlower", NsPerOp: 10, Ord: 0}, &parse.Benchmark{Name: "BenchmarkSlower", NsPerOp: 11}},
+	}
+
+	// Test just one magnitude-based sort order; they are symmetric.
+	sort.Sort(ByDeltaNsPerOp(c))
+	want := []string{"BenchmarkMuchFaster", "BenchmarkSlower", "BenchmarkSameA", "BenchmarkSameB"}
+	have := []string{c[0].Name(), c[1].Name(), c[2].Name(), c[3].Name()}
+	if !reflect.DeepEqual(want, have) {
+		t.Errorf("ByDeltaNsOp incorrect sorting: want %v have %v", want, have)
+	}
+
+	sort.Sort(ByParseOrder(c))
+	want = []string{"BenchmarkSlower", "BenchmarkSameB", "BenchmarkSameA", "BenchmarkMuchFaster"}
+	have = []string{c[0].Name(), c[1].Name(), c[2].Name(), c[3].Name()}
+	if !reflect.DeepEqual(want, have) {
+		t.Errorf("ByParseOrder incorrect sorting: want %v have %v", want, have)
+	}
+}
diff --git a/cmd/benchcmp/doc.go b/cmd/benchcmp/doc.go
new file mode 100644
index 0000000..f5c7a36
--- /dev/null
+++ b/cmd/benchcmp/doc.go
@@ -0,0 +1,37 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+/*
+
+The benchcmp command displays performance changes between benchmarks.
+
+Benchcmp parses the output of two 'go test' benchmark runs,
+correlates the results per benchmark, and displays the deltas.
+
+To measure the performance impact of a change, use 'go test'
+to run benchmarks before and after the change:
+
+	go test -run=NONE -bench=. ./... > old.txt
+	# make changes
+	go test -run=NONE -bench=. ./... > new.txt
+
+Then feed the benchmark results to benchcmp:
+
+	benchcmp old.txt new.txt
+
+Benchcmp will summarize and display the performance changes,
+in a format like this:
+
+	$ benchcmp old.txt new.txt
+	benchmark           old ns/op     new ns/op     delta
+	BenchmarkConcat     523           68.6          -86.88%
+
+	benchmark           old allocs     new allocs     delta
+	BenchmarkConcat     3              1              -66.67%
+
+	benchmark           old bytes     new bytes     delta
+	BenchmarkConcat     80            48            -40.00%
+
+*/
+package main // import "golang.org/x/tools/cmd/benchcmp"
diff --git a/cmd/callgraph/main.go b/cmd/callgraph/main.go
new file mode 100644
index 0000000..29179dd
--- /dev/null
+++ b/cmd/callgraph/main.go
@@ -0,0 +1,337 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// callgraph: a tool for reporting the call graph of a Go program.
+// See Usage for details, or run with -help.
+package main // import "golang.org/x/tools/cmd/callgraph"
+
+// TODO(adonovan):
+//
+// Features:
+// - restrict graph to a single package
+// - output
+//   - functions reachable from root (use digraph tool?)
+//   - unreachable functions (use digraph tool?)
+//   - dynamic (runtime) types
+//   - indexed output (numbered nodes)
+//   - JSON output
+//   - additional template fields:
+//     callee file/line/col
+
+import (
+	"bytes"
+	"flag"
+	"fmt"
+	"go/build"
+	"go/token"
+	"io"
+	"os"
+	"runtime"
+	"text/template"
+
+	"golang.org/x/tools/go/buildutil"
+	"golang.org/x/tools/go/callgraph"
+	"golang.org/x/tools/go/callgraph/cha"
+	"golang.org/x/tools/go/callgraph/rta"
+	"golang.org/x/tools/go/callgraph/static"
+	"golang.org/x/tools/go/loader"
+	"golang.org/x/tools/go/pointer"
+	"golang.org/x/tools/go/ssa"
+	"golang.org/x/tools/go/ssa/ssautil"
+)
+
+var algoFlag = flag.String("algo", "rta",
+	`Call graph construction algorithm (static, cha, rta, pta)`)
+
+var testFlag = flag.Bool("test", false,
+	"Loads test code (*_test.go) for imported packages")
+
+var formatFlag = flag.String("format",
+	"{{.Caller}}\t--{{.Dynamic}}-{{.Line}}:{{.Column}}-->\t{{.Callee}}",
+	"A template expression specifying how to format an edge")
+
+func init() {
+	flag.Var((*buildutil.TagsFlag)(&build.Default.BuildTags), "tags", buildutil.TagsFlagDoc)
+}
+
+const Usage = `callgraph: display the the call graph of a Go program.
+
+Usage:
+
+  callgraph [-algo=static|cha|rta|pta] [-test] [-format=...] <args>...
+
+Flags:
+
+-algo      Specifies the call-graph construction algorithm, one of:
+
+            static      static calls only (unsound)
+            cha         Class Hierarchy Analysis
+            rta         Rapid Type Analysis
+            pta         inclusion-based Points-To Analysis
+
+           The algorithms are ordered by increasing precision in their
+           treatment of dynamic calls (and thus also computational cost).
+           RTA and PTA require a whole program (main or test), and
+           include only functions reachable from main.
+
+-test      Include the package's tests in the analysis.
+
+-format    Specifies the format in which each call graph edge is displayed.
+           One of:
+
+            digraph     output suitable for input to
+                        golang.org/x/tools/cmd/digraph.
+            graphviz    output in AT&T GraphViz (.dot) format.
+
+           All other values are interpreted using text/template syntax.
+           The default value is:
+
+            {{.Caller}}\t--{{.Dynamic}}-{{.Line}}:{{.Column}}-->\t{{.Callee}}
+
+           The structure passed to the template is (effectively):
+
+                   type Edge struct {
+                           Caller      *ssa.Function // calling function
+                           Callee      *ssa.Function // called function
+
+                           // Call site:
+                           Filename    string // containing file
+                           Offset      int    // offset within file of '('
+                           Line        int    // line number
+                           Column      int    // column number of call
+                           Dynamic     string // "static" or "dynamic"
+                           Description string // e.g. "static method call"
+                   }
+
+           Caller and Callee are *ssa.Function values, which print as
+           "(*sync/atomic.Mutex).Lock", but other attributes may be
+           derived from them, e.g. Caller.Pkg.Object.Path yields the
+           import path of the enclosing package.  Consult the go/ssa
+           API documentation for details.
+
+` + loader.FromArgsUsage + `
+
+Examples:
+
+  Show the call graph of the trivial web server application:
+
+    callgraph -format digraph $GOROOT/src/net/http/triv.go
+
+  Same, but show only the packages of each function:
+
+    callgraph -format '{{.Caller.Pkg.Object.Path}} -> {{.Callee.Pkg.Object.Path}}' \
+      $GOROOT/src/net/http/triv.go | sort | uniq
+
+  Show functions that make dynamic calls into the 'fmt' test package,
+  using the pointer analysis algorithm:
+
+    callgraph -format='{{.Caller}} -{{.Dynamic}}-> {{.Callee}}' -test -algo=pta fmt |
+      sed -ne 's/-dynamic-/--/p' |
+      sed -ne 's/-->.*fmt_test.*$//p' | sort | uniq
+
+  Show all functions directly called by the callgraph tool's main function:
+
+    callgraph -format=digraph golang.org/x/tools/cmd/callgraph |
+      digraph succs golang.org/x/tools/cmd/callgraph.main
+`
+
+func init() {
+	// If $GOMAXPROCS isn't set, use the full capacity of the machine.
+	// For small machines, use at least 4 threads.
+	if os.Getenv("GOMAXPROCS") == "" {
+		n := runtime.NumCPU()
+		if n < 4 {
+			n = 4
+		}
+		runtime.GOMAXPROCS(n)
+	}
+}
+
+func main() {
+	flag.Parse()
+	if err := doCallgraph(&build.Default, *algoFlag, *formatFlag, *testFlag, flag.Args()); err != nil {
+		fmt.Fprintf(os.Stderr, "callgraph: %s\n", err)
+		os.Exit(1)
+	}
+}
+
+var stdout io.Writer = os.Stdout
+
+func doCallgraph(ctxt *build.Context, algo, format string, tests bool, args []string) error {
+	conf := loader.Config{Build: ctxt}
+
+	if len(args) == 0 {
+		fmt.Fprintln(os.Stderr, Usage)
+		return nil
+	}
+
+	// Use the initial packages from the command line.
+	args, err := conf.FromArgs(args, tests)
+	if err != nil {
+		return err
+	}
+
+	// Load, parse and type-check the whole program.
+	iprog, err := conf.Load()
+	if err != nil {
+		return err
+	}
+
+	// Create and build SSA-form program representation.
+	prog := ssautil.CreateProgram(iprog, 0)
+	prog.BuildAll()
+
+	// -- call graph construction ------------------------------------------
+
+	var cg *callgraph.Graph
+
+	switch algo {
+	case "static":
+		cg = static.CallGraph(prog)
+
+	case "cha":
+		cg = cha.CallGraph(prog)
+
+	case "pta":
+		main, err := mainPackage(prog, tests)
+		if err != nil {
+			return err
+		}
+		config := &pointer.Config{
+			Mains:          []*ssa.Package{main},
+			BuildCallGraph: true,
+		}
+		ptares, err := pointer.Analyze(config)
+		if err != nil {
+			return err // internal error in pointer analysis
+		}
+		cg = ptares.CallGraph
+
+	case "rta":
+		main, err := mainPackage(prog, tests)
+		if err != nil {
+			return err
+		}
+		roots := []*ssa.Function{
+			main.Func("init"),
+			main.Func("main"),
+		}
+		rtares := rta.Analyze(roots, true)
+		cg = rtares.CallGraph
+
+		// NB: RTA gives us Reachable and RuntimeTypes too.
+
+	default:
+		return fmt.Errorf("unknown algorithm: %s", algo)
+	}
+
+	cg.DeleteSyntheticNodes()
+
+	// -- output------------------------------------------------------------
+
+	var before, after string
+
+	// Pre-canned formats.
+	switch format {
+	case "digraph":
+		format = `{{printf "%q %q" .Caller .Callee}}`
+
+	case "graphviz":
+		before = "digraph callgraph {\n"
+		after = "}\n"
+		format = `  {{printf "%q" .Caller}} -> {{printf "%q" .Callee}}`
+	}
+
+	tmpl, err := template.New("-format").Parse(format)
+	if err != nil {
+		return fmt.Errorf("invalid -format template: %v", err)
+	}
+
+	// Allocate these once, outside the traversal.
+	var buf bytes.Buffer
+	data := Edge{fset: prog.Fset}
+
+	fmt.Fprint(stdout, before)
+	if err := callgraph.GraphVisitEdges(cg, func(edge *callgraph.Edge) error {
+		data.position.Offset = -1
+		data.edge = edge
+		data.Caller = edge.Caller.Func
+		data.Callee = edge.Callee.Func
+
+		buf.Reset()
+		if err := tmpl.Execute(&buf, &data); err != nil {
+			return err
+		}
+		stdout.Write(buf.Bytes())
+		if len := buf.Len(); len == 0 || buf.Bytes()[len-1] != '\n' {
+			fmt.Fprintln(stdout)
+		}
+		return nil
+	}); err != nil {
+		return err
+	}
+	fmt.Fprint(stdout, after)
+	return nil
+}
+
+// mainPackage returns the main package to analyze.
+// The resulting package has a main() function.
+func mainPackage(prog *ssa.Program, tests bool) (*ssa.Package, error) {
+	pkgs := prog.AllPackages()
+
+	// TODO(adonovan): allow independent control over tests, mains and libraries.
+	// TODO(adonovan): put this logic in a library; we keep reinventing it.
+
+	if tests {
+		// If -test, use all packages' tests.
+		if len(pkgs) > 0 {
+			if main := prog.CreateTestMainPackage(pkgs...); main != nil {
+				return main, nil
+			}
+		}
+		return nil, fmt.Errorf("no tests")
+	}
+
+	// Otherwise, use the first package named main.
+	for _, pkg := range pkgs {
+		if pkg.Object.Name() == "main" {
+			if pkg.Func("main") == nil {
+				return nil, fmt.Errorf("no func main() in main package")
+			}
+			return pkg, nil
+		}
+	}
+
+	return nil, fmt.Errorf("no main package")
+}
+
+type Edge struct {
+	Caller *ssa.Function
+	Callee *ssa.Function
+
+	edge     *callgraph.Edge
+	fset     *token.FileSet
+	position token.Position // initialized lazily
+}
+
+func (e *Edge) pos() *token.Position {
+	if e.position.Offset == -1 {
+		e.position = e.fset.Position(e.edge.Pos()) // called lazily
+	}
+	return &e.position
+}
+
+func (e *Edge) Filename() string { return e.pos().Filename }
+func (e *Edge) Column() int      { return e.pos().Column }
+func (e *Edge) Line() int        { return e.pos().Line }
+func (e *Edge) Offset() int      { return e.pos().Offset }
+
+func (e *Edge) Dynamic() string {
+	if e.edge.Site != nil && e.edge.Site.Common().StaticCallee() == nil {
+		return "dynamic"
+	}
+	return "static"
+}
+
+func (e *Edge) Description() string { return e.edge.Description() }
diff --git a/cmd/callgraph/main_test.go b/cmd/callgraph/main_test.go
new file mode 100644
index 0000000..f1f7166
--- /dev/null
+++ b/cmd/callgraph/main_test.go
@@ -0,0 +1,81 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// No testdata on Android.
+
+// +build !android
+
+package main
+
+import (
+	"bytes"
+	"fmt"
+	"go/build"
+	"reflect"
+	"sort"
+	"strings"
+	"testing"
+)
+
+func TestCallgraph(t *testing.T) {
+	ctxt := build.Default // copy
+	ctxt.GOPATH = "testdata"
+
+	const format = "{{.Caller}} --> {{.Callee}}"
+
+	for _, test := range []struct {
+		algo, format string
+		tests        bool
+		want         []string
+	}{
+		{"rta", format, false, []string{
+			// rta imprecisely shows cross product of {main,main2} x {C,D}
+			`pkg.main --> (pkg.C).f`,
+			`pkg.main --> (pkg.D).f`,
+			`pkg.main --> pkg.main2`,
+			`pkg.main2 --> (pkg.C).f`,
+			`pkg.main2 --> (pkg.D).f`,
+		}},
+		{"pta", format, false, []string{
+			// pta distinguishes main->C, main2->D.  Also has a root node.
+			`<root> --> pkg.init`,
+			`<root> --> pkg.main`,
+			`pkg.main --> (pkg.C).f`,
+			`pkg.main --> pkg.main2`,
+			`pkg.main2 --> (pkg.D).f`,
+		}},
+		// tests: main is not called.
+		{"rta", format, true, []string{
+			`pkg.Example --> (pkg.C).f`,
+			`test$main.init --> pkg.init`,
+		}},
+		{"pta", format, true, []string{
+			`<root> --> pkg.Example`,
+			`<root> --> test$main.init`,
+			`pkg.Example --> (pkg.C).f`,
+			`test$main.init --> pkg.init`,
+		}},
+	} {
+		stdout = new(bytes.Buffer)
+		if err := doCallgraph(&ctxt, test.algo, test.format, test.tests, []string{"pkg"}); err != nil {
+			t.Error(err)
+			continue
+		}
+
+		got := sortedLines(fmt.Sprint(stdout))
+		if !reflect.DeepEqual(got, test.want) {
+			t.Errorf("callgraph(%q, %q, %t):\ngot:\n%s\nwant:\n%s",
+				test.algo, test.format, test.tests,
+				strings.Join(got, "\n"),
+				strings.Join(test.want, "\n"))
+		}
+	}
+}
+
+func sortedLines(s string) []string {
+	s = strings.TrimSpace(s)
+	lines := strings.Split(s, "\n")
+	sort.Strings(lines)
+	return lines
+}
diff --git a/cmd/callgraph/testdata/src/pkg/pkg.go b/cmd/callgraph/testdata/src/pkg/pkg.go
new file mode 100644
index 0000000..b81c97f
--- /dev/null
+++ b/cmd/callgraph/testdata/src/pkg/pkg.go
@@ -0,0 +1,25 @@
+package main
+
+type I interface {
+	f()
+}
+
+type C int
+
+func (C) f() {}
+
+type D int
+
+func (D) f() {}
+
+func main() {
+	var i I = C(0)
+	i.f() // dynamic call
+
+	main2()
+}
+
+func main2() {
+	var i I = D(0)
+	i.f() // dynamic call
+}
diff --git a/cmd/callgraph/testdata/src/pkg/pkg_test.go b/cmd/callgraph/testdata/src/pkg/pkg_test.go
new file mode 100644
index 0000000..d624757
--- /dev/null
+++ b/cmd/callgraph/testdata/src/pkg/pkg_test.go
@@ -0,0 +1,7 @@
+package main
+
+// Don't import "testing", it adds a lot of callgraph edges.
+
+func Example() {
+	C(0).f()
+}
diff --git a/cmd/cover/README b/cmd/cover/README
new file mode 100644
index 0000000..ff9523d
--- /dev/null
+++ b/cmd/cover/README
@@ -0,0 +1,2 @@
+NOTE: For Go releases 1.5 and later, this tool lives in the
+standard repository. The code here is not maintained.
diff --git a/cmd/cover/cover.go b/cmd/cover/cover.go
new file mode 100644
index 0000000..31ec434
--- /dev/null
+++ b/cmd/cover/cover.go
@@ -0,0 +1,722 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+	"bytes"
+	"flag"
+	"fmt"
+	"go/ast"
+	"go/parser"
+	"go/printer"
+	"go/token"
+	"io"
+	"io/ioutil"
+	"log"
+	"os"
+	"path/filepath"
+	"sort"
+	"strconv"
+	"strings"
+)
+
+const usageMessage = "" +
+	`Usage of 'go tool cover':
+Given a coverage profile produced by 'go test':
+	go test -coverprofile=c.out
+
+Open a web browser displaying annotated source code:
+	go tool cover -html=c.out
+
+Write out an HTML file instead of launching a web browser:
+	go tool cover -html=c.out -o coverage.html
+
+Display coverage percentages to stdout for each function:
+	go tool cover -func=c.out
+
+Finally, to generate modified source code with coverage annotations
+(what go test -cover does):
+	go tool cover -mode=set -var=CoverageVariableName program.go
+`
+
+func usage() {
+	fmt.Fprintln(os.Stderr, usageMessage)
+	fmt.Fprintln(os.Stderr, "Flags:")
+	flag.PrintDefaults()
+	fmt.Fprintln(os.Stderr, "\n  Only one of -html, -func, or -mode may be set.")
+	os.Exit(2)
+}
+
+var (
+	mode    = flag.String("mode", "", "coverage mode: set, count, atomic")
+	varVar  = flag.String("var", "GoCover", "name of coverage variable to generate")
+	output  = flag.String("o", "", "file for output; default: stdout")
+	htmlOut = flag.String("html", "", "generate HTML representation of coverage profile")
+	funcOut = flag.String("func", "", "output coverage profile information for each function")
+)
+
+var profile string // The profile to read; the value of -html or -func
+
+var counterStmt func(*File, ast.Expr) ast.Stmt
+
+const (
+	atomicPackagePath = "sync/atomic"
+	atomicPackageName = "_cover_atomic_"
+)
+
+func main() {
+	flag.Usage = usage
+	flag.Parse()
+
+	// Usage information when no arguments.
+	if flag.NFlag() == 0 && flag.NArg() == 0 {
+		flag.Usage()
+	}
+
+	err := parseFlags()
+	if err != nil {
+		fmt.Fprintln(os.Stderr, err)
+		fmt.Fprintln(os.Stderr, `For usage information, run "go tool cover -help"`)
+		os.Exit(2)
+	}
+
+	// Generate coverage-annotated source.
+	if *mode != "" {
+		annotate(flag.Arg(0))
+		return
+	}
+
+	// Output HTML or function coverage information.
+	if *htmlOut != "" {
+		err = htmlOutput(profile, *output)
+	} else {
+		err = funcOutput(profile, *output)
+	}
+
+	if err != nil {
+		fmt.Fprintf(os.Stderr, "cover: %v\n", err)
+		os.Exit(2)
+	}
+}
+
+// parseFlags sets the profile and counterStmt globals and performs validations.
+func parseFlags() error {
+	profile = *htmlOut
+	if *funcOut != "" {
+		if profile != "" {
+			return fmt.Errorf("too many options")
+		}
+		profile = *funcOut
+	}
+
+	// Must either display a profile or rewrite Go source.
+	if (profile == "") == (*mode == "") {
+		return fmt.Errorf("too many options")
+	}
+
+	if *mode != "" {
+		switch *mode {
+		case "set":
+			counterStmt = setCounterStmt
+		case "count":
+			counterStmt = incCounterStmt
+		case "atomic":
+			counterStmt = atomicCounterStmt
+		default:
+			return fmt.Errorf("unknown -mode %v", *mode)
+		}
+
+		if flag.NArg() == 0 {
+			return fmt.Errorf("missing source file")
+		} else if flag.NArg() == 1 {
+			return nil
+		}
+	} else if flag.NArg() == 0 {
+		return nil
+	}
+	return fmt.Errorf("too many arguments")
+}
+
+// Block represents the information about a basic block to be recorded in the analysis.
+// Note: Our definition of basic block is based on control structures; we don't break
+// apart && and ||. We could but it doesn't seem important enough to bother.
+type Block struct {
+	startByte token.Pos
+	endByte   token.Pos
+	numStmt   int
+}
+
+// File is a wrapper for the state of a file used in the parser.
+// The basic parse tree walker is a method of this type.
+type File struct {
+	fset      *token.FileSet
+	name      string // Name of file.
+	astFile   *ast.File
+	blocks    []Block
+	atomicPkg string // Package name for "sync/atomic" in this file.
+}
+
+// Visit implements the ast.Visitor interface.
+func (f *File) Visit(node ast.Node) ast.Visitor {
+	switch n := node.(type) {
+	case *ast.BlockStmt:
+		// If it's a switch or select, the body is a list of case clauses; don't tag the block itself.
+		if len(n.List) > 0 {
+			switch n.List[0].(type) {
+			case *ast.CaseClause: // switch
+				for _, n := range n.List {
+					clause := n.(*ast.CaseClause)
+					clause.Body = f.addCounters(clause.Pos(), clause.End(), clause.Body, false)
+				}
+				return f
+			case *ast.CommClause: // select
+				for _, n := range n.List {
+					clause := n.(*ast.CommClause)
+					clause.Body = f.addCounters(clause.Pos(), clause.End(), clause.Body, false)
+				}
+				return f
+			}
+		}
+		n.List = f.addCounters(n.Lbrace, n.Rbrace+1, n.List, true) // +1 to step past closing brace.
+	case *ast.IfStmt:
+		ast.Walk(f, n.Body)
+		if n.Else == nil {
+			return nil
+		}
+		// The elses are special, because if we have
+		//	if x {
+		//	} else if y {
+		//	}
+		// we want to cover the "if y". To do this, we need a place to drop the counter,
+		// so we add a hidden block:
+		//	if x {
+		//	} else {
+		//		if y {
+		//		}
+		//	}
+		switch stmt := n.Else.(type) {
+		case *ast.IfStmt:
+			block := &ast.BlockStmt{
+				Lbrace: n.Body.End(), // Start at end of the "if" block so the covered part looks like it starts at the "else".
+				List:   []ast.Stmt{stmt},
+				Rbrace: stmt.End(),
+			}
+			n.Else = block
+		case *ast.BlockStmt:
+			stmt.Lbrace = n.Body.End() // Start at end of the "if" block so the covered part looks like it starts at the "else".
+		default:
+			panic("unexpected node type in if")
+		}
+		ast.Walk(f, n.Else)
+		return nil
+	case *ast.SelectStmt:
+		// Don't annotate an empty select - creates a syntax error.
+		if n.Body == nil || len(n.Body.List) == 0 {
+			return nil
+		}
+	case *ast.SwitchStmt:
+		// Don't annotate an empty switch - creates a syntax error.
+		if n.Body == nil || len(n.Body.List) == 0 {
+			return nil
+		}
+	case *ast.TypeSwitchStmt:
+		// Don't annotate an empty type switch - creates a syntax error.
+		if n.Body == nil || len(n.Body.List) == 0 {
+			return nil
+		}
+	}
+	return f
+}
+
+// unquote returns the unquoted string.
+func unquote(s string) string {
+	t, err := strconv.Unquote(s)
+	if err != nil {
+		log.Fatalf("cover: improperly quoted string %q\n", s)
+	}
+	return t
+}
+
+// addImport adds an import for the specified path, if one does not already exist, and returns
+// the local package name.
+func (f *File) addImport(path string) string {
+	// Does the package already import it?
+	for _, s := range f.astFile.Imports {
+		if unquote(s.Path.Value) == path {
+			if s.Name != nil {
+				return s.Name.Name
+			}
+			return filepath.Base(path)
+		}
+	}
+	newImport := &ast.ImportSpec{
+		Name: ast.NewIdent(atomicPackageName),
+		Path: &ast.BasicLit{
+			Kind:  token.STRING,
+			Value: fmt.Sprintf("%q", path),
+		},
+	}
+	impDecl := &ast.GenDecl{
+		Tok: token.IMPORT,
+		Specs: []ast.Spec{
+			newImport,
+		},
+	}
+	// Make the new import the first Decl in the file.
+	astFile := f.astFile
+	astFile.Decls = append(astFile.Decls, nil)
+	copy(astFile.Decls[1:], astFile.Decls[0:])
+	astFile.Decls[0] = impDecl
+	astFile.Imports = append(astFile.Imports, newImport)
+
+	// Now refer to the package, just in case it ends up unused.
+	// That is, append to the end of the file the declaration
+	//	var _ = _cover_atomic_.AddUint32
+	reference := &ast.GenDecl{
+		Tok: token.VAR,
+		Specs: []ast.Spec{
+			&ast.ValueSpec{
+				Names: []*ast.Ident{
+					ast.NewIdent("_"),
+				},
+				Values: []ast.Expr{
+					&ast.SelectorExpr{
+						X:   ast.NewIdent(atomicPackageName),
+						Sel: ast.NewIdent("AddUint32"),
+					},
+				},
+			},
+		},
+	}
+	astFile.Decls = append(astFile.Decls, reference)
+	return atomicPackageName
+}
+
+var slashslash = []byte("//")
+
+// initialComments returns the prefix of content containing only
+// whitespace and line comments.  Any +build directives must appear
+// within this region.  This approach is more reliable than using
+// go/printer to print a modified AST containing comments.
+//
+func initialComments(content []byte) []byte {
+	// Derived from go/build.Context.shouldBuild.
+	end := 0
+	p := content
+	for len(p) > 0 {
+		line := p
+		if i := bytes.IndexByte(line, '\n'); i >= 0 {
+			line, p = line[:i], p[i+1:]
+		} else {
+			p = p[len(p):]
+		}
+		line = bytes.TrimSpace(line)
+		if len(line) == 0 { // Blank line.
+			end = len(content) - len(p)
+			continue
+		}
+		if !bytes.HasPrefix(line, slashslash) { // Not comment line.
+			break
+		}
+	}
+	return content[:end]
+}
+
+func annotate(name string) {
+	fset := token.NewFileSet()
+	content, err := ioutil.ReadFile(name)
+	if err != nil {
+		log.Fatalf("cover: %s: %s", name, err)
+	}
+	parsedFile, err := parser.ParseFile(fset, name, content, parser.ParseComments)
+	if err != nil {
+		log.Fatalf("cover: %s: %s", name, err)
+	}
+	parsedFile.Comments = trimComments(parsedFile, fset)
+
+	file := &File{
+		fset:    fset,
+		name:    name,
+		astFile: parsedFile,
+	}
+	if *mode == "atomic" {
+		file.atomicPkg = file.addImport(atomicPackagePath)
+	}
+	ast.Walk(file, file.astFile)
+	fd := os.Stdout
+	if *output != "" {
+		var err error
+		fd, err = os.Create(*output)
+		if err != nil {
+			log.Fatalf("cover: %s", err)
+		}
+	}
+	fd.Write(initialComments(content)) // Retain '// +build' directives.
+	file.print(fd)
+	// After printing the source tree, add some declarations for the counters etc.
+	// We could do this by adding to the tree, but it's easier just to print the text.
+	file.addVariables(fd)
+}
+
+// trimComments drops all but the //go: comments, some of which are semantically important.
+// We drop all others because they can appear in places that cause our counters
+// to appear in syntactically incorrect places. //go: appears at the beginning of
+// the line and is syntactically safe.
+func trimComments(file *ast.File, fset *token.FileSet) []*ast.CommentGroup {
+	var comments []*ast.CommentGroup
+	for _, group := range file.Comments {
+		var list []*ast.Comment
+		for _, comment := range group.List {
+			if strings.HasPrefix(comment.Text, "//go:") && fset.Position(comment.Slash).Column == 1 {
+				list = append(list, comment)
+			}
+		}
+		if list != nil {
+			comments = append(comments, &ast.CommentGroup{list})
+		}
+	}
+	return comments
+}
+
+func (f *File) print(w io.Writer) {
+	printer.Fprint(w, f.fset, f.astFile)
+}
+
+// intLiteral returns an ast.BasicLit representing the integer value.
+func (f *File) intLiteral(i int) *ast.BasicLit {
+	node := &ast.BasicLit{
+		Kind:  token.INT,
+		Value: fmt.Sprint(i),
+	}
+	return node
+}
+
+// index returns an ast.BasicLit representing the number of counters present.
+func (f *File) index() *ast.BasicLit {
+	return f.intLiteral(len(f.blocks))
+}
+
+// setCounterStmt returns the expression: __count[23] = 1.
+func setCounterStmt(f *File, counter ast.Expr) ast.Stmt {
+	return &ast.AssignStmt{
+		Lhs: []ast.Expr{counter},
+		Tok: token.ASSIGN,
+		Rhs: []ast.Expr{f.intLiteral(1)},
+	}
+}
+
+// incCounterStmt returns the expression: __count[23]++.
+func incCounterStmt(f *File, counter ast.Expr) ast.Stmt {
+	return &ast.IncDecStmt{
+		X:   counter,
+		Tok: token.INC,
+	}
+}
+
+// atomicCounterStmt returns the expression: atomic.AddUint32(&__count[23], 1)
+func atomicCounterStmt(f *File, counter ast.Expr) ast.Stmt {
+	return &ast.ExprStmt{
+		X: &ast.CallExpr{
+			Fun: &ast.SelectorExpr{
+				X:   ast.NewIdent(f.atomicPkg),
+				Sel: ast.NewIdent("AddUint32"),
+			},
+			Args: []ast.Expr{&ast.UnaryExpr{
+				Op: token.AND,
+				X:  counter,
+			},
+				f.intLiteral(1),
+			},
+		},
+	}
+}
+
+// newCounter creates a new counter expression of the appropriate form.
+func (f *File) newCounter(start, end token.Pos, numStmt int) ast.Stmt {
+	counter := &ast.IndexExpr{
+		X: &ast.SelectorExpr{
+			X:   ast.NewIdent(*varVar),
+			Sel: ast.NewIdent("Count"),
+		},
+		Index: f.index(),
+	}
+	stmt := counterStmt(f, counter)
+	f.blocks = append(f.blocks, Block{start, end, numStmt})
+	return stmt
+}
+
+// addCounters takes a list of statements and adds counters to the beginning of
+// each basic block at the top level of that list. For instance, given
+//
+//	S1
+//	if cond {
+//		S2
+// 	}
+//	S3
+//
+// counters will be added before S1 and before S3. The block containing S2
+// will be visited in a separate call.
+// TODO: Nested simple blocks get unnecessary (but correct) counters
+func (f *File) addCounters(pos, blockEnd token.Pos, list []ast.Stmt, extendToClosingBrace bool) []ast.Stmt {
+	// Special case: make sure we add a counter to an empty block. Can't do this below
+	// or we will add a counter to an empty statement list after, say, a return statement.
+	if len(list) == 0 {
+		return []ast.Stmt{f.newCounter(pos, blockEnd, 0)}
+	}
+	// We have a block (statement list), but it may have several basic blocks due to the
+	// appearance of statements that affect the flow of control.
+	var newList []ast.Stmt
+	for {
+		// Find first statement that affects flow of control (break, continue, if, etc.).
+		// It will be the last statement of this basic block.
+		var last int
+		end := blockEnd
+		for last = 0; last < len(list); last++ {
+			end = f.statementBoundary(list[last])
+			if f.endsBasicSourceBlock(list[last]) {
+				extendToClosingBrace = false // Block is broken up now.
+				last++
+				break
+			}
+		}
+		if extendToClosingBrace {
+			end = blockEnd
+		}
+		if pos != end { // Can have no source to cover if e.g. blocks abut.
+			newList = append(newList, f.newCounter(pos, end, last))
+		}
+		newList = append(newList, list[0:last]...)
+		list = list[last:]
+		if len(list) == 0 {
+			break
+		}
+		pos = list[0].Pos()
+	}
+	return newList
+}
+
+// hasFuncLiteral reports the existence and position of the first func literal
+// in the node, if any. If a func literal appears, it usually marks the termination
+// of a basic block because the function body is itself a block.
+// Therefore we draw a line at the start of the body of the first function literal we find.
+// TODO: what if there's more than one? Probably doesn't matter much.
+func hasFuncLiteral(n ast.Node) (bool, token.Pos) {
+	if n == nil {
+		return false, 0
+	}
+	var literal funcLitFinder
+	ast.Walk(&literal, n)
+	return literal.found(), token.Pos(literal)
+}
+
+// statementBoundary finds the location in s that terminates the current basic
+// block in the source.
+func (f *File) statementBoundary(s ast.Stmt) token.Pos {
+	// Control flow statements are easy.
+	switch s := s.(type) {
+	case *ast.BlockStmt:
+		// Treat blocks like basic blocks to avoid overlapping counters.
+		return s.Lbrace
+	case *ast.IfStmt:
+		found, pos := hasFuncLiteral(s.Init)
+		if found {
+			return pos
+		}
+		found, pos = hasFuncLiteral(s.Cond)
+		if found {
+			return pos
+		}
+		return s.Body.Lbrace
+	case *ast.ForStmt:
+		found, pos := hasFuncLiteral(s.Init)
+		if found {
+			return pos
+		}
+		found, pos = hasFuncLiteral(s.Cond)
+		if found {
+			return pos
+		}
+		found, pos = hasFuncLiteral(s.Post)
+		if found {
+			return pos
+		}
+		return s.Body.Lbrace
+	case *ast.LabeledStmt:
+		return f.statementBoundary(s.Stmt)
+	case *ast.RangeStmt:
+		found, pos := hasFuncLiteral(s.X)
+		if found {
+			return pos
+		}
+		return s.Body.Lbrace
+	case *ast.SwitchStmt:
+		found, pos := hasFuncLiteral(s.Init)
+		if found {
+			return pos
+		}
+		found, pos = hasFuncLiteral(s.Tag)
+		if found {
+			return pos
+		}
+		return s.Body.Lbrace
+	case *ast.SelectStmt:
+		return s.Body.Lbrace
+	case *ast.TypeSwitchStmt:
+		found, pos := hasFuncLiteral(s.Init)
+		if found {
+			return pos
+		}
+		return s.Body.Lbrace
+	}
+	// If not a control flow statement, it is a declaration, expression, call, etc. and it may have a function literal.
+	// If it does, that's tricky because we want to exclude the body of the function from this block.
+	// Draw a line at the start of the body of the first function literal we find.
+	// TODO: what if there's more than one? Probably doesn't matter much.
+	found, pos := hasFuncLiteral(s)
+	if found {
+		return pos
+	}
+	return s.End()
+}
+
+// endsBasicSourceBlock reports whether s changes the flow of control: break, if, etc.,
+// or if it's just problematic, for instance contains a function literal, which will complicate
+// accounting due to the block-within-an expression.
+func (f *File) endsBasicSourceBlock(s ast.Stmt) bool {
+	switch s := s.(type) {
+	case *ast.BlockStmt:
+		// Treat blocks like basic blocks to avoid overlapping counters.
+		return true
+	case *ast.BranchStmt:
+		return true
+	case *ast.ForStmt:
+		return true
+	case *ast.IfStmt:
+		return true
+	case *ast.LabeledStmt:
+		return f.endsBasicSourceBlock(s.Stmt)
+	case *ast.RangeStmt:
+		return true
+	case *ast.SwitchStmt:
+		return true
+	case *ast.SelectStmt:
+		return true
+	case *ast.TypeSwitchStmt:
+		return true
+	case *ast.ExprStmt:
+		// Calls to panic change the flow.
+		// We really should verify that "panic" is the predefined function,
+		// but without type checking we can't and the likelihood of it being
+		// an actual problem is vanishingly small.
+		if call, ok := s.X.(*ast.CallExpr); ok {
+			if ident, ok := call.Fun.(*ast.Ident); ok && ident.Name == "panic" && len(call.Args) == 1 {
+				return true
+			}
+		}
+	}
+	found, _ := hasFuncLiteral(s)
+	return found
+}
+
+// funcLitFinder implements the ast.Visitor pattern to find the location of any
+// function literal in a subtree.
+type funcLitFinder token.Pos
+
+func (f *funcLitFinder) Visit(node ast.Node) (w ast.Visitor) {
+	if f.found() {
+		return nil // Prune search.
+	}
+	switch n := node.(type) {
+	case *ast.FuncLit:
+		*f = funcLitFinder(n.Body.Lbrace)
+		return nil // Prune search.
+	}
+	return f
+}
+
+func (f *funcLitFinder) found() bool {
+	return token.Pos(*f) != token.NoPos
+}
+
+// Sort interface for []block1; used for self-check in addVariables.
+
+type block1 struct {
+	Block
+	index int
+}
+
+type blockSlice []block1
+
+func (b blockSlice) Len() int           { return len(b) }
+func (b blockSlice) Less(i, j int) bool { return b[i].startByte < b[j].startByte }
+func (b blockSlice) Swap(i, j int)      { b[i], b[j] = b[j], b[i] }
+
+// offset translates a token position into a 0-indexed byte offset.
+func (f *File) offset(pos token.Pos) int {
+	return f.fset.Position(pos).Offset
+}
+
+// addVariables adds to the end of the file the declarations to set up the counter and position variables.
+func (f *File) addVariables(w io.Writer) {
+	// Self-check: Verify that the instrumented basic blocks are disjoint.
+	t := make([]block1, len(f.blocks))
+	for i := range f.blocks {
+		t[i].Block = f.blocks[i]
+		t[i].index = i
+	}
+	sort.Sort(blockSlice(t))
+	for i := 1; i < len(t); i++ {
+		if t[i-1].endByte > t[i].startByte {
+			fmt.Fprintf(os.Stderr, "cover: internal error: block %d overlaps block %d\n", t[i-1].index, t[i].index)
+			// Note: error message is in byte positions, not token positions.
+			fmt.Fprintf(os.Stderr, "\t%s:#%d,#%d %s:#%d,#%d\n",
+				f.name, f.offset(t[i-1].startByte), f.offset(t[i-1].endByte),
+				f.name, f.offset(t[i].startByte), f.offset(t[i].endByte))
+		}
+	}
+
+	// Declare the coverage struct as a package-level variable.
+	fmt.Fprintf(w, "\nvar %s = struct {\n", *varVar)
+	fmt.Fprintf(w, "\tCount     [%d]uint32\n", len(f.blocks))
+	fmt.Fprintf(w, "\tPos       [3 * %d]uint32\n", len(f.blocks))
+	fmt.Fprintf(w, "\tNumStmt   [%d]uint16\n", len(f.blocks))
+	fmt.Fprintf(w, "} {\n")
+
+	// Initialize the position array field.
+	fmt.Fprintf(w, "\tPos: [3 * %d]uint32{\n", len(f.blocks))
+
+	// A nice long list of positions. Each position is encoded as follows to reduce size:
+	// - 32-bit starting line number
+	// - 32-bit ending line number
+	// - (16 bit ending column number << 16) | (16-bit starting column number).
+	for i, block := range f.blocks {
+		start := f.fset.Position(block.startByte)
+		end := f.fset.Position(block.endByte)
+		fmt.Fprintf(w, "\t\t%d, %d, %#x, // [%d]\n", start.Line, end.Line, (end.Column&0xFFFF)<<16|(start.Column&0xFFFF), i)
+	}
+
+	// Close the position array.
+	fmt.Fprintf(w, "\t},\n")
+
+	// Initialize the position array field.
+	fmt.Fprintf(w, "\tNumStmt: [%d]uint16{\n", len(f.blocks))
+
+	// A nice long list of statements-per-block, so we can give a conventional
+	// valuation of "percent covered". To save space, it's a 16-bit number, so we
+	// clamp it if it overflows - won't matter in practice.
+	for i, block := range f.blocks {
+		n := block.numStmt
+		if n > 1<<16-1 {
+			n = 1<<16 - 1
+		}
+		fmt.Fprintf(w, "\t\t%d, // %d\n", n, i)
+	}
+
+	// Close the statements-per-block array.
+	fmt.Fprintf(w, "\t},\n")
+
+	// Close the struct initialization.
+	fmt.Fprintf(w, "}\n")
+}
diff --git a/cmd/cover/cover_test.go b/cmd/cover/cover_test.go
new file mode 100644
index 0000000..a18778b
--- /dev/null
+++ b/cmd/cover/cover_test.go
@@ -0,0 +1,94 @@
+// Copyright 2013 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// No testdata on Android.
+
+// +build !android
+
+package main_test
+
+import (
+	"bytes"
+	"fmt"
+	"io/ioutil"
+	"os"
+	"os/exec"
+	"path/filepath"
+	"testing"
+)
+
+const (
+	// Data directory, also the package directory for the test.
+	testdata = "testdata"
+
+	// Binaries we compile.
+	testcover = "./testcover.exe"
+)
+
+var (
+	// Files we use.
+	testMain    = filepath.Join(testdata, "main.go")
+	testTest    = filepath.Join(testdata, "test.go")
+	coverInput  = filepath.Join(testdata, "test_line.go")
+	coverOutput = filepath.Join(testdata, "test_cover.go")
+)
+
+var debug = false // Keeps the rewritten files around if set.
+
+// Run this shell script, but do it in Go so it can be run by "go test".
+//
+//	replace the word LINE with the line number < testdata/test.go > testdata/test_line.go
+// 	go build -o ./testcover
+// 	./testcover -mode=count -var=CoverTest -o ./testdata/test_cover.go testdata/test_line.go
+//	go run ./testdata/main.go ./testdata/test.go
+//
+func TestCover(t *testing.T) {
+	// Read in the test file (testTest) and write it, with LINEs specified, to coverInput.
+	file, err := ioutil.ReadFile(testTest)
+	if err != nil {
+		t.Fatal(err)
+	}
+	lines := bytes.Split(file, []byte("\n"))
+	for i, line := range lines {
+		lines[i] = bytes.Replace(line, []byte("LINE"), []byte(fmt.Sprint(i+1)), -1)
+	}
+	err = ioutil.WriteFile(coverInput, bytes.Join(lines, []byte("\n")), 0666)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	// defer removal of test_line.go
+	if !debug {
+		defer os.Remove(coverInput)
+	}
+
+	// go build -o testcover
+	cmd := exec.Command("go", "build", "-o", testcover)
+	run(cmd, t)
+
+	// defer removal of testcover
+	defer os.Remove(testcover)
+
+	// ./testcover -mode=count -var=coverTest -o ./testdata/test_cover.go testdata/test_line.go
+	cmd = exec.Command(testcover, "-mode=count", "-var=coverTest", "-o", coverOutput, coverInput)
+	run(cmd, t)
+
+	// defer removal of ./testdata/test_cover.go
+	if !debug {
+		defer os.Remove(coverOutput)
+	}
+
+	// go run ./testdata/main.go ./testdata/test.go
+	cmd = exec.Command("go", "run", testMain, coverOutput)
+	run(cmd, t)
+}
+
+func run(c *exec.Cmd, t *testing.T) {
+	c.Stdout = os.Stdout
+	c.Stderr = os.Stderr
+	err := c.Run()
+	if err != nil {
+		t.Fatal(err)
+	}
+}
diff --git a/cmd/cover/doc.go b/cmd/cover/doc.go
new file mode 100644
index 0000000..b74d5b3
--- /dev/null
+++ b/cmd/cover/doc.go
@@ -0,0 +1,27 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+/*
+Cover is a program for analyzing the coverage profiles generated by
+'go test -coverprofile=cover.out'.
+
+Cover is also used by 'go test -cover' to rewrite the source code with
+annotations to track which parts of each function are executed.
+It operates on one Go source file at a time, computing approximate
+basic block information by studying the source. It is thus more portable
+than binary-rewriting coverage tools, but also a little less capable.
+For instance, it does not probe inside && and || expressions, and can
+be mildly confused by single statements with multiple function literals.
+
+For usage information, please see:
+	go help testflag
+	go tool cover -help
+
+No longer maintained:
+
+For Go releases 1.5 and later, this tool lives in the
+standard repository. The code here is not maintained.
+
+*/
+package main // import "golang.org/x/tools/cmd/cover"
diff --git a/cmd/cover/func.go b/cmd/cover/func.go
new file mode 100644
index 0000000..41d9fce
--- /dev/null
+++ b/cmd/cover/func.go
@@ -0,0 +1,166 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file implements the visitor that computes the (line, column)-(line-column) range for each function.
+
+package main
+
+import (
+	"bufio"
+	"fmt"
+	"go/ast"
+	"go/build"
+	"go/parser"
+	"go/token"
+	"os"
+	"path/filepath"
+	"text/tabwriter"
+
+	"golang.org/x/tools/cover"
+)
+
+// funcOutput takes two file names as arguments, a coverage profile to read as input and an output
+// file to write ("" means to write to standard output). The function reads the profile and produces
+// as output the coverage data broken down by function, like this:
+//
+//	fmt/format.go:30:	init			100.0%
+//	fmt/format.go:57:	clearflags		100.0%
+//	...
+//	fmt/scan.go:1046:	doScan			100.0%
+//	fmt/scan.go:1075:	advance			96.2%
+//	fmt/scan.go:1119:	doScanf			96.8%
+//	total:		(statements)			91.9%
+
+func funcOutput(profile, outputFile string) error {
+	profiles, err := cover.ParseProfiles(profile)
+	if err != nil {
+		return err
+	}
+
+	var out *bufio.Writer
+	if outputFile == "" {
+		out = bufio.NewWriter(os.Stdout)
+	} else {
+		fd, err := os.Create(outputFile)
+		if err != nil {
+			return err
+		}
+		defer fd.Close()
+		out = bufio.NewWriter(fd)
+	}
+	defer out.Flush()
+
+	tabber := tabwriter.NewWriter(out, 1, 8, 1, '\t', 0)
+	defer tabber.Flush()
+
+	var total, covered int64
+	for _, profile := range profiles {
+		fn := profile.FileName
+		file, err := findFile(fn)
+		if err != nil {
+			return err
+		}
+		funcs, err := findFuncs(file)
+		if err != nil {
+			return err
+		}
+		// Now match up functions and profile blocks.
+		for _, f := range funcs {
+			c, t := f.coverage(profile)
+			fmt.Fprintf(tabber, "%s:%d:\t%s\t%.1f%%\n", fn, f.startLine, f.name, 100.0*float64(c)/float64(t))
+			total += t
+			covered += c
+		}
+	}
+	fmt.Fprintf(tabber, "total:\t(statements)\t%.1f%%\n", 100.0*float64(covered)/float64(total))
+
+	return nil
+}
+
+// findFuncs parses the file and returns a slice of FuncExtent descriptors.
+func findFuncs(name string) ([]*FuncExtent, error) {
+	fset := token.NewFileSet()
+	parsedFile, err := parser.ParseFile(fset, name, nil, 0)
+	if err != nil {
+		return nil, err
+	}
+	visitor := &FuncVisitor{
+		fset:    fset,
+		name:    name,
+		astFile: parsedFile,
+	}
+	ast.Walk(visitor, visitor.astFile)
+	return visitor.funcs, nil
+}
+
+// FuncExtent describes a function's extent in the source by file and position.
+type FuncExtent struct {
+	name      string
+	startLine int
+	startCol  int
+	endLine   int
+	endCol    int
+}
+
+// FuncVisitor implements the visitor that builds the function position list for a file.
+type FuncVisitor struct {
+	fset    *token.FileSet
+	name    string // Name of file.
+	astFile *ast.File
+	funcs   []*FuncExtent
+}
+
+// Visit implements the ast.Visitor interface.
+func (v *FuncVisitor) Visit(node ast.Node) ast.Visitor {
+	switch n := node.(type) {
+	case *ast.FuncDecl:
+		start := v.fset.Position(n.Pos())
+		end := v.fset.Position(n.End())
+		fe := &FuncExtent{
+			name:      n.Name.Name,
+			startLine: start.Line,
+			startCol:  start.Column,
+			endLine:   end.Line,
+			endCol:    end.Column,
+		}
+		v.funcs = append(v.funcs, fe)
+	}
+	return v
+}
+
+// coverage returns the fraction of the statements in the function that were covered, as a numerator and denominator.
+func (f *FuncExtent) coverage(profile *cover.Profile) (num, den int64) {
+	// We could avoid making this n^2 overall by doing a single scan and annotating the functions,
+	// but the sizes of the data structures is never very large and the scan is almost instantaneous.
+	var covered, total int64
+	// The blocks are sorted, so we can stop counting as soon as we reach the end of the relevant block.
+	for _, b := range profile.Blocks {
+		if b.StartLine > f.endLine || (b.StartLine == f.endLine && b.StartCol >= f.endCol) {
+			// Past the end of the function.
+			break
+		}
+		if b.EndLine < f.startLine || (b.EndLine == f.startLine && b.EndCol <= f.startCol) {
+			// Before the beginning of the function
+			continue
+		}
+		total += int64(b.NumStmt)
+		if b.Count > 0 {
+			covered += int64(b.NumStmt)
+		}
+	}
+	if total == 0 {
+		total = 1 // Avoid zero denominator.
+	}
+	return covered, total
+}
+
+// findFile finds the location of the named file in GOROOT, GOPATH etc.
+func findFile(file string) (string, error) {
+	dir, file := filepath.Split(file)
+	pkg, err := build.Import(dir, ".", build.FindOnly)
+	if err != nil {
+		return "", fmt.Errorf("can't find %q: %v", file, err)
+	}
+	return filepath.Join(pkg.Dir, file), nil
+}
diff --git a/cmd/cover/html.go b/cmd/cover/html.go
new file mode 100644
index 0000000..f6b2264
--- /dev/null
+++ b/cmd/cover/html.go
@@ -0,0 +1,281 @@
+// Copyright 2013 The Go Authors. 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 (
+	"bufio"
+	"bytes"
+	"fmt"
+	"html/template"
+	"io"
+	"io/ioutil"
+	"math"
+	"os"
+	"os/exec"
+	"path/filepath"
+	"runtime"
+
+	"golang.org/x/tools/cover"
+)
+
+// htmlOutput reads the profile data from profile and generates an HTML
+// coverage report, writing it to outfile. If outfile is empty,
+// it writes the report to a temporary file and opens it in a web browser.
+func htmlOutput(profile, outfile string) error {
+	profiles, err := cover.ParseProfiles(profile)
+	if err != nil {
+		return err
+	}
+
+	var d templateData
+
+	for _, profile := range profiles {
+		fn := profile.FileName
+		if profile.Mode == "set" {
+			d.Set = true
+		}
+		file, err := findFile(fn)
+		if err != nil {
+			return err
+		}
+		src, err := ioutil.ReadFile(file)
+		if err != nil {
+			return fmt.Errorf("can't read %q: %v", fn, err)
+		}
+		var buf bytes.Buffer
+		err = htmlGen(&buf, src, profile.Boundaries(src))
+		if err != nil {
+			return err
+		}
+		d.Files = append(d.Files, &templateFile{
+			Name:     fn,
+			Body:     template.HTML(buf.String()),
+			Coverage: percentCovered(profile),
+		})
+	}
+
+	var out *os.File
+	if outfile == "" {
+		var dir string
+		dir, err = ioutil.TempDir("", "cover")
+		if err != nil {
+			return err
+		}
+		out, err = os.Create(filepath.Join(dir, "coverage.html"))
+	} else {
+		out, err = os.Create(outfile)
+	}
+	err = htmlTemplate.Execute(out, d)
+	if err == nil {
+		err = out.Close()
+	}
+	if err != nil {
+		return err
+	}
+
+	if outfile == "" {
+		if !startBrowser("file://" + out.Name()) {
+			fmt.Fprintf(os.Stderr, "HTML output written to %s\n", out.Name())
+		}
+	}
+
+	return nil
+}
+
+// percentCovered returns, as a percentage, the fraction of the statements in
+// the profile covered by the test run.
+// In effect, it reports the coverage of a given source file.
+func percentCovered(p *cover.Profile) float64 {
+	var total, covered int64
+	for _, b := range p.Blocks {
+		total += int64(b.NumStmt)
+		if b.Count > 0 {
+			covered += int64(b.NumStmt)
+		}
+	}
+	if total == 0 {
+		return 0
+	}
+	return float64(covered) / float64(total) * 100
+}
+
+// htmlGen generates an HTML coverage report with the provided filename,
+// source code, and tokens, and writes it to the given Writer.
+func htmlGen(w io.Writer, src []byte, boundaries []cover.Boundary) error {
+	dst := bufio.NewWriter(w)
+	for i := range src {
+		for len(boundaries) > 0 && boundaries[0].Offset == i {
+			b := boundaries[0]
+			if b.Start {
+				n := 0
+				if b.Count > 0 {
+					n = int(math.Floor(b.Norm*9)) + 1
+				}
+				fmt.Fprintf(dst, `<span class="cov%v" title="%v">`, n, b.Count)
+			} else {
+				dst.WriteString("</span>")
+			}
+			boundaries = boundaries[1:]
+		}
+		switch b := src[i]; b {
+		case '>':
+			dst.WriteString("&gt;")
+		case '<':
+			dst.WriteString("&lt;")
+		case '&':
+			dst.WriteString("&amp;")
+		case '\t':
+			dst.WriteString("        ")
+		default:
+			dst.WriteByte(b)
+		}
+	}
+	return dst.Flush()
+}
+
+// startBrowser tries to open the URL in a browser
+// and reports whether it succeeds.
+func startBrowser(url string) bool {
+	// try to start the browser
+	var args []string
+	switch runtime.GOOS {
+	case "darwin":
+		args = []string{"open"}
+	case "windows":
+		args = []string{"cmd", "/c", "start"}
+	default:
+		args = []string{"xdg-open"}
+	}
+	cmd := exec.Command(args[0], append(args[1:], url)...)
+	return cmd.Start() == nil
+}
+
+// rgb returns an rgb value for the specified coverage value
+// between 0 (no coverage) and 10 (max coverage).
+func rgb(n int) string {
+	if n == 0 {
+		return "rgb(192, 0, 0)" // Red
+	}
+	// Gradient from gray to green.
+	r := 128 - 12*(n-1)
+	g := 128 + 12*(n-1)
+	b := 128 + 3*(n-1)
+	return fmt.Sprintf("rgb(%v, %v, %v)", r, g, b)
+}
+
+// colors generates the CSS rules for coverage colors.
+func colors() template.CSS {
+	var buf bytes.Buffer
+	for i := 0; i < 11; i++ {
+		fmt.Fprintf(&buf, ".cov%v { color: %v }\n", i, rgb(i))
+	}
+	return template.CSS(buf.String())
+}
+
+var htmlTemplate = template.Must(template.New("html").Funcs(template.FuncMap{
+	"colors": colors,
+}).Parse(tmplHTML))
+
+type templateData struct {
+	Files []*templateFile
+	Set   bool
+}
+
+type templateFile struct {
+	Name     string
+	Body     template.HTML
+	Coverage float64
+}
+
+const tmplHTML = `
+<!DOCTYPE html>
+<html>
+	<head>
+		<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+		<style>
+			body {
+				background: black;
+				color: rgb(80, 80, 80);
+			}
+			body, pre, #legend span {
+				font-family: Menlo, monospace;
+				font-weight: bold;
+			}
+			#topbar {
+				background: black;
+				position: fixed;
+				top: 0; left: 0; right: 0;
+				height: 42px;
+				border-bottom: 1px solid rgb(80, 80, 80);
+			}
+			#content {
+				margin-top: 50px;
+			}
+			#nav, #legend {
+				float: left;
+				margin-left: 10px;
+			}
+			#legend {
+				margin-top: 12px;
+			}
+			#nav {
+				margin-top: 10px;
+			}
+			#legend span {
+				margin: 0 5px;
+			}
+			{{colors}}
+		</style>
+	</head>
+	<body>
+		<div id="topbar">
+			<div id="nav">
+				<select id="files">
+				{{range $i, $f := .Files}}
+				<option value="file{{$i}}">{{$f.Name}} ({{printf "%.1f" $f.Coverage}}%)</option>
+				{{end}}
+				</select>
+			</div>
+			<div id="legend">
+				<span>not tracked</span>
+			{{if .Set}}
+				<span class="cov0">not covered</span>
+				<span class="cov8">covered</span>
+			{{else}}
+				<span class="cov0">no coverage</span>
+				<span class="cov1">low coverage</span>
+				<span class="cov2">*</span>
+				<span class="cov3">*</span>
+				<span class="cov4">*</span>
+				<span class="cov5">*</span>
+				<span class="cov6">*</span>
+				<span class="cov7">*</span>
+				<span class="cov8">*</span>
+				<span class="cov9">*</span>
+				<span class="cov10">high coverage</span>
+			{{end}}
+			</div>
+		</div>
+		<div id="content">
+		{{range $i, $f := .Files}}
+		<pre class="file" id="file{{$i}}" {{if $i}}style="display: none"{{end}}>{{$f.Body}}</pre>
+		{{end}}
+		</div>
+	</body>
+	<script>
+	(function() {
+		var files = document.getElementById('files');
+		var visible = document.getElementById('file0');
+		files.addEventListener('change', onChange, false);
+		function onChange() {
+			visible.style.display = 'none';
+			visible = document.getElementById(files.value);
+			visible.style.display = 'block';
+			window.scrollTo(0, 0);
+		}
+	})();
+	</script>
+</html>
+`
diff --git a/cmd/cover/testdata/main.go b/cmd/cover/testdata/main.go
new file mode 100644
index 0000000..6ed39c4
--- /dev/null
+++ b/cmd/cover/testdata/main.go
@@ -0,0 +1,112 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Test runner for coverage test. This file is not coverage-annotated; test.go is.
+// It knows the coverage counter is called "coverTest".
+
+package main
+
+import (
+	"fmt"
+	"os"
+)
+
+func main() {
+	testAll()
+	verify()
+}
+
+type block struct {
+	count uint32
+	line  uint32
+}
+
+var counters = make(map[block]bool)
+
+// check records the location and expected value for a counter.
+func check(line, count uint32) {
+	b := block{
+		count,
+		line,
+	}
+	counters[b] = true
+}
+
+// checkVal is a version of check that returns its extra argument,
+// so it can be used in conditionals.
+func checkVal(line, count uint32, val int) int {
+	b := block{
+		count,
+		line,
+	}
+	counters[b] = true
+	return val
+}
+
+var PASS = true
+
+// verify checks the expected counts against the actual. It runs after the test has completed.
+func verify() {
+	for b := range counters {
+		got, index := count(b.line)
+		if b.count == anything && got != 0 {
+			got = anything
+		}
+		if got != b.count {
+			fmt.Fprintf(os.Stderr, "test_go:%d expected count %d got %d [counter %d]\n", b.line, b.count, got, index)
+			PASS = false
+		}
+	}
+	verifyPanic()
+	if !PASS {
+		fmt.Fprintf(os.Stderr, "FAIL\n")
+		os.Exit(2)
+	}
+}
+
+// verifyPanic is a special check for the known counter that should be
+// after the panic call in testPanic.
+func verifyPanic() {
+	if coverTest.Count[panicIndex-1] != 1 {
+		// Sanity check for test before panic.
+		fmt.Fprintf(os.Stderr, "bad before panic")
+		PASS = false
+	}
+	if coverTest.Count[panicIndex] != 0 {
+		fmt.Fprintf(os.Stderr, "bad at panic: %d should be 0\n", coverTest.Count[panicIndex])
+		PASS = false
+	}
+	if coverTest.Count[panicIndex+1] != 1 {
+		fmt.Fprintf(os.Stderr, "bad after panic")
+		PASS = false
+	}
+}
+
+// count returns the count and index for the counter at the specified line.
+func count(line uint32) (uint32, int) {
+	// Linear search is fine. Choose perfect fit over approximate.
+	// We can have a closing brace for a range on the same line as a condition for an "else if"
+	// and we don't want that brace to steal the count for the condition on the "if".
+	// Therefore we test for a perfect (lo==line && hi==line) match, but if we can't
+	// find that we take the first imperfect match.
+	index := -1
+	indexLo := uint32(1e9)
+	for i := range coverTest.Count {
+		lo, hi := coverTest.Pos[3*i], coverTest.Pos[3*i+1]
+		if lo == line && line == hi {
+			return coverTest.Count[i], i
+		}
+		// Choose the earliest match (the counters are in unpredictable order).
+		if lo <= line && line <= hi && indexLo > lo {
+			index = i
+			indexLo = lo
+		}
+	}
+	if index == -1 {
+		fmt.Fprintln(os.Stderr, "cover_test: no counter for line", line)
+		PASS = false
+		return 0, 0
+	}
+	return coverTest.Count[index], index
+}
diff --git a/cmd/cover/testdata/test.go b/cmd/cover/testdata/test.go
new file mode 100644
index 0000000..9013950
--- /dev/null
+++ b/cmd/cover/testdata/test.go
@@ -0,0 +1,218 @@
+// Copyright 2013 The Go 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 program is processed by the cover command, and then testAll is called.
+// The test driver in main.go can then compare the coverage statistics with expectation.
+
+// The word LINE is replaced by the line number in this file. When the file is executed,
+// the coverage processing has changed the line numbers, so we can't use runtime.Caller.
+
+package main
+
+const anything = 1e9 // Just some unlikely value that means "we got here, don't care how often"
+
+func testAll() {
+	testSimple()
+	testBlockRun()
+	testIf()
+	testFor()
+	testRange()
+	testSwitch()
+	testTypeSwitch()
+	testSelect1()
+	testSelect2()
+	testPanic()
+	testEmptySwitches()
+}
+
+// The indexes of the counters in testPanic are known to main.go
+const panicIndex = 3
+
+// This test appears first because the index of its counters is known to main.go
+func testPanic() {
+	defer func() {
+		recover()
+	}()
+	check(LINE, 1)
+	panic("should not get next line")
+	check(LINE, 0) // this is GoCover.Count[panicIndex]
+	// The next counter is in testSimple and it will be non-zero.
+	// If the panic above does not trigger a counter, the test will fail
+	// because GoCover.Count[panicIndex] will be the one in testSimple.
+}
+
+func testSimple() {
+	check(LINE, 1)
+}
+
+func testIf() {
+	if true {
+		check(LINE, 1)
+	} else {
+		check(LINE, 0)
+	}
+	if false {
+		check(LINE, 0)
+	} else {
+		check(LINE, 1)
+	}
+	for i := 0; i < 3; i++ {
+		if checkVal(LINE, 3, i) <= 2 {
+			check(LINE, 3)
+		}
+		if checkVal(LINE, 3, i) <= 1 {
+			check(LINE, 2)
+		}
+		if checkVal(LINE, 3, i) <= 0 {
+			check(LINE, 1)
+		}
+	}
+	for i := 0; i < 3; i++ {
+		if checkVal(LINE, 3, i) <= 1 {
+			check(LINE, 2)
+		} else {
+			check(LINE, 1)
+		}
+	}
+	for i := 0; i < 3; i++ {
+		if checkVal(LINE, 3, i) <= 0 {
+			check(LINE, 1)
+		} else if checkVal(LINE, 2, i) <= 1 {
+			check(LINE, 1)
+		} else if checkVal(LINE, 1, i) <= 2 {
+			check(LINE, 1)
+		} else if checkVal(LINE, 0, i) <= 3 {
+			check(LINE, 0)
+		}
+	}
+	if func(a, b int) bool { return a < b }(3, 4) {
+		check(LINE, 1)
+	}
+}
+
+func testFor() {
+	for i := 0; i < 10; func() { i++; check(LINE, 10) }() {
+		check(LINE, 10)
+	}
+}
+
+func testRange() {
+	for _, f := range []func(){
+		func() { check(LINE, 1) },
+	} {
+		f()
+		check(LINE, 1)
+	}
+}
+
+func testBlockRun() {
+	check(LINE, 1)
+	{
+		check(LINE, 1)
+	}
+	{
+		check(LINE, 1)
+	}
+	check(LINE, 1)
+	{
+		check(LINE, 1)
+	}
+	{
+		check(LINE, 1)
+	}
+	check(LINE, 1)
+}
+
+func testSwitch() {
+	for i := 0; i < 5; func() { i++; check(LINE, 5) }() {
+		switch i {
+		case 0:
+			check(LINE, 1)
+		case 1:
+			check(LINE, 1)
+		case 2:
+			check(LINE, 1)
+		default:
+			check(LINE, 2)
+		}
+	}
+}
+
+func testTypeSwitch() {
+	var x = []interface{}{1, 2.0, "hi"}
+	for _, v := range x {
+		switch func() { check(LINE, 3) }(); v.(type) {
+		case int:
+			check(LINE, 1)
+		case float64:
+			check(LINE, 1)
+		case string:
+			check(LINE, 1)
+		case complex128:
+			check(LINE, 0)
+		default:
+			check(LINE, 0)
+		}
+	}
+}
+
+func testSelect1() {
+	c := make(chan int)
+	go func() {
+		for i := 0; i < 1000; i++ {
+			c <- i
+		}
+	}()
+	for {
+		select {
+		case <-c:
+			check(LINE, anything)
+		case <-c:
+			check(LINE, anything)
+		default:
+			check(LINE, 1)
+			return
+		}
+	}
+}
+
+func testSelect2() {
+	c1 := make(chan int, 1000)
+	c2 := make(chan int, 1000)
+	for i := 0; i < 1000; i++ {
+		c1 <- i
+		c2 <- i
+	}
+	for {
+		select {
+		case <-c1:
+			check(LINE, 1000)
+		case <-c2:
+			check(LINE, 1000)
+		default:
+			check(LINE, 1)
+			return
+		}
+	}
+}
+
+// Empty control statements created syntax errors. This function
+// is here just to be sure that those are handled correctly now.
+func testEmptySwitches() {
+	check(LINE, 1)
+	switch 3 {
+	}
+	check(LINE, 1)
+	switch i := (interface{})(3).(int); i {
+	}
+	check(LINE, 1)
+	c := make(chan int)
+	go func() {
+		check(LINE, 1)
+		c <- 1
+		select {}
+	}()
+	<-c
+	check(LINE, 1)
+}
diff --git a/cmd/digraph/digraph.go b/cmd/digraph/digraph.go
new file mode 100644
index 0000000..3ad2950
--- /dev/null
+++ b/cmd/digraph/digraph.go
@@ -0,0 +1,540 @@
+// The digraph command performs queries over unlabelled directed graphs
+// represented in text form.  It is intended to integrate nicely with
+// typical UNIX command pipelines.
+//
+// Since directed graphs (import graphs, reference graphs, call graphs,
+// etc) often arise during software tool development and debugging, this
+// command is included in the go.tools repository.
+//
+// TODO(adonovan):
+// - support input files other than stdin
+// - suport alternative formats (AT&T GraphViz, CSV, etc),
+//   a comment syntax, etc.
+// - allow queries to nest, like Blaze query language.
+//
+package main // import "golang.org/x/tools/cmd/digraph"
+
+import (
+	"bufio"
+	"bytes"
+	"errors"
+	"flag"
+	"fmt"
+	"io"
+	"os"
+	"sort"
+	"strconv"
+	"unicode"
+	"unicode/utf8"
+)
+
+const Usage = `digraph: queries over directed graphs in text form.
+
+Graph format:
+
+  Each line contains zero or more words.  Words are separated by
+  unquoted whitespace; words may contain Go-style double-quoted portions,
+  allowing spaces and other characters to be expressed.
+
+  Each field declares a node, and if there are more than one,
+  an edge from the first to each subsequent one.
+  The graph is provided on the standard input.
+
+  For instance, the following (acyclic) graph specifies a partial order
+  among the subtasks of getting dressed:
+
+	% cat clothes.txt
+	socks shoes
+	"boxer shorts" pants
+	pants belt shoes
+	shirt tie sweater
+	sweater jacket
+	hat
+
+  The line "shirt tie sweater" indicates the two edges shirt -> tie and
+  shirt -> sweater, not shirt -> tie -> sweater.
+
+Supported queries:
+
+  nodes
+	the set of all nodes
+  degree
+	the in-degree and out-degree of each node.
+  preds <label> ...
+	the set of immediate predecessors of the specified nodes
+  succs <label> ...
+	the set of immediate successors of the specified nodes
+  forward <label> ...
+	the set of nodes transitively reachable from the specified nodes
+  reverse <label> ...
+	the set of nodes that transitively reach the specified nodes
+  somepath <label> <label>
+	the list of nodes on some arbitrary path from the first node to the second
+  allpaths <label> <label>
+	the set of nodes on all paths from the first node to the second
+  sccs
+	all strongly connected components (one per line)
+  scc <label>
+	the set of nodes nodes strongly connected to the specified one
+
+Example usage:
+
+   Show the transitive closure of imports of the digraph tool itself:
+   % go list -f '{{.ImportPath}}{{.Imports}}' ... | tr '[]' '  ' |
+         digraph forward golang.org/x/tools/cmd/digraph
+
+   Show which clothes (see above) must be donned before a jacket:
+   %  digraph reverse jacket <clothes.txt
+
+`
+
+func main() {
+	flag.Parse()
+
+	args := flag.Args()
+	if len(args) == 0 {
+		fmt.Println(Usage)
+		return
+	}
+
+	if err := digraph(args[0], args[1:]); err != nil {
+		fmt.Fprintf(os.Stderr, "digraph: %s\n", err)
+		os.Exit(1)
+	}
+}
+
+type nodelist []string
+
+func (l nodelist) println(sep string) {
+	for i, label := range l {
+		if i > 0 {
+			fmt.Fprint(stdout, sep)
+		}
+		fmt.Fprint(stdout, label)
+	}
+	fmt.Fprintln(stdout)
+}
+
+type nodeset map[string]bool
+
+func (s nodeset) sort() nodelist {
+	labels := make(nodelist, len(s))
+	var i int
+	for label := range s {
+		labels[i] = label
+		i++
+	}
+	sort.Strings(labels)
+	return labels
+}
+
+func (s nodeset) addAll(x nodeset) {
+	for label := range x {
+		s[label] = true
+	}
+}
+
+// A graph maps nodes to the non-nil set of their immediate successors.
+type graph map[string]nodeset
+
+func (g graph) addNode(label string) nodeset {
+	edges := g[label]
+	if edges == nil {
+		edges = make(nodeset)
+		g[label] = edges
+	}
+	return edges
+}
+
+func (g graph) addEdges(from string, to ...string) {
+	edges := g.addNode(from)
+	for _, to := range to {
+		g.addNode(to)
+		edges[to] = true
+	}
+}
+
+func (g graph) reachableFrom(roots nodeset) nodeset {
+	seen := make(nodeset)
+	var visit func(label string)
+	visit = func(label string) {
+		if !seen[label] {
+			seen[label] = true
+			for e := range g[label] {
+				visit(e)
+			}
+		}
+	}
+	for root := range roots {
+		visit(root)
+	}
+	return seen
+}
+
+func (g graph) transpose() graph {
+	rev := make(graph)
+	for label, edges := range g {
+		rev.addNode(label)
+		for succ := range edges {
+			rev.addEdges(succ, label)
+		}
+	}
+	return rev
+}
+
+func (g graph) sccs() []nodeset {
+	// Kosaraju's algorithm---Tarjan is overkill here.
+
+	// Forward pass.
+	S := make(nodelist, 0, len(g)) // postorder stack
+	seen := make(nodeset)
+	var visit func(label string)
+	visit = func(label string) {
+		if !seen[label] {
+			seen[label] = true
+			for e := range g[label] {
+				visit(e)
+			}
+			S = append(S, label)
+		}
+	}
+	for label := range g {
+		visit(label)
+	}
+
+	// Reverse pass.
+	rev := g.transpose()
+	var scc nodeset
+	seen = make(nodeset)
+	var rvisit func(label string)
+	rvisit = func(label string) {
+		if !seen[label] {
+			seen[label] = true
+			scc[label] = true
+			for e := range rev[label] {
+				rvisit(e)
+			}
+		}
+	}
+	var sccs []nodeset
+	for len(S) > 0 {
+		top := S[len(S)-1]
+		S = S[:len(S)-1] // pop
+		if !seen[top] {
+			scc = make(nodeset)
+			rvisit(top)
+			sccs = append(sccs, scc)
+		}
+	}
+	return sccs
+}
+
+func parse(rd io.Reader) (graph, error) {
+	g := make(graph)
+
+	var linenum int
+	in := bufio.NewScanner(rd)
+	for in.Scan() {
+		linenum++
+		// Split into words, honoring double-quotes per Go spec.
+		words, err := split(in.Text())
+		if err != nil {
+			return nil, fmt.Errorf("at line %d: %v", linenum, err)
+		}
+		if len(words) > 0 {
+			g.addEdges(words[0], words[1:]...)
+		}
+	}
+	if err := in.Err(); err != nil {
+		return nil, err
+	}
+	return g, nil
+}
+
+var stdin io.Reader = os.Stdin
+var stdout io.Writer = os.Stdout
+
+func digraph(cmd string, args []string) error {
+	// Parse the input graph.
+	g, err := parse(stdin)
+	if err != nil {
+		return err
+	}
+
+	// Parse the command line.
+	switch cmd {
+	case "nodes":
+		if len(args) != 0 {
+			return fmt.Errorf("usage: digraph nodes")
+		}
+		nodes := make(nodeset)
+		for label := range g {
+			nodes[label] = true
+		}
+		nodes.sort().println("\n")
+
+	case "degree":
+		if len(args) != 0 {
+			return fmt.Errorf("usage: digraph degree")
+		}
+		nodes := make(nodeset)
+		for label := range g {
+			nodes[label] = true
+		}
+		rev := g.transpose()
+		for _, label := range nodes.sort() {
+			fmt.Fprintf(stdout, "%d\t%d\t%s\n", len(rev[label]), len(g[label]), label)
+		}
+
+	case "succs", "preds":
+		if len(args) == 0 {
+			return fmt.Errorf("usage: digraph %s <label> ...", cmd)
+		}
+		g := g
+		if cmd == "preds" {
+			g = g.transpose()
+		}
+		result := make(nodeset)
+		for _, root := range args {
+			edges := g[root]
+			if edges == nil {
+				return fmt.Errorf("no such node %q", root)
+			}
+			result.addAll(edges)
+		}
+		result.sort().println("\n")
+
+	case "forward", "reverse":
+		if len(args) == 0 {
+			return fmt.Errorf("usage: digraph %s <label> ...", cmd)
+		}
+		roots := make(nodeset)
+		for _, root := range args {
+			if g[root] == nil {
+				return fmt.Errorf("no such node %q", root)
+			}
+			roots[root] = true
+		}
+		g := g
+		if cmd == "reverse" {
+			g = g.transpose()
+		}
+		g.reachableFrom(roots).sort().println("\n")
+
+	case "somepath":
+		if len(args) != 2 {
+			return fmt.Errorf("usage: digraph somepath <from> <to>")
+		}
+		from, to := args[0], args[1]
+		if g[from] == nil {
+			return fmt.Errorf("no such 'from' node %q", from)
+		}
+		if g[to] == nil {
+			return fmt.Errorf("no such 'to' node %q", to)
+		}
+
+		seen := make(nodeset)
+		var visit func(path nodelist, label string) bool
+		visit = func(path nodelist, label string) bool {
+			if !seen[label] {
+				seen[label] = true
+				if label == to {
+					append(path, label).println("\n")
+					return true // unwind
+				}
+				for e := range g[label] {
+					if visit(append(path, label), e) {
+						return true
+					}
+				}
+			}
+			return false
+		}
+		if !visit(make(nodelist, 0, 100), from) {
+			return fmt.Errorf("no path from %q to %q", args[0], args[1])
+		}
+
+	case "allpaths":
+		if len(args) != 2 {
+			return fmt.Errorf("usage: digraph allpaths <from> <to>")
+		}
+		from, to := args[0], args[1]
+		if g[from] == nil {
+			return fmt.Errorf("no such 'from' node %q", from)
+		}
+		if g[to] == nil {
+			return fmt.Errorf("no such 'to' node %q", to)
+		}
+
+		seen := make(nodeset) // value of seen[x] indicates whether x is on some path to 'to'
+		var visit func(label string) bool
+		visit = func(label string) bool {
+			reachesTo, ok := seen[label]
+			if !ok {
+				reachesTo = label == to
+
+				seen[label] = reachesTo
+				for e := range g[label] {
+					if visit(e) {
+						reachesTo = true
+					}
+				}
+				seen[label] = reachesTo
+			}
+			return reachesTo
+		}
+		if !visit(from) {
+			return fmt.Errorf("no path from %q to %q", from, to)
+		}
+		for label, reachesTo := range seen {
+			if !reachesTo {
+				delete(seen, label)
+			}
+		}
+		seen.sort().println("\n")
+
+	case "sccs":
+		if len(args) != 0 {
+			return fmt.Errorf("usage: digraph sccs")
+		}
+		for _, scc := range g.sccs() {
+			scc.sort().println(" ")
+		}
+
+	case "scc":
+		if len(args) != 1 {
+			return fmt.Errorf("usage: digraph scc <label>")
+		}
+		label := args[0]
+		if g[label] == nil {
+			return fmt.Errorf("no such node %q", label)
+		}
+		for _, scc := range g.sccs() {
+			if scc[label] {
+				scc.sort().println("\n")
+				break
+			}
+		}
+
+	default:
+		return fmt.Errorf("no such command %q", cmd)
+	}
+
+	return nil
+}
+
+// -- Utilities --------------------------------------------------------
+
+// split splits a line into words, which are generally separated by
+// spaces, but Go-style double-quoted string literals are also supported.
+// (This approximates the behaviour of the Bourne shell.)
+//
+//   `one "two three"` -> ["one" "two three"]
+//   `a"\n"b` -> ["a\nb"]
+//
+func split(line string) ([]string, error) {
+	var (
+		words   []string
+		inWord  bool
+		current bytes.Buffer
+	)
+
+	for len(line) > 0 {
+		r, size := utf8.DecodeRuneInString(line)
+		if unicode.IsSpace(r) {
+			if inWord {
+				words = append(words, current.String())
+				current.Reset()
+				inWord = false
+			}
+		} else if r == '"' {
+			var ok bool
+			size, ok = quotedLength(line)
+			if !ok {
+				return nil, errors.New("invalid quotation")
+			}
+			s, err := strconv.Unquote(line[:size])
+			if err != nil {
+				return nil, err
+			}
+			current.WriteString(s)
+			inWord = true
+		} else {
+			current.WriteRune(r)
+			inWord = true
+		}
+		line = line[size:]
+	}
+	if inWord {
+		words = append(words, current.String())
+	}
+	return words, nil
+}
+
+// quotedLength returns the length in bytes of the prefix of input that
+// contain a possibly-valid double-quoted Go string literal.
+//
+// On success, n is at least two (""); input[:n] may be passed to
+// strconv.Unquote to interpret its value, and input[n:] contains the
+// rest of the input.
+//
+// On failure, quotedLength returns false, and the entire input can be
+// passed to strconv.Unquote if an informative error message is desired.
+//
+// quotedLength does not and need not detect all errors, such as
+// invalid hex or octal escape sequences, since it assumes
+// strconv.Unquote will be applied to the prefix.  It guarantees only
+// that if there is a prefix of input containing a valid string literal,
+// its length is returned.
+//
+// TODO(adonovan): move this into a strconv-like utility package.
+//
+func quotedLength(input string) (n int, ok bool) {
+	var offset int
+
+	// next returns the rune at offset, or -1 on EOF.
+	// offset advances to just after that rune.
+	next := func() rune {
+		if offset < len(input) {
+			r, size := utf8.DecodeRuneInString(input[offset:])
+			offset += size
+			return r
+		}
+		return -1
+	}
+
+	if next() != '"' {
+		return // error: not a quotation
+	}
+
+	for {
+		r := next()
+		if r == '\n' || r < 0 {
+			return // error: string literal not terminated
+		}
+		if r == '"' {
+			return offset, true // success
+		}
+		if r == '\\' {
+			var skip int
+			switch next() {
+			case 'a', 'b', 'f', 'n', 'r', 't', 'v', '\\', '"':
+				skip = 0
+			case '0', '1', '2', '3', '4', '5', '6', '7':
+				skip = 2
+			case 'x':
+				skip = 2
+			case 'u':
+				skip = 4
+			case 'U':
+				skip = 8
+			default:
+				return // error: invalid escape
+			}
+
+			for i := 0; i < skip; i++ {
+				next()
+			}
+		}
+	}
+}
diff --git a/cmd/digraph/digraph_test.go b/cmd/digraph/digraph_test.go
new file mode 100644
index 0000000..0c90304
--- /dev/null
+++ b/cmd/digraph/digraph_test.go
@@ -0,0 +1,121 @@
+package main
+
+import (
+	"bytes"
+	"fmt"
+	"reflect"
+	"strings"
+	"testing"
+)
+
+func TestDigraph(t *testing.T) {
+	const g1 = `
+socks shoes
+shorts pants
+pants belt shoes
+shirt tie sweater
+sweater jacket
+hat
+`
+
+	const g2 = `
+a b c
+b d
+c d
+d c
+`
+
+	for _, test := range []struct {
+		input string
+		cmd   string
+		args  []string
+		want  string
+	}{
+		{g1, "nodes", nil, "belt\nhat\njacket\npants\nshirt\nshoes\nshorts\nsocks\nsweater\ntie\n"},
+		{g1, "reverse", []string{"jacket"}, "jacket\nshirt\nsweater\n"},
+		{g1, "forward", []string{"socks"}, "shoes\nsocks\n"},
+		{g1, "forward", []string{"socks", "sweater"}, "jacket\nshoes\nsocks\nsweater\n"},
+
+		{g2, "allpaths", []string{"a", "d"}, "a\nb\nc\nd\n"},
+
+		{g2, "sccs", nil, "a\nb\nc d\n"},
+		{g2, "scc", []string{"d"}, "c\nd\n"},
+		{g2, "succs", []string{"a"}, "b\nc\n"},
+		{g2, "preds", []string{"c"}, "a\nd\n"},
+		{g2, "preds", []string{"c", "d"}, "a\nb\nc\nd\n"},
+	} {
+		stdin = strings.NewReader(test.input)
+		stdout = new(bytes.Buffer)
+		if err := digraph(test.cmd, test.args); err != nil {
+			t.Error(err)
+			continue
+		}
+
+		got := stdout.(fmt.Stringer).String()
+		if got != test.want {
+			t.Errorf("digraph(%s, %s) = %q, want %q", test.cmd, test.args, got, test.want)
+		}
+	}
+
+	// TODO(adonovan):
+	// - test somepath (it's nondeterministic).
+	// - test errors
+}
+
+func TestSplit(t *testing.T) {
+	for _, test := range []struct {
+		line string
+		want []string
+	}{
+		{`one "2a 2b" three`, []string{"one", "2a 2b", "three"}},
+		{`one tw"\n\x0a\u000a\012"o three`, []string{"one", "tw\n\n\n\no", "three"}},
+	} {
+		got, err := split(test.line)
+		if err != nil {
+			t.Errorf("split(%s) failed: %v", test.line, err)
+		}
+		if !reflect.DeepEqual(got, test.want) {
+			t.Errorf("split(%s) = %v, want %v", test.line, got, test.want)
+		}
+	}
+}
+
+func TestQuotedLength(t *testing.T) {
+	for _, test := range []struct {
+		input string
+		want  int
+	}{
+		{`"abc"`, 5},
+		{`"abc"def`, 5},
+		{`"abc\"d"ef`, 8}, // "abc\"d" is consumed, ef is residue
+		{`"\012\n\x0a\u000a\U0000000a"`, 28},
+		{"\"\xff\"", 3}, // bad UTF-8 is ok
+		{`"\xff"`, 6},   // hex escape for bad UTF-8 is ok
+	} {
+		got, ok := quotedLength(test.input)
+		if !ok {
+			got = 0
+		}
+		if got != test.want {
+			t.Errorf("quotedLength(%s) = %d, want %d", test.input, got, test.want)
+		}
+	}
+
+	// errors
+	for _, input := range []string{
+		``,            // not a quotation
+		`a`,           // not a quotation
+		`'a'`,         // not a quotation
+		`"a`,          // not terminated
+		`"\0"`,        // short octal escape
+		`"\x1"`,       // short hex escape
+		`"\u000"`,     // short \u escape
+		`"\U0000000"`, // short \U escape
+		`"\k"`,        // invalid escape
+		"\"ab\nc\"",   // newline
+	} {
+		if n, ok := quotedLength(input); ok {
+			t.Errorf("quotedLength(%s) = %d, want !ok", input, n)
+		}
+	}
+}
diff --git a/cmd/eg/eg.go b/cmd/eg/eg.go
new file mode 100644
index 0000000..5970c1a
--- /dev/null
+++ b/cmd/eg/eg.go
@@ -0,0 +1,150 @@
+// The eg command performs example-based refactoring.
+// For documentation, run the command, or see Help in
+// golang.org/x/tools/refactor/eg.
+package main // import "golang.org/x/tools/cmd/eg"
+
+import (
+	"flag"
+	"fmt"
+	"go/build"
+	"go/parser"
+	"go/printer"
+	"go/token"
+	"os"
+	"os/exec"
+	"strings"
+
+	"golang.org/x/tools/go/buildutil"
+	"golang.org/x/tools/go/loader"
+	"golang.org/x/tools/refactor/eg"
+)
+
+var (
+	beforeeditFlag = flag.String("beforeedit", "", "A command to exec before each file is edited (e.g. chmod, checkout).  Whitespace delimits argument words.  The string '{}' is replaced by the file name.")
+	helpFlag       = flag.Bool("help", false, "show detailed help message")
+	templateFlag   = flag.String("t", "", "template.go file specifying the refactoring")
+	transitiveFlag = flag.Bool("transitive", false, "apply refactoring to all dependencies too")
+	writeFlag      = flag.Bool("w", false, "rewrite input files in place (by default, the results are printed to standard output)")
+	verboseFlag    = flag.Bool("v", false, "show verbose matcher diagnostics")
+)
+
+func init() {
+	flag.Var((*buildutil.TagsFlag)(&build.Default.BuildTags), "tags", buildutil.TagsFlagDoc)
+}
+
+const usage = `eg: an example-based refactoring tool.
+
+Usage: eg -t template.go [-w] [-transitive] <args>...
+
+-help            show detailed help message
+-t template.go	 specifies the template file (use -help to see explanation)
+-w          	 causes files to be re-written in place.
+-transitive 	 causes all dependencies to be refactored too.
+-v               show verbose matcher diagnostics
+-beforeedit cmd  a command to exec before each file is modified.
+                 "{}" represents the name of the file.
+` + loader.FromArgsUsage
+
+func main() {
+	if err := doMain(); err != nil {
+		fmt.Fprintf(os.Stderr, "eg: %s\n", err)
+		os.Exit(1)
+	}
+}
+
+func doMain() error {
+	flag.Parse()
+	args := flag.Args()
+
+	if *helpFlag {
+		fmt.Fprint(os.Stderr, eg.Help)
+		os.Exit(2)
+	}
+
+	if len(args) == 0 {
+		fmt.Fprint(os.Stderr, usage)
+		os.Exit(1)
+	}
+
+	if *templateFlag == "" {
+		return fmt.Errorf("no -t template.go file specified")
+	}
+
+	conf := loader.Config{
+		Fset:       token.NewFileSet(),
+		ParserMode: parser.ParseComments,
+	}
+
+	// The first Created package is the template.
+	conf.CreateFromFilenames("template", *templateFlag)
+
+	if _, err := conf.FromArgs(args, true); err != nil {
+		return err
+	}
+
+	// Load, parse and type-check the whole program.
+	iprog, err := conf.Load()
+	if err != nil {
+		return err
+	}
+
+	// Analyze the template.
+	template := iprog.Created[0]
+	xform, err := eg.NewTransformer(iprog.Fset, template, *verboseFlag)
+	if err != nil {
+		return err
+	}
+
+	// Apply it to the input packages.
+	var pkgs []*loader.PackageInfo
+	if *transitiveFlag {
+		for _, info := range iprog.AllPackages {
+			pkgs = append(pkgs, info)
+		}
+	} else {
+		pkgs = iprog.InitialPackages()
+	}
+	var hadErrors bool
+	for _, pkg := range pkgs {
+		if pkg == template {
+			continue
+		}
+		for _, file := range pkg.Files {
+			n := xform.Transform(&pkg.Info, pkg.Pkg, file)
+			if n == 0 {
+				continue
+			}
+			filename := iprog.Fset.File(file.Pos()).Name()
+			fmt.Fprintf(os.Stderr, "=== %s (%d matches)\n", filename, n)
+			if *writeFlag {
+				// Run the before-edit command (e.g. "chmod +w",  "checkout") if any.
+				if *beforeeditFlag != "" {
+					args := strings.Fields(*beforeeditFlag)
+					// Replace "{}" with the filename, like find(1).
+					for i := range args {
+						if i > 0 {
+							args[i] = strings.Replace(args[i], "{}", filename, -1)
+						}
+					}
+					cmd := exec.Command(args[0], args[1:]...)
+					cmd.Stdout = os.Stdout
+					cmd.Stderr = os.Stderr
+					if err := cmd.Run(); err != nil {
+						fmt.Fprintf(os.Stderr, "Warning: edit hook %q failed (%s)\n",
+							args, err)
+					}
+				}
+				if err := eg.WriteAST(iprog.Fset, filename, file); err != nil {
+					fmt.Fprintf(os.Stderr, "eg: %s\n", err)
+					hadErrors = true
+				}
+			} else {
+				printer.Fprint(os.Stdout, iprog.Fset, file)
+			}
+		}
+	}
+	if hadErrors {
+		os.Exit(1)
+	}
+	return nil
+}
diff --git a/cmd/fiximports/main.go b/cmd/fiximports/main.go
new file mode 100644
index 0000000..86ae777
--- /dev/null
+++ b/cmd/fiximports/main.go
@@ -0,0 +1,451 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// The fiximports command fixes import declarations to use the canonical
+// import path for packages that have an "import comment" as defined by
+// https://golang.org/s/go14customimport.
+//
+//
+// Background
+//
+// The Go 1 custom import path mechanism lets the maintainer of a
+// package give it a stable name by which clients may import and "go
+// get" it, independent of the underlying version control system (such
+// as Git) or server (such as github.com) that hosts it.  Requests for
+// the custom name are redirected to the underlying name.  This allows
+// packages to be migrated from one underlying server or system to
+// another without breaking existing clients.
+//
+// Because this redirect mechanism creates aliases for existing
+// packages, it's possible for a single program to import the same
+// package by its canonical name and by an alias.  The resulting
+// executable will contain two copies of the package, which is wasteful
+// at best and incorrect at worst.
+//
+// To avoid this, "go build" reports an error if it encounters a special
+// comment like the one below, and if the import path in the comment
+// does not match the path of the enclosing package relative to
+// GOPATH/src:
+//
+//      $ grep ^package $GOPATH/src/github.com/bob/vanity/foo/foo.go
+// 	package foo // import "vanity.com/foo"
+//
+// The error from "go build" indicates that the package canonically
+// known as "vanity.com/foo" is locally installed under the
+// non-canonical name "github.com/bob/vanity/foo".
+//
+//
+// Usage
+//
+// When a package that you depend on introduces a custom import comment,
+// and your workspace imports it by the non-canonical name, your build
+// will stop working as soon as you update your copy of that package
+// using "go get -u".
+//
+// The purpose of the fiximports tool is to fix up all imports of the
+// non-canonical path within a Go workspace, replacing them with imports
+// of the canonical path.  Following a run of fiximports, the workspace
+// will no longer depend on the non-canonical copy of the package, so it
+// should be safe to delete.  It may be necessary to run "go get -u"
+// again to ensure that the package is locally installed under its
+// canonical path, if it was not already.
+//
+// The fiximports tool operates locally; it does not make HTTP requests
+// and does not discover new custom import comments.  It only operates
+// on non-canonical packages present in your workspace.
+//
+// The -baddomains flag is a list of domain names that should always be
+// considered non-canonical.  You can use this if you wish to make sure
+// that you no longer have any dependencies on packages from that
+// domain, even those that do not yet provide a canical import path
+// comment.  For example, the default value of -baddomains includes the
+// moribund code hosting site code.google.com, so fiximports will report
+// an error for each import of a package from this domain remaining
+// after canonicalization.
+//
+// To see the changes fiximports would make without applying them, use
+// the -n flag.
+//
+package main
+
+import (
+	"bytes"
+	"encoding/json"
+	"flag"
+	"fmt"
+	"go/ast"
+	"go/build"
+	"go/format"
+	"go/parser"
+	"go/token"
+	"io"
+	"io/ioutil"
+	"log"
+	"os"
+	"os/exec"
+	"path"
+	"path/filepath"
+	"sort"
+	"strconv"
+	"strings"
+)
+
+// flags
+var (
+	dryrun     = flag.Bool("n", false, "dry run: show changes, but don't apply them")
+	badDomains = flag.String("baddomains", "code.google.com",
+		"a comma-separated list of domains from which packages should not be imported")
+)
+
+// seams for testing
+var (
+	stderr    io.Writer = os.Stderr
+	writeFile           = ioutil.WriteFile
+)
+
+const usage = `fiximports: rewrite import paths to use canonical package names.
+
+Usage: fiximports [-n] package...
+
+The package... arguments specify a list of packages
+in the style of the go tool; see "go help packages".
+Hint: use "all" or "..." to match the entire workspace.
+
+For details, see http://godoc.org/golang.org/x/tools/cmd/fiximports.
+
+Flags:
+  -n:	       dry run: show changes, but don't apply them
+  -baddomains  a comma-separated list of domains from which packages
+               should not be imported
+`
+
+func main() {
+	flag.Parse()
+
+	if len(flag.Args()) == 0 {
+		fmt.Fprintf(stderr, usage)
+		os.Exit(1)
+	}
+	if !fiximports(flag.Args()...) {
+		os.Exit(1)
+	}
+}
+
+// fiximports fixes imports in the specified packages.
+// Invariant: a false result implies an error was already printed.
+func fiximports(packages ...string) bool {
+	// importedBy is the transpose of the package import graph.
+	importedBy := make(map[string]map[*build.Package]bool)
+
+	// addEdge adds an edge to the import graph.
+	addEdge := func(from *build.Package, to string) {
+		if to == "C" || to == "unsafe" {
+			return // fake
+		}
+		pkgs := importedBy[to]
+		if pkgs == nil {
+			pkgs = make(map[*build.Package]bool)
+			importedBy[to] = pkgs
+		}
+		pkgs[from] = true
+	}
+
+	// List metadata for all packages in the workspace.
+	pkgs, err := list("...")
+	if err != nil {
+		fmt.Fprintf(stderr, "importfix: %v\n", err)
+		return false
+	}
+
+	// noncanonical maps each non-canonical package path to
+	// its canonical name.
+	// A present nil value indicates that the canonical package
+	// is unknown: hosted on a bad domain with no redirect.
+	noncanonical := make(map[string]*build.Package)
+	domains := strings.Split(*badDomains, ",")
+
+	// Find non-canonical packages and populate importedBy graph.
+	for _, p := range pkgs {
+		if p.Error != nil {
+			msg := p.Error.Err
+			if strings.Contains(msg, "code in directory") &&
+				strings.Contains(msg, "expects import") {
+				// don't show the very errors we're trying to fix
+			} else {
+				fmt.Fprintln(stderr, msg)
+			}
+		}
+
+		for _, imp := range p.Imports {
+			addEdge(&p.Package, imp)
+		}
+		for _, imp := range p.TestImports {
+			addEdge(&p.Package, imp)
+		}
+		for _, imp := range p.XTestImports {
+			addEdge(&p.Package, imp)
+		}
+
+		if p.ImportComment != "" {
+			if p.ImportComment != p.ImportPath {
+				noncanonical[p.ImportPath] = &p.Package
+			}
+		} else {
+			for _, domain := range domains {
+				slash := strings.Index(p.ImportPath, "/")
+				if slash < 0 {
+					continue // no slash: standard package
+				}
+				if p.ImportPath[:slash] == domain {
+					// Package comes from bad domain and has no import comment.
+					// Report an error each time this package is imported.
+					noncanonical[p.ImportPath] = nil
+
+					// TODO(adonovan): should we make an HTTP request to
+					// see if there's an HTTP redirect, a "go-import" meta tag,
+					// or an import comment in the the latest revision?
+					// It would duplicate a lot of logic from "go get".
+				}
+				break
+			}
+		}
+	}
+
+	// Find all clients (direct importers) of noncanonical packages.
+	// These are the packages that need fixing up.
+	clients := make(map[*build.Package]bool)
+	for path := range noncanonical {
+		for client := range importedBy[path] {
+			clients[client] = true
+		}
+	}
+
+	// Restrict rewrites to the set of packages specified by the user.
+	if len(packages) == 1 && (packages[0] == "all" || packages[0] == "...") {
+		// no restriction
+	} else {
+		pkgs, err := list(packages...)
+		if err != nil {
+			fmt.Fprintf(stderr, "importfix: %v\n", err)
+			return false
+		}
+		seen := make(map[string]bool)
+		for _, p := range pkgs {
+			seen[p.ImportPath] = true
+		}
+		for client := range clients {
+			if !seen[client.ImportPath] {
+				delete(clients, client)
+			}
+		}
+	}
+
+	// Rewrite selected client packages.
+	ok := true
+	for client := range clients {
+		if !rewritePackage(client, noncanonical) {
+			ok = false
+
+			// There were errors.
+			// Show direct and indirect imports of client.
+			seen := make(map[string]bool)
+			var direct, indirect []string
+			for p := range importedBy[client.ImportPath] {
+				direct = append(direct, p.ImportPath)
+				seen[p.ImportPath] = true
+			}
+
+			var visit func(path string)
+			visit = func(path string) {
+				for q := range importedBy[path] {
+					qpath := q.ImportPath
+					if !seen[qpath] {
+						seen[qpath] = true
+						indirect = append(indirect, qpath)
+						visit(qpath)
+					}
+				}
+			}
+
+			if direct != nil {
+				fmt.Fprintf(stderr, "\timported directly by:\n")
+				sort.Strings(direct)
+				for _, path := range direct {
+					fmt.Fprintf(stderr, "\t\t%s\n", path)
+					visit(path)
+				}
+
+				if indirect != nil {
+					fmt.Fprintf(stderr, "\timported indirectly by:\n")
+					sort.Strings(indirect)
+					for _, path := range indirect {
+						fmt.Fprintf(stderr, "\t\t%s\n", path)
+					}
+				}
+			}
+		}
+	}
+
+	return ok
+}
+
+// Invariant: false result => error already printed.
+func rewritePackage(client *build.Package, noncanonical map[string]*build.Package) bool {
+	ok := true
+
+	used := make(map[string]bool)
+	var filenames []string
+	filenames = append(filenames, client.GoFiles...)
+	filenames = append(filenames, client.TestGoFiles...)
+	filenames = append(filenames, client.XTestGoFiles...)
+	var first bool
+	for _, filename := range filenames {
+		if !first {
+			first = true
+			fmt.Fprintf(stderr, "%s\n", client.ImportPath)
+		}
+		err := rewriteFile(filepath.Join(client.Dir, filename), noncanonical, used)
+		if err != nil {
+			fmt.Fprintf(stderr, "\tERROR: %v\n", err)
+			ok = false
+		}
+	}
+
+	// Show which imports were renamed in this package.
+	var keys []string
+	for key := range used {
+		keys = append(keys, key)
+	}
+	sort.Strings(keys)
+	for _, key := range keys {
+		if p := noncanonical[key]; p != nil {
+			fmt.Fprintf(stderr, "\tfixed: %s -> %s\n", key, p.ImportComment)
+		} else {
+			fmt.Fprintf(stderr, "\tERROR: %s has no import comment\n", key)
+			ok = false
+		}
+	}
+
+	return ok
+}
+
+// rewrite reads, modifies, and writes filename, replacing all imports
+// of packages P in noncanonical by noncanonical[P].
+// It records in used which noncanonical packages were imported.
+// used[P]=="" indicates that P was imported but its canonical path is unknown.
+func rewriteFile(filename string, noncanonical map[string]*build.Package, used map[string]bool) error {
+	fset := token.NewFileSet()
+	f, err := parser.ParseFile(fset, filename, nil, parser.ParseComments)
+	if err != nil {
+		return err
+	}
+	var changed bool
+	for _, imp := range f.Imports {
+		impPath, err := strconv.Unquote(imp.Path.Value)
+		if err != nil {
+			log.Printf("%s: bad import spec %q: %v",
+				fset.Position(imp.Pos()), imp.Path.Value, err)
+			continue
+		}
+		p, ok := noncanonical[impPath]
+		if !ok {
+			continue // import path is canonical
+		}
+
+		used[impPath] = true
+
+		if p == nil {
+			// The canonical path is unknown.
+			// Show the offending import.
+			// TODO(adonovan): should we show the actual source text?
+			fmt.Fprintf(stderr, "\t%s:%d: import %q\n",
+				shortPath(filename),
+				fset.Position(imp.Pos()).Line, impPath)
+			continue
+		}
+
+		changed = true
+
+		imp.Path.Value = strconv.Quote(p.ImportComment)
+
+		// Add a renaming import if necessary.
+		//
+		// This is a guess at best.  We can't see whether a 'go
+		// get' of the canonical import path would have the same
+		// name or not.  Assume it's the last segment.
+		//
+		// TODO(adonovan): should we make an HTTP request?
+		newBase := path.Base(p.ImportComment)
+		if imp.Name == nil && newBase != p.Name {
+			imp.Name = &ast.Ident{Name: p.Name}
+		}
+	}
+
+	if changed && !*dryrun {
+		var buf bytes.Buffer
+		if err := format.Node(&buf, fset, f); err != nil {
+			return fmt.Errorf("%s: couldn't format file: %v", filename, err)
+		}
+		return writeFile(filename, buf.Bytes(), 0644)
+	}
+
+	return nil
+}
+
+// listPackage is a copy of cmd/go/list.Package.
+// It has more fields than build.Package and we need some of them.
+type listPackage struct {
+	build.Package
+	Error *packageError // error loading package
+}
+
+// A packageError describes an error loading information about a package.
+type packageError struct {
+	ImportStack []string // shortest path from package named on command line to this one
+	Pos         string   // position of error
+	Err         string   // the error itself
+}
+
+// list runs 'go list' with the specified arguments and returns the
+// metadata for matching packages.
+func list(args ...string) ([]*listPackage, error) {
+	cmd := exec.Command("go", append([]string{"list", "-e", "-json"}, args...)...)
+	cmd.Stdout = new(bytes.Buffer)
+	cmd.Stderr = stderr
+	if err := cmd.Run(); err != nil {
+		return nil, err
+	}
+
+	dec := json.NewDecoder(cmd.Stdout.(io.Reader))
+	var pkgs []*listPackage
+	for {
+		var p listPackage
+		if err := dec.Decode(&p); err == io.EOF {
+			break
+		} else if err != nil {
+			return nil, err
+		}
+		pkgs = append(pkgs, &p)
+	}
+	return pkgs, nil
+}
+
+var cwd string
+
+func init() {
+	var err error
+	cwd, err = os.Getwd()
+	if err != nil {
+		log.Fatalf("os.Getwd: %v", err)
+	}
+}
+
+// shortPath returns an absolute or relative name for path, whatever is shorter.
+// Plundered from $GOROOT/src/cmd/go/build.go.
+func shortPath(path string) string {
+	if rel, err := filepath.Rel(cwd, path); err == nil && len(rel) < len(path) {
+		return rel
+	}
+	return path
+}
diff --git a/cmd/fiximports/main_test.go b/cmd/fiximports/main_test.go
new file mode 100644
index 0000000..c8f7bc3
--- /dev/null
+++ b/cmd/fiximports/main_test.go
@@ -0,0 +1,169 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// No testdata on Android.
+
+// +build !android
+
+package main
+
+import (
+	"bytes"
+	"os"
+	"path/filepath"
+	"runtime"
+	"strings"
+	"testing"
+)
+
+// TODO(adonovan):
+// - test introduction of renaming imports.
+// - test induced failures of rewriteFile.
+
+// Guide to the test packages:
+//
+// new.com/one		-- canonical name for old.com/one
+// old.com/one		-- non-canonical; has import comment "new.com/one"
+// old.com/bad		-- has a parse error
+// fruit.io/orange	\
+// fruit.io/banana	 } orange -> pear -> banana -> titanic.biz/bar
+// fruit.io/pear	/
+// titanic.biz/bar	-- domain is sinking; package has jumped ship to new.com/bar
+// titanic.biz/foo	-- domain is sinking but package has no import comment yet
+
+func TestFixImports(t *testing.T) {
+	gopath := filepath.Join(cwd, "testdata")
+	if err := os.Setenv("GOPATH", gopath); err != nil {
+		t.Fatalf("os.Setenv: %v", err)
+	}
+	defer func() {
+		stderr = os.Stderr
+		*badDomains = "code.google.com"
+	}()
+
+	for i, test := range []struct {
+		packages    []string // packages to rewrite, "go list" syntax
+		badDomains  string   // -baddomains flag
+		wantOK      bool
+		wantStderr  string
+		wantRewrite map[string]string
+	}{
+		// #0. No errors.
+		{
+			packages:   []string{"all"},
+			badDomains: "code.google.com",
+			wantOK:     true,
+			wantStderr: `
+testdata/src/old.com/bad/bad.go:2:43: expected 'package', found 'EOF'
+fruit.io/banana
+	fixed: old.com/one -> new.com/one
+	fixed: titanic.biz/bar -> new.com/bar
+`,
+			wantRewrite: map[string]string{
+				"$GOPATH/src/fruit.io/banana/banana.go": `package banana
+
+import (
+	_ "new.com/bar"
+	_ "new.com/one"
+	_ "titanic.biz/foo"
+)`,
+			},
+		},
+		// #1. No packages needed rewriting.
+		{
+			packages:   []string{"titanic.biz/...", "old.com/...", "new.com/..."},
+			badDomains: "code.google.com",
+			wantOK:     true,
+			wantStderr: `
+testdata/src/old.com/bad/bad.go:2:43: expected 'package', found 'EOF'
+`,
+		},
+		// #2. Some packages without import comments matched bad domains.
+		{
+			packages:   []string{"all"},
+			badDomains: "titanic.biz",
+			wantOK:     false,
+			wantStderr: `
+testdata/src/old.com/bad/bad.go:2:43: expected 'package', found 'EOF'
+fruit.io/banana
+	testdata/src/fruit.io/banana/banana.go:6: import "titanic.biz/foo"
+	fixed: old.com/one -> new.com/one
+	fixed: titanic.biz/bar -> new.com/bar
+	ERROR: titanic.biz/foo has no import comment
+	imported directly by:
+		fruit.io/pear
+	imported indirectly by:
+		fruit.io/orange
+`,
+			wantRewrite: map[string]string{
+				"$GOPATH/src/fruit.io/banana/banana.go": `package banana
+
+import (
+	_ "new.com/bar"
+	_ "new.com/one"
+	_ "titanic.biz/foo"
+)`,
+			},
+		},
+	} {
+		*badDomains = test.badDomains
+
+		stderr = new(bytes.Buffer)
+		gotRewrite := make(map[string]string)
+		writeFile = func(filename string, content []byte, mode os.FileMode) error {
+			filename = strings.Replace(filename, gopath, "$GOPATH", 1)
+			filename = filepath.ToSlash(filename)
+			gotRewrite[filename] = string(bytes.TrimSpace(content))
+			return nil
+		}
+
+		if runtime.GOOS == "windows" {
+			test.wantStderr = strings.Replace(test.wantStderr, `testdata/src/old.com/bad/bad.go`, `testdata\src\old.com\bad\bad.go`, -1)
+			test.wantStderr = strings.Replace(test.wantStderr, `testdata/src/fruit.io/banana/banana.go`, `testdata\src\fruit.io\banana\banana.go`, -1)
+		}
+
+		// Check status code.
+		if fiximports(test.packages...) != test.wantOK {
+			t.Errorf("#%d. fiximports() = %t", i, !test.wantOK)
+		}
+
+		// Compare stderr output.
+		if stderr.(*bytes.Buffer).String() != test.wantStderr {
+			t.Errorf("#%d. stderr: got <<%s>>, want <<%s>>",
+				i, stderr, test.wantStderr)
+		}
+
+		// Compare rewrites.
+		for k, v := range gotRewrite {
+			if test.wantRewrite[k] != v {
+				t.Errorf("#%d. rewrite[%s] = <<%s>>, want <<%s>>",
+					i, k, v, test.wantRewrite[k])
+			}
+			delete(test.wantRewrite, k)
+		}
+		for k, v := range test.wantRewrite {
+			t.Errorf("#%d. rewrite[%s] missing, want <<%s>>", i, k, v)
+		}
+	}
+}
+
+// TestDryRun tests that the -n flag suppresses calls to writeFile.
+func TestDryRun(t *testing.T) {
+	gopath := filepath.Join(cwd, "testdata")
+	if err := os.Setenv("GOPATH", gopath); err != nil {
+		t.Fatalf("os.Setenv: %v", err)
+	}
+
+	*dryrun = true
+	defer func() { *dryrun = false }() // restore
+	stderr = new(bytes.Buffer)
+	writeFile = func(filename string, content []byte, mode os.FileMode) error {
+		t.Fatalf("writeFile(%s) called in dryrun mode", filename)
+		return nil
+	}
+
+	if !fiximports("all") {
+		t.Fatalf("fiximports failed: %s", stderr)
+	}
+}
diff --git a/cmd/fiximports/testdata/src/fruit.io/banana/banana.go b/cmd/fiximports/testdata/src/fruit.io/banana/banana.go
new file mode 100644
index 0000000..04e0242
--- /dev/null
+++ b/cmd/fiximports/testdata/src/fruit.io/banana/banana.go
@@ -0,0 +1,7 @@
+package banana
+
+import (
+	_ "old.com/one"
+	_ "titanic.biz/bar"
+	_ "titanic.biz/foo"
+)
diff --git a/cmd/fiximports/testdata/src/fruit.io/orange/orange.go b/cmd/fiximports/testdata/src/fruit.io/orange/orange.go
new file mode 100644
index 0000000..ae65daa
--- /dev/null
+++ b/cmd/fiximports/testdata/src/fruit.io/orange/orange.go
@@ -0,0 +1,3 @@
+package orange
+
+import _ "fruit.io/pear"
diff --git a/cmd/fiximports/testdata/src/fruit.io/pear/pear.go b/cmd/fiximports/testdata/src/fruit.io/pear/pear.go
new file mode 100644
index 0000000..de92df0
--- /dev/null
+++ b/cmd/fiximports/testdata/src/fruit.io/pear/pear.go
@@ -0,0 +1,3 @@
+package pear
+
+import _ "fruit.io/banana"
diff --git a/cmd/fiximports/testdata/src/new.com/one/one.go b/cmd/fiximports/testdata/src/new.com/one/one.go
new file mode 100644
index 0000000..a8c5e83
--- /dev/null
+++ b/cmd/fiximports/testdata/src/new.com/one/one.go
@@ -0,0 +1 @@
+package one // import "new.com/one"
diff --git a/cmd/fiximports/testdata/src/old.com/bad/bad.go b/cmd/fiximports/testdata/src/old.com/bad/bad.go
new file mode 100644
index 0000000..a1a3d1a
--- /dev/null
+++ b/cmd/fiximports/testdata/src/old.com/bad/bad.go
@@ -0,0 +1,2 @@
+// This ill-formed Go source file is here to ensure the tool is robust
+// against bad packages in the workspace.
diff --git a/cmd/fiximports/testdata/src/old.com/one/one.go b/cmd/fiximports/testdata/src/old.com/one/one.go
new file mode 100644
index 0000000..a8c5e83
--- /dev/null
+++ b/cmd/fiximports/testdata/src/old.com/one/one.go
@@ -0,0 +1 @@
+package one // import "new.com/one"
diff --git a/cmd/fiximports/testdata/src/titanic.biz/bar/bar.go b/cmd/fiximports/testdata/src/titanic.biz/bar/bar.go
new file mode 100644
index 0000000..cc720bc
--- /dev/null
+++ b/cmd/fiximports/testdata/src/titanic.biz/bar/bar.go
@@ -0,0 +1,2 @@
+// This package is moving to new.com too.
+package bar // import "new.com/bar"
diff --git a/cmd/fiximports/testdata/src/titanic.biz/foo/foo.go b/cmd/fiximports/testdata/src/titanic.biz/foo/foo.go
new file mode 100644
index 0000000..145c31b
--- /dev/null
+++ b/cmd/fiximports/testdata/src/titanic.biz/foo/foo.go
@@ -0,0 +1,2 @@
+// This package hasn't jumped ship yet.
+package foo
diff --git a/cmd/godex/doc.go b/cmd/godex/doc.go
new file mode 100644
index 0000000..ceb7c2f
--- /dev/null
+++ b/cmd/godex/doc.go
@@ -0,0 +1,69 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// The godex command prints (dumps) exported information of packages
+// or selected package objects.
+//
+// In contrast to godoc, godex extracts this information from compiled
+// object files. Hence the exported data is truly what a compiler will
+// see, at the cost of missing commentary.
+//
+// Usage: godex [flags] {path[.name]}
+//
+// Each argument must be a (possibly partial) package path, optionally
+// followed by a dot and the name of a package object:
+//
+//	godex math
+//	godex math.Sin
+//	godex math.Sin fmt.Printf
+//	godex go/types
+//
+// godex automatically tries all possible package path prefixes if only a
+// partial package path is given. For instance, for the path "go/types",
+// godex prepends "golang.org/x/tools".
+//
+// The prefixes are computed by searching the directories specified by
+// the GOROOT and GOPATH environment variables (and by excluding the
+// build OS- and architecture-specific directory names from the path).
+// The search order is depth-first and alphabetic; for a partial path
+// "foo", a package "a/foo" is found before "b/foo".
+//
+// Absolute and relative paths may be provided, which disable automatic
+// prefix generation:
+//
+//	godex $GOROOT/pkg/darwin_amd64/sort
+//	godex ./sort
+//
+// All but the last path element may contain dots; a dot in the last path
+// element separates the package path from the package object name. If the
+// last path element contains a dot, terminate the argument with another
+// dot (indicating an empty object name). For instance, the path for a
+// package foo.bar would be specified as in:
+//
+//	godex foo.bar.
+//
+// The flags are:
+//
+//	-s=""
+//		only consider packages from src, where src is one of the supported compilers
+//	-v=false
+//		verbose mode
+//
+// The following sources (-s arguments) are supported:
+//
+//	gc
+//		gc-generated object files
+//	gccgo
+//		gccgo-generated object files
+//	gccgo-new
+//		gccgo-generated object files using a condensed format (experimental)
+//	source
+//		(uncompiled) source code (not yet implemented)
+//
+// If no -s argument is provided, godex will try to find a matching source.
+//
+package main // import "golang.org/x/tools/cmd/godex"
+
+// BUG(gri): support for -s=source is not yet implemented
+// BUG(gri): gccgo-importing appears to have occasional problems stalling godex; try -s=gc as work-around
diff --git a/cmd/godex/gc.go b/cmd/godex/gc.go
new file mode 100644
index 0000000..85335b9
--- /dev/null
+++ b/cmd/godex/gc.go
@@ -0,0 +1,15 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file implements access to gc-generated export data.
+
+package main
+
+import (
+	"golang.org/x/tools/go/gcimporter"
+)
+
+func init() {
+	register("gc", gcimporter.Import)
+}
diff --git a/cmd/godex/gccgo.go b/cmd/godex/gccgo.go
new file mode 100644
index 0000000..aee2d8e
--- /dev/null
+++ b/cmd/godex/gccgo.go
@@ -0,0 +1,40 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file implements access to gccgo-generated export data.
+
+package main
+
+import (
+	"golang.org/x/tools/go/gccgoimporter"
+	"golang.org/x/tools/go/types"
+)
+
+var (
+	initmap = make(map[*types.Package]gccgoimporter.InitData)
+)
+
+func init() {
+	incpaths := []string{"/"}
+
+	// importer for default gccgo
+	var inst gccgoimporter.GccgoInstallation
+	inst.InitFromDriver("gccgo")
+	register("gccgo", inst.GetImporter(incpaths, initmap))
+}
+
+// Print the extra gccgo compiler data for this package, if it exists.
+func (p *printer) printGccgoExtra(pkg *types.Package) {
+	if initdata, ok := initmap[pkg]; ok {
+		p.printf("/*\npriority %d\n", initdata.Priority)
+
+		p.printDecl("init", len(initdata.Inits), func() {
+			for _, init := range initdata.Inits {
+				p.printf("%s %s %d\n", init.Name, init.InitFunc, init.Priority)
+			}
+		})
+
+		p.print("*/\n")
+	}
+}
diff --git a/cmd/godex/godex.go b/cmd/godex/godex.go
new file mode 100644
index 0000000..dee0990
--- /dev/null
+++ b/cmd/godex/godex.go
@@ -0,0 +1,207 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+	"errors"
+	"flag"
+	"fmt"
+	"go/build"
+	"io/ioutil"
+	"os"
+	"path/filepath"
+	"strings"
+
+	"golang.org/x/tools/go/types"
+)
+
+var (
+	source  = flag.String("s", "", "only consider packages from src, where src is one of the supported compilers")
+	verbose = flag.Bool("v", false, "verbose mode")
+)
+
+// lists of registered sources and corresponding importers
+var (
+	sources      []string
+	importers    []types.Importer
+	importFailed = errors.New("import failed")
+)
+
+// map of imported packages
+var packages = make(map[string]*types.Package)
+
+func usage() {
+	fmt.Fprintln(os.Stderr, "usage: godex [flags] {path|qualifiedIdent}")
+	flag.PrintDefaults()
+	os.Exit(2)
+}
+
+func report(msg string) {
+	fmt.Fprintln(os.Stderr, "error: "+msg)
+	os.Exit(2)
+}
+
+func main() {
+	flag.Usage = usage
+	flag.Parse()
+
+	if flag.NArg() == 0 {
+		report("no package name, path, or file provided")
+	}
+
+	imp := tryImports
+	if *source != "" {
+		imp = lookup(*source)
+		if imp == nil {
+			report("source (-s argument) must be one of: " + strings.Join(sources, ", "))
+		}
+	}
+
+	for _, arg := range flag.Args() {
+		path, name := splitPathIdent(arg)
+		logf("\tprocessing %q: path = %q, name = %s\n", arg, path, name)
+
+		// generate possible package path prefixes
+		// (at the moment we do this for each argument - should probably cache the generated prefixes)
+		prefixes := make(chan string)
+		go genPrefixes(prefixes, !filepath.IsAbs(path) && !build.IsLocalImport(path))
+
+		// import package
+		pkg, err := tryPrefixes(packages, prefixes, path, imp)
+		if err != nil {
+			logf("\t=> ignoring %q: %s\n", path, err)
+			continue
+		}
+
+		// filter objects if needed
+		var filter func(types.Object) bool
+		if name != "" {
+			filter = func(obj types.Object) bool {
+				// TODO(gri) perhaps use regular expression matching here?
+				return obj.Name() == name
+			}
+		}
+
+		// print contents
+		print(os.Stdout, pkg, filter)
+	}
+}
+
+func logf(format string, args ...interface{}) {
+	if *verbose {
+		fmt.Fprintf(os.Stderr, format, args...)
+	}
+}
+
+// splitPathIdent splits a path.name argument into its components.
+// All but the last path element may contain dots.
+func splitPathIdent(arg string) (path, name string) {
+	if i := strings.LastIndex(arg, "."); i >= 0 {
+		if j := strings.LastIndex(arg, "/"); j < i {
+			// '.' is not part of path
+			path = arg[:i]
+			name = arg[i+1:]
+			return
+		}
+	}
+	path = arg
+	return
+}
+
+// tryPrefixes tries to import the package given by (the possibly partial) path using the given importer imp
+// by prepending all possible prefixes to path. It returns with the first package that it could import, or
+// with an error.
+func tryPrefixes(packages map[string]*types.Package, prefixes chan string, path string, imp types.Importer) (pkg *types.Package, err error) {
+	for prefix := range prefixes {
+		actual := path
+		if prefix == "" {
+			// don't use filepath.Join as it will sanitize the path and remove
+			// a leading dot and then the path is not recognized as a relative
+			// package path by the importers anymore
+			logf("\ttrying no prefix\n")
+		} else {
+			actual = filepath.Join(prefix, path)
+			logf("\ttrying prefix %q\n", prefix)
+		}
+		pkg, err = imp(packages, actual)
+		if err == nil {
+			break
+		}
+		logf("\t=> importing %q failed: %s\n", actual, err)
+	}
+	return
+}
+
+// tryImports is an importer that tries all registered importers
+// successively until one of them succeeds or all of them failed.
+func tryImports(packages map[string]*types.Package, path string) (pkg *types.Package, err error) {
+	for i, imp := range importers {
+		logf("\t\ttrying %s import\n", sources[i])
+		pkg, err = imp(packages, path)
+		if err == nil {
+			break
+		}
+		logf("\t\t=> %s import failed: %s\n", sources[i], err)
+	}
+	return
+}
+
+// protect protects an importer imp from panics and returns the protected importer.
+func protect(imp types.Importer) types.Importer {
+	return func(packages map[string]*types.Package, path string) (pkg *types.Package, err error) {
+		defer func() {
+			if recover() != nil {
+				pkg = nil
+				err = importFailed
+			}
+		}()
+		return imp(packages, path)
+	}
+}
+
+// register registers an importer imp for a given source src.
+func register(src string, imp types.Importer) {
+	if lookup(src) != nil {
+		panic(src + " importer already registered")
+	}
+	sources = append(sources, src)
+	importers = append(importers, protect(imp))
+}
+
+// lookup returns the importer imp for a given source src.
+func lookup(src string) types.Importer {
+	for i, s := range sources {
+		if s == src {
+			return importers[i]
+		}
+	}
+	return nil
+}
+
+func genPrefixes(out chan string, all bool) {
+	out <- ""
+	if all {
+		platform := build.Default.GOOS + "_" + build.Default.GOARCH
+		dirnames := append([]string{build.Default.GOROOT}, filepath.SplitList(build.Default.GOPATH)...)
+		for _, dirname := range dirnames {
+			walkDir(filepath.Join(dirname, "pkg", platform), "", out)
+		}
+	}
+	close(out)
+}
+
+func walkDir(dirname, prefix string, out chan string) {
+	fiList, err := ioutil.ReadDir(dirname)
+	if err != nil {
+		return
+	}
+	for _, fi := range fiList {
+		if fi.IsDir() && !strings.HasPrefix(fi.Name(), ".") {
+			prefix := filepath.Join(prefix, fi.Name())
+			out <- prefix
+			walkDir(filepath.Join(dirname, fi.Name()), prefix, out)
+		}
+	}
+}
diff --git a/cmd/godex/print.go b/cmd/godex/print.go
new file mode 100644
index 0000000..e519f41
--- /dev/null
+++ b/cmd/godex/print.go
@@ -0,0 +1,368 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+	"bytes"
+	"fmt"
+	"go/token"
+	"io"
+	"math/big"
+
+	"golang.org/x/tools/go/exact"
+	"golang.org/x/tools/go/types"
+)
+
+// TODO(gri) use tabwriter for alignment?
+
+func print(w io.Writer, pkg *types.Package, filter func(types.Object) bool) {
+	var p printer
+	p.pkg = pkg
+	p.printPackage(pkg, filter)
+	p.printGccgoExtra(pkg)
+	io.Copy(w, &p.buf)
+}
+
+type printer struct {
+	pkg    *types.Package
+	buf    bytes.Buffer
+	indent int  // current indentation level
+	last   byte // last byte written
+}
+
+func (p *printer) print(s string) {
+	// Write the string one byte at a time. We care about the presence of
+	// newlines for indentation which we will see even in the presence of
+	// (non-corrupted) Unicode; no need to read one rune at a time.
+	for i := 0; i < len(s); i++ {
+		ch := s[i]
+		if ch != '\n' && p.last == '\n' {
+			// Note: This could lead to a range overflow for very large
+			// indentations, but it's extremely unlikely to happen for
+			// non-pathological code.
+			p.buf.WriteString("\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t"[:p.indent])
+		}
+		p.buf.WriteByte(ch)
+		p.last = ch
+	}
+}
+
+func (p *printer) printf(format string, args ...interface{}) {
+	p.print(fmt.Sprintf(format, args...))
+}
+
+// methodsFor returns the named type and corresponding methods if the type
+// denoted by obj is not an interface and has methods. Otherwise it returns
+// the zero value.
+func methodsFor(obj *types.TypeName) (*types.Named, []*types.Selection) {
+	named, _ := obj.Type().(*types.Named)
+	if named == nil {
+		// A type name's type can also be the
+		// exported basic type unsafe.Pointer.
+		return nil, nil
+	}
+	if _, ok := named.Underlying().(*types.Interface); ok {
+		// ignore interfaces
+		return nil, nil
+	}
+	methods := combinedMethodSet(named)
+	if len(methods) == 0 {
+		return nil, nil
+	}
+	return named, methods
+}
+
+func (p *printer) printPackage(pkg *types.Package, filter func(types.Object) bool) {
+	// collect objects by kind
+	var (
+		consts   []*types.Const
+		typem    []*types.Named    // non-interface types with methods
+		typez    []*types.TypeName // interfaces or types without methods
+		vars     []*types.Var
+		funcs    []*types.Func
+		builtins []*types.Builtin
+		methods  = make(map[*types.Named][]*types.Selection) // method sets for named types
+	)
+	scope := pkg.Scope()
+	for _, name := range scope.Names() {
+		obj := scope.Lookup(name)
+		if obj.Exported() {
+			// collect top-level exported and possibly filtered objects
+			if filter == nil || filter(obj) {
+				switch obj := obj.(type) {
+				case *types.Const:
+					consts = append(consts, obj)
+				case *types.TypeName:
+					// group into types with methods and types without
+					if named, m := methodsFor(obj); named != nil {
+						typem = append(typem, named)
+						methods[named] = m
+					} else {
+						typez = append(typez, obj)
+					}
+				case *types.Var:
+					vars = append(vars, obj)
+				case *types.Func:
+					funcs = append(funcs, obj)
+				case *types.Builtin:
+					// for unsafe.Sizeof, etc.
+					builtins = append(builtins, obj)
+				}
+			}
+		} else if filter == nil {
+			// no filtering: collect top-level unexported types with methods
+			if obj, _ := obj.(*types.TypeName); obj != nil {
+				// see case *types.TypeName above
+				if named, m := methodsFor(obj); named != nil {
+					typem = append(typem, named)
+					methods[named] = m
+				}
+			}
+		}
+	}
+
+	p.printf("package %s  // %q\n", pkg.Name(), pkg.Path())
+
+	p.printDecl("const", len(consts), func() {
+		for _, obj := range consts {
+			p.printObj(obj)
+			p.print("\n")
+		}
+	})
+
+	p.printDecl("var", len(vars), func() {
+		for _, obj := range vars {
+			p.printObj(obj)
+			p.print("\n")
+		}
+	})
+
+	p.printDecl("type", len(typez), func() {
+		for _, obj := range typez {
+			p.printf("%s ", obj.Name())
+			p.writeType(p.pkg, obj.Type().Underlying())
+			p.print("\n")
+		}
+	})
+
+	// non-interface types with methods
+	for _, named := range typem {
+		first := true
+		if obj := named.Obj(); obj.Exported() {
+			if first {
+				p.print("\n")
+				first = false
+			}
+			p.printf("type %s ", obj.Name())
+			p.writeType(p.pkg, named.Underlying())
+			p.print("\n")
+		}
+		for _, m := range methods[named] {
+			if obj := m.Obj(); obj.Exported() {
+				if first {
+					p.print("\n")
+					first = false
+				}
+				p.printFunc(m.Recv(), obj.(*types.Func))
+				p.print("\n")
+			}
+		}
+	}
+
+	if len(funcs) > 0 {
+		p.print("\n")
+		for _, obj := range funcs {
+			p.printFunc(nil, obj)
+			p.print("\n")
+		}
+	}
+
+	// TODO(gri) better handling of builtins (package unsafe only)
+	if len(builtins) > 0 {
+		p.print("\n")
+		for _, obj := range builtins {
+			p.printf("func %s() // builtin\n", obj.Name())
+		}
+	}
+
+	p.print("\n")
+}
+
+func (p *printer) printDecl(keyword string, n int, printGroup func()) {
+	switch n {
+	case 0:
+		// nothing to do
+	case 1:
+		p.printf("\n%s ", keyword)
+		printGroup()
+	default:
+		p.printf("\n%s (\n", keyword)
+		p.indent++
+		printGroup()
+		p.indent--
+		p.print(")\n")
+	}
+}
+
+// absInt returns the absolute value of v as a *big.Int.
+// v must be a numeric value.
+func absInt(v exact.Value) *big.Int {
+	// compute big-endian representation of v
+	b := exact.Bytes(v) // little-endian
+	for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
+		b[i], b[j] = b[j], b[i]
+	}
+	return new(big.Int).SetBytes(b)
+}
+
+var (
+	one = big.NewRat(1, 1)
+	ten = big.NewRat(10, 1)
+)
+
+// floatString returns the string representation for a
+// numeric value v in normalized floating-point format.
+func floatString(v exact.Value) string {
+	if exact.Sign(v) == 0 {
+		return "0.0"
+	}
+	// x != 0
+
+	// convert |v| into a big.Rat x
+	x := new(big.Rat).SetFrac(absInt(exact.Num(v)), absInt(exact.Denom(v)))
+
+	// normalize x and determine exponent e
+	// (This is not very efficient, but also not speed-critical.)
+	var e int
+	for x.Cmp(ten) >= 0 {
+		x.Quo(x, ten)
+		e++
+	}
+	for x.Cmp(one) < 0 {
+		x.Mul(x, ten)
+		e--
+	}
+
+	// TODO(gri) Values such as 1/2 are easier to read in form 0.5
+	// rather than 5.0e-1. Similarly, 1.0e1 is easier to read as
+	// 10.0. Fine-tune best exponent range for readability.
+
+	s := x.FloatString(100) // good-enough precision
+
+	// trim trailing 0's
+	i := len(s)
+	for i > 0 && s[i-1] == '0' {
+		i--
+	}
+	s = s[:i]
+
+	// add a 0 if the number ends in decimal point
+	if len(s) > 0 && s[len(s)-1] == '.' {
+		s += "0"
+	}
+
+	// add exponent and sign
+	if e != 0 {
+		s += fmt.Sprintf("e%+d", e)
+	}
+	if exact.Sign(v) < 0 {
+		s = "-" + s
+	}
+
+	// TODO(gri) If v is a "small" fraction (i.e., numerator and denominator
+	// are just a small number of decimal digits), add the exact fraction as
+	// a comment. For instance: 3.3333...e-1 /* = 1/3 */
+
+	return s
+}
+
+// valString returns the string representation for the value v.
+// Setting floatFmt forces an integer value to be formatted in
+// normalized floating-point format.
+// TODO(gri) Move this code into package exact.
+func valString(v exact.Value, floatFmt bool) string {
+	switch v.Kind() {
+	case exact.Int:
+		if floatFmt {
+			return floatString(v)
+		}
+	case exact.Float:
+		return floatString(v)
+	case exact.Complex:
+		re := exact.Real(v)
+		im := exact.Imag(v)
+		var s string
+		if exact.Sign(re) != 0 {
+			s = floatString(re)
+			if exact.Sign(im) >= 0 {
+				s += " + "
+			} else {
+				s += " - "
+				im = exact.UnaryOp(token.SUB, im, 0) // negate im
+			}
+		}
+		// im != 0, otherwise v would be exact.Int or exact.Float
+		return s + floatString(im) + "i"
+	}
+	return v.String()
+}
+
+func (p *printer) printObj(obj types.Object) {
+	p.print(obj.Name())
+
+	typ, basic := obj.Type().Underlying().(*types.Basic)
+	if basic && typ.Info()&types.IsUntyped != 0 {
+		// don't write untyped types
+	} else {
+		p.print(" ")
+		p.writeType(p.pkg, obj.Type())
+	}
+
+	if obj, ok := obj.(*types.Const); ok {
+		floatFmt := basic && typ.Info()&(types.IsFloat|types.IsComplex) != 0
+		p.print(" = ")
+		p.print(valString(obj.Val(), floatFmt))
+	}
+}
+
+func (p *printer) printFunc(recvType types.Type, obj *types.Func) {
+	p.print("func ")
+	sig := obj.Type().(*types.Signature)
+	if recvType != nil {
+		p.print("(")
+		p.writeType(p.pkg, recvType)
+		p.print(") ")
+	}
+	p.print(obj.Name())
+	p.writeSignature(p.pkg, sig)
+}
+
+// combinedMethodSet returns the method set for a named type T
+// merged with all the methods of *T that have different names than
+// the methods of T.
+//
+// combinedMethodSet is analogous to types/typeutil.IntuitiveMethodSet
+// but doesn't require a MethodSetCache.
+// TODO(gri) If this functionality doesn't change over time, consider
+// just calling IntuitiveMethodSet eventually.
+func combinedMethodSet(T *types.Named) []*types.Selection {
+	// method set for T
+	mset := types.NewMethodSet(T)
+	var res []*types.Selection
+	for i, n := 0, mset.Len(); i < n; i++ {
+		res = append(res, mset.At(i))
+	}
+
+	// add all *T methods with names different from T methods
+	pmset := types.NewMethodSet(types.NewPointer(T))
+	for i, n := 0, pmset.Len(); i < n; i++ {
+		pm := pmset.At(i)
+		if obj := pm.Obj(); mset.Lookup(obj.Pkg(), obj.Name()) == nil {
+			res = append(res, pm)
+		}
+	}
+
+	return res
+}
diff --git a/cmd/godex/source.go b/cmd/godex/source.go
new file mode 100644
index 0000000..22d7813
--- /dev/null
+++ b/cmd/godex/source.go
@@ -0,0 +1,19 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file implements access to export data from source.
+
+package main
+
+import (
+	"golang.org/x/tools/go/types"
+)
+
+func init() {
+	register("source", sourceImporter)
+}
+
+func sourceImporter(packages map[string]*types.Package, path string) (*types.Package, error) {
+	panic("unimplemented")
+}
diff --git a/cmd/godex/writetype.go b/cmd/godex/writetype.go
new file mode 100644
index 0000000..10c8e65
--- /dev/null
+++ b/cmd/godex/writetype.go
@@ -0,0 +1,242 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file implements writing of types. The functionality is lifted
+// directly from go/types, but now contains various modifications for
+// nicer output.
+//
+// TODO(gri) back-port once we have a fixed interface and once the
+// go/types API is not frozen anymore for the 1.3 release; and remove
+// this implementation if possible.
+
+package main
+
+import "golang.org/x/tools/go/types"
+
+func (p *printer) writeType(this *types.Package, typ types.Type) {
+	p.writeTypeInternal(this, typ, make([]types.Type, 8))
+}
+
+// From go/types - leave for now to ease back-porting this code.
+const GcCompatibilityMode = false
+
+func (p *printer) writeTypeInternal(this *types.Package, typ types.Type, visited []types.Type) {
+	// Theoretically, this is a quadratic lookup algorithm, but in
+	// practice deeply nested composite types with unnamed component
+	// types are uncommon. This code is likely more efficient than
+	// using a map.
+	for _, t := range visited {
+		if t == typ {
+			p.printf("○%T", typ) // cycle to typ
+			return
+		}
+	}
+	visited = append(visited, typ)
+
+	switch t := typ.(type) {
+	case nil:
+		p.print("<nil>")
+
+	case *types.Basic:
+		if t.Kind() == types.UnsafePointer {
+			p.print("unsafe.")
+		}
+		if GcCompatibilityMode {
+			// forget the alias names
+			switch t.Kind() {
+			case types.Byte:
+				t = types.Typ[types.Uint8]
+			case types.Rune:
+				t = types.Typ[types.Int32]
+			}
+		}
+		p.print(t.Name())
+
+	case *types.Array:
+		p.printf("[%d]", t.Len())
+		p.writeTypeInternal(this, t.Elem(), visited)
+
+	case *types.Slice:
+		p.print("[]")
+		p.writeTypeInternal(this, t.Elem(), visited)
+
+	case *types.Struct:
+		n := t.NumFields()
+		if n == 0 {
+			p.print("struct{}")
+			return
+		}
+
+		p.print("struct {\n")
+		p.indent++
+		for i := 0; i < n; i++ {
+			f := t.Field(i)
+			if !f.Anonymous() {
+				p.printf("%s ", f.Name())
+			}
+			p.writeTypeInternal(this, f.Type(), visited)
+			if tag := t.Tag(i); tag != "" {
+				p.printf(" %q", tag)
+			}
+			p.print("\n")
+		}
+		p.indent--
+		p.print("}")
+
+	case *types.Pointer:
+		p.print("*")
+		p.writeTypeInternal(this, t.Elem(), visited)
+
+	case *types.Tuple:
+		p.writeTuple(this, t, false, visited)
+
+	case *types.Signature:
+		p.print("func")
+		p.writeSignatureInternal(this, t, visited)
+
+	case *types.Interface:
+		// We write the source-level methods and embedded types rather
+		// than the actual method set since resolved method signatures
+		// may have non-printable cycles if parameters have anonymous
+		// interface types that (directly or indirectly) embed the
+		// current interface. For instance, consider the result type
+		// of m:
+		//
+		//     type T interface{
+		//         m() interface{ T }
+		//     }
+		//
+		n := t.NumMethods()
+		if n == 0 {
+			p.print("interface{}")
+			return
+		}
+
+		p.print("interface {\n")
+		p.indent++
+		if GcCompatibilityMode {
+			// print flattened interface
+			// (useful to compare against gc-generated interfaces)
+			for i := 0; i < n; i++ {
+				m := t.Method(i)
+				p.print(m.Name())
+				p.writeSignatureInternal(this, m.Type().(*types.Signature), visited)
+				p.print("\n")
+			}
+		} else {
+			// print explicit interface methods and embedded types
+			for i, n := 0, t.NumExplicitMethods(); i < n; i++ {
+				m := t.ExplicitMethod(i)
+				p.print(m.Name())
+				p.writeSignatureInternal(this, m.Type().(*types.Signature), visited)
+				p.print("\n")
+			}
+			for i, n := 0, t.NumEmbeddeds(); i < n; i++ {
+				typ := t.Embedded(i)
+				p.writeTypeInternal(this, typ, visited)
+				p.print("\n")
+			}
+		}
+		p.indent--
+		p.print("}")
+
+	case *types.Map:
+		p.print("map[")
+		p.writeTypeInternal(this, t.Key(), visited)
+		p.print("]")
+		p.writeTypeInternal(this, t.Elem(), visited)
+
+	case *types.Chan:
+		var s string
+		var parens bool
+		switch t.Dir() {
+		case types.SendRecv:
+			s = "chan "
+			// chan (<-chan T) requires parentheses
+			if c, _ := t.Elem().(*types.Chan); c != nil && c.Dir() == types.RecvOnly {
+				parens = true
+			}
+		case types.SendOnly:
+			s = "chan<- "
+		case types.RecvOnly:
+			s = "<-chan "
+		default:
+			panic("unreachable")
+		}
+		p.print(s)
+		if parens {
+			p.print("(")
+		}
+		p.writeTypeInternal(this, t.Elem(), visited)
+		if parens {
+			p.print(")")
+		}
+
+	case *types.Named:
+		s := "<Named w/o object>"
+		if obj := t.Obj(); obj != nil {
+			if pkg := obj.Pkg(); pkg != nil {
+				if pkg != this {
+					p.print(pkg.Path())
+					p.print(".")
+				}
+				// TODO(gri): function-local named types should be displayed
+				// differently from named types at package level to avoid
+				// ambiguity.
+			}
+			s = obj.Name()
+		}
+		p.print(s)
+
+	default:
+		// For externally defined implementations of Type.
+		p.print(t.String())
+	}
+}
+
+func (p *printer) writeTuple(this *types.Package, tup *types.Tuple, variadic bool, visited []types.Type) {
+	p.print("(")
+	for i, n := 0, tup.Len(); i < n; i++ {
+		if i > 0 {
+			p.print(", ")
+		}
+		v := tup.At(i)
+		if name := v.Name(); name != "" {
+			p.print(name)
+			p.print(" ")
+		}
+		typ := v.Type()
+		if variadic && i == n-1 {
+			p.print("...")
+			typ = typ.(*types.Slice).Elem()
+		}
+		p.writeTypeInternal(this, typ, visited)
+	}
+	p.print(")")
+}
+
+func (p *printer) writeSignature(this *types.Package, sig *types.Signature) {
+	p.writeSignatureInternal(this, sig, make([]types.Type, 8))
+}
+
+func (p *printer) writeSignatureInternal(this *types.Package, sig *types.Signature, visited []types.Type) {
+	p.writeTuple(this, sig.Params(), sig.Variadic(), visited)
+
+	res := sig.Results()
+	n := res.Len()
+	if n == 0 {
+		// no result
+		return
+	}
+
+	p.print(" ")
+	if n == 1 && res.At(0).Name() == "" {
+		// single unnamed result
+		p.writeTypeInternal(this, res.At(0).Type(), visited)
+		return
+	}
+
+	// multiple or named result(s)
+	p.writeTuple(this, res, false, visited)
+}
diff --git a/cmd/godoc/README.godoc-app b/cmd/godoc/README.godoc-app
new file mode 100644
index 0000000..50a0516
--- /dev/null
+++ b/cmd/godoc/README.godoc-app
@@ -0,0 +1,56 @@
+godoc on appengine
+------------------
+
+Prerequisites
+-------------
+
+* Go appengine SDK
+  https://developers.google.com/appengine/downloads#Google_App_Engine_SDK_for_Go
+
+* Go sources at tip under $GOROOT
+
+* Godoc sources at tip inside $GOPATH
+  (go get -d golang.org/x/tools/cmd/godoc)
+
+
+Directory structure
+-------------------
+
+* Let $APPDIR be the directory containing the app engine files.
+  (e.g., $APPDIR=$HOME/godoc-app)
+
+* $APPDIR contains the following entries (this may change depending on
+  app-engine release and version of godoc):
+
+	app.yaml
+	golang.org/x/tools/cmd/godoc
+	godoc.zip
+	index.split.*
+
+* The app.yaml file is set up per app engine documentation.
+  For instance:
+
+	application: godoc-app
+	version: 1
+	runtime: go
+	api_version: go1
+
+	handlers:
+	- url: /.*
+	  script: _go_app
+
+
+Configuring and running godoc
+-----------------------------
+
+To configure godoc, run
+
+	bash setup-godoc-app.bash
+
+to prepare an $APPDIR as described above. See the script for details on usage.
+
+To run godoc locally, using the App Engine development server, run
+
+	<path to go_appengine>/dev_appserver.py $APPDIR
+
+godoc should come up at http://localhost:8080 .
diff --git a/cmd/godoc/appinit.go b/cmd/godoc/appinit.go
new file mode 100644
index 0000000..3d6a921
--- /dev/null
+++ b/cmd/godoc/appinit.go
@@ -0,0 +1,67 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build appengine
+
+package main
+
+// This file replaces main.go when running godoc under app-engine.
+// See README.godoc-app for details.
+
+import (
+	"archive/zip"
+	"log"
+	"path"
+	"regexp"
+
+	"golang.org/x/tools/godoc"
+	"golang.org/x/tools/godoc/static"
+	"golang.org/x/tools/godoc/vfs"
+	"golang.org/x/tools/godoc/vfs/mapfs"
+	"golang.org/x/tools/godoc/vfs/zipfs"
+)
+
+func init() {
+	playEnabled = true
+
+	log.Println("initializing godoc ...")
+	log.Printf(".zip file   = %s", zipFilename)
+	log.Printf(".zip GOROOT = %s", zipGoroot)
+	log.Printf("index files = %s", indexFilenames)
+
+	goroot := path.Join("/", zipGoroot) // fsHttp paths are relative to '/'
+
+	// read .zip file and set up file systems
+	const zipfile = zipFilename
+	rc, err := zip.OpenReader(zipfile)
+	if err != nil {
+		log.Fatalf("%s: %s\n", zipfile, err)
+	}
+	// rc is never closed (app running forever)
+	fs.Bind("/", zipfs.New(rc, zipFilename), goroot, vfs.BindReplace)
+	fs.Bind("/lib/godoc", mapfs.New(static.Files), "/", vfs.BindReplace)
+
+	corpus := godoc.NewCorpus(fs)
+	corpus.Verbose = false
+	corpus.MaxResults = 10000 // matches flag default in main.go
+	corpus.IndexEnabled = true
+	corpus.IndexFiles = indexFilenames
+	if err := corpus.Init(); err != nil {
+		log.Fatal(err)
+	}
+	corpus.IndexDirectory = indexDirectoryDefault
+	go corpus.RunIndexer()
+
+	pres = godoc.NewPresentation(corpus)
+	pres.TabWidth = 8
+	pres.ShowPlayground = true
+	pres.ShowExamples = true
+	pres.DeclLinks = true
+	pres.NotesRx = regexp.MustCompile("BUG")
+
+	readTemplates(pres, true)
+	registerHandlers(pres)
+
+	log.Println("godoc initialization complete")
+}
diff --git a/cmd/godoc/blog.go b/cmd/godoc/blog.go
new file mode 100644
index 0000000..dec4732
--- /dev/null
+++ b/cmd/godoc/blog.go
@@ -0,0 +1,81 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+	"fmt"
+	"go/build"
+	"log"
+	"net/http"
+	"os"
+	"path/filepath"
+	"runtime"
+	"strings"
+	"sync"
+
+	"golang.org/x/tools/blog"
+	"golang.org/x/tools/godoc/redirect"
+)
+
+const (
+	blogRepo = "golang.org/x/blog"
+	blogURL  = "http://blog.golang.org/"
+	blogPath = "/blog/"
+)
+
+var (
+	blogServer   http.Handler // set by blogInit
+	blogInitOnce sync.Once
+	playEnabled  bool
+)
+
+func init() {
+	// Initialize blog only when first accessed.
+	http.HandleFunc(blogPath, func(w http.ResponseWriter, r *http.Request) {
+		blogInitOnce.Do(blogInit)
+		blogServer.ServeHTTP(w, r)
+	})
+}
+
+func blogInit() {
+	// Binary distributions will include the blog content in "/blog".
+	root := filepath.Join(runtime.GOROOT(), "blog")
+
+	// Prefer content from go.blog repository if present.
+	if pkg, err := build.Import(blogRepo, "", build.FindOnly); err == nil {
+		root = pkg.Dir
+	}
+
+	// If content is not available fall back to redirect.
+	if fi, err := os.Stat(root); err != nil || !fi.IsDir() {
+		fmt.Fprintf(os.Stderr, "Blog content not available locally. "+
+			"To install, run \n\tgo get %v\n", blogRepo)
+		blogServer = http.HandlerFunc(blogRedirectHandler)
+		return
+	}
+
+	s, err := blog.NewServer(blog.Config{
+		BaseURL:      blogPath,
+		BasePath:     strings.TrimSuffix(blogPath, "/"),
+		ContentPath:  filepath.Join(root, "content"),
+		TemplatePath: filepath.Join(root, "template"),
+		HomeArticles: 5,
+		PlayEnabled:  playEnabled,
+	})
+	if err != nil {
+		log.Fatal(err)
+	}
+	blogServer = s
+}
+
+func blogRedirectHandler(w http.ResponseWriter, r *http.Request) {
+	if r.URL.Path == blogPath {
+		http.Redirect(w, r, blogURL, http.StatusFound)
+		return
+	}
+	blogPrefixHandler.ServeHTTP(w, r)
+}
+
+var blogPrefixHandler = redirect.PrefixHandler(blogPath, blogURL)
diff --git a/cmd/godoc/codewalk.go b/cmd/godoc/codewalk.go
new file mode 100644
index 0000000..e3bf5cd
--- /dev/null
+++ b/cmd/godoc/codewalk.go
@@ -0,0 +1,523 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// The /doc/codewalk/ tree is synthesized from codewalk descriptions,
+// files named $GOROOT/doc/codewalk/*.xml.
+// For an example and a description of the format, see
+// http://golang.org/doc/codewalk/codewalk or run godoc -http=:6060
+// and see http://localhost:6060/doc/codewalk/codewalk .
+// That page is itself a codewalk; the source code for it is
+// $GOROOT/doc/codewalk/codewalk.xml.
+
+package main
+
+import (
+	"bytes"
+	"encoding/xml"
+	"errors"
+	"fmt"
+	"io"
+	"log"
+	"net/http"
+	"os"
+	pathpkg "path"
+	"regexp"
+	"sort"
+	"strconv"
+	"strings"
+	"text/template"
+	"unicode/utf8"
+
+	"golang.org/x/tools/godoc"
+	"golang.org/x/tools/godoc/vfs"
+)
+
+var codewalkHTML, codewalkdirHTML *template.Template
+
+// Handler for /doc/codewalk/ and below.
+func codewalk(w http.ResponseWriter, r *http.Request) {
+	relpath := r.URL.Path[len("/doc/codewalk/"):]
+	abspath := r.URL.Path
+
+	r.ParseForm()
+	if f := r.FormValue("fileprint"); f != "" {
+		codewalkFileprint(w, r, f)
+		return
+	}
+
+	// If directory exists, serve list of code walks.
+	dir, err := fs.Lstat(abspath)
+	if err == nil && dir.IsDir() {
+		codewalkDir(w, r, relpath, abspath)
+		return
+	}
+
+	// If file exists, serve using standard file server.
+	if err == nil {
+		pres.ServeFile(w, r)
+		return
+	}
+
+	// Otherwise append .xml and hope to find
+	// a codewalk description, but before trim
+	// the trailing /.
+	abspath = strings.TrimRight(abspath, "/")
+	cw, err := loadCodewalk(abspath + ".xml")
+	if err != nil {
+		log.Print(err)
+		pres.ServeError(w, r, relpath, err)
+		return
+	}
+
+	// Canonicalize the path and redirect if changed
+	if redir(w, r) {
+		return
+	}
+
+	pres.ServePage(w, godoc.Page{
+		Title:    "Codewalk: " + cw.Title,
+		Tabtitle: cw.Title,
+		Body:     applyTemplate(codewalkHTML, "codewalk", cw),
+	})
+}
+
+func redir(w http.ResponseWriter, r *http.Request) (redirected bool) {
+	canonical := pathpkg.Clean(r.URL.Path)
+	if !strings.HasSuffix(canonical, "/") {
+		canonical += "/"
+	}
+	if r.URL.Path != canonical {
+		url := *r.URL
+		url.Path = canonical
+		http.Redirect(w, r, url.String(), http.StatusMovedPermanently)
+		redirected = true
+	}
+	return
+}
+
+func applyTemplate(t *template.Template, name string, data interface{}) []byte {
+	var buf bytes.Buffer
+	if err := t.Execute(&buf, data); err != nil {
+		log.Printf("%s.Execute: %s", name, err)
+	}
+	return buf.Bytes()
+}
+
+// A Codewalk represents a single codewalk read from an XML file.
+type Codewalk struct {
+	Title string      `xml:"title,attr"`
+	File  []string    `xml:"file"`
+	Step  []*Codestep `xml:"step"`
+}
+
+// A Codestep is a single step in a codewalk.
+type Codestep struct {
+	// Filled in from XML
+	Src   string `xml:"src,attr"`
+	Title string `xml:"title,attr"`
+	XML   string `xml:",innerxml"`
+
+	// Derived from Src; not in XML.
+	Err    error
+	File   string
+	Lo     int
+	LoByte int
+	Hi     int
+	HiByte int
+	Data   []byte
+}
+
+// String method for printing in template.
+// Formats file address nicely.
+func (st *Codestep) String() string {
+	s := st.File
+	if st.Lo != 0 || st.Hi != 0 {
+		s += fmt.Sprintf(":%d", st.Lo)
+		if st.Lo != st.Hi {
+			s += fmt.Sprintf(",%d", st.Hi)
+		}
+	}
+	return s
+}
+
+// loadCodewalk reads a codewalk from the named XML file.
+func loadCodewalk(filename string) (*Codewalk, error) {
+	f, err := fs.Open(filename)
+	if err != nil {
+		return nil, err
+	}
+	defer f.Close()
+	cw := new(Codewalk)
+	d := xml.NewDecoder(f)
+	d.Entity = xml.HTMLEntity
+	err = d.Decode(cw)
+	if err != nil {
+		return nil, &os.PathError{Op: "parsing", Path: filename, Err: err}
+	}
+
+	// Compute file list, evaluate line numbers for addresses.
+	m := make(map[string]bool)
+	for _, st := range cw.Step {
+		i := strings.Index(st.Src, ":")
+		if i < 0 {
+			i = len(st.Src)
+		}
+		filename := st.Src[0:i]
+		data, err := vfs.ReadFile(fs, filename)
+		if err != nil {
+			st.Err = err
+			continue
+		}
+		if i < len(st.Src) {
+			lo, hi, err := addrToByteRange(st.Src[i+1:], 0, data)
+			if err != nil {
+				st.Err = err
+				continue
+			}
+			// Expand match to line boundaries.
+			for lo > 0 && data[lo-1] != '\n' {
+				lo--
+			}
+			for hi < len(data) && (hi == 0 || data[hi-1] != '\n') {
+				hi++
+			}
+			st.Lo = byteToLine(data, lo)
+			st.Hi = byteToLine(data, hi-1)
+		}
+		st.Data = data
+		st.File = filename
+		m[filename] = true
+	}
+
+	// Make list of files
+	cw.File = make([]string, len(m))
+	i := 0
+	for f := range m {
+		cw.File[i] = f
+		i++
+	}
+	sort.Strings(cw.File)
+
+	return cw, nil
+}
+
+// codewalkDir serves the codewalk directory listing.
+// It scans the directory for subdirectories or files named *.xml
+// and prepares a table.
+func codewalkDir(w http.ResponseWriter, r *http.Request, relpath, abspath string) {
+	type elem struct {
+		Name  string
+		Title string
+	}
+
+	dir, err := fs.ReadDir(abspath)
+	if err != nil {
+		log.Print(err)
+		pres.ServeError(w, r, relpath, err)
+		return
+	}
+	var v []interface{}
+	for _, fi := range dir {
+		name := fi.Name()
+		if fi.IsDir() {
+			v = append(v, &elem{name + "/", ""})
+		} else if strings.HasSuffix(name, ".xml") {
+			cw, err := loadCodewalk(abspath + "/" + name)
+			if err != nil {
+				continue
+			}
+			v = append(v, &elem{name[0 : len(name)-len(".xml")], cw.Title})
+		}
+	}
+
+	pres.ServePage(w, godoc.Page{
+		Title: "Codewalks",
+		Body:  applyTemplate(codewalkdirHTML, "codewalkdir", v),
+	})
+}
+
+// codewalkFileprint serves requests with ?fileprint=f&lo=lo&hi=hi.
+// The filename f has already been retrieved and is passed as an argument.
+// Lo and hi are the numbers of the first and last line to highlight
+// in the response.  This format is used for the middle window pane
+// of the codewalk pages.  It is a separate iframe and does not get
+// the usual godoc HTML wrapper.
+func codewalkFileprint(w http.ResponseWriter, r *http.Request, f string) {
+	abspath := f
+	data, err := vfs.ReadFile(fs, abspath)
+	if err != nil {
+		log.Print(err)
+		pres.ServeError(w, r, f, err)
+		return
+	}
+	lo, _ := strconv.Atoi(r.FormValue("lo"))
+	hi, _ := strconv.Atoi(r.FormValue("hi"))
+	if hi < lo {
+		hi = lo
+	}
+	lo = lineToByte(data, lo)
+	hi = lineToByte(data, hi+1)
+
+	// Put the mark 4 lines before lo, so that the iframe
+	// shows a few lines of context before the highlighted
+	// section.
+	n := 4
+	mark := lo
+	for ; mark > 0 && n > 0; mark-- {
+		if data[mark-1] == '\n' {
+			if n--; n == 0 {
+				break
+			}
+		}
+	}
+
+	io.WriteString(w, `<style type="text/css">@import "/doc/codewalk/codewalk.css";</style><pre>`)
+	template.HTMLEscape(w, data[0:mark])
+	io.WriteString(w, "<a name='mark'></a>")
+	template.HTMLEscape(w, data[mark:lo])
+	if lo < hi {
+		io.WriteString(w, "<div class='codewalkhighlight'>")
+		template.HTMLEscape(w, data[lo:hi])
+		io.WriteString(w, "</div>")
+	}
+	template.HTMLEscape(w, data[hi:])
+	io.WriteString(w, "</pre>")
+}
+
+// addrToByte evaluates the given address starting at offset start in data.
+// It returns the lo and hi byte offset of the matched region within data.
+// See http://plan9.bell-labs.com/sys/doc/sam/sam.html Table II
+// for details on the syntax.
+func addrToByteRange(addr string, start int, data []byte) (lo, hi int, err error) {
+	var (
+		dir        byte
+		prevc      byte
+		charOffset bool
+	)
+	lo = start
+	hi = start
+	for addr != "" && err == nil {
+		c := addr[0]
+		switch c {
+		default:
+			err = errors.New("invalid address syntax near " + string(c))
+		case ',':
+			if len(addr) == 1 {
+				hi = len(data)
+			} else {
+				_, hi, err = addrToByteRange(addr[1:], hi, data)
+			}
+			return
+
+		case '+', '-':
+			if prevc == '+' || prevc == '-' {
+				lo, hi, err = addrNumber(data, lo, hi, prevc, 1, charOffset)
+			}
+			dir = c
+
+		case '$':
+			lo = len(data)
+			hi = len(data)
+			if len(addr) > 1 {
+				dir = '+'
+			}
+
+		case '#':
+			charOffset = true
+
+		case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
+			var i int
+			for i = 1; i < len(addr); i++ {
+				if addr[i] < '0' || addr[i] > '9' {
+					break
+				}
+			}
+			var n int
+			n, err = strconv.Atoi(addr[0:i])
+			if err != nil {
+				break
+			}
+			lo, hi, err = addrNumber(data, lo, hi, dir, n, charOffset)
+			dir = 0
+			charOffset = false
+			prevc = c
+			addr = addr[i:]
+			continue
+
+		case '/':
+			var i, j int
+		Regexp:
+			for i = 1; i < len(addr); i++ {
+				switch addr[i] {
+				case '\\':
+					i++
+				case '/':
+					j = i + 1
+					break Regexp
+				}
+			}
+			if j == 0 {
+				j = i
+			}
+			pattern := addr[1:i]
+			lo, hi, err = addrRegexp(data, lo, hi, dir, pattern)
+			prevc = c
+			addr = addr[j:]
+			continue
+		}
+		prevc = c
+		addr = addr[1:]
+	}
+
+	if err == nil && dir != 0 {
+		lo, hi, err = addrNumber(data, lo, hi, dir, 1, charOffset)
+	}
+	if err != nil {
+		return 0, 0, err
+	}
+	return lo, hi, nil
+}
+
+// addrNumber applies the given dir, n, and charOffset to the address lo, hi.
+// dir is '+' or '-', n is the count, and charOffset is true if the syntax
+// used was #n.  Applying +n (or +#n) means to advance n lines
+// (or characters) after hi.  Applying -n (or -#n) means to back up n lines
+// (or characters) before lo.
+// The return value is the new lo, hi.
+func addrNumber(data []byte, lo, hi int, dir byte, n int, charOffset bool) (int, int, error) {
+	switch dir {
+	case 0:
+		lo = 0
+		hi = 0
+		fallthrough
+
+	case '+':
+		if charOffset {
+			pos := hi
+			for ; n > 0 && pos < len(data); n-- {
+				_, size := utf8.DecodeRune(data[pos:])
+				pos += size
+			}
+			if n == 0 {
+				return pos, pos, nil
+			}
+			break
+		}
+		// find next beginning of line
+		if hi > 0 {
+			for hi < len(data) && data[hi-1] != '\n' {
+				hi++
+			}
+		}
+		lo = hi
+		if n == 0 {
+			return lo, hi, nil
+		}
+		for ; hi < len(data); hi++ {
+			if data[hi] != '\n' {
+				continue
+			}
+			switch n--; n {
+			case 1:
+				lo = hi + 1
+			case 0:
+				return lo, hi + 1, nil
+			}
+		}
+
+	case '-':
+		if charOffset {
+			// Scan backward for bytes that are not UTF-8 continuation bytes.
+			pos := lo
+			for ; pos > 0 && n > 0; pos-- {
+				if data[pos]&0xc0 != 0x80 {
+					n--
+				}
+			}
+			if n == 0 {
+				return pos, pos, nil
+			}
+			break
+		}
+		// find earlier beginning of line
+		for lo > 0 && data[lo-1] != '\n' {
+			lo--
+		}
+		hi = lo
+		if n == 0 {
+			return lo, hi, nil
+		}
+		for ; lo >= 0; lo-- {
+			if lo > 0 && data[lo-1] != '\n' {
+				continue
+			}
+			switch n--; n {
+			case 1:
+				hi = lo
+			case 0:
+				return lo, hi, nil
+			}
+		}
+	}
+
+	return 0, 0, errors.New("address out of range")
+}
+
+// addrRegexp searches for pattern in the given direction starting at lo, hi.
+// The direction dir is '+' (search forward from hi) or '-' (search backward from lo).
+// Backward searches are unimplemented.
+func addrRegexp(data []byte, lo, hi int, dir byte, pattern string) (int, int, error) {
+	re, err := regexp.Compile(pattern)
+	if err != nil {
+		return 0, 0, err
+	}
+	if dir == '-' {
+		// Could implement reverse search using binary search
+		// through file, but that seems like overkill.
+		return 0, 0, errors.New("reverse search not implemented")
+	}
+	m := re.FindIndex(data[hi:])
+	if len(m) > 0 {
+		m[0] += hi
+		m[1] += hi
+	} else if hi > 0 {
+		// No match.  Wrap to beginning of data.
+		m = re.FindIndex(data)
+	}
+	if len(m) == 0 {
+		return 0, 0, errors.New("no match for " + pattern)
+	}
+	return m[0], m[1], nil
+}
+
+// lineToByte returns the byte index of the first byte of line n.
+// Line numbers begin at 1.
+func lineToByte(data []byte, n int) int {
+	if n <= 1 {
+		return 0
+	}
+	n--
+	for i, c := range data {
+		if c == '\n' {
+			if n--; n == 0 {
+				return i + 1
+			}
+		}
+	}
+	return len(data)
+}
+
+// byteToLine returns the number of the line containing the byte at index i.
+func byteToLine(data []byte, i int) int {
+	l := 1
+	for j, c := range data {
+		if j == i {
+			return l
+		}
+		if c == '\n' {
+			l++
+		}
+	}
+	return l
+}
diff --git a/cmd/godoc/dl.go b/cmd/godoc/dl.go
new file mode 100644
index 0000000..bd73831
--- /dev/null
+++ b/cmd/godoc/dl.go
@@ -0,0 +1,14 @@
+// Copyright 2014 The Go Authors. 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 "net/http"
+
+// Register a redirect handler for /dl/ to the golang.org download page.
+// This file will not be included when deploying godoc to golang.org.
+
+func init() {
+	http.Handle("/dl/", http.RedirectHandler("http://golang.org/dl/", http.StatusFound))
+}
diff --git a/cmd/godoc/doc.go b/cmd/godoc/doc.go
new file mode 100644
index 0000000..17cf23e
--- /dev/null
+++ b/cmd/godoc/doc.go
@@ -0,0 +1,146 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+/*
+
+Godoc extracts and generates documentation for Go programs.
+
+It has two modes.
+
+Without the -http flag, it runs in command-line mode and prints plain text
+documentation to standard output and exits. If both a library package and
+a command with the same name exists, using the prefix cmd/ will force
+documentation on the command rather than the library package. If the -src
+flag is specified, godoc prints the exported interface of a package in Go
+source form, or the implementation of a specific exported language entity:
+
+	godoc fmt                # documentation for package fmt
+	godoc fmt Printf         # documentation for fmt.Printf
+	godoc cmd/go             # force documentation for the go command
+	godoc -src fmt           # fmt package interface in Go source form
+	godoc -src fmt Printf    # implementation of fmt.Printf
+
+In command-line mode, the -q flag enables search queries against a godoc running
+as a webserver. If no explicit server address is specified with the -server flag,
+godoc first tries localhost:6060 and then http://golang.org.
+
+	godoc -q Reader
+	godoc -q math.Sin
+	godoc -server=:6060 -q sin
+
+With the -http flag, it runs as a web server and presents the documentation as a
+web page.
+
+	godoc -http=:6060
+
+Usage:
+	godoc [flag] package [name ...]
+
+The flags are:
+	-v
+		verbose mode
+	-q
+		arguments are considered search queries: a legal query is a
+		single identifier (such as ToLower) or a qualified identifier
+		(such as math.Sin)
+	-src
+		print (exported) source in command-line mode
+	-tabwidth=4
+		width of tabs in units of spaces
+	-timestamps=true
+		show timestamps with directory listings
+	-index
+		enable identifier and full text search index
+		(no search box is shown if -index is not set)
+	-index_files=""
+		glob pattern specifying index files; if not empty,
+		the index is read from these files in sorted order
+	-index_throttle=0.75
+		index throttle value; a value of 0 means no time is allocated
+		to the indexer (the indexer will never finish), a value of 1.0
+		means that index creation is running at full throttle (other
+		goroutines may get no time while the index is built)
+	-links=true:
+		link identifiers to their declarations
+	-write_index=false
+		write index to a file; the file name must be specified with
+		-index_files
+	-maxresults=10000
+		maximum number of full text search results shown
+		(no full text index is built if maxresults <= 0)
+	-notes="BUG"
+		regular expression matching note markers to show
+		(e.g., "BUG|TODO", ".*")
+	-html
+		print HTML in command-line mode
+	-goroot=$GOROOT
+		Go root directory
+	-http=addr
+		HTTP service address (e.g., '127.0.0.1:6060' or just ':6060')
+	-server=addr
+		webserver address for command line searches
+	-analysis=type,pointer
+		comma-separated list of analyses to perform
+    		"type": display identifier resolution, type info, method sets,
+			'implements', and static callees
+		"pointer" display channel peers, callers and dynamic callees
+			(significantly slower)
+		See http://golang.org/lib/godoc/analysis/help.html for details.
+	-templates=""
+		directory containing alternate template files; if set,
+		the directory may provide alternative template files
+		for the files in $GOROOT/lib/godoc
+	-url=path
+		print to standard output the data that would be served by
+		an HTTP request for path
+	-zip=""
+		zip file providing the file system to serve; disabled if empty
+
+By default, godoc looks at the packages it finds via $GOROOT and $GOPATH (if set).
+This behavior can be altered by providing an alternative $GOROOT with the -goroot
+flag.
+
+When godoc runs as a web server and -index is set, a search index is maintained.
+The index is created at startup.
+
+The index contains both identifier and full text search information (searchable
+via regular expressions). The maximum number of full text search results shown
+can be set with the -maxresults flag; if set to 0, no full text results are
+shown, and only an identifier index but no full text search index is created.
+
+The presentation mode of web pages served by godoc can be controlled with the
+"m" URL parameter; it accepts a comma-separated list of flag names as value:
+
+	all	show documentation for all declarations, not just the exported ones
+	methods	show all embedded methods, not just those of unexported anonymous fields
+	src	show the original source code rather then the extracted documentation
+	text	present the page in textual (command-line) form rather than HTML
+	flat	present flat (not indented) directory listings using full paths
+
+For instance, http://golang.org/pkg/math/big/?m=all,text shows the documentation
+for all (not just the exported) declarations of package big, in textual form (as
+it would appear when using godoc from the command line: "godoc -src math/big .*").
+
+By default, godoc serves files from the file system of the underlying OS.
+Instead, a .zip file may be provided via the -zip flag, which contains
+the file system to serve. The file paths stored in the .zip file must use
+slash ('/') as path separator; and they must be unrooted. $GOROOT (or -goroot)
+must be set to the .zip file directory path containing the Go root directory.
+For instance, for a .zip file created by the command:
+
+	zip go.zip $HOME/go
+
+one may run godoc as follows:
+
+	godoc -http=:6060 -zip=go.zip -goroot=$HOME/go
+
+Godoc documentation is converted to HTML or to text using the go/doc package;
+see http://golang.org/pkg/go/doc/#ToHTML for the exact rules.
+Godoc also shows example code that is runnable by the testing package;
+see http://golang.org/pkg/testing/#hdr-Examples for the conventions.
+See "Godoc: documenting Go code" for how to write good comments for godoc:
+http://golang.org/doc/articles/godoc_documenting_go_code.html
+
+*/
+package main // import "golang.org/x/tools/cmd/godoc"
diff --git a/cmd/godoc/godoc_test.go b/cmd/godoc/godoc_test.go
new file mode 100644
index 0000000..a228fae
--- /dev/null
+++ b/cmd/godoc/godoc_test.go
@@ -0,0 +1,440 @@
+// Copyright 2013 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main_test
+
+import (
+	"bufio"
+	"bytes"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"net"
+	"net/http"
+	"os"
+	"os/exec"
+	"path/filepath"
+	"regexp"
+	"runtime"
+	"strings"
+	"testing"
+	"time"
+)
+
+var godocTests = []struct {
+	args      []string
+	matches   []string // regular expressions
+	dontmatch []string // regular expressions
+}{
+	{
+		args: []string{"fmt"},
+		matches: []string{
+			`import "fmt"`,
+			`Package fmt implements formatted I/O`,
+		},
+	},
+	{
+		args: []string{"io", "WriteString"},
+		matches: []string{
+			`func WriteString\(`,
+			`WriteString writes the contents of the string s to w`,
+		},
+	},
+	{
+		args: []string{"nonexistingpkg"},
+		matches: []string{
+			`no such file or directory|does not exist|cannot find the file`,
+		},
+	},
+	{
+		args: []string{"fmt", "NonexistentSymbol"},
+		matches: []string{
+			`No match found\.`,
+		},
+	},
+	{
+		args: []string{"-src", "syscall", "Open"},
+		matches: []string{
+			`func Open\(`,
+		},
+		dontmatch: []string{
+			`No match found\.`,
+		},
+	},
+}
+
+// buildGodoc builds the godoc executable.
+// It returns its path, and a cleanup function.
+//
+// TODO(adonovan): opt: do this at most once, and do the cleanup
+// exactly once.  How though?  There's no atexit.
+func buildGodoc(t *testing.T) (bin string, cleanup func()) {
+	if runtime.GOARCH == "arm" {
+		t.Skip("skipping test on arm platforms; too slow")
+	}
+	tmp, err := ioutil.TempDir("", "godoc-regtest-")
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer func() {
+		if cleanup == nil { // probably, go build failed.
+			os.RemoveAll(tmp)
+		}
+	}()
+
+	bin = filepath.Join(tmp, "godoc")
+	if runtime.GOOS == "windows" {
+		bin += ".exe"
+	}
+	cmd := exec.Command("go", "build", "-o", bin)
+	if err := cmd.Run(); err != nil {
+		t.Fatalf("Building godoc: %v", err)
+	}
+
+	return bin, func() { os.RemoveAll(tmp) }
+}
+
+// Basic regression test for godoc command-line tool.
+func TestCLI(t *testing.T) {
+	bin, cleanup := buildGodoc(t)
+	defer cleanup()
+	for _, test := range godocTests {
+		cmd := exec.Command(bin, test.args...)
+		cmd.Args[0] = "godoc"
+		out, err := cmd.CombinedOutput()
+		if err != nil {
+			t.Errorf("Running with args %#v: %v", test.args, err)
+			continue
+		}
+		for _, pat := range test.matches {
+			re := regexp.MustCompile(pat)
+			if !re.Match(out) {
+				t.Errorf("godoc %v =\n%s\nwanted /%v/", strings.Join(test.args, " "), out, pat)
+			}
+		}
+		for _, pat := range test.dontmatch {
+			re := regexp.MustCompile(pat)
+			if re.Match(out) {
+				t.Errorf("godoc %v =\n%s\ndid not want /%v/", strings.Join(test.args, " "), out, pat)
+			}
+		}
+	}
+}
+
+func serverAddress(t *testing.T) string {
+	ln, err := net.Listen("tcp", "127.0.0.1:0")
+	if err != nil {
+		ln, err = net.Listen("tcp6", "[::1]:0")
+	}
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer ln.Close()
+	return ln.Addr().String()
+}
+
+func waitForServerReady(t *testing.T, addr string) {
+	waitForServer(t,
+		fmt.Sprintf("http://%v/", addr),
+		"The Go Programming Language",
+		5*time.Second)
+}
+
+func waitForSearchReady(t *testing.T, addr string) {
+	waitForServer(t,
+		fmt.Sprintf("http://%v/search?q=FALLTHROUGH", addr),
+		"The list of tokens.",
+		2*time.Minute)
+}
+
+const pollInterval = 200 * time.Millisecond
+
+func waitForServer(t *testing.T, url, match string, timeout time.Duration) {
+	// "health check" duplicated from x/tools/cmd/tipgodoc/tip.go
+	deadline := time.Now().Add(timeout)
+	for time.Now().Before(deadline) {
+		time.Sleep(pollInterval)
+		res, err := http.Get(url)
+		if err != nil {
+			continue
+		}
+		rbody, err := ioutil.ReadAll(res.Body)
+		res.Body.Close()
+		if err == nil && res.StatusCode == http.StatusOK &&
+			bytes.Contains(rbody, []byte(match)) {
+			return
+		}
+	}
+	t.Fatalf("Server failed to respond in %v", timeout)
+}
+
+func killAndWait(cmd *exec.Cmd) {
+	cmd.Process.Kill()
+	cmd.Wait()
+}
+
+// Basic integration test for godoc HTTP interface.
+func TestWeb(t *testing.T) {
+	testWeb(t, false)
+}
+
+// Basic integration test for godoc HTTP interface.
+func TestWebIndex(t *testing.T) {
+	if testing.Short() {
+		t.Skip("skipping test in -short mode")
+	}
+	testWeb(t, true)
+}
+
+// Basic integration test for godoc HTTP interface.
+func testWeb(t *testing.T, withIndex bool) {
+	bin, cleanup := buildGodoc(t)
+	defer cleanup()
+	addr := serverAddress(t)
+	args := []string{fmt.Sprintf("-http=%s", addr)}
+	if withIndex {
+		args = append(args, "-index", "-index_interval=-1s")
+	}
+	cmd := exec.Command(bin, args...)
+	cmd.Stdout = os.Stderr
+	cmd.Stderr = os.Stderr
+	cmd.Args[0] = "godoc"
+	cmd.Env = godocEnv()
+	if err := cmd.Start(); err != nil {
+		t.Fatalf("failed to start godoc: %s", err)
+	}
+	defer killAndWait(cmd)
+
+	if withIndex {
+		waitForSearchReady(t, addr)
+	} else {
+		waitForServerReady(t, addr)
+	}
+
+	tests := []struct {
+		path      string
+		match     []string
+		dontmatch []string
+		needIndex bool
+	}{
+		{
+			path:  "/",
+			match: []string{"Go is an open source programming language"},
+		},
+		{
+			path:  "/pkg/fmt/",
+			match: []string{"Package fmt implements formatted I/O"},
+		},
+		{
+			path:  "/src/fmt/",
+			match: []string{"scan_test.go"},
+		},
+		{
+			path:  "/src/fmt/print.go",
+			match: []string{"// Println formats using"},
+		},
+		{
+			path: "/pkg",
+			match: []string{
+				"Standard library",
+				"Package fmt implements formatted I/O",
+			},
+			dontmatch: []string{
+				"internal/syscall",
+				"cmd/gc",
+			},
+		},
+		{
+			path: "/pkg/?m=all",
+			match: []string{
+				"Standard library",
+				"Package fmt implements formatted I/O",
+				"internal/syscall",
+			},
+			dontmatch: []string{
+				"cmd/gc",
+			},
+		},
+		{
+			path: "/search?q=notwithstanding",
+			match: []string{
+				"/src",
+			},
+			dontmatch: []string{
+				"/pkg/bootstrap",
+			},
+			needIndex: true,
+		},
+	}
+	for _, test := range tests {
+		if test.needIndex && !withIndex {
+			continue
+		}
+		url := fmt.Sprintf("http://%s%s", addr, test.path)
+		resp, err := http.Get(url)
+		if err != nil {
+			t.Errorf("GET %s failed: %s", url, err)
+			continue
+		}
+		body, err := ioutil.ReadAll(resp.Body)
+		resp.Body.Close()
+		if err != nil {
+			t.Errorf("GET %s: failed to read body: %s (response: %v)", url, err, resp)
+		}
+		isErr := false
+		for _, substr := range test.match {
+			if !bytes.Contains(body, []byte(substr)) {
+				t.Errorf("GET %s: wanted substring %q in body", url, substr)
+				isErr = true
+			}
+		}
+		for _, substr := range test.dontmatch {
+			if bytes.Contains(body, []byte(substr)) {
+				t.Errorf("GET %s: didn't want substring %q in body", url, substr)
+				isErr = true
+			}
+		}
+		if isErr {
+			t.Errorf("GET %s: got:\n%s", url, body)
+		}
+	}
+}
+
+// Basic integration test for godoc -analysis=type (via HTTP interface).
+func TestTypeAnalysis(t *testing.T) {
+	if runtime.GOOS == "plan9" {
+		t.Skip("skipping test on plan9 (issue #11974)") // see comment re: Plan 9 below
+	}
+
+	// Write a fake GOROOT/GOPATH.
+	tmpdir, err := ioutil.TempDir("", "godoc-analysis")
+	if err != nil {
+		t.Fatalf("ioutil.TempDir failed: %s", err)
+	}
+	defer os.RemoveAll(tmpdir)
+	for _, f := range []struct{ file, content string }{
+		{"goroot/src/lib/lib.go", `
+package lib
+type T struct{}
+const C = 3
+var V T
+func (T) F() int { return C }
+`},
+		{"gopath/src/app/main.go", `
+package main
+import "lib"
+func main() { print(lib.V) }
+`},
+	} {
+		file := filepath.Join(tmpdir, f.file)
+		if err := os.MkdirAll(filepath.Dir(file), 0755); err != nil {
+			t.Fatalf("MkdirAll(%s) failed: %s", filepath.Dir(file), err)
+		}
+		if err := ioutil.WriteFile(file, []byte(f.content), 0644); err != nil {
+			t.Fatal(err)
+		}
+	}
+
+	// Start the server.
+	bin, cleanup := buildGodoc(t)
+	defer cleanup()
+	addr := serverAddress(t)
+	cmd := exec.Command(bin, fmt.Sprintf("-http=%s", addr), "-analysis=type")
+	cmd.Env = append(cmd.Env, fmt.Sprintf("GOROOT=%s", filepath.Join(tmpdir, "goroot")))
+	cmd.Env = append(cmd.Env, fmt.Sprintf("GOPATH=%s", filepath.Join(tmpdir, "gopath")))
+	for _, e := range os.Environ() {
+		if strings.HasPrefix(e, "GOROOT=") || strings.HasPrefix(e, "GOPATH=") {
+			continue
+		}
+		cmd.Env = append(cmd.Env, e)
+	}
+	cmd.Stdout = os.Stderr
+	stderr, err := cmd.StderrPipe()
+	if err != nil {
+		t.Fatal(err)
+	}
+	cmd.Args[0] = "godoc"
+	if err := cmd.Start(); err != nil {
+		t.Fatalf("failed to start godoc: %s", err)
+	}
+	defer killAndWait(cmd)
+	waitForServerReady(t, addr)
+
+	// Wait for type analysis to complete.
+	reader := bufio.NewReader(stderr)
+	for {
+		s, err := reader.ReadString('\n') // on Plan 9 this fails
+		if err != nil {
+			t.Fatal(err)
+		}
+		fmt.Fprint(os.Stderr, s)
+		if strings.Contains(s, "Type analysis complete.") {
+			break
+		}
+	}
+	go io.Copy(os.Stderr, reader)
+
+	t0 := time.Now()
+
+	// Make an HTTP request and check for a regular expression match.
+	// The patterns are very crude checks that basic type information
+	// has been annotated onto the source view.
+tryagain:
+	for _, test := range []struct{ url, pattern string }{
+		{"/src/lib/lib.go", "L2.*package .*Package docs for lib.*/lib"},
+		{"/src/lib/lib.go", "L3.*type .*type info for T.*struct"},
+		{"/src/lib/lib.go", "L5.*var V .*type T struct"},
+		{"/src/lib/lib.go", "L6.*func .*type T struct.*T.*return .*const C untyped int.*C"},
+
+		{"/src/app/main.go", "L2.*package .*Package docs for app"},
+		{"/src/app/main.go", "L3.*import .*Package docs for lib.*lib"},
+		{"/src/app/main.go", "L4.*func main.*package lib.*lib.*var lib.V lib.T.*V"},
+	} {
+		url := fmt.Sprintf("http://%s%s", addr, test.url)
+		resp, err := http.Get(url)
+		if err != nil {
+			t.Errorf("GET %s failed: %s", url, err)
+			continue
+		}
+		body, err := ioutil.ReadAll(resp.Body)
+		resp.Body.Close()
+		if err != nil {
+			t.Errorf("GET %s: failed to read body: %s (response: %v)", url, err, resp)
+			continue
+		}
+
+		if !bytes.Contains(body, []byte("Static analysis features")) {
+			// Type analysis results usually become available within
+			// ~4ms after godoc startup (for this input on my machine).
+			if elapsed := time.Since(t0); elapsed > 500*time.Millisecond {
+				t.Fatalf("type analysis results still unavailable after %s", elapsed)
+			}
+			time.Sleep(10 * time.Millisecond)
+			goto tryagain
+		}
+
+		match, err := regexp.Match(test.pattern, body)
+		if err != nil {
+			t.Errorf("regexp.Match(%q) failed: %s", test.pattern, err)
+			continue
+		}
+		if !match {
+			// This is a really ugly failure message.
+			t.Errorf("GET %s: body doesn't match %q, got:\n%s",
+				url, test.pattern, string(body))
+		}
+	}
+}
+
+// godocEnv returns the process environment without the GOPATH variable.
+// (We don't want the indexer looking at the local workspace during tests.)
+func godocEnv() (env []string) {
+	for _, v := range os.Environ() {
+		if strings.HasPrefix(v, "GOPATH=") {
+			continue
+		}
+		env = append(env, v)
+	}
+	return
+}
diff --git a/cmd/godoc/handlers.go b/cmd/godoc/handlers.go
new file mode 100644
index 0000000..1f79d80
--- /dev/null
+++ b/cmd/godoc/handlers.go
@@ -0,0 +1,83 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// The /doc/codewalk/ tree is synthesized from codewalk descriptions,
+// files named $GOROOT/doc/codewalk/*.xml.
+// For an example and a description of the format, see
+// http://golang.org/doc/codewalk/codewalk or run godoc -http=:6060
+// and see http://localhost:6060/doc/codewalk/codewalk .
+// That page is itself a codewalk; the source code for it is
+// $GOROOT/doc/codewalk/codewalk.xml.
+
+package main
+
+import (
+	"log"
+	"net/http"
+	"text/template"
+
+	"golang.org/x/tools/godoc"
+	"golang.org/x/tools/godoc/redirect"
+	"golang.org/x/tools/godoc/vfs"
+)
+
+var (
+	pres *godoc.Presentation
+	fs   = vfs.NameSpace{}
+)
+
+func registerHandlers(pres *godoc.Presentation) {
+	if pres == nil {
+		panic("nil Presentation")
+	}
+	http.HandleFunc("/doc/codewalk/", codewalk)
+	http.Handle("/doc/play/", pres.FileServer())
+	http.Handle("/robots.txt", pres.FileServer())
+	http.Handle("/", pres)
+	http.Handle("/pkg/C/", redirect.Handler("/cmd/cgo/"))
+	redirect.Register(nil)
+}
+
+func readTemplate(name string) *template.Template {
+	if pres == nil {
+		panic("no global Presentation set yet")
+	}
+	path := "lib/godoc/" + name
+
+	// use underlying file system fs to read the template file
+	// (cannot use template ParseFile functions directly)
+	data, err := vfs.ReadFile(fs, path)
+	if err != nil {
+		log.Fatal("readTemplate: ", err)
+	}
+	// be explicit with errors (for app engine use)
+	t, err := template.New(name).Funcs(pres.FuncMap()).Parse(string(data))
+	if err != nil {
+		log.Fatal("readTemplate: ", err)
+	}
+	return t
+}
+
+func readTemplates(p *godoc.Presentation, html bool) {
+	p.PackageText = readTemplate("package.txt")
+	p.SearchText = readTemplate("search.txt")
+
+	if html || p.HTMLMode {
+		codewalkHTML = readTemplate("codewalk.html")
+		codewalkdirHTML = readTemplate("codewalkdir.html")
+		p.CallGraphHTML = readTemplate("callgraph.html")
+		p.DirlistHTML = readTemplate("dirlist.html")
+		p.ErrorHTML = readTemplate("error.html")
+		p.ExampleHTML = readTemplate("example.html")
+		p.GodocHTML = readTemplate("godoc.html")
+		p.ImplementsHTML = readTemplate("implements.html")
+		p.MethodSetHTML = readTemplate("methodset.html")
+		p.PackageHTML = readTemplate("package.html")
+		p.SearchHTML = readTemplate("search.html")
+		p.SearchDocHTML = readTemplate("searchdoc.html")
+		p.SearchCodeHTML = readTemplate("searchcode.html")
+		p.SearchTxtHTML = readTemplate("searchtxt.html")
+		p.SearchDescXML = readTemplate("opensearch.xml")
+	}
+}
diff --git a/cmd/godoc/index.go b/cmd/godoc/index.go
new file mode 100644
index 0000000..f84b29a
--- /dev/null
+++ b/cmd/godoc/index.go
@@ -0,0 +1,11 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import "strings"
+
+func indexDirectoryDefault(dir string) bool {
+	return dir != "/pkg" && !strings.HasPrefix(dir, "/pkg/")
+}
diff --git a/cmd/godoc/main.go b/cmd/godoc/main.go
new file mode 100644
index 0000000..3496013
--- /dev/null
+++ b/cmd/godoc/main.go
@@ -0,0 +1,329 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// godoc: Go Documentation Server
+
+// Web server tree:
+//
+//	http://godoc/		main landing page
+//	http://godoc/doc/	serve from $GOROOT/doc - spec, mem, etc.
+//	http://godoc/src/	serve files from $GOROOT/src; .go gets pretty-printed
+//	http://godoc/cmd/	serve documentation about commands
+//	http://godoc/pkg/	serve documentation about packages
+//				(idea is if you say import "compress/zlib", you go to
+//				http://godoc/pkg/compress/zlib)
+//
+// Command-line interface:
+//
+//	godoc packagepath [name ...]
+//
+//	godoc compress/zlib
+//		- prints doc for package compress/zlib
+//	godoc crypto/block Cipher NewCMAC
+//		- prints doc for Cipher and NewCMAC in package crypto/block
+
+// +build !appengine
+
+package main
+
+import (
+	"archive/zip"
+	_ "expvar" // to serve /debug/vars
+	"flag"
+	"fmt"
+	"go/build"
+	"log"
+	"net/http"
+	"net/http/httptest"
+	_ "net/http/pprof" // to serve /debug/pprof/*
+	"net/url"
+	"os"
+	"path/filepath"
+	"regexp"
+	"runtime"
+	"strings"
+
+	"golang.org/x/tools/godoc"
+	"golang.org/x/tools/godoc/analysis"
+	"golang.org/x/tools/godoc/static"
+	"golang.org/x/tools/godoc/vfs"
+	"golang.org/x/tools/godoc/vfs/gatefs"
+	"golang.org/x/tools/godoc/vfs/mapfs"
+	"golang.org/x/tools/godoc/vfs/zipfs"
+)
+
+const (
+	defaultAddr = ":6060" // default webserver address
+	toolsPath   = "golang.org/x/tools/cmd/"
+)
+
+var (
+	// file system to serve
+	// (with e.g.: zip -r go.zip $GOROOT -i \*.go -i \*.html -i \*.css -i \*.js -i \*.txt -i \*.c -i \*.h -i \*.s -i \*.png -i \*.jpg -i \*.sh -i favicon.ico)
+	zipfile = flag.String("zip", "", "zip file providing the file system to serve; disabled if empty")
+
+	// file-based index
+	writeIndex = flag.Bool("write_index", false, "write index to a file; the file name must be specified with -index_files")
+
+	analysisFlag = flag.String("analysis", "", `comma-separated list of analyses to perform (supported: type, pointer). See http://golang.org/lib/godoc/analysis/help.html`)
+
+	// network
+	httpAddr   = flag.String("http", "", "HTTP service address (e.g., '"+defaultAddr+"')")
+	serverAddr = flag.String("server", "", "webserver address for command line searches")
+
+	// layout control
+	html    = flag.Bool("html", false, "print HTML in command-line mode")
+	srcMode = flag.Bool("src", false, "print (exported) source in command-line mode")
+	urlFlag = flag.String("url", "", "print HTML for named URL")
+
+	// command-line searches
+	query = flag.Bool("q", false, "arguments are considered search queries")
+
+	verbose = flag.Bool("v", false, "verbose mode")
+
+	// file system roots
+	// TODO(gri) consider the invariant that goroot always end in '/'
+	goroot = flag.String("goroot", runtime.GOROOT(), "Go root directory")
+
+	// layout control
+	tabWidth       = flag.Int("tabwidth", 4, "tab width")
+	showTimestamps = flag.Bool("timestamps", false, "show timestamps with directory listings")
+	templateDir    = flag.String("templates", "", "directory containing alternate template files")
+	showPlayground = flag.Bool("play", false, "enable playground in web interface")
+	showExamples   = flag.Bool("ex", false, "show examples in command line mode")
+	declLinks      = flag.Bool("links", true, "link identifiers to their declarations")
+
+	// search index
+	indexEnabled  = flag.Bool("index", false, "enable search index")
+	indexFiles    = flag.String("index_files", "", "glob pattern specifying index files; if not empty, the index is read from these files in sorted order")
+	indexInterval = flag.Duration("index_interval", 0, "interval of indexing; 0 for default (5m), negative to only index once at startup")
+	maxResults    = flag.Int("maxresults", 10000, "maximum number of full text search results shown")
+	indexThrottle = flag.Float64("index_throttle", 0.75, "index throttle value; 0.0 = no time allocated, 1.0 = full throttle")
+
+	// source code notes
+	notesRx = flag.String("notes", "BUG", "regular expression matching note markers to show")
+)
+
+func usage() {
+	fmt.Fprintf(os.Stderr,
+		"usage: godoc package [name ...]\n"+
+			"	godoc -http="+defaultAddr+"\n")
+	flag.PrintDefaults()
+	os.Exit(2)
+}
+
+func loggingHandler(h http.Handler) http.Handler {
+	return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
+		log.Printf("%s\t%s", req.RemoteAddr, req.URL)
+		h.ServeHTTP(w, req)
+	})
+}
+
+func handleURLFlag() {
+	// Try up to 10 fetches, following redirects.
+	urlstr := *urlFlag
+	for i := 0; i < 10; i++ {
+		// Prepare request.
+		u, err := url.Parse(urlstr)
+		if err != nil {
+			log.Fatal(err)
+		}
+		req := &http.Request{
+			URL: u,
+		}
+
+		// Invoke default HTTP handler to serve request
+		// to our buffering httpWriter.
+		w := httptest.NewRecorder()
+		http.DefaultServeMux.ServeHTTP(w, req)
+
+		// Return data, error, or follow redirect.
+		switch w.Code {
+		case 200: // ok
+			os.Stdout.Write(w.Body.Bytes())
+			return
+		case 301, 302, 303, 307: // redirect
+			redirect := w.HeaderMap.Get("Location")
+			if redirect == "" {
+				log.Fatalf("HTTP %d without Location header", w.Code)
+			}
+			urlstr = redirect
+		default:
+			log.Fatalf("HTTP error %d", w.Code)
+		}
+	}
+	log.Fatalf("too many redirects")
+}
+
+func main() {
+	flag.Usage = usage
+	flag.Parse()
+
+	playEnabled = *showPlayground
+
+	// Check usage: either server and no args, command line and args, or index creation mode
+	if (*httpAddr != "" || *urlFlag != "") != (flag.NArg() == 0) && !*writeIndex {
+		usage()
+	}
+
+	var fsGate chan bool
+	fsGate = make(chan bool, 20)
+
+	// Determine file system to use.
+	if *zipfile == "" {
+		// use file system of underlying OS
+		rootfs := gatefs.New(vfs.OS(*goroot), fsGate)
+		fs.Bind("/", rootfs, "/", vfs.BindReplace)
+	} else {
+		// use file system specified via .zip file (path separator must be '/')
+		rc, err := zip.OpenReader(*zipfile)
+		if err != nil {
+			log.Fatalf("%s: %s\n", *zipfile, err)
+		}
+		defer rc.Close() // be nice (e.g., -writeIndex mode)
+		fs.Bind("/", zipfs.New(rc, *zipfile), *goroot, vfs.BindReplace)
+	}
+	if *templateDir != "" {
+		fs.Bind("/lib/godoc", vfs.OS(*templateDir), "/", vfs.BindBefore)
+	} else {
+		fs.Bind("/lib/godoc", mapfs.New(static.Files), "/", vfs.BindReplace)
+	}
+
+	// Bind $GOPATH trees into Go root.
+	for _, p := range filepath.SplitList(build.Default.GOPATH) {
+		fs.Bind("/src", gatefs.New(vfs.OS(p), fsGate), "/src", vfs.BindAfter)
+	}
+
+	httpMode := *httpAddr != ""
+
+	var typeAnalysis, pointerAnalysis bool
+	if *analysisFlag != "" {
+		for _, a := range strings.Split(*analysisFlag, ",") {
+			switch a {
+			case "type":
+				typeAnalysis = true
+			case "pointer":
+				pointerAnalysis = true
+			default:
+				log.Fatalf("unknown analysis: %s", a)
+			}
+		}
+	}
+
+	corpus := godoc.NewCorpus(fs)
+	corpus.Verbose = *verbose
+	corpus.MaxResults = *maxResults
+	corpus.IndexEnabled = *indexEnabled && httpMode
+	if *maxResults == 0 {
+		corpus.IndexFullText = false
+	}
+	corpus.IndexFiles = *indexFiles
+	corpus.IndexDirectory = indexDirectoryDefault
+	corpus.IndexThrottle = *indexThrottle
+	corpus.IndexInterval = *indexInterval
+	if *writeIndex {
+		corpus.IndexThrottle = 1.0
+		corpus.IndexEnabled = true
+	}
+	if *writeIndex || httpMode || *urlFlag != "" {
+		if err := corpus.Init(); err != nil {
+			log.Fatal(err)
+		}
+	}
+
+	pres = godoc.NewPresentation(corpus)
+	pres.TabWidth = *tabWidth
+	pres.ShowTimestamps = *showTimestamps
+	pres.ShowPlayground = *showPlayground
+	pres.ShowExamples = *showExamples
+	pres.DeclLinks = *declLinks
+	pres.SrcMode = *srcMode
+	pres.HTMLMode = *html
+	if *notesRx != "" {
+		pres.NotesRx = regexp.MustCompile(*notesRx)
+	}
+
+	readTemplates(pres, httpMode || *urlFlag != "")
+	registerHandlers(pres)
+
+	if *writeIndex {
+		// Write search index and exit.
+		if *indexFiles == "" {
+			log.Fatal("no index file specified")
+		}
+
+		log.Println("initialize file systems")
+		*verbose = true // want to see what happens
+
+		corpus.UpdateIndex()
+
+		log.Println("writing index file", *indexFiles)
+		f, err := os.Create(*indexFiles)
+		if err != nil {
+			log.Fatal(err)
+		}
+		index, _ := corpus.CurrentIndex()
+		_, err = index.WriteTo(f)
+		if err != nil {
+			log.Fatal(err)
+		}
+
+		log.Println("done")
+		return
+	}
+
+	// Print content that would be served at the URL *urlFlag.
+	if *urlFlag != "" {
+		handleURLFlag()
+		return
+	}
+
+	if httpMode {
+		// HTTP server mode.
+		var handler http.Handler = http.DefaultServeMux
+		if *verbose {
+			log.Printf("Go Documentation Server")
+			log.Printf("version = %s", runtime.Version())
+			log.Printf("address = %s", *httpAddr)
+			log.Printf("goroot = %s", *goroot)
+			log.Printf("tabwidth = %d", *tabWidth)
+			switch {
+			case !*indexEnabled:
+				log.Print("search index disabled")
+			case *maxResults > 0:
+				log.Printf("full text index enabled (maxresults = %d)", *maxResults)
+			default:
+				log.Print("identifier search index enabled")
+			}
+			fs.Fprint(os.Stderr)
+			handler = loggingHandler(handler)
+		}
+
+		// Initialize search index.
+		if *indexEnabled {
+			go corpus.RunIndexer()
+		}
+
+		// Start type/pointer analysis.
+		if typeAnalysis || pointerAnalysis {
+			go analysis.Run(pointerAnalysis, &corpus.Analysis)
+		}
+
+		// Start http server.
+		if err := http.ListenAndServe(*httpAddr, handler); err != nil {
+			log.Fatalf("ListenAndServe %s: %v", *httpAddr, err)
+		}
+
+		return
+	}
+
+	if *query {
+		handleRemoteSearch()
+		return
+	}
+
+	if err := godoc.CommandLine(os.Stdout, fs, pres, flag.Args()); err != nil {
+		log.Print(err)
+	}
+}
diff --git a/cmd/godoc/play.go b/cmd/godoc/play.go
new file mode 100644
index 0000000..a56ffe2
--- /dev/null
+++ b/cmd/godoc/play.go
@@ -0,0 +1,44 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+	"encoding/json"
+	"fmt"
+	"go/format"
+	"net/http"
+
+	// This package registers "/compile" and "/share" handlers
+	// that redirect to the golang.org playground.
+	_ "golang.org/x/tools/playground"
+)
+
+func init() {
+	http.HandleFunc("/fmt", fmtHandler)
+}
+
+type fmtResponse struct {
+	Body  string
+	Error string
+}
+
+// fmtHandler takes a Go program in its "body" form value, formats it with
+// standard gofmt formatting, and writes a fmtResponse as a JSON object.
+func fmtHandler(w http.ResponseWriter, r *http.Request) {
+	resp := new(fmtResponse)
+	body, err := format.Source([]byte(r.FormValue("body")))
+	if err != nil {
+		resp.Error = err.Error()
+	} else {
+		resp.Body = string(body)
+	}
+	json.NewEncoder(w).Encode(resp)
+}
+
+// disabledHandler serves a 501 "Not Implemented" response.
+func disabledHandler(w http.ResponseWriter, r *http.Request) {
+	w.WriteHeader(http.StatusNotImplemented)
+	fmt.Fprint(w, "This functionality is not available via local godoc.")
+}
diff --git a/cmd/godoc/remotesearch.go b/cmd/godoc/remotesearch.go
new file mode 100644
index 0000000..f01d5c7
--- /dev/null
+++ b/cmd/godoc/remotesearch.go
@@ -0,0 +1,72 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !appengine
+
+package main
+
+import (
+	"errors"
+	"flag"
+	"io"
+	"log"
+	"net/http"
+	"net/url"
+	"os"
+)
+
+func handleRemoteSearch() {
+	// Command-line queries.
+	for i := 0; i < flag.NArg(); i++ {
+		res, err := remoteSearch(flag.Arg(i))
+		if err != nil {
+			log.Fatalf("remoteSearch: %s", err)
+		}
+		io.Copy(os.Stdout, res.Body)
+	}
+	return
+}
+
+// remoteSearchURL returns the search URL for a given query as needed by
+// remoteSearch. If html is set, an html result is requested; otherwise
+// the result is in textual form.
+// Adjust this function as necessary if modeNames or FormValue parameters
+// change.
+func remoteSearchURL(query string, html bool) string {
+	s := "/search?m=text&q="
+	if html {
+		s = "/search?q="
+	}
+	return s + url.QueryEscape(query)
+}
+
+func remoteSearch(query string) (res *http.Response, err error) {
+	// list of addresses to try
+	var addrs []string
+	if *serverAddr != "" {
+		// explicit server address - only try this one
+		addrs = []string{*serverAddr}
+	} else {
+		addrs = []string{
+			defaultAddr,
+			"golang.org",
+		}
+	}
+
+	// remote search
+	search := remoteSearchURL(query, *html)
+	for _, addr := range addrs {
+		url := "http://" + addr + search
+		res, err = http.Get(url)
+		if err == nil && res.StatusCode == http.StatusOK {
+			break
+		}
+	}
+
+	if err == nil && res.StatusCode != http.StatusOK {
+		err = errors.New(res.Status)
+	}
+
+	return
+}
diff --git a/cmd/godoc/setup-godoc-app.bash b/cmd/godoc/setup-godoc-app.bash
new file mode 100755
index 0000000..9d82cd7
--- /dev/null
+++ b/cmd/godoc/setup-godoc-app.bash
@@ -0,0 +1,134 @@
+#!/usr/bin/env bash
+
+# Copyright 2011 The Go Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+
+# This script creates a complete godoc app in $APPDIR.
+# It copies the cmd/godoc and src/go/... sources from GOROOT,
+# synthesizes an app.yaml file, and creates the .zip, index, and
+# configuration files.
+#
+# If an argument is provided it is assumed to be the app-engine godoc directory.
+# Without an argument, $APPDIR is used instead. If GOROOT is not set, "go env"
+# is consulted to find the $GOROOT.
+#
+# The script creates a .zip file representing the $GOROOT file system
+# and computes the correspondig search index files. These files are then
+# copied to $APPDIR. A corresponding godoc configuration file is created
+# in $APPDIR/appconfig.go.
+
+ZIPFILE=godoc.zip
+INDEXFILE=godoc.index
+SPLITFILES=index.split.
+GODOC=golang.org/x/tools/cmd/godoc
+CONFIGFILE=$GODOC/appconfig.go
+
+error() {
+	echo "error: $1"
+	exit 2
+}
+
+getArgs() {
+	if [ -z $APPENGINE_SDK ]; then
+		error "APPENGINE_SDK environment variable not set"
+	fi
+	if [ ! -x $APPENGINE_SDK/goapp ]; then
+		error "couldn't find goapp command in $APPENGINE_SDK"
+	fi
+	if [ -z $GOROOT ]; then
+		GOROOT=$(go env GOROOT)
+		echo "GOROOT not set explicitly, using go env value instead"
+	fi
+	if [ -z $APPDIR ]; then
+		if [ $# == 0 ]; then
+			error "APPDIR not set, and no argument provided"
+		fi
+		APPDIR=$1
+		echo "APPDIR not set, using argument instead"
+	fi
+
+	# safety checks
+	if [ ! -d $GOROOT ]; then
+		error "$GOROOT is not a directory"
+	fi
+	if [ -e $APPDIR ]; then
+		error "$APPDIR exists; check and remove it before trying again"
+	fi
+
+	# reporting
+	echo "GOROOT = $GOROOT"
+	echo "APPDIR = $APPDIR"
+}
+
+fetchGodoc() {
+	echo "*** Fetching godoc (if not already in GOPATH)"
+	unset GOBIN
+	go=$APPENGINE_SDK/goapp
+	$go get -d -tags appengine $GODOC
+	mkdir -p $APPDIR/$GODOC
+	cp $(find $($go list -f '{{.Dir}}' $GODOC) -type f -depth 1) $APPDIR/$GODOC/
+}
+
+makeAppYaml() {
+	echo "*** make $APPDIR/app.yaml"
+	cat > $APPDIR/app.yaml <<EOF
+application: godoc
+version: 1
+runtime: go
+api_version: go1.4beta
+
+handlers:
+- url: /.*
+  script: _go_app
+EOF
+}
+
+makeZipfile() {
+	echo "*** make $APPDIR/$ZIPFILE"
+	zip -q -r $APPDIR/$ZIPFILE $GOROOT/*
+}
+
+makeIndexfile() {
+	echo "*** make $APPDIR/$INDEXFILE"
+	GOPATH= godoc -write_index -index_files=$APPDIR/$INDEXFILE -zip=$APPDIR/$ZIPFILE
+}
+
+splitIndexfile() {
+	echo "*** split $APPDIR/$INDEXFILE"
+	split -b8m $APPDIR/$INDEXFILE $APPDIR/$SPLITFILES
+}
+
+makeConfigfile() {
+	echo "*** make $APPDIR/$CONFIGFILE"
+	cat > $APPDIR/$CONFIGFILE <<EOF
+package main
+
+// GENERATED FILE - DO NOT MODIFY BY HAND.
+// (generated by golang.org/x/tools/cmd/godoc/setup-godoc-app.bash)
+
+const (
+	// .zip filename
+	zipFilename = "$ZIPFILE"
+
+	// goroot directory in .zip file
+	zipGoroot = "$GOROOT"
+
+	// glob pattern describing search index files
+	// (if empty, the index is built at run-time)
+	indexFilenames = "$SPLITFILES*"
+)
+EOF
+}
+
+getArgs "$@"
+set -e
+mkdir $APPDIR
+fetchGodoc
+makeAppYaml
+makeZipfile
+makeIndexfile
+splitIndexfile
+makeConfigfile
+
+echo "*** setup complete"
diff --git a/cmd/godoc/x.go b/cmd/godoc/x.go
new file mode 100644
index 0000000..b4af41a
--- /dev/null
+++ b/cmd/godoc/x.go
@@ -0,0 +1,85 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file contains the handlers that serve go-import redirects for Go
+// sub-repositories. It specifies the mapping from import paths like
+// "golang.org/x/tools" to the actual repository locations.
+
+package main
+
+import (
+	"html/template"
+	"log"
+	"net/http"
+	"strings"
+)
+
+const xPrefix = "/x/"
+
+type xRepo struct {
+	URL, VCS string
+}
+
+var xMap = map[string]xRepo{
+	"codereview": {"https://code.google.com/p/go.codereview", "hg"},
+
+	"benchmarks": {"https://go.googlesource.com/benchmarks", "git"},
+	"blog":       {"https://go.googlesource.com/blog", "git"},
+	"build":      {"https://go.googlesource.com/build", "git"},
+	"crypto":     {"https://go.googlesource.com/crypto", "git"},
+	"debug":      {"https://go.googlesource.com/debug", "git"},
+	"exp":        {"https://go.googlesource.com/exp", "git"},
+	"image":      {"https://go.googlesource.com/image", "git"},
+	"mobile":     {"https://go.googlesource.com/mobile", "git"},
+	"net":        {"https://go.googlesource.com/net", "git"},
+	"oauth2":     {"https://go.googlesource.com/oauth2", "git"},
+	"playground": {"https://go.googlesource.com/playground", "git"},
+	"review":     {"https://go.googlesource.com/review", "git"},
+	"sys":        {"https://go.googlesource.com/sys", "git"},
+	"talks":      {"https://go.googlesource.com/talks", "git"},
+	"text":       {"https://go.googlesource.com/text", "git"},
+	"tools":      {"https://go.googlesource.com/tools", "git"},
+	"tour":       {"https://go.googlesource.com/tour", "git"},
+}
+
+func init() {
+	http.HandleFunc(xPrefix, xHandler)
+}
+
+func xHandler(w http.ResponseWriter, r *http.Request) {
+	head, tail := strings.TrimPrefix(r.URL.Path, xPrefix), ""
+	if i := strings.Index(head, "/"); i != -1 {
+		head, tail = head[:i], head[i:]
+	}
+	if head == "" {
+		http.Redirect(w, r, "https://godoc.org/-/subrepo", http.StatusTemporaryRedirect)
+		return
+	}
+	repo, ok := xMap[head]
+	if !ok {
+		http.NotFound(w, r)
+		return
+	}
+	data := struct {
+		Prefix, Head, Tail string
+		Repo               xRepo
+	}{xPrefix, head, tail, repo}
+	if err := xTemplate.Execute(w, data); err != nil {
+		log.Println("xHandler:", err)
+	}
+}
+
+var xTemplate = template.Must(template.New("x").Parse(`<!DOCTYPE html>
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+<meta name="go-import" content="golang.org{{.Prefix}}{{.Head}} {{.Repo.VCS}} {{.Repo.URL}}">
+<meta name="go-source" content="golang.org{{.Prefix}}{{.Head}} https://github.com/golang/{{.Head}}/ https://github.com/golang/{{.Head}}/tree/master{/dir} https://github.com/golang/{{.Head}}/blob/master{/dir}/{file}#L{line}">
+<meta http-equiv="refresh" content="0; url=https://godoc.org/golang.org{{.Prefix}}{{.Head}}{{.Tail}}">
+</head>
+<body>
+Nothing to see here; <a href="https://godoc.org/golang.org{{.Prefix}}{{.Head}}{{.Tail}}">move along</a>.
+</body>
+</html>
+`))
diff --git a/cmd/goimports/doc.go b/cmd/goimports/doc.go
new file mode 100644
index 0000000..46b2b07
--- /dev/null
+++ b/cmd/goimports/doc.go
@@ -0,0 +1,33 @@
+/*
+
+Command goimports updates your Go import lines,
+adding missing ones and removing unreferenced ones.
+
+     $ go get golang.org/x/tools/cmd/goimports
+
+It's a drop-in replacement for your editor's gofmt-on-save hook.
+It has the same command-line interface as gofmt and formats
+your code in the same way.
+
+For emacs, make sure you have the latest go-mode.el:
+   https://github.com/dominikh/go-mode.el
+Then in your .emacs file:
+   (setq gofmt-command "goimports")
+   (add-to-list 'load-path "/home/you/somewhere/emacs/")
+   (require 'go-mode-load)
+   (add-hook 'before-save-hook 'gofmt-before-save)
+
+For vim, set "gofmt_command" to "goimports":
+    https://golang.org/change/39c724dd7f252
+    https://golang.org/wiki/IDEsAndTextEditorPlugins
+    etc
+
+For GoSublime, follow the steps described here:
+    http://michaelwhatcott.com/gosublime-goimports/
+
+For other editors, you probably know what to do.
+
+Happy hacking!
+
+*/
+package main // import "golang.org/x/tools/cmd/goimports"
diff --git a/cmd/goimports/goimports.go b/cmd/goimports/goimports.go
new file mode 100644
index 0000000..b0b7aa8
--- /dev/null
+++ b/cmd/goimports/goimports.go
@@ -0,0 +1,201 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+	"bytes"
+	"flag"
+	"fmt"
+	"go/scanner"
+	"io"
+	"io/ioutil"
+	"os"
+	"os/exec"
+	"path/filepath"
+	"runtime"
+	"strings"
+
+	"golang.org/x/tools/imports"
+)
+
+var (
+	// main operation modes
+	list   = flag.Bool("l", false, "list files whose formatting differs from goimport's")
+	write  = flag.Bool("w", false, "write result to (source) file instead of stdout")
+	doDiff = flag.Bool("d", false, "display diffs instead of rewriting files")
+
+	options = &imports.Options{
+		TabWidth:  8,
+		TabIndent: true,
+		Comments:  true,
+		Fragment:  true,
+	}
+	exitCode = 0
+)
+
+func init() {
+	flag.BoolVar(&options.AllErrors, "e", false, "report all errors (not just the first 10 on different lines)")
+}
+
+func report(err error) {
+	scanner.PrintError(os.Stderr, err)
+	exitCode = 2
+}
+
+func usage() {
+	fmt.Fprintf(os.Stderr, "usage: goimports [flags] [path ...]\n")
+	flag.PrintDefaults()
+	os.Exit(2)
+}
+
+func isGoFile(f os.FileInfo) bool {
+	// ignore non-Go files
+	name := f.Name()
+	return !f.IsDir() && !strings.HasPrefix(name, ".") && strings.HasSuffix(name, ".go")
+}
+
+func processFile(filename string, in io.Reader, out io.Writer, stdin bool) error {
+	opt := options
+	if stdin {
+		nopt := *options
+		nopt.Fragment = true
+		opt = &nopt
+	}
+
+	if in == nil {
+		f, err := os.Open(filename)
+		if err != nil {
+			return err
+		}
+		defer f.Close()
+		in = f
+	}
+
+	src, err := ioutil.ReadAll(in)
+	if err != nil {
+		return err
+	}
+
+	res, err := imports.Process(filename, src, opt)
+	if err != nil {
+		return err
+	}
+
+	if !bytes.Equal(src, res) {
+		// formatting has changed
+		if *list {
+			fmt.Fprintln(out, filename)
+		}
+		if *write {
+			err = ioutil.WriteFile(filename, res, 0)
+			if err != nil {
+				return err
+			}
+		}
+		if *doDiff {
+			data, err := diff(src, res)
+			if err != nil {
+				return fmt.Errorf("computing diff: %s", err)
+			}
+			fmt.Printf("diff %s gofmt/%s\n", filename, filename)
+			out.Write(data)
+		}
+	}
+
+	if !*list && !*write && !*doDiff {
+		_, err = out.Write(res)
+	}
+
+	return err
+}
+
+func visitFile(path string, f os.FileInfo, err error) error {
+	if err == nil && isGoFile(f) {
+		err = processFile(path, nil, os.Stdout, false)
+	}
+	if err != nil {
+		report(err)
+	}
+	return nil
+}
+
+func walkDir(path string) {
+	filepath.Walk(path, visitFile)
+}
+
+func main() {
+	runtime.GOMAXPROCS(runtime.NumCPU())
+
+	// call gofmtMain in a separate function
+	// so that it can use defer and have them
+	// run before the exit.
+	gofmtMain()
+	os.Exit(exitCode)
+}
+
+// parseFlags parses command line flags and returns the paths to process.
+// It's a var so that custom implementations can replace it in other files.
+var parseFlags = func() []string {
+	flag.Parse()
+	return flag.Args()
+}
+
+func gofmtMain() {
+	flag.Usage = usage
+	paths := parseFlags()
+
+	if options.TabWidth < 0 {
+		fmt.Fprintf(os.Stderr, "negative tabwidth %d\n", options.TabWidth)
+		exitCode = 2
+		return
+	}
+
+	if len(paths) == 0 {
+		if err := processFile("<standard input>", os.Stdin, os.Stdout, true); err != nil {
+			report(err)
+		}
+		return
+	}
+
+	for _, path := range paths {
+		switch dir, err := os.Stat(path); {
+		case err != nil:
+			report(err)
+		case dir.IsDir():
+			walkDir(path)
+		default:
+			if err := processFile(path, nil, os.Stdout, false); err != nil {
+				report(err)
+			}
+		}
+	}
+}
+
+func diff(b1, b2 []byte) (data []byte, err error) {
+	f1, err := ioutil.TempFile("", "gofmt")
+	if err != nil {
+		return
+	}
+	defer os.Remove(f1.Name())
+	defer f1.Close()
+
+	f2, err := ioutil.TempFile("", "gofmt")
+	if err != nil {
+		return
+	}
+	defer os.Remove(f2.Name())
+	defer f2.Close()
+
+	f1.Write(b1)
+	f2.Write(b2)
+
+	data, err = exec.Command("diff", "-u", f1.Name(), f2.Name()).CombinedOutput()
+	if len(data) > 0 {
+		// diff exits with a non-zero status when the files don't match.
+		// Ignore that failure as long as we get output.
+		err = nil
+	}
+	return
+}
diff --git a/cmd/gomvpkg/main.go b/cmd/gomvpkg/main.go
new file mode 100644
index 0000000..959b84e
--- /dev/null
+++ b/cmd/gomvpkg/main.go
@@ -0,0 +1,94 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// licence that can be found in the LICENSE file.
+
+// The gomvpkg command moves go packages, updating import declarations.
+// See the -help message or Usage constant for details.
+package main
+
+import (
+	"flag"
+	"fmt"
+	"go/build"
+	"os"
+
+	"golang.org/x/tools/go/buildutil"
+	"golang.org/x/tools/refactor/rename"
+)
+
+var (
+	fromFlag     = flag.String("from", "", "Import path of package to be moved")
+	toFlag       = flag.String("to", "", "Destination import path for package")
+	vcsMvCmdFlag = flag.String("vcs_mv_cmd", "", `A template for the version control system's "move directory" command, e.g. "git mv {{.Src}} {{.Dst}}`)
+	helpFlag     = flag.Bool("help", false, "show usage message")
+)
+
+func init() {
+	flag.Var((*buildutil.TagsFlag)(&build.Default.BuildTags), "tags", buildutil.TagsFlagDoc)
+}
+
+const Usage = `gomvpkg: moves a package, updating import declarations
+
+Usage:
+
+ gomvpkg -from <path> -to <path> [-vcs_mv_cmd <template>]
+
+Flags:
+
+-from        specifies the import path of the package to be moved
+
+-to          specifies the destination import path
+
+-vcs_mv_cmd  specifies a shell command to inform the version control system of a
+             directory move.  The argument is a template using the syntax of the
+             text/template package. It has two fields: Src and Dst, the absolute
+             paths of the directories.
+
+             For example: "git mv {{.Src}} {{.Dst}}"
+
+gomvpkg determines the set of packages that might be affected, including all
+packages importing the 'from' package and any of its subpackages. It will move
+the 'from' package and all its subpackages to the destination path and update all
+imports of those packages to point to its new import path.
+
+gomvpkg rejects moves in which a package already exists at the destination import
+path, or in which a directory already exists at the location the package would be
+moved to.
+
+gomvpkg will not always be able to rename imports when a package's name is changed.
+Import statements may want further cleanup.
+
+gomvpkg's behavior is not defined if any of the packages to be moved are
+imported using dot imports.
+
+Examples:
+
+% gomvpkg -from myproject/foo -to myproject/bar
+
+  Move the package with import path "myproject/foo" to the new path
+  "myproject/bar".
+
+% gomvpkg -from myproject/foo -to myproject/bar -vcs_mv_cmd "git mv {{.Src}} {{.Dst}}"
+
+  Move the package with import path "myproject/foo" to the new path
+  "myproject/bar" using "git mv" to execute the directory move.
+`
+
+func main() {
+	flag.Parse()
+
+	if len(flag.Args()) > 0 {
+		fmt.Fprintln(os.Stderr, "gomvpkg: surplus arguments.")
+		os.Exit(1)
+	}
+
+	if *helpFlag || *fromFlag == "" || *toFlag == "" {
+		fmt.Println(Usage)
+		return
+	}
+
+	if err := rename.Move(&build.Default, *fromFlag, *toFlag, *vcsMvCmdFlag); err != nil {
+		fmt.Fprintf(os.Stderr, "gomvpkg: %s.\n", err)
+		os.Exit(1)
+	}
+}
diff --git a/cmd/gorename/main.go b/cmd/gorename/main.go
new file mode 100644
index 0000000..922dc0c
--- /dev/null
+++ b/cmd/gorename/main.go
@@ -0,0 +1,63 @@
+// The gorename command performs precise type-safe renaming of
+// identifiers in Go source code.
+//
+// Run with -help for usage information, or view the Usage constant in
+// package golang.org/x/tools/refactor/rename, which contains most of
+// the implementation.
+//
+package main // import "golang.org/x/tools/cmd/gorename"
+
+import (
+	"flag"
+	"fmt"
+	"go/build"
+	"os"
+	"runtime"
+
+	"golang.org/x/tools/go/buildutil"
+	"golang.org/x/tools/refactor/rename"
+)
+
+var (
+	offsetFlag = flag.String("offset", "", "file and byte offset of identifier to be renamed, e.g. 'file.go:#123'.  For use by editors.")
+	fromFlag   = flag.String("from", "", "identifier to be renamed; see -help for formats")
+	toFlag     = flag.String("to", "", "new name for identifier")
+	helpFlag   = flag.Bool("help", false, "show usage message")
+)
+
+func init() {
+	flag.Var((*buildutil.TagsFlag)(&build.Default.BuildTags), "tags", buildutil.TagsFlagDoc)
+	flag.BoolVar(&rename.Force, "force", false, "proceed, even if conflicts were reported")
+	flag.BoolVar(&rename.DryRun, "dryrun", false, "show the change, but do not apply it")
+	flag.BoolVar(&rename.Verbose, "v", false, "print verbose information")
+
+	// If $GOMAXPROCS isn't set, use the full capacity of the machine.
+	// For small machines, use at least 4 threads.
+	if os.Getenv("GOMAXPROCS") == "" {
+		n := runtime.NumCPU()
+		if n < 4 {
+			n = 4
+		}
+		runtime.GOMAXPROCS(n)
+	}
+}
+
+func main() {
+	flag.Parse()
+	if len(flag.Args()) > 0 {
+		fmt.Fprintln(os.Stderr, "gorename: surplus arguments.")
+		os.Exit(1)
+	}
+
+	if *helpFlag || (*offsetFlag == "" && *fromFlag == "" && *toFlag == "") {
+		fmt.Println(rename.Usage)
+		return
+	}
+
+	if err := rename.Main(&build.Default, *offsetFlag, *fromFlag, *toFlag); err != nil {
+		if err != rename.ConflictError {
+			fmt.Fprintf(os.Stderr, "gorename: %s\n", err)
+		}
+		os.Exit(1)
+	}
+}
diff --git a/cmd/gotype/doc.go b/cmd/gotype/doc.go
new file mode 100644
index 0000000..ea0b2b1
--- /dev/null
+++ b/cmd/gotype/doc.go
@@ -0,0 +1,62 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+/*
+The gotype command does syntactic and semantic analysis of Go files
+and packages like the front-end of a Go compiler. Errors are reported
+if the analysis fails; otherwise gotype is quiet (unless -v is set).
+
+Without a list of paths, gotype reads from standard input, which
+must provide a single Go source file defining a complete package.
+
+If a single path is specified that is a directory, gotype checks
+the Go files in that directory; they must all belong to the same
+package.
+
+Otherwise, each path must be the filename of Go file belonging to
+the same package.
+
+Usage:
+	gotype [flags] [path...]
+
+The flags are:
+	-a
+		use all (incl. _test.go) files when processing a directory
+	-e
+		report all errors (not just the first 10)
+	-v
+		verbose mode
+	-gccgo
+		use gccimporter instead of gcimporter
+
+Debugging flags:
+	-seq
+		parse sequentially, rather than in parallel
+	-ast
+		print AST (forces -seq)
+	-trace
+		print parse trace (forces -seq)
+	-comments
+		parse comments (ignored unless -ast or -trace is provided)
+
+Examples:
+
+To check the files a.go, b.go, and c.go:
+
+	gotype a.go b.go c.go
+
+To check an entire package in the directory dir and print the processed files:
+
+	gotype -v dir
+
+To check an entire package including tests in the local directory:
+
+	gotype -a .
+
+To verify the output of a pipe:
+
+	echo "package foo" | gotype
+
+*/
+package main // import "golang.org/x/tools/cmd/gotype"
diff --git a/cmd/gotype/gotype.go b/cmd/gotype/gotype.go
new file mode 100644
index 0000000..4a5c7de
--- /dev/null
+++ b/cmd/gotype/gotype.go
@@ -0,0 +1,262 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+	"flag"
+	"fmt"
+	"go/ast"
+	"go/build"
+	"go/parser"
+	"go/scanner"
+	"go/token"
+	"io/ioutil"
+	"os"
+	"path/filepath"
+	"runtime"
+	"time"
+
+	"golang.org/x/tools/go/gccgoimporter"
+	_ "golang.org/x/tools/go/gcimporter"
+	"golang.org/x/tools/go/types"
+)
+
+var (
+	// main operation modes
+	allFiles  = flag.Bool("a", false, "use all (incl. _test.go) files when processing a directory")
+	allErrors = flag.Bool("e", false, "report all errors (not just the first 10)")
+	verbose   = flag.Bool("v", false, "verbose mode")
+	gccgo     = flag.Bool("gccgo", false, "use gccgoimporter instead of gcimporter")
+
+	// debugging support
+	sequential    = flag.Bool("seq", false, "parse sequentially, rather than in parallel")
+	printAST      = flag.Bool("ast", false, "print AST (forces -seq)")
+	printTrace    = flag.Bool("trace", false, "print parse trace (forces -seq)")
+	parseComments = flag.Bool("comments", false, "parse comments (ignored unless -ast or -trace is provided)")
+)
+
+var (
+	fset       = token.NewFileSet()
+	errorCount = 0
+	parserMode parser.Mode
+	sizes      types.Sizes
+)
+
+func initParserMode() {
+	if *allErrors {
+		parserMode |= parser.AllErrors
+	}
+	if *printTrace {
+		parserMode |= parser.Trace
+	}
+	if *parseComments && (*printAST || *printTrace) {
+		parserMode |= parser.ParseComments
+	}
+}
+
+func initSizes() {
+	wordSize := 8
+	maxAlign := 8
+	switch build.Default.GOARCH {
+	case "386", "arm":
+		wordSize = 4
+		maxAlign = 4
+		// add more cases as needed
+	}
+	sizes = &types.StdSizes{WordSize: int64(wordSize), MaxAlign: int64(maxAlign)}
+}
+
+func usage() {
+	fmt.Fprintln(os.Stderr, "usage: gotype [flags] [path ...]")
+	flag.PrintDefaults()
+	os.Exit(2)
+}
+
+func report(err error) {
+	scanner.PrintError(os.Stderr, err)
+	if list, ok := err.(scanner.ErrorList); ok {
+		errorCount += len(list)
+		return
+	}
+	errorCount++
+}
+
+// parse may be called concurrently
+func parse(filename string, src interface{}) (*ast.File, error) {
+	if *verbose {
+		fmt.Println(filename)
+	}
+	file, err := parser.ParseFile(fset, filename, src, parserMode) // ok to access fset concurrently
+	if *printAST {
+		ast.Print(fset, file)
+	}
+	return file, err
+}
+
+func parseStdin() (*ast.File, error) {
+	src, err := ioutil.ReadAll(os.Stdin)
+	if err != nil {
+		return nil, err
+	}
+	return parse("<standard input>", src)
+}
+
+func parseFiles(filenames []string) ([]*ast.File, error) {
+	files := make([]*ast.File, len(filenames))
+
+	if *sequential {
+		for i, filename := range filenames {
+			var err error
+			files[i], err = parse(filename, nil)
+			if err != nil {
+				return nil, err // leave unfinished goroutines hanging
+			}
+		}
+	} else {
+		type parseResult struct {
+			file *ast.File
+			err  error
+		}
+
+		out := make(chan parseResult)
+		for _, filename := range filenames {
+			go func(filename string) {
+				file, err := parse(filename, nil)
+				out <- parseResult{file, err}
+			}(filename)
+		}
+
+		for i := range filenames {
+			res := <-out
+			if res.err != nil {
+				return nil, res.err // leave unfinished goroutines hanging
+			}
+			files[i] = res.file
+		}
+	}
+
+	return files, nil
+}
+
+func parseDir(dirname string) ([]*ast.File, error) {
+	ctxt := build.Default
+	pkginfo, err := ctxt.ImportDir(dirname, 0)
+	if _, nogo := err.(*build.NoGoError); err != nil && !nogo {
+		return nil, err
+	}
+	filenames := append(pkginfo.GoFiles, pkginfo.CgoFiles...)
+	if *allFiles {
+		filenames = append(filenames, pkginfo.TestGoFiles...)
+	}
+
+	// complete file names
+	for i, filename := range filenames {
+		filenames[i] = filepath.Join(dirname, filename)
+	}
+
+	return parseFiles(filenames)
+}
+
+func getPkgFiles(args []string) ([]*ast.File, error) {
+	if len(args) == 0 {
+		// stdin
+		file, err := parseStdin()
+		if err != nil {
+			return nil, err
+		}
+		return []*ast.File{file}, nil
+	}
+
+	if len(args) == 1 {
+		// possibly a directory
+		path := args[0]
+		info, err := os.Stat(path)
+		if err != nil {
+			return nil, err
+		}
+		if info.IsDir() {
+			return parseDir(path)
+		}
+	}
+
+	// list of files
+	return parseFiles(args)
+}
+
+func checkPkgFiles(files []*ast.File) {
+	type bailout struct{}
+	conf := types.Config{
+		FakeImportC: true,
+		Error: func(err error) {
+			if !*allErrors && errorCount >= 10 {
+				panic(bailout{})
+			}
+			report(err)
+		},
+		Sizes: sizes,
+	}
+	if *gccgo {
+		var inst gccgoimporter.GccgoInstallation
+		inst.InitFromDriver("gccgo")
+		conf.Import = inst.GetImporter(nil, nil)
+	}
+
+	defer func() {
+		switch p := recover().(type) {
+		case nil, bailout:
+			// normal return or early exit
+		default:
+			// re-panic
+			panic(p)
+		}
+	}()
+
+	const path = "pkg" // any non-empty string will do for now
+	conf.Check(path, fset, files, nil)
+}
+
+func printStats(d time.Duration) {
+	fileCount := 0
+	lineCount := 0
+	fset.Iterate(func(f *token.File) bool {
+		fileCount++
+		lineCount += f.LineCount()
+		return true
+	})
+
+	fmt.Printf(
+		"%s (%d files, %d lines, %d lines/s)\n",
+		d, fileCount, lineCount, int64(float64(lineCount)/d.Seconds()),
+	)
+}
+
+func main() {
+	runtime.GOMAXPROCS(runtime.NumCPU()) // remove this once runtime is smarter
+
+	flag.Usage = usage
+	flag.Parse()
+	if *printAST || *printTrace {
+		*sequential = true
+	}
+	initParserMode()
+	initSizes()
+
+	start := time.Now()
+
+	files, err := getPkgFiles(flag.Args())
+	if err != nil {
+		report(err)
+		os.Exit(2)
+	}
+
+	checkPkgFiles(files)
+	if errorCount > 0 {
+		os.Exit(2)
+	}
+
+	if *verbose {
+		printStats(time.Since(start))
+	}
+}
diff --git a/cmd/html2article/conv.go b/cmd/html2article/conv.go
new file mode 100644
index 0000000..d3267d7
--- /dev/null
+++ b/cmd/html2article/conv.go
@@ -0,0 +1,366 @@
+// Copyright 2013 The Go 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 program takes an HTML file and outputs a corresponding article file in
+// present format. See: golang.org/x/tools/present
+package main // import "golang.org/x/tools/cmd/html2article"
+
+import (
+	"bufio"
+	"bytes"
+	"errors"
+	"flag"
+	"fmt"
+	"io"
+	"log"
+	"net/url"
+	"os"
+	"regexp"
+	"strings"
+
+	"golang.org/x/net/html"
+	"golang.org/x/net/html/atom"
+)
+
+func main() {
+	flag.Parse()
+
+	err := convert(os.Stdout, os.Stdin)
+	if err != nil {
+		log.Fatal(err)
+	}
+}
+
+func convert(w io.Writer, r io.Reader) error {
+	root, err := html.Parse(r)
+	if err != nil {
+		return err
+	}
+
+	style := find(root, isTag(atom.Style))
+	parseStyles(style)
+
+	body := find(root, isTag(atom.Body))
+	if body == nil {
+		return errors.New("couldn't find body")
+	}
+	article := limitNewlineRuns(makeHeadings(strings.TrimSpace(text(body))))
+	_, err = fmt.Fprintf(w, "Title\n\n%s", article)
+	return err
+}
+
+type Style string
+
+const (
+	Bold   Style = "*"
+	Italic Style = "_"
+	Code   Style = "`"
+)
+
+var cssRules = make(map[string]Style)
+
+func parseStyles(style *html.Node) {
+	if style == nil || style.FirstChild == nil {
+		log.Println("couldn't find styles")
+		return
+	}
+	s := bufio.NewScanner(strings.NewReader(style.FirstChild.Data))
+
+	findRule := func(b []byte, atEOF bool) (advance int, token []byte, err error) {
+		if i := bytes.Index(b, []byte("{")); i >= 0 {
+			token = bytes.TrimSpace(b[:i])
+			advance = i
+		}
+		return
+	}
+	findBody := func(b []byte, atEOF bool) (advance int, token []byte, err error) {
+		if len(b) == 0 {
+			return
+		}
+		if b[0] != '{' {
+			err = fmt.Errorf("expected {, got %c", b[0])
+			return
+		}
+		if i := bytes.Index(b, []byte("}")); i < 0 {
+			err = fmt.Errorf("can't find closing }")
+			return
+		} else {
+			token = b[1:i]
+			advance = i + 1
+		}
+		return
+	}
+
+	s.Split(findRule)
+	for s.Scan() {
+		rule := s.Text()
+		s.Split(findBody)
+		if !s.Scan() {
+			break
+		}
+		b := strings.ToLower(s.Text())
+		switch {
+		case strings.Contains(b, "italic"):
+			cssRules[rule] = Italic
+		case strings.Contains(b, "bold"):
+			cssRules[rule] = Bold
+		case strings.Contains(b, "Consolas") || strings.Contains(b, "Courier New"):
+			cssRules[rule] = Code
+		}
+		s.Split(findRule)
+	}
+	if err := s.Err(); err != nil {
+		log.Println(err)
+	}
+}
+
+var newlineRun = regexp.MustCompile(`\n\n+`)
+
+func limitNewlineRuns(s string) string {
+	return newlineRun.ReplaceAllString(s, "\n\n")
+}
+
+func makeHeadings(body string) string {
+	buf := new(bytes.Buffer)
+	lines := strings.Split(body, "\n")
+	for i, s := range lines {
+		if i == 0 && !isBoldTitle(s) {
+			buf.WriteString("* Introduction\n\n")
+		}
+		if isBoldTitle(s) {
+			s = strings.TrimSpace(strings.Replace(s, "*", " ", -1))
+			s = "* " + s
+		}
+		buf.WriteString(s)
+		buf.WriteByte('\n')
+	}
+	return buf.String()
+}
+
+func isBoldTitle(s string) bool {
+	return !strings.Contains(s, " ") &&
+		strings.HasPrefix(s, "*") &&
+		strings.HasSuffix(s, "*")
+}
+
+func indent(buf *bytes.Buffer, s string) {
+	for _, l := range strings.Split(s, "\n") {
+		if l != "" {
+			buf.WriteByte('\t')
+			buf.WriteString(l)
+		}
+		buf.WriteByte('\n')
+	}
+}
+
+func unwrap(buf *bytes.Buffer, s string) {
+	var cont bool
+	for _, l := range strings.Split(s, "\n") {
+		l = strings.TrimSpace(l)
+		if len(l) == 0 {
+			if cont {
+				buf.WriteByte('\n')
+				buf.WriteByte('\n')
+			}
+			cont = false
+		} else {
+			if cont {
+				buf.WriteByte(' ')
+			}
+			buf.WriteString(l)
+			cont = true
+		}
+	}
+}
+
+func text(n *html.Node) string {
+	var buf bytes.Buffer
+	walk(n, func(n *html.Node) bool {
+		switch n.Type {
+		case html.TextNode:
+			buf.WriteString(n.Data)
+			return false
+		case html.ElementNode:
+			// no-op
+		default:
+			return true
+		}
+		a := n.DataAtom
+		if a == atom.Span {
+			switch {
+			case hasStyle(Code)(n):
+				a = atom.Code
+			case hasStyle(Bold)(n):
+				a = atom.B
+			case hasStyle(Italic)(n):
+				a = atom.I
+			}
+		}
+		switch a {
+		case atom.Br:
+			buf.WriteByte('\n')
+		case atom.P:
+			unwrap(&buf, childText(n))
+			buf.WriteString("\n\n")
+		case atom.Li:
+			buf.WriteString("- ")
+			unwrap(&buf, childText(n))
+			buf.WriteByte('\n')
+		case atom.Pre:
+			indent(&buf, childText(n))
+			buf.WriteByte('\n')
+		case atom.A:
+			href, text := attr(n, "href"), childText(n)
+			// Skip links with no text.
+			if strings.TrimSpace(text) == "" {
+				break
+			}
+			// Don't emit empty links.
+			if strings.TrimSpace(href) == "" {
+				buf.WriteString(text)
+				break
+			}
+			// Use original url for Google Docs redirections.
+			if u, err := url.Parse(href); err != nil {
+				log.Printf("parsing url %q: %v", href, err)
+			} else if u.Host == "www.google.com" && u.Path == "/url" {
+				href = u.Query().Get("q")
+			}
+			fmt.Fprintf(&buf, "[[%s][%s]]", href, text)
+		case atom.Code:
+			buf.WriteString(highlight(n, "`"))
+		case atom.B:
+			buf.WriteString(highlight(n, "*"))
+		case atom.I:
+			buf.WriteString(highlight(n, "_"))
+		case atom.Img:
+			src := attr(n, "src")
+			fmt.Fprintf(&buf, ".image %s\n", src)
+		case atom.Iframe:
+			src, w, h := attr(n, "src"), attr(n, "width"), attr(n, "height")
+			fmt.Fprintf(&buf, "\n.iframe %s %s %s\n", src, h, w)
+		case atom.Param:
+			if attr(n, "name") == "movie" {
+				// Old style YouTube embed.
+				u := attr(n, "value")
+				u = strings.Replace(u, "/v/", "/embed/", 1)
+				if i := strings.Index(u, "&"); i >= 0 {
+					u = u[:i]
+				}
+				fmt.Fprintf(&buf, "\n.iframe %s 540 304\n", u)
+			}
+		case atom.Title:
+		default:
+			return true
+		}
+		return false
+	})
+	return buf.String()
+}
+
+func childText(node *html.Node) string {
+	var buf bytes.Buffer
+	for n := node.FirstChild; n != nil; n = n.NextSibling {
+		fmt.Fprint(&buf, text(n))
+	}
+	return buf.String()
+}
+
+func highlight(node *html.Node, char string) string {
+	t := strings.Replace(childText(node), " ", char, -1)
+	return fmt.Sprintf("%s%s%s", char, t, char)
+}
+
+type selector func(*html.Node) bool
+
+func isTag(a atom.Atom) selector {
+	return func(n *html.Node) bool {
+		return n.DataAtom == a
+	}
+}
+
+func hasClass(name string) selector {
+	return func(n *html.Node) bool {
+		for _, a := range n.Attr {
+			if a.Key == "class" {
+				for _, c := range strings.Fields(a.Val) {
+					if c == name {
+						return true
+					}
+				}
+			}
+		}
+		return false
+	}
+}
+
+func hasStyle(s Style) selector {
+	return func(n *html.Node) bool {
+		for rule, s2 := range cssRules {
+			if s2 != s {
+				continue
+			}
+			if strings.HasPrefix(rule, ".") && hasClass(rule[1:])(n) {
+				return true
+			}
+			if n.DataAtom.String() == rule {
+				return true
+			}
+		}
+		return false
+	}
+}
+
+func hasAttr(key, val string) selector {
+	return func(n *html.Node) bool {
+		for _, a := range n.Attr {
+			if a.Key == key && a.Val == val {
+				return true
+			}
+		}
+		return false
+	}
+}
+
+func attr(node *html.Node, key string) (value string) {
+	for _, attr := range node.Attr {
+		if attr.Key == key {
+			return attr.Val
+		}
+	}
+	return ""
+}
+
+func findAll(node *html.Node, fn selector) (nodes []*html.Node) {
+	walk(node, func(n *html.Node) bool {
+		if fn(n) {
+			nodes = append(nodes, n)
+		}
+		return true
+	})
+	return
+}
+
+func find(n *html.Node, fn selector) *html.Node {
+	var result *html.Node
+	walk(n, func(n *html.Node) bool {
+		if result != nil {
+			return false
+		}
+		if fn(n) {
+			result = n
+			return false
+		}
+		return true
+	})
+	return result
+}
+
+func walk(n *html.Node, fn selector) {
+	if fn(n) {
+		for c := n.FirstChild; c != nil; c = c.NextSibling {
+			walk(c, fn)
+		}
+	}
+}
diff --git a/cmd/oracle/emacs-test.bash b/cmd/oracle/emacs-test.bash
new file mode 100755
index 0000000..8c39091
--- /dev/null
+++ b/cmd/oracle/emacs-test.bash
@@ -0,0 +1,50 @@
+#!/bin/bash
+#
+# Simple test of Go oracle/Emacs integration.
+# Requires that GOROOT and GOPATH are set.
+# Side effect: builds and installs oracle in $GOROOT.
+
+set -eu
+
+[ -z "$GOROOT" ] && { echo "Error: GOROOT is unset." >&2; exit 1; }
+[ -z "$GOPATH" ] && { echo "Error: GOPATH is unset." >&2; exit 1; }
+
+log=/tmp/$(basename $0)-$$.log
+thisdir=$(dirname $0)
+
+function die() {
+  echo "Error: $@."
+  cat $log
+  exit 1
+} >&2
+
+trap "rm -f $log" EXIT
+
+# Build and install oracle.
+go get golang.org/x/tools/cmd/oracle || die "'go get' failed"
+mv -f $GOPATH/bin/oracle $GOROOT/bin/
+$GOROOT/bin/oracle >$log 2>&1 || true # (prints usage and exits 1)
+grep -q "Run.*help" $log || die "$GOROOT/bin/oracle not installed"
+
+
+# Run Emacs, set the scope to the oracle tool itself,
+# load ./main.go, and describe the "fmt" import.
+emacs --batch --no-splash --no-window-system --no-init \
+    --load $GOROOT/misc/emacs/go-mode.el \
+    --load $thisdir/oracle.el \
+    --eval '
+(progn
+  (setq go-oracle-scope "golang.org/x/tools/cmd/oracle")
+  (find-file "'$thisdir'/main.go")
+  (search-forward "\"fmt\"")
+  (backward-char)
+  (go-oracle-describe)
+  (princ (with-current-buffer "*go-oracle*"
+                              (buffer-substring-no-properties (point-min) (point-max))))
+  (kill-emacs 0))
+' main.go >$log 2>&1 || die "emacs command failed"
+
+# Check that Println is mentioned.
+grep -q "fmt/print.go.*func  Println" $log || die "didn't find expected lines in log; got:"
+
+echo "PASS"
diff --git a/cmd/oracle/main.go b/cmd/oracle/main.go
new file mode 100644
index 0000000..a7a1661
--- /dev/null
+++ b/cmd/oracle/main.go
@@ -0,0 +1,204 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// oracle: a tool for answering questions about Go source code.
+// http://golang.org/s/oracle-design
+// http://golang.org/s/oracle-user-manual
+//
+// Run with -help flag or help subcommand for usage information.
+//
+package main // import "golang.org/x/tools/cmd/oracle"
+
+import (
+	"bufio"
+	"encoding/json"
+	"encoding/xml"
+	"flag"
+	"fmt"
+	"go/build"
+	"io"
+	"log"
+	"os"
+	"runtime"
+	"runtime/pprof"
+
+	"golang.org/x/tools/go/buildutil"
+	"golang.org/x/tools/go/loader"
+	"golang.org/x/tools/oracle"
+)
+
+var posFlag = flag.String("pos", "",
+	"Filename and byte offset or extent of a syntax element about which to query, "+
+		"e.g. foo.go:#123,#456, bar.go:#123.")
+
+var ptalogFlag = flag.String("ptalog", "",
+	"Location of the points-to analysis log file, or empty to disable logging.")
+
+var formatFlag = flag.String("format", "plain", "Output format.  One of {plain,json,xml}.")
+
+var reflectFlag = flag.Bool("reflect", false, "Analyze reflection soundly (slow).")
+
+func init() {
+	flag.Var((*buildutil.TagsFlag)(&build.Default.BuildTags), "tags", buildutil.TagsFlagDoc)
+}
+
+const useHelp = "Run 'oracle -help' for more information.\n"
+
+const helpMessage = `Go source code oracle.
+Usage: oracle [<flag> ...] <mode> <args> ...
+
+The -format flag controls the output format:
+	plain	an editor-friendly format in which every line of output
+		is of the form "pos: text", where pos is "-" if unknown.
+	json	structured data in JSON syntax.
+	xml	structured data in XML syntax.
+
+The -pos flag is required in all modes.
+
+The mode argument determines the query to perform:
+
+	callees	  	show possible targets of selected function call
+	callers	  	show possible callers of selected function
+	callstack 	show path from callgraph root to selected function
+	definition	show declaration of selected identifier
+	describe  	describe selected syntax: definition, methods, etc
+	freevars  	show free variables of selection
+	implements	show 'implements' relation for selected type or method
+	peers     	show send/receive corresponding to selected channel op
+	referrers 	show all refs to entity denoted by selected identifier
+	what		show basic information about the selected syntax node
+
+The user manual is available here:  http://golang.org/s/oracle-user-manual
+
+Examples:
+
+Describe the syntax at offset 530 in this file (an import spec):
+% oracle -pos=src/golang.org/x/tools/cmd/oracle/main.go:#530 describe \
+   golang.org/x/tools/cmd/oracle
+
+Print the callgraph of the trivial web-server in JSON format:
+% oracle -format=json $GOROOT/src/net/http/triv.go callgraph
+` + loader.FromArgsUsage
+
+var cpuprofile = flag.String("cpuprofile", "", "write cpu profile to file")
+
+func init() {
+	// If $GOMAXPROCS isn't set, use the full capacity of the machine.
+	// For small machines, use at least 4 threads.
+	if os.Getenv("GOMAXPROCS") == "" {
+		n := runtime.NumCPU()
+		if n < 4 {
+			n = 4
+		}
+		runtime.GOMAXPROCS(n)
+	}
+}
+
+func printHelp() {
+	fmt.Fprintln(os.Stderr, helpMessage)
+	fmt.Fprintln(os.Stderr, "Flags:")
+	flag.PrintDefaults()
+}
+
+func main() {
+	// Don't print full help unless -help was requested.
+	// Just gently remind users that it's there.
+	flag.Usage = func() { fmt.Fprint(os.Stderr, useHelp) }
+	flag.CommandLine.Init(os.Args[0], flag.ContinueOnError) // hack
+	if err := flag.CommandLine.Parse(os.Args[1:]); err != nil {
+		// (err has already been printed)
+		if err == flag.ErrHelp {
+			printHelp()
+		}
+		os.Exit(2)
+	}
+
+	args := flag.Args()
+	if len(args) == 0 || args[0] == "" {
+		fmt.Fprint(os.Stderr, "oracle: a mode argument is required.\n"+useHelp)
+		os.Exit(2)
+	}
+
+	mode := args[0]
+	args = args[1:]
+	if mode == "help" {
+		printHelp()
+		os.Exit(2)
+	}
+
+	// Set up points-to analysis log file.
+	var ptalog io.Writer
+	if *ptalogFlag != "" {
+		if f, err := os.Create(*ptalogFlag); err != nil {
+			log.Fatalf("Failed to create PTA log file: %s", err)
+		} else {
+			buf := bufio.NewWriter(f)
+			ptalog = buf
+			defer func() {
+				if err := buf.Flush(); err != nil {
+					log.Printf("flush: %s", err)
+				}
+				if err := f.Close(); err != nil {
+					log.Printf("close: %s", err)
+				}
+			}()
+		}
+	}
+
+	// Profiling support.
+	if *cpuprofile != "" {
+		f, err := os.Create(*cpuprofile)
+		if err != nil {
+			log.Fatal(err)
+		}
+		pprof.StartCPUProfile(f)
+		defer pprof.StopCPUProfile()
+	}
+
+	// -format flag
+	switch *formatFlag {
+	case "json", "plain", "xml":
+		// ok
+	default:
+		fmt.Fprintf(os.Stderr, "oracle: illegal -format value: %q.\n"+useHelp, *formatFlag)
+		os.Exit(2)
+	}
+
+	// Ask the oracle.
+	query := oracle.Query{
+		Mode:       mode,
+		Pos:        *posFlag,
+		Build:      &build.Default,
+		Scope:      args,
+		PTALog:     ptalog,
+		Reflection: *reflectFlag,
+	}
+
+	if err := oracle.Run(&query); err != nil {
+		fmt.Fprintf(os.Stderr, "oracle: %s\n", err)
+		os.Exit(1)
+	}
+
+	// Print the result.
+	switch *formatFlag {
+	case "json":
+		b, err := json.MarshalIndent(query.Serial(), "", "\t")
+		if err != nil {
+			fmt.Fprintf(os.Stderr, "oracle: JSON error: %s\n", err)
+			os.Exit(1)
+		}
+		os.Stdout.Write(b)
+
+	case "xml":
+		b, err := xml.MarshalIndent(query.Serial(), "", "\t")
+		if err != nil {
+			fmt.Fprintf(os.Stderr, "oracle: XML error: %s\n", err)
+			os.Exit(1)
+		}
+		os.Stdout.Write(b)
+
+	case "plain":
+		query.WriteTo(os.Stdout)
+	}
+}
diff --git a/cmd/oracle/oracle.el b/cmd/oracle/oracle.el
new file mode 100644
index 0000000..33c7409
--- /dev/null
+++ b/cmd/oracle/oracle.el
@@ -0,0 +1,230 @@
+;;;
+;;; Integration of the Go 'oracle' analysis tool into Emacs.
+;;;
+;;; To install the Go oracle, run:
+;;; % export GOROOT=... GOPATH=...
+;;; % go get golang.org/x/tools/cmd/oracle
+;;; % mv $GOPATH/bin/oracle $GOROOT/bin/
+;;;
+;;; Load this file into Emacs and set go-oracle-scope to your
+;;; configuration. Then, find a file of Go source code, enable
+;;; go-oracle-mode, select an expression of interest, and press `C-c C-o d'
+;;; (for "describe") or run one of the other go-oracle-xxx commands.
+;;;
+;;; TODO(adonovan): simplify installation and configuration by making
+;;; oracle a subcommand of 'go tool'.
+
+(require 'compile)
+(require 'go-mode)
+(require 'cl)
+
+(defgroup go-oracle nil
+  "Options specific to the Go oracle."
+  :group 'go)
+
+(defcustom go-oracle-command "oracle"
+  "The Go oracle command."
+  :type 'string
+  :group 'go-oracle)
+
+(defcustom go-oracle-scope ""
+  "The scope of the analysis.  See `go-oracle-set-scope'."
+  :type 'string
+  :group 'go-oracle)
+
+(defvar go-oracle--scope-history
+  nil
+  "History of values supplied to `go-oracle-set-scope'.")
+
+;; Extend go-mode-map.
+(let ((m go-mode-map))
+  (define-key m (kbd "C-c C-o t") #'go-oracle-describe) ; t for type
+  (define-key m (kbd "C-c C-o f") #'go-oracle-freevars)
+  (define-key m (kbd "C-c C-o g") #'go-oracle-callgraph)
+  (define-key m (kbd "C-c C-o i") #'go-oracle-implements)
+  (define-key m (kbd "C-c C-o c") #'go-oracle-peers)  ; c for channel
+  (define-key m (kbd "C-c C-o r") #'go-oracle-referrers)
+  (define-key m (kbd "C-c C-o d") #'go-oracle-definition)
+  (define-key m (kbd "C-c C-o p") #'go-oracle-pointsto)
+  (define-key m (kbd "C-c C-o s") #'go-oracle-callstack)
+  (define-key m (kbd "C-c C-o <") #'go-oracle-callers)
+  (define-key m (kbd "C-c C-o >") #'go-oracle-callees)
+  (define-key m (kbd "<f5>") #'go-oracle-describe)
+  (define-key m (kbd "<f6>") #'go-oracle-referrers))
+
+;; TODO(dominikh): Rethink set-scope some. Setting it to a file is
+;; painful because it doesn't use find-file, and variables/~ aren't
+;; expanded. Setting it to an import path is somewhat painful because
+;; it doesn't make use of go-mode's import path completion. One option
+;; would be having two different functions, but then we can't
+;; automatically call it when no scope has been set. Also it wouldn't
+;; easily allow specifying more than one file/package.
+(defun go-oracle-set-scope ()
+  "Set the scope for the Go oracle, prompting the user to edit the
+previous scope.
+
+The scope specifies a set of arguments, separated by spaces.
+It may be:
+1) a set of packages whose main() functions will be analyzed.
+2) a list of *.go filenames; they will treated like as a single
+   package (see #3).
+3) a single package whose main() function and/or Test* functions
+   will be analyzed.
+
+In the common case, this is similar to the argument(s) you would
+specify to 'go build'."
+  (interactive)
+  (let ((scope (read-from-minibuffer "Go oracle scope: "
+                                     go-oracle-scope
+                                     nil
+                                     nil
+                                     'go-oracle--scope-history)))
+    (if (string-equal "" scope)
+        (error "You must specify a non-empty scope for the Go oracle"))
+    (setq go-oracle-scope scope)))
+
+(defun go-oracle--run (mode &optional need-scope)
+  "Run the Go oracle in the specified MODE, passing it the
+selected region of the current buffer.  If NEED-SCOPE, prompt for
+a scope if not already set.  Process the output to replace each
+file name with a small hyperlink.  Display the result."
+  (if (not buffer-file-name)
+      (error "Cannot use oracle on a buffer without a file name"))
+  ;; It's not sufficient to save a modified buffer since if
+  ;; gofmt-before-save is on the before-save-hook, saving will
+  ;; disturb the selected region.
+  (if (buffer-modified-p)
+      (error "Please save the buffer before invoking go-oracle"))
+  (and need-scope
+       (string-equal "" go-oracle-scope)
+       (go-oracle-set-scope))
+  (let* ((filename (file-truename buffer-file-name))
+         (posflag (if (use-region-p)
+                      (format "-pos=%s:#%d,#%d"
+                              filename
+                              (1- (go--position-bytes (region-beginning)))
+                              (1- (go--position-bytes (region-end))))
+                    (format "-pos=%s:#%d"
+                            filename
+                            (1- (position-bytes (point))))))
+         (env-vars (go-root-and-paths))
+         (goroot-env (concat "GOROOT=" (car env-vars)))
+         (gopath-env (concat "GOPATH=" (mapconcat #'identity (cdr env-vars) ":"))))
+    (with-current-buffer (get-buffer-create "*go-oracle*")
+      (setq buffer-read-only nil)
+      (erase-buffer)
+      (insert "Go Oracle\n")
+      (let ((args (append (list go-oracle-command nil t nil posflag mode)
+                          (split-string go-oracle-scope " " t))))
+        ;; Log the command to *Messages*, for debugging.
+        (message "Command: %s:" args)
+        (message nil) ; clears/shrinks minibuffer
+
+        (message "Running oracle...")
+        ;; Use dynamic binding to modify/restore the environment
+        (let ((process-environment (list* goroot-env gopath-env process-environment)))
+            (apply #'call-process args)))
+      (insert "\n")
+      (compilation-mode)
+      (setq compilation-error-screen-columns nil)
+
+      ;; Hide the file/line info to save space.
+      ;; Replace each with a little widget.
+      ;; compilation-mode + this loop = slooow.
+      ;; TODO(adonovan): have oracle give us JSON
+      ;; and we'll do the markup directly.
+      (let ((buffer-read-only nil)
+            (p 1))
+        (while (not (null p))
+          (let ((np (compilation-next-single-property-change p 'compilation-message)))
+            (if np
+                (when (equal (line-number-at-pos p) (line-number-at-pos np))
+                  ;; Using a fixed width greatly improves readability, so
+                  ;; if the filename is longer than 20, show ".../last/17chars.go".
+                  ;; This usually includes the last segment of the package name.
+                  ;; Don't show the line or column number.
+                  (let* ((loc (buffer-substring p np)) ; "/home/foo/go/pkg/file.go:1:2-3:4"
+                         (i (search ":" loc)))
+                    (setq loc (cond
+                               ((null i)  "...")
+                               ((>= i 17) (concat "..." (substring loc (- i 17) i)))
+                               (t         (substring loc 0 i))))
+                    ;; np is (typically) the space following ":"; consume it too.
+                    (put-text-property p np 'display (concat loc ":")))
+                  (goto-char np)
+                  (insert " ")
+                  (incf np))) ; so we don't get stuck (e.g. on a panic stack dump)
+            (setq p np)))
+        (message nil))
+
+      (let ((w (display-buffer (current-buffer))))
+        (balance-windows)
+        (shrink-window-if-larger-than-buffer w)
+        (set-window-point w (point-min))))))
+
+(defun go-oracle-callees ()
+  "Show possible callees of the function call at the current point."
+  (interactive)
+  (go-oracle--run "callees" t))
+
+(defun go-oracle-callers ()
+  "Show the set of callers of the function containing the current point."
+  (interactive)
+  (go-oracle--run "callers" t))
+
+(defun go-oracle-callgraph ()
+  "Show the callgraph of the current program."
+  (interactive)
+  (go-oracle--run "callgraph" t))
+
+(defun go-oracle-callstack ()
+  "Show an arbitrary path from a root of the call graph to the
+function containing the current point."
+  (interactive)
+  (go-oracle--run "callstack" t))
+
+(defun go-oracle-definition ()
+  "Show the definition of the selected identifier."
+  (interactive)
+  (go-oracle--run "definition"))
+
+(defun go-oracle-describe ()
+  "Describe the selected syntax, its kind, type and methods."
+  (interactive)
+  (go-oracle--run "describe"))
+
+(defun go-oracle-pointsto ()
+  "Show what the selected expression points to."
+  (interactive)
+  (go-oracle--run "pointsto" t))
+
+(defun go-oracle-implements ()
+  "Describe the 'implements' relation for types in the package
+containing the current point."
+  (interactive)
+  (go-oracle--run "implements"))
+
+(defun go-oracle-freevars ()
+  "Enumerate the free variables of the current selection."
+  (interactive)
+  (go-oracle--run "freevars"))
+
+(defun go-oracle-peers ()
+  "Enumerate the set of possible corresponding sends/receives for
+this channel receive/send operation."
+  (interactive)
+  (go-oracle--run "peers" t))
+
+(defun go-oracle-referrers ()
+  "Enumerate all references to the object denoted by the selected
+identifier."
+  (interactive)
+  (go-oracle--run "referrers"))
+
+(defun go-oracle-whicherrs ()
+  "Show globals, constants and types to which the selected
+expression (of type 'error') may refer."
+  (interactive)
+  (go-oracle--run "whicherrs" t))
+
+(provide 'go-oracle)
diff --git a/cmd/oracle/oracle.vim b/cmd/oracle/oracle.vim
new file mode 100644
index 0000000..cadda78
--- /dev/null
+++ b/cmd/oracle/oracle.vim
@@ -0,0 +1,107 @@
+" -*- text -*-
+"  oracle.vim -- Vim integration for the Go oracle.
+"
+"  Load with (e.g.)  :source oracle.vim
+"  Call with (e.g.)  :GoOracleDescribe
+"  while cursor or selection is over syntax of interest.
+"  Run :copen to show the quick-fix file.
+"
+" This is an absolutely rudimentary integration of the Go Oracle into
+" Vim's quickfix mechanism and it needs a number of usability
+" improvements before it can be practically useful to Vim users.
+" Voluntary contributions welcomed!
+"
+" TODO(adonovan):
+" - reject buffers with no filename.
+" - hide all filenames in quickfix buffer.
+
+" Get the path to the Go oracle executable.
+func! s:go_oracle_bin()
+  let [ext, sep] = (has('win32') || has('win64') ? ['.exe', ';'] : ['', ':'])
+  let go_oracle = globpath(join(split($GOPATH, sep), ','), '/bin/oracle' . ext)
+  if go_oracle == ''
+    let go_oracle = globpath($GOROOT, '/bin/oracle' . ext)
+  endif
+  return go_oracle
+endfunction
+
+let s:go_oracle = s:go_oracle_bin()
+
+func! s:qflist(output)
+  let qflist = []
+  " Parse GNU-style 'file:line.col-line.col: message' format.
+  let mx = '^\(\a:[\\/][^:]\+\|[^:]\+\):\(\d\+\):\(\d\+\):\(.*\)$'
+  for line in split(a:output, "\n")
+    let ml = matchlist(line, mx)
+    " Ignore non-match lines or warnings
+    if ml == [] || ml[4] =~ '^ warning:'
+      continue
+    endif
+    let item = {
+    \  'filename': ml[1],
+    \  'text': ml[4],
+    \  'lnum': ml[2],
+    \  'col': ml[3],
+    \}
+    let bnr = bufnr(fnameescape(ml[1]))
+    if bnr != -1
+      let item['bufnr'] = bnr
+    endif
+    call add(qflist, item)
+  endfor
+  call setqflist(qflist)
+  cwindow
+endfun
+
+func! s:getpos(l, c)
+  if &encoding != 'utf-8'
+    let buf = a:l == 1 ? '' : (join(getline(1, a:l-1), "\n") . "\n")
+    let buf .= a:c == 1 ? '' : getline('.')[:a:c-2]
+    return len(iconv(buf, &encoding, 'utf-8'))
+  endif
+  return line2byte(a:l) + (a:c-2)
+endfun
+
+func! s:RunOracle(mode, selected) range abort
+  let fname = expand('%:p')
+  let sname = get(g:, 'go_oracle_scope_file', fname)
+  if a:selected != -1
+    let pos1 = s:getpos(line("'<"), col("'<"))
+    let pos2 = s:getpos(line("'>"), col("'>"))
+    let cmd = printf('%s -pos=%s:#%d,#%d %s %s',
+      \  s:go_oracle,
+      \  shellescape(fname), pos1, pos2, a:mode, shellescape(sname))
+  else
+    let pos = s:getpos(line('.'), col('.'))
+    let cmd = printf('%s -pos=%s:#%d %s %s',
+      \  s:go_oracle,
+      \  shellescape(fname), pos, a:mode, shellescape(sname))
+  endif
+  call s:qflist(system(cmd))
+endfun
+
+" Describe the expression at the current point.
+command! -range=% GoOracleDescribe
+  \ call s:RunOracle('describe', <count>)
+
+" Show possible callees of the function call at the current point.
+command! -range=% GoOracleCallees
+  \ call s:RunOracle('callees', <count>)
+
+" Show the set of callers of the function containing the current point.
+command! -range=% GoOracleCallers
+  \ call s:RunOracle('callers', <count>)
+
+" Show the callgraph of the current program.
+command! -range=% GoOracleCallgraph
+  \ call s:RunOracle('callgraph', <count>)
+
+" Describe the 'implements' relation for types in the
+" package containing the current point.
+command! -range=% GoOracleImplements
+  \ call s:RunOracle('implements', <count>)
+
+" Enumerate the set of possible corresponding sends/receives for
+" this channel receive/send operation.
+command! -range=% GoOracleChannelPeers
+  \ call s:RunOracle('peers', <count>)
diff --git a/cmd/present/appengine.go b/cmd/present/appengine.go
new file mode 100644
index 0000000..7df536c
--- /dev/null
+++ b/cmd/present/appengine.go
@@ -0,0 +1,30 @@
+// Copyright 2012 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build appengine
+
+package main
+
+import (
+	"mime"
+
+	"golang.org/x/tools/present"
+
+	_ "golang.org/x/tools/playground"
+)
+
+var basePath = "./present/"
+
+func init() {
+	initTemplates(basePath)
+	playScript(basePath, "HTTPTransport")
+	present.PlayEnabled = true
+
+	// App Engine has no /etc/mime.types
+	mime.AddExtensionType(".svg", "image/svg+xml")
+}
+
+func playable(c present.Code) bool {
+	return present.PlayEnabled && c.Play && c.Ext == ".go"
+}
diff --git a/cmd/present/dir.go b/cmd/present/dir.go
new file mode 100644
index 0000000..6845a21
--- /dev/null
+++ b/cmd/present/dir.go
@@ -0,0 +1,213 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+	"html/template"
+	"io"
+	"log"
+	"net/http"
+	"os"
+	"path/filepath"
+	"sort"
+
+	"golang.org/x/tools/present"
+)
+
+func init() {
+	http.HandleFunc("/", dirHandler)
+}
+
+// dirHandler serves a directory listing for the requested path, rooted at basePath.
+func dirHandler(w http.ResponseWriter, r *http.Request) {
+	if r.URL.Path == "/favicon.ico" {
+		http.Error(w, "not found", 404)
+		return
+	}
+	const base = "."
+	name := filepath.Join(base, r.URL.Path)
+	if isDoc(name) {
+		err := renderDoc(w, name)
+		if err != nil {
+			log.Println(err)
+			http.Error(w, err.Error(), 500)
+		}
+		return
+	}
+	if isDir, err := dirList(w, name); err != nil {
+		log.Println(err)
+		http.Error(w, err.Error(), 500)
+		return
+	} else if isDir {
+		return
+	}
+	http.FileServer(http.Dir(base)).ServeHTTP(w, r)
+}
+
+func isDoc(path string) bool {
+	_, ok := contentTemplate[filepath.Ext(path)]
+	return ok
+}
+
+var (
+	// dirListTemplate holds the front page template.
+	dirListTemplate *template.Template
+
+	// contentTemplate maps the presentable file extensions to the
+	// template to be executed.
+	contentTemplate map[string]*template.Template
+)
+
+func initTemplates(base string) error {
+	// Locate the template file.
+	actionTmpl := filepath.Join(base, "templates/action.tmpl")
+
+	contentTemplate = make(map[string]*template.Template)
+
+	for ext, contentTmpl := range map[string]string{
+		".slide":   "slides.tmpl",
+		".article": "article.tmpl",
+	} {
+		contentTmpl = filepath.Join(base, "templates", contentTmpl)
+
+		// Read and parse the input.
+		tmpl := present.Template()
+		tmpl = tmpl.Funcs(template.FuncMap{"playable": playable})
+		if _, err := tmpl.ParseFiles(actionTmpl, contentTmpl); err != nil {
+			return err
+		}
+		contentTemplate[ext] = tmpl
+	}
+
+	var err error
+	dirListTemplate, err = template.ParseFiles(filepath.Join(base, "templates/dir.tmpl"))
+	if err != nil {
+		return err
+	}
+
+	return nil
+}
+
+// renderDoc reads the present file, gets its template representation,
+// and executes the template, sending output to w.
+func renderDoc(w io.Writer, docFile string) error {
+	// Read the input and build the doc structure.
+	doc, err := parse(docFile, 0)
+	if err != nil {
+		return err
+	}
+
+	// Find which template should be executed.
+	tmpl := contentTemplate[filepath.Ext(docFile)]
+
+	// Execute the template.
+	return doc.Render(w, tmpl)
+}
+
+func parse(name string, mode present.ParseMode) (*present.Doc, error) {
+	f, err := os.Open(name)
+	if err != nil {
+		return nil, err
+	}
+	defer f.Close()
+	return present.Parse(f, name, 0)
+}
+
+// dirList scans the given path and writes a directory listing to w.
+// It parses the first part of each .slide file it encounters to display the
+// presentation title in the listing.
+// If the given path is not a directory, it returns (isDir == false, err == nil)
+// and writes nothing to w.
+func dirList(w io.Writer, name string) (isDir bool, err error) {
+	f, err := os.Open(name)
+	if err != nil {
+		return false, err
+	}
+	defer f.Close()
+	fi, err := f.Stat()
+	if err != nil {
+		return false, err
+	}
+	if isDir = fi.IsDir(); !isDir {
+		return false, nil
+	}
+	fis, err := f.Readdir(0)
+	if err != nil {
+		return false, err
+	}
+	d := &dirListData{Path: name}
+	for _, fi := range fis {
+		// skip the golang.org directory
+		if name == "." && fi.Name() == "golang.org" {
+			continue
+		}
+		e := dirEntry{
+			Name: fi.Name(),
+			Path: filepath.ToSlash(filepath.Join(name, fi.Name())),
+		}
+		if fi.IsDir() && showDir(e.Name) {
+			d.Dirs = append(d.Dirs, e)
+			continue
+		}
+		if isDoc(e.Name) {
+			if p, err := parse(e.Path, present.TitlesOnly); err != nil {
+				log.Println(err)
+			} else {
+				e.Title = p.Title
+			}
+			switch filepath.Ext(e.Path) {
+			case ".article":
+				d.Articles = append(d.Articles, e)
+			case ".slide":
+				d.Slides = append(d.Slides, e)
+			}
+		} else if showFile(e.Name) {
+			d.Other = append(d.Other, e)
+		}
+	}
+	if d.Path == "." {
+		d.Path = ""
+	}
+	sort.Sort(d.Dirs)
+	sort.Sort(d.Slides)
+	sort.Sort(d.Articles)
+	sort.Sort(d.Other)
+	return true, dirListTemplate.Execute(w, d)
+}
+
+// showFile reports whether the given file should be displayed in the list.
+func showFile(n string) bool {
+	switch filepath.Ext(n) {
+	case ".pdf":
+	case ".html":
+	case ".go":
+	default:
+		return isDoc(n)
+	}
+	return true
+}
+
+// showDir reports whether the given directory should be displayed in the list.
+func showDir(n string) bool {
+	if len(n) > 0 && (n[0] == '.' || n[0] == '_') || n == "present" {
+		return false
+	}
+	return true
+}
+
+type dirListData struct {
+	Path                          string
+	Dirs, Slides, Articles, Other dirEntrySlice
+}
+
+type dirEntry struct {
+	Name, Path, Title string
+}
+
+type dirEntrySlice []dirEntry
+
+func (s dirEntrySlice) Len() int           { return len(s) }
+func (s dirEntrySlice) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }
+func (s dirEntrySlice) Less(i, j int) bool { return s[i].Name < s[j].Name }
diff --git a/cmd/present/doc.go b/cmd/present/doc.go
new file mode 100644
index 0000000..fafcefe
--- /dev/null
+++ b/cmd/present/doc.go
@@ -0,0 +1,31 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+/*
+Present displays slide presentations and articles. It runs a web server that
+presents slide and article files from the current directory.
+
+It may be run as a stand-alone command or an App Engine app.
+Instructions for deployment to App Engine are in the README of the
+golang.org/x/tools repository.
+
+Usage of present:
+  -base="": base path for slide template and static resources
+  -http="127.0.0.1:3999": HTTP service address (e.g., '127.0.0.1:3999')
+  -nacl=false: use Native Client environment playground (prevents non-Go code execution)
+  -orighost="": host component of web origin URL (e.g., 'localhost')
+  -play=true: enable playground (permit execution of arbitrary user code)
+
+The setup of the Go version of NaCl is documented at:
+https://golang.org/wiki/NativeClient
+
+Input files are named foo.extension, where "extension" defines the format of
+the generated output. The supported formats are:
+	.slide        // HTML5 slide presentation
+	.article      // article format, such as a blog post
+
+The present file format is documented by the present package:
+http://godoc.org/golang.org/x/tools/present
+*/
+package main // import "golang.org/x/tools/cmd/present"
diff --git a/cmd/present/local.go b/cmd/present/local.go
new file mode 100644
index 0000000..d91dcc2
--- /dev/null
+++ b/cmd/present/local.go
@@ -0,0 +1,145 @@
+// Copyright 2013 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !appengine
+
+package main
+
+import (
+	"flag"
+	"fmt"
+	"go/build"
+	"log"
+	"net"
+	"net/http"
+	"net/url"
+	"os"
+	"runtime"
+	"strings"
+
+	"golang.org/x/tools/playground/socket"
+	"golang.org/x/tools/present"
+)
+
+const basePkg = "golang.org/x/tools/cmd/present"
+
+var basePath string
+
+func main() {
+	httpAddr := flag.String("http", "127.0.0.1:3999", "HTTP service address (e.g., '127.0.0.1:3999')")
+	originHost := flag.String("orighost", "", "host component of web origin URL (e.g., 'localhost')")
+	flag.StringVar(&basePath, "base", "", "base path for slide template and static resources")
+	flag.BoolVar(&present.PlayEnabled, "play", true, "enable playground (permit execution of arbitrary user code)")
+	nativeClient := flag.Bool("nacl", false, "use Native Client environment playground (prevents non-Go code execution)")
+	flag.Parse()
+
+	if basePath == "" {
+		p, err := build.Default.Import(basePkg, "", build.FindOnly)
+		if err != nil {
+			fmt.Fprintf(os.Stderr, "Couldn't find gopresent files: %v\n", err)
+			fmt.Fprintf(os.Stderr, basePathMessage, basePkg)
+			os.Exit(1)
+		}
+		basePath = p.Dir
+	}
+	err := initTemplates(basePath)
+	if err != nil {
+		log.Fatalf("Failed to parse templates: %v", err)
+	}
+
+	ln, err := net.Listen("tcp", *httpAddr)
+	if err != nil {
+		log.Fatal(err)
+	}
+	defer ln.Close()
+
+	_, port, err := net.SplitHostPort(ln.Addr().String())
+	if err != nil {
+		log.Fatal(err)
+	}
+	origin := &url.URL{Scheme: "http"}
+	if *originHost != "" {
+		origin.Host = net.JoinHostPort(*originHost, port)
+	} else if ln.Addr().(*net.TCPAddr).IP.IsUnspecified() {
+		name, _ := os.Hostname()
+		origin.Host = net.JoinHostPort(name, port)
+	} else {
+		reqHost, reqPort, err := net.SplitHostPort(*httpAddr)
+		if err != nil {
+			log.Fatal(err)
+		}
+		if reqPort == "0" {
+			origin.Host = net.JoinHostPort(reqHost, port)
+		} else {
+			origin.Host = *httpAddr
+		}
+	}
+
+	if present.PlayEnabled {
+		if *nativeClient {
+			socket.RunScripts = false
+			socket.Environ = func() []string {
+				if runtime.GOARCH == "amd64" {
+					return environ("GOOS=nacl", "GOARCH=amd64p32")
+				}
+				return environ("GOOS=nacl")
+			}
+		}
+		playScript(basePath, "SocketTransport")
+		http.Handle("/socket", socket.NewHandler(origin))
+	}
+	http.Handle("/static/", http.FileServer(http.Dir(basePath)))
+
+	if !ln.Addr().(*net.TCPAddr).IP.IsLoopback() &&
+		present.PlayEnabled && !*nativeClient {
+		log.Print(localhostWarning)
+	}
+
+	log.Printf("Open your web browser and visit %s", origin.String())
+	log.Fatal(http.Serve(ln, nil))
+}
+
+func playable(c present.Code) bool {
+	return present.PlayEnabled && c.Play
+}
+
+func environ(vars ...string) []string {
+	env := os.Environ()
+	for _, r := range vars {
+		k := strings.SplitAfter(r, "=")[0]
+		var found bool
+		for i, v := range env {
+			if strings.HasPrefix(v, k) {
+				env[i] = r
+				found = true
+			}
+		}
+		if !found {
+			env = append(env, r)
+		}
+	}
+	return env
+}
+
+const basePathMessage = `
+By default, gopresent locates the slide template files and associated
+static content by looking for a %q package
+in your Go workspaces (GOPATH).
+
+You may use the -base flag to specify an alternate location.
+`
+
+const localhostWarning = `
+WARNING!  WARNING!  WARNING!
+
+The present server appears to be listening on an address that is not localhost.
+Anyone with access to this address and port will have access to this machine as
+the user running present.
+
+To avoid this message, listen on localhost or run with -play=false.
+
+If you don't understand this message, hit Control-C to terminate this process.
+
+WARNING!  WARNING!  WARNING!
+`
diff --git a/cmd/present/play.go b/cmd/present/play.go
new file mode 100644
index 0000000..831b99f
--- /dev/null
+++ b/cmd/present/play.go
@@ -0,0 +1,43 @@
+// Copyright 2012 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+	"bytes"
+	"fmt"
+	"io/ioutil"
+	"net/http"
+	"path/filepath"
+	"time"
+
+	"golang.org/x/tools/godoc/static"
+)
+
+var scripts = []string{"jquery.js", "jquery-ui.js", "playground.js", "play.js"}
+
+// playScript registers an HTTP handler at /play.js that serves all the
+// scripts specified by the variable above, and appends a line that
+// initializes the playground with the specified transport.
+func playScript(root, transport string) {
+	modTime := time.Now()
+	var buf bytes.Buffer
+	for _, p := range scripts {
+		if s, ok := static.Files[p]; ok {
+			buf.WriteString(s)
+			continue
+		}
+		b, err := ioutil.ReadFile(filepath.Join(root, "static", p))
+		if err != nil {
+			panic(err)
+		}
+		buf.Write(b)
+	}
+	fmt.Fprintf(&buf, "\ninitPlayground(new %v());\n", transport)
+	b := buf.Bytes()
+	http.HandleFunc("/play.js", func(w http.ResponseWriter, r *http.Request) {
+		w.Header().Set("Content-type", "application/javascript")
+		http.ServeContent(w, r, "", modTime, bytes.NewReader(b))
+	})
+}
diff --git a/cmd/present/static/article.css b/cmd/present/static/article.css
new file mode 100644
index 0000000..e6ab1e8
--- /dev/null
+++ b/cmd/present/static/article.css
@@ -0,0 +1,136 @@
+body {
+	margin: 0;
+	font-family: Helvetica, Arial, sans-serif;
+	font-size: 16px;
+}
+pre,
+code {
+	font-family: Menlo, monospace;
+	font-size: 14px;
+}
+pre {
+	line-height: 18px;
+	margin: 0;
+	padding: 0;
+}
+a {
+	color: #375EAB;
+	text-decoration: none;
+}
+a:hover {
+	text-decoration: underline;
+}
+p, ul, ol {
+	margin: 20px;
+}
+
+h1, h2, h3, h4 {
+	margin: 20px 0;
+	padding: 0;
+	color: #375EAB;
+	font-weight: bold;
+}
+h1 {
+	font-size: 24px;
+}
+h2 {
+	font-size: 20px;
+	background: #E0EBF5;
+	padding: 2px 5px;
+}
+h3 {
+	font-size: 20px;
+}
+h3, h4 {
+	margin: 20px 5px;
+}
+h4 {
+	font-size: 16px;
+}
+
+div#heading {
+	float: left;
+	margin: 0 0 10px 0;
+	padding: 21px 0;
+	font-size: 20px;
+	font-weight: normal;
+}
+
+div#topbar {
+	background: #E0EBF5;
+	height: 64px;
+	overflow: hidden;
+}
+
+body {
+	text-align: center;
+}
+div#page {
+	width: 100%;
+}
+div#page > .container,
+div#topbar > .container {
+	text-align: left;
+	margin-left: auto;
+	margin-right: auto;
+	padding: 0 20px;
+	width: 900px;
+}
+div#page.wide > .container,
+div#topbar.wide > .container {
+	width: auto;
+}
+
+div#footer {
+	text-align: center;
+	color: #666;
+	font-size: 14px;
+	margin: 40px 0;
+}
+
+.author p {
+	margin: 20, 0, 0, 0px;
+}
+
+div.code,
+div.output {
+	margin: 20px;
+	padding: 10px;
+	-webkit-border-radius: 5px;
+	-moz-border-radius: 5px;
+	border-radius: 5px;
+}
+
+div.code { background: #e9e9e9; }
+div.output { background: black; }
+div.output .stdout { color: #e6e6e6; }
+div.output .stderr { color: rgb(244, 74, 63); }
+div.output .system { color: rgb(255, 209, 77) }
+
+.buttons {
+	margin-left: 20px;
+}
+div.output .buttons {
+	margin-left: 0;
+	margin-bottom: 10px;
+}
+
+#toc {
+	float: right;
+	margin: 0px 10px;
+	padding: 10px;
+	border: 1px solid #e5ecf9; 
+	background-color: white;
+	max-width: 33%;
+
+	-webkit-border-radius: 5px;
+	-moz-border-radius: 5px;
+	border-radius: 5px;
+}
+
+#toc ul, #toc a {
+	list-style-type: none;
+	padding-left: 10px;
+	color: black;
+	margin: 0px;
+}
diff --git a/cmd/present/static/dir.css b/cmd/present/static/dir.css
new file mode 100644
index 0000000..97587e6
--- /dev/null
+++ b/cmd/present/static/dir.css
@@ -0,0 +1,186 @@
+/* copied from $GOROOT/doc/style.css */
+
+body {
+	margin: 0;
+	font-family: Helvetica, Arial, sans-serif;
+	font-size: 16px;
+}
+pre,
+code {
+	font-family: Menlo, monospace;
+	font-size: 14px;
+}
+pre {
+	line-height: 18px;
+}
+pre .comment {
+	color: #375EAB;
+}
+pre .highlight,
+pre .highlight-comment,
+pre .selection-highlight,
+pre .selection-highlight-comment {
+	background: #FFFF00;
+}
+pre .selection,
+pre .selection-comment {
+	background: #FF9632;
+}
+pre .ln {
+	color: #999;
+}
+body {
+	color: #222;
+}
+a,
+.exampleHeading .text {
+	color: #375EAB;
+	text-decoration: none;
+}
+a:hover,
+.exampleHeading .text:hover {
+	text-decoration: underline;
+}
+p,
+pre,
+ul,
+ol {
+	margin: 20px;
+}
+pre {
+	background: #e9e9e9;
+	padding: 10px;
+
+	-webkit-border-radius: 5px;
+	-moz-border-radius: 5px;
+	border-radius: 5px;
+}
+
+h1,
+h2,
+h3,
+h4,
+.rootHeading {
+	margin: 20px 0;
+	padding: 0;
+	color: #375EAB;
+	font-weight: bold;
+}
+h1 {
+	font-size: 24px;
+}
+h2 {
+	font-size: 20px;
+	background: #E0EBF5;
+	padding: 2px 5px;
+}
+h3 {
+	font-size: 20px;
+}
+h3,
+h4 {
+	margin: 20px 5px;
+}
+h4 {
+	font-size: 16px;
+}
+
+dl {
+	margin: 20px;
+}
+dd {
+	margin: 2px 20px;
+}
+dl,
+dd {
+	font-size: 14px;
+}
+div#nav table td {
+	vertical-align: top;
+}
+
+div#heading {
+	float: left;
+	margin: 0 0 10px 0;
+	padding: 21px 0;
+	font-size: 20px;
+	font-weight: normal;
+}
+div#heading a {
+	color: #222;
+	text-decoration: none;
+}
+
+div#topbar {
+	background: #E0EBF5;
+	height: 64px;
+}
+
+body {
+	text-align: center;
+}
+div#page,
+div#topbar > .container {
+	clear: both;
+	text-align: left;
+	margin-left: auto;
+	margin-right: auto;
+	padding: 0 20px;
+	width: 900px;
+}
+div#page.wide,
+div#topbar > .wide {
+	width: auto;
+}
+div#plusone {
+	float: right;
+}
+
+div#footer {
+	color: #666;
+	font-size: 14px;
+	margin: 40px 0;
+}
+
+div#menu > a,
+div#menu > input {
+	padding: 10px;
+
+	text-decoration: none;
+	font-size: 16px;
+
+	-webkit-border-radius: 5px;
+	-moz-border-radius: 5px;
+	border-radius: 5px;
+}
+div#menu > a,
+div#menu > input {
+	border: 1px solid #375EAB;
+}
+div#menu > a {
+	color: white;
+	background: #375EAB;
+}
+
+div#menu {
+	float: right;
+	min-width: 590px;
+	padding: 10px 0;
+	text-align: right;
+}
+div#menu > a {
+	margin-right: 5px;
+	margin-bottom: 10px;
+
+	padding: 10px;
+}
+div#menu > input {
+	position: relative;
+	top: 1px;
+	width: 60px;
+	background: white;
+	color: #222;
+}
+div#menu > input.inactive {
+	color: #999;
+}
diff --git a/cmd/present/static/dir.js b/cmd/present/static/dir.js
new file mode 100644
index 0000000..5b0c37e
--- /dev/null
+++ b/cmd/present/static/dir.js
@@ -0,0 +1,41 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// copied from $GOROOT/doc/godocs.js
+
+function bindEvent(el, e, fn) {
+  if (el.addEventListener){
+    el.addEventListener(e, fn, false);
+  } else if (el.attachEvent){
+    el.attachEvent('on'+e, fn);
+  }
+}
+
+function godocs_bindSearchEvents() {
+  var search = document.getElementById('search');
+  if (!search) {
+    // no search box (index disabled)
+    return;
+  }
+  function clearInactive() {
+    if (search.className == "inactive") {
+      search.value = "";
+      search.className = "";
+    }
+  }
+  function restoreInactive() {
+    if (search.value !== "") {
+      return;
+    }
+    if (search.type != "search") {
+      search.value = search.getAttribute("placeholder");
+    }
+    search.className = "inactive";
+  }
+  restoreInactive();
+  bindEvent(search, 'focus', clearInactive);
+  bindEvent(search, 'blur', restoreInactive);
+}
+
+bindEvent(window, 'load', godocs_bindSearchEvents);
diff --git a/cmd/present/static/favicon.ico b/cmd/present/static/favicon.ico
new file mode 100644
index 0000000..48854ff
--- /dev/null
+++ b/cmd/present/static/favicon.ico
Binary files differ
diff --git a/cmd/present/static/jquery-ui.js b/cmd/present/static/jquery-ui.js
new file mode 100644
index 0000000..f391938
--- /dev/null
+++ b/cmd/present/static/jquery-ui.js
@@ -0,0 +1,6 @@
+/*! jQuery UI - v1.10.2 - 2013-03-20
+* http://jqueryui.com
+* Includes: jquery.ui.core.js, jquery.ui.widget.js, jquery.ui.mouse.js, jquery.ui.resizable.js
+* Copyright 2013 jQuery Foundation and other contributors Licensed MIT */
+
+(function(e,t){function i(t,i){var a,n,r,o=t.nodeName.toLowerCase();return"area"===o?(a=t.parentNode,n=a.name,t.href&&n&&"map"===a.nodeName.toLowerCase()?(r=e("img[usemap=#"+n+"]")[0],!!r&&s(r)):!1):(/input|select|textarea|button|object/.test(o)?!t.disabled:"a"===o?t.href||i:i)&&s(t)}function s(t){return e.expr.filters.visible(t)&&!e(t).parents().addBack().filter(function(){return"hidden"===e.css(this,"visibility")}).length}var a=0,n=/^ui-id-\d+$/;e.ui=e.ui||{},e.extend(e.ui,{version:"1.10.2",keyCode:{BACKSPACE:8,COMMA:188,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,LEFT:37,NUMPAD_ADD:107,NUMPAD_DECIMAL:110,NUMPAD_DIVIDE:111,NUMPAD_ENTER:108,NUMPAD_MULTIPLY:106,NUMPAD_SUBTRACT:109,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SPACE:32,TAB:9,UP:38}}),e.fn.extend({focus:function(t){return function(i,s){return"number"==typeof i?this.each(function(){var t=this;setTimeout(function(){e(t).focus(),s&&s.call(t)},i)}):t.apply(this,arguments)}}(e.fn.focus),scrollParent:function(){var t;return t=e.ui.ie&&/(static|relative)/.test(this.css("position"))||/absolute/.test(this.css("position"))?this.parents().filter(function(){return/(relative|absolute|fixed)/.test(e.css(this,"position"))&&/(auto|scroll)/.test(e.css(this,"overflow")+e.css(this,"overflow-y")+e.css(this,"overflow-x"))}).eq(0):this.parents().filter(function(){return/(auto|scroll)/.test(e.css(this,"overflow")+e.css(this,"overflow-y")+e.css(this,"overflow-x"))}).eq(0),/fixed/.test(this.css("position"))||!t.length?e(document):t},zIndex:function(i){if(i!==t)return this.css("zIndex",i);if(this.length)for(var s,a,n=e(this[0]);n.length&&n[0]!==document;){if(s=n.css("position"),("absolute"===s||"relative"===s||"fixed"===s)&&(a=parseInt(n.css("zIndex"),10),!isNaN(a)&&0!==a))return a;n=n.parent()}return 0},uniqueId:function(){return this.each(function(){this.id||(this.id="ui-id-"+ ++a)})},removeUniqueId:function(){return this.each(function(){n.test(this.id)&&e(this).removeAttr("id")})}}),e.extend(e.expr[":"],{data:e.expr.createPseudo?e.expr.createPseudo(function(t){return function(i){return!!e.data(i,t)}}):function(t,i,s){return!!e.data(t,s[3])},focusable:function(t){return i(t,!isNaN(e.attr(t,"tabindex")))},tabbable:function(t){var s=e.attr(t,"tabindex"),a=isNaN(s);return(a||s>=0)&&i(t,!a)}}),e("<a>").outerWidth(1).jquery||e.each(["Width","Height"],function(i,s){function a(t,i,s,a){return e.each(n,function(){i-=parseFloat(e.css(t,"padding"+this))||0,s&&(i-=parseFloat(e.css(t,"border"+this+"Width"))||0),a&&(i-=parseFloat(e.css(t,"margin"+this))||0)}),i}var n="Width"===s?["Left","Right"]:["Top","Bottom"],r=s.toLowerCase(),o={innerWidth:e.fn.innerWidth,innerHeight:e.fn.innerHeight,outerWidth:e.fn.outerWidth,outerHeight:e.fn.outerHeight};e.fn["inner"+s]=function(i){return i===t?o["inner"+s].call(this):this.each(function(){e(this).css(r,a(this,i)+"px")})},e.fn["outer"+s]=function(t,i){return"number"!=typeof t?o["outer"+s].call(this,t):this.each(function(){e(this).css(r,a(this,t,!0,i)+"px")})}}),e.fn.addBack||(e.fn.addBack=function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}),e("<a>").data("a-b","a").removeData("a-b").data("a-b")&&(e.fn.removeData=function(t){return function(i){return arguments.length?t.call(this,e.camelCase(i)):t.call(this)}}(e.fn.removeData)),e.ui.ie=!!/msie [\w.]+/.exec(navigator.userAgent.toLowerCase()),e.support.selectstart="onselectstart"in document.createElement("div"),e.fn.extend({disableSelection:function(){return this.bind((e.support.selectstart?"selectstart":"mousedown")+".ui-disableSelection",function(e){e.preventDefault()})},enableSelection:function(){return this.unbind(".ui-disableSelection")}}),e.extend(e.ui,{plugin:{add:function(t,i,s){var a,n=e.ui[t].prototype;for(a in s)n.plugins[a]=n.plugins[a]||[],n.plugins[a].push([i,s[a]])},call:function(e,t,i){var s,a=e.plugins[t];if(a&&e.element[0].parentNode&&11!==e.element[0].parentNode.nodeType)for(s=0;a.length>s;s++)e.options[a[s][0]]&&a[s][1].apply(e.element,i)}},hasScroll:function(t,i){if("hidden"===e(t).css("overflow"))return!1;var s=i&&"left"===i?"scrollLeft":"scrollTop",a=!1;return t[s]>0?!0:(t[s]=1,a=t[s]>0,t[s]=0,a)}})})(jQuery);(function(e,t){var i=0,s=Array.prototype.slice,n=e.cleanData;e.cleanData=function(t){for(var i,s=0;null!=(i=t[s]);s++)try{e(i).triggerHandler("remove")}catch(a){}n(t)},e.widget=function(i,s,n){var a,r,o,h,l={},u=i.split(".")[0];i=i.split(".")[1],a=u+"-"+i,n||(n=s,s=e.Widget),e.expr[":"][a.toLowerCase()]=function(t){return!!e.data(t,a)},e[u]=e[u]||{},r=e[u][i],o=e[u][i]=function(e,i){return this._createWidget?(arguments.length&&this._createWidget(e,i),t):new o(e,i)},e.extend(o,r,{version:n.version,_proto:e.extend({},n),_childConstructors:[]}),h=new s,h.options=e.widget.extend({},h.options),e.each(n,function(i,n){return e.isFunction(n)?(l[i]=function(){var e=function(){return s.prototype[i].apply(this,arguments)},t=function(e){return s.prototype[i].apply(this,e)};return function(){var i,s=this._super,a=this._superApply;return this._super=e,this._superApply=t,i=n.apply(this,arguments),this._super=s,this._superApply=a,i}}(),t):(l[i]=n,t)}),o.prototype=e.widget.extend(h,{widgetEventPrefix:r?h.widgetEventPrefix:i},l,{constructor:o,namespace:u,widgetName:i,widgetFullName:a}),r?(e.each(r._childConstructors,function(t,i){var s=i.prototype;e.widget(s.namespace+"."+s.widgetName,o,i._proto)}),delete r._childConstructors):s._childConstructors.push(o),e.widget.bridge(i,o)},e.widget.extend=function(i){for(var n,a,r=s.call(arguments,1),o=0,h=r.length;h>o;o++)for(n in r[o])a=r[o][n],r[o].hasOwnProperty(n)&&a!==t&&(i[n]=e.isPlainObject(a)?e.isPlainObject(i[n])?e.widget.extend({},i[n],a):e.widget.extend({},a):a);return i},e.widget.bridge=function(i,n){var a=n.prototype.widgetFullName||i;e.fn[i]=function(r){var o="string"==typeof r,h=s.call(arguments,1),l=this;return r=!o&&h.length?e.widget.extend.apply(null,[r].concat(h)):r,o?this.each(function(){var s,n=e.data(this,a);return n?e.isFunction(n[r])&&"_"!==r.charAt(0)?(s=n[r].apply(n,h),s!==n&&s!==t?(l=s&&s.jquery?l.pushStack(s.get()):s,!1):t):e.error("no such method '"+r+"' for "+i+" widget instance"):e.error("cannot call methods on "+i+" prior to initialization; "+"attempted to call method '"+r+"'")}):this.each(function(){var t=e.data(this,a);t?t.option(r||{})._init():e.data(this,a,new n(r,this))}),l}},e.Widget=function(){},e.Widget._childConstructors=[],e.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",defaultElement:"<div>",options:{disabled:!1,create:null},_createWidget:function(t,s){s=e(s||this.defaultElement||this)[0],this.element=e(s),this.uuid=i++,this.eventNamespace="."+this.widgetName+this.uuid,this.options=e.widget.extend({},this.options,this._getCreateOptions(),t),this.bindings=e(),this.hoverable=e(),this.focusable=e(),s!==this&&(e.data(s,this.widgetFullName,this),this._on(!0,this.element,{remove:function(e){e.target===s&&this.destroy()}}),this.document=e(s.style?s.ownerDocument:s.document||s),this.window=e(this.document[0].defaultView||this.document[0].parentWindow)),this._create(),this._trigger("create",null,this._getCreateEventData()),this._init()},_getCreateOptions:e.noop,_getCreateEventData:e.noop,_create:e.noop,_init:e.noop,destroy:function(){this._destroy(),this.element.unbind(this.eventNamespace).removeData(this.widgetName).removeData(this.widgetFullName).removeData(e.camelCase(this.widgetFullName)),this.widget().unbind(this.eventNamespace).removeAttr("aria-disabled").removeClass(this.widgetFullName+"-disabled "+"ui-state-disabled"),this.bindings.unbind(this.eventNamespace),this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus")},_destroy:e.noop,widget:function(){return this.element},option:function(i,s){var n,a,r,o=i;if(0===arguments.length)return e.widget.extend({},this.options);if("string"==typeof i)if(o={},n=i.split("."),i=n.shift(),n.length){for(a=o[i]=e.widget.extend({},this.options[i]),r=0;n.length-1>r;r++)a[n[r]]=a[n[r]]||{},a=a[n[r]];if(i=n.pop(),s===t)return a[i]===t?null:a[i];a[i]=s}else{if(s===t)return this.options[i]===t?null:this.options[i];o[i]=s}return this._setOptions(o),this},_setOptions:function(e){var t;for(t in e)this._setOption(t,e[t]);return this},_setOption:function(e,t){return this.options[e]=t,"disabled"===e&&(this.widget().toggleClass(this.widgetFullName+"-disabled ui-state-disabled",!!t).attr("aria-disabled",t),this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus")),this},enable:function(){return this._setOption("disabled",!1)},disable:function(){return this._setOption("disabled",!0)},_on:function(i,s,n){var a,r=this;"boolean"!=typeof i&&(n=s,s=i,i=!1),n?(s=a=e(s),this.bindings=this.bindings.add(s)):(n=s,s=this.element,a=this.widget()),e.each(n,function(n,o){function h(){return i||r.options.disabled!==!0&&!e(this).hasClass("ui-state-disabled")?("string"==typeof o?r[o]:o).apply(r,arguments):t}"string"!=typeof o&&(h.guid=o.guid=o.guid||h.guid||e.guid++);var l=n.match(/^(\w+)\s*(.*)$/),u=l[1]+r.eventNamespace,c=l[2];c?a.delegate(c,u,h):s.bind(u,h)})},_off:function(e,t){t=(t||"").split(" ").join(this.eventNamespace+" ")+this.eventNamespace,e.unbind(t).undelegate(t)},_delay:function(e,t){function i(){return("string"==typeof e?s[e]:e).apply(s,arguments)}var s=this;return setTimeout(i,t||0)},_hoverable:function(t){this.hoverable=this.hoverable.add(t),this._on(t,{mouseenter:function(t){e(t.currentTarget).addClass("ui-state-hover")},mouseleave:function(t){e(t.currentTarget).removeClass("ui-state-hover")}})},_focusable:function(t){this.focusable=this.focusable.add(t),this._on(t,{focusin:function(t){e(t.currentTarget).addClass("ui-state-focus")},focusout:function(t){e(t.currentTarget).removeClass("ui-state-focus")}})},_trigger:function(t,i,s){var n,a,r=this.options[t];if(s=s||{},i=e.Event(i),i.type=(t===this.widgetEventPrefix?t:this.widgetEventPrefix+t).toLowerCase(),i.target=this.element[0],a=i.originalEvent)for(n in a)n in i||(i[n]=a[n]);return this.element.trigger(i,s),!(e.isFunction(r)&&r.apply(this.element[0],[i].concat(s))===!1||i.isDefaultPrevented())}},e.each({show:"fadeIn",hide:"fadeOut"},function(t,i){e.Widget.prototype["_"+t]=function(s,n,a){"string"==typeof n&&(n={effect:n});var r,o=n?n===!0||"number"==typeof n?i:n.effect||i:t;n=n||{},"number"==typeof n&&(n={duration:n}),r=!e.isEmptyObject(n),n.complete=a,n.delay&&s.delay(n.delay),r&&e.effects&&e.effects.effect[o]?s[t](n):o!==t&&s[o]?s[o](n.duration,n.easing,a):s.queue(function(i){e(this)[t](),a&&a.call(s[0]),i()})}})})(jQuery);(function(e){var t=!1;e(document).mouseup(function(){t=!1}),e.widget("ui.mouse",{version:"1.10.2",options:{cancel:"input,textarea,button,select,option",distance:1,delay:0},_mouseInit:function(){var t=this;this.element.bind("mousedown."+this.widgetName,function(e){return t._mouseDown(e)}).bind("click."+this.widgetName,function(i){return!0===e.data(i.target,t.widgetName+".preventClickEvent")?(e.removeData(i.target,t.widgetName+".preventClickEvent"),i.stopImmediatePropagation(),!1):undefined}),this.started=!1},_mouseDestroy:function(){this.element.unbind("."+this.widgetName),this._mouseMoveDelegate&&e(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate)},_mouseDown:function(i){if(!t){this._mouseStarted&&this._mouseUp(i),this._mouseDownEvent=i;var s=this,n=1===i.which,a="string"==typeof this.options.cancel&&i.target.nodeName?e(i.target).closest(this.options.cancel).length:!1;return n&&!a&&this._mouseCapture(i)?(this.mouseDelayMet=!this.options.delay,this.mouseDelayMet||(this._mouseDelayTimer=setTimeout(function(){s.mouseDelayMet=!0},this.options.delay)),this._mouseDistanceMet(i)&&this._mouseDelayMet(i)&&(this._mouseStarted=this._mouseStart(i)!==!1,!this._mouseStarted)?(i.preventDefault(),!0):(!0===e.data(i.target,this.widgetName+".preventClickEvent")&&e.removeData(i.target,this.widgetName+".preventClickEvent"),this._mouseMoveDelegate=function(e){return s._mouseMove(e)},this._mouseUpDelegate=function(e){return s._mouseUp(e)},e(document).bind("mousemove."+this.widgetName,this._mouseMoveDelegate).bind("mouseup."+this.widgetName,this._mouseUpDelegate),i.preventDefault(),t=!0,!0)):!0}},_mouseMove:function(t){return e.ui.ie&&(!document.documentMode||9>document.documentMode)&&!t.button?this._mouseUp(t):this._mouseStarted?(this._mouseDrag(t),t.preventDefault()):(this._mouseDistanceMet(t)&&this._mouseDelayMet(t)&&(this._mouseStarted=this._mouseStart(this._mouseDownEvent,t)!==!1,this._mouseStarted?this._mouseDrag(t):this._mouseUp(t)),!this._mouseStarted)},_mouseUp:function(t){return e(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate),this._mouseStarted&&(this._mouseStarted=!1,t.target===this._mouseDownEvent.target&&e.data(t.target,this.widgetName+".preventClickEvent",!0),this._mouseStop(t)),!1},_mouseDistanceMet:function(e){return Math.max(Math.abs(this._mouseDownEvent.pageX-e.pageX),Math.abs(this._mouseDownEvent.pageY-e.pageY))>=this.options.distance},_mouseDelayMet:function(){return this.mouseDelayMet},_mouseStart:function(){},_mouseDrag:function(){},_mouseStop:function(){},_mouseCapture:function(){return!0}})})(jQuery);(function(e){function t(e){return parseInt(e,10)||0}function i(e){return!isNaN(parseInt(e,10))}e.widget("ui.resizable",e.ui.mouse,{version:"1.10.2",widgetEventPrefix:"resize",options:{alsoResize:!1,animate:!1,animateDuration:"slow",animateEasing:"swing",aspectRatio:!1,autoHide:!1,containment:!1,ghost:!1,grid:!1,handles:"e,s,se",helper:!1,maxHeight:null,maxWidth:null,minHeight:10,minWidth:10,zIndex:90,resize:null,start:null,stop:null},_create:function(){var t,i,s,n,a,o=this,r=this.options;if(this.element.addClass("ui-resizable"),e.extend(this,{_aspectRatio:!!r.aspectRatio,aspectRatio:r.aspectRatio,originalElement:this.element,_proportionallyResizeElements:[],_helper:r.helper||r.ghost||r.animate?r.helper||"ui-resizable-helper":null}),this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)&&(this.element.wrap(e("<div class='ui-wrapper' style='overflow: hidden;'></div>").css({position:this.element.css("position"),width:this.element.outerWidth(),height:this.element.outerHeight(),top:this.element.css("top"),left:this.element.css("left")})),this.element=this.element.parent().data("ui-resizable",this.element.data("ui-resizable")),this.elementIsWrapper=!0,this.element.css({marginLeft:this.originalElement.css("marginLeft"),marginTop:this.originalElement.css("marginTop"),marginRight:this.originalElement.css("marginRight"),marginBottom:this.originalElement.css("marginBottom")}),this.originalElement.css({marginLeft:0,marginTop:0,marginRight:0,marginBottom:0}),this.originalResizeStyle=this.originalElement.css("resize"),this.originalElement.css("resize","none"),this._proportionallyResizeElements.push(this.originalElement.css({position:"static",zoom:1,display:"block"})),this.originalElement.css({margin:this.originalElement.css("margin")}),this._proportionallyResize()),this.handles=r.handles||(e(".ui-resizable-handle",this.element).length?{n:".ui-resizable-n",e:".ui-resizable-e",s:".ui-resizable-s",w:".ui-resizable-w",se:".ui-resizable-se",sw:".ui-resizable-sw",ne:".ui-resizable-ne",nw:".ui-resizable-nw"}:"e,s,se"),this.handles.constructor===String)for("all"===this.handles&&(this.handles="n,e,s,w,se,sw,ne,nw"),t=this.handles.split(","),this.handles={},i=0;t.length>i;i++)s=e.trim(t[i]),a="ui-resizable-"+s,n=e("<div class='ui-resizable-handle "+a+"'></div>"),n.css({zIndex:r.zIndex}),"se"===s&&n.addClass("ui-icon ui-icon-gripsmall-diagonal-se"),this.handles[s]=".ui-resizable-"+s,this.element.append(n);this._renderAxis=function(t){var i,s,n,a;t=t||this.element;for(i in this.handles)this.handles[i].constructor===String&&(this.handles[i]=e(this.handles[i],this.element).show()),this.elementIsWrapper&&this.originalElement[0].nodeName.match(/textarea|input|select|button/i)&&(s=e(this.handles[i],this.element),a=/sw|ne|nw|se|n|s/.test(i)?s.outerHeight():s.outerWidth(),n=["padding",/ne|nw|n/.test(i)?"Top":/se|sw|s/.test(i)?"Bottom":/^e$/.test(i)?"Right":"Left"].join(""),t.css(n,a),this._proportionallyResize()),e(this.handles[i]).length},this._renderAxis(this.element),this._handles=e(".ui-resizable-handle",this.element).disableSelection(),this._handles.mouseover(function(){o.resizing||(this.className&&(n=this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i)),o.axis=n&&n[1]?n[1]:"se")}),r.autoHide&&(this._handles.hide(),e(this.element).addClass("ui-resizable-autohide").mouseenter(function(){r.disabled||(e(this).removeClass("ui-resizable-autohide"),o._handles.show())}).mouseleave(function(){r.disabled||o.resizing||(e(this).addClass("ui-resizable-autohide"),o._handles.hide())})),this._mouseInit()},_destroy:function(){this._mouseDestroy();var t,i=function(t){e(t).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing").removeData("resizable").removeData("ui-resizable").unbind(".resizable").find(".ui-resizable-handle").remove()};return this.elementIsWrapper&&(i(this.element),t=this.element,this.originalElement.css({position:t.css("position"),width:t.outerWidth(),height:t.outerHeight(),top:t.css("top"),left:t.css("left")}).insertAfter(t),t.remove()),this.originalElement.css("resize",this.originalResizeStyle),i(this.originalElement),this},_mouseCapture:function(t){var i,s,n=!1;for(i in this.handles)s=e(this.handles[i])[0],(s===t.target||e.contains(s,t.target))&&(n=!0);return!this.options.disabled&&n},_mouseStart:function(i){var s,n,a,o=this.options,r=this.element.position(),h=this.element;return this.resizing=!0,/absolute/.test(h.css("position"))?h.css({position:"absolute",top:h.css("top"),left:h.css("left")}):h.is(".ui-draggable")&&h.css({position:"absolute",top:r.top,left:r.left}),this._renderProxy(),s=t(this.helper.css("left")),n=t(this.helper.css("top")),o.containment&&(s+=e(o.containment).scrollLeft()||0,n+=e(o.containment).scrollTop()||0),this.offset=this.helper.offset(),this.position={left:s,top:n},this.size=this._helper?{width:h.outerWidth(),height:h.outerHeight()}:{width:h.width(),height:h.height()},this.originalSize=this._helper?{width:h.outerWidth(),height:h.outerHeight()}:{width:h.width(),height:h.height()},this.originalPosition={left:s,top:n},this.sizeDiff={width:h.outerWidth()-h.width(),height:h.outerHeight()-h.height()},this.originalMousePosition={left:i.pageX,top:i.pageY},this.aspectRatio="number"==typeof o.aspectRatio?o.aspectRatio:this.originalSize.width/this.originalSize.height||1,a=e(".ui-resizable-"+this.axis).css("cursor"),e("body").css("cursor","auto"===a?this.axis+"-resize":a),h.addClass("ui-resizable-resizing"),this._propagate("start",i),!0},_mouseDrag:function(t){var i,s=this.helper,n={},a=this.originalMousePosition,o=this.axis,r=this.position.top,h=this.position.left,l=this.size.width,u=this.size.height,c=t.pageX-a.left||0,d=t.pageY-a.top||0,p=this._change[o];return p?(i=p.apply(this,[t,c,d]),this._updateVirtualBoundaries(t.shiftKey),(this._aspectRatio||t.shiftKey)&&(i=this._updateRatio(i,t)),i=this._respectSize(i,t),this._updateCache(i),this._propagate("resize",t),this.position.top!==r&&(n.top=this.position.top+"px"),this.position.left!==h&&(n.left=this.position.left+"px"),this.size.width!==l&&(n.width=this.size.width+"px"),this.size.height!==u&&(n.height=this.size.height+"px"),s.css(n),!this._helper&&this._proportionallyResizeElements.length&&this._proportionallyResize(),e.isEmptyObject(n)||this._trigger("resize",t,this.ui()),!1):!1},_mouseStop:function(t){this.resizing=!1;var i,s,n,a,o,r,h,l=this.options,u=this;return this._helper&&(i=this._proportionallyResizeElements,s=i.length&&/textarea/i.test(i[0].nodeName),n=s&&e.ui.hasScroll(i[0],"left")?0:u.sizeDiff.height,a=s?0:u.sizeDiff.width,o={width:u.helper.width()-a,height:u.helper.height()-n},r=parseInt(u.element.css("left"),10)+(u.position.left-u.originalPosition.left)||null,h=parseInt(u.element.css("top"),10)+(u.position.top-u.originalPosition.top)||null,l.animate||this.element.css(e.extend(o,{top:h,left:r})),u.helper.height(u.size.height),u.helper.width(u.size.width),this._helper&&!l.animate&&this._proportionallyResize()),e("body").css("cursor","auto"),this.element.removeClass("ui-resizable-resizing"),this._propagate("stop",t),this._helper&&this.helper.remove(),!1},_updateVirtualBoundaries:function(e){var t,s,n,a,o,r=this.options;o={minWidth:i(r.minWidth)?r.minWidth:0,maxWidth:i(r.maxWidth)?r.maxWidth:1/0,minHeight:i(r.minHeight)?r.minHeight:0,maxHeight:i(r.maxHeight)?r.maxHeight:1/0},(this._aspectRatio||e)&&(t=o.minHeight*this.aspectRatio,n=o.minWidth/this.aspectRatio,s=o.maxHeight*this.aspectRatio,a=o.maxWidth/this.aspectRatio,t>o.minWidth&&(o.minWidth=t),n>o.minHeight&&(o.minHeight=n),o.maxWidth>s&&(o.maxWidth=s),o.maxHeight>a&&(o.maxHeight=a)),this._vBoundaries=o},_updateCache:function(e){this.offset=this.helper.offset(),i(e.left)&&(this.position.left=e.left),i(e.top)&&(this.position.top=e.top),i(e.height)&&(this.size.height=e.height),i(e.width)&&(this.size.width=e.width)},_updateRatio:function(e){var t=this.position,s=this.size,n=this.axis;return i(e.height)?e.width=e.height*this.aspectRatio:i(e.width)&&(e.height=e.width/this.aspectRatio),"sw"===n&&(e.left=t.left+(s.width-e.width),e.top=null),"nw"===n&&(e.top=t.top+(s.height-e.height),e.left=t.left+(s.width-e.width)),e},_respectSize:function(e){var t=this._vBoundaries,s=this.axis,n=i(e.width)&&t.maxWidth&&t.maxWidth<e.width,a=i(e.height)&&t.maxHeight&&t.maxHeight<e.height,o=i(e.width)&&t.minWidth&&t.minWidth>e.width,r=i(e.height)&&t.minHeight&&t.minHeight>e.height,h=this.originalPosition.left+this.originalSize.width,l=this.position.top+this.size.height,u=/sw|nw|w/.test(s),c=/nw|ne|n/.test(s);return o&&(e.width=t.minWidth),r&&(e.height=t.minHeight),n&&(e.width=t.maxWidth),a&&(e.height=t.maxHeight),o&&u&&(e.left=h-t.minWidth),n&&u&&(e.left=h-t.maxWidth),r&&c&&(e.top=l-t.minHeight),a&&c&&(e.top=l-t.maxHeight),e.width||e.height||e.left||!e.top?e.width||e.height||e.top||!e.left||(e.left=null):e.top=null,e},_proportionallyResize:function(){if(this._proportionallyResizeElements.length){var e,t,i,s,n,a=this.helper||this.element;for(e=0;this._proportionallyResizeElements.length>e;e++){if(n=this._proportionallyResizeElements[e],!this.borderDif)for(this.borderDif=[],i=[n.css("borderTopWidth"),n.css("borderRightWidth"),n.css("borderBottomWidth"),n.css("borderLeftWidth")],s=[n.css("paddingTop"),n.css("paddingRight"),n.css("paddingBottom"),n.css("paddingLeft")],t=0;i.length>t;t++)this.borderDif[t]=(parseInt(i[t],10)||0)+(parseInt(s[t],10)||0);n.css({height:a.height()-this.borderDif[0]-this.borderDif[2]||0,width:a.width()-this.borderDif[1]-this.borderDif[3]||0})}}},_renderProxy:function(){var t=this.element,i=this.options;this.elementOffset=t.offset(),this._helper?(this.helper=this.helper||e("<div style='overflow:hidden;'></div>"),this.helper.addClass(this._helper).css({width:this.element.outerWidth()-1,height:this.element.outerHeight()-1,position:"absolute",left:this.elementOffset.left+"px",top:this.elementOffset.top+"px",zIndex:++i.zIndex}),this.helper.appendTo("body").disableSelection()):this.helper=this.element},_change:{e:function(e,t){return{width:this.originalSize.width+t}},w:function(e,t){var i=this.originalSize,s=this.originalPosition;return{left:s.left+t,width:i.width-t}},n:function(e,t,i){var s=this.originalSize,n=this.originalPosition;return{top:n.top+i,height:s.height-i}},s:function(e,t,i){return{height:this.originalSize.height+i}},se:function(t,i,s){return e.extend(this._change.s.apply(this,arguments),this._change.e.apply(this,[t,i,s]))},sw:function(t,i,s){return e.extend(this._change.s.apply(this,arguments),this._change.w.apply(this,[t,i,s]))},ne:function(t,i,s){return e.extend(this._change.n.apply(this,arguments),this._change.e.apply(this,[t,i,s]))},nw:function(t,i,s){return e.extend(this._change.n.apply(this,arguments),this._change.w.apply(this,[t,i,s]))}},_propagate:function(t,i){e.ui.plugin.call(this,t,[i,this.ui()]),"resize"!==t&&this._trigger(t,i,this.ui())},plugins:{},ui:function(){return{originalElement:this.originalElement,element:this.element,helper:this.helper,position:this.position,size:this.size,originalSize:this.originalSize,originalPosition:this.originalPosition}}}),e.ui.plugin.add("resizable","animate",{stop:function(t){var i=e(this).data("ui-resizable"),s=i.options,n=i._proportionallyResizeElements,a=n.length&&/textarea/i.test(n[0].nodeName),o=a&&e.ui.hasScroll(n[0],"left")?0:i.sizeDiff.height,r=a?0:i.sizeDiff.width,h={width:i.size.width-r,height:i.size.height-o},l=parseInt(i.element.css("left"),10)+(i.position.left-i.originalPosition.left)||null,u=parseInt(i.element.css("top"),10)+(i.position.top-i.originalPosition.top)||null;i.element.animate(e.extend(h,u&&l?{top:u,left:l}:{}),{duration:s.animateDuration,easing:s.animateEasing,step:function(){var s={width:parseInt(i.element.css("width"),10),height:parseInt(i.element.css("height"),10),top:parseInt(i.element.css("top"),10),left:parseInt(i.element.css("left"),10)};n&&n.length&&e(n[0]).css({width:s.width,height:s.height}),i._updateCache(s),i._propagate("resize",t)}})}}),e.ui.plugin.add("resizable","containment",{start:function(){var i,s,n,a,o,r,h,l=e(this).data("ui-resizable"),u=l.options,c=l.element,d=u.containment,p=d instanceof e?d.get(0):/parent/.test(d)?c.parent().get(0):d;p&&(l.containerElement=e(p),/document/.test(d)||d===document?(l.containerOffset={left:0,top:0},l.containerPosition={left:0,top:0},l.parentData={element:e(document),left:0,top:0,width:e(document).width(),height:e(document).height()||document.body.parentNode.scrollHeight}):(i=e(p),s=[],e(["Top","Right","Left","Bottom"]).each(function(e,n){s[e]=t(i.css("padding"+n))}),l.containerOffset=i.offset(),l.containerPosition=i.position(),l.containerSize={height:i.innerHeight()-s[3],width:i.innerWidth()-s[1]},n=l.containerOffset,a=l.containerSize.height,o=l.containerSize.width,r=e.ui.hasScroll(p,"left")?p.scrollWidth:o,h=e.ui.hasScroll(p)?p.scrollHeight:a,l.parentData={element:p,left:n.left,top:n.top,width:r,height:h}))},resize:function(t){var i,s,n,a,o=e(this).data("ui-resizable"),r=o.options,h=o.containerOffset,l=o.position,u=o._aspectRatio||t.shiftKey,c={top:0,left:0},d=o.containerElement;d[0]!==document&&/static/.test(d.css("position"))&&(c=h),l.left<(o._helper?h.left:0)&&(o.size.width=o.size.width+(o._helper?o.position.left-h.left:o.position.left-c.left),u&&(o.size.height=o.size.width/o.aspectRatio),o.position.left=r.helper?h.left:0),l.top<(o._helper?h.top:0)&&(o.size.height=o.size.height+(o._helper?o.position.top-h.top:o.position.top),u&&(o.size.width=o.size.height*o.aspectRatio),o.position.top=o._helper?h.top:0),o.offset.left=o.parentData.left+o.position.left,o.offset.top=o.parentData.top+o.position.top,i=Math.abs((o._helper?o.offset.left-c.left:o.offset.left-c.left)+o.sizeDiff.width),s=Math.abs((o._helper?o.offset.top-c.top:o.offset.top-h.top)+o.sizeDiff.height),n=o.containerElement.get(0)===o.element.parent().get(0),a=/relative|absolute/.test(o.containerElement.css("position")),n&&a&&(i-=o.parentData.left),i+o.size.width>=o.parentData.width&&(o.size.width=o.parentData.width-i,u&&(o.size.height=o.size.width/o.aspectRatio)),s+o.size.height>=o.parentData.height&&(o.size.height=o.parentData.height-s,u&&(o.size.width=o.size.height*o.aspectRatio))},stop:function(){var t=e(this).data("ui-resizable"),i=t.options,s=t.containerOffset,n=t.containerPosition,a=t.containerElement,o=e(t.helper),r=o.offset(),h=o.outerWidth()-t.sizeDiff.width,l=o.outerHeight()-t.sizeDiff.height;t._helper&&!i.animate&&/relative/.test(a.css("position"))&&e(this).css({left:r.left-n.left-s.left,width:h,height:l}),t._helper&&!i.animate&&/static/.test(a.css("position"))&&e(this).css({left:r.left-n.left-s.left,width:h,height:l})}}),e.ui.plugin.add("resizable","alsoResize",{start:function(){var t=e(this).data("ui-resizable"),i=t.options,s=function(t){e(t).each(function(){var t=e(this);t.data("ui-resizable-alsoresize",{width:parseInt(t.width(),10),height:parseInt(t.height(),10),left:parseInt(t.css("left"),10),top:parseInt(t.css("top"),10)})})};"object"!=typeof i.alsoResize||i.alsoResize.parentNode?s(i.alsoResize):i.alsoResize.length?(i.alsoResize=i.alsoResize[0],s(i.alsoResize)):e.each(i.alsoResize,function(e){s(e)})},resize:function(t,i){var s=e(this).data("ui-resizable"),n=s.options,a=s.originalSize,o=s.originalPosition,r={height:s.size.height-a.height||0,width:s.size.width-a.width||0,top:s.position.top-o.top||0,left:s.position.left-o.left||0},h=function(t,s){e(t).each(function(){var t=e(this),n=e(this).data("ui-resizable-alsoresize"),a={},o=s&&s.length?s:t.parents(i.originalElement[0]).length?["width","height"]:["width","height","top","left"];e.each(o,function(e,t){var i=(n[t]||0)+(r[t]||0);i&&i>=0&&(a[t]=i||null)}),t.css(a)})};"object"!=typeof n.alsoResize||n.alsoResize.nodeType?h(n.alsoResize):e.each(n.alsoResize,function(e,t){h(e,t)})},stop:function(){e(this).removeData("resizable-alsoresize")}}),e.ui.plugin.add("resizable","ghost",{start:function(){var t=e(this).data("ui-resizable"),i=t.options,s=t.size;t.ghost=t.originalElement.clone(),t.ghost.css({opacity:.25,display:"block",position:"relative",height:s.height,width:s.width,margin:0,left:0,top:0}).addClass("ui-resizable-ghost").addClass("string"==typeof i.ghost?i.ghost:""),t.ghost.appendTo(t.helper)},resize:function(){var t=e(this).data("ui-resizable");t.ghost&&t.ghost.css({position:"relative",height:t.size.height,width:t.size.width})},stop:function(){var t=e(this).data("ui-resizable");t.ghost&&t.helper&&t.helper.get(0).removeChild(t.ghost.get(0))}}),e.ui.plugin.add("resizable","grid",{resize:function(){var t=e(this).data("ui-resizable"),i=t.options,s=t.size,n=t.originalSize,a=t.originalPosition,o=t.axis,r="number"==typeof i.grid?[i.grid,i.grid]:i.grid,h=r[0]||1,l=r[1]||1,u=Math.round((s.width-n.width)/h)*h,c=Math.round((s.height-n.height)/l)*l,d=n.width+u,p=n.height+c,f=i.maxWidth&&d>i.maxWidth,m=i.maxHeight&&p>i.maxHeight,g=i.minWidth&&i.minWidth>d,v=i.minHeight&&i.minHeight>p;i.grid=r,g&&(d+=h),v&&(p+=l),f&&(d-=h),m&&(p-=l),/^(se|s|e)$/.test(o)?(t.size.width=d,t.size.height=p):/^(ne)$/.test(o)?(t.size.width=d,t.size.height=p,t.position.top=a.top-c):/^(sw)$/.test(o)?(t.size.width=d,t.size.height=p,t.position.left=a.left-u):(t.size.width=d,t.size.height=p,t.position.top=a.top-c,t.position.left=a.left-u)}})})(jQuery);
\ No newline at end of file
diff --git a/cmd/present/static/slides.js b/cmd/present/static/slides.js
new file mode 100644
index 0000000..3697b4e
--- /dev/null
+++ b/cmd/present/static/slides.js
@@ -0,0 +1,526 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+var PERMANENT_URL_PREFIX = '/static/';
+
+var SLIDE_CLASSES = ['far-past', 'past', 'current', 'next', 'far-next'];
+
+var PM_TOUCH_SENSITIVITY = 15;
+
+var curSlide;
+
+/* ---------------------------------------------------------------------- */
+/* classList polyfill by Eli Grey
+ * (http://purl.eligrey.com/github/classList.js/blob/master/classList.js) */
+
+if (typeof document !== "undefined" && !("classList" in document.createElement("a"))) {
+
+(function (view) {
+
+var
+    classListProp = "classList"
+  , protoProp = "prototype"
+  , elemCtrProto = (view.HTMLElement || view.Element)[protoProp]
+  , objCtr = Object
+    strTrim = String[protoProp].trim || function () {
+    return this.replace(/^\s+|\s+$/g, "");
+  }
+  , arrIndexOf = Array[protoProp].indexOf || function (item) {
+    for (var i = 0, len = this.length; i < len; i++) {
+      if (i in this && this[i] === item) {
+        return i;
+      }
+    }
+    return -1;
+  }
+  // Vendors: please allow content code to instantiate DOMExceptions
+  , DOMEx = function (type, message) {
+    this.name = type;
+    this.code = DOMException[type];
+    this.message = message;
+  }
+  , checkTokenAndGetIndex = function (classList, token) {
+    if (token === "") {
+      throw new DOMEx(
+          "SYNTAX_ERR"
+        , "An invalid or illegal string was specified"
+      );
+    }
+    if (/\s/.test(token)) {
+      throw new DOMEx(
+          "INVALID_CHARACTER_ERR"
+        , "String contains an invalid character"
+      );
+    }
+    return arrIndexOf.call(classList, token);
+  }
+  , ClassList = function (elem) {
+    var
+        trimmedClasses = strTrim.call(elem.className)
+      , classes = trimmedClasses ? trimmedClasses.split(/\s+/) : []
+    ;
+    for (var i = 0, len = classes.length; i < len; i++) {
+      this.push(classes[i]);
+    }
+    this._updateClassName = function () {
+      elem.className = this.toString();
+    };
+  }
+  , classListProto = ClassList[protoProp] = []
+  , classListGetter = function () {
+    return new ClassList(this);
+  }
+;
+// Most DOMException implementations don't allow calling DOMException's toString()
+// on non-DOMExceptions. Error's toString() is sufficient here.
+DOMEx[protoProp] = Error[protoProp];
+classListProto.item = function (i) {
+  return this[i] || null;
+};
+classListProto.contains = function (token) {
+  token += "";
+  return checkTokenAndGetIndex(this, token) !== -1;
+};
+classListProto.add = function (token) {
+  token += "";
+  if (checkTokenAndGetIndex(this, token) === -1) {
+    this.push(token);
+    this._updateClassName();
+  }
+};
+classListProto.remove = function (token) {
+  token += "";
+  var index = checkTokenAndGetIndex(this, token);
+  if (index !== -1) {
+    this.splice(index, 1);
+    this._updateClassName();
+  }
+};
+classListProto.toggle = function (token) {
+  token += "";
+  if (checkTokenAndGetIndex(this, token) === -1) {
+    this.add(token);
+  } else {
+    this.remove(token);
+  }
+};
+classListProto.toString = function () {
+  return this.join(" ");
+};
+
+if (objCtr.defineProperty) {
+  var classListPropDesc = {
+      get: classListGetter
+    , enumerable: true
+    , configurable: true
+  };
+  try {
+    objCtr.defineProperty(elemCtrProto, classListProp, classListPropDesc);
+  } catch (ex) { // IE 8 doesn't support enumerable:true
+    if (ex.number === -0x7FF5EC54) {
+      classListPropDesc.enumerable = false;
+      objCtr.defineProperty(elemCtrProto, classListProp, classListPropDesc);
+    }
+  }
+} else if (objCtr[protoProp].__defineGetter__) {
+  elemCtrProto.__defineGetter__(classListProp, classListGetter);
+}
+
+}(self));
+
+}
+/* ---------------------------------------------------------------------- */
+
+/* Slide movement */
+
+function hideHelpText() {
+  $('#help').hide();
+};
+
+function getSlideEl(no) {
+  if ((no < 0) || (no >= slideEls.length)) {
+    return null;
+  } else {
+    return slideEls[no];
+  }
+};
+
+function updateSlideClass(slideNo, className) {
+  var el = getSlideEl(slideNo);
+
+  if (!el) {
+    return;
+  }
+
+  if (className) {
+    el.classList.add(className);
+  }
+
+  for (var i in SLIDE_CLASSES) {
+    if (className != SLIDE_CLASSES[i]) {
+      el.classList.remove(SLIDE_CLASSES[i]);
+    }
+  }
+};
+
+function updateSlides() {
+  if (window.trackPageview) window.trackPageview();
+
+  for (var i = 0; i < slideEls.length; i++) {
+    switch (i) {
+      case curSlide - 2:
+        updateSlideClass(i, 'far-past');
+        break;
+      case curSlide - 1:
+        updateSlideClass(i, 'past');
+        break;
+      case curSlide:
+        updateSlideClass(i, 'current');
+        break;
+      case curSlide + 1:
+        updateSlideClass(i, 'next');
+        break;
+      case curSlide + 2:
+        updateSlideClass(i, 'far-next');
+        break;
+      default:
+        updateSlideClass(i);
+        break;
+    }
+  }
+
+  triggerLeaveEvent(curSlide - 1);
+  triggerEnterEvent(curSlide);
+
+  window.setTimeout(function() {
+    // Hide after the slide
+    disableSlideFrames(curSlide - 2);
+  }, 301);
+
+  enableSlideFrames(curSlide - 1);
+  enableSlideFrames(curSlide + 2);
+
+  updateHash();
+};
+
+function prevSlide() {
+  hideHelpText();
+  if (curSlide > 0) {
+    curSlide--;
+
+    updateSlides();
+  }
+};
+
+function nextSlide() {
+  hideHelpText();
+  if (curSlide < slideEls.length - 1) {
+    curSlide++;
+
+    updateSlides();
+  }
+};
+
+/* Slide events */
+
+function triggerEnterEvent(no) {
+  var el = getSlideEl(no);
+  if (!el) {
+    return;
+  }
+
+  var onEnter = el.getAttribute('onslideenter');
+  if (onEnter) {
+    new Function(onEnter).call(el);
+  }
+
+  var evt = document.createEvent('Event');
+  evt.initEvent('slideenter', true, true);
+  evt.slideNumber = no + 1; // Make it readable
+
+  el.dispatchEvent(evt);
+};
+
+function triggerLeaveEvent(no) {
+  var el = getSlideEl(no);
+  if (!el) {
+    return;
+  }
+
+  var onLeave = el.getAttribute('onslideleave');
+  if (onLeave) {
+    new Function(onLeave).call(el);
+  }
+
+  var evt = document.createEvent('Event');
+  evt.initEvent('slideleave', true, true);
+  evt.slideNumber = no + 1; // Make it readable
+
+  el.dispatchEvent(evt);
+};
+
+/* Touch events */
+
+function handleTouchStart(event) {
+  if (event.touches.length == 1) {
+    touchDX = 0;
+    touchDY = 0;
+
+    touchStartX = event.touches[0].pageX;
+    touchStartY = event.touches[0].pageY;
+
+    document.body.addEventListener('touchmove', handleTouchMove, true);
+    document.body.addEventListener('touchend', handleTouchEnd, true);
+  }
+};
+
+function handleTouchMove(event) {
+  if (event.touches.length > 1) {
+    cancelTouch();
+  } else {
+    touchDX = event.touches[0].pageX - touchStartX;
+    touchDY = event.touches[0].pageY - touchStartY;
+    event.preventDefault();
+  }
+};
+
+function handleTouchEnd(event) {
+  var dx = Math.abs(touchDX);
+  var dy = Math.abs(touchDY);
+
+  if ((dx > PM_TOUCH_SENSITIVITY) && (dy < (dx * 2 / 3))) {
+    if (touchDX > 0) {
+      prevSlide();
+    } else {
+      nextSlide();
+    }
+  }
+
+  cancelTouch();
+};
+
+function cancelTouch() {
+  document.body.removeEventListener('touchmove', handleTouchMove, true);
+  document.body.removeEventListener('touchend', handleTouchEnd, true);
+};
+
+/* Preloading frames */
+
+function disableSlideFrames(no) {
+  var el = getSlideEl(no);
+  if (!el) {
+    return;
+  }
+
+  var frames = el.getElementsByTagName('iframe');
+  for (var i = 0, frame; frame = frames[i]; i++) {
+    disableFrame(frame);
+  }
+};
+
+function enableSlideFrames(no) {
+  var el = getSlideEl(no);
+  if (!el) {
+    return;
+  }
+
+  var frames = el.getElementsByTagName('iframe');
+  for (var i = 0, frame; frame = frames[i]; i++) {
+    enableFrame(frame);
+  }
+};
+
+function disableFrame(frame) {
+  frame.src = 'about:blank';
+};
+
+function enableFrame(frame) {
+  var src = frame._src;
+
+  if (frame.src != src && src != 'about:blank') {
+    frame.src = src;
+  }
+};
+
+function setupFrames() {
+  var frames = document.querySelectorAll('iframe');
+  for (var i = 0, frame; frame = frames[i]; i++) {
+    frame._src = frame.src;
+    disableFrame(frame);
+  }
+
+  enableSlideFrames(curSlide);
+  enableSlideFrames(curSlide + 1);
+  enableSlideFrames(curSlide + 2);
+};
+
+function setupInteraction() {
+  /* Clicking and tapping */
+
+  var el = document.createElement('div');
+  el.className = 'slide-area';
+  el.id = 'prev-slide-area';
+  el.addEventListener('click', prevSlide, false);
+  document.querySelector('section.slides').appendChild(el);
+
+  var el = document.createElement('div');
+  el.className = 'slide-area';
+  el.id = 'next-slide-area';
+  el.addEventListener('click', nextSlide, false);
+  document.querySelector('section.slides').appendChild(el);
+
+  /* Swiping */
+
+  document.body.addEventListener('touchstart', handleTouchStart, false);
+}
+
+/* Hash functions */
+
+function getCurSlideFromHash() {
+  var slideNo = parseInt(location.hash.substr(1));
+
+  if (slideNo) {
+    curSlide = slideNo - 1;
+  } else {
+    curSlide = 0;
+  }
+};
+
+function updateHash() {
+  location.replace('#' + (curSlide + 1));
+};
+
+/* Event listeners */
+
+function handleBodyKeyDown(event) {
+  // If we're in a code element, only handle pgup/down.
+  var inCode = event.target.classList.contains("code");
+
+  switch (event.keyCode) {
+    case 72: // 'H' hides the help text
+    case 27: // escape key
+      if (!inCode) hideHelpText();
+      break;
+
+    case 39: // right arrow
+    case 13: // Enter
+    case 32: // space
+      if (inCode) break;
+    case 34: // PgDn
+      nextSlide();
+      event.preventDefault();
+      break;
+
+    case 37: // left arrow
+    case 8: // Backspace
+      if (inCode) break;
+    case 33: // PgUp
+      prevSlide();
+      event.preventDefault();
+      break;
+
+    case 40: // down arrow
+      if (inCode) break;
+      nextSlide();
+      event.preventDefault();
+      break;
+
+    case 38: // up arrow
+      if (inCode) break;
+      prevSlide();
+      event.preventDefault();
+      break;
+  }
+};
+
+function addEventListeners() {
+  document.addEventListener('keydown', handleBodyKeyDown, false);
+};
+
+/* Initialization */
+
+function addFontStyle() {
+  var el = document.createElement('link');
+  el.rel = 'stylesheet';
+  el.type = 'text/css';
+  el.href = '//fonts.googleapis.com/css?family=' +
+            'Open+Sans:regular,semibold,italic,italicsemibold|Droid+Sans+Mono';
+
+  document.body.appendChild(el);
+};
+
+function addGeneralStyle() {
+  var el = document.createElement('link');
+  el.rel = 'stylesheet';
+  el.type = 'text/css';
+  el.href = PERMANENT_URL_PREFIX + 'styles.css';
+  document.body.appendChild(el);
+
+  var el = document.createElement('meta');
+  el.name = 'viewport';
+  el.content = 'width=1100,height=750';
+  document.querySelector('head').appendChild(el);
+
+  var el = document.createElement('meta');
+  el.name = 'apple-mobile-web-app-capable';
+  el.content = 'yes';
+  document.querySelector('head').appendChild(el);
+};
+
+function showHelpText() {
+};
+
+function handleDomLoaded() {
+  slideEls = document.querySelectorAll('section.slides > article');
+
+  setupFrames();
+
+  addFontStyle();
+  addGeneralStyle();
+  addEventListeners();
+
+  updateSlides();
+
+  setupInteraction();
+
+  if (window.location.hostname == "localhost" || window.location.hostname == "127.0.0.1" || window.location.hostname == "::1") {
+    hideHelpText();
+  }
+
+  document.body.classList.add('loaded');
+};
+
+function initialize() {
+  getCurSlideFromHash();
+
+  if (window['_DEBUG']) {
+    PERMANENT_URL_PREFIX = '../';
+  }
+
+  if (window['_DCL']) {
+    handleDomLoaded();
+  } else {
+    document.addEventListener('DOMContentLoaded', handleDomLoaded, false);
+  }
+}
+
+// If ?debug exists then load the script relative instead of absolute
+if (!window['_DEBUG'] && document.location.href.indexOf('?debug') !== -1) {
+  document.addEventListener('DOMContentLoaded', function() {
+    // Avoid missing the DomContentLoaded event
+    window['_DCL'] = true
+  }, false);
+
+  window['_DEBUG'] = true;
+  var script = document.createElement('script');
+  script.type = 'text/javascript';
+  script.src = '../slides.js';
+  var s = document.getElementsByTagName('script')[0];
+  s.parentNode.insertBefore(script, s);
+
+  // Remove this script
+  s.parentNode.removeChild(s);
+} else {
+  initialize();
+}
diff --git a/cmd/present/static/styles.css b/cmd/present/static/styles.css
new file mode 100644
index 0000000..5cb2953
--- /dev/null
+++ b/cmd/present/static/styles.css
@@ -0,0 +1,523 @@
+@media screen {
+  /* Framework */
+  html {
+    height: 100%;
+  }
+
+  body {
+    margin: 0;
+    padding: 0;
+
+    display: block !important;
+
+    height: 100%;
+    min-height: 740px;
+
+    overflow-x: hidden;
+    overflow-y: auto;
+
+    background: rgb(215, 215, 215);
+    background: -o-radial-gradient(rgb(240, 240, 240), rgb(190, 190, 190));
+    background: -moz-radial-gradient(rgb(240, 240, 240), rgb(190, 190, 190));
+    background: -webkit-radial-gradient(rgb(240, 240, 240), rgb(190, 190, 190));
+    background: -webkit-gradient(radial, 50% 50%, 0, 50% 50%, 500, from(rgb(240, 240, 240)), to(rgb(190, 190, 190)));
+
+    -webkit-font-smoothing: antialiased;
+  }
+
+  .slides {
+    width: 100%;
+    height: 100%;
+    left: 0;
+    top: 0;
+
+    position: absolute;
+
+    -webkit-transform: translate3d(0, 0, 0);
+  }
+
+  .slides > article {
+    display: block;
+
+    position: absolute;
+    overflow: hidden;
+
+    width: 900px;
+    height: 700px;
+
+    left: 50%;
+    top: 50%;
+
+    margin-left: -450px;
+    margin-top: -350px;
+
+    padding: 40px 60px;
+
+    box-sizing: border-box;
+    -o-box-sizing: border-box;
+    -moz-box-sizing: border-box;
+    -webkit-box-sizing: border-box;
+
+    border-radius: 10px;
+    -o-border-radius: 10px;
+    -moz-border-radius: 10px;
+    -webkit-border-radius: 10px;
+
+    background-color: white;
+
+    border: 1px solid rgba(0, 0, 0, .3);
+
+    transition: transform .3s ease-out;
+    -o-transition: -o-transform .3s ease-out;
+    -moz-transition: -moz-transform .3s ease-out;
+    -webkit-transition: -webkit-transform .3s ease-out;
+  }
+  .slides.layout-widescreen > article {
+    margin-left: -550px;
+    width: 1100px;
+  }
+  .slides.layout-faux-widescreen > article {
+    margin-left: -550px;
+    width: 1100px;
+
+    padding: 40px 160px;
+  }
+
+  .slides.layout-widescreen > article:not(.nobackground):not(.biglogo),
+  .slides.layout-faux-widescreen > article:not(.nobackground):not(.biglogo) {
+    background-position-x: 0, 840px;
+  }
+
+  /* Clickable/tappable areas */
+
+  .slide-area {
+    z-index: 1000;
+
+    position: absolute;
+    left: 0;
+    top: 0;
+    width: 150px;
+    height: 700px;
+
+    left: 50%;
+    top: 50%;
+
+    cursor: pointer;
+    margin-top: -350px;
+
+    tap-highlight-color: transparent;
+    -o-tap-highlight-color: transparent;
+    -moz-tap-highlight-color: transparent;
+    -webkit-tap-highlight-color: transparent;
+  }
+  #prev-slide-area {
+    margin-left: -550px;
+  }
+  #next-slide-area {
+    margin-left: 400px;
+  }
+  .slides.layout-widescreen #prev-slide-area,
+  .slides.layout-faux-widescreen #prev-slide-area {
+    margin-left: -650px;
+  }
+  .slides.layout-widescreen #next-slide-area,
+  .slides.layout-faux-widescreen #next-slide-area {
+    margin-left: 500px;
+  }
+
+  /* Slides */
+
+  .slides > article {
+    display: none;
+  }
+  .slides > article.far-past {
+    display: block;
+    transform: translate(-2040px);
+    -o-transform: translate(-2040px);
+    -moz-transform: translate(-2040px);
+    -webkit-transform: translate3d(-2040px, 0, 0);
+  }
+  .slides > article.past {
+    display: block;
+    transform: translate(-1020px);
+    -o-transform: translate(-1020px);
+    -moz-transform: translate(-1020px);
+    -webkit-transform: translate3d(-1020px, 0, 0);
+  }
+  .slides > article.current {
+    display: block;
+    transform: translate(0);
+    -o-transform: translate(0);
+    -moz-transform: translate(0);
+    -webkit-transform: translate3d(0, 0, 0);
+  }
+  .slides > article.next {
+    display: block;
+    transform: translate(1020px);
+    -o-transform: translate(1020px);
+    -moz-transform: translate(1020px);
+    -webkit-transform: translate3d(1020px, 0, 0);
+  }
+  .slides > article.far-next {
+    display: block;
+    transform: translate(2040px);
+    -o-transform: translate(2040px);
+    -moz-transform: translate(2040px);
+    -webkit-transform: translate3d(2040px, 0, 0);
+  }
+
+  .slides.layout-widescreen > article.far-past,
+  .slides.layout-faux-widescreen > article.far-past {
+    display: block;
+    transform: translate(-2260px);
+    -o-transform: translate(-2260px);
+    -moz-transform: translate(-2260px);
+    -webkit-transform: translate3d(-2260px, 0, 0);
+  }
+  .slides.layout-widescreen > article.past,
+  .slides.layout-faux-widescreen > article.past {
+    display: block;
+    transform: translate(-1130px);
+    -o-transform: translate(-1130px);
+    -moz-transform: translate(-1130px);
+    -webkit-transform: translate3d(-1130px, 0, 0);
+  }
+  .slides.layout-widescreen > article.current,
+  .slides.layout-faux-widescreen > article.current {
+    display: block;
+    transform: translate(0);
+    -o-transform: translate(0);
+    -moz-transform: translate(0);
+    -webkit-transform: translate3d(0, 0, 0);
+  }
+  .slides.layout-widescreen > article.next,
+  .slides.layout-faux-widescreen > article.next {
+    display: block;
+    transform: translate(1130px);
+    -o-transform: translate(1130px);
+    -moz-transform: translate(1130px);
+    -webkit-transform: translate3d(1130px, 0, 0);
+  }
+  .slides.layout-widescreen > article.far-next,
+  .slides.layout-faux-widescreen > article.far-next {
+    display: block;
+    transform: translate(2260px);
+    -o-transform: translate(2260px);
+    -moz-transform: translate(2260px);
+    -webkit-transform: translate3d(2260px, 0, 0);
+  }
+}
+
+@media print {
+  /* Set page layout */
+  @page {
+    size: A4 landscape;
+  }
+
+  body {
+    display: block !important;
+  }
+
+  .slides > article {
+    display: block;
+
+    position: relative;
+
+    page-break-inside: never;
+    page-break-after: always;
+
+    overflow: hidden;
+  }
+
+  h2 {
+    position: static !important;
+    margin-top: 400px !important;
+    margin-bottom: 100px !important;
+  }
+
+  div.code {
+    background: rgb(240, 240, 240);
+  }
+
+  /* Add explicit links */
+  a:link:after, a:visited:after {
+   content: " (" attr(href) ") ";
+   font-size: 50%;
+  }
+
+  #help {
+    display: none;
+    visibility: hidden;
+  }
+}
+
+/* Styles for slides */
+
+.slides > article {
+  font-family: 'Open Sans', Arial, sans-serif;
+
+  color: black;
+  text-shadow: 0 1px 1px rgba(0, 0, 0, .1);
+
+  font-size: 26px;
+  line-height: 36px;
+
+  letter-spacing: -1px;
+}
+
+b {
+  font-weight: 600;
+}
+
+a {
+  color: rgb(0, 102, 204);
+  text-decoration: none;
+}
+a:visited {
+  color: rgba(0, 102, 204, .75);
+}
+a:hover {
+  color: black;
+}
+
+p {
+  margin: 0;
+  padding: 0;
+
+  margin-top: 20px;
+}
+p:first-child {
+  margin-top: 0;
+}
+
+h1 {
+  font-size: 60px;
+  line-height: 60px;
+
+  padding: 0;
+  margin: 0;
+  margin-top: 200px;
+  margin-bottom: 5px;
+  padding-right: 40px;
+
+  font-weight: 600;
+
+  letter-spacing: -3px;
+
+  color: rgb(51, 51, 51);
+}
+
+h2 {
+  font-size: 45px;
+  line-height: 45px;
+
+  position: absolute;
+  bottom: 150px;
+
+  padding: 0;
+  margin: 0;
+  padding-right: 40px;
+
+  font-weight: 600;
+
+  letter-spacing: -2px;
+
+  color: rgb(51, 51, 51);
+}
+
+h3 {
+  font-size: 30px;
+  line-height: 36px;
+
+  padding: 0;
+  margin: 0;
+  padding-right: 40px;
+
+  font-weight: 600;
+
+  letter-spacing: -1px;
+
+  color: rgb(51, 51, 51);
+}
+
+ul {
+  margin: 0;
+  padding: 0;
+  margin-top: 20px;
+  margin-left: 1.5em;
+}
+li {
+  padding: 0;
+  margin: 0 0 .5em 0;
+}
+
+div.code {
+  padding: 5px 10px;
+  margin-top: 20px;
+  margin-bottom: 20px;
+  overflow: hidden;
+
+  background: rgb(240, 240, 240);
+  border: 1px solid rgb(224, 224, 224);
+}
+pre {
+  margin: 0;
+  padding: 0;
+
+  font-family: 'Droid Sans Mono', 'Courier New', monospace;
+  font-size: 18px;
+  line-height: 24px;
+  letter-spacing: -1px;
+
+  color: black;
+}
+
+code {
+  font-size: 95%;
+  font-family: 'Droid Sans Mono', 'Courier New', monospace;
+
+  color: black;
+}
+
+article > .image {
+  text-align: center;
+  margin-top: 40px;
+}
+
+table {
+  width: 100%;
+  border-collapse: collapse;
+  margin-top: 40px;
+}
+th {
+  font-weight: 600;
+  text-align: left;
+}
+td,
+th {
+  border: 1px solid rgb(224, 224, 224);
+  padding: 5px 10px;
+  vertical-align: top;
+}
+
+p.link {
+  margin-left: 20px;
+}
+
+/* Code */
+div.code {
+  outline: 0px solid transparent;
+}
+div.playground {
+  position: relative;
+}
+div.output {
+  position: absolute;
+  left: 50%;
+  top: 50%;
+  right: 40px;
+  bottom: 40px;
+  background: #202020;
+  padding: 5px 10px;
+  z-index: 2;
+
+  border-radius: 10px;
+  -o-border-radius: 10px;
+  -moz-border-radius: 10px;
+  -webkit-border-radius: 10px;
+
+}
+div.output pre {
+  margin: 0;
+  padding: 0;
+  background: none;
+  border: none;
+  width: 100%;
+  height: 100%;
+  overflow: auto;
+}
+div.output .stdout, div.output pre {
+  color: #e6e6e6;
+}
+div.output .stderr, div.output .error {
+  color: rgb(255, 200, 200);
+}
+div.output .system, div.output .exit {
+  color: rgb(255, 230, 120)
+}
+.buttons {
+  position: relative;
+  float: right;
+  top: -60px;
+  right: 10px;
+}
+div.output .buttons {
+  position: absolute;
+  float: none;
+  top: auto;
+  right: 5px;
+  bottom: 5px;
+}
+
+/* Presenter details */
+.presenter {
+  margin-top: 20px;
+}
+.presenter p,
+.presenter .link {
+  margin: 0;
+  font-size: 28px;
+  line-height: 1.2em;
+}
+
+/* Output resize details */
+.ui-resizable-handle {
+  position: absolute;
+}
+.ui-resizable-n {
+  cursor: n-resize;
+  height: 7px;
+  width: 100%;
+  top: -5px;
+  left: 0;
+}
+.ui-resizable-w {
+  cursor: w-resize;
+  width: 7px;
+  left: -5px;
+  top: 0;
+  height: 100%;
+}
+.ui-resizable-nw {
+  cursor: nw-resize;
+  width: 9px;
+  height: 9px;
+  left: -5px;
+  top: -5px;
+}
+iframe {
+  border: none;
+}
+figcaption {
+  color: #666;
+  text-align: center;
+  font-size: 0.75em;
+}
+
+#help {
+  font-family: 'Open Sans', Arial, sans-serif;
+  text-align: center;
+  color: white;
+  background: #000;
+  opacity: 0.5;
+  position: fixed;
+  bottom: 25px;
+  left: 50px;
+  right: 50px;
+  padding: 20px;
+
+  border-radius: 10px;
+  -o-border-radius: 10px;
+  -moz-border-radius: 10px;
+  -webkit-border-radius: 10px;
+}
diff --git a/cmd/present/templates/action.tmpl b/cmd/present/templates/action.tmpl
new file mode 100644
index 0000000..2893058
--- /dev/null
+++ b/cmd/present/templates/action.tmpl
@@ -0,0 +1,48 @@
+{/*
+This is the action template.
+It determines how the formatting actions are rendered.
+*/}
+
+{{define "section"}}
+  <h{{len .Number}} id="TOC_{{.FormattedNumber}}">{{.FormattedNumber}} {{.Title}}</h{{len .Number}}>
+  {{range .Elem}}{{elem $.Template .}}{{end}}
+{{end}}
+
+{{define "list"}}
+  <ul>
+  {{range .Bullet}}
+    <li>{{style .}}</li>
+  {{end}}
+  </ul>
+{{end}}
+
+{{define "text"}}
+  {{if .Pre}}
+  <div class="code"><pre>{{range .Lines}}{{.}}{{end}}</pre></div>
+  {{else}}
+  <p>
+    {{range $i, $l := .Lines}}{{if $i}}{{template "newline"}}
+    {{end}}{{style $l}}{{end}}
+  </p>
+  {{end}}
+{{end}}
+
+{{define "code"}}
+  <div class="code{{if playable .}} playground{{end}}" contenteditable="true" spellcheck="false">{{.Text}}</div>
+{{end}}
+
+{{define "image"}}
+<div class="image">
+  <img src="{{.URL}}"{{with .Height}} height="{{.}}"{{end}}{{with .Width}} width="{{.}}"{{end}}>
+</div>
+{{end}}
+
+{{define "iframe"}}
+<iframe src="{{.URL}}"{{with .Height}} height="{{.}}"{{end}}{{with .Width}} width="{{.}}"{{end}}></iframe>
+{{end}}
+
+{{define "link"}}<p class="link"><a href="{{.URL}}" target="_blank">{{style .Label}}</a></p>{{end}}
+
+{{define "html"}}{{.HTML}}{{end}}
+
+{{define "caption"}}<figcaption>{{style .Text}}</figcaption>{{end}}
\ No newline at end of file
diff --git a/cmd/present/templates/article.tmpl b/cmd/present/templates/article.tmpl
new file mode 100644
index 0000000..40d1c93
--- /dev/null
+++ b/cmd/present/templates/article.tmpl
@@ -0,0 +1,58 @@
+{/* This is the article template. It defines how articles are formatted. */}
+
+{{define "root"}}
+<!DOCTYPE html>
+<html>
+  <head>
+    <title>{{.Title}}</title>
+    <link type="text/css" rel="stylesheet" href="/static/article.css">
+    <meta charset='utf-8'>
+  </head>
+
+  <body>
+    <div id="topbar" class="wide">
+      <div class="container">
+        <div id="heading">{{.Title}}
+          {{with .Subtitle}}{{.}}{{end}}
+        </div>
+      </div>
+    </div>
+    <div id="page" class="wide">
+      <div class="container">
+        {{with .Sections}}
+          <div id="toc">
+            {{template "TOC" .}}
+          </div>
+        {{end}}
+
+        {{range .Sections}}
+          {{elem $.Template .}}
+        {{end}}{{/* of Section block */}}
+
+        {{if .Authors}}
+          <h2>Authors</h2>
+          {{range .Authors}}
+            <div class="author">
+              {{range .Elem}}{{elem $.Template .}}{{end}}
+            </div>
+          {{end}}
+        {{end}}
+      </div>
+    </div>
+    <script src='/play.js'></script>
+  </body>
+</html>
+{{end}}
+
+{{define "TOC"}}
+  <ul>
+  {{range .}}
+    <li><a href="#TOC_{{.FormattedNumber}}">{{.Title}}</a></li>
+    {{with .Sections}}{{template "TOC" .}}{{end}}
+  {{end}}
+  </ul>
+{{end}}
+
+{{define "newline"}}
+{{/* No automatic line break. Paragraphs are free-form. */}}
+{{end}}
diff --git a/cmd/present/templates/dir.tmpl b/cmd/present/templates/dir.tmpl
new file mode 100644
index 0000000..15cf97f
--- /dev/null
+++ b/cmd/present/templates/dir.tmpl
@@ -0,0 +1,81 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+  <title>Talks - The Go Programming Language</title>
+  <link type="text/css" rel="stylesheet" href="/static/dir.css">
+  <script src="/static/dir.js"></script>
+</head>
+<body>
+
+<div id="topbar"><div class="container">
+
+<form method="GET" action="//golang.org/search">
+<div id="menu">
+<a href="http://golang.org/doc/">Documents</a>
+<a href="http://golang.org/ref">References</a>
+<a href="http://golang.org/pkg/">Packages</a>
+<a href="http://golang.org/project/">The Project</a>
+<a href="http://golang.org/help/">Help</a>
+<input type="text" id="search" name="q" class="inactive" value="Search">
+</div>
+<div id="heading"><a href="/">The Go Programming Language</a></div>
+</form>
+
+</div></div>
+
+<div id="page">
+
+  <h1>Go talks</h1>
+
+  {{with .Path}}<h2>{{.}}</h2>{{end}}
+
+  {{with .Articles}}
+  <h4>Articles:</h4>
+  <dl>
+  {{range .}}
+  <dd><a href="/{{.Path}}">{{.Name}}</a>: {{.Title}}</dd>
+  {{end}}
+  </dl>
+  {{end}}
+
+  {{with .Slides}}
+  <h4>Slide decks:</h4>
+  <dl>
+  {{range .}}
+  <dd><a href="/{{.Path}}">{{.Name}}</a>: {{.Title}}</dd>
+  {{end}}
+  </dl>
+  {{end}}
+
+  {{with .Other}}
+  <h4>Files:</h4>
+  <dl>
+  {{range .}}
+  <dd><a href="/{{.Path}}">{{.Name}}</a></dd>
+  {{end}}
+  </dl>
+  {{end}}
+
+  {{with .Dirs}}
+  <h4>Sub-directories:</h4>
+  <dl>
+  {{range .}}
+  <dd><a href="/{{.Path}}">{{.Name}}</a></dd>
+  {{end}}
+  </dl>
+  {{end}}
+
+</div>
+
+<div id="footer">
+Except as <a href="https://developers.google.com/site-policies#restrictions">noted</a>,
+the content of this page is licensed under the
+Creative Commons Attribution 3.0 License,
+and code is licensed under a <a href="http://golang.org/LICENSE">BSD license</a>.<br>
+<a href="http://golang.org/doc/tos.html">Terms of Service</a> |
+<a href="http://www.google.com/intl/en/policies/privacy/">Privacy Policy</a>
+</div>
+
+</body>
+</html>
diff --git a/cmd/present/templates/slides.tmpl b/cmd/present/templates/slides.tmpl
new file mode 100644
index 0000000..11070d2
--- /dev/null
+++ b/cmd/present/templates/slides.tmpl
@@ -0,0 +1,66 @@
+{/* This is the slide template. It defines how presentations are formatted. */}
+
+{{define "root"}}
+<!DOCTYPE html>
+<html>
+  <head>
+    <title>{{.Title}}</title>
+    <meta charset='utf-8'>
+    <script src='/static/slides.js'></script>
+  </head>
+
+  <body style='display: none'>
+
+    <section class='slides layout-widescreen'>
+      
+      <article>
+        <h1>{{.Title}}</h1>
+        {{with .Subtitle}}<h3>{{.}}</h3>{{end}}
+        {{if not .Time.IsZero}}<h3>{{.Time.Format "2 January 2006"}}</h3>{{end}}
+        {{range .Authors}}
+          <div class="presenter">
+            {{range .TextElem}}{{elem $.Template .}}{{end}}
+          </div>
+        {{end}}
+      </article>
+      
+  {{range $i, $s := .Sections}}
+  <!-- start of slide {{$s.Number}} -->
+      <article>
+      {{if $s.Elem}}
+        <h3>{{$s.Title}}</h3>
+        {{range $s.Elem}}{{elem $.Template .}}{{end}}
+      {{else}}
+        <h2>{{$s.Title}}</h2>
+      {{end}}
+      </article>
+  <!-- end of slide {{$i}} -->
+  {{end}}{{/* of Slide block */}}
+
+      <article>
+        <h3>Thank you</h3>
+        {{range .Authors}}
+          <div class="presenter">
+            {{range .Elem}}{{elem $.Template .}}{{end}}
+          </div>
+        {{end}}
+      </article>
+
+    </section>
+
+    <div id="help">
+      Use the left and right arrow keys or click the left and right
+      edges of the page to navigate between slides.<br>
+      (Press 'H' or navigate to hide this message.)
+    </div>
+
+  </body>
+  {{if .PlayEnabled}}
+  <script src='/play.js'></script>
+  {{end}}
+</html>
+{{end}}
+
+{{define "newline"}}
+<br>
+{{end}}
diff --git a/cmd/ssadump/main.go b/cmd/ssadump/main.go
new file mode 100644
index 0000000..75f1601
--- /dev/null
+++ b/cmd/ssadump/main.go
@@ -0,0 +1,186 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// ssadump: a tool for displaying and interpreting the SSA form of Go programs.
+package main // import "golang.org/x/tools/cmd/ssadump"
+
+import (
+	"flag"
+	"fmt"
+	"go/build"
+	"os"
+	"runtime"
+	"runtime/pprof"
+
+	"golang.org/x/tools/go/buildutil"
+	"golang.org/x/tools/go/loader"
+	"golang.org/x/tools/go/ssa"
+	"golang.org/x/tools/go/ssa/interp"
+	"golang.org/x/tools/go/ssa/ssautil"
+	"golang.org/x/tools/go/types"
+)
+
+var (
+	modeFlag = ssa.BuilderModeFlag(flag.CommandLine, "build", 0)
+
+	testFlag = flag.Bool("test", false, "Loads test code (*_test.go) for imported packages.")
+
+	runFlag = flag.Bool("run", false, "Invokes the SSA interpreter on the program.")
+
+	interpFlag = flag.String("interp", "", `Options controlling the SSA test interpreter.
+The value is a sequence of zero or more more of these letters:
+R	disable [R]ecover() from panic; show interpreter crash instead.
+T	[T]race execution of the program.  Best for single-threaded programs!
+`)
+)
+
+const usage = `SSA builder and interpreter.
+Usage: ssadump [<flag> ...] <args> ...
+Use -help flag to display options.
+
+Examples:
+% ssadump -build=F hello.go              # dump SSA form of a single package
+% ssadump -run -interp=T hello.go        # interpret a program, with tracing
+% ssadump -run -test unicode -- -test.v  # interpret the unicode package's tests, verbosely
+` + loader.FromArgsUsage +
+	`
+When -run is specified, ssadump will run the program.
+The entry point depends on the -test flag:
+if clear, it runs the first package named main.
+if set, it runs the tests of each package.
+`
+
+var cpuprofile = flag.String("cpuprofile", "", "write cpu profile to file")
+
+func init() {
+	flag.Var((*buildutil.TagsFlag)(&build.Default.BuildTags), "tags", buildutil.TagsFlagDoc)
+
+	// If $GOMAXPROCS isn't set, use the full capacity of the machine.
+	// For small machines, use at least 4 threads.
+	if os.Getenv("GOMAXPROCS") == "" {
+		n := runtime.NumCPU()
+		if n < 4 {
+			n = 4
+		}
+		runtime.GOMAXPROCS(n)
+	}
+}
+
+func main() {
+	if err := doMain(); err != nil {
+		fmt.Fprintf(os.Stderr, "ssadump: %s\n", err)
+		os.Exit(1)
+	}
+}
+
+func doMain() error {
+	flag.Parse()
+	args := flag.Args()
+
+	conf := loader.Config{Build: &build.Default}
+
+	// Choose types.Sizes from conf.Build.
+	var wordSize int64 = 8
+	switch conf.Build.GOARCH {
+	case "386", "arm":
+		wordSize = 4
+	}
+	conf.TypeChecker.Sizes = &types.StdSizes{
+		MaxAlign: 8,
+		WordSize: wordSize,
+	}
+
+	var interpMode interp.Mode
+	for _, c := range *interpFlag {
+		switch c {
+		case 'T':
+			interpMode |= interp.EnableTracing
+		case 'R':
+			interpMode |= interp.DisableRecover
+		default:
+			return fmt.Errorf("unknown -interp option: '%c'", c)
+		}
+	}
+
+	if len(args) == 0 {
+		fmt.Fprint(os.Stderr, usage)
+		os.Exit(1)
+	}
+
+	// Profiling support.
+	if *cpuprofile != "" {
+		f, err := os.Create(*cpuprofile)
+		if err != nil {
+			fmt.Fprintln(os.Stderr, err)
+			os.Exit(1)
+		}
+		pprof.StartCPUProfile(f)
+		defer pprof.StopCPUProfile()
+	}
+
+	// Use the initial packages from the command line.
+	args, err := conf.FromArgs(args, *testFlag)
+	if err != nil {
+		return err
+	}
+
+	// The interpreter needs the runtime package.
+	if *runFlag {
+		conf.Import("runtime")
+	}
+
+	// Load, parse and type-check the whole program.
+	iprog, err := conf.Load()
+	if err != nil {
+		return err
+	}
+
+	// Create and build SSA-form program representation.
+	prog := ssautil.CreateProgram(iprog, *modeFlag)
+
+	// Build and display only the initial packages
+	// (and synthetic wrappers), unless -run is specified.
+	for _, info := range iprog.InitialPackages() {
+		prog.Package(info.Pkg).Build()
+	}
+
+	// Run the interpreter.
+	if *runFlag {
+		prog.BuildAll()
+
+		var main *ssa.Package
+		pkgs := prog.AllPackages()
+		if *testFlag {
+			// If -test, run all packages' tests.
+			if len(pkgs) > 0 {
+				main = prog.CreateTestMainPackage(pkgs...)
+			}
+			if main == nil {
+				return fmt.Errorf("no tests")
+			}
+		} else {
+			// Otherwise, run main.main.
+			for _, pkg := range pkgs {
+				if pkg.Object.Name() == "main" {
+					main = pkg
+					if main.Func("main") == nil {
+						return fmt.Errorf("no func main() in main package")
+					}
+					break
+				}
+			}
+			if main == nil {
+				return fmt.Errorf("no main package")
+			}
+		}
+
+		if runtime.GOARCH != build.Default.GOARCH {
+			return fmt.Errorf("cross-interpretation is not supported (target has GOARCH %s, interpreter has %s)",
+				build.Default.GOARCH, runtime.GOARCH)
+		}
+
+		interp.Interpret(main, interpMode, conf.TypeChecker.Sizes, main.Object.Path(), args)
+	}
+	return nil
+}
diff --git a/cmd/stress/stress.go b/cmd/stress/stress.go
new file mode 100644
index 0000000..e0ff6b4
--- /dev/null
+++ b/cmd/stress/stress.go
@@ -0,0 +1,122 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// TODO: syscall.SIGABRT is not defined for Plan 9 (issue #11975)
+
+// +build !plan9
+
+// The stress utility is intended for catching of episodic failures.
+// It runs a given process in parallel in a loop and collects any failures.
+// Usage:
+// 	$ stress ./fmt.test -test.run=TestSometing -test.cpu=10
+// You can also specify a number of parallel processes with -p flag;
+// instruct the utility to not kill hanged processes for gdb attach;
+// or specify the failure output you are looking for (if you want to
+// ignore some other episodic failures).
+package main
+
+import (
+	"flag"
+	"fmt"
+	"io/ioutil"
+	"os"
+	"os/exec"
+	"regexp"
+	"runtime"
+	"syscall"
+	"time"
+)
+
+var (
+	flagP       = flag.Int("p", runtime.NumCPU(), "run `N` processes in parallel")
+	flagTimeout = flag.Duration("timeout", 10*time.Minute, "timeout each process after `duration`")
+	flagKill    = flag.Bool("kill", true, "kill timed out processes if true, otherwise just print pid (to attach with gdb)")
+	flagFailure = flag.String("failure", "", "fail only if output matches `regexp`")
+	flagIgnore  = flag.String("ignore", "", "ignore failure if output matches `regexp`")
+)
+
+func main() {
+	flag.Parse()
+	if *flagP <= 0 || *flagTimeout <= 0 || len(flag.Args()) == 0 {
+		flag.Usage()
+		os.Exit(1)
+	}
+	var failureRe, ignoreRe *regexp.Regexp
+	if *flagFailure != "" {
+		var err error
+		if failureRe, err = regexp.Compile(*flagFailure); err != nil {
+			fmt.Println("bad failure regexp:", err)
+			os.Exit(1)
+		}
+	}
+	if *flagIgnore != "" {
+		var err error
+		if ignoreRe, err = regexp.Compile(*flagIgnore); err != nil {
+			fmt.Println("bad ignore regexp:", err)
+			os.Exit(1)
+		}
+	}
+	res := make(chan []byte)
+	for i := 0; i < *flagP; i++ {
+		go func() {
+			for {
+				cmd := exec.Command(flag.Args()[0], flag.Args()[1:]...)
+				done := make(chan bool)
+				if *flagTimeout > 0 {
+					go func() {
+						select {
+						case <-done:
+							return
+						case <-time.After(*flagTimeout):
+						}
+						if !*flagKill {
+							fmt.Printf("process %v timed out\n", cmd.Process.Pid)
+							return
+						}
+						cmd.Process.Signal(syscall.SIGABRT)
+						select {
+						case <-done:
+							return
+						case <-time.After(10 * time.Second):
+						}
+						cmd.Process.Kill()
+					}()
+				}
+				out, err := cmd.CombinedOutput()
+				close(done)
+				if err != nil && (failureRe == nil || failureRe.Match(out)) && (ignoreRe == nil || !ignoreRe.Match(out)) {
+					out = append(out, fmt.Sprintf("\n\nERROR: %v\n", err)...)
+				} else {
+					out = []byte{}
+				}
+				res <- out
+			}
+		}()
+	}
+	runs, fails := 0, 0
+	ticker := time.NewTicker(5 * time.Second).C
+	for {
+		select {
+		case out := <-res:
+			runs++
+			if len(out) == 0 {
+				continue
+			}
+			fails++
+			f, err := ioutil.TempFile("", "go-stress")
+			if err != nil {
+				fmt.Printf("failed to create temp file: %v\n", err)
+				os.Exit(1)
+			}
+			f.Write(out)
+			f.Close()
+			if len(out) > 2<<10 {
+				out = out[:2<<10]
+			}
+			fmt.Printf("\n%s\n%s\n", f.Name(), out)
+		case <-ticker:
+			fmt.Printf("%v runs so far, %v failures\n", runs, fails)
+		}
+	}
+}
diff --git a/cmd/stringer/endtoend_test.go b/cmd/stringer/endtoend_test.go
new file mode 100644
index 0000000..d71a6c1
--- /dev/null
+++ b/cmd/stringer/endtoend_test.go
@@ -0,0 +1,111 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// go command is not available on android
+
+// +build !android
+
+package main
+
+import (
+	"fmt"
+	"go/build"
+	"io"
+	"io/ioutil"
+	"os"
+	"os/exec"
+	"path/filepath"
+	"strings"
+	"testing"
+)
+
+// This file contains a test that compiles and runs each program in testdata
+// after generating the string method for its type. The rule is that for testdata/x.go
+// we run stringer -type X and then compile and run the program. The resulting
+// binary panics if the String method for X is not correct, including for error cases.
+
+func TestEndToEnd(t *testing.T) {
+	dir, err := ioutil.TempDir("", "stringer")
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer os.RemoveAll(dir)
+	// Create stringer in temporary directory.
+	stringer := filepath.Join(dir, "stringer.exe")
+	err = run("go", "build", "-o", stringer, "stringer.go")
+	if err != nil {
+		t.Fatalf("building stringer: %s", err)
+	}
+	// Read the testdata directory.
+	fd, err := os.Open("testdata")
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer fd.Close()
+	names, err := fd.Readdirnames(-1)
+	if err != nil {
+		t.Fatalf("Readdirnames: %s", err)
+	}
+	// Generate, compile, and run the test programs.
+	for _, name := range names {
+		if !strings.HasSuffix(name, ".go") {
+			t.Errorf("%s is not a Go file", name)
+			continue
+		}
+		if name == "cgo.go" && !build.Default.CgoEnabled {
+			t.Logf("cgo is no enabled for %s", name)
+			continue
+		}
+		// Names are known to be ASCII and long enough.
+		typeName := fmt.Sprintf("%c%s", name[0]+'A'-'a', name[1:len(name)-len(".go")])
+		stringerCompileAndRun(t, dir, stringer, typeName, name)
+	}
+}
+
+// stringerCompileAndRun runs stringer for the named file and compiles and
+// runs the target binary in directory dir. That binary will panic if the String method is incorrect.
+func stringerCompileAndRun(t *testing.T, dir, stringer, typeName, fileName string) {
+	t.Logf("run: %s %s\n", fileName, typeName)
+	source := filepath.Join(dir, fileName)
+	err := copy(source, filepath.Join("testdata", fileName))
+	if err != nil {
+		t.Fatalf("copying file to temporary directory: %s", err)
+	}
+	stringSource := filepath.Join(dir, typeName+"_string.go")
+	// Run stringer in temporary directory.
+	err = run(stringer, "-type", typeName, "-output", stringSource, source)
+	if err != nil {
+		t.Fatal(err)
+	}
+	// Run the binary in the temporary directory.
+	err = run("go", "run", stringSource, source)
+	if err != nil {
+		t.Fatal(err)
+	}
+}
+
+// copy copies the from file to the to file.
+func copy(to, from string) error {
+	toFd, err := os.Create(to)
+	if err != nil {
+		return err
+	}
+	defer toFd.Close()
+	fromFd, err := os.Open(from)
+	if err != nil {
+		return err
+	}
+	defer fromFd.Close()
+	_, err = io.Copy(toFd, fromFd)
+	return err
+}
+
+// run runs a single command and returns an error if it does not succeed.
+// os/exec should have this function, to be honest.
+func run(name string, arg ...string) error {
+	cmd := exec.Command(name, arg...)
+	cmd.Stdout = os.Stdout
+	cmd.Stderr = os.Stderr
+	return cmd.Run()
+}
diff --git a/cmd/stringer/golden_test.go b/cmd/stringer/golden_test.go
new file mode 100644
index 0000000..12df238
--- /dev/null
+++ b/cmd/stringer/golden_test.go
@@ -0,0 +1,258 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file contains simple golden tests for various examples.
+// Besides validating the results when the implementation changes,
+// it provides a way to look at the generated code without having
+// to execute the print statements in one's head.
+
+package main
+
+import (
+	"strings"
+	"testing"
+)
+
+// Golden represents a test case.
+type Golden struct {
+	name   string
+	input  string // input; the package clause is provided when running the test.
+	output string // exected output.
+}
+
+var golden = []Golden{
+	{"day", day_in, day_out},
+	{"offset", offset_in, offset_out},
+	{"gap", gap_in, gap_out},
+	{"num", num_in, num_out},
+	{"unum", unum_in, unum_out},
+	{"prime", prime_in, prime_out},
+}
+
+// Each example starts with "type XXX [u]int", with a single space separating them.
+
+// Simple test: enumeration of type int starting at 0.
+const day_in = `type Day int
+const (
+	Monday Day = iota
+	Tuesday
+	Wednesday
+	Thursday
+	Friday
+	Saturday
+	Sunday
+)
+`
+
+const day_out = `
+const _Day_name = "MondayTuesdayWednesdayThursdayFridaySaturdaySunday"
+
+var _Day_index = [...]uint8{0, 6, 13, 22, 30, 36, 44, 50}
+
+func (i Day) String() string {
+	if i < 0 || i >= Day(len(_Day_index)-1) {
+		return fmt.Sprintf("Day(%d)", i)
+	}
+	return _Day_name[_Day_index[i]:_Day_index[i+1]]
+}
+`
+
+// Enumeration with an offset.
+// Also includes a duplicate.
+const offset_in = `type Number int
+const (
+	_ Number = iota
+	One
+	Two
+	Three
+	AnotherOne = One  // Duplicate; note that AnotherOne doesn't appear below.
+)
+`
+
+const offset_out = `
+const _Number_name = "OneTwoThree"
+
+var _Number_index = [...]uint8{0, 3, 6, 11}
+
+func (i Number) String() string {
+	i -= 1
+	if i < 0 || i >= Number(len(_Number_index)-1) {
+		return fmt.Sprintf("Number(%d)", i+1)
+	}
+	return _Number_name[_Number_index[i]:_Number_index[i+1]]
+}
+`
+
+// Gaps and an offset.
+const gap_in = `type Gap int
+const (
+	Two Gap = 2
+	Three Gap = 3
+	Five Gap = 5
+	Six Gap = 6
+	Seven Gap = 7
+	Eight Gap = 8
+	Nine Gap = 9
+	Eleven Gap = 11
+)
+`
+
+const gap_out = `
+const (
+	_Gap_name_0 = "TwoThree"
+	_Gap_name_1 = "FiveSixSevenEightNine"
+	_Gap_name_2 = "Eleven"
+)
+
+var (
+	_Gap_index_0 = [...]uint8{0, 3, 8}
+	_Gap_index_1 = [...]uint8{0, 4, 7, 12, 17, 21}
+	_Gap_index_2 = [...]uint8{0, 6}
+)
+
+func (i Gap) String() string {
+	switch {
+	case 2 <= i && i <= 3:
+		i -= 2
+		return _Gap_name_0[_Gap_index_0[i]:_Gap_index_0[i+1]]
+	case 5 <= i && i <= 9:
+		i -= 5
+		return _Gap_name_1[_Gap_index_1[i]:_Gap_index_1[i+1]]
+	case i == 11:
+		return _Gap_name_2
+	default:
+		return fmt.Sprintf("Gap(%d)", i)
+	}
+}
+`
+
+// Signed integers spanning zero.
+const num_in = `type Num int
+const (
+	m_2 Num = -2 + iota
+	m_1
+	m0
+	m1
+	m2
+)
+`
+
+const num_out = `
+const _Num_name = "m_2m_1m0m1m2"
+
+var _Num_index = [...]uint8{0, 3, 6, 8, 10, 12}
+
+func (i Num) String() string {
+	i -= -2
+	if i < 0 || i >= Num(len(_Num_index)-1) {
+		return fmt.Sprintf("Num(%d)", i+-2)
+	}
+	return _Num_name[_Num_index[i]:_Num_index[i+1]]
+}
+`
+
+// Unsigned integers spanning zero.
+const unum_in = `type Unum uint
+const (
+	m_2 Unum = iota + 253
+	m_1
+)
+
+const (
+	m0 Unum = iota
+	m1
+	m2
+)
+`
+
+const unum_out = `
+const (
+	_Unum_name_0 = "m0m1m2"
+	_Unum_name_1 = "m_2m_1"
+)
+
+var (
+	_Unum_index_0 = [...]uint8{0, 2, 4, 6}
+	_Unum_index_1 = [...]uint8{0, 3, 6}
+)
+
+func (i Unum) String() string {
+	switch {
+	case 0 <= i && i <= 2:
+		return _Unum_name_0[_Unum_index_0[i]:_Unum_index_0[i+1]]
+	case 253 <= i && i <= 254:
+		i -= 253
+		return _Unum_name_1[_Unum_index_1[i]:_Unum_index_1[i+1]]
+	default:
+		return fmt.Sprintf("Unum(%d)", i)
+	}
+}
+`
+
+// Enough gaps to trigger a map implementation of the method.
+// Also includes a duplicate to test that it doesn't cause problems
+const prime_in = `type Prime int
+const (
+	p2 Prime = 2
+	p3 Prime = 3
+	p5 Prime = 5
+	p7 Prime = 7
+	p77 Prime = 7 // Duplicate; note that p77 doesn't appear below.
+	p11 Prime = 11
+	p13 Prime = 13
+	p17 Prime = 17
+	p19 Prime = 19
+	p23 Prime = 23
+	p29 Prime = 29
+	p37 Prime = 31
+	p41 Prime = 41
+	p43 Prime = 43
+)
+`
+
+const prime_out = `
+const _Prime_name = "p2p3p5p7p11p13p17p19p23p29p37p41p43"
+
+var _Prime_map = map[Prime]string{
+	2:  _Prime_name[0:2],
+	3:  _Prime_name[2:4],
+	5:  _Prime_name[4:6],
+	7:  _Prime_name[6:8],
+	11: _Prime_name[8:11],
+	13: _Prime_name[11:14],
+	17: _Prime_name[14:17],
+	19: _Prime_name[17:20],
+	23: _Prime_name[20:23],
+	29: _Prime_name[23:26],
+	31: _Prime_name[26:29],
+	41: _Prime_name[29:32],
+	43: _Prime_name[32:35],
+}
+
+func (i Prime) String() string {
+	if str, ok := _Prime_map[i]; ok {
+		return str
+	}
+	return fmt.Sprintf("Prime(%d)", i)
+}
+`
+
+func TestGolden(t *testing.T) {
+	for _, test := range golden {
+		var g Generator
+		input := "package test\n" + test.input
+		file := test.name + ".go"
+		g.parsePackage(".", []string{file}, input)
+		// Extract the name and type of the constant from the first line.
+		tokens := strings.SplitN(test.input, " ", 3)
+		if len(tokens) != 3 {
+			t.Fatalf("%s: need type declaration on first line", test.name)
+		}
+		g.generate(tokens[1])
+		got := string(g.format())
+		if got != test.output {
+			t.Errorf("%s: got\n====\n%s====\nexpected\n====%s", test.name, got, test.output)
+		}
+	}
+}
diff --git a/cmd/stringer/stringer.go b/cmd/stringer/stringer.go
new file mode 100644
index 0000000..be87dec
--- /dev/null
+++ b/cmd/stringer/stringer.go
@@ -0,0 +1,638 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Stringer is a tool to automate the creation of methods that satisfy the fmt.Stringer
+// interface. Given the name of a (signed or unsigned) integer type T that has constants
+// defined, stringer will create a new self-contained Go source file implementing
+//	func (t T) String() string
+// The file is created in the same package and directory as the package that defines T.
+// It has helpful defaults designed for use with go generate.
+//
+// Stringer works best with constants that are consecutive values such as created using iota,
+// but creates good code regardless. In the future it might also provide custom support for
+// constant sets that are bit patterns.
+//
+// For example, given this snippet,
+//
+//	package painkiller
+//
+//	type Pill int
+//
+//	const (
+//		Placebo Pill = iota
+//		Aspirin
+//		Ibuprofen
+//		Paracetamol
+//		Acetaminophen = Paracetamol
+//	)
+//
+// running this command
+//
+//	stringer -type=Pill
+//
+// in the same directory will create the file pill_string.go, in package painkiller,
+// containing a definition of
+//
+//	func (Pill) String() string
+//
+// That method will translate the value of a Pill constant to the string representation
+// of the respective constant name, so that the call fmt.Print(painkiller.Aspirin) will
+// print the string "Aspirin".
+//
+// Typically this process would be run using go generate, like this:
+//
+//	//go:generate stringer -type=Pill
+//
+// If multiple constants have the same value, the lexically first matching name will
+// be used (in the example, Acetaminophen will print as "Paracetamol").
+//
+// With no arguments, it processes the package in the current directory.
+// Otherwise, the arguments must name a single directory holding a Go package
+// or a set of Go source files that represent a single Go package.
+//
+// The -type flag accepts a comma-separated list of types so a single run can
+// generate methods for multiple types. The default output file is t_string.go,
+// where t is the lower-cased name of the first type listed. It can be overridden
+// with the -output flag.
+//
+package main // import "golang.org/x/tools/cmd/stringer"
+
+import (
+	"bytes"
+	"flag"
+	"fmt"
+	"go/ast"
+	"go/build"
+	"go/format"
+	"go/parser"
+	"go/token"
+	"io/ioutil"
+	"log"
+	"os"
+	"path/filepath"
+	"sort"
+	"strings"
+
+	"golang.org/x/tools/go/exact"
+	"golang.org/x/tools/go/types"
+
+	_ "golang.org/x/tools/go/gcimporter"
+)
+
+var (
+	typeNames = flag.String("type", "", "comma-separated list of type names; must be set")
+	output    = flag.String("output", "", "output file name; default srcdir/<type>_string.go")
+)
+
+// Usage is a replacement usage function for the flags package.
+func Usage() {
+	fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0])
+	fmt.Fprintf(os.Stderr, "\tstringer [flags] -type T [directory]\n")
+	fmt.Fprintf(os.Stderr, "\tstringer [flags[ -type T files... # Must be a single package\n")
+	fmt.Fprintf(os.Stderr, "For more information, see:\n")
+	fmt.Fprintf(os.Stderr, "\thttp://godoc.org/golang.org/x/tools/cmd/stringer\n")
+	fmt.Fprintf(os.Stderr, "Flags:\n")
+	flag.PrintDefaults()
+}
+
+func main() {
+	log.SetFlags(0)
+	log.SetPrefix("stringer: ")
+	flag.Usage = Usage
+	flag.Parse()
+	if len(*typeNames) == 0 {
+		flag.Usage()
+		os.Exit(2)
+	}
+	types := strings.Split(*typeNames, ",")
+
+	// We accept either one directory or a list of files. Which do we have?
+	args := flag.Args()
+	if len(args) == 0 {
+		// Default: process whole package in current directory.
+		args = []string{"."}
+	}
+
+	// Parse the package once.
+	var (
+		dir string
+		g   Generator
+	)
+	if len(args) == 1 && isDirectory(args[0]) {
+		dir = args[0]
+		g.parsePackageDir(args[0])
+	} else {
+		dir = filepath.Dir(args[0])
+		g.parsePackageFiles(args)
+	}
+
+	// Print the header and package clause.
+	g.Printf("// generated by stringer %s; DO NOT EDIT\n", strings.Join(os.Args[1:], " "))
+	g.Printf("\n")
+	g.Printf("package %s", g.pkg.name)
+	g.Printf("\n")
+	g.Printf("import \"fmt\"\n") // Used by all methods.
+
+	// Run generate for each type.
+	for _, typeName := range types {
+		g.generate(typeName)
+	}
+
+	// Format the output.
+	src := g.format()
+
+	// Write to file.
+	outputName := *output
+	if outputName == "" {
+		baseName := fmt.Sprintf("%s_string.go", types[0])
+		outputName = filepath.Join(dir, strings.ToLower(baseName))
+	}
+	err := ioutil.WriteFile(outputName, src, 0644)
+	if err != nil {
+		log.Fatalf("writing output: %s", err)
+	}
+}
+
+// isDirectory reports whether the named file is a directory.
+func isDirectory(name string) bool {
+	info, err := os.Stat(name)
+	if err != nil {
+		log.Fatal(err)
+	}
+	return info.IsDir()
+}
+
+// Generator holds the state of the analysis. Primarily used to buffer
+// the output for format.Source.
+type Generator struct {
+	buf bytes.Buffer // Accumulated output.
+	pkg *Package     // Package we are scanning.
+}
+
+func (g *Generator) Printf(format string, args ...interface{}) {
+	fmt.Fprintf(&g.buf, format, args...)
+}
+
+// File holds a single parsed file and associated data.
+type File struct {
+	pkg  *Package  // Package to which this file belongs.
+	file *ast.File // Parsed AST.
+	// These fields are reset for each type being generated.
+	typeName string  // Name of the constant type.
+	values   []Value // Accumulator for constant values of that type.
+}
+
+type Package struct {
+	dir      string
+	name     string
+	defs     map[*ast.Ident]types.Object
+	files    []*File
+	typesPkg *types.Package
+}
+
+// parsePackageDir parses the package residing in the directory.
+func (g *Generator) parsePackageDir(directory string) {
+	pkg, err := build.Default.ImportDir(directory, 0)
+	if err != nil {
+		log.Fatalf("cannot process directory %s: %s", directory, err)
+	}
+	var names []string
+	names = append(names, pkg.GoFiles...)
+	names = append(names, pkg.CgoFiles...)
+	// TODO: Need to think about constants in test files. Maybe write type_string_test.go
+	// in a separate pass? For later.
+	// names = append(names, pkg.TestGoFiles...) // These are also in the "foo" package.
+	names = append(names, pkg.SFiles...)
+	names = prefixDirectory(directory, names)
+	g.parsePackage(directory, names, nil)
+}
+
+// parsePackageFiles parses the package occupying the named files.
+func (g *Generator) parsePackageFiles(names []string) {
+	g.parsePackage(".", names, nil)
+}
+
+// prefixDirectory places the directory name on the beginning of each name in the list.
+func prefixDirectory(directory string, names []string) []string {
+	if directory == "." {
+		return names
+	}
+	ret := make([]string, len(names))
+	for i, name := range names {
+		ret[i] = filepath.Join(directory, name)
+	}
+	return ret
+}
+
+// parsePackage analyzes the single package constructed from the named files.
+// If text is non-nil, it is a string to be used instead of the content of the file,
+// to be used for testing. parsePackage exits if there is an error.
+func (g *Generator) parsePackage(directory string, names []string, text interface{}) {
+	var files []*File
+	var astFiles []*ast.File
+	g.pkg = new(Package)
+	fs := token.NewFileSet()
+	for _, name := range names {
+		if !strings.HasSuffix(name, ".go") {
+			continue
+		}
+		parsedFile, err := parser.ParseFile(fs, name, text, 0)
+		if err != nil {
+			log.Fatalf("parsing package: %s: %s", name, err)
+		}
+		astFiles = append(astFiles, parsedFile)
+		files = append(files, &File{
+			file: parsedFile,
+			pkg:  g.pkg,
+		})
+	}
+	if len(astFiles) == 0 {
+		log.Fatalf("%s: no buildable Go files", directory)
+	}
+	g.pkg.name = astFiles[0].Name.Name
+	g.pkg.files = files
+	g.pkg.dir = directory
+	// Type check the package.
+	g.pkg.check(fs, astFiles)
+}
+
+// check type-checks the package. The package must be OK to proceed.
+func (pkg *Package) check(fs *token.FileSet, astFiles []*ast.File) {
+	pkg.defs = make(map[*ast.Ident]types.Object)
+	config := types.Config{FakeImportC: true}
+	info := &types.Info{
+		Defs: pkg.defs,
+	}
+	typesPkg, err := config.Check(pkg.dir, fs, astFiles, info)
+	if err != nil {
+		log.Fatalf("checking package: %s", err)
+	}
+	pkg.typesPkg = typesPkg
+}
+
+// generate produces the String method for the named type.
+func (g *Generator) generate(typeName string) {
+	values := make([]Value, 0, 100)
+	for _, file := range g.pkg.files {
+		// Set the state for this run of the walker.
+		file.typeName = typeName
+		file.values = nil
+		if file.file != nil {
+			ast.Inspect(file.file, file.genDecl)
+			values = append(values, file.values...)
+		}
+	}
+
+	if len(values) == 0 {
+		log.Fatalf("no values defined for type %s", typeName)
+	}
+	runs := splitIntoRuns(values)
+	// The decision of which pattern to use depends on the number of
+	// runs in the numbers. If there's only one, it's easy. For more than
+	// one, there's a tradeoff between complexity and size of the data
+	// and code vs. the simplicity of a map. A map takes more space,
+	// but so does the code. The decision here (crossover at 10) is
+	// arbitrary, but considers that for large numbers of runs the cost
+	// of the linear scan in the switch might become important, and
+	// rather than use yet another algorithm such as binary search,
+	// we punt and use a map. In any case, the likelihood of a map
+	// being necessary for any realistic example other than bitmasks
+	// is very low. And bitmasks probably deserve their own analysis,
+	// to be done some other day.
+	switch {
+	case len(runs) == 1:
+		g.buildOneRun(runs, typeName)
+	case len(runs) <= 10:
+		g.buildMultipleRuns(runs, typeName)
+	default:
+		g.buildMap(runs, typeName)
+	}
+}
+
+// splitIntoRuns breaks the values into runs of contiguous sequences.
+// For example, given 1,2,3,5,6,7 it returns {1,2,3},{5,6,7}.
+// The input slice is known to be non-empty.
+func splitIntoRuns(values []Value) [][]Value {
+	// We use stable sort so the lexically first name is chosen for equal elements.
+	sort.Stable(byValue(values))
+	// Remove duplicates. Stable sort has put the one we want to print first,
+	// so use that one. The String method won't care about which named constant
+	// was the argument, so the first name for the given value is the only one to keep.
+	// We need to do this because identical values would cause the switch or map
+	// to fail to compile.
+	j := 1
+	for i := 1; i < len(values); i++ {
+		if values[i].value != values[i-1].value {
+			values[j] = values[i]
+			j++
+		}
+	}
+	values = values[:j]
+	runs := make([][]Value, 0, 10)
+	for len(values) > 0 {
+		// One contiguous sequence per outer loop.
+		i := 1
+		for i < len(values) && values[i].value == values[i-1].value+1 {
+			i++
+		}
+		runs = append(runs, values[:i])
+		values = values[i:]
+	}
+	return runs
+}
+
+// format returns the gofmt-ed contents of the Generator's buffer.
+func (g *Generator) format() []byte {
+	src, err := format.Source(g.buf.Bytes())
+	if err != nil {
+		// Should never happen, but can arise when developing this code.
+		// The user can compile the output to see the error.
+		log.Printf("warning: internal error: invalid Go generated: %s", err)
+		log.Printf("warning: compile the package to analyze the error")
+		return g.buf.Bytes()
+	}
+	return src
+}
+
+// Value represents a declared constant.
+type Value struct {
+	name string // The name of the constant.
+	// The value is stored as a bit pattern alone. The boolean tells us
+	// whether to interpret it as an int64 or a uint64; the only place
+	// this matters is when sorting.
+	// Much of the time the str field is all we need; it is printed
+	// by Value.String.
+	value  uint64 // Will be converted to int64 when needed.
+	signed bool   // Whether the constant is a signed type.
+	str    string // The string representation given by the "go/exact" package.
+}
+
+func (v *Value) String() string {
+	return v.str
+}
+
+// byValue lets us sort the constants into increasing order.
+// We take care in the Less method to sort in signed or unsigned order,
+// as appropriate.
+type byValue []Value
+
+func (b byValue) Len() int      { return len(b) }
+func (b byValue) Swap(i, j int) { b[i], b[j] = b[j], b[i] }
+func (b byValue) Less(i, j int) bool {
+	if b[i].signed {
+		return int64(b[i].value) < int64(b[j].value)
+	}
+	return b[i].value < b[j].value
+}
+
+// genDecl processes one declaration clause.
+func (f *File) genDecl(node ast.Node) bool {
+	decl, ok := node.(*ast.GenDecl)
+	if !ok || decl.Tok != token.CONST {
+		// We only care about const declarations.
+		return true
+	}
+	// The name of the type of the constants we are declaring.
+	// Can change if this is a multi-element declaration.
+	typ := ""
+	// Loop over the elements of the declaration. Each element is a ValueSpec:
+	// a list of names possibly followed by a type, possibly followed by values.
+	// If the type and value are both missing, we carry down the type (and value,
+	// but the "go/types" package takes care of that).
+	for _, spec := range decl.Specs {
+		vspec := spec.(*ast.ValueSpec) // Guaranteed to succeed as this is CONST.
+		if vspec.Type == nil && len(vspec.Values) > 0 {
+			// "X = 1". With no type but a value, the constant is untyped.
+			// Skip this vspec and reset the remembered type.
+			typ = ""
+			continue
+		}
+		if vspec.Type != nil {
+			// "X T". We have a type. Remember it.
+			ident, ok := vspec.Type.(*ast.Ident)
+			if !ok {
+				continue
+			}
+			typ = ident.Name
+		}
+		if typ != f.typeName {
+			// This is not the type we're looking for.
+			continue
+		}
+		// We now have a list of names (from one line of source code) all being
+		// declared with the desired type.
+		// Grab their names and actual values and store them in f.values.
+		for _, name := range vspec.Names {
+			if name.Name == "_" {
+				continue
+			}
+			// This dance lets the type checker find the values for us. It's a
+			// bit tricky: look up the object declared by the name, find its
+			// types.Const, and extract its value.
+			obj, ok := f.pkg.defs[name]
+			if !ok {
+				log.Fatalf("no value for constant %s", name)
+			}
+			info := obj.Type().Underlying().(*types.Basic).Info()
+			if info&types.IsInteger == 0 {
+				log.Fatalf("can't handle non-integer constant type %s", typ)
+			}
+			value := obj.(*types.Const).Val() // Guaranteed to succeed as this is CONST.
+			if value.Kind() != exact.Int {
+				log.Fatalf("can't happen: constant is not an integer %s", name)
+			}
+			i64, isInt := exact.Int64Val(value)
+			u64, isUint := exact.Uint64Val(value)
+			if !isInt && !isUint {
+				log.Fatalf("internal error: value of %s is not an integer: %s", name, value.String())
+			}
+			if !isInt {
+				u64 = uint64(i64)
+			}
+			v := Value{
+				name:   name.Name,
+				value:  u64,
+				signed: info&types.IsUnsigned == 0,
+				str:    value.String(),
+			}
+			f.values = append(f.values, v)
+		}
+	}
+	return false
+}
+
+// Helpers
+
+// usize returns the number of bits of the smallest unsigned integer
+// type that will hold n. Used to create the smallest possible slice of
+// integers to use as indexes into the concatenated strings.
+func usize(n int) int {
+	switch {
+	case n < 1<<8:
+		return 8
+	case n < 1<<16:
+		return 16
+	default:
+		// 2^32 is enough constants for anyone.
+		return 32
+	}
+}
+
+// declareIndexAndNameVars declares the index slices and concatenated names
+// strings representing the runs of values.
+func (g *Generator) declareIndexAndNameVars(runs [][]Value, typeName string) {
+	var indexes, names []string
+	for i, run := range runs {
+		index, name := g.createIndexAndNameDecl(run, typeName, fmt.Sprintf("_%d", i))
+		indexes = append(indexes, index)
+		names = append(names, name)
+	}
+	g.Printf("const (\n")
+	for _, name := range names {
+		g.Printf("\t%s\n", name)
+	}
+	g.Printf(")\n\n")
+	g.Printf("var (")
+	for _, index := range indexes {
+		g.Printf("\t%s\n", index)
+	}
+	g.Printf(")\n\n")
+}
+
+// declareIndexAndNameVar is the single-run version of declareIndexAndNameVars
+func (g *Generator) declareIndexAndNameVar(run []Value, typeName string) {
+	index, name := g.createIndexAndNameDecl(run, typeName, "")
+	g.Printf("const %s\n", name)
+	g.Printf("var %s\n", index)
+}
+
+// createIndexAndNameDecl returns the pair of declarations for the run. The caller will add "const" and "var".
+func (g *Generator) createIndexAndNameDecl(run []Value, typeName string, suffix string) (string, string) {
+	b := new(bytes.Buffer)
+	indexes := make([]int, len(run))
+	for i := range run {
+		b.WriteString(run[i].name)
+		indexes[i] = b.Len()
+	}
+	nameConst := fmt.Sprintf("_%s_name%s = %q", typeName, suffix, b.String())
+	nameLen := b.Len()
+	b.Reset()
+	fmt.Fprintf(b, "_%s_index%s = [...]uint%d{0, ", typeName, suffix, usize(nameLen))
+	for i, v := range indexes {
+		if i > 0 {
+			fmt.Fprintf(b, ", ")
+		}
+		fmt.Fprintf(b, "%d", v)
+	}
+	fmt.Fprintf(b, "}")
+	return b.String(), nameConst
+}
+
+// declareNameVars declares the concatenated names string representing all the values in the runs.
+func (g *Generator) declareNameVars(runs [][]Value, typeName string, suffix string) {
+	g.Printf("const _%s_name%s = \"", typeName, suffix)
+	for _, run := range runs {
+		for i := range run {
+			g.Printf("%s", run[i].name)
+		}
+	}
+	g.Printf("\"\n")
+}
+
+// buildOneRun generates the variables and String method for a single run of contiguous values.
+func (g *Generator) buildOneRun(runs [][]Value, typeName string) {
+	values := runs[0]
+	g.Printf("\n")
+	g.declareIndexAndNameVar(values, typeName)
+	// The generated code is simple enough to write as a Printf format.
+	lessThanZero := ""
+	if values[0].signed {
+		lessThanZero = "i < 0 || "
+	}
+	if values[0].value == 0 { // Signed or unsigned, 0 is still 0.
+		g.Printf(stringOneRun, typeName, usize(len(values)), lessThanZero)
+	} else {
+		g.Printf(stringOneRunWithOffset, typeName, values[0].String(), usize(len(values)), lessThanZero)
+	}
+}
+
+// Arguments to format are:
+//	[1]: type name
+//	[2]: size of index element (8 for uint8 etc.)
+//	[3]: less than zero check (for signed types)
+const stringOneRun = `func (i %[1]s) String() string {
+	if %[3]si >= %[1]s(len(_%[1]s_index)-1) {
+		return fmt.Sprintf("%[1]s(%%d)", i)
+	}
+	return _%[1]s_name[_%[1]s_index[i]:_%[1]s_index[i+1]]
+}
+`
+
+// Arguments to format are:
+//	[1]: type name
+//	[2]: lowest defined value for type, as a string
+//	[3]: size of index element (8 for uint8 etc.)
+//	[4]: less than zero check (for signed types)
+/*
+ */
+const stringOneRunWithOffset = `func (i %[1]s) String() string {
+	i -= %[2]s
+	if %[4]si >= %[1]s(len(_%[1]s_index)-1) {
+		return fmt.Sprintf("%[1]s(%%d)", i + %[2]s)
+	}
+	return _%[1]s_name[_%[1]s_index[i] : _%[1]s_index[i+1]]
+}
+`
+
+// buildMultipleRuns generates the variables and String method for multiple runs of contiguous values.
+// For this pattern, a single Printf format won't do.
+func (g *Generator) buildMultipleRuns(runs [][]Value, typeName string) {
+	g.Printf("\n")
+	g.declareIndexAndNameVars(runs, typeName)
+	g.Printf("func (i %s) String() string {\n", typeName)
+	g.Printf("\tswitch {\n")
+	for i, values := range runs {
+		if len(values) == 1 {
+			g.Printf("\tcase i == %s:\n", &values[0])
+			g.Printf("\t\treturn _%s_name_%d\n", typeName, i)
+			continue
+		}
+		g.Printf("\tcase %s <= i && i <= %s:\n", &values[0], &values[len(values)-1])
+		if values[0].value != 0 {
+			g.Printf("\t\ti -= %s\n", &values[0])
+		}
+		g.Printf("\t\treturn _%s_name_%d[_%s_index_%d[i]:_%s_index_%d[i+1]]\n",
+			typeName, i, typeName, i, typeName, i)
+	}
+	g.Printf("\tdefault:\n")
+	g.Printf("\t\treturn fmt.Sprintf(\"%s(%%d)\", i)\n", typeName)
+	g.Printf("\t}\n")
+	g.Printf("}\n")
+}
+
+// buildMap handles the case where the space is so sparse a map is a reasonable fallback.
+// It's a rare situation but has simple code.
+func (g *Generator) buildMap(runs [][]Value, typeName string) {
+	g.Printf("\n")
+	g.declareNameVars(runs, typeName, "")
+	g.Printf("\nvar _%s_map = map[%s]string{\n", typeName, typeName)
+	n := 0
+	for _, values := range runs {
+		for _, value := range values {
+			g.Printf("\t%s: _%s_name[%d:%d],\n", &value, typeName, n, n+len(value.name))
+			n += len(value.name)
+		}
+	}
+	g.Printf("}\n\n")
+	g.Printf(stringMap, typeName)
+}
+
+// Argument to format is the type name.
+const stringMap = `func (i %[1]s) String() string {
+	if str, ok := _%[1]s_map[i]; ok {
+		return str
+	}
+	return fmt.Sprintf("%[1]s(%%d)", i)
+}
+`
diff --git a/cmd/stringer/testdata/cgo.go b/cmd/stringer/testdata/cgo.go
new file mode 100644
index 0000000..ef38f95
--- /dev/null
+++ b/cmd/stringer/testdata/cgo.go
@@ -0,0 +1,32 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Import "C" shouldn't be imported.
+
+package main
+
+/*
+#define HELLO 1
+*/
+import "C"
+
+import "fmt"
+
+type Cgo uint32
+
+const (
+	// MustScanSubDirs indicates that events were coalesced hierarchically.
+	MustScanSubDirs Cgo = 1 << iota
+)
+
+func main() {
+	_ = C.HELLO
+	ck(MustScanSubDirs, "MustScanSubDirs")
+}
+
+func ck(day Cgo, str string) {
+	if fmt.Sprint(day) != str {
+		panic("cgo.go: " + str)
+	}
+}
diff --git a/cmd/stringer/testdata/day.go b/cmd/stringer/testdata/day.go
new file mode 100644
index 0000000..35fa8dc
--- /dev/null
+++ b/cmd/stringer/testdata/day.go
@@ -0,0 +1,39 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Simple test: enumeration of type int starting at 0.
+
+package main
+
+import "fmt"
+
+type Day int
+
+const (
+	Monday Day = iota
+	Tuesday
+	Wednesday
+	Thursday
+	Friday
+	Saturday
+	Sunday
+)
+
+func main() {
+	ck(Monday, "Monday")
+	ck(Tuesday, "Tuesday")
+	ck(Wednesday, "Wednesday")
+	ck(Thursday, "Thursday")
+	ck(Friday, "Friday")
+	ck(Saturday, "Saturday")
+	ck(Sunday, "Sunday")
+	ck(-127, "Day(-127)")
+	ck(127, "Day(127)")
+}
+
+func ck(day Day, str string) {
+	if fmt.Sprint(day) != str {
+		panic("day.go: " + str)
+	}
+}
diff --git a/cmd/stringer/testdata/gap.go b/cmd/stringer/testdata/gap.go
new file mode 100644
index 0000000..bc8a90c
--- /dev/null
+++ b/cmd/stringer/testdata/gap.go
@@ -0,0 +1,44 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Gaps and an offset.
+
+package main
+
+import "fmt"
+
+type Gap int
+
+const (
+	Two    Gap = 2
+	Three  Gap = 3
+	Five   Gap = 5
+	Six    Gap = 6
+	Seven  Gap = 7
+	Eight  Gap = 8
+	Nine   Gap = 9
+	Eleven Gap = 11
+)
+
+func main() {
+	ck(0, "Gap(0)")
+	ck(1, "Gap(1)")
+	ck(Two, "Two")
+	ck(Three, "Three")
+	ck(4, "Gap(4)")
+	ck(Five, "Five")
+	ck(Six, "Six")
+	ck(Seven, "Seven")
+	ck(Eight, "Eight")
+	ck(Nine, "Nine")
+	ck(10, "Gap(10)")
+	ck(Eleven, "Eleven")
+	ck(12, "Gap(12)")
+}
+
+func ck(gap Gap, str string) {
+	if fmt.Sprint(gap) != str {
+		panic("gap.go: " + str)
+	}
+}
diff --git a/cmd/stringer/testdata/num.go b/cmd/stringer/testdata/num.go
new file mode 100644
index 0000000..0d5ab10
--- /dev/null
+++ b/cmd/stringer/testdata/num.go
@@ -0,0 +1,35 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Signed integers spanning zero.
+
+package main
+
+import "fmt"
+
+type Num int
+
+const (
+	m_2 Num = -2 + iota
+	m_1
+	m0
+	m1
+	m2
+)
+
+func main() {
+	ck(-3, "Num(-3)")
+	ck(m_2, "m_2")
+	ck(m_1, "m_1")
+	ck(m0, "m0")
+	ck(m1, "m1")
+	ck(m2, "m2")
+	ck(3, "Num(3)")
+}
+
+func ck(num Num, str string) {
+	if fmt.Sprint(num) != str {
+		panic("num.go: " + str)
+	}
+}
diff --git a/cmd/stringer/testdata/number.go b/cmd/stringer/testdata/number.go
new file mode 100644
index 0000000..7f1c824
--- /dev/null
+++ b/cmd/stringer/testdata/number.go
@@ -0,0 +1,34 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Enumeration with an offset.
+// Also includes a duplicate.
+
+package main
+
+import "fmt"
+
+type Number int
+
+const (
+	_ Number = iota
+	One
+	Two
+	Three
+	AnotherOne = One // Duplicate; note that AnotherOne doesn't appear below.
+)
+
+func main() {
+	ck(One, "One")
+	ck(Two, "Two")
+	ck(Three, "Three")
+	ck(AnotherOne, "One")
+	ck(127, "Number(127)")
+}
+
+func ck(num Number, str string) {
+	if fmt.Sprint(num) != str {
+		panic("number.go: " + str)
+	}
+}
diff --git a/cmd/stringer/testdata/prime.go b/cmd/stringer/testdata/prime.go
new file mode 100644
index 0000000..f551a1a
--- /dev/null
+++ b/cmd/stringer/testdata/prime.go
@@ -0,0 +1,56 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Enough gaps to trigger a map implementation of the method.
+// Also includes a duplicate to test that it doesn't cause problems
+
+package main
+
+import "fmt"
+
+type Prime int
+
+const (
+	p2  Prime = 2
+	p3  Prime = 3
+	p5  Prime = 5
+	p7  Prime = 7
+	p77 Prime = 7 // Duplicate; note that p77 doesn't appear below.
+	p11 Prime = 11
+	p13 Prime = 13
+	p17 Prime = 17
+	p19 Prime = 19
+	p23 Prime = 23
+	p29 Prime = 29
+	p37 Prime = 31
+	p41 Prime = 41
+	p43 Prime = 43
+)
+
+func main() {
+	ck(0, "Prime(0)")
+	ck(1, "Prime(1)")
+	ck(p2, "p2")
+	ck(p3, "p3")
+	ck(4, "Prime(4)")
+	ck(p5, "p5")
+	ck(p7, "p7")
+	ck(p77, "p7")
+	ck(p11, "p11")
+	ck(p13, "p13")
+	ck(p17, "p17")
+	ck(p19, "p19")
+	ck(p23, "p23")
+	ck(p29, "p29")
+	ck(p37, "p37")
+	ck(p41, "p41")
+	ck(p43, "p43")
+	ck(44, "Prime(44)")
+}
+
+func ck(prime Prime, str string) {
+	if fmt.Sprint(prime) != str {
+		panic("prime.go: " + str)
+	}
+}
diff --git a/cmd/stringer/testdata/unum.go b/cmd/stringer/testdata/unum.go
new file mode 100644
index 0000000..2f8508f
--- /dev/null
+++ b/cmd/stringer/testdata/unum.go
@@ -0,0 +1,38 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Unsigned integers spanning zero.
+
+package main
+
+import "fmt"
+
+type Unum uint8
+
+const (
+	m_2 Unum = iota + 253
+	m_1
+)
+
+const (
+	m0 Unum = iota
+	m1
+	m2
+)
+
+func main() {
+	ck(^Unum(0)-3, "Unum(252)")
+	ck(m_2, "m_2")
+	ck(m_1, "m_1")
+	ck(m0, "m0")
+	ck(m1, "m1")
+	ck(m2, "m2")
+	ck(3, "Unum(3)")
+}
+
+func ck(unum Unum, str string) {
+	if fmt.Sprint(unum) != str {
+		panic("unum.go: " + str)
+	}
+}
diff --git a/cmd/stringer/testdata/unum2.go b/cmd/stringer/testdata/unum2.go
new file mode 100644
index 0000000..edbbedf
--- /dev/null
+++ b/cmd/stringer/testdata/unum2.go
@@ -0,0 +1,31 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Unsigned integers - check maximum size
+
+package main
+
+import "fmt"
+
+type Unum2 uint8
+
+const (
+	Zero Unum2 = iota
+	One
+	Two
+)
+
+func main() {
+	ck(Zero, "Zero")
+	ck(One, "One")
+	ck(Two, "Two")
+	ck(3, "Unum2(3)")
+	ck(255, "Unum2(255)")
+}
+
+func ck(unum Unum2, str string) {
+	if fmt.Sprint(unum) != str {
+		panic("unum.go: " + str)
+	}
+}
diff --git a/cmd/stringer/util_test.go b/cmd/stringer/util_test.go
new file mode 100644
index 0000000..1aeba6e
--- /dev/null
+++ b/cmd/stringer/util_test.go
@@ -0,0 +1,77 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file contains tests for some of the internal functions.
+
+package main
+
+import (
+	"fmt"
+	"testing"
+)
+
+// Helpers to save typing in the test cases.
+type u []uint64
+type uu [][]uint64
+
+type SplitTest struct {
+	input  u
+	output uu
+	signed bool
+}
+
+var (
+	m2  = uint64(2)
+	m1  = uint64(1)
+	m0  = uint64(0)
+	m_1 = ^uint64(0)     // -1 when signed.
+	m_2 = ^uint64(0) - 1 // -2 when signed.
+)
+
+var splitTests = []SplitTest{
+	// No need for a test for the empty case; that's picked off before splitIntoRuns.
+	// Single value.
+	{u{1}, uu{u{1}}, false},
+	// Out of order.
+	{u{3, 2, 1}, uu{u{1, 2, 3}}, true},
+	// Out of order.
+	{u{3, 2, 1}, uu{u{1, 2, 3}}, false},
+	// A gap at the beginning.
+	{u{1, 33, 32, 31}, uu{u{1}, u{31, 32, 33}}, true},
+	// A gap in the middle, in mixed order.
+	{u{33, 7, 32, 31, 9, 8}, uu{u{7, 8, 9}, u{31, 32, 33}}, true},
+	// Gaps throughout
+	{u{33, 44, 1, 32, 45, 31}, uu{u{1}, u{31, 32, 33}, u{44, 45}}, true},
+	// Unsigned values spanning 0.
+	{u{m1, m0, m_1, m2, m_2}, uu{u{m0, m1, m2}, u{m_2, m_1}}, false},
+	// Signed values spanning 0
+	{u{m1, m0, m_1, m2, m_2}, uu{u{m_2, m_1, m0, m1, m2}}, true},
+}
+
+func TestSplitIntoRuns(t *testing.T) {
+Outer:
+	for n, test := range splitTests {
+		values := make([]Value, len(test.input))
+		for i, v := range test.input {
+			values[i] = Value{"", v, test.signed, fmt.Sprint(v)}
+		}
+		runs := splitIntoRuns(values)
+		if len(runs) != len(test.output) {
+			t.Errorf("#%d: %v: got %d runs; expected %d", n, test.input, len(runs), len(test.output))
+			continue
+		}
+		for i, run := range runs {
+			if len(run) != len(test.output[i]) {
+				t.Errorf("#%d: got %v; expected %v", n, runs, test.output)
+				continue Outer
+			}
+			for j, v := range run {
+				if v.value != test.output[i][j] {
+					t.Errorf("#%d: got %v; expected %v", n, runs, test.output)
+					continue Outer
+				}
+			}
+		}
+	}
+}
diff --git a/cmd/tipgodoc/Dockerfile b/cmd/tipgodoc/Dockerfile
new file mode 100644
index 0000000..760ca0b
--- /dev/null
+++ b/cmd/tipgodoc/Dockerfile
@@ -0,0 +1,13 @@
+FROM golang:1.4.2
+
+RUN apt-get update && apt-get install --no-install-recommends -y -q build-essential git
+
+# golang puts its go install here (weird but true)
+ENV GOROOT_BOOTSTRAP /usr/src/go
+
+# golang sets GOPATH=/go
+ADD . /go/src/tipgodoc
+RUN go install tipgodoc
+ENTRYPOINT ["/go/bin/tipgodoc"]
+# Kubernetes expects us to listen on port 8080
+EXPOSE 8080 
diff --git a/cmd/tipgodoc/README b/cmd/tipgodoc/README
new file mode 100644
index 0000000..602e546
--- /dev/null
+++ b/cmd/tipgodoc/README
@@ -0,0 +1,3 @@
+To deploy as an App Engine Manged VM, use gcloud:
+
+	$ gcloud --project golang-org preview app deploy .
diff --git a/cmd/tipgodoc/app.yaml b/cmd/tipgodoc/app.yaml
new file mode 100644
index 0000000..59e5a06
--- /dev/null
+++ b/cmd/tipgodoc/app.yaml
@@ -0,0 +1,15 @@
+application: golang-org
+version: tip
+runtime: custom
+api_version: go1
+vm: true
+
+manual_scaling:
+  instances: 1
+
+handlers:
+- url: /.*
+  script: _go_app
+
+health_check:
+  enable_health_check: False
diff --git a/cmd/tipgodoc/tip.go b/cmd/tipgodoc/tip.go
new file mode 100644
index 0000000..ab3b8e6
--- /dev/null
+++ b/cmd/tipgodoc/tip.go
@@ -0,0 +1,298 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by the Apache 2.0
+// license that can be found in the LICENSE file.
+
+// Command tipgodoc is the beginning of the new tip.golang.org server,
+// serving the latest HEAD straight from the Git oven.
+package main
+
+import (
+	"bufio"
+	"bytes"
+	"encoding/json"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"log"
+	"net/http"
+	"net/http/httputil"
+	"net/url"
+	"os"
+	"os/exec"
+	"path/filepath"
+	"sync"
+	"time"
+)
+
+const (
+	repoURL      = "https://go.googlesource.com/"
+	metaURL      = "https://go.googlesource.com/?b=master&format=JSON"
+	startTimeout = 5 * time.Minute
+)
+
+var indexingMsg = []byte("Indexing in progress: result may be inaccurate")
+
+func main() {
+	p := new(Proxy)
+	go p.run()
+	http.Handle("/", p)
+
+	if err := http.ListenAndServe(":8080", nil); err != nil {
+		p.stop()
+		log.Fatal(err)
+	}
+}
+
+// Proxy implements the tip.golang.org server: a reverse-proxy
+// that builds and runs godoc instances showing the latest docs.
+type Proxy struct {
+	mu    sync.Mutex // protects the followin'
+	proxy http.Handler
+	cur   string    // signature of gorepo+toolsrepo
+	cmd   *exec.Cmd // live godoc instance, or nil for none
+	side  string
+	err   error
+}
+
+func (p *Proxy) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+	if r.URL.Path == "/_tipstatus" {
+		p.serveStatus(w, r)
+		return
+	}
+	p.mu.Lock()
+	proxy := p.proxy
+	err := p.err
+	p.mu.Unlock()
+	if proxy == nil {
+		s := "tip.golang.org is starting up"
+		if err != nil {
+			s = err.Error()
+		}
+		http.Error(w, s, http.StatusInternalServerError)
+		return
+	}
+	proxy.ServeHTTP(w, r)
+}
+
+func (p *Proxy) serveStatus(w http.ResponseWriter, r *http.Request) {
+	p.mu.Lock()
+	defer p.mu.Unlock()
+	fmt.Fprintf(w, "side=%v\ncurrent=%v\nerror=%v\n", p.side, p.cur, p.err)
+}
+
+// run runs in its own goroutine.
+func (p *Proxy) run() {
+	p.side = "a"
+	for {
+		p.poll()
+		time.Sleep(30 * time.Second)
+	}
+}
+
+func (p *Proxy) stop() {
+	p.mu.Lock()
+	defer p.mu.Unlock()
+	if p.cmd != nil {
+		p.cmd.Process.Kill()
+	}
+}
+
+// poll runs from the run loop goroutine.
+func (p *Proxy) poll() {
+	heads := gerritMetaMap()
+	if heads == nil {
+		return
+	}
+
+	sig := heads["go"] + "-" + heads["tools"]
+
+	p.mu.Lock()
+	changes := sig != p.cur
+	curSide := p.side
+	p.cur = sig
+	p.mu.Unlock()
+
+	if !changes {
+		return
+	}
+
+	newSide := "b"
+	if curSide == "b" {
+		newSide = "a"
+	}
+
+	cmd, hostport, err := initSide(newSide, heads["go"], heads["tools"])
+
+	p.mu.Lock()
+	defer p.mu.Unlock()
+	if err != nil {
+		log.Println(err)
+		p.err = err
+		return
+	}
+
+	u, err := url.Parse(fmt.Sprintf("http://%v/", hostport))
+	if err != nil {
+		log.Println(err)
+		p.err = err
+		return
+	}
+	p.proxy = httputil.NewSingleHostReverseProxy(u)
+	p.side = newSide
+	if p.cmd != nil {
+		p.cmd.Process.Kill()
+	}
+	p.cmd = cmd
+}
+
+func initSide(side, goHash, toolsHash string) (godoc *exec.Cmd, hostport string, err error) {
+	dir := filepath.Join(os.TempDir(), "tipgodoc", side)
+	if err := os.MkdirAll(dir, 0755); err != nil {
+		return nil, "", err
+	}
+
+	goDir := filepath.Join(dir, "go")
+	toolsDir := filepath.Join(dir, "gopath/src/golang.org/x/tools")
+	if err := checkout(repoURL+"go", goHash, goDir); err != nil {
+		return nil, "", err
+	}
+	if err := checkout(repoURL+"tools", toolsHash, toolsDir); err != nil {
+		return nil, "", err
+	}
+
+	make := exec.Command(filepath.Join(goDir, "src/make.bash"))
+	make.Dir = filepath.Join(goDir, "src")
+	if err := runErr(make); err != nil {
+		return nil, "", err
+	}
+	goBin := filepath.Join(goDir, "bin/go")
+	install := exec.Command(goBin, "install", "golang.org/x/tools/cmd/godoc")
+	install.Env = []string{
+		"GOROOT=" + goDir,
+		"GOPATH=" + filepath.Join(dir, "gopath"),
+		"GOROOT_BOOTSTRAP=" + os.Getenv("GOROOT_BOOTSTRAP"),
+	}
+	if err := runErr(install); err != nil {
+		return nil, "", err
+	}
+
+	godocBin := filepath.Join(goDir, "bin/godoc")
+	hostport = "localhost:8081"
+	if side == "b" {
+		hostport = "localhost:8082"
+	}
+	godoc = exec.Command(godocBin, "-http="+hostport, "-index", "-index_interval=-1s")
+	godoc.Env = []string{"GOROOT=" + goDir}
+	// TODO(adg): log this somewhere useful
+	godoc.Stdout = os.Stdout
+	godoc.Stderr = os.Stderr
+	if err := godoc.Start(); err != nil {
+		return nil, "", err
+	}
+	go func() {
+		// TODO(bradfitz): tell the proxy that this side is dead
+		if err := godoc.Wait(); err != nil {
+			log.Printf("side %v exited: %v", side, err)
+		}
+	}()
+
+	deadline := time.Now().Add(startTimeout)
+	for time.Now().Before(deadline) {
+		time.Sleep(time.Second)
+		var res *http.Response
+		res, err = http.Get(fmt.Sprintf("http://%v/search?q=FALLTHROUGH", hostport))
+		if err != nil {
+			continue
+		}
+		rbody, err := ioutil.ReadAll(res.Body)
+		res.Body.Close()
+		if err == nil && res.StatusCode == http.StatusOK &&
+			!bytes.Contains(rbody, indexingMsg) {
+			return godoc, hostport, nil
+		}
+	}
+	godoc.Process.Kill()
+	return nil, "", fmt.Errorf("timed out waiting for side %v at %v (%v)", side, hostport, err)
+}
+
+func runErr(cmd *exec.Cmd) error {
+	out, err := cmd.CombinedOutput()
+	if err != nil {
+		if len(out) == 0 {
+			return err
+		}
+		return fmt.Errorf("%s\n%v", out, err)
+	}
+	return nil
+}
+
+func checkout(repo, hash, path string) error {
+	// Clone git repo if it doesn't exist.
+	if _, err := os.Stat(filepath.Join(path, ".git")); os.IsNotExist(err) {
+		if err := os.MkdirAll(filepath.Dir(path), 0755); err != nil {
+			return err
+		}
+		if err := runErr(exec.Command("git", "clone", repo, path)); err != nil {
+			return err
+		}
+	} else if err != nil {
+		return err
+	}
+
+	// Pull down changes and update to hash.
+	cmd := exec.Command("git", "fetch")
+	cmd.Dir = path
+	if err := runErr(cmd); err != nil {
+		return err
+	}
+	cmd = exec.Command("git", "reset", "--hard", hash)
+	cmd.Dir = path
+	if err := runErr(cmd); err != nil {
+		return err
+	}
+	cmd = exec.Command("git", "clean", "-d", "-f", "-x")
+	cmd.Dir = path
+	return runErr(cmd)
+}
+
+// gerritMetaMap returns the map from repo name (e.g. "go") to its
+// latest master hash.
+// The returned map is nil on any transient error.
+func gerritMetaMap() map[string]string {
+	res, err := http.Get(metaURL)
+	if err != nil {
+		return nil
+	}
+	defer res.Body.Close()
+	defer io.Copy(ioutil.Discard, res.Body) // ensure EOF for keep-alive
+	if res.StatusCode != 200 {
+		return nil
+	}
+	var meta map[string]struct {
+		Branches map[string]string
+	}
+	br := bufio.NewReader(res.Body)
+	// For security reasons or something, this URL starts with ")]}'\n" before
+	// the JSON object. So ignore that.
+	// Shawn Pearce says it's guaranteed to always be just one line, ending in '\n'.
+	for {
+		b, err := br.ReadByte()
+		if err != nil {
+			return nil
+		}
+		if b == '\n' {
+			break
+		}
+	}
+	if err := json.NewDecoder(br).Decode(&meta); err != nil {
+		log.Printf("JSON decoding error from %v: %s", metaURL, err)
+		return nil
+	}
+	m := map[string]string{}
+	for repo, v := range meta {
+		if master, ok := v.Branches["master"]; ok {
+			m[repo] = master
+		}
+	}
+	return m
+}
diff --git a/cmd/vet/asmdecl.go b/cmd/vet/asmdecl.go
new file mode 100644
index 0000000..6bdfdbf
--- /dev/null
+++ b/cmd/vet/asmdecl.go
@@ -0,0 +1,662 @@
+// Copyright 2013 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Identify mismatches between assembly files and Go func declarations.
+
+package main
+
+import (
+	"bytes"
+	"fmt"
+	"go/ast"
+	"go/token"
+	"regexp"
+	"strconv"
+	"strings"
+)
+
+// 'kind' is a kind of assembly variable.
+// The kinds 1, 2, 4, 8 stand for values of that size.
+type asmKind int
+
+// These special kinds are not valid sizes.
+const (
+	asmString asmKind = 100 + iota
+	asmSlice
+	asmInterface
+	asmEmptyInterface
+)
+
+// An asmArch describes assembly parameters for an architecture
+type asmArch struct {
+	name      string
+	ptrSize   int
+	intSize   int
+	maxAlign  int
+	bigEndian bool
+	stack     string
+	lr        bool
+}
+
+// An asmFunc describes the expected variables for a function on a given architecture.
+type asmFunc struct {
+	arch        *asmArch
+	size        int // size of all arguments
+	vars        map[string]*asmVar
+	varByOffset map[int]*asmVar
+}
+
+// An asmVar describes a single assembly variable.
+type asmVar struct {
+	name  string
+	kind  asmKind
+	typ   string
+	off   int
+	size  int
+	inner []*asmVar
+}
+
+var (
+	asmArch386       = asmArch{"386", 4, 4, 4, false, "SP", false}
+	asmArchArm       = asmArch{"arm", 4, 4, 4, false, "R13", true}
+	asmArchArm64     = asmArch{"arm64", 8, 8, 8, false, "RSP", true}
+	asmArchAmd64     = asmArch{"amd64", 8, 8, 8, false, "SP", false}
+	asmArchAmd64p32  = asmArch{"amd64p32", 4, 4, 8, false, "SP", false}
+	asmArchPower64   = asmArch{"power64", 8, 8, 8, true, "R1", true}
+	asmArchPower64LE = asmArch{"power64le", 8, 8, 8, false, "R1", true}
+
+	arches = []*asmArch{
+		&asmArch386,
+		&asmArchArm,
+		&asmArchArm64,
+		&asmArchAmd64,
+		&asmArchAmd64p32,
+		&asmArchPower64,
+		&asmArchPower64LE,
+	}
+)
+
+var (
+	re           = regexp.MustCompile
+	asmPlusBuild = re(`//\s+\+build\s+([^\n]+)`)
+	asmTEXT      = re(`\bTEXT\b.*·([^\(]+)\(SB\)(?:\s*,\s*([0-9A-Z|+]+))?(?:\s*,\s*\$(-?[0-9]+)(?:-([0-9]+))?)?`)
+	asmDATA      = re(`\b(DATA|GLOBL)\b`)
+	asmNamedFP   = re(`([a-zA-Z0-9_\xFF-\x{10FFFF}]+)(?:\+([0-9]+))\(FP\)`)
+	asmUnnamedFP = re(`[^+\-0-9](([0-9]+)\(FP\))`)
+	asmSP        = re(`[^+\-0-9](([0-9]+)\(([A-Z0-9]+)\))`)
+	asmOpcode    = re(`^\s*(?:[A-Z0-9a-z_]+:)?\s*([A-Z]+)\s*([^,]*)(?:,\s*(.*))?`)
+	power64Suff  = re(`([BHWD])(ZU|Z|U|BR)?$`)
+)
+
+func asmCheck(pkg *Package) {
+	if !vet("asmdecl") {
+		return
+	}
+
+	// No work if no assembly files.
+	if !pkg.hasFileWithSuffix(".s") {
+		return
+	}
+
+	// Gather declarations. knownFunc[name][arch] is func description.
+	knownFunc := make(map[string]map[string]*asmFunc)
+
+	for _, f := range pkg.files {
+		if f.file != nil {
+			for _, decl := range f.file.Decls {
+				if decl, ok := decl.(*ast.FuncDecl); ok && decl.Body == nil {
+					knownFunc[decl.Name.Name] = f.asmParseDecl(decl)
+				}
+			}
+		}
+	}
+
+Files:
+	for _, f := range pkg.files {
+		if !strings.HasSuffix(f.name, ".s") {
+			continue
+		}
+		Println("Checking file", f.name)
+
+		// Determine architecture from file name if possible.
+		var arch string
+		var archDef *asmArch
+		for _, a := range arches {
+			if strings.HasSuffix(f.name, "_"+a.name+".s") {
+				arch = a.name
+				archDef = a
+				break
+			}
+		}
+
+		lines := strings.SplitAfter(string(f.content), "\n")
+		var (
+			fn                 *asmFunc
+			fnName             string
+			localSize, argSize int
+			wroteSP            bool
+			haveRetArg         bool
+			retLine            []int
+		)
+
+		flushRet := func() {
+			if fn != nil && fn.vars["ret"] != nil && !haveRetArg && len(retLine) > 0 {
+				v := fn.vars["ret"]
+				for _, line := range retLine {
+					f.Badf(token.NoPos, "%s:%d: [%s] %s: RET without writing to %d-byte ret+%d(FP)", f.name, line, arch, fnName, v.size, v.off)
+				}
+			}
+			retLine = nil
+		}
+		for lineno, line := range lines {
+			lineno++
+
+			badf := func(format string, args ...interface{}) {
+				f.Badf(token.NoPos, "%s:%d: [%s] %s: %s", f.name, lineno, arch, fnName, fmt.Sprintf(format, args...))
+			}
+
+			if arch == "" {
+				// Determine architecture from +build line if possible.
+				if m := asmPlusBuild.FindStringSubmatch(line); m != nil {
+				Fields:
+					for _, fld := range strings.Fields(m[1]) {
+						for _, a := range arches {
+							if a.name == fld {
+								arch = a.name
+								archDef = a
+								break Fields
+							}
+						}
+					}
+				}
+			}
+
+			if m := asmTEXT.FindStringSubmatch(line); m != nil {
+				flushRet()
+				if arch == "" {
+					f.Warnf(token.NoPos, "%s: cannot determine architecture for assembly file", f.name)
+					continue Files
+				}
+				fnName = m[1]
+				fn = knownFunc[m[1]][arch]
+				if fn != nil {
+					size, _ := strconv.Atoi(m[4])
+					if size != fn.size && (m[2] != "7" && !strings.Contains(m[2], "NOSPLIT") || size != 0) {
+						badf("wrong argument size %d; expected $...-%d", size, fn.size)
+					}
+				}
+				localSize, _ = strconv.Atoi(m[3])
+				localSize += archDef.intSize
+				if archDef.lr {
+					// Account for caller's saved LR
+					localSize += archDef.intSize
+				}
+				argSize, _ = strconv.Atoi(m[4])
+				if fn == nil && !strings.Contains(fnName, "<>") {
+					badf("function %s missing Go declaration", fnName)
+				}
+				wroteSP = false
+				haveRetArg = false
+				continue
+			} else if strings.Contains(line, "TEXT") && strings.Contains(line, "SB") {
+				// function, but not visible from Go (didn't match asmTEXT), so stop checking
+				flushRet()
+				fn = nil
+				fnName = ""
+				continue
+			}
+
+			if strings.Contains(line, "RET") {
+				retLine = append(retLine, lineno)
+			}
+
+			if fnName == "" {
+				continue
+			}
+
+			if asmDATA.FindStringSubmatch(line) != nil {
+				fn = nil
+			}
+
+			if archDef == nil {
+				continue
+			}
+
+			if strings.Contains(line, ", "+archDef.stack) || strings.Contains(line, ",\t"+archDef.stack) {
+				wroteSP = true
+				continue
+			}
+
+			for _, m := range asmSP.FindAllStringSubmatch(line, -1) {
+				if m[3] != archDef.stack || wroteSP {
+					continue
+				}
+				off := 0
+				if m[1] != "" {
+					off, _ = strconv.Atoi(m[2])
+				}
+				if off >= localSize {
+					if fn != nil {
+						v := fn.varByOffset[off-localSize]
+						if v != nil {
+							badf("%s should be %s+%d(FP)", m[1], v.name, off-localSize)
+							continue
+						}
+					}
+					if off >= localSize+argSize {
+						badf("use of %s points beyond argument frame", m[1])
+						continue
+					}
+					badf("use of %s to access argument frame", m[1])
+				}
+			}
+
+			if fn == nil {
+				continue
+			}
+
+			for _, m := range asmUnnamedFP.FindAllStringSubmatch(line, -1) {
+				off, _ := strconv.Atoi(m[2])
+				v := fn.varByOffset[off]
+				if v != nil {
+					badf("use of unnamed argument %s; offset %d is %s+%d(FP)", m[1], off, v.name, v.off)
+				} else {
+					badf("use of unnamed argument %s", m[1])
+				}
+			}
+
+			for _, m := range asmNamedFP.FindAllStringSubmatch(line, -1) {
+				name := m[1]
+				off := 0
+				if m[2] != "" {
+					off, _ = strconv.Atoi(m[2])
+				}
+				if name == "ret" || strings.HasPrefix(name, "ret_") {
+					haveRetArg = true
+				}
+				v := fn.vars[name]
+				if v == nil {
+					// Allow argframe+0(FP).
+					if name == "argframe" && off == 0 {
+						continue
+					}
+					v = fn.varByOffset[off]
+					if v != nil {
+						badf("unknown variable %s; offset %d is %s+%d(FP)", name, off, v.name, v.off)
+					} else {
+						badf("unknown variable %s", name)
+					}
+					continue
+				}
+				asmCheckVar(badf, fn, line, m[0], off, v)
+			}
+		}
+		flushRet()
+	}
+}
+
+// asmParseDecl parses a function decl for expected assembly variables.
+func (f *File) asmParseDecl(decl *ast.FuncDecl) map[string]*asmFunc {
+	var (
+		arch   *asmArch
+		fn     *asmFunc
+		offset int
+		failed bool
+	)
+
+	addVar := func(outer string, v asmVar) {
+		if vo := fn.vars[outer]; vo != nil {
+			vo.inner = append(vo.inner, &v)
+		}
+		fn.vars[v.name] = &v
+		for i := 0; i < v.size; i++ {
+			fn.varByOffset[v.off+i] = &v
+		}
+	}
+
+	addParams := func(list []*ast.Field) {
+		for i, fld := range list {
+			// Determine alignment, size, and kind of type in declaration.
+			var align, size int
+			var kind asmKind
+			names := fld.Names
+			typ := f.gofmt(fld.Type)
+			switch t := fld.Type.(type) {
+			default:
+				switch typ {
+				default:
+					f.Warnf(fld.Type.Pos(), "unknown assembly argument type %s", typ)
+					failed = true
+					return
+				case "int8", "uint8", "byte", "bool":
+					size = 1
+				case "int16", "uint16":
+					size = 2
+				case "int32", "uint32", "float32":
+					size = 4
+				case "int64", "uint64", "float64":
+					align = arch.maxAlign
+					size = 8
+				case "int", "uint":
+					size = arch.intSize
+				case "uintptr", "iword", "Word", "Errno", "unsafe.Pointer":
+					size = arch.ptrSize
+				case "string", "ErrorString":
+					size = arch.ptrSize * 2
+					align = arch.ptrSize
+					kind = asmString
+				}
+			case *ast.ChanType, *ast.FuncType, *ast.MapType, *ast.StarExpr:
+				size = arch.ptrSize
+			case *ast.InterfaceType:
+				align = arch.ptrSize
+				size = 2 * arch.ptrSize
+				if len(t.Methods.List) > 0 {
+					kind = asmInterface
+				} else {
+					kind = asmEmptyInterface
+				}
+			case *ast.ArrayType:
+				if t.Len == nil {
+					size = arch.ptrSize + 2*arch.intSize
+					align = arch.ptrSize
+					kind = asmSlice
+					break
+				}
+				f.Warnf(fld.Type.Pos(), "unsupported assembly argument type %s", typ)
+				failed = true
+			case *ast.StructType:
+				f.Warnf(fld.Type.Pos(), "unsupported assembly argument type %s", typ)
+				failed = true
+			}
+			if align == 0 {
+				align = size
+			}
+			if kind == 0 {
+				kind = asmKind(size)
+			}
+			offset += -offset & (align - 1)
+
+			// Create variable for each name being declared with this type.
+			if len(names) == 0 {
+				name := "unnamed"
+				if decl.Type.Results != nil && len(decl.Type.Results.List) > 0 && &list[0] == &decl.Type.Results.List[0] && i == 0 {
+					// Assume assembly will refer to single unnamed result as r.
+					name = "ret"
+				}
+				names = []*ast.Ident{{Name: name}}
+			}
+			for _, id := range names {
+				name := id.Name
+				addVar("", asmVar{
+					name: name,
+					kind: kind,
+					typ:  typ,
+					off:  offset,
+					size: size,
+				})
+				switch kind {
+				case 8:
+					if arch.ptrSize == 4 {
+						w1, w2 := "lo", "hi"
+						if arch.bigEndian {
+							w1, w2 = w2, w1
+						}
+						addVar(name, asmVar{
+							name: name + "_" + w1,
+							kind: 4,
+							typ:  "half " + typ,
+							off:  offset,
+							size: 4,
+						})
+						addVar(name, asmVar{
+							name: name + "_" + w2,
+							kind: 4,
+							typ:  "half " + typ,
+							off:  offset + 4,
+							size: 4,
+						})
+					}
+
+				case asmEmptyInterface:
+					addVar(name, asmVar{
+						name: name + "_type",
+						kind: asmKind(arch.ptrSize),
+						typ:  "interface type",
+						off:  offset,
+						size: arch.ptrSize,
+					})
+					addVar(name, asmVar{
+						name: name + "_data",
+						kind: asmKind(arch.ptrSize),
+						typ:  "interface data",
+						off:  offset + arch.ptrSize,
+						size: arch.ptrSize,
+					})
+
+				case asmInterface:
+					addVar(name, asmVar{
+						name: name + "_itable",
+						kind: asmKind(arch.ptrSize),
+						typ:  "interface itable",
+						off:  offset,
+						size: arch.ptrSize,
+					})
+					addVar(name, asmVar{
+						name: name + "_data",
+						kind: asmKind(arch.ptrSize),
+						typ:  "interface data",
+						off:  offset + arch.ptrSize,
+						size: arch.ptrSize,
+					})
+
+				case asmSlice:
+					addVar(name, asmVar{
+						name: name + "_base",
+						kind: asmKind(arch.ptrSize),
+						typ:  "slice base",
+						off:  offset,
+						size: arch.ptrSize,
+					})
+					addVar(name, asmVar{
+						name: name + "_len",
+						kind: asmKind(arch.intSize),
+						typ:  "slice len",
+						off:  offset + arch.ptrSize,
+						size: arch.intSize,
+					})
+					addVar(name, asmVar{
+						name: name + "_cap",
+						kind: asmKind(arch.intSize),
+						typ:  "slice cap",
+						off:  offset + arch.ptrSize + arch.intSize,
+						size: arch.intSize,
+					})
+
+				case asmString:
+					addVar(name, asmVar{
+						name: name + "_base",
+						kind: asmKind(arch.ptrSize),
+						typ:  "string base",
+						off:  offset,
+						size: arch.ptrSize,
+					})
+					addVar(name, asmVar{
+						name: name + "_len",
+						kind: asmKind(arch.intSize),
+						typ:  "string len",
+						off:  offset + arch.ptrSize,
+						size: arch.intSize,
+					})
+				}
+				offset += size
+			}
+		}
+	}
+
+	m := make(map[string]*asmFunc)
+	for _, arch = range arches {
+		fn = &asmFunc{
+			arch:        arch,
+			vars:        make(map[string]*asmVar),
+			varByOffset: make(map[int]*asmVar),
+		}
+		offset = 0
+		addParams(decl.Type.Params.List)
+		if decl.Type.Results != nil && len(decl.Type.Results.List) > 0 {
+			offset += -offset & (arch.maxAlign - 1)
+			addParams(decl.Type.Results.List)
+		}
+		fn.size = offset
+		m[arch.name] = fn
+	}
+
+	if failed {
+		return nil
+	}
+	return m
+}
+
+// asmCheckVar checks a single variable reference.
+func asmCheckVar(badf func(string, ...interface{}), fn *asmFunc, line, expr string, off int, v *asmVar) {
+	m := asmOpcode.FindStringSubmatch(line)
+	if m == nil {
+		if !strings.HasPrefix(strings.TrimSpace(line), "//") {
+			badf("cannot find assembly opcode")
+		}
+		return
+	}
+
+	// Determine operand sizes from instruction.
+	// Typically the suffix suffices, but there are exceptions.
+	var src, dst, kind asmKind
+	op := m[1]
+	switch fn.arch.name + "." + op {
+	case "386.FMOVLP":
+		src, dst = 8, 4
+	case "arm.MOVD":
+		src = 8
+	case "arm.MOVW":
+		src = 4
+	case "arm.MOVH", "arm.MOVHU":
+		src = 2
+	case "arm.MOVB", "arm.MOVBU":
+		src = 1
+	// LEA* opcodes don't really read the second arg.
+	// They just take the address of it.
+	case "386.LEAL":
+		dst = 4
+	case "amd64.LEAQ":
+		dst = 8
+	case "amd64p32.LEAL":
+		dst = 4
+	default:
+		switch fn.arch.name {
+		case "386", "amd64":
+			if strings.HasPrefix(op, "F") && (strings.HasSuffix(op, "D") || strings.HasSuffix(op, "DP")) {
+				// FMOVDP, FXCHD, etc
+				src = 8
+				break
+			}
+			if strings.HasPrefix(op, "F") && (strings.HasSuffix(op, "F") || strings.HasSuffix(op, "FP")) {
+				// FMOVFP, FXCHF, etc
+				src = 4
+				break
+			}
+			if strings.HasSuffix(op, "SD") {
+				// MOVSD, SQRTSD, etc
+				src = 8
+				break
+			}
+			if strings.HasSuffix(op, "SS") {
+				// MOVSS, SQRTSS, etc
+				src = 4
+				break
+			}
+			if strings.HasPrefix(op, "SET") {
+				// SETEQ, etc
+				src = 1
+				break
+			}
+			switch op[len(op)-1] {
+			case 'B':
+				src = 1
+			case 'W':
+				src = 2
+			case 'L':
+				src = 4
+			case 'D', 'Q':
+				src = 8
+			}
+		case "power64", "power64le":
+			// Strip standard suffixes to reveal size letter.
+			m := power64Suff.FindStringSubmatch(op)
+			if m != nil {
+				switch m[1][0] {
+				case 'B':
+					src = 1
+				case 'H':
+					src = 2
+				case 'W':
+					src = 4
+				case 'D':
+					src = 8
+				}
+			}
+		}
+	}
+	if dst == 0 {
+		dst = src
+	}
+
+	// Determine whether the match we're holding
+	// is the first or second argument.
+	if strings.Index(line, expr) > strings.Index(line, ",") {
+		kind = dst
+	} else {
+		kind = src
+	}
+
+	vk := v.kind
+	vt := v.typ
+	switch vk {
+	case asmInterface, asmEmptyInterface, asmString, asmSlice:
+		// allow reference to first word (pointer)
+		vk = v.inner[0].kind
+		vt = v.inner[0].typ
+	}
+
+	if off != v.off {
+		var inner bytes.Buffer
+		for i, vi := range v.inner {
+			if len(v.inner) > 1 {
+				fmt.Fprintf(&inner, ",")
+			}
+			fmt.Fprintf(&inner, " ")
+			if i == len(v.inner)-1 {
+				fmt.Fprintf(&inner, "or ")
+			}
+			fmt.Fprintf(&inner, "%s+%d(FP)", vi.name, vi.off)
+		}
+		badf("invalid offset %s; expected %s+%d(FP)%s", expr, v.name, v.off, inner.String())
+		return
+	}
+	if kind != 0 && kind != vk {
+		var inner bytes.Buffer
+		if len(v.inner) > 0 {
+			fmt.Fprintf(&inner, " containing")
+			for i, vi := range v.inner {
+				if i > 0 && len(v.inner) > 2 {
+					fmt.Fprintf(&inner, ",")
+				}
+				fmt.Fprintf(&inner, " ")
+				if i > 0 && i == len(v.inner)-1 {
+					fmt.Fprintf(&inner, "and ")
+				}
+				fmt.Fprintf(&inner, "%s+%d(FP)", vi.name, vi.off)
+			}
+		}
+		badf("invalid %s of %s; %s is %d-byte value%s", op, expr, vt, vk, inner.String())
+	}
+}
diff --git a/cmd/vet/assign.go b/cmd/vet/assign.go
new file mode 100644
index 0000000..54c1ae1
--- /dev/null
+++ b/cmd/vet/assign.go
@@ -0,0 +1,49 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+/*
+This file contains the code to check for useless assignments.
+*/
+
+package main
+
+import (
+	"go/ast"
+	"go/token"
+	"reflect"
+)
+
+func init() {
+	register("assign",
+		"check for useless assignments",
+		checkAssignStmt,
+		assignStmt)
+}
+
+// TODO: should also check for assignments to struct fields inside methods
+// that are on T instead of *T.
+
+// checkAssignStmt checks for assignments of the form "<expr> = <expr>".
+// These are almost always useless, and even when they aren't they are usually a mistake.
+func checkAssignStmt(f *File, node ast.Node) {
+	stmt := node.(*ast.AssignStmt)
+	if stmt.Tok != token.ASSIGN {
+		return // ignore :=
+	}
+	if len(stmt.Lhs) != len(stmt.Rhs) {
+		// If LHS and RHS have different cardinality, they can't be the same.
+		return
+	}
+	for i, lhs := range stmt.Lhs {
+		rhs := stmt.Rhs[i]
+		if reflect.TypeOf(lhs) != reflect.TypeOf(rhs) {
+			continue // short-circuit the heavy-weight gofmt check
+		}
+		le := f.gofmt(lhs)
+		re := f.gofmt(rhs)
+		if le == re {
+			f.Badf(stmt.Pos(), "self-assignment of %s to %s", re, le)
+		}
+	}
+}
diff --git a/cmd/vet/atomic.go b/cmd/vet/atomic.go
new file mode 100644
index 0000000..c084f13
--- /dev/null
+++ b/cmd/vet/atomic.go
@@ -0,0 +1,66 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+	"go/ast"
+	"go/token"
+)
+
+func init() {
+	register("atomic",
+		"check for common mistaken usages of the sync/atomic package",
+		checkAtomicAssignment,
+		assignStmt)
+}
+
+// checkAtomicAssignment walks the assignment statement checking for common
+// mistaken usage of atomic package, such as: x = atomic.AddUint64(&x, 1)
+func checkAtomicAssignment(f *File, node ast.Node) {
+	n := node.(*ast.AssignStmt)
+	if len(n.Lhs) != len(n.Rhs) {
+		return
+	}
+
+	for i, right := range n.Rhs {
+		call, ok := right.(*ast.CallExpr)
+		if !ok {
+			continue
+		}
+		sel, ok := call.Fun.(*ast.SelectorExpr)
+		if !ok {
+			continue
+		}
+		pkg, ok := sel.X.(*ast.Ident)
+		if !ok || pkg.Name != "atomic" {
+			continue
+		}
+
+		switch sel.Sel.Name {
+		case "AddInt32", "AddInt64", "AddUint32", "AddUint64", "AddUintptr":
+			f.checkAtomicAddAssignment(n.Lhs[i], call)
+		}
+	}
+}
+
+// checkAtomicAddAssignment walks the atomic.Add* method calls checking for assigning the return value
+// to the same variable being used in the operation
+func (f *File) checkAtomicAddAssignment(left ast.Expr, call *ast.CallExpr) {
+	if len(call.Args) != 2 {
+		return
+	}
+	arg := call.Args[0]
+	broken := false
+
+	if uarg, ok := arg.(*ast.UnaryExpr); ok && uarg.Op == token.AND {
+		broken = f.gofmt(left) == f.gofmt(uarg.X)
+	} else if star, ok := left.(*ast.StarExpr); ok {
+		broken = f.gofmt(star.X) == f.gofmt(arg)
+	}
+
+	if broken {
+		f.Bad(left.Pos(), "direct assignment to atomic value")
+	}
+}
diff --git a/cmd/vet/bool.go b/cmd/vet/bool.go
new file mode 100644
index 0000000..07c2a93
--- /dev/null
+++ b/cmd/vet/bool.go
@@ -0,0 +1,186 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file contains boolean condition tests.
+
+package main
+
+import (
+	"go/ast"
+	"go/token"
+)
+
+func init() {
+	register("bool",
+		"check for mistakes involving boolean operators",
+		checkBool,
+		binaryExpr)
+}
+
+func checkBool(f *File, n ast.Node) {
+	e := n.(*ast.BinaryExpr)
+
+	var op boolOp
+	switch e.Op {
+	case token.LOR:
+		op = or
+	case token.LAND:
+		op = and
+	default:
+		return
+	}
+
+	comm := op.commutativeSets(e)
+	for _, exprs := range comm {
+		op.checkRedundant(f, exprs)
+		op.checkSuspect(f, exprs)
+	}
+}
+
+type boolOp struct {
+	name  string
+	tok   token.Token // token corresponding to this operator
+	badEq token.Token // token corresponding to the equality test that should not be used with this operator
+}
+
+var (
+	or  = boolOp{"or", token.LOR, token.NEQ}
+	and = boolOp{"and", token.LAND, token.EQL}
+)
+
+// commutativeSets returns all side effect free sets of
+// expressions in e that are connected by op.
+// For example, given 'a || b || f() || c || d' with the or op,
+// commutativeSets returns {{b, a}, {d, c}}.
+func (op boolOp) commutativeSets(e *ast.BinaryExpr) [][]ast.Expr {
+	exprs := op.split(e)
+
+	// Partition the slice of expressions into commutative sets.
+	i := 0
+	var sets [][]ast.Expr
+	for j := 0; j <= len(exprs); j++ {
+		if j == len(exprs) || hasSideEffects(exprs[j]) {
+			if i < j {
+				sets = append(sets, exprs[i:j])
+			}
+			i = j + 1
+		}
+	}
+
+	return sets
+}
+
+// checkRedundant checks for expressions of the form
+//   e && e
+//   e || e
+// Exprs must contain only side effect free expressions.
+func (op boolOp) checkRedundant(f *File, exprs []ast.Expr) {
+	seen := make(map[string]bool)
+	for _, e := range exprs {
+		efmt := f.gofmt(e)
+		if seen[efmt] {
+			f.Badf(e.Pos(), "redundant %s: %s %s %s", op.name, efmt, op.tok, efmt)
+		} else {
+			seen[efmt] = true
+		}
+	}
+}
+
+// checkSuspect checks for expressions of the form
+//   x != c1 || x != c2
+//   x == c1 && x == c2
+// where c1 and c2 are constant expressions.
+// If c1 and c2 are the same then it's redundant;
+// if c1 and c2 are different then it's always true or always false.
+// Exprs must contain only side effect free expressions.
+func (op boolOp) checkSuspect(f *File, exprs []ast.Expr) {
+	// seen maps from expressions 'x' to equality expressions 'x != c'.
+	seen := make(map[string]string)
+
+	for _, e := range exprs {
+		bin, ok := e.(*ast.BinaryExpr)
+		if !ok || bin.Op != op.badEq {
+			continue
+		}
+
+		// In order to avoid false positives, restrict to cases
+		// in which one of the operands is constant. We're then
+		// interested in the other operand.
+		// In the rare case in which both operands are constant
+		// (e.g. runtime.GOOS and "windows"), we'll only catch
+		// mistakes if the LHS is repeated, which is how most
+		// code is written.
+		var x ast.Expr
+		switch {
+		case f.pkg.types[bin.Y].Value != nil:
+			x = bin.X
+		case f.pkg.types[bin.X].Value != nil:
+			x = bin.Y
+		default:
+			continue
+		}
+
+		// e is of the form 'x != c' or 'x == c'.
+		xfmt := f.gofmt(x)
+		efmt := f.gofmt(e)
+		if prev, found := seen[xfmt]; found {
+			// checkRedundant handles the case in which efmt == prev.
+			if efmt != prev {
+				f.Badf(e.Pos(), "suspect %s: %s %s %s", op.name, efmt, op.tok, prev)
+			}
+		} else {
+			seen[xfmt] = efmt
+		}
+	}
+}
+
+// hasSideEffects reports whether evaluation of e has side effects.
+func hasSideEffects(e ast.Expr) bool {
+	safe := true
+	ast.Inspect(e, func(node ast.Node) bool {
+		switch n := node.(type) {
+		// Using CallExpr here will catch conversions
+		// as well as function and method invocations.
+		// We'll live with the false negatives for now.
+		case *ast.CallExpr:
+			safe = false
+			return false
+		case *ast.UnaryExpr:
+			if n.Op == token.ARROW {
+				safe = false
+				return false
+			}
+		}
+		return true
+	})
+	return !safe
+}
+
+// split returns a slice of all subexpressions in e that are connected by op.
+// For example, given 'a || (b || c) || d' with the or op,
+// split returns []{d, c, b, a}.
+func (op boolOp) split(e ast.Expr) (exprs []ast.Expr) {
+	for {
+		e = unparen(e)
+		if b, ok := e.(*ast.BinaryExpr); ok && b.Op == op.tok {
+			exprs = append(exprs, op.split(b.Y)...)
+			e = b.X
+		} else {
+			exprs = append(exprs, e)
+			break
+		}
+	}
+	return
+}
+
+// unparen returns e with any enclosing parentheses stripped.
+func unparen(e ast.Expr) ast.Expr {
+	for {
+		p, ok := e.(*ast.ParenExpr)
+		if !ok {
+			return e
+		}
+		e = p.X
+	}
+}
diff --git a/cmd/vet/buildtag.go b/cmd/vet/buildtag.go
new file mode 100644
index 0000000..2d86edf
--- /dev/null
+++ b/cmd/vet/buildtag.go
@@ -0,0 +1,91 @@
+// Copyright 2013 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+	"bytes"
+	"fmt"
+	"os"
+	"strings"
+	"unicode"
+)
+
+var (
+	nl         = []byte("\n")
+	slashSlash = []byte("//")
+	plusBuild  = []byte("+build")
+)
+
+// checkBuildTag checks that build tags are in the correct location and well-formed.
+func checkBuildTag(name string, data []byte) {
+	if !vet("buildtags") {
+		return
+	}
+	lines := bytes.SplitAfter(data, nl)
+
+	// Determine cutpoint where +build comments are no longer valid.
+	// They are valid in leading // comments in the file followed by
+	// a blank line.
+	var cutoff int
+	for i, line := range lines {
+		line = bytes.TrimSpace(line)
+		if len(line) == 0 {
+			cutoff = i
+			continue
+		}
+		if bytes.HasPrefix(line, slashSlash) {
+			continue
+		}
+		break
+	}
+
+	for i, line := range lines {
+		line = bytes.TrimSpace(line)
+		if !bytes.HasPrefix(line, slashSlash) {
+			continue
+		}
+		text := bytes.TrimSpace(line[2:])
+		if bytes.HasPrefix(text, plusBuild) {
+			fields := bytes.Fields(text)
+			if !bytes.Equal(fields[0], plusBuild) {
+				// Comment is something like +buildasdf not +build.
+				fmt.Fprintf(os.Stderr, "%s:%d: possible malformed +build comment\n", name, i+1)
+				continue
+			}
+			if i >= cutoff {
+				fmt.Fprintf(os.Stderr, "%s:%d: +build comment must appear before package clause and be followed by a blank line\n", name, i+1)
+				setExit(1)
+				continue
+			}
+			// Check arguments.
+		Args:
+			for _, arg := range fields[1:] {
+				for _, elem := range strings.Split(string(arg), ",") {
+					if strings.HasPrefix(elem, "!!") {
+						fmt.Fprintf(os.Stderr, "%s:%d: invalid double negative in build constraint: %s\n", name, i+1, arg)
+						setExit(1)
+						break Args
+					}
+					if strings.HasPrefix(elem, "!") {
+						elem = elem[1:]
+					}
+					for _, c := range elem {
+						if !unicode.IsLetter(c) && !unicode.IsDigit(c) && c != '_' && c != '.' {
+							fmt.Fprintf(os.Stderr, "%s:%d: invalid non-alphanumeric build constraint: %s\n", name, i+1, arg)
+							setExit(1)
+							break Args
+						}
+					}
+				}
+			}
+			continue
+		}
+		// Comment with +build but not at beginning.
+		if bytes.Contains(line, plusBuild) && i < cutoff {
+			fmt.Fprintf(os.Stderr, "%s:%d: possible malformed +build comment\n", name, i+1)
+			continue
+		}
+	}
+}
diff --git a/cmd/vet/composite.go b/cmd/vet/composite.go
new file mode 100644
index 0000000..0c3f916
--- /dev/null
+++ b/cmd/vet/composite.go
@@ -0,0 +1,125 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file contains the test for unkeyed struct literals.
+
+package main
+
+import (
+	"flag"
+	"go/ast"
+	"strings"
+
+	"golang.org/x/tools/cmd/vet/whitelist"
+)
+
+var compositeWhiteList = flag.Bool("compositewhitelist", true, "use composite white list; for testing only")
+
+func init() {
+	register("composites",
+		"check that composite literals used field-keyed elements",
+		checkUnkeyedLiteral,
+		compositeLit)
+}
+
+// checkUnkeyedLiteral checks if a composite literal is a struct literal with
+// unkeyed fields.
+func checkUnkeyedLiteral(f *File, node ast.Node) {
+	c := node.(*ast.CompositeLit)
+	typ := c.Type
+	for {
+		if typ1, ok := c.Type.(*ast.ParenExpr); ok {
+			typ = typ1
+			continue
+		}
+		break
+	}
+
+	switch typ.(type) {
+	case *ast.ArrayType:
+		return
+	case *ast.MapType:
+		return
+	case *ast.StructType:
+		return // a literal struct type does not need to use keys
+	case *ast.Ident:
+		// A simple type name like t or T does not need keys either,
+		// since it is almost certainly declared in the current package.
+		// (The exception is names being used via import . "pkg", but
+		// those are already breaking the Go 1 compatibility promise,
+		// so not reporting potential additional breakage seems okay.)
+		return
+	}
+
+	// Otherwise the type is a selector like pkg.Name.
+	// We only care if pkg.Name is a struct, not if it's a map, array, or slice.
+	isStruct, typeString := f.pkg.isStruct(c)
+	if !isStruct {
+		return
+	}
+
+	if typeString == "" { // isStruct doesn't know
+		typeString = f.gofmt(typ)
+	}
+
+	// It's a struct, or we can't tell it's not a struct because we don't have types.
+
+	// Check if the CompositeLit contains an unkeyed field.
+	allKeyValue := true
+	for _, e := range c.Elts {
+		if _, ok := e.(*ast.KeyValueExpr); !ok {
+			allKeyValue = false
+			break
+		}
+	}
+	if allKeyValue {
+		return
+	}
+
+	// Check that the CompositeLit's type has the form pkg.Typ.
+	s, ok := c.Type.(*ast.SelectorExpr)
+	if !ok {
+		return
+	}
+	pkg, ok := s.X.(*ast.Ident)
+	if !ok {
+		return
+	}
+
+	// Convert the package name to an import path, and compare to a whitelist.
+	path := pkgPath(f, pkg.Name)
+	if path == "" {
+		f.Badf(c.Pos(), "unresolvable package for %s.%s literal", pkg.Name, s.Sel.Name)
+		return
+	}
+	typeName := path + "." + s.Sel.Name
+	if *compositeWhiteList && whitelist.UnkeyedLiteral[typeName] {
+		return
+	}
+
+	f.Bad(c.Pos(), typeString+" composite literal uses unkeyed fields")
+}
+
+// pkgPath returns the import path "image/png" for the package name "png".
+//
+// This is based purely on syntax and convention, and not on the imported
+// package's contents. It will be incorrect if a package name differs from the
+// leaf element of the import path, or if the package was a dot import.
+func pkgPath(f *File, pkgName string) (path string) {
+	for _, x := range f.file.Imports {
+		s := strings.Trim(x.Path.Value, `"`)
+		if x.Name != nil {
+			// Catch `import pkgName "foo/bar"`.
+			if x.Name.Name == pkgName {
+				return s
+			}
+		} else {
+			// Catch `import "pkgName"` or `import "foo/bar/pkgName"`.
+			if s == pkgName || strings.HasSuffix(s, "/"+pkgName) {
+				return s
+			}
+		}
+	}
+	return ""
+}
diff --git a/cmd/vet/copylock.go b/cmd/vet/copylock.go
new file mode 100644
index 0000000..e8a6820
--- /dev/null
+++ b/cmd/vet/copylock.go
@@ -0,0 +1,155 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file contains the code to check that locks are not passed by value.
+
+package main
+
+import (
+	"bytes"
+	"fmt"
+	"go/ast"
+	"go/token"
+
+	"golang.org/x/tools/go/types"
+)
+
+func init() {
+	register("copylocks",
+		"check that locks are not passed by value",
+		checkCopyLocks,
+		funcDecl, rangeStmt)
+}
+
+// checkCopyLocks checks whether node might
+// inadvertently copy a lock.
+func checkCopyLocks(f *File, node ast.Node) {
+	switch node := node.(type) {
+	case *ast.RangeStmt:
+		checkCopyLocksRange(f, node)
+	case *ast.FuncDecl:
+		checkCopyLocksFunc(f, node)
+	}
+}
+
+// checkCopyLocksFunc checks whether a function might
+// inadvertently copy a lock, by checking whether
+// its receiver, parameters, or return values
+// are locks.
+func checkCopyLocksFunc(f *File, d *ast.FuncDecl) {
+	if d.Recv != nil && len(d.Recv.List) > 0 {
+		expr := d.Recv.List[0].Type
+		if path := lockPath(f.pkg.typesPkg, f.pkg.types[expr].Type); path != nil {
+			f.Badf(expr.Pos(), "%s passes Lock by value: %v", d.Name.Name, path)
+		}
+	}
+
+	if d.Type.Params != nil {
+		for _, field := range d.Type.Params.List {
+			expr := field.Type
+			if path := lockPath(f.pkg.typesPkg, f.pkg.types[expr].Type); path != nil {
+				f.Badf(expr.Pos(), "%s passes Lock by value: %v", d.Name.Name, path)
+			}
+		}
+	}
+
+	if d.Type.Results != nil {
+		for _, field := range d.Type.Results.List {
+			expr := field.Type
+			if path := lockPath(f.pkg.typesPkg, f.pkg.types[expr].Type); path != nil {
+				f.Badf(expr.Pos(), "%s returns Lock by value: %v", d.Name.Name, path)
+			}
+		}
+	}
+}
+
+// checkCopyLocksRange checks whether a range statement
+// might inadvertently copy a lock by checking whether
+// any of the range variables are locks.
+func checkCopyLocksRange(f *File, r *ast.RangeStmt) {
+	checkCopyLocksRangeVar(f, r.Tok, r.Key)
+	checkCopyLocksRangeVar(f, r.Tok, r.Value)
+}
+
+func checkCopyLocksRangeVar(f *File, rtok token.Token, e ast.Expr) {
+	if e == nil {
+		return
+	}
+	id, isId := e.(*ast.Ident)
+	if isId && id.Name == "_" {
+		return
+	}
+
+	var typ types.Type
+	if rtok == token.DEFINE {
+		if !isId {
+			return
+		}
+		obj := f.pkg.defs[id]
+		if obj == nil {
+			return
+		}
+		typ = obj.Type()
+	} else {
+		typ = f.pkg.types[e].Type
+	}
+
+	if typ == nil {
+		return
+	}
+	if path := lockPath(f.pkg.typesPkg, typ); path != nil {
+		f.Badf(e.Pos(), "range var %s copies Lock: %v", f.gofmt(e), path)
+	}
+}
+
+type typePath []types.Type
+
+// String pretty-prints a typePath.
+func (path typePath) String() string {
+	n := len(path)
+	var buf bytes.Buffer
+	for i := range path {
+		if i > 0 {
+			fmt.Fprint(&buf, " contains ")
+		}
+		// The human-readable path is in reverse order, outermost to innermost.
+		fmt.Fprint(&buf, path[n-i-1].String())
+	}
+	return buf.String()
+}
+
+// lockPath returns a typePath describing the location of a lock value
+// contained in typ. If there is no contained lock, it returns nil.
+func lockPath(tpkg *types.Package, typ types.Type) typePath {
+	if typ == nil {
+		return nil
+	}
+
+	// We're only interested in the case in which the underlying
+	// type is a struct. (Interfaces and pointers are safe to copy.)
+	styp, ok := typ.Underlying().(*types.Struct)
+	if !ok {
+		return nil
+	}
+
+	// We're looking for cases in which a reference to this type
+	// can be locked, but a value cannot. This differentiates
+	// embedded interfaces from embedded values.
+	if plock := types.NewMethodSet(types.NewPointer(typ)).Lookup(tpkg, "Lock"); plock != nil {
+		if lock := types.NewMethodSet(typ).Lookup(tpkg, "Lock"); lock == nil {
+			return []types.Type{typ}
+		}
+	}
+
+	nfields := styp.NumFields()
+	for i := 0; i < nfields; i++ {
+		ftyp := styp.Field(i).Type()
+		subpath := lockPath(tpkg, ftyp)
+		if subpath != nil {
+			return append(subpath, typ)
+		}
+	}
+
+	return nil
+}
diff --git a/cmd/vet/deadcode.go b/cmd/vet/deadcode.go
new file mode 100644
index 0000000..3b306c2
--- /dev/null
+++ b/cmd/vet/deadcode.go
@@ -0,0 +1,296 @@
+// Copyright 2013 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Check for syntactically unreachable code.
+
+package main
+
+import (
+	"go/ast"
+	"go/token"
+)
+
+func init() {
+	register("unreachable",
+		"check for unreachable code",
+		checkUnreachable,
+		funcDecl, funcLit)
+}
+
+type deadState struct {
+	f           *File
+	hasBreak    map[ast.Stmt]bool
+	hasGoto     map[string]bool
+	labels      map[string]ast.Stmt
+	breakTarget ast.Stmt
+
+	reachable bool
+}
+
+// checkUnreachable checks a function body for dead code.
+func checkUnreachable(f *File, node ast.Node) {
+	var body *ast.BlockStmt
+	switch n := node.(type) {
+	case *ast.FuncDecl:
+		body = n.Body
+	case *ast.FuncLit:
+		body = n.Body
+	}
+	if body == nil {
+		return
+	}
+
+	d := &deadState{
+		f:        f,
+		hasBreak: make(map[ast.Stmt]bool),
+		hasGoto:  make(map[string]bool),
+		labels:   make(map[string]ast.Stmt),
+	}
+
+	d.findLabels(body)
+
+	d.reachable = true
+	d.findDead(body)
+}
+
+// findLabels gathers information about the labels defined and used by stmt
+// and about which statements break, whether a label is involved or not.
+func (d *deadState) findLabels(stmt ast.Stmt) {
+	switch x := stmt.(type) {
+	default:
+		d.f.Warnf(x.Pos(), "internal error in findLabels: unexpected statement %T", x)
+
+	case *ast.AssignStmt,
+		*ast.BadStmt,
+		*ast.DeclStmt,
+		*ast.DeferStmt,
+		*ast.EmptyStmt,
+		*ast.ExprStmt,
+		*ast.GoStmt,
+		*ast.IncDecStmt,
+		*ast.ReturnStmt,
+		*ast.SendStmt:
+		// no statements inside
+
+	case *ast.BlockStmt:
+		for _, stmt := range x.List {
+			d.findLabels(stmt)
+		}
+
+	case *ast.BranchStmt:
+		switch x.Tok {
+		case token.GOTO:
+			if x.Label != nil {
+				d.hasGoto[x.Label.Name] = true
+			}
+
+		case token.BREAK:
+			stmt := d.breakTarget
+			if x.Label != nil {
+				stmt = d.labels[x.Label.Name]
+			}
+			if stmt != nil {
+				d.hasBreak[stmt] = true
+			}
+		}
+
+	case *ast.IfStmt:
+		d.findLabels(x.Body)
+		if x.Else != nil {
+			d.findLabels(x.Else)
+		}
+
+	case *ast.LabeledStmt:
+		d.labels[x.Label.Name] = x.Stmt
+		d.findLabels(x.Stmt)
+
+	// These cases are all the same, but the x.Body only works
+	// when the specific type of x is known, so the cases cannot
+	// be merged.
+	case *ast.ForStmt:
+		outer := d.breakTarget
+		d.breakTarget = x
+		d.findLabels(x.Body)
+		d.breakTarget = outer
+
+	case *ast.RangeStmt:
+		outer := d.breakTarget
+		d.breakTarget = x
+		d.findLabels(x.Body)
+		d.breakTarget = outer
+
+	case *ast.SelectStmt:
+		outer := d.breakTarget
+		d.breakTarget = x
+		d.findLabels(x.Body)
+		d.breakTarget = outer
+
+	case *ast.SwitchStmt:
+		outer := d.breakTarget
+		d.breakTarget = x
+		d.findLabels(x.Body)
+		d.breakTarget = outer
+
+	case *ast.TypeSwitchStmt:
+		outer := d.breakTarget
+		d.breakTarget = x
+		d.findLabels(x.Body)
+		d.breakTarget = outer
+
+	case *ast.CommClause:
+		for _, stmt := range x.Body {
+			d.findLabels(stmt)
+		}
+
+	case *ast.CaseClause:
+		for _, stmt := range x.Body {
+			d.findLabels(stmt)
+		}
+	}
+}
+
+// findDead walks the statement looking for dead code.
+// If d.reachable is false on entry, stmt itself is dead.
+// When findDead returns, d.reachable tells whether the
+// statement following stmt is reachable.
+func (d *deadState) findDead(stmt ast.Stmt) {
+	// Is this a labeled goto target?
+	// If so, assume it is reachable due to the goto.
+	// This is slightly conservative, in that we don't
+	// check that the goto is reachable, so
+	//	L: goto L
+	// will not provoke a warning.
+	// But it's good enough.
+	if x, isLabel := stmt.(*ast.LabeledStmt); isLabel && d.hasGoto[x.Label.Name] {
+		d.reachable = true
+	}
+
+	if !d.reachable {
+		switch stmt.(type) {
+		case *ast.EmptyStmt:
+			// do not warn about unreachable empty statements
+		default:
+			d.f.Bad(stmt.Pos(), "unreachable code")
+			d.reachable = true // silence error about next statement
+		}
+	}
+
+	switch x := stmt.(type) {
+	default:
+		d.f.Warnf(x.Pos(), "internal error in findDead: unexpected statement %T", x)
+
+	case *ast.AssignStmt,
+		*ast.BadStmt,
+		*ast.DeclStmt,
+		*ast.DeferStmt,
+		*ast.EmptyStmt,
+		*ast.GoStmt,
+		*ast.IncDecStmt,
+		*ast.SendStmt:
+		// no control flow
+
+	case *ast.BlockStmt:
+		for _, stmt := range x.List {
+			d.findDead(stmt)
+		}
+
+	case *ast.BranchStmt:
+		switch x.Tok {
+		case token.BREAK, token.GOTO, token.FALLTHROUGH:
+			d.reachable = false
+		case token.CONTINUE:
+			// NOTE: We accept "continue" statements as terminating.
+			// They are not necessary in the spec definition of terminating,
+			// because a continue statement cannot be the final statement
+			// before a return. But for the more general problem of syntactically
+			// identifying dead code, continue redirects control flow just
+			// like the other terminating statements.
+			d.reachable = false
+		}
+
+	case *ast.ExprStmt:
+		// Call to panic?
+		call, ok := x.X.(*ast.CallExpr)
+		if ok {
+			name, ok := call.Fun.(*ast.Ident)
+			if ok && name.Name == "panic" && name.Obj == nil {
+				d.reachable = false
+			}
+		}
+
+	case *ast.ForStmt:
+		d.findDead(x.Body)
+		d.reachable = x.Cond != nil || d.hasBreak[x]
+
+	case *ast.IfStmt:
+		d.findDead(x.Body)
+		if x.Else != nil {
+			r := d.reachable
+			d.reachable = true
+			d.findDead(x.Else)
+			d.reachable = d.reachable || r
+		} else {
+			// might not have executed if statement
+			d.reachable = true
+		}
+
+	case *ast.LabeledStmt:
+		d.findDead(x.Stmt)
+
+	case *ast.RangeStmt:
+		d.findDead(x.Body)
+		d.reachable = true
+
+	case *ast.ReturnStmt:
+		d.reachable = false
+
+	case *ast.SelectStmt:
+		// NOTE: Unlike switch and type switch below, we don't care
+		// whether a select has a default, because a select without a
+		// default blocks until one of the cases can run. That's different
+		// from a switch without a default, which behaves like it has
+		// a default with an empty body.
+		anyReachable := false
+		for _, comm := range x.Body.List {
+			d.reachable = true
+			for _, stmt := range comm.(*ast.CommClause).Body {
+				d.findDead(stmt)
+			}
+			anyReachable = anyReachable || d.reachable
+		}
+		d.reachable = anyReachable || d.hasBreak[x]
+
+	case *ast.SwitchStmt:
+		anyReachable := false
+		hasDefault := false
+		for _, cas := range x.Body.List {
+			cc := cas.(*ast.CaseClause)
+			if cc.List == nil {
+				hasDefault = true
+			}
+			d.reachable = true
+			for _, stmt := range cc.Body {
+				d.findDead(stmt)
+			}
+			anyReachable = anyReachable || d.reachable
+		}
+		d.reachable = anyReachable || d.hasBreak[x] || !hasDefault
+
+	case *ast.TypeSwitchStmt:
+		anyReachable := false
+		hasDefault := false
+		for _, cas := range x.Body.List {
+			cc := cas.(*ast.CaseClause)
+			if cc.List == nil {
+				hasDefault = true
+			}
+			d.reachable = true
+			for _, stmt := range cc.Body {
+				d.findDead(stmt)
+			}
+			anyReachable = anyReachable || d.reachable
+		}
+		d.reachable = anyReachable || d.hasBreak[x] || !hasDefault
+	}
+}
diff --git a/cmd/vet/doc.go b/cmd/vet/doc.go
new file mode 100644
index 0000000..a19de3f
--- /dev/null
+++ b/cmd/vet/doc.go
@@ -0,0 +1,190 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+/*
+
+Vet examines Go source code and reports suspicious constructs, such as Printf
+calls whose arguments do not align with the format string. Vet uses heuristics
+that do not guarantee all reports are genuine problems, but it can find errors
+not caught by the compilers.
+
+It can be invoked three ways:
+
+By package, from the go tool:
+	go vet package/path/name
+vets the package whose path is provided.
+
+By files:
+	go tool vet source/directory/*.go
+vets the files named, all of which must be in the same package.
+
+By directory:
+	go tool vet source/directory
+recursively descends the directory, vetting each package it finds.
+
+Vet's exit code is 2 for erroneous invocation of the tool, 1 if a
+problem was reported, and 0 otherwise. Note that the tool does not
+check every possible problem and depends on unreliable heuristics
+so it should be used as guidance only, not as a firm indicator of
+program correctness.
+
+By default all checks are performed. If any flags are explicitly set
+to true, only those tests are run. Conversely, if any flag is
+explicitly set to false, only those tests are disabled.
+Thus -printf=true runs the printf check, -printf=false runs all checks
+except the printf check.
+
+Available checks:
+
+Printf family
+
+Flag: -printf
+
+Suspicious calls to functions in the Printf family, including any functions
+with these names, disregarding case:
+	Print Printf Println
+	Fprint Fprintf Fprintln
+	Sprint Sprintf Sprintln
+	Error Errorf
+	Fatal Fatalf
+	Log Logf
+	Panic Panicf Panicln
+If the function name ends with an 'f', the function is assumed to take
+a format descriptor string in the manner of fmt.Printf. If not, vet
+complains about arguments that look like format descriptor strings.
+
+It also checks for errors such as using a Writer as the first argument of
+Printf.
+
+Methods
+
+Flag: -methods
+
+Non-standard signatures for methods with familiar names, including:
+	Format GobEncode GobDecode MarshalJSON MarshalXML
+	Peek ReadByte ReadFrom ReadRune Scan Seek
+	UnmarshalJSON UnreadByte UnreadRune WriteByte
+	WriteTo
+
+Struct tags
+
+Flag: -structtags
+
+Struct tags that do not follow the format understood by reflect.StructTag.Get.
+Well-known encoding struct tags (json, xml) used with unexported fields.
+
+Unkeyed composite literals
+
+Flag: -composites
+
+Composite struct literals that do not use the field-keyed syntax.
+
+Assembly declarations
+
+Flag: -asmdecl
+
+Mismatches between assembly files and Go function declarations.
+
+Useless assignments
+
+Flag: -assign
+
+Check for useless assignments.
+
+Atomic mistakes
+
+Flag: -atomic
+
+Common mistaken usages of the sync/atomic package.
+
+Boolean conditions
+
+Flag: -bool
+
+Mistakes involving boolean operators.
+
+Build tags
+
+Flag: -buildtags
+
+Badly formed or misplaced +build tags.
+
+Copying locks
+
+Flag: -copylocks
+
+Locks that are erroneously passed by value.
+
+Nil function comparison
+
+Flag: -nilfunc
+
+Comparisons between functions and nil.
+
+Range loop variables
+
+Flag: -rangeloops
+
+Incorrect uses of range loop variables in closures.
+
+Unreachable code
+
+Flag: -unreachable
+
+Unreachable code.
+
+Shadowed variables
+
+Flag: -shadow=false (experimental; must be set explicitly)
+
+Variables that may have been unintentionally shadowed.
+
+Misuse of unsafe Pointers
+
+Flag: -unsafeptr
+
+Likely incorrect uses of unsafe.Pointer to convert integers to pointers.
+A conversion from uintptr to unsafe.Pointer is invalid if it implies that
+there is a uintptr-typed word in memory that holds a pointer value,
+because that word will be invisible to stack copying and to the garbage
+collector.
+
+Unused result of certain function calls
+
+Flag: -unusedresult
+
+Calls to well-known functions and methods that return a value that is
+discarded.  By default, this includes functions like fmt.Errorf and
+fmt.Sprintf and methods like String and Error. The flags -unusedfuncs
+and -unusedstringmethods control the set.
+
+Shifts
+
+Flag: -shift
+
+Shifts equal to or longer than the variable's length.
+
+Other flags
+
+These flags configure the behavior of vet:
+
+	-all (default true)
+		Check everything; disabled if any explicit check is requested.
+	-v
+		Verbose mode
+	-printfuncs
+		A comma-separated list of print-like functions to supplement
+		the standard list.  Each entry is in the form Name:N where N
+		is the zero-based argument position of the first argument
+		involved in the print: either the format or the first print
+		argument for non-formatted prints.  For example,
+		if you have Warn and Warnf functions that take an
+		io.Writer as their first argument, like Fprintf,
+			-printfuncs=Warn:1,Warnf:1
+	-shadowstrict
+		Whether to be strict about shadowing; can be noisy.
+	-test
+		For testing only: sets -all and -shadow.
+*/
+package main // import "golang.org/x/tools/cmd/vet"
diff --git a/cmd/vet/main.go b/cmd/vet/main.go
new file mode 100644
index 0000000..e4b6877
--- /dev/null
+++ b/cmd/vet/main.go
@@ -0,0 +1,488 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Vet is a simple checker for static errors in Go source code.
+// See doc.go for more information.
+package main
+
+import (
+	"bytes"
+	"flag"
+	"fmt"
+	"go/ast"
+	"go/build"
+	"go/parser"
+	"go/printer"
+	"go/token"
+	"io/ioutil"
+	"os"
+	"path/filepath"
+	"strconv"
+	"strings"
+
+	_ "golang.org/x/tools/go/gcimporter"
+	"golang.org/x/tools/go/types"
+)
+
+var (
+	verbose  = flag.Bool("v", false, "verbose")
+	testFlag = flag.Bool("test", false, "for testing only: sets -all and -shadow")
+	tags     = flag.String("tags", "", "comma-separated list of build tags to apply when parsing")
+	tagList  = []string{} // exploded version of tags flag; set in main
+)
+
+var exitCode = 0
+
+// "all" is here only for the appearance of backwards compatibility.
+// It has no effect; the triState flags do the work.
+var all = flag.Bool("all", true, "check everything; disabled if any explicit check is requested")
+
+// Flags to control which individual checks to perform.
+var report = map[string]*triState{
+	// Only unusual checks are written here.
+	// Most checks that operate during the AST walk are added by register.
+	"asmdecl":   triStateFlag("asmdecl", unset, "check assembly against Go declarations"),
+	"buildtags": triStateFlag("buildtags", unset, "check that +build tags are valid"),
+}
+
+// experimental records the flags enabling experimental features. These must be
+// requested explicitly; they are not enabled by -all.
+var experimental = map[string]bool{}
+
+// setTrueCount record how many flags are explicitly set to true.
+var setTrueCount int
+
+// A triState is a boolean that knows whether it has been set to either true or false.
+// It is used to identify if a flag appears; the standard boolean flag cannot
+// distinguish missing from unset. It also satisfies flag.Value.
+type triState int
+
+const (
+	unset triState = iota
+	setTrue
+	setFalse
+)
+
+func triStateFlag(name string, value triState, usage string) *triState {
+	flag.Var(&value, name, usage)
+	return &value
+}
+
+// triState implements flag.Value, flag.Getter, and flag.boolFlag.
+// They work like boolean flags: we can say vet -printf as well as vet -printf=true
+func (ts *triState) Get() interface{} {
+	return *ts == setTrue
+}
+
+func (ts triState) isTrue() bool {
+	return ts == setTrue
+}
+
+func (ts *triState) Set(value string) error {
+	b, err := strconv.ParseBool(value)
+	if err != nil {
+		return err
+	}
+	if b {
+		*ts = setTrue
+		setTrueCount++
+	} else {
+		*ts = setFalse
+	}
+	return nil
+}
+
+func (ts *triState) String() string {
+	switch *ts {
+	case unset:
+		return "unset"
+	case setTrue:
+		return "true"
+	case setFalse:
+		return "false"
+	}
+	panic("not reached")
+}
+
+func (ts triState) IsBoolFlag() bool {
+	return true
+}
+
+// vet tells whether to report errors for the named check, a flag name.
+func vet(name string) bool {
+	if *testFlag {
+		return true
+	}
+	return report[name].isTrue()
+}
+
+// setExit sets the value for os.Exit when it is called, later.  It
+// remembers the highest value.
+func setExit(err int) {
+	if err > exitCode {
+		exitCode = err
+	}
+}
+
+var (
+	// Each of these vars has a corresponding case in (*File).Visit.
+	assignStmt    *ast.AssignStmt
+	binaryExpr    *ast.BinaryExpr
+	callExpr      *ast.CallExpr
+	compositeLit  *ast.CompositeLit
+	exprStmt      *ast.ExprStmt
+	field         *ast.Field
+	funcDecl      *ast.FuncDecl
+	funcLit       *ast.FuncLit
+	genDecl       *ast.GenDecl
+	interfaceType *ast.InterfaceType
+	rangeStmt     *ast.RangeStmt
+
+	// checkers is a two-level map.
+	// The outer level is keyed by a nil pointer, one of the AST vars above.
+	// The inner level is keyed by checker name.
+	checkers = make(map[ast.Node]map[string]func(*File, ast.Node))
+)
+
+func register(name, usage string, fn func(*File, ast.Node), types ...ast.Node) {
+	report[name] = triStateFlag(name, unset, usage)
+	for _, typ := range types {
+		m := checkers[typ]
+		if m == nil {
+			m = make(map[string]func(*File, ast.Node))
+			checkers[typ] = m
+		}
+		m[name] = fn
+	}
+}
+
+// Usage is a replacement usage function for the flags package.
+func Usage() {
+	fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0])
+	fmt.Fprintf(os.Stderr, "\tvet [flags] directory...\n")
+	fmt.Fprintf(os.Stderr, "\tvet [flags] files... # Must be a single package\n")
+	fmt.Fprintf(os.Stderr, "For more information run\n")
+	fmt.Fprintf(os.Stderr, "\tgodoc golang.org/x/tools/cmd/vet\n\n")
+	fmt.Fprintf(os.Stderr, "Flags:\n")
+	flag.PrintDefaults()
+	os.Exit(2)
+}
+
+// File is a wrapper for the state of a file used in the parser.
+// The parse tree walkers are all methods of this type.
+type File struct {
+	pkg     *Package
+	fset    *token.FileSet
+	name    string
+	content []byte
+	file    *ast.File
+	b       bytes.Buffer // for use by methods
+
+	// The objects that are receivers of a "String() string" method.
+	// This is used by the recursiveStringer method in print.go.
+	stringers map[*ast.Object]bool
+
+	// Registered checkers to run.
+	checkers map[ast.Node][]func(*File, ast.Node)
+}
+
+func main() {
+	flag.Usage = Usage
+	flag.Parse()
+
+	// If any flag is set, we run only those checks requested.
+	// If no flags are set true, set all the non-experimental ones not explicitly set (in effect, set the "-all" flag).
+	if setTrueCount == 0 {
+		for name, setting := range report {
+			if *setting == unset && !experimental[name] {
+				*setting = setTrue
+			}
+		}
+	}
+
+	tagList = strings.Split(*tags, ",")
+
+	initPrintFlags()
+	initUnusedFlags()
+
+	if flag.NArg() == 0 {
+		Usage()
+	}
+	dirs := false
+	files := false
+	for _, name := range flag.Args() {
+		// Is it a directory?
+		fi, err := os.Stat(name)
+		if err != nil {
+			warnf("error walking tree: %s", err)
+			continue
+		}
+		if fi.IsDir() {
+			dirs = true
+		} else {
+			files = true
+		}
+	}
+	if dirs && files {
+		Usage()
+	}
+	if dirs {
+		for _, name := range flag.Args() {
+			walkDir(name)
+		}
+		os.Exit(exitCode)
+	}
+	if !doPackage(".", flag.Args()) {
+		warnf("no files checked")
+	}
+	os.Exit(exitCode)
+}
+
+// prefixDirectory places the directory name on the beginning of each name in the list.
+func prefixDirectory(directory string, names []string) {
+	if directory != "." {
+		for i, name := range names {
+			names[i] = filepath.Join(directory, name)
+		}
+	}
+}
+
+// doPackageDir analyzes the single package found in the directory, if there is one,
+// plus a test package, if there is one.
+func doPackageDir(directory string) {
+	context := build.Default
+	if len(context.BuildTags) != 0 {
+		warnf("build tags %s previously set", context.BuildTags)
+	}
+	context.BuildTags = append(tagList, context.BuildTags...)
+
+	pkg, err := context.ImportDir(directory, 0)
+	if err != nil {
+		// If it's just that there are no go source files, that's fine.
+		if _, nogo := err.(*build.NoGoError); nogo {
+			return
+		}
+		// Non-fatal: we are doing a recursive walk and there may be other directories.
+		warnf("cannot process directory %s: %s", directory, err)
+		return
+	}
+	var names []string
+	names = append(names, pkg.GoFiles...)
+	names = append(names, pkg.CgoFiles...)
+	names = append(names, pkg.TestGoFiles...) // These are also in the "foo" package.
+	names = append(names, pkg.SFiles...)
+	prefixDirectory(directory, names)
+	doPackage(directory, names)
+	// Is there also a "foo_test" package? If so, do that one as well.
+	if len(pkg.XTestGoFiles) > 0 {
+		names = pkg.XTestGoFiles
+		prefixDirectory(directory, names)
+		doPackage(directory, names)
+	}
+}
+
+type Package struct {
+	path      string
+	defs      map[*ast.Ident]types.Object
+	uses      map[*ast.Ident]types.Object
+	selectors map[*ast.SelectorExpr]*types.Selection
+	types     map[ast.Expr]types.TypeAndValue
+	spans     map[types.Object]Span
+	files     []*File
+	typesPkg  *types.Package
+}
+
+// doPackage analyzes the single package constructed from the named files.
+// It returns whether any files were checked.
+func doPackage(directory string, names []string) bool {
+	var files []*File
+	var astFiles []*ast.File
+	fs := token.NewFileSet()
+	for _, name := range names {
+		data, err := ioutil.ReadFile(name)
+		if err != nil {
+			// Warn but continue to next package.
+			warnf("%s: %s", name, err)
+			return false
+		}
+		checkBuildTag(name, data)
+		var parsedFile *ast.File
+		if strings.HasSuffix(name, ".go") {
+			parsedFile, err = parser.ParseFile(fs, name, data, 0)
+			if err != nil {
+				warnf("%s: %s", name, err)
+				return false
+			}
+			astFiles = append(astFiles, parsedFile)
+		}
+		files = append(files, &File{fset: fs, content: data, name: name, file: parsedFile})
+	}
+	if len(astFiles) == 0 {
+		return false
+	}
+	pkg := new(Package)
+	pkg.path = astFiles[0].Name.Name
+	pkg.files = files
+	// Type check the package.
+	err := pkg.check(fs, astFiles)
+	if err != nil && *verbose {
+		warnf("%s", err)
+	}
+
+	// Check.
+	chk := make(map[ast.Node][]func(*File, ast.Node))
+	for typ, set := range checkers {
+		for name, fn := range set {
+			if vet(name) {
+				chk[typ] = append(chk[typ], fn)
+			}
+		}
+	}
+	for _, file := range files {
+		file.pkg = pkg
+		file.checkers = chk
+		if file.file != nil {
+			file.walkFile(file.name, file.file)
+		}
+	}
+	asmCheck(pkg)
+	return true
+}
+
+func visit(path string, f os.FileInfo, err error) error {
+	if err != nil {
+		warnf("walk error: %s", err)
+		return err
+	}
+	// One package per directory. Ignore the files themselves.
+	if !f.IsDir() {
+		return nil
+	}
+	doPackageDir(path)
+	return nil
+}
+
+func (pkg *Package) hasFileWithSuffix(suffix string) bool {
+	for _, f := range pkg.files {
+		if strings.HasSuffix(f.name, suffix) {
+			return true
+		}
+	}
+	return false
+}
+
+// walkDir recursively walks the tree looking for Go packages.
+func walkDir(root string) {
+	filepath.Walk(root, visit)
+}
+
+// errorf formats the error to standard error, adding program
+// identification and a newline, and exits.
+func errorf(format string, args ...interface{}) {
+	fmt.Fprintf(os.Stderr, "vet: "+format+"\n", args...)
+	os.Exit(2)
+}
+
+// warnf formats the error to standard error, adding program
+// identification and a newline, but does not exit.
+func warnf(format string, args ...interface{}) {
+	fmt.Fprintf(os.Stderr, "vet: "+format+"\n", args...)
+	setExit(1)
+}
+
+// Println is fmt.Println guarded by -v.
+func Println(args ...interface{}) {
+	if !*verbose {
+		return
+	}
+	fmt.Println(args...)
+}
+
+// Printf is fmt.Printf guarded by -v.
+func Printf(format string, args ...interface{}) {
+	if !*verbose {
+		return
+	}
+	fmt.Printf(format+"\n", args...)
+}
+
+// Bad reports an error and sets the exit code..
+func (f *File) Bad(pos token.Pos, args ...interface{}) {
+	f.Warn(pos, args...)
+	setExit(1)
+}
+
+// Badf reports a formatted error and sets the exit code.
+func (f *File) Badf(pos token.Pos, format string, args ...interface{}) {
+	f.Warnf(pos, format, args...)
+	setExit(1)
+}
+
+// loc returns a formatted representation of the position.
+func (f *File) loc(pos token.Pos) string {
+	if pos == token.NoPos {
+		return ""
+	}
+	// Do not print columns. Because the pos often points to the start of an
+	// expression instead of the inner part with the actual error, the
+	// precision can mislead.
+	posn := f.fset.Position(pos)
+	return fmt.Sprintf("%s:%d: ", posn.Filename, posn.Line)
+}
+
+// Warn reports an error but does not set the exit code.
+func (f *File) Warn(pos token.Pos, args ...interface{}) {
+	fmt.Fprint(os.Stderr, f.loc(pos)+fmt.Sprintln(args...))
+}
+
+// Warnf reports a formatted error but does not set the exit code.
+func (f *File) Warnf(pos token.Pos, format string, args ...interface{}) {
+	fmt.Fprintf(os.Stderr, f.loc(pos)+format+"\n", args...)
+}
+
+// walkFile walks the file's tree.
+func (f *File) walkFile(name string, file *ast.File) {
+	Println("Checking file", name)
+	ast.Walk(f, file)
+}
+
+// Visit implements the ast.Visitor interface.
+func (f *File) Visit(node ast.Node) ast.Visitor {
+	var key ast.Node
+	switch node.(type) {
+	case *ast.AssignStmt:
+		key = assignStmt
+	case *ast.BinaryExpr:
+		key = binaryExpr
+	case *ast.CallExpr:
+		key = callExpr
+	case *ast.CompositeLit:
+		key = compositeLit
+	case *ast.ExprStmt:
+		key = exprStmt
+	case *ast.Field:
+		key = field
+	case *ast.FuncDecl:
+		key = funcDecl
+	case *ast.FuncLit:
+		key = funcLit
+	case *ast.GenDecl:
+		key = genDecl
+	case *ast.InterfaceType:
+		key = interfaceType
+	case *ast.RangeStmt:
+		key = rangeStmt
+	}
+	for _, fn := range f.checkers[key] {
+		fn(f, node)
+	}
+	return f
+}
+
+// gofmt returns a string representation of the expression.
+func (f *File) gofmt(x ast.Expr) string {
+	f.b.Reset()
+	printer.Fprint(&f.b, f.fset, x)
+	return f.b.String()
+}
diff --git a/cmd/vet/method.go b/cmd/vet/method.go
new file mode 100644
index 0000000..00949df
--- /dev/null
+++ b/cmd/vet/method.go
@@ -0,0 +1,182 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file contains the code to check canonical methods.
+
+package main
+
+import (
+	"fmt"
+	"go/ast"
+	"go/printer"
+	"strings"
+)
+
+func init() {
+	register("methods",
+		"check that canonically named methods are canonically defined",
+		checkCanonicalMethod,
+		funcDecl, interfaceType)
+}
+
+type MethodSig struct {
+	args    []string
+	results []string
+}
+
+// canonicalMethods lists the input and output types for Go methods
+// that are checked using dynamic interface checks.  Because the
+// checks are dynamic, such methods would not cause a compile error
+// if they have the wrong signature: instead the dynamic check would
+// fail, sometimes mysteriously.  If a method is found with a name listed
+// here but not the input/output types listed here, vet complains.
+//
+// A few of the canonical methods have very common names.
+// For example, a type might implement a Scan method that
+// has nothing to do with fmt.Scanner, but we still want to check
+// the methods that are intended to implement fmt.Scanner.
+// To do that, the arguments that have a = prefix are treated as
+// signals that the canonical meaning is intended: if a Scan
+// method doesn't have a fmt.ScanState as its first argument,
+// we let it go.  But if it does have a fmt.ScanState, then the
+// rest has to match.
+var canonicalMethods = map[string]MethodSig{
+	// "Flush": {{}, {"error"}}, // http.Flusher and jpeg.writer conflict
+	"Format":        {[]string{"=fmt.State", "rune"}, []string{}},                      // fmt.Formatter
+	"GobDecode":     {[]string{"[]byte"}, []string{"error"}},                           // gob.GobDecoder
+	"GobEncode":     {[]string{}, []string{"[]byte", "error"}},                         // gob.GobEncoder
+	"MarshalJSON":   {[]string{}, []string{"[]byte", "error"}},                         // json.Marshaler
+	"MarshalXML":    {[]string{"*xml.Encoder", "xml.StartElement"}, []string{"error"}}, // xml.Marshaler
+	"Peek":          {[]string{"=int"}, []string{"[]byte", "error"}},                   // image.reader (matching bufio.Reader)
+	"ReadByte":      {[]string{}, []string{"byte", "error"}},                           // io.ByteReader
+	"ReadFrom":      {[]string{"=io.Reader"}, []string{"int64", "error"}},              // io.ReaderFrom
+	"ReadRune":      {[]string{}, []string{"rune", "int", "error"}},                    // io.RuneReader
+	"Scan":          {[]string{"=fmt.ScanState", "rune"}, []string{"error"}},           // fmt.Scanner
+	"Seek":          {[]string{"=int64", "int"}, []string{"int64", "error"}},           // io.Seeker
+	"UnmarshalJSON": {[]string{"[]byte"}, []string{"error"}},                           // json.Unmarshaler
+	"UnmarshalXML":  {[]string{"*xml.Decoder", "xml.StartElement"}, []string{"error"}}, // xml.Unmarshaler
+	"UnreadByte":    {[]string{}, []string{"error"}},
+	"UnreadRune":    {[]string{}, []string{"error"}},
+	"WriteByte":     {[]string{"byte"}, []string{"error"}},                // jpeg.writer (matching bufio.Writer)
+	"WriteTo":       {[]string{"=io.Writer"}, []string{"int64", "error"}}, // io.WriterTo
+}
+
+func checkCanonicalMethod(f *File, node ast.Node) {
+	switch n := node.(type) {
+	case *ast.FuncDecl:
+		if n.Recv != nil {
+			canonicalMethod(f, n.Name, n.Type)
+		}
+	case *ast.InterfaceType:
+		for _, field := range n.Methods.List {
+			for _, id := range field.Names {
+				canonicalMethod(f, id, field.Type.(*ast.FuncType))
+			}
+		}
+	}
+}
+
+func canonicalMethod(f *File, id *ast.Ident, t *ast.FuncType) {
+	// Expected input/output.
+	expect, ok := canonicalMethods[id.Name]
+	if !ok {
+		return
+	}
+
+	// Actual input/output
+	args := typeFlatten(t.Params.List)
+	var results []ast.Expr
+	if t.Results != nil {
+		results = typeFlatten(t.Results.List)
+	}
+
+	// Do the =s (if any) all match?
+	if !f.matchParams(expect.args, args, "=") || !f.matchParams(expect.results, results, "=") {
+		return
+	}
+
+	// Everything must match.
+	if !f.matchParams(expect.args, args, "") || !f.matchParams(expect.results, results, "") {
+		expectFmt := id.Name + "(" + argjoin(expect.args) + ")"
+		if len(expect.results) == 1 {
+			expectFmt += " " + argjoin(expect.results)
+		} else if len(expect.results) > 1 {
+			expectFmt += " (" + argjoin(expect.results) + ")"
+		}
+
+		f.b.Reset()
+		if err := printer.Fprint(&f.b, f.fset, t); err != nil {
+			fmt.Fprintf(&f.b, "<%s>", err)
+		}
+		actual := f.b.String()
+		actual = strings.TrimPrefix(actual, "func")
+		actual = id.Name + actual
+
+		f.Badf(id.Pos(), "method %s should have signature %s", actual, expectFmt)
+	}
+}
+
+func argjoin(x []string) string {
+	y := make([]string, len(x))
+	for i, s := range x {
+		if s[0] == '=' {
+			s = s[1:]
+		}
+		y[i] = s
+	}
+	return strings.Join(y, ", ")
+}
+
+// Turn parameter list into slice of types
+// (in the ast, types are Exprs).
+// Have to handle f(int, bool) and f(x, y, z int)
+// so not a simple 1-to-1 conversion.
+func typeFlatten(l []*ast.Field) []ast.Expr {
+	var t []ast.Expr
+	for _, f := range l {
+		if len(f.Names) == 0 {
+			t = append(t, f.Type)
+			continue
+		}
+		for _ = range f.Names {
+			t = append(t, f.Type)
+		}
+	}
+	return t
+}
+
+// Does each type in expect with the given prefix match the corresponding type in actual?
+func (f *File) matchParams(expect []string, actual []ast.Expr, prefix string) bool {
+	for i, x := range expect {
+		if !strings.HasPrefix(x, prefix) {
+			continue
+		}
+		if i >= len(actual) {
+			return false
+		}
+		if !f.matchParamType(x, actual[i]) {
+			return false
+		}
+	}
+	if prefix == "" && len(actual) > len(expect) {
+		return false
+	}
+	return true
+}
+
+// Does this one type match?
+func (f *File) matchParamType(expect string, actual ast.Expr) bool {
+	if strings.HasPrefix(expect, "=") {
+		expect = expect[1:]
+	}
+	// Strip package name if we're in that package.
+	if n := len(f.file.Name.Name); len(expect) > n && expect[:n] == f.file.Name.Name && expect[n] == '.' {
+		expect = expect[n+1:]
+	}
+
+	// Overkill but easy.
+	f.b.Reset()
+	printer.Fprint(&f.b, f.fset, actual)
+	return f.b.String() == expect
+}
diff --git a/cmd/vet/nilfunc.go b/cmd/vet/nilfunc.go
new file mode 100644
index 0000000..fa1bac7
--- /dev/null
+++ b/cmd/vet/nilfunc.go
@@ -0,0 +1,68 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+/*
+This file contains the code to check for useless function comparisons.
+A useless comparison is one like f == nil as opposed to f() == nil.
+*/
+
+package main
+
+import (
+	"go/ast"
+	"go/token"
+
+	"golang.org/x/tools/go/types"
+)
+
+func init() {
+	register("nilfunc",
+		"check for comparisons between functions and nil",
+		checkNilFuncComparison,
+		binaryExpr)
+}
+
+func checkNilFuncComparison(f *File, node ast.Node) {
+	e := node.(*ast.BinaryExpr)
+
+	// Only want == or != comparisons.
+	if e.Op != token.EQL && e.Op != token.NEQ {
+		return
+	}
+
+	// Only want comparisons with a nil identifier on one side.
+	var e2 ast.Expr
+	switch {
+	case f.isNil(e.X):
+		e2 = e.Y
+	case f.isNil(e.Y):
+		e2 = e.X
+	default:
+		return
+	}
+
+	// Only want identifiers or selector expressions.
+	var obj types.Object
+	switch v := e2.(type) {
+	case *ast.Ident:
+		obj = f.pkg.uses[v]
+	case *ast.SelectorExpr:
+		obj = f.pkg.uses[v.Sel]
+	default:
+		return
+	}
+
+	// Only want functions.
+	if _, ok := obj.(*types.Func); !ok {
+		return
+	}
+
+	f.Badf(e.Pos(), "comparison of function %v %v nil is always %v", obj.Name(), e.Op, e.Op == token.NEQ)
+}
+
+// isNil reports whether the provided expression is the built-in nil
+// identifier.
+func (f *File) isNil(e ast.Expr) bool {
+	return f.pkg.types[e].Type == types.Typ[types.UntypedNil]
+}
diff --git a/cmd/vet/print.go b/cmd/vet/print.go
new file mode 100644
index 0000000..b20d935
--- /dev/null
+++ b/cmd/vet/print.go
@@ -0,0 +1,587 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file contains the printf-checker.
+
+package main
+
+import (
+	"bytes"
+	"flag"
+	"go/ast"
+	"go/token"
+	"strconv"
+	"strings"
+	"unicode/utf8"
+
+	"golang.org/x/tools/go/exact"
+	"golang.org/x/tools/go/types"
+)
+
+var printfuncs = flag.String("printfuncs", "", "comma-separated list of print function names to check")
+
+func init() {
+	register("printf",
+		"check printf-like invocations",
+		checkFmtPrintfCall,
+		funcDecl, callExpr)
+}
+
+func initPrintFlags() {
+	if *printfuncs == "" {
+		return
+	}
+	for _, name := range strings.Split(*printfuncs, ",") {
+		if len(name) == 0 {
+			flag.Usage()
+		}
+		skip := 0
+		if colon := strings.LastIndex(name, ":"); colon > 0 {
+			var err error
+			skip, err = strconv.Atoi(name[colon+1:])
+			if err != nil {
+				errorf(`illegal format for "Func:N" argument %q; %s`, name, err)
+			}
+			name = name[:colon]
+		}
+		name = strings.ToLower(name)
+		if name[len(name)-1] == 'f' {
+			printfList[name] = skip
+		} else {
+			printList[name] = skip
+		}
+	}
+}
+
+// printfList records the formatted-print functions. The value is the location
+// of the format parameter. Names are lower-cased so the lookup is
+// case insensitive.
+var printfList = map[string]int{
+	"errorf":  0,
+	"fatalf":  0,
+	"fprintf": 1,
+	"logf":    0,
+	"panicf":  0,
+	"printf":  0,
+	"sprintf": 0,
+}
+
+// printList records the unformatted-print functions. The value is the location
+// of the first parameter to be printed.  Names are lower-cased so the lookup is
+// case insensitive.
+var printList = map[string]int{
+	"error":  0,
+	"fatal":  0,
+	"fprint": 1, "fprintln": 1,
+	"log":   0,
+	"panic": 0, "panicln": 0,
+	"print": 0, "println": 0,
+	"sprint": 0, "sprintln": 0,
+}
+
+// checkCall triggers the print-specific checks if the call invokes a print function.
+func checkFmtPrintfCall(f *File, node ast.Node) {
+	if d, ok := node.(*ast.FuncDecl); ok && isStringer(f, d) {
+		// Remember we saw this.
+		if f.stringers == nil {
+			f.stringers = make(map[*ast.Object]bool)
+		}
+		if l := d.Recv.List; len(l) == 1 {
+			if n := l[0].Names; len(n) == 1 {
+				f.stringers[n[0].Obj] = true
+			}
+		}
+		return
+	}
+
+	call, ok := node.(*ast.CallExpr)
+	if !ok {
+		return
+	}
+	var Name string
+	switch x := call.Fun.(type) {
+	case *ast.Ident:
+		Name = x.Name
+	case *ast.SelectorExpr:
+		Name = x.Sel.Name
+	default:
+		return
+	}
+
+	name := strings.ToLower(Name)
+	if skip, ok := printfList[name]; ok {
+		f.checkPrintf(call, Name, skip)
+		return
+	}
+	if skip, ok := printList[name]; ok {
+		f.checkPrint(call, Name, skip)
+		return
+	}
+}
+
+// isStringer returns true if the provided declaration is a "String() string"
+// method, an implementation of fmt.Stringer.
+func isStringer(f *File, d *ast.FuncDecl) bool {
+	return d.Recv != nil && d.Name.Name == "String" && d.Type.Results != nil &&
+		len(d.Type.Params.List) == 0 && len(d.Type.Results.List) == 1 &&
+		f.pkg.types[d.Type.Results.List[0].Type].Type == types.Typ[types.String]
+}
+
+// formatState holds the parsed representation of a printf directive such as "%3.*[4]d".
+// It is constructed by parsePrintfVerb.
+type formatState struct {
+	verb     rune   // the format verb: 'd' for "%d"
+	format   string // the full format directive from % through verb, "%.3d".
+	name     string // Printf, Sprintf etc.
+	flags    []byte // the list of # + etc.
+	argNums  []int  // the successive argument numbers that are consumed, adjusted to refer to actual arg in call
+	indexed  bool   // whether an indexing expression appears: %[1]d.
+	firstArg int    // Index of first argument after the format in the Printf call.
+	// Used only during parse.
+	file         *File
+	call         *ast.CallExpr
+	argNum       int  // Which argument we're expecting to format now.
+	indexPending bool // Whether we have an indexed argument that has not resolved.
+	nbytes       int  // number of bytes of the format string consumed.
+}
+
+// checkPrintf checks a call to a formatted print routine such as Printf.
+// call.Args[formatIndex] is (well, should be) the format argument.
+func (f *File) checkPrintf(call *ast.CallExpr, name string, formatIndex int) {
+	if formatIndex >= len(call.Args) {
+		f.Bad(call.Pos(), "too few arguments in call to", name)
+		return
+	}
+	lit := f.pkg.types[call.Args[formatIndex]].Value
+	if lit == nil {
+		if *verbose {
+			f.Warn(call.Pos(), "can't check non-constant format in call to", name)
+		}
+		return
+	}
+	if lit.Kind() != exact.String {
+		f.Badf(call.Pos(), "constant %v not a string in call to %s", lit, name)
+		return
+	}
+	format := exact.StringVal(lit)
+	firstArg := formatIndex + 1 // Arguments are immediately after format string.
+	if !strings.Contains(format, "%") {
+		if len(call.Args) > firstArg {
+			f.Badf(call.Pos(), "no formatting directive in %s call", name)
+		}
+		return
+	}
+	// Hard part: check formats against args.
+	argNum := firstArg
+	indexed := false
+	for i, w := 0, 0; i < len(format); i += w {
+		w = 1
+		if format[i] == '%' {
+			state := f.parsePrintfVerb(call, name, format[i:], firstArg, argNum)
+			if state == nil {
+				return
+			}
+			w = len(state.format)
+			if state.indexed {
+				indexed = true
+			}
+			if !f.okPrintfArg(call, state) { // One error per format is enough.
+				return
+			}
+			if len(state.argNums) > 0 {
+				// Continue with the next sequential argument.
+				argNum = state.argNums[len(state.argNums)-1] + 1
+			}
+		}
+	}
+	// Dotdotdot is hard.
+	if call.Ellipsis.IsValid() && argNum >= len(call.Args)-1 {
+		return
+	}
+	// If the arguments were direct indexed, we assume the programmer knows what's up.
+	// Otherwise, there should be no leftover arguments.
+	if !indexed && argNum != len(call.Args) {
+		expect := argNum - firstArg
+		numArgs := len(call.Args) - firstArg
+		f.Badf(call.Pos(), "wrong number of args for format in %s call: %d needed but %d args", name, expect, numArgs)
+	}
+}
+
+// parseFlags accepts any printf flags.
+func (s *formatState) parseFlags() {
+	for s.nbytes < len(s.format) {
+		switch c := s.format[s.nbytes]; c {
+		case '#', '0', '+', '-', ' ':
+			s.flags = append(s.flags, c)
+			s.nbytes++
+		default:
+			return
+		}
+	}
+}
+
+// scanNum advances through a decimal number if present.
+func (s *formatState) scanNum() {
+	for ; s.nbytes < len(s.format); s.nbytes++ {
+		c := s.format[s.nbytes]
+		if c < '0' || '9' < c {
+			return
+		}
+	}
+}
+
+// parseIndex scans an index expression. It returns false if there is a syntax error.
+func (s *formatState) parseIndex() bool {
+	if s.nbytes == len(s.format) || s.format[s.nbytes] != '[' {
+		return true
+	}
+	// Argument index present.
+	s.indexed = true
+	s.nbytes++ // skip '['
+	start := s.nbytes
+	s.scanNum()
+	if s.nbytes == len(s.format) || s.nbytes == start || s.format[s.nbytes] != ']' {
+		s.file.Badf(s.call.Pos(), "illegal syntax for printf argument index")
+		return false
+	}
+	arg32, err := strconv.ParseInt(s.format[start:s.nbytes], 10, 32)
+	if err != nil {
+		s.file.Badf(s.call.Pos(), "illegal syntax for printf argument index: %s", err)
+		return false
+	}
+	s.nbytes++ // skip ']'
+	arg := int(arg32)
+	arg += s.firstArg - 1 // We want to zero-index the actual arguments.
+	s.argNum = arg
+	s.indexPending = true
+	return true
+}
+
+// parseNum scans a width or precision (or *). It returns false if there's a bad index expression.
+func (s *formatState) parseNum() bool {
+	if s.nbytes < len(s.format) && s.format[s.nbytes] == '*' {
+		if s.indexPending { // Absorb it.
+			s.indexPending = false
+		}
+		s.nbytes++
+		s.argNums = append(s.argNums, s.argNum)
+		s.argNum++
+	} else {
+		s.scanNum()
+	}
+	return true
+}
+
+// parsePrecision scans for a precision. It returns false if there's a bad index expression.
+func (s *formatState) parsePrecision() bool {
+	// If there's a period, there may be a precision.
+	if s.nbytes < len(s.format) && s.format[s.nbytes] == '.' {
+		s.flags = append(s.flags, '.') // Treat precision as a flag.
+		s.nbytes++
+		if !s.parseIndex() {
+			return false
+		}
+		if !s.parseNum() {
+			return false
+		}
+	}
+	return true
+}
+
+// parsePrintfVerb looks the formatting directive that begins the format string
+// and returns a formatState that encodes what the directive wants, without looking
+// at the actual arguments present in the call. The result is nil if there is an error.
+func (f *File) parsePrintfVerb(call *ast.CallExpr, name, format string, firstArg, argNum int) *formatState {
+	state := &formatState{
+		format:   format,
+		name:     name,
+		flags:    make([]byte, 0, 5),
+		argNum:   argNum,
+		argNums:  make([]int, 0, 1),
+		nbytes:   1, // There's guaranteed to be a percent sign.
+		indexed:  false,
+		firstArg: firstArg,
+		file:     f,
+		call:     call,
+	}
+	// There may be flags.
+	state.parseFlags()
+	indexPending := false
+	// There may be an index.
+	if !state.parseIndex() {
+		return nil
+	}
+	// There may be a width.
+	if !state.parseNum() {
+		return nil
+	}
+	// There may be a precision.
+	if !state.parsePrecision() {
+		return nil
+	}
+	// Now a verb, possibly prefixed by an index (which we may already have).
+	if !indexPending && !state.parseIndex() {
+		return nil
+	}
+	if state.nbytes == len(state.format) {
+		f.Badf(call.Pos(), "missing verb at end of format string in %s call", name)
+		return nil
+	}
+	verb, w := utf8.DecodeRuneInString(state.format[state.nbytes:])
+	state.verb = verb
+	state.nbytes += w
+	if verb != '%' {
+		state.argNums = append(state.argNums, state.argNum)
+	}
+	state.format = state.format[:state.nbytes]
+	return state
+}
+
+// printfArgType encodes the types of expressions a printf verb accepts. It is a bitmask.
+type printfArgType int
+
+const (
+	argBool printfArgType = 1 << iota
+	argInt
+	argRune
+	argString
+	argFloat
+	argComplex
+	argPointer
+	anyType printfArgType = ^0
+)
+
+type printVerb struct {
+	verb  rune   // User may provide verb through Formatter; could be a rune.
+	flags string // known flags are all ASCII
+	typ   printfArgType
+}
+
+// Common flag sets for printf verbs.
+const (
+	noFlag       = ""
+	numFlag      = " -+.0"
+	sharpNumFlag = " -+.0#"
+	allFlags     = " -+.0#"
+)
+
+// printVerbs identifies which flags are known to printf for each verb.
+// TODO: A type that implements Formatter may do what it wants, and vet
+// will complain incorrectly.
+var printVerbs = []printVerb{
+	// '-' is a width modifier, always valid.
+	// '.' is a precision for float, max width for strings.
+	// '+' is required sign for numbers, Go format for %v.
+	// '#' is alternate format for several verbs.
+	// ' ' is spacer for numbers
+	{'%', noFlag, 0},
+	{'b', numFlag, argInt | argFloat | argComplex},
+	{'c', "-", argRune | argInt},
+	{'d', numFlag, argInt},
+	{'e', numFlag, argFloat | argComplex},
+	{'E', numFlag, argFloat | argComplex},
+	{'f', numFlag, argFloat | argComplex},
+	{'F', numFlag, argFloat | argComplex},
+	{'g', numFlag, argFloat | argComplex},
+	{'G', numFlag, argFloat | argComplex},
+	{'o', sharpNumFlag, argInt},
+	{'p', "-#", argPointer},
+	{'q', " -+.0#", argRune | argInt | argString},
+	{'s', " -+.0", argString},
+	{'t', "-", argBool},
+	{'T', "-", anyType},
+	{'U', "-#", argRune | argInt},
+	{'v', allFlags, anyType},
+	{'x', sharpNumFlag, argRune | argInt | argString},
+	{'X', sharpNumFlag, argRune | argInt | argString},
+}
+
+// okPrintfArg compares the formatState to the arguments actually present,
+// reporting any discrepancies it can discern. If the final argument is ellipsissed,
+// there's little it can do for that.
+func (f *File) okPrintfArg(call *ast.CallExpr, state *formatState) (ok bool) {
+	var v printVerb
+	found := false
+	// Linear scan is fast enough for a small list.
+	for _, v = range printVerbs {
+		if v.verb == state.verb {
+			found = true
+			break
+		}
+	}
+	if !found {
+		f.Badf(call.Pos(), "unrecognized printf verb %q", state.verb)
+		return false
+	}
+	for _, flag := range state.flags {
+		if !strings.ContainsRune(v.flags, rune(flag)) {
+			f.Badf(call.Pos(), "unrecognized printf flag for verb %q: %q", state.verb, flag)
+			return false
+		}
+	}
+	// Verb is good. If len(state.argNums)>trueArgs, we have something like %.*s and all
+	// but the final arg must be an integer.
+	trueArgs := 1
+	if state.verb == '%' {
+		trueArgs = 0
+	}
+	nargs := len(state.argNums)
+	for i := 0; i < nargs-trueArgs; i++ {
+		argNum := state.argNums[i]
+		if !f.argCanBeChecked(call, i, true, state) {
+			return
+		}
+		arg := call.Args[argNum]
+		if !f.matchArgType(argInt, nil, arg) {
+			f.Badf(call.Pos(), "arg %s for * in printf format not of type int", f.gofmt(arg))
+			return false
+		}
+	}
+	if state.verb == '%' {
+		return true
+	}
+	argNum := state.argNums[len(state.argNums)-1]
+	if !f.argCanBeChecked(call, len(state.argNums)-1, false, state) {
+		return false
+	}
+	arg := call.Args[argNum]
+	if !f.matchArgType(v.typ, nil, arg) {
+		typeString := ""
+		if typ := f.pkg.types[arg].Type; typ != nil {
+			typeString = typ.String()
+		}
+		f.Badf(call.Pos(), "arg %s for printf verb %%%c of wrong type: %s", f.gofmt(arg), state.verb, typeString)
+		return false
+	}
+	if v.typ&argString != 0 && v.verb != 'T' && !bytes.Contains(state.flags, []byte{'#'}) && f.recursiveStringer(arg) {
+		f.Badf(call.Pos(), "arg %s for printf causes recursive call to String method", f.gofmt(arg))
+		return false
+	}
+	return true
+}
+
+// recursiveStringer reports whether the provided argument is r or &r for the
+// fmt.Stringer receiver identifier r.
+func (f *File) recursiveStringer(e ast.Expr) bool {
+	if len(f.stringers) == 0 {
+		return false
+	}
+	var obj *ast.Object
+	switch e := e.(type) {
+	case *ast.Ident:
+		obj = e.Obj
+	case *ast.UnaryExpr:
+		if id, ok := e.X.(*ast.Ident); ok && e.Op == token.AND {
+			obj = id.Obj
+		}
+	}
+
+	// It's unlikely to be a recursive stringer if it has a Format method.
+	if typ := f.pkg.types[e].Type; typ != nil {
+		// Not a perfect match; see issue 6259.
+		if f.hasMethod(typ, "Format") {
+			return false
+		}
+	}
+
+	// We compare the underlying Object, which checks that the identifier
+	// is the one we declared as the receiver for the String method in
+	// which this printf appears.
+	return f.stringers[obj]
+}
+
+// argCanBeChecked reports whether the specified argument is statically present;
+// it may be beyond the list of arguments or in a terminal slice... argument, which
+// means we can't see it.
+func (f *File) argCanBeChecked(call *ast.CallExpr, formatArg int, isStar bool, state *formatState) bool {
+	argNum := state.argNums[formatArg]
+	if argNum < 0 {
+		// Shouldn't happen, so catch it with prejudice.
+		panic("negative arg num")
+	}
+	if argNum == 0 {
+		f.Badf(call.Pos(), `index value [0] for %s("%s"); indexes start at 1`, state.name, state.format)
+		return false
+	}
+	if argNum < len(call.Args)-1 {
+		return true // Always OK.
+	}
+	if call.Ellipsis.IsValid() {
+		return false // We just can't tell; there could be many more arguments.
+	}
+	if argNum < len(call.Args) {
+		return true
+	}
+	// There are bad indexes in the format or there are fewer arguments than the format needs.
+	// This is the argument number relative to the format: Printf("%s", "hi") will give 1 for the "hi".
+	arg := argNum - state.firstArg + 1 // People think of arguments as 1-indexed.
+	f.Badf(call.Pos(), `missing argument for %s("%s"): format reads arg %d, have only %d args`, state.name, state.format, arg, len(call.Args)-state.firstArg)
+	return false
+}
+
+// checkPrint checks a call to an unformatted print routine such as Println.
+// call.Args[firstArg] is the first argument to be printed.
+func (f *File) checkPrint(call *ast.CallExpr, name string, firstArg int) {
+	isLn := strings.HasSuffix(name, "ln")
+	isF := strings.HasPrefix(name, "F")
+	args := call.Args
+	if name == "Log" && len(args) > 0 {
+		// Special case: Don't complain about math.Log or cmplx.Log.
+		// Not strictly necessary because the only complaint likely is for Log("%d")
+		// but it feels wrong to check that math.Log is a good print function.
+		if sel, ok := args[0].(*ast.SelectorExpr); ok {
+			if x, ok := sel.X.(*ast.Ident); ok {
+				if x.Name == "math" || x.Name == "cmplx" {
+					return
+				}
+			}
+		}
+	}
+	// check for Println(os.Stderr, ...)
+	if firstArg == 0 && !isF && len(args) > 0 {
+		if sel, ok := args[0].(*ast.SelectorExpr); ok {
+			if x, ok := sel.X.(*ast.Ident); ok {
+				if x.Name == "os" && strings.HasPrefix(sel.Sel.Name, "Std") {
+					f.Badf(call.Pos(), "first argument to %s is %s.%s", name, x.Name, sel.Sel.Name)
+				}
+			}
+		}
+	}
+	if len(args) <= firstArg {
+		// If we have a call to a method called Error that satisfies the Error interface,
+		// then it's ok. Otherwise it's something like (*T).Error from the testing package
+		// and we need to check it.
+		if name == "Error" && f.isErrorMethodCall(call) {
+			return
+		}
+		// If it's an Error call now, it's probably for printing errors.
+		if !isLn {
+			// Check the signature to be sure: there are niladic functions called "error".
+			if firstArg != 0 || f.numArgsInSignature(call) != firstArg {
+				f.Badf(call.Pos(), "no args in %s call", name)
+			}
+		}
+		return
+	}
+	arg := args[firstArg]
+	if lit, ok := arg.(*ast.BasicLit); ok && lit.Kind == token.STRING {
+		if strings.Contains(lit.Value, "%") {
+			f.Badf(call.Pos(), "possible formatting directive in %s call", name)
+		}
+	}
+	if isLn {
+		// The last item, if a string, should not have a newline.
+		arg = args[len(call.Args)-1]
+		if lit, ok := arg.(*ast.BasicLit); ok && lit.Kind == token.STRING {
+			if strings.HasSuffix(lit.Value, `\n"`) {
+				f.Badf(call.Pos(), "%s call ends with newline", name)
+			}
+		}
+	}
+	for _, arg := range args {
+		if f.recursiveStringer(arg) {
+			f.Badf(call.Pos(), "arg %s for print causes recursive call to String method", f.gofmt(arg))
+		}
+	}
+}
diff --git a/cmd/vet/rangeloop.go b/cmd/vet/rangeloop.go
new file mode 100644
index 0000000..96e2ca8
--- /dev/null
+++ b/cmd/vet/rangeloop.go
@@ -0,0 +1,70 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+/*
+This file contains the code to check range loop variables bound inside function
+literals that are deferred or launched in new goroutines. We only check
+instances where the defer or go statement is the last statement in the loop
+body, as otherwise we would need whole program analysis.
+
+For example:
+
+	for i, v := range s {
+		go func() {
+			println(i, v) // not what you might expect
+		}()
+	}
+
+See: http://golang.org/doc/go_faq.html#closures_and_goroutines
+*/
+
+package main
+
+import "go/ast"
+
+func init() {
+	register("rangeloops",
+		"check that range loop variables are used correctly",
+		checkRangeLoop,
+		rangeStmt)
+}
+
+// checkRangeLoop walks the body of the provided range statement, checking if
+// its index or value variables are used unsafely inside goroutines or deferred
+// function literals.
+func checkRangeLoop(f *File, node ast.Node) {
+	n := node.(*ast.RangeStmt)
+	key, _ := n.Key.(*ast.Ident)
+	val, _ := n.Value.(*ast.Ident)
+	if key == nil && val == nil {
+		return
+	}
+	sl := n.Body.List
+	if len(sl) == 0 {
+		return
+	}
+	var last *ast.CallExpr
+	switch s := sl[len(sl)-1].(type) {
+	case *ast.GoStmt:
+		last = s.Call
+	case *ast.DeferStmt:
+		last = s.Call
+	default:
+		return
+	}
+	lit, ok := last.Fun.(*ast.FuncLit)
+	if !ok {
+		return
+	}
+	ast.Inspect(lit.Body, func(n ast.Node) bool {
+		id, ok := n.(*ast.Ident)
+		if !ok || id.Obj == nil {
+			return true
+		}
+		if key != nil && id.Obj == key.Obj || val != nil && id.Obj == val.Obj {
+			f.Bad(id.Pos(), "range variable", id.Name, "captured by func literal")
+		}
+		return true
+	})
+}
diff --git a/cmd/vet/shadow.go b/cmd/vet/shadow.go
new file mode 100644
index 0000000..fa680a0
--- /dev/null
+++ b/cmd/vet/shadow.go
@@ -0,0 +1,245 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+/*
+This file contains the code to check for shadowed variables.
+A shadowed variable is a variable declared in an inner scope
+with the same name and type as a variable in an outer scope,
+and where the outer variable is mentioned after the inner one
+is declared.
+
+(This definition can be refined; the module generates too many
+false positives and is not yet enabled by default.)
+
+For example:
+
+	func BadRead(f *os.File, buf []byte) error {
+		var err error
+		for {
+			n, err := f.Read(buf) // shadows the function variable 'err'
+			if err != nil {
+				break // causes return of wrong value
+			}
+			foo(buf)
+		}
+		return err
+	}
+
+*/
+
+package main
+
+import (
+	"flag"
+	"go/ast"
+	"go/token"
+
+	"golang.org/x/tools/go/types"
+)
+
+var strictShadowing = flag.Bool("shadowstrict", false, "whether to be strict about shadowing; can be noisy")
+
+func init() {
+	register("shadow",
+		"check for shadowed variables (experimental; must be set explicitly)",
+		checkShadow,
+		assignStmt, genDecl)
+	experimental["shadow"] = true
+}
+
+func checkShadow(f *File, node ast.Node) {
+	switch n := node.(type) {
+	case *ast.AssignStmt:
+		checkShadowAssignment(f, n)
+	case *ast.GenDecl:
+		checkShadowDecl(f, n)
+	}
+}
+
+// Span stores the minimum range of byte positions in the file in which a
+// given variable (types.Object) is mentioned. It is lexically defined: it spans
+// from the beginning of its first mention to the end of its last mention.
+// A variable is considered shadowed (if *strictShadowing is off) only if the
+// shadowing variable is declared within the span of the shadowed variable.
+// In other words, if a variable is shadowed but not used after the shadowed
+// variable is declared, it is inconsequential and not worth complaining about.
+// This simple check dramatically reduces the nuisance rate for the shadowing
+// check, at least until something cleverer comes along.
+//
+// One wrinkle: A "naked return" is a silent use of a variable that the Span
+// will not capture, but the compilers catch naked returns of shadowed
+// variables so we don't need to.
+//
+// Cases this gets wrong (TODO):
+// - If a for loop's continuation statement mentions a variable redeclared in
+// the block, we should complain about it but don't.
+// - A variable declared inside a function literal can falsely be identified
+// as shadowing a variable in the outer function.
+//
+type Span struct {
+	min token.Pos
+	max token.Pos
+}
+
+// contains reports whether the position is inside the span.
+func (s Span) contains(pos token.Pos) bool {
+	return s.min <= pos && pos < s.max
+}
+
+// growSpan expands the span for the object to contain the instance represented
+// by the identifier.
+func (pkg *Package) growSpan(ident *ast.Ident, obj types.Object) {
+	if *strictShadowing {
+		return // No need
+	}
+	pos := ident.Pos()
+	end := ident.End()
+	span, ok := pkg.spans[obj]
+	if ok {
+		if span.min > pos {
+			span.min = pos
+		}
+		if span.max < end {
+			span.max = end
+		}
+	} else {
+		span = Span{pos, end}
+	}
+	pkg.spans[obj] = span
+}
+
+// checkShadowAssignment checks for shadowing in a short variable declaration.
+func checkShadowAssignment(f *File, a *ast.AssignStmt) {
+	if a.Tok != token.DEFINE {
+		return
+	}
+	if f.idiomaticShortRedecl(a) {
+		return
+	}
+	for _, expr := range a.Lhs {
+		ident, ok := expr.(*ast.Ident)
+		if !ok {
+			f.Badf(expr.Pos(), "invalid AST: short variable declaration of non-identifier")
+			return
+		}
+		checkShadowing(f, ident)
+	}
+}
+
+// idiomaticShortRedecl reports whether this short declaration can be ignored for
+// the purposes of shadowing, that is, that any redeclarations it contains are deliberate.
+func (f *File) idiomaticShortRedecl(a *ast.AssignStmt) bool {
+	// Don't complain about deliberate redeclarations of the form
+	//	i := i
+	// Such constructs are idiomatic in range loops to create a new variable
+	// for each iteration. Another example is
+	//	switch n := n.(type)
+	if len(a.Rhs) != len(a.Lhs) {
+		return false
+	}
+	// We know it's an assignment, so the LHS must be all identifiers. (We check anyway.)
+	for i, expr := range a.Lhs {
+		lhs, ok := expr.(*ast.Ident)
+		if !ok {
+			f.Badf(expr.Pos(), "invalid AST: short variable declaration of non-identifier")
+			return true // Don't do any more processing.
+		}
+		switch rhs := a.Rhs[i].(type) {
+		case *ast.Ident:
+			if lhs.Name != rhs.Name {
+				return false
+			}
+		case *ast.TypeAssertExpr:
+			if id, ok := rhs.X.(*ast.Ident); ok {
+				if lhs.Name != id.Name {
+					return false
+				}
+			}
+		}
+	}
+	return true
+}
+
+// idiomaticRedecl reports whether this declaration spec can be ignored for
+// the purposes of shadowing, that is, that any redeclarations it contains are deliberate.
+func (f *File) idiomaticRedecl(d *ast.ValueSpec) bool {
+	// Don't complain about deliberate redeclarations of the form
+	//	var i, j = i, j
+	if len(d.Names) != len(d.Values) {
+		return false
+	}
+	for i, lhs := range d.Names {
+		if rhs, ok := d.Values[i].(*ast.Ident); ok {
+			if lhs.Name != rhs.Name {
+				return false
+			}
+		}
+	}
+	return true
+}
+
+// checkShadowDecl checks for shadowing in a general variable declaration.
+func checkShadowDecl(f *File, d *ast.GenDecl) {
+	if d.Tok != token.VAR {
+		return
+	}
+	for _, spec := range d.Specs {
+		valueSpec, ok := spec.(*ast.ValueSpec)
+		if !ok {
+			f.Badf(spec.Pos(), "invalid AST: var GenDecl not ValueSpec")
+			return
+		}
+		// Don't complain about deliberate redeclarations of the form
+		//	var i = i
+		if f.idiomaticRedecl(valueSpec) {
+			return
+		}
+		for _, ident := range valueSpec.Names {
+			checkShadowing(f, ident)
+		}
+	}
+}
+
+// checkShadowing checks whether the identifier shadows an identifier in an outer scope.
+func checkShadowing(f *File, ident *ast.Ident) {
+	if ident.Name == "_" {
+		// Can't shadow the blank identifier.
+		return
+	}
+	obj := f.pkg.defs[ident]
+	if obj == nil {
+		return
+	}
+	// obj.Parent.Parent is the surrounding scope. If we can find another declaration
+	// starting from there, we have a shadowed identifier.
+	_, shadowed := obj.Parent().Parent().LookupParent(obj.Name(), obj.Pos())
+	if shadowed == nil {
+		return
+	}
+	// Don't complain if it's shadowing a universe-declared identifier; that's fine.
+	if shadowed.Parent() == types.Universe {
+		return
+	}
+	if *strictShadowing {
+		// The shadowed identifier must appear before this one to be an instance of shadowing.
+		if shadowed.Pos() > ident.Pos() {
+			return
+		}
+	} else {
+		// Don't complain if the span of validity of the shadowed identifier doesn't include
+		// the shadowing identifier.
+		span, ok := f.pkg.spans[shadowed]
+		if !ok {
+			f.Badf(ident.Pos(), "internal error: no range for %s", ident.Name)
+			return
+		}
+		if !span.contains(ident.Pos()) {
+			return
+		}
+	}
+	// Don't complain if the types differ: that implies the programmer really wants two different things.
+	if types.Identical(obj.Type(), shadowed.Type()) {
+		f.Badf(ident.Pos(), "declaration of %s shadows declaration at %s", obj.Name(), f.loc(shadowed.Pos()))
+	}
+}
diff --git a/cmd/vet/shift.go b/cmd/vet/shift.go
new file mode 100644
index 0000000..2385c23
--- /dev/null
+++ b/cmd/vet/shift.go
@@ -0,0 +1,83 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+/*
+This file contains the code to check for suspicious shifts.
+*/
+
+package main
+
+import (
+	"go/ast"
+	"go/token"
+
+	"golang.org/x/tools/go/exact"
+	"golang.org/x/tools/go/types"
+)
+
+func init() {
+	register("shift",
+		"check for useless shifts",
+		checkShift,
+		binaryExpr, assignStmt)
+}
+
+func checkShift(f *File, node ast.Node) {
+	switch node := node.(type) {
+	case *ast.BinaryExpr:
+		if node.Op == token.SHL || node.Op == token.SHR {
+			checkLongShift(f, node, node.X, node.Y)
+		}
+	case *ast.AssignStmt:
+		if len(node.Lhs) != 1 || len(node.Rhs) != 1 {
+			return
+		}
+		if node.Tok == token.SHL_ASSIGN || node.Tok == token.SHR_ASSIGN {
+			checkLongShift(f, node, node.Lhs[0], node.Rhs[0])
+		}
+	}
+}
+
+// checkLongShift checks if shift or shift-assign operations shift by more than
+// the length of the underlying variable.
+func checkLongShift(f *File, node ast.Node, x, y ast.Expr) {
+	v := f.pkg.types[y].Value
+	if v == nil {
+		return
+	}
+	amt, ok := exact.Int64Val(v)
+	if !ok {
+		return
+	}
+	t := f.pkg.types[x].Type
+	if t == nil {
+		return
+	}
+	b, ok := t.Underlying().(*types.Basic)
+	if !ok {
+		return
+	}
+	var size int64
+	var msg string
+	switch b.Kind() {
+	case types.Uint8, types.Int8:
+		size = 8
+	case types.Uint16, types.Int16:
+		size = 16
+	case types.Uint32, types.Int32:
+		size = 32
+	case types.Uint64, types.Int64:
+		size = 64
+	case types.Int, types.Uint, types.Uintptr:
+		// These types may be as small as 32 bits, but no smaller.
+		size = 32
+		msg = "might be "
+	default:
+		return
+	}
+	if amt >= size {
+		ident := f.gofmt(x)
+		f.Badf(node.Pos(), "%s %stoo small for shift of %d", ident, msg, amt)
+	}
+}
diff --git a/cmd/vet/structtag.go b/cmd/vet/structtag.go
new file mode 100644
index 0000000..e8164a4
--- /dev/null
+++ b/cmd/vet/structtag.go
@@ -0,0 +1,122 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file contains the test for canonical struct tags.
+
+package main
+
+import (
+	"errors"
+	"go/ast"
+	"reflect"
+	"strconv"
+)
+
+func init() {
+	register("structtags",
+		"check that struct field tags have canonical format and apply to exported fields as needed",
+		checkCanonicalFieldTag,
+		field)
+}
+
+// checkCanonicalFieldTag checks a struct field tag.
+func checkCanonicalFieldTag(f *File, node ast.Node) {
+	field := node.(*ast.Field)
+	if field.Tag == nil {
+		return
+	}
+
+	tag, err := strconv.Unquote(field.Tag.Value)
+	if err != nil {
+		f.Badf(field.Pos(), "unable to read struct tag %s", field.Tag.Value)
+		return
+	}
+
+	if err := validateStructTag(tag); err != nil {
+		f.Badf(field.Pos(), "struct field tag %s not compatible with reflect.StructTag.Get: %s", field.Tag.Value, err)
+	}
+
+	// Check for use of json or xml tags with unexported fields.
+
+	// Embedded struct. Nothing to do for now, but that
+	// may change, depending on what happens with issue 7363.
+	if len(field.Names) == 0 {
+		return
+	}
+
+	if field.Names[0].IsExported() {
+		return
+	}
+
+	st := reflect.StructTag(tag)
+	for _, enc := range [...]string{"json", "xml"} {
+		if st.Get(enc) != "" {
+			f.Badf(field.Pos(), "struct field %s has %s tag but is not exported", field.Names[0].Name, enc)
+			return
+		}
+	}
+}
+
+var (
+	errTagSyntax      = errors.New("bad syntax for struct tag pair")
+	errTagKeySyntax   = errors.New("bad syntax for struct tag key")
+	errTagValueSyntax = errors.New("bad syntax for struct tag value")
+)
+
+// validateStructTag parses the struct tag and returns an error if it is not
+// in the canonical format, which is a space-separated list of key:"value"
+// settings. The value may contain spaces.
+func validateStructTag(tag string) error {
+	// This code is based on the StructTag.Get code in package reflect.
+
+	for tag != "" {
+		// Skip leading space.
+		i := 0
+		for i < len(tag) && tag[i] == ' ' {
+			i++
+		}
+		tag = tag[i:]
+		if tag == "" {
+			break
+		}
+
+		// Scan to colon. A space, a quote or a control character is a syntax error.
+		// Strictly speaking, control chars include the range [0x7f, 0x9f], not just
+		// [0x00, 0x1f], but in practice, we ignore the multi-byte control characters
+		// as it is simpler to inspect the tag's bytes than the tag's runes.
+		i = 0
+		for i < len(tag) && tag[i] > ' ' && tag[i] != ':' && tag[i] != '"' && tag[i] != 0x7f {
+			i++
+		}
+		if i == 0 {
+			return errTagKeySyntax
+		}
+		if i+1 >= len(tag) || tag[i] != ':' {
+			return errTagSyntax
+		}
+		if tag[i+1] != '"' {
+			return errTagValueSyntax
+		}
+		tag = tag[i+1:]
+
+		// Scan quoted string to find value.
+		i = 1
+		for i < len(tag) && tag[i] != '"' {
+			if tag[i] == '\\' {
+				i++
+			}
+			i++
+		}
+		if i >= len(tag) {
+			return errTagValueSyntax
+		}
+		qvalue := string(tag[:i+1])
+		tag = tag[i+1:]
+
+		if _, err := strconv.Unquote(qvalue); err != nil {
+			return errTagValueSyntax
+		}
+	}
+	return nil
+}
diff --git a/cmd/vet/testdata/asm.go b/cmd/vet/testdata/asm.go
new file mode 100644
index 0000000..9a3d531
--- /dev/null
+++ b/cmd/vet/testdata/asm.go
@@ -0,0 +1,33 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build ignore
+
+// This file contains declarations to test the assembly in test_asm.s.
+
+package testdata
+
+func arg1(x int8, y uint8)
+func arg2(x int16, y uint16)
+func arg4(x int32, y uint32)
+func arg8(x int64, y uint64)
+func argint(x int, y uint)
+func argptr(x *byte, y *byte, c chan int, m map[int]int, f func())
+func argstring(x, y string)
+func argslice(x, y []string)
+func argiface(x interface{}, y interface {
+	m()
+})
+func returnint() int
+func returnbyte(x int) byte
+func returnnamed(x byte) (r1 int, r2 int16, r3 string, r4 byte)
+func returnintmissing() int
+func leaf(x, y int) int
+
+func noprof(x int)
+func dupok(x int)
+func nosplit(x int)
+func rodata(x int)
+func noptr(x int)
+func wrapper(x int)
diff --git a/cmd/vet/testdata/asm1.s b/cmd/vet/testdata/asm1.s
new file mode 100644
index 0000000..62f423c
--- /dev/null
+++ b/cmd/vet/testdata/asm1.s
@@ -0,0 +1,254 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build amd64
+// +build vet_test
+
+TEXT ·arg1(SB),0,$0-2
+	MOVB	x+0(FP), AX
+	// MOVB x+0(FP), AX // commented out instructions used to panic
+	MOVB	y+1(FP), BX
+	MOVW	x+0(FP), AX // ERROR "\[amd64\] arg1: invalid MOVW of x\+0\(FP\); int8 is 1-byte value"
+	MOVW	y+1(FP), AX // ERROR "invalid MOVW of y\+1\(FP\); uint8 is 1-byte value"
+	MOVL	x+0(FP), AX // ERROR "invalid MOVL of x\+0\(FP\); int8 is 1-byte value"
+	MOVL	y+1(FP), AX // ERROR "invalid MOVL of y\+1\(FP\); uint8 is 1-byte value"
+	MOVQ	x+0(FP), AX // ERROR "invalid MOVQ of x\+0\(FP\); int8 is 1-byte value"
+	MOVQ	y+1(FP), AX // ERROR "invalid MOVQ of y\+1\(FP\); uint8 is 1-byte value"
+	MOVB	x+1(FP), AX // ERROR "invalid offset x\+1\(FP\); expected x\+0\(FP\)"
+	MOVB	y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+1\(FP\)"
+	TESTB	x+0(FP), AX
+	TESTB	y+1(FP), BX
+	TESTW	x+0(FP), AX // ERROR "invalid TESTW of x\+0\(FP\); int8 is 1-byte value"
+	TESTW	y+1(FP), AX // ERROR "invalid TESTW of y\+1\(FP\); uint8 is 1-byte value"
+	TESTL	x+0(FP), AX // ERROR "invalid TESTL of x\+0\(FP\); int8 is 1-byte value"
+	TESTL	y+1(FP), AX // ERROR "invalid TESTL of y\+1\(FP\); uint8 is 1-byte value"
+	TESTQ	x+0(FP), AX // ERROR "invalid TESTQ of x\+0\(FP\); int8 is 1-byte value"
+	TESTQ	y+1(FP), AX // ERROR "invalid TESTQ of y\+1\(FP\); uint8 is 1-byte value"
+	TESTB	x+1(FP), AX // ERROR "invalid offset x\+1\(FP\); expected x\+0\(FP\)"
+	TESTB	y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+1\(FP\)"
+	MOVB	8(SP), AX // ERROR "8\(SP\) should be x\+0\(FP\)"
+	MOVB	9(SP), AX // ERROR "9\(SP\) should be y\+1\(FP\)"
+	MOVB	10(SP), AX // ERROR "use of 10\(SP\) points beyond argument frame"
+	RET
+
+TEXT ·arg2(SB),0,$0-4
+	MOVB	x+0(FP), AX // ERROR "arg2: invalid MOVB of x\+0\(FP\); int16 is 2-byte value"
+	MOVB	y+2(FP), AX // ERROR "invalid MOVB of y\+2\(FP\); uint16 is 2-byte value"
+	MOVW	x+0(FP), AX
+	MOVW	y+2(FP), BX
+	MOVL	x+0(FP), AX // ERROR "invalid MOVL of x\+0\(FP\); int16 is 2-byte value"
+	MOVL	y+2(FP), AX // ERROR "invalid MOVL of y\+2\(FP\); uint16 is 2-byte value"
+	MOVQ	x+0(FP), AX // ERROR "invalid MOVQ of x\+0\(FP\); int16 is 2-byte value"
+	MOVQ	y+2(FP), AX // ERROR "invalid MOVQ of y\+2\(FP\); uint16 is 2-byte value"
+	MOVW	x+2(FP), AX // ERROR "invalid offset x\+2\(FP\); expected x\+0\(FP\)"
+	MOVW	y+0(FP), AX // ERROR "invalid offset y\+0\(FP\); expected y\+2\(FP\)"
+	TESTB	x+0(FP), AX // ERROR "invalid TESTB of x\+0\(FP\); int16 is 2-byte value"
+	TESTB	y+2(FP), AX // ERROR "invalid TESTB of y\+2\(FP\); uint16 is 2-byte value"
+	TESTW	x+0(FP), AX
+	TESTW	y+2(FP), BX
+	TESTL	x+0(FP), AX // ERROR "invalid TESTL of x\+0\(FP\); int16 is 2-byte value"
+	TESTL	y+2(FP), AX // ERROR "invalid TESTL of y\+2\(FP\); uint16 is 2-byte value"
+	TESTQ	x+0(FP), AX // ERROR "invalid TESTQ of x\+0\(FP\); int16 is 2-byte value"
+	TESTQ	y+2(FP), AX // ERROR "invalid TESTQ of y\+2\(FP\); uint16 is 2-byte value"
+	TESTW	x+2(FP), AX // ERROR "invalid offset x\+2\(FP\); expected x\+0\(FP\)"
+	TESTW	y+0(FP), AX // ERROR "invalid offset y\+0\(FP\); expected y\+2\(FP\)"
+	RET
+
+TEXT ·arg4(SB),0,$0-2 // ERROR "arg4: wrong argument size 2; expected \$\.\.\.-8"
+	MOVB	x+0(FP), AX // ERROR "invalid MOVB of x\+0\(FP\); int32 is 4-byte value"
+	MOVB	y+4(FP), BX // ERROR "invalid MOVB of y\+4\(FP\); uint32 is 4-byte value"
+	MOVW	x+0(FP), AX // ERROR "invalid MOVW of x\+0\(FP\); int32 is 4-byte value"
+	MOVW	y+4(FP), AX // ERROR "invalid MOVW of y\+4\(FP\); uint32 is 4-byte value"
+	MOVL	x+0(FP), AX
+	MOVL	y+4(FP), AX
+	MOVQ	x+0(FP), AX // ERROR "invalid MOVQ of x\+0\(FP\); int32 is 4-byte value"
+	MOVQ	y+4(FP), AX // ERROR "invalid MOVQ of y\+4\(FP\); uint32 is 4-byte value"
+	MOVL	x+4(FP), AX // ERROR "invalid offset x\+4\(FP\); expected x\+0\(FP\)"
+	MOVL	y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+4\(FP\)"
+	TESTB	x+0(FP), AX // ERROR "invalid TESTB of x\+0\(FP\); int32 is 4-byte value"
+	TESTB	y+4(FP), BX // ERROR "invalid TESTB of y\+4\(FP\); uint32 is 4-byte value"
+	TESTW	x+0(FP), AX // ERROR "invalid TESTW of x\+0\(FP\); int32 is 4-byte value"
+	TESTW	y+4(FP), AX // ERROR "invalid TESTW of y\+4\(FP\); uint32 is 4-byte value"
+	TESTL	x+0(FP), AX
+	TESTL	y+4(FP), AX
+	TESTQ	x+0(FP), AX // ERROR "invalid TESTQ of x\+0\(FP\); int32 is 4-byte value"
+	TESTQ	y+4(FP), AX // ERROR "invalid TESTQ of y\+4\(FP\); uint32 is 4-byte value"
+	TESTL	x+4(FP), AX // ERROR "invalid offset x\+4\(FP\); expected x\+0\(FP\)"
+	TESTL	y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+4\(FP\)"
+	RET
+
+TEXT ·arg8(SB),7,$0-2 // ERROR "wrong argument size 2; expected \$\.\.\.-16"
+	MOVB	x+0(FP), AX // ERROR "invalid MOVB of x\+0\(FP\); int64 is 8-byte value"
+	MOVB	y+8(FP), BX // ERROR "invalid MOVB of y\+8\(FP\); uint64 is 8-byte value"
+	MOVW	x+0(FP), AX // ERROR "invalid MOVW of x\+0\(FP\); int64 is 8-byte value"
+	MOVW	y+8(FP), AX // ERROR "invalid MOVW of y\+8\(FP\); uint64 is 8-byte value"
+	MOVL	x+0(FP), AX // ERROR "invalid MOVL of x\+0\(FP\); int64 is 8-byte value"
+	MOVL	y+8(FP), AX // ERROR "invalid MOVL of y\+8\(FP\); uint64 is 8-byte value"
+	MOVQ	x+0(FP), AX
+	MOVQ	y+8(FP), AX
+	MOVQ	x+8(FP), AX // ERROR "invalid offset x\+8\(FP\); expected x\+0\(FP\)"
+	MOVQ	y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+8\(FP\)"
+	TESTB	x+0(FP), AX // ERROR "invalid TESTB of x\+0\(FP\); int64 is 8-byte value"
+	TESTB	y+8(FP), BX // ERROR "invalid TESTB of y\+8\(FP\); uint64 is 8-byte value"
+	TESTW	x+0(FP), AX // ERROR "invalid TESTW of x\+0\(FP\); int64 is 8-byte value"
+	TESTW	y+8(FP), AX // ERROR "invalid TESTW of y\+8\(FP\); uint64 is 8-byte value"
+	TESTL	x+0(FP), AX // ERROR "invalid TESTL of x\+0\(FP\); int64 is 8-byte value"
+	TESTL	y+8(FP), AX // ERROR "invalid TESTL of y\+8\(FP\); uint64 is 8-byte value"
+	TESTQ	x+0(FP), AX
+	TESTQ	y+8(FP), AX
+	TESTQ	x+8(FP), AX // ERROR "invalid offset x\+8\(FP\); expected x\+0\(FP\)"
+	TESTQ	y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+8\(FP\)"
+	RET
+
+TEXT ·argint(SB),0,$0-2 // ERROR "wrong argument size 2; expected \$\.\.\.-16"
+	MOVB	x+0(FP), AX // ERROR "invalid MOVB of x\+0\(FP\); int is 8-byte value"
+	MOVB	y+8(FP), BX // ERROR "invalid MOVB of y\+8\(FP\); uint is 8-byte value"
+	MOVW	x+0(FP), AX // ERROR "invalid MOVW of x\+0\(FP\); int is 8-byte value"
+	MOVW	y+8(FP), AX // ERROR "invalid MOVW of y\+8\(FP\); uint is 8-byte value"
+	MOVL	x+0(FP), AX // ERROR "invalid MOVL of x\+0\(FP\); int is 8-byte value"
+	MOVL	y+8(FP), AX // ERROR "invalid MOVL of y\+8\(FP\); uint is 8-byte value"
+	MOVQ	x+0(FP), AX
+	MOVQ	y+8(FP), AX
+	MOVQ	x+8(FP), AX // ERROR "invalid offset x\+8\(FP\); expected x\+0\(FP\)"
+	MOVQ	y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+8\(FP\)"
+	TESTB	x+0(FP), AX // ERROR "invalid TESTB of x\+0\(FP\); int is 8-byte value"
+	TESTB	y+8(FP), BX // ERROR "invalid TESTB of y\+8\(FP\); uint is 8-byte value"
+	TESTW	x+0(FP), AX // ERROR "invalid TESTW of x\+0\(FP\); int is 8-byte value"
+	TESTW	y+8(FP), AX // ERROR "invalid TESTW of y\+8\(FP\); uint is 8-byte value"
+	TESTL	x+0(FP), AX // ERROR "invalid TESTL of x\+0\(FP\); int is 8-byte value"
+	TESTL	y+8(FP), AX // ERROR "invalid TESTL of y\+8\(FP\); uint is 8-byte value"
+	TESTQ	x+0(FP), AX
+	TESTQ	y+8(FP), AX
+	TESTQ	x+8(FP), AX // ERROR "invalid offset x\+8\(FP\); expected x\+0\(FP\)"
+	TESTQ	y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+8\(FP\)"
+	RET
+
+TEXT ·argptr(SB),7,$0-2 // ERROR "wrong argument size 2; expected \$\.\.\.-40"
+	MOVB	x+0(FP), AX // ERROR "invalid MOVB of x\+0\(FP\); \*byte is 8-byte value"
+	MOVB	y+8(FP), BX // ERROR "invalid MOVB of y\+8\(FP\); \*byte is 8-byte value"
+	MOVW	x+0(FP), AX // ERROR "invalid MOVW of x\+0\(FP\); \*byte is 8-byte value"
+	MOVW	y+8(FP), AX // ERROR "invalid MOVW of y\+8\(FP\); \*byte is 8-byte value"
+	MOVL	x+0(FP), AX // ERROR "invalid MOVL of x\+0\(FP\); \*byte is 8-byte value"
+	MOVL	y+8(FP), AX // ERROR "invalid MOVL of y\+8\(FP\); \*byte is 8-byte value"
+	MOVQ	x+0(FP), AX
+	MOVQ	y+8(FP), AX
+	MOVQ	x+8(FP), AX // ERROR "invalid offset x\+8\(FP\); expected x\+0\(FP\)"
+	MOVQ	y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+8\(FP\)"
+	TESTB	x+0(FP), AX // ERROR "invalid TESTB of x\+0\(FP\); \*byte is 8-byte value"
+	TESTB	y+8(FP), BX // ERROR "invalid TESTB of y\+8\(FP\); \*byte is 8-byte value"
+	TESTW	x+0(FP), AX // ERROR "invalid TESTW of x\+0\(FP\); \*byte is 8-byte value"
+	TESTW	y+8(FP), AX // ERROR "invalid TESTW of y\+8\(FP\); \*byte is 8-byte value"
+	TESTL	x+0(FP), AX // ERROR "invalid TESTL of x\+0\(FP\); \*byte is 8-byte value"
+	TESTL	y+8(FP), AX // ERROR "invalid TESTL of y\+8\(FP\); \*byte is 8-byte value"
+	TESTQ	x+0(FP), AX
+	TESTQ	y+8(FP), AX
+	TESTQ	x+8(FP), AX // ERROR "invalid offset x\+8\(FP\); expected x\+0\(FP\)"
+	TESTQ	y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+8\(FP\)"
+	MOVL	c+16(FP), AX // ERROR "invalid MOVL of c\+16\(FP\); chan int is 8-byte value"
+	MOVL	m+24(FP), AX // ERROR "invalid MOVL of m\+24\(FP\); map\[int\]int is 8-byte value"
+	MOVL	f+32(FP), AX // ERROR "invalid MOVL of f\+32\(FP\); func\(\) is 8-byte value"
+	RET
+
+TEXT ·argstring(SB),0,$32 // ERROR "wrong argument size 0; expected \$\.\.\.-32"
+	MOVW	x+0(FP), AX // ERROR "invalid MOVW of x\+0\(FP\); string base is 8-byte value"
+	MOVL	x+0(FP), AX // ERROR "invalid MOVL of x\+0\(FP\); string base is 8-byte value"
+	MOVQ	x+0(FP), AX
+	MOVW	x_base+0(FP), AX // ERROR "invalid MOVW of x_base\+0\(FP\); string base is 8-byte value"
+	MOVL	x_base+0(FP), AX // ERROR "invalid MOVL of x_base\+0\(FP\); string base is 8-byte value"
+	MOVQ	x_base+0(FP), AX
+	MOVW	x_len+0(FP), AX // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+8\(FP\)"
+	MOVL	x_len+0(FP), AX // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+8\(FP\)"
+	MOVQ	x_len+0(FP), AX // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+8\(FP\)"
+	MOVW	x_len+8(FP), AX // ERROR "invalid MOVW of x_len\+8\(FP\); string len is 8-byte value"
+	MOVL	x_len+8(FP), AX // ERROR "invalid MOVL of x_len\+8\(FP\); string len is 8-byte value"
+	MOVQ	x_len+8(FP), AX
+	MOVQ	y+0(FP), AX // ERROR "invalid offset y\+0\(FP\); expected y\+16\(FP\)"
+	MOVQ	y_len+8(FP), AX // ERROR "invalid offset y_len\+8\(FP\); expected y_len\+24\(FP\)"
+	RET
+
+TEXT ·argslice(SB),0,$48 // ERROR "wrong argument size 0; expected \$\.\.\.-48"
+	MOVW	x+0(FP), AX // ERROR "invalid MOVW of x\+0\(FP\); slice base is 8-byte value"
+	MOVL	x+0(FP), AX // ERROR "invalid MOVL of x\+0\(FP\); slice base is 8-byte value"
+	MOVQ	x+0(FP), AX
+	MOVW	x_base+0(FP), AX // ERROR "invalid MOVW of x_base\+0\(FP\); slice base is 8-byte value"
+	MOVL	x_base+0(FP), AX // ERROR "invalid MOVL of x_base\+0\(FP\); slice base is 8-byte value"
+	MOVQ	x_base+0(FP), AX
+	MOVW	x_len+0(FP), AX // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+8\(FP\)"
+	MOVL	x_len+0(FP), AX // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+8\(FP\)"
+	MOVQ	x_len+0(FP), AX // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+8\(FP\)"
+	MOVW	x_len+8(FP), AX // ERROR "invalid MOVW of x_len\+8\(FP\); slice len is 8-byte value"
+	MOVL	x_len+8(FP), AX // ERROR "invalid MOVL of x_len\+8\(FP\); slice len is 8-byte value"
+	MOVQ	x_len+8(FP), AX
+	MOVW	x_cap+0(FP), AX // ERROR "invalid offset x_cap\+0\(FP\); expected x_cap\+16\(FP\)"
+	MOVL	x_cap+0(FP), AX // ERROR "invalid offset x_cap\+0\(FP\); expected x_cap\+16\(FP\)"
+	MOVQ	x_cap+0(FP), AX // ERROR "invalid offset x_cap\+0\(FP\); expected x_cap\+16\(FP\)"
+	MOVW	x_cap+16(FP), AX // ERROR "invalid MOVW of x_cap\+16\(FP\); slice cap is 8-byte value"
+	MOVL	x_cap+16(FP), AX // ERROR "invalid MOVL of x_cap\+16\(FP\); slice cap is 8-byte value"
+	MOVQ	x_cap+16(FP), AX
+	MOVQ	y+0(FP), AX // ERROR "invalid offset y\+0\(FP\); expected y\+24\(FP\)"
+	MOVQ	y_len+8(FP), AX // ERROR "invalid offset y_len\+8\(FP\); expected y_len\+32\(FP\)"
+	MOVQ	y_cap+16(FP), AX // ERROR "invalid offset y_cap\+16\(FP\); expected y_cap\+40\(FP\)"
+	RET
+
+TEXT ·argiface(SB),0,$0-32
+	MOVW	x+0(FP), AX // ERROR "invalid MOVW of x\+0\(FP\); interface type is 8-byte value"
+	MOVL	x+0(FP), AX // ERROR "invalid MOVL of x\+0\(FP\); interface type is 8-byte value"
+	MOVQ	x+0(FP), AX
+	MOVW	x_type+0(FP), AX // ERROR "invalid MOVW of x_type\+0\(FP\); interface type is 8-byte value"
+	MOVL	x_type+0(FP), AX // ERROR "invalid MOVL of x_type\+0\(FP\); interface type is 8-byte value"
+	MOVQ	x_type+0(FP), AX
+	MOVQ	x_itable+0(FP), AX // ERROR "unknown variable x_itable; offset 0 is x_type\+0\(FP\)"
+	MOVQ	x_itable+1(FP), AX // ERROR "unknown variable x_itable; offset 1 is x_type\+0\(FP\)"
+	MOVW	x_data+0(FP), AX // ERROR "invalid offset x_data\+0\(FP\); expected x_data\+8\(FP\)"
+	MOVL	x_data+0(FP), AX // ERROR "invalid offset x_data\+0\(FP\); expected x_data\+8\(FP\)"
+	MOVQ	x_data+0(FP), AX // ERROR "invalid offset x_data\+0\(FP\); expected x_data\+8\(FP\)"
+	MOVW	x_data+8(FP), AX // ERROR "invalid MOVW of x_data\+8\(FP\); interface data is 8-byte value"
+	MOVL	x_data+8(FP), AX // ERROR "invalid MOVL of x_data\+8\(FP\); interface data is 8-byte value"
+	MOVQ	x_data+8(FP), AX
+	MOVW	y+16(FP), AX // ERROR "invalid MOVW of y\+16\(FP\); interface itable is 8-byte value"
+	MOVL	y+16(FP), AX // ERROR "invalid MOVL of y\+16\(FP\); interface itable is 8-byte value"
+	MOVQ	y+16(FP), AX
+	MOVW	y_itable+16(FP), AX // ERROR "invalid MOVW of y_itable\+16\(FP\); interface itable is 8-byte value"
+	MOVL	y_itable+16(FP), AX // ERROR "invalid MOVL of y_itable\+16\(FP\); interface itable is 8-byte value"
+	MOVQ	y_itable+16(FP), AX
+	MOVQ	y_type+16(FP), AX // ERROR "unknown variable y_type; offset 16 is y_itable\+16\(FP\)"
+	MOVW	y_data+16(FP), AX // ERROR "invalid offset y_data\+16\(FP\); expected y_data\+24\(FP\)"
+	MOVL	y_data+16(FP), AX // ERROR "invalid offset y_data\+16\(FP\); expected y_data\+24\(FP\)"
+	MOVQ	y_data+16(FP), AX // ERROR "invalid offset y_data\+16\(FP\); expected y_data\+24\(FP\)"
+	MOVW	y_data+24(FP), AX // ERROR "invalid MOVW of y_data\+24\(FP\); interface data is 8-byte value"
+	MOVL	y_data+24(FP), AX // ERROR "invalid MOVL of y_data\+24\(FP\); interface data is 8-byte value"
+	MOVQ	y_data+24(FP), AX
+	RET
+
+TEXT ·returnint(SB),0,$0-8
+	MOVB	AX, ret+0(FP) // ERROR "invalid MOVB of ret\+0\(FP\); int is 8-byte value"
+	MOVW	AX, ret+0(FP) // ERROR "invalid MOVW of ret\+0\(FP\); int is 8-byte value"
+	MOVL	AX, ret+0(FP) // ERROR "invalid MOVL of ret\+0\(FP\); int is 8-byte value"
+	MOVQ	AX, ret+0(FP)
+	MOVQ	AX, ret+1(FP) // ERROR "invalid offset ret\+1\(FP\); expected ret\+0\(FP\)"
+	MOVQ	AX, r+0(FP) // ERROR "unknown variable r; offset 0 is ret\+0\(FP\)"
+	RET
+
+TEXT ·returnbyte(SB),0,$0-9
+	MOVQ	x+0(FP), AX
+	MOVB	AX, ret+8(FP)
+	MOVW	AX, ret+8(FP) // ERROR "invalid MOVW of ret\+8\(FP\); byte is 1-byte value"
+	MOVL	AX, ret+8(FP) // ERROR "invalid MOVL of ret\+8\(FP\); byte is 1-byte value"
+	MOVQ	AX, ret+8(FP) // ERROR "invalid MOVQ of ret\+8\(FP\); byte is 1-byte value"
+	MOVB	AX, ret+7(FP) // ERROR "invalid offset ret\+7\(FP\); expected ret\+8\(FP\)"
+	RET
+
+TEXT ·returnnamed(SB),0,$0-41
+	MOVB	x+0(FP), AX
+	MOVQ	AX, r1+8(FP)
+	MOVW	AX, r2+16(FP)
+	MOVQ	AX, r3+24(FP)
+	MOVQ	AX, r3_base+24(FP)
+	MOVQ	AX, r3_len+32(FP)
+	MOVB	AX, r4+40(FP)
+	MOVL	AX, r1+8(FP) // ERROR "invalid MOVL of r1\+8\(FP\); int is 8-byte value"
+	RET
+
+TEXT ·returnintmissing(SB),0,$0-8
+	RET // ERROR "RET without writing to 8-byte ret\+0\(FP\)"
diff --git a/cmd/vet/testdata/asm2.s b/cmd/vet/testdata/asm2.s
new file mode 100644
index 0000000..c33c02a
--- /dev/null
+++ b/cmd/vet/testdata/asm2.s
@@ -0,0 +1,257 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build 386
+// +build vet_test
+
+TEXT ·arg1(SB),0,$0-2
+	MOVB	x+0(FP), AX
+	MOVB	y+1(FP), BX
+	MOVW	x+0(FP), AX // ERROR "\[386\] arg1: invalid MOVW of x\+0\(FP\); int8 is 1-byte value"
+	MOVW	y+1(FP), AX // ERROR "invalid MOVW of y\+1\(FP\); uint8 is 1-byte value"
+	MOVL	x+0(FP), AX // ERROR "invalid MOVL of x\+0\(FP\); int8 is 1-byte value"
+	MOVL	y+1(FP), AX // ERROR "invalid MOVL of y\+1\(FP\); uint8 is 1-byte value"
+	MOVQ	x+0(FP), AX // ERROR "invalid MOVQ of x\+0\(FP\); int8 is 1-byte value"
+	MOVQ	y+1(FP), AX // ERROR "invalid MOVQ of y\+1\(FP\); uint8 is 1-byte value"
+	MOVB	x+1(FP), AX // ERROR "invalid offset x\+1\(FP\); expected x\+0\(FP\)"
+	MOVB	y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+1\(FP\)"
+	TESTB	x+0(FP), AX
+	TESTB	y+1(FP), BX
+	TESTW	x+0(FP), AX // ERROR "invalid TESTW of x\+0\(FP\); int8 is 1-byte value"
+	TESTW	y+1(FP), AX // ERROR "invalid TESTW of y\+1\(FP\); uint8 is 1-byte value"
+	TESTL	x+0(FP), AX // ERROR "invalid TESTL of x\+0\(FP\); int8 is 1-byte value"
+	TESTL	y+1(FP), AX // ERROR "invalid TESTL of y\+1\(FP\); uint8 is 1-byte value"
+	TESTQ	x+0(FP), AX // ERROR "invalid TESTQ of x\+0\(FP\); int8 is 1-byte value"
+	TESTQ	y+1(FP), AX // ERROR "invalid TESTQ of y\+1\(FP\); uint8 is 1-byte value"
+	TESTB	x+1(FP), AX // ERROR "invalid offset x\+1\(FP\); expected x\+0\(FP\)"
+	TESTB	y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+1\(FP\)"
+	MOVB	4(SP), AX // ERROR "4\(SP\) should be x\+0\(FP\)"
+	MOVB	5(SP), AX // ERROR "5\(SP\) should be y\+1\(FP\)"
+	MOVB	6(SP), AX // ERROR "use of 6\(SP\) points beyond argument frame"
+	RET
+
+TEXT ·arg2(SB),0,$0-4
+	MOVB	x+0(FP), AX // ERROR "arg2: invalid MOVB of x\+0\(FP\); int16 is 2-byte value"
+	MOVB	y+2(FP), AX // ERROR "invalid MOVB of y\+2\(FP\); uint16 is 2-byte value"
+	MOVW	x+0(FP), AX
+	MOVW	y+2(FP), BX
+	MOVL	x+0(FP), AX // ERROR "invalid MOVL of x\+0\(FP\); int16 is 2-byte value"
+	MOVL	y+2(FP), AX // ERROR "invalid MOVL of y\+2\(FP\); uint16 is 2-byte value"
+	MOVQ	x+0(FP), AX // ERROR "invalid MOVQ of x\+0\(FP\); int16 is 2-byte value"
+	MOVQ	y+2(FP), AX // ERROR "invalid MOVQ of y\+2\(FP\); uint16 is 2-byte value"
+	MOVW	x+2(FP), AX // ERROR "invalid offset x\+2\(FP\); expected x\+0\(FP\)"
+	MOVW	y+0(FP), AX // ERROR "invalid offset y\+0\(FP\); expected y\+2\(FP\)"
+	TESTB	x+0(FP), AX // ERROR "invalid TESTB of x\+0\(FP\); int16 is 2-byte value"
+	TESTB	y+2(FP), AX // ERROR "invalid TESTB of y\+2\(FP\); uint16 is 2-byte value"
+	TESTW	x+0(FP), AX
+	TESTW	y+2(FP), BX
+	TESTL	x+0(FP), AX // ERROR "invalid TESTL of x\+0\(FP\); int16 is 2-byte value"
+	TESTL	y+2(FP), AX // ERROR "invalid TESTL of y\+2\(FP\); uint16 is 2-byte value"
+	TESTQ	x+0(FP), AX // ERROR "invalid TESTQ of x\+0\(FP\); int16 is 2-byte value"
+	TESTQ	y+2(FP), AX // ERROR "invalid TESTQ of y\+2\(FP\); uint16 is 2-byte value"
+	TESTW	x+2(FP), AX // ERROR "invalid offset x\+2\(FP\); expected x\+0\(FP\)"
+	TESTW	y+0(FP), AX // ERROR "invalid offset y\+0\(FP\); expected y\+2\(FP\)"
+	RET
+
+TEXT ·arg4(SB),0,$0-2 // ERROR "arg4: wrong argument size 2; expected \$\.\.\.-8"
+	MOVB	x+0(FP), AX // ERROR "invalid MOVB of x\+0\(FP\); int32 is 4-byte value"
+	MOVB	y+4(FP), BX // ERROR "invalid MOVB of y\+4\(FP\); uint32 is 4-byte value"
+	MOVW	x+0(FP), AX // ERROR "invalid MOVW of x\+0\(FP\); int32 is 4-byte value"
+	MOVW	y+4(FP), AX // ERROR "invalid MOVW of y\+4\(FP\); uint32 is 4-byte value"
+	MOVL	x+0(FP), AX
+	MOVL	y+4(FP), AX
+	MOVQ	x+0(FP), AX // ERROR "invalid MOVQ of x\+0\(FP\); int32 is 4-byte value"
+	MOVQ	y+4(FP), AX // ERROR "invalid MOVQ of y\+4\(FP\); uint32 is 4-byte value"
+	MOVL	x+4(FP), AX // ERROR "invalid offset x\+4\(FP\); expected x\+0\(FP\)"
+	MOVL	y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+4\(FP\)"
+	TESTB	x+0(FP), AX // ERROR "invalid TESTB of x\+0\(FP\); int32 is 4-byte value"
+	TESTB	y+4(FP), BX // ERROR "invalid TESTB of y\+4\(FP\); uint32 is 4-byte value"
+	TESTW	x+0(FP), AX // ERROR "invalid TESTW of x\+0\(FP\); int32 is 4-byte value"
+	TESTW	y+4(FP), AX // ERROR "invalid TESTW of y\+4\(FP\); uint32 is 4-byte value"
+	TESTL	x+0(FP), AX
+	TESTL	y+4(FP), AX
+	TESTQ	x+0(FP), AX // ERROR "invalid TESTQ of x\+0\(FP\); int32 is 4-byte value"
+	TESTQ	y+4(FP), AX // ERROR "invalid TESTQ of y\+4\(FP\); uint32 is 4-byte value"
+	TESTL	x+4(FP), AX // ERROR "invalid offset x\+4\(FP\); expected x\+0\(FP\)"
+	TESTL	y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+4\(FP\)"
+	RET
+
+TEXT ·arg8(SB),7,$0-2 // ERROR "wrong argument size 2; expected \$\.\.\.-16"
+	MOVB	x+0(FP), AX // ERROR "invalid MOVB of x\+0\(FP\); int64 is 8-byte value"
+	MOVB	y+8(FP), BX // ERROR "invalid MOVB of y\+8\(FP\); uint64 is 8-byte value"
+	MOVW	x+0(FP), AX // ERROR "invalid MOVW of x\+0\(FP\); int64 is 8-byte value"
+	MOVW	y+8(FP), AX // ERROR "invalid MOVW of y\+8\(FP\); uint64 is 8-byte value"
+	MOVL	x+0(FP), AX // ERROR "invalid MOVL of x\+0\(FP\); int64 is 8-byte value containing x_lo\+0\(FP\) and x_hi\+4\(FP\)"
+	MOVL	x_lo+0(FP), AX
+	MOVL	x_hi+4(FP), AX
+	MOVL	y+8(FP), AX // ERROR "invalid MOVL of y\+8\(FP\); uint64 is 8-byte value containing y_lo\+8\(FP\) and y_hi\+12\(FP\)"
+	MOVL	y_lo+8(FP), AX
+	MOVL	y_hi+12(FP), AX
+	MOVQ	x+0(FP), AX
+	MOVQ	y+8(FP), AX
+	MOVQ	x+8(FP), AX // ERROR "invalid offset x\+8\(FP\); expected x\+0\(FP\)"
+	MOVQ	y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+8\(FP\)"
+	TESTB	x+0(FP), AX // ERROR "invalid TESTB of x\+0\(FP\); int64 is 8-byte value"
+	TESTB	y+8(FP), BX // ERROR "invalid TESTB of y\+8\(FP\); uint64 is 8-byte value"
+	TESTW	x+0(FP), AX // ERROR "invalid TESTW of x\+0\(FP\); int64 is 8-byte value"
+	TESTW	y+8(FP), AX // ERROR "invalid TESTW of y\+8\(FP\); uint64 is 8-byte value"
+	TESTL	x+0(FP), AX // ERROR "invalid TESTL of x\+0\(FP\); int64 is 8-byte value containing x_lo\+0\(FP\) and x_hi\+4\(FP\)"
+	TESTL	y+8(FP), AX // ERROR "invalid TESTL of y\+8\(FP\); uint64 is 8-byte value containing y_lo\+8\(FP\) and y_hi\+12\(FP\)"
+	TESTQ	x+0(FP), AX
+	TESTQ	y+8(FP), AX
+	TESTQ	x+8(FP), AX // ERROR "invalid offset x\+8\(FP\); expected x\+0\(FP\)"
+	TESTQ	y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+8\(FP\)"
+	RET
+
+TEXT ·argint(SB),0,$0-2 // ERROR "wrong argument size 2; expected \$\.\.\.-8"
+	MOVB	x+0(FP), AX // ERROR "invalid MOVB of x\+0\(FP\); int is 4-byte value"
+	MOVB	y+4(FP), BX // ERROR "invalid MOVB of y\+4\(FP\); uint is 4-byte value"
+	MOVW	x+0(FP), AX // ERROR "invalid MOVW of x\+0\(FP\); int is 4-byte value"
+	MOVW	y+4(FP), AX // ERROR "invalid MOVW of y\+4\(FP\); uint is 4-byte value"
+	MOVL	x+0(FP), AX
+	MOVL	y+4(FP), AX
+	MOVQ	x+0(FP), AX // ERROR "invalid MOVQ of x\+0\(FP\); int is 4-byte value"
+	MOVQ	y+4(FP), AX // ERROR "invalid MOVQ of y\+4\(FP\); uint is 4-byte value"
+	MOVQ	x+4(FP), AX // ERROR "invalid offset x\+4\(FP\); expected x\+0\(FP\)"
+	MOVQ	y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+4\(FP\)"
+	TESTB	x+0(FP), AX // ERROR "invalid TESTB of x\+0\(FP\); int is 4-byte value"
+	TESTB	y+4(FP), BX // ERROR "invalid TESTB of y\+4\(FP\); uint is 4-byte value"
+	TESTW	x+0(FP), AX // ERROR "invalid TESTW of x\+0\(FP\); int is 4-byte value"
+	TESTW	y+4(FP), AX // ERROR "invalid TESTW of y\+4\(FP\); uint is 4-byte value"
+	TESTL	x+0(FP), AX
+	TESTL	y+4(FP), AX
+	TESTQ	x+0(FP), AX // ERROR "invalid TESTQ of x\+0\(FP\); int is 4-byte value"
+	TESTQ	y+4(FP), AX // ERROR "invalid TESTQ of y\+4\(FP\); uint is 4-byte value"
+	TESTQ	x+4(FP), AX // ERROR "invalid offset x\+4\(FP\); expected x\+0\(FP\)"
+	TESTQ	y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+4\(FP\)"
+	RET
+
+TEXT ·argptr(SB),7,$0-2 // ERROR "wrong argument size 2; expected \$\.\.\.-20"
+	MOVB	x+0(FP), AX // ERROR "invalid MOVB of x\+0\(FP\); \*byte is 4-byte value"
+	MOVB	y+4(FP), BX // ERROR "invalid MOVB of y\+4\(FP\); \*byte is 4-byte value"
+	MOVW	x+0(FP), AX // ERROR "invalid MOVW of x\+0\(FP\); \*byte is 4-byte value"
+	MOVW	y+4(FP), AX // ERROR "invalid MOVW of y\+4\(FP\); \*byte is 4-byte value"
+	MOVL	x+0(FP), AX
+	MOVL	y+4(FP), AX
+	MOVQ	x+0(FP), AX // ERROR "invalid MOVQ of x\+0\(FP\); \*byte is 4-byte value"
+	MOVQ	y+4(FP), AX // ERROR "invalid MOVQ of y\+4\(FP\); \*byte is 4-byte value"
+	MOVQ	x+4(FP), AX // ERROR "invalid offset x\+4\(FP\); expected x\+0\(FP\)"
+	MOVQ	y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+4\(FP\)"
+	TESTB	x+0(FP), AX // ERROR "invalid TESTB of x\+0\(FP\); \*byte is 4-byte value"
+	TESTB	y+4(FP), BX // ERROR "invalid TESTB of y\+4\(FP\); \*byte is 4-byte value"
+	TESTW	x+0(FP), AX // ERROR "invalid TESTW of x\+0\(FP\); \*byte is 4-byte value"
+	TESTW	y+4(FP), AX // ERROR "invalid TESTW of y\+4\(FP\); \*byte is 4-byte value"
+	TESTL	x+0(FP), AX
+	TESTL	y+4(FP), AX
+	TESTQ	x+0(FP), AX // ERROR "invalid TESTQ of x\+0\(FP\); \*byte is 4-byte value"
+	TESTQ	y+4(FP), AX // ERROR "invalid TESTQ of y\+4\(FP\); \*byte is 4-byte value"
+	TESTQ	x+4(FP), AX // ERROR "invalid offset x\+4\(FP\); expected x\+0\(FP\)"
+	TESTQ	y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+4\(FP\)"
+	MOVW	c+8(FP), AX // ERROR "invalid MOVW of c\+8\(FP\); chan int is 4-byte value"
+	MOVW	m+12(FP), AX // ERROR "invalid MOVW of m\+12\(FP\); map\[int\]int is 4-byte value"
+	MOVW	f+16(FP), AX // ERROR "invalid MOVW of f\+16\(FP\); func\(\) is 4-byte value"
+	RET
+
+TEXT ·argstring(SB),0,$16 // ERROR "wrong argument size 0; expected \$\.\.\.-16"
+	MOVW	x+0(FP), AX // ERROR "invalid MOVW of x\+0\(FP\); string base is 4-byte value"
+	MOVL	x+0(FP), AX
+	MOVQ	x+0(FP), AX // ERROR "invalid MOVQ of x\+0\(FP\); string base is 4-byte value"
+	MOVW	x_base+0(FP), AX // ERROR "invalid MOVW of x_base\+0\(FP\); string base is 4-byte value"
+	MOVL	x_base+0(FP), AX
+	MOVQ	x_base+0(FP), AX // ERROR "invalid MOVQ of x_base\+0\(FP\); string base is 4-byte value"
+	MOVW	x_len+0(FP), AX // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+4\(FP\)"
+	MOVL	x_len+0(FP), AX // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+4\(FP\)"
+	MOVQ	x_len+0(FP), AX // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+4\(FP\)"
+	MOVW	x_len+4(FP), AX // ERROR "invalid MOVW of x_len\+4\(FP\); string len is 4-byte value"
+	MOVL	x_len+4(FP), AX
+	MOVQ	x_len+4(FP), AX // ERROR "invalid MOVQ of x_len\+4\(FP\); string len is 4-byte value"
+	MOVQ	y+0(FP), AX // ERROR "invalid offset y\+0\(FP\); expected y\+8\(FP\)"
+	MOVQ	y_len+4(FP), AX // ERROR "invalid offset y_len\+4\(FP\); expected y_len\+12\(FP\)"
+	RET
+
+TEXT ·argslice(SB),0,$24 // ERROR "wrong argument size 0; expected \$\.\.\.-24"
+	MOVW	x+0(FP), AX // ERROR "invalid MOVW of x\+0\(FP\); slice base is 4-byte value"
+	MOVL	x+0(FP), AX
+	MOVQ	x+0(FP), AX // ERROR "invalid MOVQ of x\+0\(FP\); slice base is 4-byte value"
+	MOVW	x_base+0(FP), AX // ERROR "invalid MOVW of x_base\+0\(FP\); slice base is 4-byte value"
+	MOVL	x_base+0(FP), AX
+	MOVQ	x_base+0(FP), AX // ERROR "invalid MOVQ of x_base\+0\(FP\); slice base is 4-byte value"
+	MOVW	x_len+0(FP), AX // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+4\(FP\)"
+	MOVL	x_len+0(FP), AX // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+4\(FP\)"
+	MOVQ	x_len+0(FP), AX // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+4\(FP\)"
+	MOVW	x_len+4(FP), AX // ERROR "invalid MOVW of x_len\+4\(FP\); slice len is 4-byte value"
+	MOVL	x_len+4(FP), AX
+	MOVQ	x_len+4(FP), AX // ERROR "invalid MOVQ of x_len\+4\(FP\); slice len is 4-byte value"
+	MOVW	x_cap+0(FP), AX // ERROR "invalid offset x_cap\+0\(FP\); expected x_cap\+8\(FP\)"
+	MOVL	x_cap+0(FP), AX // ERROR "invalid offset x_cap\+0\(FP\); expected x_cap\+8\(FP\)"
+	MOVQ	x_cap+0(FP), AX // ERROR "invalid offset x_cap\+0\(FP\); expected x_cap\+8\(FP\)"
+	MOVW	x_cap+8(FP), AX // ERROR "invalid MOVW of x_cap\+8\(FP\); slice cap is 4-byte value"
+	MOVL	x_cap+8(FP), AX
+	MOVQ	x_cap+8(FP), AX // ERROR "invalid MOVQ of x_cap\+8\(FP\); slice cap is 4-byte value"
+	MOVQ	y+0(FP), AX // ERROR "invalid offset y\+0\(FP\); expected y\+12\(FP\)"
+	MOVQ	y_len+4(FP), AX // ERROR "invalid offset y_len\+4\(FP\); expected y_len\+16\(FP\)"
+	MOVQ	y_cap+8(FP), AX // ERROR "invalid offset y_cap\+8\(FP\); expected y_cap\+20\(FP\)"
+	RET
+
+TEXT ·argiface(SB),0,$0-16
+	MOVW	x+0(FP), AX // ERROR "invalid MOVW of x\+0\(FP\); interface type is 4-byte value"
+	MOVL	x+0(FP), AX
+	MOVQ	x+0(FP), AX // ERROR "invalid MOVQ of x\+0\(FP\); interface type is 4-byte value"
+	MOVW	x_type+0(FP), AX // ERROR "invalid MOVW of x_type\+0\(FP\); interface type is 4-byte value"
+	MOVL	x_type+0(FP), AX
+	MOVQ	x_type+0(FP), AX // ERROR "invalid MOVQ of x_type\+0\(FP\); interface type is 4-byte value"
+	MOVQ	x_itable+0(FP), AX // ERROR "unknown variable x_itable; offset 0 is x_type\+0\(FP\)"
+	MOVQ	x_itable+1(FP), AX // ERROR "unknown variable x_itable; offset 1 is x_type\+0\(FP\)"
+	MOVW	x_data+0(FP), AX // ERROR "invalid offset x_data\+0\(FP\); expected x_data\+4\(FP\)"
+	MOVL	x_data+0(FP), AX // ERROR "invalid offset x_data\+0\(FP\); expected x_data\+4\(FP\)"
+	MOVQ	x_data+0(FP), AX // ERROR "invalid offset x_data\+0\(FP\); expected x_data\+4\(FP\)"
+	MOVW	x_data+4(FP), AX // ERROR "invalid MOVW of x_data\+4\(FP\); interface data is 4-byte value"
+	MOVL	x_data+4(FP), AX
+	MOVQ	x_data+4(FP), AX // ERROR "invalid MOVQ of x_data\+4\(FP\); interface data is 4-byte value"
+	MOVW	y+8(FP), AX // ERROR "invalid MOVW of y\+8\(FP\); interface itable is 4-byte value"
+	MOVL	y+8(FP), AX
+	MOVQ	y+8(FP), AX // ERROR "invalid MOVQ of y\+8\(FP\); interface itable is 4-byte value"
+	MOVW	y_itable+8(FP), AX // ERROR "invalid MOVW of y_itable\+8\(FP\); interface itable is 4-byte value"
+	MOVL	y_itable+8(FP), AX
+	MOVQ	y_itable+8(FP), AX // ERROR "invalid MOVQ of y_itable\+8\(FP\); interface itable is 4-byte value"
+	MOVQ	y_type+8(FP), AX // ERROR "unknown variable y_type; offset 8 is y_itable\+8\(FP\)"
+	MOVW	y_data+8(FP), AX // ERROR "invalid offset y_data\+8\(FP\); expected y_data\+12\(FP\)"
+	MOVL	y_data+8(FP), AX // ERROR "invalid offset y_data\+8\(FP\); expected y_data\+12\(FP\)"
+	MOVQ	y_data+8(FP), AX // ERROR "invalid offset y_data\+8\(FP\); expected y_data\+12\(FP\)"
+	MOVW	y_data+12(FP), AX // ERROR "invalid MOVW of y_data\+12\(FP\); interface data is 4-byte value"
+	MOVL	y_data+12(FP), AX
+	MOVQ	y_data+12(FP), AX // ERROR "invalid MOVQ of y_data\+12\(FP\); interface data is 4-byte value"
+	RET
+
+TEXT ·returnint(SB),0,$0-4
+	MOVB	AX, ret+0(FP) // ERROR "invalid MOVB of ret\+0\(FP\); int is 4-byte value"
+	MOVW	AX, ret+0(FP) // ERROR "invalid MOVW of ret\+0\(FP\); int is 4-byte value"
+	MOVL	AX, ret+0(FP)
+	MOVQ	AX, ret+0(FP) // ERROR "invalid MOVQ of ret\+0\(FP\); int is 4-byte value"
+	MOVQ	AX, ret+1(FP) // ERROR "invalid offset ret\+1\(FP\); expected ret\+0\(FP\)"
+	MOVQ	AX, r+0(FP) // ERROR "unknown variable r; offset 0 is ret\+0\(FP\)"
+	RET
+
+TEXT ·returnbyte(SB),0,$0-5
+	MOVL	x+0(FP), AX
+	MOVB	AX, ret+4(FP)
+	MOVW	AX, ret+4(FP) // ERROR "invalid MOVW of ret\+4\(FP\); byte is 1-byte value"
+	MOVL	AX, ret+4(FP) // ERROR "invalid MOVL of ret\+4\(FP\); byte is 1-byte value"
+	MOVQ	AX, ret+4(FP) // ERROR "invalid MOVQ of ret\+4\(FP\); byte is 1-byte value"
+	MOVB	AX, ret+3(FP) // ERROR "invalid offset ret\+3\(FP\); expected ret\+4\(FP\)"
+	RET
+
+TEXT ·returnnamed(SB),0,$0-21
+	MOVB	x+0(FP), AX
+	MOVL	AX, r1+4(FP)
+	MOVW	AX, r2+8(FP)
+	MOVL	AX, r3+12(FP)
+	MOVL	AX, r3_base+12(FP)
+	MOVL	AX, r3_len+16(FP)
+	MOVB	AX, r4+20(FP)
+	MOVQ	AX, r1+4(FP) // ERROR "invalid MOVQ of r1\+4\(FP\); int is 4-byte value"
+	RET
+
+TEXT ·returnintmissing(SB),0,$0-4
+	RET // ERROR "RET without writing to 4-byte ret\+0\(FP\)"
diff --git a/cmd/vet/testdata/asm3.s b/cmd/vet/testdata/asm3.s
new file mode 100644
index 0000000..3d69356
--- /dev/null
+++ b/cmd/vet/testdata/asm3.s
@@ -0,0 +1,178 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build arm
+// +build vet_test
+
+TEXT ·arg1(SB),0,$0-2
+	MOVB	x+0(FP), AX
+	MOVB	y+1(FP), BX
+	MOVH	x+0(FP), AX // ERROR "\[arm\] arg1: invalid MOVH of x\+0\(FP\); int8 is 1-byte value"
+	MOVH	y+1(FP), AX // ERROR "invalid MOVH of y\+1\(FP\); uint8 is 1-byte value"
+	MOVW	x+0(FP), AX // ERROR "invalid MOVW of x\+0\(FP\); int8 is 1-byte value"
+	MOVW	y+1(FP), AX // ERROR "invalid MOVW of y\+1\(FP\); uint8 is 1-byte value"
+	MOVB	x+1(FP), AX // ERROR "invalid offset x\+1\(FP\); expected x\+0\(FP\)"
+	MOVB	y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+1\(FP\)"
+	MOVB	8(R13), AX // ERROR "8\(R13\) should be x\+0\(FP\)"
+	MOVB	9(R13), AX // ERROR "9\(R13\) should be y\+1\(FP\)"
+	MOVB	10(R13), AX // ERROR "use of 10\(R13\) points beyond argument frame"
+	RET
+
+TEXT ·arg2(SB),0,$0-4
+	MOVB	x+0(FP), AX // ERROR "arg2: invalid MOVB of x\+0\(FP\); int16 is 2-byte value"
+	MOVB	y+2(FP), AX // ERROR "invalid MOVB of y\+2\(FP\); uint16 is 2-byte value"
+	MOVH	x+0(FP), AX
+	MOVH	y+2(FP), BX
+	MOVW	x+0(FP), AX // ERROR "invalid MOVW of x\+0\(FP\); int16 is 2-byte value"
+	MOVW	y+2(FP), AX // ERROR "invalid MOVW of y\+2\(FP\); uint16 is 2-byte value"
+	MOVH	x+2(FP), AX // ERROR "invalid offset x\+2\(FP\); expected x\+0\(FP\)"
+	MOVH	y+0(FP), AX // ERROR "invalid offset y\+0\(FP\); expected y\+2\(FP\)"
+	RET
+
+TEXT ·arg4(SB),0,$0-2 // ERROR "arg4: wrong argument size 2; expected \$\.\.\.-8"
+	MOVB	x+0(FP), AX // ERROR "invalid MOVB of x\+0\(FP\); int32 is 4-byte value"
+	MOVB	y+4(FP), BX // ERROR "invalid MOVB of y\+4\(FP\); uint32 is 4-byte value"
+	MOVH	x+0(FP), AX // ERROR "invalid MOVH of x\+0\(FP\); int32 is 4-byte value"
+	MOVH	y+4(FP), AX // ERROR "invalid MOVH of y\+4\(FP\); uint32 is 4-byte value"
+	MOVW	x+0(FP), AX
+	MOVW	y+4(FP), AX
+	MOVW	x+4(FP), AX // ERROR "invalid offset x\+4\(FP\); expected x\+0\(FP\)"
+	MOVW	y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+4\(FP\)"
+	RET
+
+TEXT ·arg8(SB),7,$0-2 // ERROR "wrong argument size 2; expected \$\.\.\.-16"
+	MOVB	x+0(FP), AX // ERROR "invalid MOVB of x\+0\(FP\); int64 is 8-byte value"
+	MOVB	y+8(FP), BX // ERROR "invalid MOVB of y\+8\(FP\); uint64 is 8-byte value"
+	MOVH	x+0(FP), AX // ERROR "invalid MOVH of x\+0\(FP\); int64 is 8-byte value"
+	MOVH	y+8(FP), AX // ERROR "invalid MOVH of y\+8\(FP\); uint64 is 8-byte value"
+	MOVW	x+0(FP), AX // ERROR "invalid MOVW of x\+0\(FP\); int64 is 8-byte value containing x_lo\+0\(FP\) and x_hi\+4\(FP\)"
+	MOVW	x_lo+0(FP), AX
+	MOVW	x_hi+4(FP), AX
+	MOVW	y+8(FP), AX // ERROR "invalid MOVW of y\+8\(FP\); uint64 is 8-byte value containing y_lo\+8\(FP\) and y_hi\+12\(FP\)"
+	MOVW	y_lo+8(FP), AX
+	MOVW	y_hi+12(FP), AX
+	MOVQ	x+0(FP), AX
+	MOVQ	y+8(FP), AX
+	MOVQ	x+8(FP), AX // ERROR "invalid offset x\+8\(FP\); expected x\+0\(FP\)"
+	MOVQ	y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+8\(FP\)"
+	RET
+
+TEXT ·argint(SB),0,$0-2 // ERROR "wrong argument size 2; expected \$\.\.\.-8"
+	MOVB	x+0(FP), AX // ERROR "invalid MOVB of x\+0\(FP\); int is 4-byte value"
+	MOVB	y+4(FP), BX // ERROR "invalid MOVB of y\+4\(FP\); uint is 4-byte value"
+	MOVH	x+0(FP), AX // ERROR "invalid MOVH of x\+0\(FP\); int is 4-byte value"
+	MOVH	y+4(FP), AX // ERROR "invalid MOVH of y\+4\(FP\); uint is 4-byte value"
+	MOVW	x+0(FP), AX
+	MOVW	y+4(FP), AX
+	MOVQ	x+4(FP), AX // ERROR "invalid offset x\+4\(FP\); expected x\+0\(FP\)"
+	MOVQ	y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+4\(FP\)"
+	RET
+
+TEXT ·argptr(SB),7,$0-2 // ERROR "wrong argument size 2; expected \$\.\.\.-20"
+	MOVB	x+0(FP), AX // ERROR "invalid MOVB of x\+0\(FP\); \*byte is 4-byte value"
+	MOVB	y+4(FP), BX // ERROR "invalid MOVB of y\+4\(FP\); \*byte is 4-byte value"
+	MOVH	x+0(FP), AX // ERROR "invalid MOVH of x\+0\(FP\); \*byte is 4-byte value"
+	MOVH	y+4(FP), AX // ERROR "invalid MOVH of y\+4\(FP\); \*byte is 4-byte value"
+	MOVW	x+0(FP), AX
+	MOVW	y+4(FP), AX
+	MOVQ	x+4(FP), AX // ERROR "invalid offset x\+4\(FP\); expected x\+0\(FP\)"
+	MOVQ	y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+4\(FP\)"
+	MOVH	c+8(FP), AX // ERROR "invalid MOVH of c\+8\(FP\); chan int is 4-byte value"
+	MOVH	m+12(FP), AX // ERROR "invalid MOVH of m\+12\(FP\); map\[int\]int is 4-byte value"
+	MOVH	f+16(FP), AX // ERROR "invalid MOVH of f\+16\(FP\); func\(\) is 4-byte value"
+	RET
+
+TEXT ·argstring(SB),0,$16 // ERROR "wrong argument size 0; expected \$\.\.\.-16"
+	MOVH	x+0(FP), AX // ERROR "invalid MOVH of x\+0\(FP\); string base is 4-byte value"
+	MOVW	x+0(FP), AX
+	MOVH	x_base+0(FP), AX // ERROR "invalid MOVH of x_base\+0\(FP\); string base is 4-byte value"
+	MOVW	x_base+0(FP), AX
+	MOVH	x_len+0(FP), AX // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+4\(FP\)"
+	MOVW	x_len+0(FP), AX // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+4\(FP\)"
+	MOVQ	x_len+0(FP), AX // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+4\(FP\)"
+	MOVH	x_len+4(FP), AX // ERROR "invalid MOVH of x_len\+4\(FP\); string len is 4-byte value"
+	MOVW	x_len+4(FP), AX
+	MOVQ	y+0(FP), AX // ERROR "invalid offset y\+0\(FP\); expected y\+8\(FP\)"
+	MOVQ	y_len+4(FP), AX // ERROR "invalid offset y_len\+4\(FP\); expected y_len\+12\(FP\)"
+	RET
+
+TEXT ·argslice(SB),0,$24 // ERROR "wrong argument size 0; expected \$\.\.\.-24"
+	MOVH	x+0(FP), AX // ERROR "invalid MOVH of x\+0\(FP\); slice base is 4-byte value"
+	MOVW	x+0(FP), AX
+	MOVH	x_base+0(FP), AX // ERROR "invalid MOVH of x_base\+0\(FP\); slice base is 4-byte value"
+	MOVW	x_base+0(FP), AX
+	MOVH	x_len+0(FP), AX // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+4\(FP\)"
+	MOVW	x_len+0(FP), AX // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+4\(FP\)"
+	MOVQ	x_len+0(FP), AX // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+4\(FP\)"
+	MOVH	x_len+4(FP), AX // ERROR "invalid MOVH of x_len\+4\(FP\); slice len is 4-byte value"
+	MOVW	x_len+4(FP), AX
+	MOVH	x_cap+0(FP), AX // ERROR "invalid offset x_cap\+0\(FP\); expected x_cap\+8\(FP\)"
+	MOVW	x_cap+0(FP), AX // ERROR "invalid offset x_cap\+0\(FP\); expected x_cap\+8\(FP\)"
+	MOVQ	x_cap+0(FP), AX // ERROR "invalid offset x_cap\+0\(FP\); expected x_cap\+8\(FP\)"
+	MOVH	x_cap+8(FP), AX // ERROR "invalid MOVH of x_cap\+8\(FP\); slice cap is 4-byte value"
+	MOVW	x_cap+8(FP), AX
+	MOVQ	y+0(FP), AX // ERROR "invalid offset y\+0\(FP\); expected y\+12\(FP\)"
+	MOVQ	y_len+4(FP), AX // ERROR "invalid offset y_len\+4\(FP\); expected y_len\+16\(FP\)"
+	MOVQ	y_cap+8(FP), AX // ERROR "invalid offset y_cap\+8\(FP\); expected y_cap\+20\(FP\)"
+	RET
+
+TEXT ·argiface(SB),0,$0-16
+	MOVH	x+0(FP), AX // ERROR "invalid MOVH of x\+0\(FP\); interface type is 4-byte value"
+	MOVW	x+0(FP), AX
+	MOVH	x_type+0(FP), AX // ERROR "invalid MOVH of x_type\+0\(FP\); interface type is 4-byte value"
+	MOVW	x_type+0(FP), AX
+	MOVQ	x_itable+0(FP), AX // ERROR "unknown variable x_itable; offset 0 is x_type\+0\(FP\)"
+	MOVQ	x_itable+1(FP), AX // ERROR "unknown variable x_itable; offset 1 is x_type\+0\(FP\)"
+	MOVH	x_data+0(FP), AX // ERROR "invalid offset x_data\+0\(FP\); expected x_data\+4\(FP\)"
+	MOVW	x_data+0(FP), AX // ERROR "invalid offset x_data\+0\(FP\); expected x_data\+4\(FP\)"
+	MOVQ	x_data+0(FP), AX // ERROR "invalid offset x_data\+0\(FP\); expected x_data\+4\(FP\)"
+	MOVH	x_data+4(FP), AX // ERROR "invalid MOVH of x_data\+4\(FP\); interface data is 4-byte value"
+	MOVW	x_data+4(FP), AX
+	MOVH	y+8(FP), AX // ERROR "invalid MOVH of y\+8\(FP\); interface itable is 4-byte value"
+	MOVW	y+8(FP), AX
+	MOVH	y_itable+8(FP), AX // ERROR "invalid MOVH of y_itable\+8\(FP\); interface itable is 4-byte value"
+	MOVW	y_itable+8(FP), AX
+	MOVQ	y_type+8(FP), AX // ERROR "unknown variable y_type; offset 8 is y_itable\+8\(FP\)"
+	MOVH	y_data+8(FP), AX // ERROR "invalid offset y_data\+8\(FP\); expected y_data\+12\(FP\)"
+	MOVW	y_data+8(FP), AX // ERROR "invalid offset y_data\+8\(FP\); expected y_data\+12\(FP\)"
+	MOVQ	y_data+8(FP), AX // ERROR "invalid offset y_data\+8\(FP\); expected y_data\+12\(FP\)"
+	MOVH	y_data+12(FP), AX // ERROR "invalid MOVH of y_data\+12\(FP\); interface data is 4-byte value"
+	MOVW	y_data+12(FP), AX
+	RET
+
+TEXT ·returnint(SB),0,$0-4
+	MOVB	AX, ret+0(FP) // ERROR "invalid MOVB of ret\+0\(FP\); int is 4-byte value"
+	MOVH	AX, ret+0(FP) // ERROR "invalid MOVH of ret\+0\(FP\); int is 4-byte value"
+	MOVW	AX, ret+0(FP)
+	MOVQ	AX, ret+1(FP) // ERROR "invalid offset ret\+1\(FP\); expected ret\+0\(FP\)"
+	MOVQ	AX, r+0(FP) // ERROR "unknown variable r; offset 0 is ret\+0\(FP\)"
+	RET
+
+TEXT ·returnbyte(SB),0,$0-5
+	MOVW	x+0(FP), AX
+	MOVB	AX, ret+4(FP)
+	MOVH	AX, ret+4(FP) // ERROR "invalid MOVH of ret\+4\(FP\); byte is 1-byte value"
+	MOVW	AX, ret+4(FP) // ERROR "invalid MOVW of ret\+4\(FP\); byte is 1-byte value"
+	MOVB	AX, ret+3(FP) // ERROR "invalid offset ret\+3\(FP\); expected ret\+4\(FP\)"
+	RET
+
+TEXT ·returnnamed(SB),0,$0-21
+	MOVB	x+0(FP), AX
+	MOVW	AX, r1+4(FP)
+	MOVH	AX, r2+8(FP)
+	MOVW	AX, r3+12(FP)
+	MOVW	AX, r3_base+12(FP)
+	MOVW	AX, r3_len+16(FP)
+	MOVB	AX, r4+20(FP)
+	MOVB	AX, r1+4(FP) // ERROR "invalid MOVB of r1\+4\(FP\); int is 4-byte value"
+	RET
+
+TEXT ·returnintmissing(SB),0,$0-4
+	RET // ERROR "RET without writing to 4-byte ret\+0\(FP\)"
+
+TEXT ·leaf(SB),0,$-4-12
+	MOVW	x+0(FP), AX
+	MOVW	y+4(FP), AX
+	MOVW	AX, ret+8(FP)
+	RET
diff --git a/cmd/vet/testdata/asm4.s b/cmd/vet/testdata/asm4.s
new file mode 100644
index 0000000..044b050
--- /dev/null
+++ b/cmd/vet/testdata/asm4.s
@@ -0,0 +1,26 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build amd64
+// +build vet_test
+
+// Test cases for symbolic NOSPLIT etc. on TEXT symbols.
+
+TEXT ·noprof(SB),NOPROF,$0-8
+	RET
+
+TEXT ·dupok(SB),DUPOK,$0-8
+	RET
+
+TEXT ·nosplit(SB),NOSPLIT,$0
+	RET
+
+TEXT ·rodata(SB),RODATA,$0-8
+	RET
+
+TEXT ·noptr(SB),NOPTR|NOSPLIT,$0
+	RET
+
+TEXT ·wrapper(SB),WRAPPER,$0-8
+	RET
diff --git a/cmd/vet/testdata/assign.go b/cmd/vet/testdata/assign.go
new file mode 100644
index 0000000..32ba868
--- /dev/null
+++ b/cmd/vet/testdata/assign.go
@@ -0,0 +1,18 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file contains tests for the useless-assignment checker.
+
+package testdata
+
+type ST struct {
+	x int
+}
+
+func (s *ST) SetX(x int) {
+	// Accidental self-assignment; it should be "s.x = x"
+	x = x // ERROR "self-assignment of x to x"
+	// Another mistake
+	s.x = s.x // ERROR "self-assignment of s.x to s.x"
+}
diff --git a/cmd/vet/testdata/atomic.go b/cmd/vet/testdata/atomic.go
new file mode 100644
index 0000000..1ba261d
--- /dev/null
+++ b/cmd/vet/testdata/atomic.go
@@ -0,0 +1,43 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file contains tests for the atomic checker.
+
+package testdata
+
+import (
+	"sync/atomic"
+)
+
+type Counter uint64
+
+func AtomicTests() {
+	x := uint64(1)
+	x = atomic.AddUint64(&x, 1)        // ERROR "direct assignment to atomic value"
+	_, x = 10, atomic.AddUint64(&x, 1) // ERROR "direct assignment to atomic value"
+	x, _ = atomic.AddUint64(&x, 1), 10 // ERROR "direct assignment to atomic value"
+
+	y := &x
+	*y = atomic.AddUint64(y, 1) // ERROR "direct assignment to atomic value"
+
+	var su struct{ Counter uint64 }
+	su.Counter = atomic.AddUint64(&su.Counter, 1) // ERROR "direct assignment to atomic value"
+	z1 := atomic.AddUint64(&su.Counter, 1)
+	_ = z1 // Avoid err "z declared and not used"
+
+	var sp struct{ Counter *uint64 }
+	*sp.Counter = atomic.AddUint64(sp.Counter, 1) // ERROR "direct assignment to atomic value"
+	z2 := atomic.AddUint64(sp.Counter, 1)
+	_ = z2 // Avoid err "z declared and not used"
+
+	au := []uint64{10, 20}
+	au[0] = atomic.AddUint64(&au[0], 1) // ERROR "direct assignment to atomic value"
+	au[1] = atomic.AddUint64(&au[0], 1)
+
+	ap := []*uint64{&au[0], &au[1]}
+	*ap[0] = atomic.AddUint64(ap[0], 1) // ERROR "direct assignment to atomic value"
+	*ap[1] = atomic.AddUint64(ap[0], 1)
+
+	x = atomic.AddUint64() // Used to make vet crash; now silently ignored.
+}
diff --git a/cmd/vet/testdata/bool.go b/cmd/vet/testdata/bool.go
new file mode 100644
index 0000000..af6cc01
--- /dev/null
+++ b/cmd/vet/testdata/bool.go
@@ -0,0 +1,113 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file contains tests for the bool checker.
+
+package testdata
+
+import "io"
+
+func RatherStupidConditions() {
+	var f, g func() int
+	if f() == 0 || f() == 0 { // OK f might have side effects
+	}
+	if v, w := f(), g(); v == w || v == w { // ERROR "redundant or: v == w || v == w"
+	}
+	_ = f == nil || f == nil // ERROR "redundant or: f == nil || f == nil"
+
+	_ = i == byte(1) || i == byte(1) // TODO conversions are treated as if they may have side effects
+
+	var c chan int
+	_ = 0 == <-c || 0 == <-c                                  // OK subsequent receives may yield different values
+	for i, j := <-c, <-c; i == j || i == j; i, j = <-c, <-c { // ERROR "redundant or: i == j || i == j"
+	}
+
+	var i, j, k int
+	_ = i+1 == 1 || i+1 == 1         // ERROR "redundant or: i\+1 == 1 || i\+1 == 1"
+	_ = i == 1 || j+1 == i || i == 1 // ERROR "redundant or: i == 1 || i == 1"
+
+	_ = i == 1 || i == 1 || f() == 1 // ERROR "redundant or: i == 1 || i == 1"
+	_ = i == 1 || f() == 1 || i == 1 // OK f may alter i as a side effect
+	_ = f() == 1 || i == 1 || i == 1 // ERROR "redundant or: i == 1 || i == 1"
+
+	// Test partition edge cases
+	_ = f() == 1 || i == 1 || i == 1 || j == 1 // ERROR "redundant or: i == 1 || i == 1"
+	_ = f() == 1 || j == 1 || i == 1 || i == 1 // ERROR "redundant or: i == 1 || i == 1"
+	_ = i == 1 || f() == 1 || i == 1 || i == 1 // ERROR "redundant or: i == 1 || i == 1"
+	_ = i == 1 || i == 1 || f() == 1 || i == 1 // ERROR "redundant or: i == 1 || i == 1"
+	_ = i == 1 || i == 1 || j == 1 || f() == 1 // ERROR "redundant or: i == 1 || i == 1"
+	_ = j == 1 || i == 1 || i == 1 || f() == 1 // ERROR "redundant or: i == 1 || i == 1"
+	_ = i == 1 || f() == 1 || f() == 1 || i == 1
+
+	_ = i == 1 || (i == 1 || i == 2)             // ERROR "redundant or: i == 1 || i == 1"
+	_ = i == 1 || (f() == 1 || i == 1)           // OK f may alter i as a side effect
+	_ = i == 1 || (i == 1 || f() == 1)           // ERROR "redundant or: i == 1 || i == 1"
+	_ = i == 1 || (i == 2 || (i == 1 || i == 3)) // ERROR "redundant or: i == 1 || i == 1"
+
+	var a, b bool
+	_ = i == 1 || (a || (i == 1 || b)) // ERROR "redundant or: i == 1 || i == 1"
+
+	// Check that all redundant ors are flagged
+	_ = j == 0 ||
+		i == 1 ||
+		f() == 1 ||
+		j == 0 || // ERROR "redundant or: j == 0 || j == 0"
+		i == 1 || // ERROR "redundant or: i == 1 || i == 1"
+		i == 1 || // ERROR "redundant or: i == 1 || i == 1"
+		i == 1 ||
+		j == 0 ||
+		k == 0
+
+	_ = i == 1*2*3 || i == 1*2*3 // ERROR "redundant or: i == 1\*2\*3 || i == 1\*2\*3"
+
+	// These test that redundant, suspect expressions do not trigger multiple errors.
+	_ = i != 0 || i != 0 // ERROR "redundant or: i != 0 || i != 0"
+	_ = i == 0 && i == 0 // ERROR "redundant and: i == 0 && i == 0"
+
+	// and is dual to or; check the basics and
+	// let the or tests pull the rest of the weight.
+	_ = 0 != <-c && 0 != <-c         // OK subsequent receives may yield different values
+	_ = f() != 0 && f() != 0         // OK f might have side effects
+	_ = f != nil && f != nil         // ERROR "redundant and: f != nil && f != nil"
+	_ = i != 1 && i != 1 && f() != 1 // ERROR "redundant and: i != 1 && i != 1"
+	_ = i != 1 && f() != 1 && i != 1 // OK f may alter i as a side effect
+	_ = f() != 1 && i != 1 && i != 1 // ERROR "redundant and: i != 1 && i != 1"
+}
+
+func RoyallySuspectConditions() {
+	var i, j int
+
+	_ = i == 0 || i == 1 // OK
+	_ = i != 0 || i != 1 // ERROR "suspect or: i != 0 || i != 1"
+	_ = i != 0 || 1 != i // ERROR "suspect or: i != 0 || 1 != i"
+	_ = 0 != i || 1 != i // ERROR "suspect or: 0 != i || 1 != i"
+	_ = 0 != i || i != 1 // ERROR "suspect or: 0 != i || i != 1"
+
+	_ = (0 != i) || i != 1 // ERROR "suspect or: 0 != i || i != 1"
+
+	_ = i+3 != 7 || j+5 == 0 || i+3 != 9 // ERROR "suspect or: i\+3 != 7 || i\+3 != 9"
+
+	_ = i != 0 || j == 0 || i != 1 // ERROR "suspect or: i != 0 || i != 1"
+
+	_ = i != 0 || i != 1<<4 // ERROR "suspect or: i != 0 || i != 1<<4"
+
+	_ = i != 0 || j != 0
+	_ = 0 != i || 0 != j
+
+	var s string
+	_ = s != "one" || s != "the other" // ERROR "suspect or: s != .one. || s != .the other."
+
+	_ = "et" != "alii" || "et" != "cetera"         // ERROR "suspect or: .et. != .alii. || .et. != .cetera."
+	_ = "me gustas" != "tu" || "le gustas" != "tu" // OK we could catch this case, but it's not worth the code
+
+	var err error
+	_ = err != nil || err != io.EOF // TODO catch this case?
+
+	// Sanity check and.
+	_ = i != 0 && i != 1 // OK
+	_ = i == 0 && i == 1 // ERROR "suspect and: i == 0 && i == 1"
+	_ = i == 0 && 1 == i // ERROR "suspect and: i == 0 && 1 == i"
+	_ = 0 == i && 1 == i // ERROR "suspect and: 0 == i && 1 == i"
+	_ = 0 == i && i == 1 // ERROR "suspect and: 0 == i && i == 1"
+}
diff --git a/cmd/vet/testdata/buildtag.go b/cmd/vet/testdata/buildtag.go
new file mode 100644
index 0000000..eb36fd3
--- /dev/null
+++ b/cmd/vet/testdata/buildtag.go
@@ -0,0 +1,14 @@
+// Copyright 2013 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file contains tests for the buildtag checker.
+
+// +builder // ERROR "possible malformed \+build comment"
+// +build !ignore
+
+package testdata
+
+// +build toolate // ERROR "build comment must appear before package clause and be followed by a blank line"
+
+var _ = 3
diff --git a/cmd/vet/testdata/buildtag_bad.go b/cmd/vet/testdata/buildtag_bad.go
new file mode 100644
index 0000000..fbe10cf
--- /dev/null
+++ b/cmd/vet/testdata/buildtag_bad.go
@@ -0,0 +1,15 @@
+// This file contains misplaced or malformed build constraints.
+// The Go tool will skip it, because the constraints are invalid.
+// It serves only to test the tag checker during make test.
+
+// Mention +build // ERROR "possible malformed \+build comment"
+
+// +build !!bang // ERROR "invalid double negative in build constraint"
+// +build @#$ // ERROR "invalid non-alphanumeric build constraint"
+
+// +build toolate // ERROR "build comment must appear before package clause and be followed by a blank line"
+package bad
+
+// This is package 'bad' rather than 'main' so the erroneous build
+// tag doesn't end up looking like a package doc for the vet command
+// when examined by godoc.
diff --git a/cmd/vet/testdata/composite.go b/cmd/vet/testdata/composite.go
new file mode 100644
index 0000000..69e7d7c
--- /dev/null
+++ b/cmd/vet/testdata/composite.go
@@ -0,0 +1,63 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file contains tests for the untagged struct literal checker.
+
+// This file contains the test for untagged struct literals.
+
+package testdata
+
+import (
+	"flag"
+	"go/scanner"
+)
+
+var Okay1 = []string{
+	"Name",
+	"Usage",
+	"DefValue",
+}
+
+var Okay2 = map[string]bool{
+	"Name":     true,
+	"Usage":    true,
+	"DefValue": true,
+}
+
+var Okay3 = struct {
+	X string
+	Y string
+	Z string
+}{
+	"Name",
+	"Usage",
+	"DefValue",
+}
+
+type MyStruct struct {
+	X string
+	Y string
+	Z string
+}
+
+var Okay4 = MyStruct{
+	"Name",
+	"Usage",
+	"DefValue",
+}
+
+// Testing is awkward because we need to reference things from a separate package
+// to trigger the warnings.
+
+var BadStructLiteralUsedInTests = flag.Flag{ // ERROR "unkeyed fields"
+	"Name",
+	"Usage",
+	nil, // Value
+	"DefValue",
+}
+
+// Used to test the check for slices and arrays: If that test is disabled and
+// vet is run with --compositewhitelist=false, this line triggers an error.
+// Clumsy but sufficient.
+var scannerErrorListTest = scanner.ErrorList{nil, nil}
diff --git a/cmd/vet/testdata/copylock_func.go b/cmd/vet/testdata/copylock_func.go
new file mode 100644
index 0000000..108c044
--- /dev/null
+++ b/cmd/vet/testdata/copylock_func.go
@@ -0,0 +1,90 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file contains tests for the copylock checker's
+// function declaration analysis.
+
+package testdata
+
+import "sync"
+
+func OkFunc(*sync.Mutex) {}
+func BadFunc(sync.Mutex) {} // ERROR "BadFunc passes Lock by value: sync.Mutex"
+func OkRet() *sync.Mutex {}
+func BadRet() sync.Mutex {} // ERROR "BadRet returns Lock by value: sync.Mutex"
+
+type EmbeddedRWMutex struct {
+	sync.RWMutex
+}
+
+func (*EmbeddedRWMutex) OkMeth() {}
+func (EmbeddedRWMutex) BadMeth() {} // ERROR "BadMeth passes Lock by value: testdata.EmbeddedRWMutex"
+func OkFunc(e *EmbeddedRWMutex)  {}
+func BadFunc(EmbeddedRWMutex)    {} // ERROR "BadFunc passes Lock by value: testdata.EmbeddedRWMutex"
+func OkRet() *EmbeddedRWMutex    {}
+func BadRet() EmbeddedRWMutex    {} // ERROR "BadRet returns Lock by value: testdata.EmbeddedRWMutex"
+
+type FieldMutex struct {
+	s sync.Mutex
+}
+
+func (*FieldMutex) OkMeth()   {}
+func (FieldMutex) BadMeth()   {} // ERROR "BadMeth passes Lock by value: testdata.FieldMutex contains sync.Mutex"
+func OkFunc(*FieldMutex)      {}
+func BadFunc(FieldMutex, int) {} // ERROR "BadFunc passes Lock by value: testdata.FieldMutex contains sync.Mutex"
+
+type L0 struct {
+	L1
+}
+
+type L1 struct {
+	l L2
+}
+
+type L2 struct {
+	sync.Mutex
+}
+
+func (*L0) Ok() {}
+func (L0) Bad() {} // ERROR "Bad passes Lock by value: testdata.L0 contains testdata.L1 contains testdata.L2"
+
+type EmbeddedMutexPointer struct {
+	s *sync.Mutex // safe to copy this pointer
+}
+
+func (*EmbeddedMutexPointer) Ok()      {}
+func (EmbeddedMutexPointer) AlsoOk()   {}
+func StillOk(EmbeddedMutexPointer)     {}
+func LookinGood() EmbeddedMutexPointer {}
+
+type EmbeddedLocker struct {
+	sync.Locker // safe to copy interface values
+}
+
+func (*EmbeddedLocker) Ok()    {}
+func (EmbeddedLocker) AlsoOk() {}
+
+type CustomLock struct{}
+
+func (*CustomLock) Lock()   {}
+func (*CustomLock) Unlock() {}
+
+func Ok(*CustomLock) {}
+func Bad(CustomLock) {} // ERROR "Bad passes Lock by value: testdata.CustomLock"
+
+// TODO: Unfortunate cases
+
+// Non-ideal error message:
+// Since we're looking for Lock methods, sync.Once's underlying
+// sync.Mutex gets called out, but without any reference to the sync.Once.
+type LocalOnce sync.Once
+
+func (LocalOnce) Bad() {} // ERROR "Bad passes Lock by value: testdata.LocalOnce contains sync.Mutex"
+
+// False negative:
+// LocalMutex doesn't have a Lock method.
+// Nevertheless, it is probably a bad idea to pass it by value.
+type LocalMutex sync.Mutex
+
+func (LocalMutex) Bad() {} // WANTED: An error here :(
diff --git a/cmd/vet/testdata/copylock_range.go b/cmd/vet/testdata/copylock_range.go
new file mode 100644
index 0000000..f95b025
--- /dev/null
+++ b/cmd/vet/testdata/copylock_range.go
@@ -0,0 +1,67 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file contains tests for the copylock checker's
+// range statement analysis.
+
+package testdata
+
+import "sync"
+
+func rangeMutex() {
+	var mu sync.Mutex
+	var i int
+
+	var s []sync.Mutex
+	for range s {
+	}
+	for i = range s {
+	}
+	for i := range s {
+	}
+	for i, _ = range s {
+	}
+	for i, _ := range s {
+	}
+	for _, mu = range s { // ERROR "range var mu copies Lock: sync.Mutex"
+	}
+	for _, m := range s { // ERROR "range var m copies Lock: sync.Mutex"
+	}
+	for i, mu = range s { // ERROR "range var mu copies Lock: sync.Mutex"
+	}
+	for i, m := range s { // ERROR "range var m copies Lock: sync.Mutex"
+	}
+
+	var a [3]sync.Mutex
+	for _, m := range a { // ERROR "range var m copies Lock: sync.Mutex"
+	}
+
+	var m map[sync.Mutex]sync.Mutex
+	for k := range m { // ERROR "range var k copies Lock: sync.Mutex"
+	}
+	for mu, _ = range m { // ERROR "range var mu copies Lock: sync.Mutex"
+	}
+	for k, _ := range m { // ERROR "range var k copies Lock: sync.Mutex"
+	}
+	for _, mu = range m { // ERROR "range var mu copies Lock: sync.Mutex"
+	}
+	for _, v := range m { // ERROR "range var v copies Lock: sync.Mutex"
+	}
+
+	var c chan sync.Mutex
+	for range c {
+	}
+	for mu = range c { // ERROR "range var mu copies Lock: sync.Mutex"
+	}
+	for v := range c { // ERROR "range var v copies Lock: sync.Mutex"
+	}
+
+	// Test non-idents in range variables
+	var t struct {
+		i  int
+		mu sync.Mutex
+	}
+	for t.i, t.mu = range s { // ERROR "range var t.mu copies Lock: sync.Mutex"
+	}
+}
diff --git a/cmd/vet/testdata/deadcode.go b/cmd/vet/testdata/deadcode.go
new file mode 100644
index 0000000..5370bc3
--- /dev/null
+++ b/cmd/vet/testdata/deadcode.go
@@ -0,0 +1,2125 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build ignore
+
+// This file contains tests for the dead code checker.
+
+package testdata
+
+type T int
+
+var x interface{}
+var c chan int
+
+func external() int // ok
+
+func _() int {
+}
+
+func _() int {
+	print(1)
+}
+
+func _() int {
+	print(1)
+	return 2
+	println() // ERROR "unreachable code"
+}
+
+func _() int {
+L:
+	print(1)
+	goto L
+	println() // ERROR "unreachable code"
+}
+
+func _() int {
+	print(1)
+	panic(2)
+	println() // ERROR "unreachable code"
+}
+
+// but only builtin panic
+func _() int {
+	var panic = func(int) {}
+	print(1)
+	panic(2)
+	println() // ok
+}
+
+func _() int {
+	{
+		print(1)
+		return 2
+		println() // ERROR "unreachable code"
+	}
+	println() // ok
+}
+
+func _() int {
+	{
+		print(1)
+		return 2
+	}
+	println() // ERROR "unreachable code"
+}
+
+func _() int {
+L:
+	{
+		print(1)
+		goto L
+		println() // ERROR "unreachable code"
+	}
+	println() // ok
+}
+
+func _() int {
+L:
+	{
+		print(1)
+		goto L
+	}
+	println() // ERROR "unreachable code"
+}
+
+func _() int {
+	print(1)
+	{
+		panic(2)
+	}
+}
+
+func _() int {
+	print(1)
+	{
+		panic(2)
+		println() // ERROR "unreachable code"
+	}
+}
+
+func _() int {
+	print(1)
+	{
+		panic(2)
+	}
+	println() // ERROR "unreachable code"
+}
+
+func _() int {
+	print(1)
+	return 2
+	{ // ERROR "unreachable code"
+	}
+}
+
+func _() int {
+L:
+	print(1)
+	goto L
+	{ // ERROR "unreachable code"
+	}
+}
+
+func _() int {
+	print(1)
+	panic(2)
+	{ // ERROR "unreachable code"
+	}
+}
+
+func _() int {
+	{
+		print(1)
+		return 2
+		{ // ERROR "unreachable code"
+		}
+	}
+}
+
+func _() int {
+L:
+	{
+		print(1)
+		goto L
+		{ // ERROR "unreachable code"
+		}
+	}
+}
+
+func _() int {
+	print(1)
+	{
+		panic(2)
+		{ // ERROR "unreachable code"
+		}
+	}
+}
+
+func _() int {
+	{
+		print(1)
+		return 2
+	}
+	{ // ERROR "unreachable code"
+	}
+}
+
+func _() int {
+L:
+	{
+		print(1)
+		goto L
+	}
+	{ // ERROR "unreachable code"
+	}
+}
+
+func _() int {
+	print(1)
+	{
+		panic(2)
+	}
+	{ // ERROR "unreachable code"
+	}
+}
+
+func _() int {
+	print(1)
+	if x == nil {
+		panic(2)
+	} else {
+		panic(3)
+	}
+	println() // ERROR "unreachable code"
+}
+
+func _() int {
+L:
+	print(1)
+	if x == nil {
+		panic(2)
+	} else {
+		goto L
+	}
+	println() // ERROR "unreachable code"
+}
+
+func _() int {
+L:
+	print(1)
+	if x == nil {
+		panic(2)
+	} else if x == 1 {
+		return 0
+	} else if x != 2 {
+		panic(3)
+	} else {
+		goto L
+	}
+	println() // ERROR "unreachable code"
+}
+
+// if-else chain missing final else is not okay, even if the
+// conditions cover every possible case.
+
+func _() int {
+	print(1)
+	if x == nil {
+		panic(2)
+	} else if x != nil {
+		panic(3)
+	}
+	println() // ok
+}
+
+func _() int {
+	print(1)
+	if x == nil {
+		panic(2)
+	}
+	println() // ok
+}
+
+func _() int {
+L:
+	print(1)
+	if x == nil {
+		panic(2)
+	} else if x == 1 {
+		return 0
+	} else if x != 1 {
+		panic(3)
+	}
+	println() // ok
+}
+
+func _() int {
+	print(1)
+	for {
+	}
+	println() // ERROR "unreachable code"
+}
+
+func _() int {
+	for {
+		for {
+			break
+		}
+	}
+	println() // ERROR "unreachable code"
+}
+
+func _() int {
+	for {
+		for {
+			break
+			println() // ERROR "unreachable code"
+		}
+	}
+}
+
+func _() int {
+	for {
+		for {
+			continue
+			println() // ERROR "unreachable code"
+		}
+	}
+}
+
+func _() int {
+	for {
+	L:
+		for {
+			break L
+		}
+	}
+	println() // ERROR "unreachable code"
+}
+
+func _() int {
+	print(1)
+	for {
+		break
+	}
+	println() // ok
+}
+
+func _() int {
+	for {
+		for {
+		}
+		break // ERROR "unreachable code"
+	}
+	println() // ok
+}
+
+func _() int {
+L:
+	for {
+		for {
+			break L
+		}
+	}
+	println() // ok
+}
+
+func _() int {
+	print(1)
+	for x == nil {
+	}
+	println() // ok
+}
+
+func _() int {
+	for x == nil {
+		for {
+			break
+		}
+	}
+	println() // ok
+}
+
+func _() int {
+	for x == nil {
+	L:
+		for {
+			break L
+		}
+	}
+	println() // ok
+}
+
+func _() int {
+	print(1)
+	for true {
+	}
+	println() // ok
+}
+
+func _() int {
+	for true {
+		for {
+			break
+		}
+	}
+	println() // ok
+}
+
+func _() int {
+	for true {
+	L:
+		for {
+			break L
+		}
+	}
+	println() // ok
+}
+
+func _() int {
+	print(1)
+	select {}
+	println() // ERROR "unreachable code"
+}
+
+func _() int {
+	print(1)
+	select {
+	case <-c:
+		print(2)
+		panic("abc")
+		println() // ERROR "unreachable code"
+	}
+}
+
+func _() int {
+	print(1)
+	select {
+	case <-c:
+		print(2)
+		panic("abc")
+	}
+	println() // ERROR "unreachable code"
+}
+
+func _() int {
+	print(1)
+	select {
+	case <-c:
+		print(2)
+		for {
+		}
+		println() // ERROR "unreachable code"
+	}
+}
+
+func _() int {
+	print(1)
+	select {
+	case <-c:
+		print(2)
+		for {
+		}
+	}
+	println() // ERROR "unreachable code"
+}
+
+func _() int {
+L:
+	print(1)
+	select {
+	case <-c:
+		print(2)
+		panic("abc")
+		println() // ERROR "unreachable code"
+	case c <- 1:
+		print(2)
+		goto L
+		println() // ERROR "unreachable code"
+	}
+}
+
+func _() int {
+L:
+	print(1)
+	select {
+	case <-c:
+		print(2)
+		panic("abc")
+	case c <- 1:
+		print(2)
+		goto L
+	}
+	println() // ERROR "unreachable code"
+}
+
+func _() int {
+	print(1)
+	select {
+	case <-c:
+		print(2)
+		panic("abc")
+		println() // ERROR "unreachable code"
+	default:
+		select {}
+		println() // ERROR "unreachable code"
+	}
+}
+
+func _() int {
+	print(1)
+	select {
+	case <-c:
+		print(2)
+		panic("abc")
+	default:
+		select {}
+	}
+	println() // ERROR "unreachable code"
+}
+
+func _() int {
+	print(1)
+	select {
+	case <-c:
+		print(2)
+	}
+	println() // ok
+}
+
+func _() int {
+L:
+	print(1)
+	select {
+	case <-c:
+		print(2)
+		panic("abc")
+		goto L // ERROR "unreachable code"
+	case c <- 1:
+		print(2)
+	}
+	println() // ok
+}
+
+func _() int {
+	print(1)
+	select {
+	case <-c:
+		print(2)
+		panic("abc")
+	default:
+		print(2)
+	}
+	println() // ok
+}
+
+func _() int {
+	print(1)
+	select {
+	default:
+		break
+	}
+	println() // ok
+}
+
+func _() int {
+	print(1)
+	select {
+	case <-c:
+		print(2)
+		panic("abc")
+		break // ERROR "unreachable code"
+	}
+	println() // ok
+}
+
+func _() int {
+	print(1)
+L:
+	select {
+	case <-c:
+		print(2)
+		for {
+			break L
+		}
+	}
+	println() // ok
+}
+
+func _() int {
+	print(1)
+L:
+	select {
+	case <-c:
+		print(2)
+		panic("abc")
+	case c <- 1:
+		print(2)
+		break L
+	}
+	println() // ok
+}
+
+func _() int {
+	print(1)
+	select {
+	case <-c:
+		print(1)
+		panic("abc")
+	default:
+		select {}
+		break // ERROR "unreachable code"
+	}
+	println() // ok
+}
+
+func _() int {
+	print(1)
+	switch x {
+	case 1:
+		print(2)
+		panic(3)
+		println() // ERROR "unreachable code"
+	default:
+		return 4
+		println() // ERROR "unreachable code"
+	}
+}
+
+func _() int {
+	print(1)
+	switch x {
+	case 1:
+		print(2)
+		panic(3)
+	default:
+		return 4
+	}
+	println() // ERROR "unreachable code"
+}
+
+func _() int {
+	print(1)
+	switch x {
+	default:
+		return 4
+		println() // ERROR "unreachable code"
+	case 1:
+		print(2)
+		panic(3)
+		println() // ERROR "unreachable code"
+	}
+}
+
+func _() int {
+	print(1)
+	switch x {
+	default:
+		return 4
+	case 1:
+		print(2)
+		panic(3)
+	}
+	println() // ERROR "unreachable code"
+}
+
+func _() int {
+	print(1)
+	switch x {
+	case 1:
+		print(2)
+		fallthrough
+	default:
+		return 4
+		println() // ERROR "unreachable code"
+	}
+}
+
+func _() int {
+	print(1)
+	switch x {
+	case 1:
+		print(2)
+		fallthrough
+	default:
+		return 4
+	}
+	println() // ERROR "unreachable code"
+}
+
+func _() int {
+	print(1)
+	switch {
+	}
+	println() // ok
+}
+
+func _() int {
+	print(1)
+	switch x {
+	case 1:
+		print(2)
+		panic(3)
+	case 2:
+		return 4
+	}
+	println() // ok
+}
+
+func _() int {
+	print(1)
+	switch x {
+	case 2:
+		return 4
+	case 1:
+		print(2)
+		panic(3)
+	}
+	println() // ok
+}
+
+func _() int {
+	print(1)
+	switch x {
+	case 1:
+		print(2)
+		fallthrough
+	case 2:
+		return 4
+	}
+	println() // ok
+}
+
+func _() int {
+	print(1)
+	switch x {
+	case 1:
+		print(2)
+		panic(3)
+	}
+	println() // ok
+}
+
+func _() int {
+	print(1)
+L:
+	switch x {
+	case 1:
+		print(2)
+		panic(3)
+		break L // ERROR "unreachable code"
+	default:
+		return 4
+	}
+	println() // ok
+}
+
+func _() int {
+	print(1)
+	switch x {
+	default:
+		return 4
+		break // ERROR "unreachable code"
+	case 1:
+		print(2)
+		panic(3)
+	}
+	println() // ok
+}
+
+func _() int {
+	print(1)
+L:
+	switch x {
+	case 1:
+		print(2)
+		for {
+			break L
+		}
+	default:
+		return 4
+	}
+	println() // ok
+}
+
+func _() int {
+	print(1)
+	switch x.(type) {
+	case int:
+		print(2)
+		panic(3)
+		println() // ERROR "unreachable code"
+	default:
+		return 4
+		println() // ERROR "unreachable code"
+	}
+}
+
+func _() int {
+	print(1)
+	switch x.(type) {
+	case int:
+		print(2)
+		panic(3)
+	default:
+		return 4
+	}
+	println() // ERROR "unreachable code"
+}
+
+func _() int {
+	print(1)
+	switch x.(type) {
+	default:
+		return 4
+		println() // ERROR "unreachable code"
+	case int:
+		print(2)
+		panic(3)
+		println() // ERROR "unreachable code"
+	}
+}
+
+func _() int {
+	print(1)
+	switch x.(type) {
+	default:
+		return 4
+	case int:
+		print(2)
+		panic(3)
+	}
+	println() // ERROR "unreachable code"
+}
+
+func _() int {
+	print(1)
+	switch x.(type) {
+	case int:
+		print(2)
+		fallthrough
+	default:
+		return 4
+		println() // ERROR "unreachable code"
+	}
+}
+
+func _() int {
+	print(1)
+	switch x.(type) {
+	case int:
+		print(2)
+		fallthrough
+	default:
+		return 4
+	}
+	println() // ERROR "unreachable code"
+}
+
+func _() int {
+	print(1)
+	switch {
+	}
+	println() // ok
+}
+
+func _() int {
+	print(1)
+	switch x.(type) {
+	case int:
+		print(2)
+		panic(3)
+	case float64:
+		return 4
+	}
+	println() // ok
+}
+
+func _() int {
+	print(1)
+	switch x.(type) {
+	case float64:
+		return 4
+	case int:
+		print(2)
+		panic(3)
+	}
+	println() // ok
+}
+
+func _() int {
+	print(1)
+	switch x.(type) {
+	case int:
+		print(2)
+		fallthrough
+	case float64:
+		return 4
+	}
+	println() // ok
+}
+
+func _() int {
+	print(1)
+	switch x.(type) {
+	case int:
+		print(2)
+		panic(3)
+	}
+	println() // ok
+}
+
+func _() int {
+	print(1)
+L:
+	switch x.(type) {
+	case int:
+		print(2)
+		panic(3)
+		break L // ERROR "unreachable code"
+	default:
+		return 4
+	}
+	println() // ok
+}
+
+func _() int {
+	print(1)
+	switch x.(type) {
+	default:
+		return 4
+		break // ERROR "unreachable code"
+	case int:
+		print(2)
+		panic(3)
+	}
+	println() // ok
+}
+
+func _() int {
+	print(1)
+L:
+	switch x.(type) {
+	case int:
+		print(2)
+		for {
+			break L
+		}
+	default:
+		return 4
+	}
+	println() // ok
+}
+
+// again, but without the leading print(1).
+// testing that everything works when the terminating statement is first.
+
+func _() int {
+	println() // ok
+}
+
+func _() int {
+	return 2
+	println() // ERROR "unreachable code"
+}
+
+func _() int {
+L:
+	goto L
+	println() // ERROR "unreachable code"
+}
+
+func _() int {
+	panic(2)
+	println() // ERROR "unreachable code"
+}
+
+// but only builtin panic
+func _() int {
+	var panic = func(int) {}
+	panic(2)
+	println() // ok
+}
+
+func _() int {
+	{
+		return 2
+		println() // ERROR "unreachable code"
+	}
+}
+
+func _() int {
+	{
+		return 2
+	}
+	println() // ERROR "unreachable code"
+}
+
+func _() int {
+L:
+	{
+		goto L
+		println() // ERROR "unreachable code"
+	}
+}
+
+func _() int {
+L:
+	{
+		goto L
+	}
+	println() // ERROR "unreachable code"
+}
+
+func _() int {
+	{
+		panic(2)
+		println() // ERROR "unreachable code"
+	}
+}
+
+func _() int {
+	{
+		panic(2)
+	}
+	println() // ERROR "unreachable code"
+}
+
+func _() int {
+	return 2
+	{ // ERROR "unreachable code"
+	}
+	println() // ok
+}
+
+func _() int {
+L:
+	goto L
+	{ // ERROR "unreachable code"
+	}
+	println() // ok
+}
+
+func _() int {
+	panic(2)
+	{ // ERROR "unreachable code"
+	}
+	println() // ok
+}
+
+func _() int {
+	{
+		return 2
+		{ // ERROR "unreachable code"
+		}
+	}
+	println() // ok
+}
+
+func _() int {
+L:
+	{
+		goto L
+		{ // ERROR "unreachable code"
+		}
+	}
+	println() // ok
+}
+
+func _() int {
+	{
+		panic(2)
+		{ // ERROR "unreachable code"
+		}
+	}
+	println() // ok
+}
+
+func _() int {
+	{
+		return 2
+	}
+	{ // ERROR "unreachable code"
+	}
+	println() // ok
+}
+
+func _() int {
+L:
+	{
+		goto L
+	}
+	{ // ERROR "unreachable code"
+	}
+	println() // ok
+}
+
+func _() int {
+	{
+		panic(2)
+	}
+	{ // ERROR "unreachable code"
+	}
+	println() // ok
+}
+
+// again, with func literals
+
+var _ = func() int {
+}
+
+var _ = func() int {
+	print(1)
+}
+
+var _ = func() int {
+	print(1)
+	return 2
+	println() // ERROR "unreachable code"
+}
+
+var _ = func() int {
+L:
+	print(1)
+	goto L
+	println() // ERROR "unreachable code"
+}
+
+var _ = func() int {
+	print(1)
+	panic(2)
+	println() // ERROR "unreachable code"
+}
+
+// but only builtin panic
+var _ = func() int {
+	var panic = func(int) {}
+	print(1)
+	panic(2)
+	println() // ok
+}
+
+var _ = func() int {
+	{
+		print(1)
+		return 2
+		println() // ERROR "unreachable code"
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	{
+		print(1)
+		return 2
+	}
+	println() // ERROR "unreachable code"
+}
+
+var _ = func() int {
+L:
+	{
+		print(1)
+		goto L
+		println() // ERROR "unreachable code"
+	}
+	println() // ok
+}
+
+var _ = func() int {
+L:
+	{
+		print(1)
+		goto L
+	}
+	println() // ERROR "unreachable code"
+}
+
+var _ = func() int {
+	print(1)
+	{
+		panic(2)
+	}
+}
+
+var _ = func() int {
+	print(1)
+	{
+		panic(2)
+		println() // ERROR "unreachable code"
+	}
+}
+
+var _ = func() int {
+	print(1)
+	{
+		panic(2)
+	}
+	println() // ERROR "unreachable code"
+}
+
+var _ = func() int {
+	print(1)
+	return 2
+	{ // ERROR "unreachable code"
+	}
+}
+
+var _ = func() int {
+L:
+	print(1)
+	goto L
+	{ // ERROR "unreachable code"
+	}
+}
+
+var _ = func() int {
+	print(1)
+	panic(2)
+	{ // ERROR "unreachable code"
+	}
+}
+
+var _ = func() int {
+	{
+		print(1)
+		return 2
+		{ // ERROR "unreachable code"
+		}
+	}
+}
+
+var _ = func() int {
+L:
+	{
+		print(1)
+		goto L
+		{ // ERROR "unreachable code"
+		}
+	}
+}
+
+var _ = func() int {
+	print(1)
+	{
+		panic(2)
+		{ // ERROR "unreachable code"
+		}
+	}
+}
+
+var _ = func() int {
+	{
+		print(1)
+		return 2
+	}
+	{ // ERROR "unreachable code"
+	}
+}
+
+var _ = func() int {
+L:
+	{
+		print(1)
+		goto L
+	}
+	{ // ERROR "unreachable code"
+	}
+}
+
+var _ = func() int {
+	print(1)
+	{
+		panic(2)
+	}
+	{ // ERROR "unreachable code"
+	}
+}
+
+var _ = func() int {
+	print(1)
+	if x == nil {
+		panic(2)
+	} else {
+		panic(3)
+	}
+	println() // ERROR "unreachable code"
+}
+
+var _ = func() int {
+L:
+	print(1)
+	if x == nil {
+		panic(2)
+	} else {
+		goto L
+	}
+	println() // ERROR "unreachable code"
+}
+
+var _ = func() int {
+L:
+	print(1)
+	if x == nil {
+		panic(2)
+	} else if x == 1 {
+		return 0
+	} else if x != 2 {
+		panic(3)
+	} else {
+		goto L
+	}
+	println() // ERROR "unreachable code"
+}
+
+// if-else chain missing final else is not okay, even if the
+// conditions cover every possible case.
+
+var _ = func() int {
+	print(1)
+	if x == nil {
+		panic(2)
+	} else if x != nil {
+		panic(3)
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	print(1)
+	if x == nil {
+		panic(2)
+	}
+	println() // ok
+}
+
+var _ = func() int {
+L:
+	print(1)
+	if x == nil {
+		panic(2)
+	} else if x == 1 {
+		return 0
+	} else if x != 1 {
+		panic(3)
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	print(1)
+	for {
+	}
+	println() // ERROR "unreachable code"
+}
+
+var _ = func() int {
+	for {
+		for {
+			break
+		}
+	}
+	println() // ERROR "unreachable code"
+}
+
+var _ = func() int {
+	for {
+		for {
+			break
+			println() // ERROR "unreachable code"
+		}
+	}
+}
+
+var _ = func() int {
+	for {
+		for {
+			continue
+			println() // ERROR "unreachable code"
+		}
+	}
+}
+
+var _ = func() int {
+	for {
+	L:
+		for {
+			break L
+		}
+	}
+	println() // ERROR "unreachable code"
+}
+
+var _ = func() int {
+	print(1)
+	for {
+		break
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	for {
+		for {
+		}
+		break // ERROR "unreachable code"
+	}
+	println() // ok
+}
+
+var _ = func() int {
+L:
+	for {
+		for {
+			break L
+		}
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	print(1)
+	for x == nil {
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	for x == nil {
+		for {
+			break
+		}
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	for x == nil {
+	L:
+		for {
+			break L
+		}
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	print(1)
+	for true {
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	for true {
+		for {
+			break
+		}
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	for true {
+	L:
+		for {
+			break L
+		}
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	print(1)
+	select {}
+	println() // ERROR "unreachable code"
+}
+
+var _ = func() int {
+	print(1)
+	select {
+	case <-c:
+		print(2)
+		panic("abc")
+		println() // ERROR "unreachable code"
+	}
+}
+
+var _ = func() int {
+	print(1)
+	select {
+	case <-c:
+		print(2)
+		panic("abc")
+	}
+	println() // ERROR "unreachable code"
+}
+
+var _ = func() int {
+	print(1)
+	select {
+	case <-c:
+		print(2)
+		for {
+		}
+		println() // ERROR "unreachable code"
+	}
+}
+
+var _ = func() int {
+	print(1)
+	select {
+	case <-c:
+		print(2)
+		for {
+		}
+	}
+	println() // ERROR "unreachable code"
+}
+
+var _ = func() int {
+L:
+	print(1)
+	select {
+	case <-c:
+		print(2)
+		panic("abc")
+		println() // ERROR "unreachable code"
+	case c <- 1:
+		print(2)
+		goto L
+		println() // ERROR "unreachable code"
+	}
+}
+
+var _ = func() int {
+L:
+	print(1)
+	select {
+	case <-c:
+		print(2)
+		panic("abc")
+	case c <- 1:
+		print(2)
+		goto L
+	}
+	println() // ERROR "unreachable code"
+}
+
+var _ = func() int {
+	print(1)
+	select {
+	case <-c:
+		print(2)
+		panic("abc")
+		println() // ERROR "unreachable code"
+	default:
+		select {}
+		println() // ERROR "unreachable code"
+	}
+}
+
+var _ = func() int {
+	print(1)
+	select {
+	case <-c:
+		print(2)
+		panic("abc")
+	default:
+		select {}
+	}
+	println() // ERROR "unreachable code"
+}
+
+var _ = func() int {
+	print(1)
+	select {
+	case <-c:
+		print(2)
+	}
+	println() // ok
+}
+
+var _ = func() int {
+L:
+	print(1)
+	select {
+	case <-c:
+		print(2)
+		panic("abc")
+		goto L // ERROR "unreachable code"
+	case c <- 1:
+		print(2)
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	print(1)
+	select {
+	case <-c:
+		print(2)
+		panic("abc")
+	default:
+		print(2)
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	print(1)
+	select {
+	default:
+		break
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	print(1)
+	select {
+	case <-c:
+		print(2)
+		panic("abc")
+		break // ERROR "unreachable code"
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	print(1)
+L:
+	select {
+	case <-c:
+		print(2)
+		for {
+			break L
+		}
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	print(1)
+L:
+	select {
+	case <-c:
+		print(2)
+		panic("abc")
+	case c <- 1:
+		print(2)
+		break L
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	print(1)
+	select {
+	case <-c:
+		print(1)
+		panic("abc")
+	default:
+		select {}
+		break // ERROR "unreachable code"
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	print(1)
+	switch x {
+	case 1:
+		print(2)
+		panic(3)
+		println() // ERROR "unreachable code"
+	default:
+		return 4
+		println() // ERROR "unreachable code"
+	}
+}
+
+var _ = func() int {
+	print(1)
+	switch x {
+	case 1:
+		print(2)
+		panic(3)
+	default:
+		return 4
+	}
+	println() // ERROR "unreachable code"
+}
+
+var _ = func() int {
+	print(1)
+	switch x {
+	default:
+		return 4
+		println() // ERROR "unreachable code"
+	case 1:
+		print(2)
+		panic(3)
+		println() // ERROR "unreachable code"
+	}
+}
+
+var _ = func() int {
+	print(1)
+	switch x {
+	default:
+		return 4
+	case 1:
+		print(2)
+		panic(3)
+	}
+	println() // ERROR "unreachable code"
+}
+
+var _ = func() int {
+	print(1)
+	switch x {
+	case 1:
+		print(2)
+		fallthrough
+	default:
+		return 4
+		println() // ERROR "unreachable code"
+	}
+}
+
+var _ = func() int {
+	print(1)
+	switch x {
+	case 1:
+		print(2)
+		fallthrough
+	default:
+		return 4
+	}
+	println() // ERROR "unreachable code"
+}
+
+var _ = func() int {
+	print(1)
+	switch {
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	print(1)
+	switch x {
+	case 1:
+		print(2)
+		panic(3)
+	case 2:
+		return 4
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	print(1)
+	switch x {
+	case 2:
+		return 4
+	case 1:
+		print(2)
+		panic(3)
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	print(1)
+	switch x {
+	case 1:
+		print(2)
+		fallthrough
+	case 2:
+		return 4
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	print(1)
+	switch x {
+	case 1:
+		print(2)
+		panic(3)
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	print(1)
+L:
+	switch x {
+	case 1:
+		print(2)
+		panic(3)
+		break L // ERROR "unreachable code"
+	default:
+		return 4
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	print(1)
+	switch x {
+	default:
+		return 4
+		break // ERROR "unreachable code"
+	case 1:
+		print(2)
+		panic(3)
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	print(1)
+L:
+	switch x {
+	case 1:
+		print(2)
+		for {
+			break L
+		}
+	default:
+		return 4
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	print(1)
+	switch x.(type) {
+	case int:
+		print(2)
+		panic(3)
+		println() // ERROR "unreachable code"
+	default:
+		return 4
+		println() // ERROR "unreachable code"
+	}
+}
+
+var _ = func() int {
+	print(1)
+	switch x.(type) {
+	case int:
+		print(2)
+		panic(3)
+	default:
+		return 4
+	}
+	println() // ERROR "unreachable code"
+}
+
+var _ = func() int {
+	print(1)
+	switch x.(type) {
+	default:
+		return 4
+		println() // ERROR "unreachable code"
+	case int:
+		print(2)
+		panic(3)
+		println() // ERROR "unreachable code"
+	}
+}
+
+var _ = func() int {
+	print(1)
+	switch x.(type) {
+	default:
+		return 4
+	case int:
+		print(2)
+		panic(3)
+	}
+	println() // ERROR "unreachable code"
+}
+
+var _ = func() int {
+	print(1)
+	switch x.(type) {
+	case int:
+		print(2)
+		fallthrough
+	default:
+		return 4
+		println() // ERROR "unreachable code"
+	}
+}
+
+var _ = func() int {
+	print(1)
+	switch x.(type) {
+	case int:
+		print(2)
+		fallthrough
+	default:
+		return 4
+	}
+	println() // ERROR "unreachable code"
+}
+
+var _ = func() int {
+	print(1)
+	switch {
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	print(1)
+	switch x.(type) {
+	case int:
+		print(2)
+		panic(3)
+	case float64:
+		return 4
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	print(1)
+	switch x.(type) {
+	case float64:
+		return 4
+	case int:
+		print(2)
+		panic(3)
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	print(1)
+	switch x.(type) {
+	case int:
+		print(2)
+		fallthrough
+	case float64:
+		return 4
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	print(1)
+	switch x.(type) {
+	case int:
+		print(2)
+		panic(3)
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	print(1)
+L:
+	switch x.(type) {
+	case int:
+		print(2)
+		panic(3)
+		break L // ERROR "unreachable code"
+	default:
+		return 4
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	print(1)
+	switch x.(type) {
+	default:
+		return 4
+		break // ERROR "unreachable code"
+	case int:
+		print(2)
+		panic(3)
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	print(1)
+L:
+	switch x.(type) {
+	case int:
+		print(2)
+		for {
+			break L
+		}
+	default:
+		return 4
+	}
+	println() // ok
+}
+
+// again, but without the leading print(1).
+// testing that everything works when the terminating statement is first.
+
+var _ = func() int {
+	println() // ok
+}
+
+var _ = func() int {
+	return 2
+	println() // ERROR "unreachable code"
+}
+
+var _ = func() int {
+L:
+	goto L
+	println() // ERROR "unreachable code"
+}
+
+var _ = func() int {
+	panic(2)
+	println() // ERROR "unreachable code"
+}
+
+// but only builtin panic
+var _ = func() int {
+	var panic = func(int) {}
+	panic(2)
+	println() // ok
+}
+
+var _ = func() int {
+	{
+		return 2
+		println() // ERROR "unreachable code"
+	}
+}
+
+var _ = func() int {
+	{
+		return 2
+	}
+	println() // ERROR "unreachable code"
+}
+
+var _ = func() int {
+L:
+	{
+		goto L
+		println() // ERROR "unreachable code"
+	}
+}
+
+var _ = func() int {
+L:
+	{
+		goto L
+	}
+	println() // ERROR "unreachable code"
+}
+
+var _ = func() int {
+	{
+		panic(2)
+		println() // ERROR "unreachable code"
+	}
+}
+
+var _ = func() int {
+	{
+		panic(2)
+	}
+	println() // ERROR "unreachable code"
+}
+
+var _ = func() int {
+	return 2
+	{ // ERROR "unreachable code"
+	}
+	println() // ok
+}
+
+var _ = func() int {
+L:
+	goto L
+	{ // ERROR "unreachable code"
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	panic(2)
+	{ // ERROR "unreachable code"
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	{
+		return 2
+		{ // ERROR "unreachable code"
+		}
+	}
+	println() // ok
+}
+
+var _ = func() int {
+L:
+	{
+		goto L
+		{ // ERROR "unreachable code"
+		}
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	{
+		panic(2)
+		{ // ERROR "unreachable code"
+		}
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	{
+		return 2
+	}
+	{ // ERROR "unreachable code"
+	}
+	println() // ok
+}
+
+var _ = func() int {
+L:
+	{
+		goto L
+	}
+	{ // ERROR "unreachable code"
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	{
+		panic(2)
+	}
+	{ // ERROR "unreachable code"
+	}
+	println() // ok
+}
+
+var _ = func() {
+	// goto without label used to panic
+	goto
+}
diff --git a/cmd/vet/testdata/method.go b/cmd/vet/testdata/method.go
new file mode 100644
index 0000000..52b500d
--- /dev/null
+++ b/cmd/vet/testdata/method.go
@@ -0,0 +1,22 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file contains tests for the canonical method checker.
+
+// This file contains the code to check canonical methods.
+
+package testdata
+
+import (
+	"fmt"
+)
+
+type MethodTest int
+
+func (t *MethodTest) Scan(x fmt.ScanState, c byte) { // ERROR "should have signature Scan"
+}
+
+type MethodTestInterface interface {
+	ReadByte() byte // ERROR "should have signature ReadByte"
+}
diff --git a/cmd/vet/testdata/nilfunc.go b/cmd/vet/testdata/nilfunc.go
new file mode 100644
index 0000000..2ce7bc8
--- /dev/null
+++ b/cmd/vet/testdata/nilfunc.go
@@ -0,0 +1,35 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package testdata
+
+func F() {}
+
+type T struct {
+	F func()
+}
+
+func (T) M() {}
+
+var Fv = F
+
+func Comparison() {
+	var t T
+	var fn func()
+	if fn == nil || Fv == nil || t.F == nil {
+		// no error; these func vars or fields may be nil
+	}
+	if F == nil { // ERROR "comparison of function F == nil is always false"
+		panic("can't happen")
+	}
+	if t.M == nil { // ERROR "comparison of function M == nil is always false"
+		panic("can't happen")
+	}
+	if F != nil { // ERROR "comparison of function F != nil is always true"
+		if t.M != nil { // ERROR "comparison of function M != nil is always true"
+			return
+		}
+	}
+	panic("can't happen")
+}
diff --git a/cmd/vet/testdata/print.go b/cmd/vet/testdata/print.go
new file mode 100644
index 0000000..3390a31
--- /dev/null
+++ b/cmd/vet/testdata/print.go
@@ -0,0 +1,342 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file contains tests for the printf checker.
+
+package testdata
+
+import (
+	"fmt"
+	"math"
+	"os"
+	"unsafe" // just for test case printing unsafe.Pointer
+)
+
+func UnsafePointerPrintfTest() {
+	var up unsafe.Pointer
+	fmt.Printf("%p, %x %X", up, up, up)
+}
+
+// Error methods that do not satisfy the Error interface and should be checked.
+type errorTest1 int
+
+func (errorTest1) Error(...interface{}) string {
+	return "hi"
+}
+
+type errorTest2 int // Analogous to testing's *T type.
+func (errorTest2) Error(...interface{}) {
+}
+
+type errorTest3 int
+
+func (errorTest3) Error() { // No return value.
+}
+
+type errorTest4 int
+
+func (errorTest4) Error() int { // Different return type.
+	return 3
+}
+
+type errorTest5 int
+
+func (errorTest5) error() { // niladic; don't complain if no args (was bug)
+}
+
+// This function never executes, but it serves as a simple test for the program.
+// Test with make test.
+func PrintfTests() {
+	var b bool
+	var i int
+	var r rune
+	var s string
+	var x float64
+	var p *int
+	var imap map[int]int
+	var fslice []float64
+	var c complex64
+	// Some good format/argtypes
+	fmt.Printf("")
+	fmt.Printf("%b %b %b", 3, i, x)
+	fmt.Printf("%c %c %c %c", 3, i, 'x', r)
+	fmt.Printf("%d %d %d", 3, i, imap)
+	fmt.Printf("%e %e %e %e", 3e9, x, fslice, c)
+	fmt.Printf("%E %E %E %E", 3e9, x, fslice, c)
+	fmt.Printf("%f %f %f %f", 3e9, x, fslice, c)
+	fmt.Printf("%F %F %F %F", 3e9, x, fslice, c)
+	fmt.Printf("%g %g %g %g", 3e9, x, fslice, c)
+	fmt.Printf("%G %G %G %G", 3e9, x, fslice, c)
+	fmt.Printf("%b %b %b %b", 3e9, x, fslice, c)
+	fmt.Printf("%o %o", 3, i)
+	fmt.Printf("%p %p", p, nil)
+	fmt.Printf("%q %q %q %q", 3, i, 'x', r)
+	fmt.Printf("%s %s %s", "hi", s, []byte{65})
+	fmt.Printf("%t %t", true, b)
+	fmt.Printf("%T %T", 3, i)
+	fmt.Printf("%U %U", 3, i)
+	fmt.Printf("%v %v", 3, i)
+	fmt.Printf("%x %x %x %x", 3, i, "hi", s)
+	fmt.Printf("%X %X %X %X", 3, i, "hi", s)
+	fmt.Printf("%.*s %d %g", 3, "hi", 23, 2.3)
+	fmt.Printf("%s", &stringerv)
+	fmt.Printf("%v", &stringerv)
+	fmt.Printf("%T", &stringerv)
+	fmt.Printf("%v", notstringerv)
+	fmt.Printf("%T", notstringerv)
+	fmt.Printf("%q", stringerarrayv)
+	fmt.Printf("%v", stringerarrayv)
+	fmt.Printf("%s", stringerarrayv)
+	fmt.Printf("%v", notstringerarrayv)
+	fmt.Printf("%T", notstringerarrayv)
+	fmt.Printf("%d", new(Formatter))
+	fmt.Printf("%*%", 2)               // Ridiculous but allowed.
+	fmt.Printf("%s", interface{}(nil)) // Nothing useful we can say.
+
+	fmt.Printf("%g", 1+2i)
+	// Some bad format/argTypes
+	fmt.Printf("%b", "hi")                     // ERROR "arg .hi. for printf verb %b of wrong type"
+	fmt.Printf("%t", c)                        // ERROR "arg c for printf verb %t of wrong type"
+	fmt.Printf("%t", 1+2i)                     // ERROR "arg 1 \+ 2i for printf verb %t of wrong type"
+	fmt.Printf("%c", 2.3)                      // ERROR "arg 2.3 for printf verb %c of wrong type"
+	fmt.Printf("%d", 2.3)                      // ERROR "arg 2.3 for printf verb %d of wrong type"
+	fmt.Printf("%e", "hi")                     // ERROR "arg .hi. for printf verb %e of wrong type"
+	fmt.Printf("%E", true)                     // ERROR "arg true for printf verb %E of wrong type"
+	fmt.Printf("%f", "hi")                     // ERROR "arg .hi. for printf verb %f of wrong type"
+	fmt.Printf("%F", 'x')                      // ERROR "arg 'x' for printf verb %F of wrong type"
+	fmt.Printf("%g", "hi")                     // ERROR "arg .hi. for printf verb %g of wrong type"
+	fmt.Printf("%g", imap)                     // ERROR "arg imap for printf verb %g of wrong type"
+	fmt.Printf("%G", i)                        // ERROR "arg i for printf verb %G of wrong type"
+	fmt.Printf("%o", x)                        // ERROR "arg x for printf verb %o of wrong type"
+	fmt.Printf("%p", 23)                       // ERROR "arg 23 for printf verb %p of wrong type"
+	fmt.Printf("%q", x)                        // ERROR "arg x for printf verb %q of wrong type"
+	fmt.Printf("%s", b)                        // ERROR "arg b for printf verb %s of wrong type"
+	fmt.Printf("%s", byte(65))                 // ERROR "arg byte\(65\) for printf verb %s of wrong type"
+	fmt.Printf("%t", 23)                       // ERROR "arg 23 for printf verb %t of wrong type"
+	fmt.Printf("%U", x)                        // ERROR "arg x for printf verb %U of wrong type"
+	fmt.Printf("%x", nil)                      // ERROR "arg nil for printf verb %x of wrong type"
+	fmt.Printf("%X", 2.3)                      // ERROR "arg 2.3 for printf verb %X of wrong type"
+	fmt.Printf("%s", stringerv)                // ERROR "arg stringerv for printf verb %s of wrong type"
+	fmt.Printf("%t", stringerv)                // ERROR "arg stringerv for printf verb %t of wrong type"
+	fmt.Printf("%q", notstringerv)             // ERROR "arg notstringerv for printf verb %q of wrong type"
+	fmt.Printf("%t", notstringerv)             // ERROR "arg notstringerv for printf verb %t of wrong type"
+	fmt.Printf("%t", stringerarrayv)           // ERROR "arg stringerarrayv for printf verb %t of wrong type"
+	fmt.Printf("%t", notstringerarrayv)        // ERROR "arg notstringerarrayv for printf verb %t of wrong type"
+	fmt.Printf("%q", notstringerarrayv)        // ERROR "arg notstringerarrayv for printf verb %q of wrong type"
+	fmt.Printf("%d", Formatter(true))          // correct (the type is responsible for formatting)
+	fmt.Printf("%s", nonemptyinterface)        // correct (the dynamic type of nonemptyinterface may be a stringer)
+	fmt.Printf("%.*s %d %g", 3, "hi", 23, 'x') // ERROR "arg 'x' for printf verb %g of wrong type"
+	fmt.Println()                              // not an error
+	fmt.Println("%s", "hi")                    // ERROR "possible formatting directive in Println call"
+	fmt.Printf("%s", "hi", 3)                  // ERROR "wrong number of args for format in Printf call"
+	_ = fmt.Sprintf("%"+("s"), "hi", 3)        // ERROR "wrong number of args for format in Sprintf call"
+	fmt.Printf("%s%%%d", "hi", 3)              // correct
+	fmt.Printf("%08s", "woo")                  // correct
+	fmt.Printf("% 8s", "woo")                  // correct
+	fmt.Printf("%.*d", 3, 3)                   // correct
+	fmt.Printf("%.*d", 3, 3, 3, 3)             // ERROR "wrong number of args for format in Printf call.*4 args"
+	fmt.Printf("%.*d", "hi", 3)                // ERROR "arg .hi. for \* in printf format not of type int"
+	fmt.Printf("%.*d", i, 3)                   // correct
+	fmt.Printf("%.*d", s, 3)                   // ERROR "arg s for \* in printf format not of type int"
+	fmt.Printf("%*%", 0.22)                    // ERROR "arg 0.22 for \* in printf format not of type int"
+	fmt.Printf("%q %q", multi()...)            // ok
+	fmt.Printf("%#q", `blah`)                  // ok
+	printf("now is the time", "buddy")         // ERROR "no formatting directive"
+	Printf("now is the time", "buddy")         // ERROR "no formatting directive"
+	Printf("hi")                               // ok
+	const format = "%s %s\n"
+	Printf(format, "hi", "there")
+	Printf(format, "hi")              // ERROR "missing argument for Printf..%s..: format reads arg 2, have only 1"
+	Printf("%s %d %.3v %q", "str", 4) // ERROR "missing argument for Printf..%.3v..: format reads arg 3, have only 2"
+	f := new(stringer)
+	f.Warn(0, "%s", "hello", 3)  // ERROR "possible formatting directive in Warn call"
+	f.Warnf(0, "%s", "hello", 3) // ERROR "wrong number of args for format in Warnf call"
+	f.Warnf(0, "%r", "hello")    // ERROR "unrecognized printf verb"
+	f.Warnf(0, "%#s", "hello")   // ERROR "unrecognized printf flag"
+	Printf("d%", 2)              // ERROR "missing verb at end of format string in Printf call"
+	Printf("%d", percentDV)
+	Printf("%d", &percentDV)
+	Printf("%d", notPercentDV)  // ERROR "arg notPercentDV for printf verb %d of wrong type"
+	Printf("%d", &notPercentDV) // ERROR "arg &notPercentDV for printf verb %d of wrong type"
+	Printf("%p", &notPercentDV) // Works regardless: we print it as a pointer.
+	Printf("%s", percentSV)
+	Printf("%s", &percentSV)
+	// Good argument reorderings.
+	Printf("%[1]d", 3)
+	Printf("%[1]*d", 3, 1)
+	Printf("%[2]*[1]d", 1, 3)
+	Printf("%[2]*.[1]*[3]d", 2, 3, 4)
+	fmt.Fprintf(os.Stderr, "%[2]*.[1]*[3]d", 2, 3, 4) // Use Fprintf to make sure we count arguments correctly.
+	// Bad argument reorderings.
+	Printf("%[xd", 3)                    // ERROR "illegal syntax for printf argument index"
+	Printf("%[x]d", 3)                   // ERROR "illegal syntax for printf argument index"
+	Printf("%[3]*s", "hi", 2)            // ERROR "missing argument for Printf.* reads arg 3, have only 2"
+	_ = fmt.Sprintf("%[3]d", 2)          // ERROR "missing argument for Sprintf.* reads arg 3, have only 1"
+	Printf("%[2]*.[1]*[3]d", 2, "hi", 4) // ERROR "arg .hi. for \* in printf format not of type int"
+	Printf("%[0]s", "arg1")              // ERROR "index value \[0\] for Printf.*; indexes start at 1"
+	Printf("%[0]d", 1)                   // ERROR "index value \[0\] for Printf.*; indexes start at 1"
+	// Something that satisfies the error interface.
+	var e error
+	fmt.Println(e.Error()) // ok
+	// Something that looks like an error interface but isn't, such as the (*T).Error method
+	// in the testing package.
+	var et1 errorTest1
+	fmt.Println(et1.Error())        // ERROR "no args in Error call"
+	fmt.Println(et1.Error("hi"))    // ok
+	fmt.Println(et1.Error("%d", 3)) // ERROR "possible formatting directive in Error call"
+	var et2 errorTest2
+	et2.Error()        // ERROR "no args in Error call"
+	et2.Error("hi")    // ok, not an error method.
+	et2.Error("%d", 3) // ERROR "possible formatting directive in Error call"
+	var et3 errorTest3
+	et3.Error() // ok, not an error method.
+	var et4 errorTest4
+	et4.Error() // ok, not an error method.
+	var et5 errorTest5
+	et5.error() // ok, not an error method.
+	// Bug: used to recur forever.
+	Printf("%p %x", recursiveStructV, recursiveStructV.next)
+	Printf("%p %x", recursiveStruct1V, recursiveStruct1V.next)
+	Printf("%p %x", recursiveSliceV, recursiveSliceV)
+	Printf("%p %x", recursiveMapV, recursiveMapV)
+	// Special handling for Log.
+	math.Log(3)  // OK
+	Log(3)       // OK
+	Log("%d", 3) // ERROR "possible formatting directive in Log call"
+	Logf("%d", 3)
+	Logf("%d", "hi") // ERROR "arg .hi. for printf verb %d of wrong type: untyped string"
+
+}
+
+// Printf is used by the test so we must declare it.
+func Printf(format string, args ...interface{}) {
+	panic("don't call - testing only")
+}
+
+// printf is used by the test so we must declare it.
+func printf(format string, args ...interface{}) {
+	panic("don't call - testing only")
+}
+
+// multi is used by the test.
+func multi() []interface{} {
+	panic("don't call - testing only")
+}
+
+type stringer float64
+
+var stringerv stringer
+
+func (*stringer) String() string {
+	return "string"
+}
+
+func (*stringer) Warn(int, ...interface{}) string {
+	return "warn"
+}
+
+func (*stringer) Warnf(int, string, ...interface{}) string {
+	return "warnf"
+}
+
+type notstringer struct {
+	f float64
+}
+
+var notstringerv notstringer
+
+type stringerarray [4]float64
+
+func (stringerarray) String() string {
+	return "string"
+}
+
+var stringerarrayv stringerarray
+
+type notstringerarray [4]float64
+
+var notstringerarrayv notstringerarray
+
+var nonemptyinterface = interface {
+	f()
+}(nil)
+
+// A data type we can print with "%d".
+type percentDStruct struct {
+	a int
+	b []byte
+	c *float64
+}
+
+var percentDV percentDStruct
+
+// A data type we cannot print correctly with "%d".
+type notPercentDStruct struct {
+	a int
+	b []byte
+	c bool
+}
+
+var notPercentDV notPercentDStruct
+
+// A data type we can print with "%s".
+type percentSStruct struct {
+	a string
+	b []byte
+	c stringerarray
+}
+
+var percentSV percentSStruct
+
+type recursiveStringer int
+
+func (s recursiveStringer) String() string {
+	_ = fmt.Sprintf("%d", s)
+	_ = fmt.Sprintf("%#v", s)
+	_ = fmt.Sprintf("%v", s)  // ERROR "arg s for printf causes recursive call to String method"
+	_ = fmt.Sprintf("%v", &s) // ERROR "arg &s for printf causes recursive call to String method"
+	_ = fmt.Sprintf("%T", s)  // ok; does not recursively call String
+	return fmt.Sprintln(s)    // ERROR "arg s for print causes recursive call to String method"
+}
+
+type recursivePtrStringer int
+
+func (p *recursivePtrStringer) String() string {
+	_ = fmt.Sprintf("%v", *p)
+	return fmt.Sprintln(p) // ERROR "arg p for print causes recursive call to String method"
+}
+
+type Formatter bool
+
+func (*Formatter) Format(fmt.State, rune) {
+}
+
+type RecursiveSlice []RecursiveSlice
+
+var recursiveSliceV = &RecursiveSlice{}
+
+type RecursiveMap map[int]RecursiveMap
+
+var recursiveMapV = make(RecursiveMap)
+
+type RecursiveStruct struct {
+	next *RecursiveStruct
+}
+
+var recursiveStructV = &RecursiveStruct{}
+
+type RecursiveStruct1 struct {
+	next *Recursive2Struct
+}
+
+type RecursiveStruct2 struct {
+	next *Recursive1Struct
+}
+
+var recursiveStruct1V = &RecursiveStruct1{}
+
+// Fix for issue 7149: Missing return type on String method caused fault.
+func (int) String() {
+	return ""
+}
diff --git a/cmd/vet/testdata/rangeloop.go b/cmd/vet/testdata/rangeloop.go
new file mode 100644
index 0000000..37b5940
--- /dev/null
+++ b/cmd/vet/testdata/rangeloop.go
@@ -0,0 +1,59 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file contains tests for the rangeloop checker.
+
+package testdata
+
+func RangeLoopTests() {
+	var s []int
+	for i, v := range s {
+		go func() {
+			println(i) // ERROR "range variable i captured by func literal"
+			println(v) // ERROR "range variable v captured by func literal"
+		}()
+	}
+	for i, v := range s {
+		defer func() {
+			println(i) // ERROR "range variable i captured by func literal"
+			println(v) // ERROR "range variable v captured by func literal"
+		}()
+	}
+	for i := range s {
+		go func() {
+			println(i) // ERROR "range variable i captured by func literal"
+		}()
+	}
+	for _, v := range s {
+		go func() {
+			println(v) // ERROR "range variable v captured by func literal"
+		}()
+	}
+	for i, v := range s {
+		go func() {
+			println(i, v)
+		}()
+		println("unfortunately, we don't catch the error above because of this statement")
+	}
+	for i, v := range s {
+		go func(i, v int) {
+			println(i, v)
+		}(i, v)
+	}
+	for i, v := range s {
+		i, v := i, v
+		go func() {
+			println(i, v)
+		}()
+	}
+	// If the key of the range statement is not an identifier
+	// the code should not panic (it used to).
+	var x [2]int
+	var f int
+	for x[0], f = range s {
+		go func() {
+			_ = f // ERROR "range variable f captured by func literal"
+		}()
+	}
+}
diff --git a/cmd/vet/testdata/shadow.go b/cmd/vet/testdata/shadow.go
new file mode 100644
index 0000000..34a6806
--- /dev/null
+++ b/cmd/vet/testdata/shadow.go
@@ -0,0 +1,54 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file contains tests for the shadowed variable checker.
+// Some of these errors are caught by the compiler (shadowed return parameters for example)
+// but are nonetheless useful tests.
+
+package testdata
+
+import "os"
+
+func ShadowRead(f *os.File, buf []byte) (err error) {
+	var x int
+	if f != nil {
+		err := 3 // OK - different type.
+		_ = err
+	}
+	if f != nil {
+		_, err := f.Read(buf) // ERROR "declaration of err shadows declaration at testdata/shadow.go:13"
+		if err != nil {
+			return err
+		}
+		i := 3 // OK
+		_ = i
+	}
+	if f != nil {
+		var _, err = f.Read(buf) // ERROR "declaration of err shadows declaration at testdata/shadow.go:13"
+		if err != nil {
+			return err
+		}
+	}
+	for i := 0; i < 10; i++ {
+		i := i // OK: obviously intentional idiomatic redeclaration
+		go func() {
+			println(i)
+		}()
+	}
+	var shadowTemp interface{}
+	switch shadowTemp := shadowTemp.(type) { // OK: obviously intentional idiomatic redeclaration
+	case int:
+		println("OK")
+		_ = shadowTemp
+	}
+	if shadowTemp := shadowTemp; true { // OK: obviously intentional idiomatic redeclaration
+		var f *os.File // OK because f is not mentioned later in the function.
+		// The declaration of x is a shadow because x is mentioned below.
+		var x int // ERROR "declaration of x shadows declaration at testdata/shadow.go:14"
+		_, _, _ = x, f, shadowTemp
+	}
+	// Use a couple of variables to trigger shadowing errors.
+	_, _ = err, x
+	return
+}
diff --git a/cmd/vet/testdata/shift.go b/cmd/vet/testdata/shift.go
new file mode 100644
index 0000000..6624f09
--- /dev/null
+++ b/cmd/vet/testdata/shift.go
@@ -0,0 +1,78 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file contains tests for the suspicious shift checker.
+
+package testdata
+
+func ShiftTest() {
+	var i8 int8
+	_ = i8 << 7
+	_ = (i8 + 1) << 8 // ERROR "\(i8 \+ 1\) too small for shift of 8"
+	_ = i8 << (7 + 1) // ERROR "i8 too small for shift of 8"
+	_ = i8 >> 8       // ERROR "i8 too small for shift of 8"
+	i8 <<= 8          // ERROR "i8 too small for shift of 8"
+	i8 >>= 8          // ERROR "i8 too small for shift of 8"
+	var i16 int16
+	_ = i16 << 15
+	_ = i16 << 16 // ERROR "i16 too small for shift of 16"
+	_ = i16 >> 16 // ERROR "i16 too small for shift of 16"
+	i16 <<= 16    // ERROR "i16 too small for shift of 16"
+	i16 >>= 16    // ERROR "i16 too small for shift of 16"
+	var i32 int32
+	_ = i32 << 31
+	_ = i32 << 32 // ERROR "i32 too small for shift of 32"
+	_ = i32 >> 32 // ERROR "i32 too small for shift of 32"
+	i32 <<= 32    // ERROR "i32 too small for shift of 32"
+	i32 >>= 32    // ERROR "i32 too small for shift of 32"
+	var i64 int64
+	_ = i64 << 63
+	_ = i64 << 64 // ERROR "i64 too small for shift of 64"
+	_ = i64 >> 64 // ERROR "i64 too small for shift of 64"
+	i64 <<= 64    // ERROR "i64 too small for shift of 64"
+	i64 >>= 64    // ERROR "i64 too small for shift of 64"
+	var u8 uint8
+	_ = u8 << 7
+	_ = u8 << 8 // ERROR "u8 too small for shift of 8"
+	_ = u8 >> 8 // ERROR "u8 too small for shift of 8"
+	u8 <<= 8    // ERROR "u8 too small for shift of 8"
+	u8 >>= 8    // ERROR "u8 too small for shift of 8"
+	var u16 uint16
+	_ = u16 << 15
+	_ = u16 << 16 // ERROR "u16 too small for shift of 16"
+	_ = u16 >> 16 // ERROR "u16 too small for shift of 16"
+	u16 <<= 16    // ERROR "u16 too small for shift of 16"
+	u16 >>= 16    // ERROR "u16 too small for shift of 16"
+	var u32 uint32
+	_ = u32 << 31
+	_ = u32 << 32 // ERROR "u32 too small for shift of 32"
+	_ = u32 >> 32 // ERROR "u32 too small for shift of 32"
+	u32 <<= 32    // ERROR "u32 too small for shift of 32"
+	u32 >>= 32    // ERROR "u32 too small for shift of 32"
+	var u64 uint64
+	_ = u64 << 63
+	_ = u64 << 64  // ERROR "u64 too small for shift of 64"
+	_ = u64 >> 64  // ERROR "u64 too small for shift of 64"
+	u64 <<= 64     // ERROR "u64 too small for shift of 64"
+	u64 >>= 64     // ERROR "u64 too small for shift of 64"
+	_ = u64 << u64 // Non-constant shifts should succeed.
+	var i int
+	_ = i << 31
+	_ = i << 32 // ERROR "i might be too small for shift of 32"
+	_ = i >> 32 // ERROR "i might be too small for shift of 32"
+	i <<= 32    // ERROR "i might be too small for shift of 32"
+	i >>= 32    // ERROR "i might be too small for shift of 32"
+	var u uint
+	_ = u << 31
+	_ = u << 32 // ERROR "u might be too small for shift of 32"
+	_ = u >> 32 // ERROR "u might be too small for shift of 32"
+	u <<= 32    // ERROR "u might be too small for shift of 32"
+	u >>= 32    // ERROR "u might be too small for shift of 32"
+	var p uintptr
+	_ = p << 31
+	_ = p << 32 // ERROR "p might be too small for shift of 32"
+	_ = p >> 32 // ERROR "p might be too small for shift of 32"
+	p <<= 32    // ERROR "p might be too small for shift of 32"
+	p >>= 32    // ERROR "p might be too small for shift of 32"
+}
diff --git a/cmd/vet/testdata/structtag.go b/cmd/vet/testdata/structtag.go
new file mode 100644
index 0000000..6878f56
--- /dev/null
+++ b/cmd/vet/testdata/structtag.go
@@ -0,0 +1,36 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file contains the test for canonical struct tags.
+
+package testdata
+
+type StructTagTest struct {
+	A   int "hello"            // ERROR "not compatible with reflect.StructTag.Get: bad syntax for struct tag pair"
+	B   int "\tx:\"y\""        // ERROR "not compatible with reflect.StructTag.Get: bad syntax for struct tag key"
+	C   int "x:\"y\"\tx:\"y\"" // ERROR "not compatible with reflect.StructTag.Get"
+	D   int "x:`y`"            // ERROR "not compatible with reflect.StructTag.Get: bad syntax for struct tag value"
+	E   int "ct\brl:\"char\""  // ERROR "not compatible with reflect.StructTag.Get: bad syntax for struct tag pair"
+	F   int `:"emptykey"`      // ERROR "not compatible with reflect.StructTag.Get: bad syntax for struct tag key"
+	G   int `x:"noEndQuote`    // ERROR "not compatible with reflect.StructTag.Get: bad syntax for struct tag value"
+	H   int `x:"trunc\x0"`     // ERROR "not compatible with reflect.StructTag.Get: bad syntax for struct tag value"
+	OK0 int `x:"y" u:"v" w:""`
+	OK1 int `x:"y:z" u:"v" w:""` // note multiple colons.
+	OK2 int "k0:\"values contain spaces\" k1:\"literal\ttabs\" k2:\"and\\tescaped\\tabs\""
+	OK3 int `under_scores:"and" CAPS:"ARE_OK"`
+}
+
+type UnexportedEncodingTagTest struct {
+	x int `json:"xx"` // ERROR "struct field x has json tag but is not exported"
+	y int `xml:"yy"`  // ERROR "struct field y has xml tag but is not exported"
+	z int
+	A int `json:"aa" xml:"bb"`
+}
+
+type unexp struct{}
+
+type JSONEmbeddedField struct {
+	UnexportedEncodingTagTest `is:"embedded"`
+	unexp                     `is:"embedded,notexported" json:"unexp"` // OK for now, see issue 7363
+}
diff --git a/cmd/vet/testdata/tagtest/file1.go b/cmd/vet/testdata/tagtest/file1.go
new file mode 100644
index 0000000..22a1509
--- /dev/null
+++ b/cmd/vet/testdata/tagtest/file1.go
@@ -0,0 +1,10 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build testtag
+
+package main
+
+func main() {
+}
diff --git a/cmd/vet/testdata/tagtest/file2.go b/cmd/vet/testdata/tagtest/file2.go
new file mode 100644
index 0000000..ba7dd91
--- /dev/null
+++ b/cmd/vet/testdata/tagtest/file2.go
@@ -0,0 +1,10 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !testtag
+
+package main
+
+func ignore() {
+}
diff --git a/cmd/vet/testdata/unsafeptr.go b/cmd/vet/testdata/unsafeptr.go
new file mode 100644
index 0000000..8f64030
--- /dev/null
+++ b/cmd/vet/testdata/unsafeptr.go
@@ -0,0 +1,61 @@
+// Copyright 2014 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package testdata
+
+import (
+	"reflect"
+	"unsafe"
+)
+
+func f() {
+	var x unsafe.Pointer
+	var y uintptr
+	x = unsafe.Pointer(y) // ERROR "possible misuse of unsafe.Pointer"
+	y = uintptr(x)
+
+	// only allowed pointer arithmetic is ptr +/- num.
+	// num+ptr is technically okay but still flagged: write ptr+num instead.
+	x = unsafe.Pointer(uintptr(x) + 1)
+	x = unsafe.Pointer(1 + uintptr(x))          // ERROR "possible misuse of unsafe.Pointer"
+	x = unsafe.Pointer(uintptr(x) + uintptr(x)) // ERROR "possible misuse of unsafe.Pointer"
+	x = unsafe.Pointer(uintptr(x) - 1)
+	x = unsafe.Pointer(1 - uintptr(x)) // ERROR "possible misuse of unsafe.Pointer"
+
+	// certain uses of reflect are okay
+	var v reflect.Value
+	x = unsafe.Pointer(v.Pointer())
+	x = unsafe.Pointer(v.UnsafeAddr())
+	var s1 *reflect.StringHeader
+	x = unsafe.Pointer(s1.Data)
+	var s2 *reflect.SliceHeader
+	x = unsafe.Pointer(s2.Data)
+	var s3 reflect.StringHeader
+	x = unsafe.Pointer(s3.Data) // ERROR "possible misuse of unsafe.Pointer"
+	var s4 reflect.SliceHeader
+	x = unsafe.Pointer(s4.Data) // ERROR "possible misuse of unsafe.Pointer"
+
+	// but only in reflect
+	var vv V
+	x = unsafe.Pointer(vv.Pointer())    // ERROR "possible misuse of unsafe.Pointer"
+	x = unsafe.Pointer(vv.UnsafeAddr()) // ERROR "possible misuse of unsafe.Pointer"
+	var ss1 *StringHeader
+	x = unsafe.Pointer(ss1.Data) // ERROR "possible misuse of unsafe.Pointer"
+	var ss2 *SliceHeader
+	x = unsafe.Pointer(ss2.Data) // ERROR "possible misuse of unsafe.Pointer"
+
+}
+
+type V interface {
+	Pointer() uintptr
+	UnsafeAddr() uintptr
+}
+
+type StringHeader struct {
+	Data uintptr
+}
+
+type SliceHeader struct {
+	Data uintptr
+}
diff --git a/cmd/vet/testdata/unused.go b/cmd/vet/testdata/unused.go
new file mode 100644
index 0000000..d50f659
--- /dev/null
+++ b/cmd/vet/testdata/unused.go
@@ -0,0 +1,29 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file contains tests for the unusedresult checker.
+
+package testdata
+
+import (
+	"bytes"
+	"errors"
+	"fmt"
+)
+
+func _() {
+	fmt.Errorf("") // ERROR "result of fmt.Errorf call not used"
+	_ = fmt.Errorf("")
+
+	errors.New("") // ERROR "result of errors.New call not used"
+
+	err := errors.New("")
+	err.Error() // ERROR "result of \(error\).Error call not used"
+
+	var buf bytes.Buffer
+	buf.String() // ERROR "result of \(bytes.Buffer\).String call not used"
+
+	fmt.Sprint("")  // ERROR "result of fmt.Sprint call not used"
+	fmt.Sprintf("") // ERROR "result of fmt.Sprintf call not used"
+}
diff --git a/cmd/vet/types.go b/cmd/vet/types.go
new file mode 100644
index 0000000..084be85
--- /dev/null
+++ b/cmd/vet/types.go
@@ -0,0 +1,369 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file contains the pieces of the tool that use typechecking from the go/types package.
+
+package main
+
+import (
+	"go/ast"
+	"go/token"
+
+	"golang.org/x/tools/go/types"
+)
+
+// imports is the canonical map of imported packages we need for typechecking.
+// It is created during initialization.
+var imports = make(map[string]*types.Package)
+
+var (
+	errorType     *types.Interface
+	stringerType  *types.Interface // possibly nil
+	formatterType *types.Interface // possibly nil
+)
+
+func init() {
+	errorType = types.Universe.Lookup("error").Type().Underlying().(*types.Interface)
+
+	if typ := importType("fmt", "Stringer"); typ != nil {
+		stringerType = typ.Underlying().(*types.Interface)
+	}
+
+	if typ := importType("fmt", "Formatter"); typ != nil {
+		formatterType = typ.Underlying().(*types.Interface)
+	}
+}
+
+// importType returns the type denoted by the qualified identifier
+// path.name, and adds the respective package to the imports map
+// as a side effect. In case of an error, importType returns nil.
+func importType(path, name string) types.Type {
+	pkg, err := types.DefaultImport(imports, path)
+	if err != nil {
+		// This can happen if the package at path hasn't been compiled yet.
+		warnf("import failed: %v", err)
+		return nil
+	}
+	if obj, ok := pkg.Scope().Lookup(name).(*types.TypeName); ok {
+		return obj.Type()
+	}
+	warnf("invalid type name %q", name)
+	return nil
+}
+
+func (pkg *Package) check(fs *token.FileSet, astFiles []*ast.File) error {
+	pkg.defs = make(map[*ast.Ident]types.Object)
+	pkg.uses = make(map[*ast.Ident]types.Object)
+	pkg.selectors = make(map[*ast.SelectorExpr]*types.Selection)
+	pkg.spans = make(map[types.Object]Span)
+	pkg.types = make(map[ast.Expr]types.TypeAndValue)
+	config := types.Config{
+		// We provide the same packages map for all imports to ensure
+		// that everybody sees identical packages for the given paths.
+		Packages: imports,
+		// By providing a Config with our own error function, it will continue
+		// past the first error. There is no need for that function to do anything.
+		Error: func(error) {},
+	}
+	info := &types.Info{
+		Selections: pkg.selectors,
+		Types:      pkg.types,
+		Defs:       pkg.defs,
+		Uses:       pkg.uses,
+	}
+	typesPkg, err := config.Check(pkg.path, fs, astFiles, info)
+	pkg.typesPkg = typesPkg
+	// update spans
+	for id, obj := range pkg.defs {
+		pkg.growSpan(id, obj)
+	}
+	for id, obj := range pkg.uses {
+		pkg.growSpan(id, obj)
+	}
+	return err
+}
+
+// isStruct reports whether the composite literal c is a struct.
+// If it is not (probably a struct), it returns a printable form of the type.
+func (pkg *Package) isStruct(c *ast.CompositeLit) (bool, string) {
+	// Check that the CompositeLit's type is a slice or array (which needs no field keys), if possible.
+	typ := pkg.types[c].Type
+	// If it's a named type, pull out the underlying type. If it's not, the Underlying
+	// method returns the type itself.
+	actual := typ
+	if actual != nil {
+		actual = actual.Underlying()
+	}
+	if actual == nil {
+		// No type information available. Assume true, so we do the check.
+		return true, ""
+	}
+	switch actual.(type) {
+	case *types.Struct:
+		return true, typ.String()
+	default:
+		return false, ""
+	}
+}
+
+// matchArgType reports an error if printf verb t is not appropriate
+// for operand arg.
+//
+// typ is used only for recursive calls; external callers must supply nil.
+//
+// (Recursion arises from the compound types {map,chan,slice} which
+// may be printed with %d etc. if that is appropriate for their element
+// types.)
+func (f *File) matchArgType(t printfArgType, typ types.Type, arg ast.Expr) bool {
+	return f.matchArgTypeInternal(t, typ, arg, make(map[types.Type]bool))
+}
+
+// matchArgTypeInternal is the internal version of matchArgType. It carries a map
+// remembering what types are in progress so we don't recur when faced with recursive
+// types or mutually recursive types.
+func (f *File) matchArgTypeInternal(t printfArgType, typ types.Type, arg ast.Expr, inProgress map[types.Type]bool) bool {
+	// %v, %T accept any argument type.
+	if t == anyType {
+		return true
+	}
+	if typ == nil {
+		// external call
+		typ = f.pkg.types[arg].Type
+		if typ == nil {
+			return true // probably a type check problem
+		}
+	}
+	// If the type implements fmt.Formatter, we have nothing to check.
+	// formatterTyp may be nil - be conservative and check for Format method in that case.
+	if formatterType != nil && types.Implements(typ, formatterType) || f.hasMethod(typ, "Format") {
+		return true
+	}
+	// If we can use a string, might arg (dynamically) implement the Stringer or Error interface?
+	if t&argString != 0 {
+		if types.AssertableTo(errorType, typ) || stringerType != nil && types.AssertableTo(stringerType, typ) {
+			return true
+		}
+	}
+
+	typ = typ.Underlying()
+	if inProgress[typ] {
+		// We're already looking at this type. The call that started it will take care of it.
+		return true
+	}
+	inProgress[typ] = true
+
+	switch typ := typ.(type) {
+	case *types.Signature:
+		return t&argPointer != 0
+
+	case *types.Map:
+		// Recur: map[int]int matches %d.
+		return t&argPointer != 0 ||
+			(f.matchArgTypeInternal(t, typ.Key(), arg, inProgress) && f.matchArgTypeInternal(t, typ.Elem(), arg, inProgress))
+
+	case *types.Chan:
+		return t&argPointer != 0
+
+	case *types.Array:
+		// Same as slice.
+		if types.Identical(typ.Elem().Underlying(), types.Typ[types.Byte]) && t&argString != 0 {
+			return true // %s matches []byte
+		}
+		// Recur: []int matches %d.
+		return t&argPointer != 0 || f.matchArgTypeInternal(t, typ.Elem().Underlying(), arg, inProgress)
+
+	case *types.Slice:
+		// Same as array.
+		if types.Identical(typ.Elem().Underlying(), types.Typ[types.Byte]) && t&argString != 0 {
+			return true // %s matches []byte
+		}
+		// Recur: []int matches %d. But watch out for
+		//	type T []T
+		// If the element is a pointer type (type T[]*T), it's handled fine by the Pointer case below.
+		return t&argPointer != 0 || f.matchArgTypeInternal(t, typ.Elem(), arg, inProgress)
+
+	case *types.Pointer:
+		// Ugly, but dealing with an edge case: a known pointer to an invalid type,
+		// probably something from a failed import.
+		if typ.Elem().String() == "invalid type" {
+			if *verbose {
+				f.Warnf(arg.Pos(), "printf argument %v is pointer to invalid or unknown type", f.gofmt(arg))
+			}
+			return true // special case
+		}
+		// If it's actually a pointer with %p, it prints as one.
+		if t == argPointer {
+			return true
+		}
+		// If it's pointer to struct, that's equivalent in our analysis to whether we can print the struct.
+		if str, ok := typ.Elem().Underlying().(*types.Struct); ok {
+			return f.matchStructArgType(t, str, arg, inProgress)
+		}
+		// The rest can print with %p as pointers, or as integers with %x etc.
+		return t&(argInt|argPointer) != 0
+
+	case *types.Struct:
+		return f.matchStructArgType(t, typ, arg, inProgress)
+
+	case *types.Interface:
+		// If the static type of the argument is empty interface, there's little we can do.
+		// Example:
+		//	func f(x interface{}) { fmt.Printf("%s", x) }
+		// Whether x is valid for %s depends on the type of the argument to f. One day
+		// we will be able to do better. For now, we assume that empty interface is OK
+		// but non-empty interfaces, with Stringer and Error handled above, are errors.
+		return typ.NumMethods() == 0
+
+	case *types.Basic:
+		switch typ.Kind() {
+		case types.UntypedBool,
+			types.Bool:
+			return t&argBool != 0
+
+		case types.UntypedInt,
+			types.Int,
+			types.Int8,
+			types.Int16,
+			types.Int32,
+			types.Int64,
+			types.Uint,
+			types.Uint8,
+			types.Uint16,
+			types.Uint32,
+			types.Uint64,
+			types.Uintptr:
+			return t&argInt != 0
+
+		case types.UntypedFloat,
+			types.Float32,
+			types.Float64:
+			return t&argFloat != 0
+
+		case types.UntypedComplex,
+			types.Complex64,
+			types.Complex128:
+			return t&argComplex != 0
+
+		case types.UntypedString,
+			types.String:
+			return t&argString != 0
+
+		case types.UnsafePointer:
+			return t&(argPointer|argInt) != 0
+
+		case types.UntypedRune:
+			return t&(argInt|argRune) != 0
+
+		case types.UntypedNil:
+			return t&argPointer != 0 // TODO?
+
+		case types.Invalid:
+			if *verbose {
+				f.Warnf(arg.Pos(), "printf argument %v has invalid or unknown type", f.gofmt(arg))
+			}
+			return true // Probably a type check problem.
+		}
+		panic("unreachable")
+	}
+
+	return false
+}
+
+// hasBasicType reports whether x's type is a types.Basic with the given kind.
+func (f *File) hasBasicType(x ast.Expr, kind types.BasicKind) bool {
+	t := f.pkg.types[x].Type
+	if t != nil {
+		t = t.Underlying()
+	}
+	b, ok := t.(*types.Basic)
+	return ok && b.Kind() == kind
+}
+
+// matchStructArgType reports whether all the elements of the struct match the expected
+// type. For instance, with "%d" all the elements must be printable with the "%d" format.
+func (f *File) matchStructArgType(t printfArgType, typ *types.Struct, arg ast.Expr, inProgress map[types.Type]bool) bool {
+	for i := 0; i < typ.NumFields(); i++ {
+		if !f.matchArgTypeInternal(t, typ.Field(i).Type(), arg, inProgress) {
+			return false
+		}
+	}
+	return true
+}
+
+// numArgsInSignature tells how many formal arguments the function type
+// being called has.
+func (f *File) numArgsInSignature(call *ast.CallExpr) int {
+	// Check the type of the function or method declaration
+	typ := f.pkg.types[call.Fun].Type
+	if typ == nil {
+		return 0
+	}
+	// The type must be a signature, but be sure for safety.
+	sig, ok := typ.(*types.Signature)
+	if !ok {
+		return 0
+	}
+	return sig.Params().Len()
+}
+
+// isErrorMethodCall reports whether the call is of a method with signature
+//	func Error() string
+// where "string" is the universe's string type. We know the method is called "Error".
+func (f *File) isErrorMethodCall(call *ast.CallExpr) bool {
+	typ := f.pkg.types[call].Type
+	if typ != nil {
+		// We know it's called "Error", so just check the function signature
+		// (stringerType has exactly one method, String).
+		if stringerType != nil && stringerType.NumMethods() == 1 {
+			return types.Identical(f.pkg.types[call.Fun].Type, stringerType.Method(0).Type())
+		}
+	}
+	// Without types, we can still check by hand.
+	// Is it a selector expression? Otherwise it's a function call, not a method call.
+	sel, ok := call.Fun.(*ast.SelectorExpr)
+	if !ok {
+		return false
+	}
+	// The package is type-checked, so if there are no arguments, we're done.
+	if len(call.Args) > 0 {
+		return false
+	}
+	// Check the type of the method declaration
+	typ = f.pkg.types[sel].Type
+	if typ == nil {
+		return false
+	}
+	// The type must be a signature, but be sure for safety.
+	sig, ok := typ.(*types.Signature)
+	if !ok {
+		return false
+	}
+	// There must be a receiver for it to be a method call. Otherwise it is
+	// a function, not something that satisfies the error interface.
+	if sig.Recv() == nil {
+		return false
+	}
+	// There must be no arguments. Already verified by type checking, but be thorough.
+	if sig.Params().Len() > 0 {
+		return false
+	}
+	// Finally the real questions.
+	// There must be one result.
+	if sig.Results().Len() != 1 {
+		return false
+	}
+	// It must have return type "string" from the universe.
+	return sig.Results().At(0).Type() == types.Typ[types.String]
+}
+
+// hasMethod reports whether the type contains a method with the given name.
+// It is part of the workaround for Formatters and should be deleted when
+// that workaround is no longer necessary.
+// TODO: This could be better once issue 6259 is fixed.
+func (f *File) hasMethod(typ types.Type, name string) bool {
+	// assume we have an addressable variable of type typ
+	obj, _, _ := types.LookupFieldOrMethod(typ, true, f.pkg.typesPkg, name)
+	_, ok := obj.(*types.Func)
+	return ok
+}
diff --git a/cmd/vet/unsafeptr.go b/cmd/vet/unsafeptr.go
new file mode 100644
index 0000000..ca15f72
--- /dev/null
+++ b/cmd/vet/unsafeptr.go
@@ -0,0 +1,98 @@
+// Copyright 2014 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Check for invalid uintptr -> unsafe.Pointer conversions.
+
+package main
+
+import (
+	"go/ast"
+	"go/token"
+
+	"golang.org/x/tools/go/types"
+)
+
+func init() {
+	register("unsafeptr",
+		"check for misuse of unsafe.Pointer",
+		checkUnsafePointer,
+		callExpr)
+}
+
+func checkUnsafePointer(f *File, node ast.Node) {
+	x := node.(*ast.CallExpr)
+	if len(x.Args) != 1 {
+		return
+	}
+	if f.hasBasicType(x.Fun, types.UnsafePointer) && f.hasBasicType(x.Args[0], types.Uintptr) && !f.isSafeUintptr(x.Args[0]) {
+		f.Badf(x.Pos(), "possible misuse of unsafe.Pointer")
+	}
+}
+
+// isSafeUintptr reports whether x - already known to be a uintptr -
+// is safe to convert to unsafe.Pointer. It is safe if x is itself derived
+// directly from an unsafe.Pointer via conversion and pointer arithmetic
+// or if x is the result of reflect.Value.Pointer or reflect.Value.UnsafeAddr
+// or obtained from the Data field of a *reflect.SliceHeader or *reflect.StringHeader.
+func (f *File) isSafeUintptr(x ast.Expr) bool {
+	switch x := x.(type) {
+	case *ast.ParenExpr:
+		return f.isSafeUintptr(x.X)
+
+	case *ast.SelectorExpr:
+		switch x.Sel.Name {
+		case "Data":
+			// reflect.SliceHeader and reflect.StringHeader are okay,
+			// but only if they are pointing at a real slice or string.
+			// It's not okay to do:
+			//	var x SliceHeader
+			//	x.Data = uintptr(unsafe.Pointer(...))
+			//	... use x ...
+			//	p := unsafe.Pointer(x.Data)
+			// because in the middle the garbage collector doesn't
+			// see x.Data as a pointer and so x.Data may be dangling
+			// by the time we get to the conversion at the end.
+			// For now approximate by saying that *Header is okay
+			// but Header is not.
+			pt, ok := f.pkg.types[x.X].Type.(*types.Pointer)
+			if ok {
+				t, ok := pt.Elem().(*types.Named)
+				if ok && t.Obj().Pkg().Path() == "reflect" {
+					switch t.Obj().Name() {
+					case "StringHeader", "SliceHeader":
+						return true
+					}
+				}
+			}
+		}
+
+	case *ast.CallExpr:
+		switch len(x.Args) {
+		case 0:
+			// maybe call to reflect.Value.Pointer or reflect.Value.UnsafeAddr.
+			sel, ok := x.Fun.(*ast.SelectorExpr)
+			if !ok {
+				break
+			}
+			switch sel.Sel.Name {
+			case "Pointer", "UnsafeAddr":
+				t, ok := f.pkg.types[sel.X].Type.(*types.Named)
+				if ok && t.Obj().Pkg().Path() == "reflect" && t.Obj().Name() == "Value" {
+					return true
+				}
+			}
+
+		case 1:
+			// maybe conversion of uintptr to unsafe.Pointer
+			return f.hasBasicType(x.Fun, types.Uintptr) && f.hasBasicType(x.Args[0], types.UnsafePointer)
+		}
+
+	case *ast.BinaryExpr:
+		switch x.Op {
+		case token.ADD, token.SUB:
+			return f.isSafeUintptr(x.X) && !f.isSafeUintptr(x.Y)
+		}
+	}
+	return false
+}
diff --git a/cmd/vet/unused.go b/cmd/vet/unused.go
new file mode 100644
index 0000000..b9d7b65
--- /dev/null
+++ b/cmd/vet/unused.go
@@ -0,0 +1,94 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file defines the check for unused results of calls to certain
+// pure functions.
+
+package main
+
+import (
+	"flag"
+	"go/ast"
+	"go/token"
+	"strings"
+
+	"golang.org/x/tools/go/types"
+)
+
+var unusedFuncsFlag = flag.String("unusedfuncs",
+	"errors.New,fmt.Errorf,fmt.Sprintf,fmt.Sprint,sort.Reverse",
+	"comma-separated list of functions whose results must be used")
+
+var unusedStringMethodsFlag = flag.String("unusedstringmethods",
+	"Error,String",
+	"comma-separated list of names of methods of type func() string whose results must be used")
+
+func init() {
+	register("unusedresult",
+		"check for unused result of calls to functions in -unusedfuncs list and methods in -unusedstringmethods list",
+		checkUnusedResult,
+		exprStmt)
+}
+
+// func() string
+var sigNoArgsStringResult = types.NewSignature(nil, nil,
+	types.NewTuple(types.NewVar(token.NoPos, nil, "", types.Typ[types.String])),
+	false)
+
+var unusedFuncs = make(map[string]bool)
+var unusedStringMethods = make(map[string]bool)
+
+func initUnusedFlags() {
+	commaSplit := func(s string, m map[string]bool) {
+		if s != "" {
+			for _, name := range strings.Split(s, ",") {
+				if len(name) == 0 {
+					flag.Usage()
+				}
+				m[name] = true
+			}
+		}
+	}
+	commaSplit(*unusedFuncsFlag, unusedFuncs)
+	commaSplit(*unusedStringMethodsFlag, unusedStringMethods)
+}
+
+func checkUnusedResult(f *File, n ast.Node) {
+	call, ok := unparen(n.(*ast.ExprStmt).X).(*ast.CallExpr)
+	if !ok {
+		return // not a call statement
+	}
+	fun := unparen(call.Fun)
+
+	if f.pkg.types[fun].IsType() {
+		return // a conversion, not a call
+	}
+
+	selector, ok := fun.(*ast.SelectorExpr)
+	if !ok {
+		return // neither a method call nor a qualified ident
+	}
+
+	sel, ok := f.pkg.selectors[selector]
+	if ok && sel.Kind() == types.MethodVal {
+		// method (e.g. foo.String())
+		obj := sel.Obj().(*types.Func)
+		sig := sel.Type().(*types.Signature)
+		if types.Identical(sig, sigNoArgsStringResult) {
+			if unusedStringMethods[obj.Name()] {
+				f.Badf(call.Lparen, "result of (%s).%s call not used",
+					sig.Recv().Type(), obj.Name())
+			}
+		}
+	} else if !ok {
+		// package-qualified function (e.g. fmt.Errorf)
+		obj, _ := f.pkg.uses[selector.Sel]
+		if obj, ok := obj.(*types.Func); ok {
+			qname := obj.Pkg().Path() + "." + obj.Name()
+			if unusedFuncs[qname] {
+				f.Badf(call.Lparen, "result of %v call not used", qname)
+			}
+		}
+	}
+}
diff --git a/cmd/vet/vet_test.go b/cmd/vet/vet_test.go
new file mode 100644
index 0000000..6a09e3d
--- /dev/null
+++ b/cmd/vet/vet_test.go
@@ -0,0 +1,106 @@
+// Copyright 2013 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// No testdata on Android.
+
+// +build !android
+
+package main_test
+
+import (
+	"bytes"
+	"os"
+	"os/exec"
+	"path/filepath"
+	"runtime"
+	"testing"
+)
+
+const (
+	dataDir = "testdata"
+	binary  = "testvet.exe"
+)
+
+// Run this shell script, but do it in Go so it can be run by "go test".
+// 	go build -o testvet
+// 	$(GOROOT)/test/errchk ./testvet -shadow -printfuncs='Warn:1,Warnf:1' testdata/*.go testdata/*.s
+// 	rm testvet
+//
+func TestVet(t *testing.T) {
+	// Plan 9 and Windows systems can't be guaranteed to have Perl and so can't run errchk.
+	switch runtime.GOOS {
+	case "plan9", "windows":
+		t.Skip("skipping test; no Perl on %q", runtime.GOOS)
+	}
+
+	// go build
+	cmd := exec.Command("go", "build", "-o", binary)
+	run(cmd, t)
+
+	// defer removal of vet
+	defer os.Remove(binary)
+
+	// errchk ./testvet
+	gos, err := filepath.Glob(filepath.Join(dataDir, "*.go"))
+	if err != nil {
+		t.Fatal(err)
+	}
+	asms, err := filepath.Glob(filepath.Join(dataDir, "*.s"))
+	if err != nil {
+		t.Fatal(err)
+	}
+	files := append(gos, asms...)
+	errchk := filepath.Join(runtime.GOROOT(), "test", "errchk")
+	flags := []string{
+		"./" + binary,
+		"-printfuncs=Warn:1,Warnf:1",
+		"-test", // TODO: Delete once -shadow is part of -all.
+	}
+	cmd = exec.Command(errchk, append(flags, files...)...)
+	if !run(cmd, t) {
+		t.Fatal("vet command failed")
+	}
+}
+
+func run(c *exec.Cmd, t *testing.T) bool {
+	output, err := c.CombinedOutput()
+	os.Stderr.Write(output)
+	if err != nil {
+		t.Fatal(err)
+	}
+	// Errchk delights by not returning non-zero status if it finds errors, so we look at the output.
+	// It prints "BUG" if there is a failure.
+	if !c.ProcessState.Success() {
+		return false
+	}
+	return !bytes.Contains(output, []byte("BUG"))
+}
+
+// TestTags verifies that the -tags argument controls which files to check.
+func TestTags(t *testing.T) {
+	// go build
+	cmd := exec.Command("go", "build", "-o", binary)
+	run(cmd, t)
+
+	// defer removal of vet
+	defer os.Remove(binary)
+
+	args := []string{
+		"-tags=testtag",
+		"-v", // We're going to look at the files it examines.
+		"testdata/tagtest",
+	}
+	cmd = exec.Command("./"+binary, args...)
+	output, err := cmd.CombinedOutput()
+	if err != nil {
+		t.Fatal(err)
+	}
+	// file1 has testtag and file2 has !testtag.
+	if !bytes.Contains(output, []byte(filepath.Join("tagtest", "file1.go"))) {
+		t.Error("file1 was excluded, should be included")
+	}
+	if bytes.Contains(output, []byte(filepath.Join("tagtest", "file2.go"))) {
+		t.Error("file2 was included, should be excluded")
+	}
+}
diff --git a/cmd/vet/whitelist/whitelist.go b/cmd/vet/whitelist/whitelist.go
new file mode 100644
index 0000000..d6f0dce
--- /dev/null
+++ b/cmd/vet/whitelist/whitelist.go
@@ -0,0 +1,53 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package whitelist defines exceptions for the vet tool.
+package whitelist // import "golang.org/x/tools/cmd/vet/whitelist"
+
+// UnkeyedLiteral are types that are actually slices, but
+// syntactically, we cannot tell whether the Typ in pkg.Typ{1, 2, 3}
+// is a slice or a struct, so we whitelist all the standard package
+// library's exported slice types.
+var UnkeyedLiteral = map[string]bool{
+	/*
+		find $GOROOT/src -type f | grep -v _test.go | xargs grep '^type.*\[\]' | \
+			grep -v ' map\[' | sed 's,/[^/]*go.type,,' | sed 's,.*src/,,' | \
+			sed 's, ,.,' |  sed 's, .*,,' | grep -v '\.[a-z]' | \
+			sort | awk '{ print "\"" $0 "\": true," }'
+	*/
+	"crypto/x509/pkix.RDNSequence":                  true,
+	"crypto/x509/pkix.RelativeDistinguishedNameSET": true,
+	"database/sql.RawBytes":                         true,
+	"debug/macho.LoadBytes":                         true,
+	"encoding/asn1.ObjectIdentifier":                true,
+	"encoding/asn1.RawContent":                      true,
+	"encoding/json.RawMessage":                      true,
+	"encoding/xml.CharData":                         true,
+	"encoding/xml.Comment":                          true,
+	"encoding/xml.Directive":                        true,
+	"go/scanner.ErrorList":                          true,
+	"image/color.Palette":                           true,
+	"net.HardwareAddr":                              true,
+	"net.IP":                                        true,
+	"net.IPMask":                                    true,
+	"sort.Float64Slice":                             true,
+	"sort.IntSlice":                                 true,
+	"sort.StringSlice":                              true,
+	"unicode.SpecialCase":                           true,
+
+	// These image and image/color struct types are frozen. We will never add fields to them.
+	"image/color.Alpha16": true,
+	"image/color.Alpha":   true,
+	"image/color.CMYK":    true,
+	"image/color.Gray16":  true,
+	"image/color.Gray":    true,
+	"image/color.NRGBA64": true,
+	"image/color.NRGBA":   true,
+	"image/color.RGBA64":  true,
+	"image/color.RGBA":    true,
+	"image/color.YCbCr":   true,
+	"image.Point":         true,
+	"image.Rectangle":     true,
+	"image.Uniform":       true,
+}
diff --git a/codereview.cfg b/codereview.cfg
new file mode 100644
index 0000000..3f8b14b
--- /dev/null
+++ b/codereview.cfg
@@ -0,0 +1 @@
+issuerepo: golang/go
diff --git a/container/intsets/sparse.go b/container/intsets/sparse.go
new file mode 100644
index 0000000..8847feb
--- /dev/null
+++ b/container/intsets/sparse.go
@@ -0,0 +1,967 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package intsets provides Sparse, a compact and fast representation
+// for sparse sets of int values.
+//
+// The time complexity of the operations Len, Insert, Remove and Has
+// is in O(n) but in practice those methods are faster and more
+// space-efficient than equivalent operations on sets based on the Go
+// map type.  The IsEmpty, Min, Max, Clear and TakeMin operations
+// require constant time.
+//
+package intsets // import "golang.org/x/tools/container/intsets"
+
+// TODO(adonovan):
+// - Add InsertAll(...int), RemoveAll(...int)
+// - Add 'bool changed' results for {Intersection,Difference}With too.
+//
+// TODO(adonovan): implement Dense, a dense bit vector with a similar API.
+// The space usage would be proportional to Max(), not Len(), and the
+// implementation would be based upon big.Int.
+//
+// TODO(adonovan): experiment with making the root block indirect (nil
+// iff IsEmpty).  This would reduce the memory usage when empty and
+// might simplify the aliasing invariants.
+//
+// TODO(adonovan): opt: make UnionWith and Difference faster.
+// These are the hot-spots for go/pointer.
+
+import (
+	"bytes"
+	"fmt"
+)
+
+// A Sparse is a set of int values.
+// Sparse operations (even queries) are not concurrency-safe.
+//
+// The zero value for Sparse is a valid empty set.
+//
+// Sparse sets must be copied using the Copy method, not by assigning
+// a Sparse value.
+//
+type Sparse struct {
+	// An uninitialized Sparse represents an empty set.
+	// An empty set may also be represented by
+	//  root.next == root.prev == &root.
+	// In a non-empty set, root.next points to the first block and
+	// root.prev to the last.
+	// root.offset and root.bits are unused.
+	root block
+}
+
+type word uintptr
+
+const (
+	_m            = ^word(0)
+	bitsPerWord   = 8 << (_m>>8&1 + _m>>16&1 + _m>>32&1)
+	bitsPerBlock  = 256 // optimal value for go/pointer solver performance
+	wordsPerBlock = bitsPerBlock / bitsPerWord
+)
+
+// Limit values of implementation-specific int type.
+const (
+	MaxInt = int(^uint(0) >> 1)
+	MinInt = -MaxInt - 1
+)
+
+// -- block ------------------------------------------------------------
+
+// A set is represented as a circular doubly-linked list of blocks,
+// each containing an offset and a bit array of fixed size
+// bitsPerBlock; the blocks are ordered by increasing offset.
+//
+// The set contains an element x iff the block whose offset is x - (x
+// mod bitsPerBlock) has the bit (x mod bitsPerBlock) set, where mod
+// is the Euclidean remainder.
+//
+// A block may only be empty transiently.
+//
+type block struct {
+	offset     int                 // offset mod bitsPerBlock == 0
+	bits       [wordsPerBlock]word // contains at least one set bit
+	next, prev *block              // doubly-linked list of blocks
+}
+
+// wordMask returns the word index (in block.bits)
+// and single-bit mask for the block's ith bit.
+func wordMask(i uint) (w uint, mask word) {
+	w = i / bitsPerWord
+	mask = 1 << (i % bitsPerWord)
+	return
+}
+
+// insert sets the block b's ith bit and
+// returns true if it was not already set.
+//
+func (b *block) insert(i uint) bool {
+	w, mask := wordMask(i)
+	if b.bits[w]&mask == 0 {
+		b.bits[w] |= mask
+		return true
+	}
+	return false
+}
+
+// remove clears the block's ith bit and
+// returns true if the bit was previously set.
+// NB: may leave the block empty.
+//
+func (b *block) remove(i uint) bool {
+	w, mask := wordMask(i)
+	if b.bits[w]&mask != 0 {
+		b.bits[w] &^= mask
+		return true
+	}
+	return false
+}
+
+// has reports whether the block's ith bit is set.
+func (b *block) has(i uint) bool {
+	w, mask := wordMask(i)
+	return b.bits[w]&mask != 0
+}
+
+// empty reports whether b.len()==0, but more efficiently.
+func (b *block) empty() bool {
+	for _, w := range b.bits {
+		if w != 0 {
+			return false
+		}
+	}
+	return true
+}
+
+// len returns the number of set bits in block b.
+func (b *block) len() int {
+	var l int
+	for _, w := range b.bits {
+		l += popcount(w)
+	}
+	return l
+}
+
+// max returns the maximum element of the block.
+// The block must not be empty.
+//
+func (b *block) max() int {
+	bi := b.offset + bitsPerBlock
+	// Decrement bi by number of high zeros in last.bits.
+	for i := len(b.bits) - 1; i >= 0; i-- {
+		if w := b.bits[i]; w != 0 {
+			return bi - nlz(w) - 1
+		}
+		bi -= bitsPerWord
+	}
+	panic("BUG: empty block")
+}
+
+// min returns the minimum element of the block,
+// and also removes it if take is set.
+// The block must not be initially empty.
+// NB: may leave the block empty.
+//
+func (b *block) min(take bool) int {
+	for i, w := range b.bits {
+		if w != 0 {
+			tz := ntz(w)
+			if take {
+				b.bits[i] = w &^ (1 << uint(tz))
+			}
+			return b.offset + int(i*bitsPerWord) + tz
+		}
+	}
+	panic("BUG: empty block")
+}
+
+// forEach calls f for each element of block b.
+// f must not mutate b's enclosing Sparse.
+func (b *block) forEach(f func(int)) {
+	for i, w := range b.bits {
+		offset := b.offset + i*bitsPerWord
+		for bi := 0; w != 0 && bi < bitsPerWord; bi++ {
+			if w&1 != 0 {
+				f(offset)
+			}
+			offset++
+			w >>= 1
+		}
+	}
+}
+
+// offsetAndBitIndex returns the offset of the block that would
+// contain x and the bit index of x within that block.
+//
+func offsetAndBitIndex(x int) (int, uint) {
+	mod := x % bitsPerBlock
+	if mod < 0 {
+		// Euclidean (non-negative) remainder
+		mod += bitsPerBlock
+	}
+	return x - mod, uint(mod)
+}
+
+// -- Sparse --------------------------------------------------------------
+
+// start returns the root's next block, which is the root block
+// (if s.IsEmpty()) or the first true block otherwise.
+// start has the side effect of ensuring that s is properly
+// initialized.
+//
+func (s *Sparse) start() *block {
+	root := &s.root
+	if root.next == nil {
+		root.next = root
+		root.prev = root
+	} else if root.next.prev != root {
+		// Copying a Sparse x leads to pernicious corruption: the
+		// new Sparse y shares the old linked list, but iteration
+		// on y will never encounter &y.root so it goes into a
+		// loop.  Fail fast before this occurs.
+		panic("A Sparse has been copied without (*Sparse).Copy()")
+	}
+
+	return root.next
+}
+
+// IsEmpty reports whether the set s is empty.
+func (s *Sparse) IsEmpty() bool {
+	return s.start() == &s.root
+}
+
+// Len returns the number of elements in the set s.
+func (s *Sparse) Len() int {
+	var l int
+	for b := s.start(); b != &s.root; b = b.next {
+		l += b.len()
+	}
+	return l
+}
+
+// Max returns the maximum element of the set s, or MinInt if s is empty.
+func (s *Sparse) Max() int {
+	if s.IsEmpty() {
+		return MinInt
+	}
+	return s.root.prev.max()
+}
+
+// Min returns the minimum element of the set s, or MaxInt if s is empty.
+func (s *Sparse) Min() int {
+	if s.IsEmpty() {
+		return MaxInt
+	}
+	return s.root.next.min(false)
+}
+
+// block returns the block that would contain offset,
+// or nil if s contains no such block.
+//
+func (s *Sparse) block(offset int) *block {
+	b := s.start()
+	for b != &s.root && b.offset <= offset {
+		if b.offset == offset {
+			return b
+		}
+		b = b.next
+	}
+	return nil
+}
+
+// Insert adds x to the set s, and reports whether the set grew.
+func (s *Sparse) Insert(x int) bool {
+	offset, i := offsetAndBitIndex(x)
+	b := s.start()
+	for b != &s.root && b.offset <= offset {
+		if b.offset == offset {
+			return b.insert(i)
+		}
+		b = b.next
+	}
+
+	// Insert new block before b.
+	new := &block{offset: offset}
+	new.next = b
+	new.prev = b.prev
+	new.prev.next = new
+	new.next.prev = new
+	return new.insert(i)
+}
+
+func (s *Sparse) removeBlock(b *block) {
+	b.prev.next = b.next
+	b.next.prev = b.prev
+}
+
+// Remove removes x from the set s, and reports whether the set shrank.
+func (s *Sparse) Remove(x int) bool {
+	offset, i := offsetAndBitIndex(x)
+	if b := s.block(offset); b != nil {
+		if !b.remove(i) {
+			return false
+		}
+		if b.empty() {
+			s.removeBlock(b)
+		}
+		return true
+	}
+	return false
+}
+
+// Clear removes all elements from the set s.
+func (s *Sparse) Clear() {
+	s.root.next = &s.root
+	s.root.prev = &s.root
+}
+
+// If set s is non-empty, TakeMin sets *p to the minimum element of
+// the set s, removes that element from the set and returns true.
+// Otherwise, it returns false and *p is undefined.
+//
+// This method may be used for iteration over a worklist like so:
+//
+// 	var x int
+// 	for worklist.TakeMin(&x) { use(x) }
+//
+func (s *Sparse) TakeMin(p *int) bool {
+	head := s.start()
+	if head == &s.root {
+		return false
+	}
+	*p = head.min(true)
+	if head.empty() {
+		s.removeBlock(head)
+	}
+	return true
+}
+
+// Has reports whether x is an element of the set s.
+func (s *Sparse) Has(x int) bool {
+	offset, i := offsetAndBitIndex(x)
+	if b := s.block(offset); b != nil {
+		return b.has(i)
+	}
+	return false
+}
+
+// forEach applies function f to each element of the set s in order.
+//
+// f must not mutate s.  Consequently, forEach is not safe to expose
+// to clients.  In any case, using "range s.AppendTo()" allows more
+// natural control flow with continue/break/return.
+//
+func (s *Sparse) forEach(f func(int)) {
+	for b := s.start(); b != &s.root; b = b.next {
+		b.forEach(f)
+	}
+}
+
+// Copy sets s to the value of x.
+func (s *Sparse) Copy(x *Sparse) {
+	if s == x {
+		return
+	}
+
+	xb := x.start()
+	sb := s.start()
+	for xb != &x.root {
+		if sb == &s.root {
+			sb = s.insertBlockBefore(sb)
+		}
+		sb.offset = xb.offset
+		sb.bits = xb.bits
+		xb = xb.next
+		sb = sb.next
+	}
+	s.discardTail(sb)
+}
+
+// insertBlockBefore returns a new block, inserting it before next.
+func (s *Sparse) insertBlockBefore(next *block) *block {
+	b := new(block)
+	b.next = next
+	b.prev = next.prev
+	b.prev.next = b
+	next.prev = b
+	return b
+}
+
+// discardTail removes block b and all its successors from s.
+func (s *Sparse) discardTail(b *block) {
+	if b != &s.root {
+		b.prev.next = &s.root
+		s.root.prev = b.prev
+	}
+}
+
+// IntersectionWith sets s to the intersection s ∩ x.
+func (s *Sparse) IntersectionWith(x *Sparse) {
+	if s == x {
+		return
+	}
+
+	xb := x.start()
+	sb := s.start()
+	for xb != &x.root && sb != &s.root {
+		switch {
+		case xb.offset < sb.offset:
+			xb = xb.next
+
+		case xb.offset > sb.offset:
+			sb = sb.next
+			s.removeBlock(sb.prev)
+
+		default:
+			var sum word
+			for i := range sb.bits {
+				r := xb.bits[i] & sb.bits[i]
+				sb.bits[i] = r
+				sum |= r
+			}
+			if sum != 0 {
+				sb = sb.next
+			} else {
+				// sb will be overwritten or removed
+			}
+
+			xb = xb.next
+		}
+	}
+
+	s.discardTail(sb)
+}
+
+// Intersection sets s to the intersection x ∩ y.
+func (s *Sparse) Intersection(x, y *Sparse) {
+	switch {
+	case s == x:
+		s.IntersectionWith(y)
+		return
+	case s == y:
+		s.IntersectionWith(x)
+		return
+	case x == y:
+		s.Copy(x)
+		return
+	}
+
+	xb := x.start()
+	yb := y.start()
+	sb := s.start()
+	for xb != &x.root && yb != &y.root {
+		switch {
+		case xb.offset < yb.offset:
+			xb = xb.next
+			continue
+		case xb.offset > yb.offset:
+			yb = yb.next
+			continue
+		}
+
+		if sb == &s.root {
+			sb = s.insertBlockBefore(sb)
+		}
+		sb.offset = xb.offset
+
+		var sum word
+		for i := range sb.bits {
+			r := xb.bits[i] & yb.bits[i]
+			sb.bits[i] = r
+			sum |= r
+		}
+		if sum != 0 {
+			sb = sb.next
+		} else {
+			// sb will be overwritten or removed
+		}
+
+		xb = xb.next
+		yb = yb.next
+	}
+
+	s.discardTail(sb)
+}
+
+// Intersects reports whether s ∩ x ≠ ∅.
+func (s *Sparse) Intersects(x *Sparse) bool {
+	sb := s.start()
+	xb := x.start()
+	for sb != &s.root && xb != &x.root {
+		switch {
+		case xb.offset < sb.offset:
+			xb = xb.next
+		case xb.offset > sb.offset:
+			sb = sb.next
+		default:
+			for i := range sb.bits {
+				if sb.bits[i]&xb.bits[i] != 0 {
+					return true
+				}
+			}
+			sb = sb.next
+			xb = xb.next
+		}
+	}
+	return false
+}
+
+// UnionWith sets s to the union s ∪ x, and reports whether s grew.
+func (s *Sparse) UnionWith(x *Sparse) bool {
+	if s == x {
+		return false
+	}
+
+	var changed bool
+	xb := x.start()
+	sb := s.start()
+	for xb != &x.root {
+		if sb != &s.root && sb.offset == xb.offset {
+			for i := range xb.bits {
+				if sb.bits[i] != xb.bits[i] {
+					sb.bits[i] |= xb.bits[i]
+					changed = true
+				}
+			}
+			xb = xb.next
+		} else if sb == &s.root || sb.offset > xb.offset {
+			sb = s.insertBlockBefore(sb)
+			sb.offset = xb.offset
+			sb.bits = xb.bits
+			changed = true
+
+			xb = xb.next
+		}
+		sb = sb.next
+	}
+	return changed
+}
+
+// Union sets s to the union x ∪ y.
+func (s *Sparse) Union(x, y *Sparse) {
+	switch {
+	case x == y:
+		s.Copy(x)
+		return
+	case s == x:
+		s.UnionWith(y)
+		return
+	case s == y:
+		s.UnionWith(x)
+		return
+	}
+
+	xb := x.start()
+	yb := y.start()
+	sb := s.start()
+	for xb != &x.root || yb != &y.root {
+		if sb == &s.root {
+			sb = s.insertBlockBefore(sb)
+		}
+		switch {
+		case yb == &y.root || (xb != &x.root && xb.offset < yb.offset):
+			sb.offset = xb.offset
+			sb.bits = xb.bits
+			xb = xb.next
+
+		case xb == &x.root || (yb != &y.root && yb.offset < xb.offset):
+			sb.offset = yb.offset
+			sb.bits = yb.bits
+			yb = yb.next
+
+		default:
+			sb.offset = xb.offset
+			for i := range xb.bits {
+				sb.bits[i] = xb.bits[i] | yb.bits[i]
+			}
+			xb = xb.next
+			yb = yb.next
+		}
+		sb = sb.next
+	}
+
+	s.discardTail(sb)
+}
+
+// DifferenceWith sets s to the difference s ∖ x.
+func (s *Sparse) DifferenceWith(x *Sparse) {
+	if s == x {
+		s.Clear()
+		return
+	}
+
+	xb := x.start()
+	sb := s.start()
+	for xb != &x.root && sb != &s.root {
+		switch {
+		case xb.offset > sb.offset:
+			sb = sb.next
+
+		case xb.offset < sb.offset:
+			xb = xb.next
+
+		default:
+			var sum word
+			for i := range sb.bits {
+				r := sb.bits[i] & ^xb.bits[i]
+				sb.bits[i] = r
+				sum |= r
+			}
+			sb = sb.next
+			xb = xb.next
+
+			if sum == 0 {
+				s.removeBlock(sb.prev)
+			}
+		}
+	}
+}
+
+// Difference sets s to the difference x ∖ y.
+func (s *Sparse) Difference(x, y *Sparse) {
+	switch {
+	case x == y:
+		s.Clear()
+		return
+	case s == x:
+		s.DifferenceWith(y)
+		return
+	case s == y:
+		var y2 Sparse
+		y2.Copy(y)
+		s.Difference(x, &y2)
+		return
+	}
+
+	xb := x.start()
+	yb := y.start()
+	sb := s.start()
+	for xb != &x.root && yb != &y.root {
+		if xb.offset > yb.offset {
+			// y has block, x has none
+			yb = yb.next
+			continue
+		}
+
+		if sb == &s.root {
+			sb = s.insertBlockBefore(sb)
+		}
+		sb.offset = xb.offset
+
+		switch {
+		case xb.offset < yb.offset:
+			// x has block, y has none
+			sb.bits = xb.bits
+
+			sb = sb.next
+
+		default:
+			// x and y have corresponding blocks
+			var sum word
+			for i := range sb.bits {
+				r := xb.bits[i] & ^yb.bits[i]
+				sb.bits[i] = r
+				sum |= r
+			}
+			if sum != 0 {
+				sb = sb.next
+			} else {
+				// sb will be overwritten or removed
+			}
+
+			yb = yb.next
+		}
+		xb = xb.next
+	}
+
+	for xb != &x.root {
+		if sb == &s.root {
+			sb = s.insertBlockBefore(sb)
+		}
+		sb.offset = xb.offset
+		sb.bits = xb.bits
+		sb = sb.next
+
+		xb = xb.next
+	}
+
+	s.discardTail(sb)
+}
+
+// SymmetricDifferenceWith sets s to the symmetric difference s ∆ x.
+func (s *Sparse) SymmetricDifferenceWith(x *Sparse) {
+	if s == x {
+		s.Clear()
+		return
+	}
+
+	sb := s.start()
+	xb := x.start()
+	for xb != &x.root && sb != &s.root {
+		switch {
+		case sb.offset < xb.offset:
+			sb = sb.next
+		case xb.offset < sb.offset:
+			nb := s.insertBlockBefore(sb)
+			nb.offset = xb.offset
+			nb.bits = xb.bits
+			xb = xb.next
+		default:
+			var sum word
+			for i := range sb.bits {
+				r := sb.bits[i] ^ xb.bits[i]
+				sb.bits[i] = r
+				sum |= r
+			}
+			sb = sb.next
+			xb = xb.next
+			if sum == 0 {
+				s.removeBlock(sb.prev)
+			}
+		}
+	}
+
+	for xb != &x.root { // append the tail of x to s
+		sb = s.insertBlockBefore(sb)
+		sb.offset = xb.offset
+		sb.bits = xb.bits
+		sb = sb.next
+		xb = xb.next
+	}
+}
+
+// SymmetricDifference sets s to the symmetric difference x ∆ y.
+func (s *Sparse) SymmetricDifference(x, y *Sparse) {
+	switch {
+	case x == y:
+		s.Clear()
+		return
+	case s == x:
+		s.SymmetricDifferenceWith(y)
+		return
+	case s == y:
+		s.SymmetricDifferenceWith(x)
+		return
+	}
+
+	sb := s.start()
+	xb := x.start()
+	yb := y.start()
+	for xb != &x.root && yb != &y.root {
+		if sb == &s.root {
+			sb = s.insertBlockBefore(sb)
+		}
+		switch {
+		case yb.offset < xb.offset:
+			sb.offset = yb.offset
+			sb.bits = yb.bits
+			sb = sb.next
+			yb = yb.next
+		case xb.offset < yb.offset:
+			sb.offset = xb.offset
+			sb.bits = xb.bits
+			sb = sb.next
+			xb = xb.next
+		default:
+			var sum word
+			for i := range sb.bits {
+				r := xb.bits[i] ^ yb.bits[i]
+				sb.bits[i] = r
+				sum |= r
+			}
+			if sum != 0 {
+				sb.offset = xb.offset
+				sb = sb.next
+			}
+			xb = xb.next
+			yb = yb.next
+		}
+	}
+
+	for xb != &x.root { // append the tail of x to s
+		if sb == &s.root {
+			sb = s.insertBlockBefore(sb)
+		}
+		sb.offset = xb.offset
+		sb.bits = xb.bits
+		sb = sb.next
+		xb = xb.next
+	}
+
+	for yb != &y.root { // append the tail of y to s
+		if sb == &s.root {
+			sb = s.insertBlockBefore(sb)
+		}
+		sb.offset = yb.offset
+		sb.bits = yb.bits
+		sb = sb.next
+		yb = yb.next
+	}
+
+	s.discardTail(sb)
+}
+
+// SubsetOf reports whether s ∖ x = ∅.
+func (s *Sparse) SubsetOf(x *Sparse) bool {
+	if s == x {
+		return true
+	}
+
+	sb := s.start()
+	xb := x.start()
+	for sb != &s.root {
+		switch {
+		case xb == &x.root || xb.offset > sb.offset:
+			return false
+		case xb.offset < sb.offset:
+			xb = xb.next
+		default:
+			for i := range sb.bits {
+				if sb.bits[i]&^xb.bits[i] != 0 {
+					return false
+				}
+			}
+			sb = sb.next
+			xb = xb.next
+		}
+	}
+	return true
+}
+
+// Equals reports whether the sets s and t have the same elements.
+func (s *Sparse) Equals(t *Sparse) bool {
+	if s == t {
+		return true
+	}
+	sb := s.start()
+	tb := t.start()
+	for {
+		switch {
+		case sb == &s.root && tb == &t.root:
+			return true
+		case sb == &s.root || tb == &t.root:
+			return false
+		case sb.offset != tb.offset:
+			return false
+		case sb.bits != tb.bits:
+			return false
+		}
+
+		sb = sb.next
+		tb = tb.next
+	}
+}
+
+// String returns a human-readable description of the set s.
+func (s *Sparse) String() string {
+	var buf bytes.Buffer
+	buf.WriteByte('{')
+	s.forEach(func(x int) {
+		if buf.Len() > 1 {
+			buf.WriteByte(' ')
+		}
+		fmt.Fprintf(&buf, "%d", x)
+	})
+	buf.WriteByte('}')
+	return buf.String()
+}
+
+// BitString returns the set as a string of 1s and 0s denoting the sum
+// of the i'th powers of 2, for each i in s.  A radix point, always
+// preceded by a digit, appears if the sum is non-integral.
+//
+// Examples:
+//              {}.BitString() =      "0"
+//           {4,5}.BitString() = "110000"
+//            {-3}.BitString() =      "0.001"
+//      {-3,0,4,5}.BitString() = "110001.001"
+//
+func (s *Sparse) BitString() string {
+	if s.IsEmpty() {
+		return "0"
+	}
+
+	min, max := s.Min(), s.Max()
+	var nbytes int
+	if max > 0 {
+		nbytes = max
+	}
+	nbytes++ // zero bit
+	radix := nbytes
+	if min < 0 {
+		nbytes += len(".") - min
+	}
+
+	b := make([]byte, nbytes)
+	for i := range b {
+		b[i] = '0'
+	}
+	if radix < nbytes {
+		b[radix] = '.'
+	}
+	s.forEach(func(x int) {
+		if x >= 0 {
+			x += len(".")
+		}
+		b[radix-x] = '1'
+	})
+	return string(b)
+}
+
+// GoString returns a string showing the internal representation of
+// the set s.
+//
+func (s *Sparse) GoString() string {
+	var buf bytes.Buffer
+	for b := s.start(); b != &s.root; b = b.next {
+		fmt.Fprintf(&buf, "block %p {offset=%d next=%p prev=%p",
+			b, b.offset, b.next, b.prev)
+		for _, w := range b.bits {
+			fmt.Fprintf(&buf, " 0%016x", w)
+		}
+		fmt.Fprintf(&buf, "}\n")
+	}
+	return buf.String()
+}
+
+// AppendTo returns the result of appending the elements of s to slice
+// in order.
+func (s *Sparse) AppendTo(slice []int) []int {
+	s.forEach(func(x int) {
+		slice = append(slice, x)
+	})
+	return slice
+}
+
+// -- Testing/debugging ------------------------------------------------
+
+// check returns an error if the representation invariants of s are violated.
+func (s *Sparse) check() error {
+	if !s.root.empty() {
+		return fmt.Errorf("non-empty root block")
+	}
+	if s.root.offset != 0 {
+		return fmt.Errorf("root block has non-zero offset %d", s.root.offset)
+	}
+	for b := s.start(); b != &s.root; b = b.next {
+		if b.offset%bitsPerBlock != 0 {
+			return fmt.Errorf("bad offset modulo: %d", b.offset)
+		}
+		if b.empty() {
+			return fmt.Errorf("empty block")
+		}
+		if b.prev.next != b {
+			return fmt.Errorf("bad prev.next link")
+		}
+		if b.next.prev != b {
+			return fmt.Errorf("bad next.prev link")
+		}
+		if b.prev != &s.root {
+			if b.offset <= b.prev.offset {
+				return fmt.Errorf("bad offset order: b.offset=%d, prev.offset=%d",
+					b.offset, b.prev.offset)
+			}
+		}
+	}
+	return nil
+}
diff --git a/container/intsets/sparse_test.go b/container/intsets/sparse_test.go
new file mode 100644
index 0000000..34b9a4e
--- /dev/null
+++ b/container/intsets/sparse_test.go
@@ -0,0 +1,638 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package intsets_test
+
+import (
+	"fmt"
+	"log"
+	"math/rand"
+	"sort"
+	"strings"
+	"testing"
+
+	"golang.org/x/tools/container/intsets"
+)
+
+func TestBasics(t *testing.T) {
+	var s intsets.Sparse
+	if len := s.Len(); len != 0 {
+		t.Errorf("Len({}): got %d, want 0", len)
+	}
+	if s := s.String(); s != "{}" {
+		t.Errorf("String({}): got %q, want \"{}\"", s)
+	}
+	if s.Has(3) {
+		t.Errorf("Has(3): got true, want false")
+	}
+	if err := s.Check(); err != nil {
+		t.Error(err)
+	}
+
+	if !s.Insert(3) {
+		t.Errorf("Insert(3): got false, want true")
+	}
+	if max := s.Max(); max != 3 {
+		t.Errorf("Max: got %d, want 3", max)
+	}
+
+	if !s.Insert(435) {
+		t.Errorf("Insert(435): got false, want true")
+	}
+	if s := s.String(); s != "{3 435}" {
+		t.Errorf("String({3 435}): got %q, want \"{3 435}\"", s)
+	}
+	if max := s.Max(); max != 435 {
+		t.Errorf("Max: got %d, want 435", max)
+	}
+	if len := s.Len(); len != 2 {
+		t.Errorf("Len: got %d, want 2", len)
+	}
+
+	if !s.Remove(435) {
+		t.Errorf("Remove(435): got false, want true")
+	}
+	if s := s.String(); s != "{3}" {
+		t.Errorf("String({3}): got %q, want \"{3}\"", s)
+	}
+}
+
+// Insert, Len, IsEmpty, Hash, Clear, AppendTo.
+func TestMoreBasics(t *testing.T) {
+	set := new(intsets.Sparse)
+	set.Insert(456)
+	set.Insert(123)
+	set.Insert(789)
+	if set.Len() != 3 {
+		t.Errorf("%s.Len: got %d, want 3", set, set.Len())
+	}
+	if set.IsEmpty() {
+		t.Errorf("%s.IsEmpty: got true", set)
+	}
+	if !set.Has(123) {
+		t.Errorf("%s.Has(123): got false", set)
+	}
+	if set.Has(1234) {
+		t.Errorf("%s.Has(1234): got true", set)
+	}
+	got := set.AppendTo([]int{-1})
+	if want := []int{-1, 123, 456, 789}; fmt.Sprint(got) != fmt.Sprint(want) {
+		t.Errorf("%s.AppendTo: got %v, want %v", set, got, want)
+	}
+
+	set.Clear()
+
+	if set.Len() != 0 {
+		t.Errorf("Clear: got %d, want 0", set.Len())
+	}
+	if !set.IsEmpty() {
+		t.Errorf("IsEmpty: got false")
+	}
+	if set.Has(123) {
+		t.Errorf("%s.Has: got false", set)
+	}
+}
+
+func TestTakeMin(t *testing.T) {
+	var set intsets.Sparse
+	set.Insert(456)
+	set.Insert(123)
+	set.Insert(789)
+	set.Insert(-123)
+	var got int
+	for i, want := range []int{-123, 123, 456, 789} {
+		if !set.TakeMin(&got) || got != want {
+			t.Errorf("TakeMin #%d: got %d, want %d", i, got, want)
+		}
+	}
+	if set.TakeMin(&got) {
+		t.Errorf("%s.TakeMin returned true", &set)
+	}
+	if err := set.Check(); err != nil {
+		t.Fatalf("check: %s: %#v", err, &set)
+	}
+}
+
+func TestMinAndMax(t *testing.T) {
+	values := []int{0, 456, 123, 789, -123} // elt 0 => empty set
+	wantMax := []int{intsets.MinInt, 456, 456, 789, 789}
+	wantMin := []int{intsets.MaxInt, 456, 123, 123, -123}
+
+	var set intsets.Sparse
+	for i, x := range values {
+		if i != 0 {
+			set.Insert(x)
+		}
+		if got, want := set.Min(), wantMin[i]; got != want {
+			t.Errorf("Min #%d: got %d, want %d", i, got, want)
+		}
+		if got, want := set.Max(), wantMax[i]; got != want {
+			t.Errorf("Max #%d: got %d, want %d", i, got, want)
+		}
+	}
+
+	set.Insert(intsets.MinInt)
+	if got, want := set.Min(), intsets.MinInt; got != want {
+		t.Errorf("Min: got %d, want %d", got, want)
+	}
+
+	set.Insert(intsets.MaxInt)
+	if got, want := set.Max(), intsets.MaxInt; got != want {
+		t.Errorf("Max: got %d, want %d", got, want)
+	}
+}
+
+func TestEquals(t *testing.T) {
+	var setX intsets.Sparse
+	setX.Insert(456)
+	setX.Insert(123)
+	setX.Insert(789)
+
+	if !setX.Equals(&setX) {
+		t.Errorf("Equals(%s, %s): got false", &setX, &setX)
+	}
+
+	var setY intsets.Sparse
+	setY.Insert(789)
+	setY.Insert(456)
+	setY.Insert(123)
+
+	if !setX.Equals(&setY) {
+		t.Errorf("Equals(%s, %s): got false", &setX, &setY)
+	}
+
+	setY.Insert(1)
+	if setX.Equals(&setY) {
+		t.Errorf("Equals(%s, %s): got true", &setX, &setY)
+	}
+
+	var empty intsets.Sparse
+	if setX.Equals(&empty) {
+		t.Errorf("Equals(%s, %s): got true", &setX, &empty)
+	}
+
+	// Edge case: some block (with offset=0) appears in X but not Y.
+	setY.Remove(123)
+	if setX.Equals(&setY) {
+		t.Errorf("Equals(%s, %s): got true", &setX, &setY)
+	}
+}
+
+// A pset is a parallel implementation of a set using both an intsets.Sparse
+// and a built-in hash map.
+type pset struct {
+	hash map[int]bool
+	bits intsets.Sparse
+}
+
+func makePset() *pset {
+	return &pset{hash: make(map[int]bool)}
+}
+
+func (set *pset) add(n int) {
+	prev := len(set.hash)
+	set.hash[n] = true
+	grewA := len(set.hash) > prev
+
+	grewB := set.bits.Insert(n)
+
+	if grewA != grewB {
+		panic(fmt.Sprintf("add(%d): grewA=%t grewB=%t", n, grewA, grewB))
+	}
+}
+
+func (set *pset) remove(n int) {
+	prev := len(set.hash)
+	delete(set.hash, n)
+	shrankA := len(set.hash) < prev
+
+	shrankB := set.bits.Remove(n)
+
+	if shrankA != shrankB {
+		panic(fmt.Sprintf("remove(%d): shrankA=%t shrankB=%t", n, shrankA, shrankB))
+	}
+}
+
+func (set *pset) check(t *testing.T, msg string) {
+	var eltsA []int
+	for elt := range set.hash {
+		eltsA = append(eltsA, int(elt))
+	}
+	sort.Ints(eltsA)
+
+	eltsB := set.bits.AppendTo(nil)
+
+	if a, b := fmt.Sprint(eltsA), fmt.Sprint(eltsB); a != b {
+		t.Errorf("check(%s): hash=%s bits=%s (%s)", msg, a, b, &set.bits)
+	}
+
+	if err := set.bits.Check(); err != nil {
+		t.Fatalf("Check(%s): %s: %#v", msg, err, &set.bits)
+	}
+}
+
+// randomPset returns a parallel set of random size and elements.
+func randomPset(prng *rand.Rand, maxSize int) *pset {
+	set := makePset()
+	size := int(prng.Int()) % maxSize
+	for i := 0; i < size; i++ {
+		// TODO(adonovan): benchmark how performance varies
+		// with this sparsity parameter.
+		n := int(prng.Int()) % 10000
+		set.add(n)
+	}
+	return set
+}
+
+// TestRandomMutations performs the same random adds/removes on two
+// set implementations and ensures that they compute the same result.
+func TestRandomMutations(t *testing.T) {
+	const debug = false
+
+	set := makePset()
+	prng := rand.New(rand.NewSource(0))
+	for i := 0; i < 10000; i++ {
+		n := int(prng.Int())%2000 - 1000
+		if i%2 == 0 {
+			if debug {
+				log.Printf("add %d", n)
+			}
+			set.add(n)
+		} else {
+			if debug {
+				log.Printf("remove %d", n)
+			}
+			set.remove(n)
+		}
+		if debug {
+			set.check(t, "post mutation")
+		}
+	}
+	set.check(t, "final")
+	if debug {
+		log.Print(&set.bits)
+	}
+}
+
+// TestSetOperations exercises classic set operations: ∩ , ∪, \.
+func TestSetOperations(t *testing.T) {
+	prng := rand.New(rand.NewSource(0))
+
+	// Use random sets of sizes from 0 to about 1000.
+	// For each operator, we test variations such as
+	// Z.op(X, Y), Z.op(X, Z) and Z.op(Z, Y) to exercise
+	// the degenerate cases of each method implementation.
+	for i := uint(0); i < 12; i++ {
+		X := randomPset(prng, 1<<i)
+		Y := randomPset(prng, 1<<i)
+
+		// TODO(adonovan): minimise dependencies between stanzas below.
+
+		// Copy(X)
+		C := makePset()
+		C.bits.Copy(&Y.bits) // no effect on result
+		C.bits.Copy(&X.bits)
+		C.hash = X.hash
+		C.check(t, "C.Copy(X)")
+		C.bits.Copy(&C.bits)
+		C.check(t, "C.Copy(C)")
+
+		// U.Union(X, Y)
+		U := makePset()
+		U.bits.Union(&X.bits, &Y.bits)
+		for n := range X.hash {
+			U.hash[n] = true
+		}
+		for n := range Y.hash {
+			U.hash[n] = true
+		}
+		U.check(t, "U.Union(X, Y)")
+
+		// U.Union(X, X)
+		U.bits.Union(&X.bits, &X.bits)
+		U.hash = X.hash
+		U.check(t, "U.Union(X, X)")
+
+		// U.Union(U, Y)
+		U = makePset()
+		U.bits.Copy(&X.bits)
+		U.bits.Union(&U.bits, &Y.bits)
+		for n := range X.hash {
+			U.hash[n] = true
+		}
+		for n := range Y.hash {
+			U.hash[n] = true
+		}
+		U.check(t, "U.Union(U, Y)")
+
+		// U.Union(X, U)
+		U.bits.Copy(&Y.bits)
+		U.bits.Union(&X.bits, &U.bits)
+		U.check(t, "U.Union(X, U)")
+
+		// U.UnionWith(U)
+		U.bits.UnionWith(&U.bits)
+		U.check(t, "U.UnionWith(U)")
+
+		// I.Intersection(X, Y)
+		I := makePset()
+		I.bits.Intersection(&X.bits, &Y.bits)
+		for n := range X.hash {
+			if Y.hash[n] {
+				I.hash[n] = true
+			}
+		}
+		I.check(t, "I.Intersection(X, Y)")
+
+		// I.Intersection(X, X)
+		I.bits.Intersection(&X.bits, &X.bits)
+		I.hash = X.hash
+		I.check(t, "I.Intersection(X, X)")
+
+		// I.Intersection(I, X)
+		I.bits.Intersection(&I.bits, &X.bits)
+		I.check(t, "I.Intersection(I, X)")
+
+		// I.Intersection(X, I)
+		I.bits.Intersection(&X.bits, &I.bits)
+		I.check(t, "I.Intersection(X, I)")
+
+		// I.Intersection(I, I)
+		I.bits.Intersection(&I.bits, &I.bits)
+		I.check(t, "I.Intersection(I, I)")
+
+		// D.Difference(X, Y)
+		D := makePset()
+		D.bits.Difference(&X.bits, &Y.bits)
+		for n := range X.hash {
+			if !Y.hash[n] {
+				D.hash[n] = true
+			}
+		}
+		D.check(t, "D.Difference(X, Y)")
+
+		// D.Difference(D, Y)
+		D.bits.Copy(&X.bits)
+		D.bits.Difference(&D.bits, &Y.bits)
+		D.check(t, "D.Difference(D, Y)")
+
+		// D.Difference(Y, D)
+		D.bits.Copy(&X.bits)
+		D.bits.Difference(&Y.bits, &D.bits)
+		D.hash = make(map[int]bool)
+		for n := range Y.hash {
+			if !X.hash[n] {
+				D.hash[n] = true
+			}
+		}
+		D.check(t, "D.Difference(Y, D)")
+
+		// D.Difference(X, X)
+		D.bits.Difference(&X.bits, &X.bits)
+		D.hash = nil
+		D.check(t, "D.Difference(X, X)")
+
+		// D.DifferenceWith(D)
+		D.bits.Copy(&X.bits)
+		D.bits.DifferenceWith(&D.bits)
+		D.check(t, "D.DifferenceWith(D)")
+
+		// SD.SymmetricDifference(X, Y)
+		SD := makePset()
+		SD.bits.SymmetricDifference(&X.bits, &Y.bits)
+		for n := range X.hash {
+			if !Y.hash[n] {
+				SD.hash[n] = true
+			}
+		}
+		for n := range Y.hash {
+			if !X.hash[n] {
+				SD.hash[n] = true
+			}
+		}
+		SD.check(t, "SD.SymmetricDifference(X, Y)")
+
+		// X.SymmetricDifferenceWith(Y)
+		SD.bits.Copy(&X.bits)
+		SD.bits.SymmetricDifferenceWith(&Y.bits)
+		SD.check(t, "X.SymmetricDifference(Y)")
+
+		// Y.SymmetricDifferenceWith(X)
+		SD.bits.Copy(&Y.bits)
+		SD.bits.SymmetricDifferenceWith(&X.bits)
+		SD.check(t, "Y.SymmetricDifference(X)")
+
+		// SD.SymmetricDifference(X, X)
+		SD.bits.SymmetricDifference(&X.bits, &X.bits)
+		SD.hash = nil
+		SD.check(t, "SD.SymmetricDifference(X, X)")
+
+		// SD.SymmetricDifference(X, Copy(X))
+		X2 := makePset()
+		X2.bits.Copy(&X.bits)
+		SD.bits.SymmetricDifference(&X.bits, &X2.bits)
+		SD.check(t, "SD.SymmetricDifference(X, Copy(X))")
+
+		// Copy(X).SymmetricDifferenceWith(X)
+		SD.bits.Copy(&X.bits)
+		SD.bits.SymmetricDifferenceWith(&X.bits)
+		SD.check(t, "Copy(X).SymmetricDifferenceWith(X)")
+	}
+}
+
+func TestIntersectionWith(t *testing.T) {
+	// Edge cases: the pairs (1,1), (1000,2000), (8000,4000)
+	// exercise the <, >, == cases in IntersectionWith that the
+	// TestSetOperations data is too dense to cover.
+	var X, Y intsets.Sparse
+	X.Insert(1)
+	X.Insert(1000)
+	X.Insert(8000)
+	Y.Insert(1)
+	Y.Insert(2000)
+	Y.Insert(4000)
+	X.IntersectionWith(&Y)
+	if got, want := X.String(), "{1}"; got != want {
+		t.Errorf("IntersectionWith: got %s, want %s", got, want)
+	}
+}
+
+func TestIntersects(t *testing.T) {
+	prng := rand.New(rand.NewSource(0))
+
+	for i := uint(0); i < 12; i++ {
+		X, Y := randomPset(prng, 1<<i), randomPset(prng, 1<<i)
+		x, y := &X.bits, &Y.bits
+
+		// test the slow way
+		var z intsets.Sparse
+		z.Copy(x)
+		z.IntersectionWith(y)
+
+		if got, want := x.Intersects(y), !z.IsEmpty(); got != want {
+			t.Errorf("Intersects: got %v, want %v", got, want)
+		}
+
+		// make it false
+		a := x.AppendTo(nil)
+		for _, v := range a {
+			y.Remove(v)
+		}
+
+		if got, want := x.Intersects(y), false; got != want {
+			t.Errorf("Intersects: got %v, want %v", got, want)
+		}
+
+		// make it true
+		if x.IsEmpty() {
+			continue
+		}
+		i := prng.Intn(len(a))
+		y.Insert(a[i])
+
+		if got, want := x.Intersects(y), true; got != want {
+			t.Errorf("Intersects: got %v, want %v", got, want)
+		}
+	}
+}
+
+func TestSubsetOf(t *testing.T) {
+	prng := rand.New(rand.NewSource(0))
+
+	for i := uint(0); i < 12; i++ {
+		X, Y := randomPset(prng, 1<<i), randomPset(prng, 1<<i)
+		x, y := &X.bits, &Y.bits
+
+		// test the slow way
+		var z intsets.Sparse
+		z.Copy(x)
+		z.DifferenceWith(y)
+
+		if got, want := x.SubsetOf(y), z.IsEmpty(); got != want {
+			t.Errorf("SubsetOf: got %v, want %v", got, want)
+		}
+
+		// make it true
+		y.UnionWith(x)
+
+		if got, want := x.SubsetOf(y), true; got != want {
+			t.Errorf("SubsetOf: got %v, want %v", got, want)
+		}
+
+		// make it false
+		if x.IsEmpty() {
+			continue
+		}
+		a := x.AppendTo(nil)
+		i := prng.Intn(len(a))
+		y.Remove(a[i])
+
+		if got, want := x.SubsetOf(y), false; got != want {
+			t.Errorf("SubsetOf: got %v, want %v", got, want)
+		}
+	}
+}
+
+func TestBitString(t *testing.T) {
+	for _, test := range []struct {
+		input []int
+		want  string
+	}{
+		{nil, "0"},
+		{[]int{0}, "1"},
+		{[]int{0, 4, 5}, "110001"},
+		{[]int{0, 7, 177}, "1" + strings.Repeat("0", 169) + "10000001"},
+		{[]int{-3, 0, 4, 5}, "110001.001"},
+		{[]int{-3}, "0.001"},
+	} {
+		var set intsets.Sparse
+		for _, x := range test.input {
+			set.Insert(x)
+		}
+		if got := set.BitString(); got != test.want {
+			t.Errorf("BitString(%s) = %s, want %s", set.String(), got, test.want)
+		}
+	}
+}
+
+func TestFailFastOnShallowCopy(t *testing.T) {
+	var x intsets.Sparse
+	x.Insert(1)
+
+	y := x // shallow copy (breaks representation invariants)
+	defer func() {
+		got := fmt.Sprint(recover())
+		want := "A Sparse has been copied without (*Sparse).Copy()"
+		if got != want {
+			t.Errorf("shallow copy: recover() = %q, want %q", got, want)
+		}
+	}()
+	y.String() // panics
+	t.Error("didn't panic as expected")
+}
+
+// -- Benchmarks -------------------------------------------------------
+
+// TODO(adonovan):
+// - Add benchmarks of each method.
+// - Gather set distributions from pointer analysis.
+// - Measure memory usage.
+
+func BenchmarkSparseBitVector(b *testing.B) {
+	prng := rand.New(rand.NewSource(0))
+	for tries := 0; tries < b.N; tries++ {
+		var x, y, z intsets.Sparse
+		for i := 0; i < 1000; i++ {
+			n := int(prng.Int()) % 100000
+			if i%2 == 0 {
+				x.Insert(n)
+			} else {
+				y.Insert(n)
+			}
+		}
+		z.Union(&x, &y)
+		z.Difference(&x, &y)
+	}
+}
+
+func BenchmarkHashTable(b *testing.B) {
+	prng := rand.New(rand.NewSource(0))
+	for tries := 0; tries < b.N; tries++ {
+		x, y, z := make(map[int]bool), make(map[int]bool), make(map[int]bool)
+		for i := 0; i < 1000; i++ {
+			n := int(prng.Int()) % 100000
+			if i%2 == 0 {
+				x[n] = true
+			} else {
+				y[n] = true
+			}
+		}
+		// union
+		for n := range x {
+			z[n] = true
+		}
+		for n := range y {
+			z[n] = true
+		}
+		// difference
+		z = make(map[int]bool)
+		for n := range y {
+			if !x[n] {
+				z[n] = true
+			}
+		}
+	}
+}
+
+func BenchmarkAppendTo(b *testing.B) {
+	prng := rand.New(rand.NewSource(0))
+	var x intsets.Sparse
+	for i := 0; i < 1000; i++ {
+		x.Insert(int(prng.Int()) % 10000)
+	}
+	var space [1000]int
+	for tries := 0; tries < b.N; tries++ {
+		x.AppendTo(space[:0])
+	}
+}
diff --git a/container/intsets/util.go b/container/intsets/util.go
new file mode 100644
index 0000000..76e682c
--- /dev/null
+++ b/container/intsets/util.go
@@ -0,0 +1,75 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package intsets
+
+var a [1 << 8]byte
+
+func init() {
+	for i := range a {
+		var n byte
+		for x := i; x != 0; x >>= 1 {
+			if x&1 != 0 {
+				n++
+			}
+		}
+		a[i] = n
+	}
+}
+
+// popcount returns the population count (number of set bits) of x.
+func popcount(x word) int {
+	return int(a[byte(x>>(0*8))] +
+		a[byte(x>>(1*8))] +
+		a[byte(x>>(2*8))] +
+		a[byte(x>>(3*8))] +
+		a[byte(x>>(4*8))] +
+		a[byte(x>>(5*8))] +
+		a[byte(x>>(6*8))] +
+		a[byte(x>>(7*8))])
+}
+
+// nlz returns the number of leading zeros of x.
+// From Hacker's Delight, fig 5.11.
+func nlz(x word) int {
+	x |= (x >> 1)
+	x |= (x >> 2)
+	x |= (x >> 4)
+	x |= (x >> 8)
+	x |= (x >> 16)
+	x |= (x >> 32)
+	return popcount(^x)
+}
+
+// ntz returns the number of trailing zeros of x.
+// From Hacker's Delight, fig 5.13.
+func ntz(x word) int {
+	if x == 0 {
+		return bitsPerWord
+	}
+	n := 1
+	if bitsPerWord == 64 {
+		if (x & 0xffffffff) == 0 {
+			n = n + 32
+			x = x >> 32
+		}
+	}
+	if (x & 0x0000ffff) == 0 {
+		n = n + 16
+		x = x >> 16
+	}
+	if (x & 0x000000ff) == 0 {
+		n = n + 8
+		x = x >> 8
+	}
+	if (x & 0x0000000f) == 0 {
+		n = n + 4
+		x = x >> 4
+	}
+	if (x & 0x00000003) == 0 {
+		n = n + 2
+		x = x >> 2
+	}
+	return n - int(x&1)
+}
diff --git a/container/intsets/util_test.go b/container/intsets/util_test.go
new file mode 100644
index 0000000..92a4bc5
--- /dev/null
+++ b/container/intsets/util_test.go
@@ -0,0 +1,25 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package intsets
+
+import "testing"
+
+func TestNLZ(t *testing.T) {
+	// Test the platform-specific edge case.
+	// NB: v must be a var (not const) so that the word() conversion is dynamic.
+	// Otherwise the compiler will report an error.
+	v := uint64(0x0000801000000000)
+	n := nlz(word(v))
+	want := 32 // (on 32-bit)
+	if bitsPerWord == 64 {
+		want = 16
+	}
+	if n != want {
+		t.Errorf("%d-bit nlz(%d) = %d, want %d", bitsPerWord, v, n, want)
+	}
+}
+
+// Backdoor for testing.
+func (s *Sparse) Check() error { return s.check() }
diff --git a/cover/profile.go b/cover/profile.go
new file mode 100644
index 0000000..a53bf4e
--- /dev/null
+++ b/cover/profile.go
@@ -0,0 +1,190 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package cover provides support for parsing coverage profiles
+// generated by "go test -coverprofile=cover.out".
+package cover // import "golang.org/x/tools/cover"
+
+import (
+	"bufio"
+	"fmt"
+	"math"
+	"os"
+	"regexp"
+	"sort"
+	"strconv"
+	"strings"
+)
+
+// Profile represents the profiling data for a specific file.
+type Profile struct {
+	FileName string
+	Mode     string
+	Blocks   []ProfileBlock
+}
+
+// ProfileBlock represents a single block of profiling data.
+type ProfileBlock struct {
+	StartLine, StartCol int
+	EndLine, EndCol     int
+	NumStmt, Count      int
+}
+
+type byFileName []*Profile
+
+func (p byFileName) Len() int           { return len(p) }
+func (p byFileName) Less(i, j int) bool { return p[i].FileName < p[j].FileName }
+func (p byFileName) Swap(i, j int)      { p[i], p[j] = p[j], p[i] }
+
+// ParseProfiles parses profile data in the specified file and returns a
+// Profile for each source file described therein.
+func ParseProfiles(fileName string) ([]*Profile, error) {
+	pf, err := os.Open(fileName)
+	if err != nil {
+		return nil, err
+	}
+	defer pf.Close()
+
+	files := make(map[string]*Profile)
+	buf := bufio.NewReader(pf)
+	// First line is "mode: foo", where foo is "set", "count", or "atomic".
+	// Rest of file is in the format
+	//	encoding/base64/base64.go:34.44,37.40 3 1
+	// where the fields are: name.go:line.column,line.column numberOfStatements count
+	s := bufio.NewScanner(buf)
+	mode := ""
+	for s.Scan() {
+		line := s.Text()
+		if mode == "" {
+			const p = "mode: "
+			if !strings.HasPrefix(line, p) || line == p {
+				return nil, fmt.Errorf("bad mode line: %v", line)
+			}
+			mode = line[len(p):]
+			continue
+		}
+		m := lineRe.FindStringSubmatch(line)
+		if m == nil {
+			return nil, fmt.Errorf("line %q doesn't match expected format: %v", m, lineRe)
+		}
+		fn := m[1]
+		p := files[fn]
+		if p == nil {
+			p = &Profile{
+				FileName: fn,
+				Mode:     mode,
+			}
+			files[fn] = p
+		}
+		p.Blocks = append(p.Blocks, ProfileBlock{
+			StartLine: toInt(m[2]),
+			StartCol:  toInt(m[3]),
+			EndLine:   toInt(m[4]),
+			EndCol:    toInt(m[5]),
+			NumStmt:   toInt(m[6]),
+			Count:     toInt(m[7]),
+		})
+	}
+	if err := s.Err(); err != nil {
+		return nil, err
+	}
+	for _, p := range files {
+		sort.Sort(blocksByStart(p.Blocks))
+	}
+	// Generate a sorted slice.
+	profiles := make([]*Profile, 0, len(files))
+	for _, profile := range files {
+		profiles = append(profiles, profile)
+	}
+	sort.Sort(byFileName(profiles))
+	return profiles, nil
+}
+
+type blocksByStart []ProfileBlock
+
+func (b blocksByStart) Len() int      { return len(b) }
+func (b blocksByStart) Swap(i, j int) { b[i], b[j] = b[j], b[i] }
+func (b blocksByStart) Less(i, j int) bool {
+	bi, bj := b[i], b[j]
+	return bi.StartLine < bj.StartLine || bi.StartLine == bj.StartLine && bi.StartCol < bj.StartCol
+}
+
+var lineRe = regexp.MustCompile(`^(.+):([0-9]+).([0-9]+),([0-9]+).([0-9]+) ([0-9]+) ([0-9]+)$`)
+
+func toInt(s string) int {
+	i, err := strconv.Atoi(s)
+	if err != nil {
+		panic(err)
+	}
+	return i
+}
+
+// Boundary represents the position in a source file of the beginning or end of a
+// block as reported by the coverage profile. In HTML mode, it will correspond to
+// the opening or closing of a <span> tag and will be used to colorize the source
+type Boundary struct {
+	Offset int     // Location as a byte offset in the source file.
+	Start  bool    // Is this the start of a block?
+	Count  int     // Event count from the cover profile.
+	Norm   float64 // Count normalized to [0..1].
+}
+
+// Boundaries returns a Profile as a set of Boundary objects within the provided src.
+func (p *Profile) Boundaries(src []byte) (boundaries []Boundary) {
+	// Find maximum count.
+	max := 0
+	for _, b := range p.Blocks {
+		if b.Count > max {
+			max = b.Count
+		}
+	}
+	// Divisor for normalization.
+	divisor := math.Log(float64(max))
+
+	// boundary returns a Boundary, populating the Norm field with a normalized Count.
+	boundary := func(offset int, start bool, count int) Boundary {
+		b := Boundary{Offset: offset, Start: start, Count: count}
+		if !start || count == 0 {
+			return b
+		}
+		if max <= 1 {
+			b.Norm = 0.8 // Profile is in"set" mode; we want a heat map. Use cov8 in the CSS.
+		} else if count > 0 {
+			b.Norm = math.Log(float64(count)) / divisor
+		}
+		return b
+	}
+
+	line, col := 1, 2 // TODO: Why is this 2?
+	for si, bi := 0, 0; si < len(src) && bi < len(p.Blocks); {
+		b := p.Blocks[bi]
+		if b.StartLine == line && b.StartCol == col {
+			boundaries = append(boundaries, boundary(si, true, b.Count))
+		}
+		if b.EndLine == line && b.EndCol == col || line > b.EndLine {
+			boundaries = append(boundaries, boundary(si, false, 0))
+			bi++
+			continue // Don't advance through src; maybe the next block starts here.
+		}
+		if src[si] == '\n' {
+			line++
+			col = 0
+		}
+		col++
+		si++
+	}
+	sort.Sort(boundariesByPos(boundaries))
+	return
+}
+
+type boundariesByPos []Boundary
+
+func (b boundariesByPos) Len() int      { return len(b) }
+func (b boundariesByPos) Swap(i, j int) { b[i], b[j] = b[j], b[i] }
+func (b boundariesByPos) Less(i, j int) bool {
+	if b[i].Offset == b[j].Offset {
+		return !b[i].Start && b[j].Start
+	}
+	return b[i].Offset < b[j].Offset
+}
diff --git a/go/ast/astutil/enclosing.go b/go/ast/astutil/enclosing.go
new file mode 100644
index 0000000..2de739e
--- /dev/null
+++ b/go/ast/astutil/enclosing.go
@@ -0,0 +1,625 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package astutil
+
+// This file defines utilities for working with source positions.
+
+import (
+	"fmt"
+	"go/ast"
+	"go/token"
+	"sort"
+)
+
+// PathEnclosingInterval returns the node that encloses the source
+// interval [start, end), and all its ancestors up to the AST root.
+//
+// The definition of "enclosing" used by this function considers
+// additional whitespace abutting a node to be enclosed by it.
+// In this example:
+//
+//              z := x + y // add them
+//                   <-A->
+//                  <----B----->
+//
+// the ast.BinaryExpr(+) node is considered to enclose interval B
+// even though its [Pos()..End()) is actually only interval A.
+// This behaviour makes user interfaces more tolerant of imperfect
+// input.
+//
+// This function treats tokens as nodes, though they are not included
+// in the result. e.g. PathEnclosingInterval("+") returns the
+// enclosing ast.BinaryExpr("x + y").
+//
+// If start==end, the 1-char interval following start is used instead.
+//
+// The 'exact' result is true if the interval contains only path[0]
+// and perhaps some adjacent whitespace.  It is false if the interval
+// overlaps multiple children of path[0], or if it contains only
+// interior whitespace of path[0].
+// In this example:
+//
+//              z := x + y // add them
+//                <--C-->     <---E-->
+//                  ^
+//                  D
+//
+// intervals C, D and E are inexact.  C is contained by the
+// z-assignment statement, because it spans three of its children (:=,
+// x, +).  So too is the 1-char interval D, because it contains only
+// interior whitespace of the assignment.  E is considered interior
+// whitespace of the BlockStmt containing the assignment.
+//
+// Precondition: [start, end) both lie within the same file as root.
+// TODO(adonovan): return (nil, false) in this case and remove precond.
+// Requires FileSet; see loader.tokenFileContainsPos.
+//
+// Postcondition: path is never nil; it always contains at least 'root'.
+//
+func PathEnclosingInterval(root *ast.File, start, end token.Pos) (path []ast.Node, exact bool) {
+	// fmt.Printf("EnclosingInterval %d %d\n", start, end) // debugging
+
+	// Precondition: node.[Pos..End) and adjoining whitespace contain [start, end).
+	var visit func(node ast.Node) bool
+	visit = func(node ast.Node) bool {
+		path = append(path, node)
+
+		nodePos := node.Pos()
+		nodeEnd := node.End()
+
+		// fmt.Printf("visit(%T, %d, %d)\n", node, nodePos, nodeEnd) // debugging
+
+		// Intersect [start, end) with interval of node.
+		if start < nodePos {
+			start = nodePos
+		}
+		if end > nodeEnd {
+			end = nodeEnd
+		}
+
+		// Find sole child that contains [start, end).
+		children := childrenOf(node)
+		l := len(children)
+		for i, child := range children {
+			// [childPos, childEnd) is unaugmented interval of child.
+			childPos := child.Pos()
+			childEnd := child.End()
+
+			// [augPos, augEnd) is whitespace-augmented interval of child.
+			augPos := childPos
+			augEnd := childEnd
+			if i > 0 {
+				augPos = children[i-1].End() // start of preceding whitespace
+			}
+			if i < l-1 {
+				nextChildPos := children[i+1].Pos()
+				// Does [start, end) lie between child and next child?
+				if start >= augEnd && end <= nextChildPos {
+					return false // inexact match
+				}
+				augEnd = nextChildPos // end of following whitespace
+			}
+
+			// fmt.Printf("\tchild %d: [%d..%d)\tcontains interval [%d..%d)?\n",
+			// 	i, augPos, augEnd, start, end) // debugging
+
+			// Does augmented child strictly contain [start, end)?
+			if augPos <= start && end <= augEnd {
+				_, isToken := child.(tokenNode)
+				return isToken || visit(child)
+			}
+
+			// Does [start, end) overlap multiple children?
+			// i.e. left-augmented child contains start
+			// but LR-augmented child does not contain end.
+			if start < childEnd && end > augEnd {
+				break
+			}
+		}
+
+		// No single child contained [start, end),
+		// so node is the result.  Is it exact?
+
+		// (It's tempting to put this condition before the
+		// child loop, but it gives the wrong result in the
+		// case where a node (e.g. ExprStmt) and its sole
+		// child have equal intervals.)
+		if start == nodePos && end == nodeEnd {
+			return true // exact match
+		}
+
+		return false // inexact: overlaps multiple children
+	}
+
+	if start > end {
+		start, end = end, start
+	}
+
+	if start < root.End() && end > root.Pos() {
+		if start == end {
+			end = start + 1 // empty interval => interval of size 1
+		}
+		exact = visit(root)
+
+		// Reverse the path:
+		for i, l := 0, len(path); i < l/2; i++ {
+			path[i], path[l-1-i] = path[l-1-i], path[i]
+		}
+	} else {
+		// Selection lies within whitespace preceding the
+		// first (or following the last) declaration in the file.
+		// The result nonetheless always includes the ast.File.
+		path = append(path, root)
+	}
+
+	return
+}
+
+// tokenNode is a dummy implementation of ast.Node for a single token.
+// They are used transiently by PathEnclosingInterval but never escape
+// this package.
+//
+type tokenNode struct {
+	pos token.Pos
+	end token.Pos
+}
+
+func (n tokenNode) Pos() token.Pos {
+	return n.pos
+}
+
+func (n tokenNode) End() token.Pos {
+	return n.end
+}
+
+func tok(pos token.Pos, len int) ast.Node {
+	return tokenNode{pos, pos + token.Pos(len)}
+}
+
+// childrenOf returns the direct non-nil children of ast.Node n.
+// It may include fake ast.Node implementations for bare tokens.
+// it is not safe to call (e.g.) ast.Walk on such nodes.
+//
+func childrenOf(n ast.Node) []ast.Node {
+	var children []ast.Node
+
+	// First add nodes for all true subtrees.
+	ast.Inspect(n, func(node ast.Node) bool {
+		if node == n { // push n
+			return true // recur
+		}
+		if node != nil { // push child
+			children = append(children, node)
+		}
+		return false // no recursion
+	})
+
+	// Then add fake Nodes for bare tokens.
+	switch n := n.(type) {
+	case *ast.ArrayType:
+		children = append(children,
+			tok(n.Lbrack, len("[")),
+			tok(n.Elt.End(), len("]")))
+
+	case *ast.AssignStmt:
+		children = append(children,
+			tok(n.TokPos, len(n.Tok.String())))
+
+	case *ast.BasicLit:
+		children = append(children,
+			tok(n.ValuePos, len(n.Value)))
+
+	case *ast.BinaryExpr:
+		children = append(children, tok(n.OpPos, len(n.Op.String())))
+
+	case *ast.BlockStmt:
+		children = append(children,
+			tok(n.Lbrace, len("{")),
+			tok(n.Rbrace, len("}")))
+
+	case *ast.BranchStmt:
+		children = append(children,
+			tok(n.TokPos, len(n.Tok.String())))
+
+	case *ast.CallExpr:
+		children = append(children,
+			tok(n.Lparen, len("(")),
+			tok(n.Rparen, len(")")))
+		if n.Ellipsis != 0 {
+			children = append(children, tok(n.Ellipsis, len("...")))
+		}
+
+	case *ast.CaseClause:
+		if n.List == nil {
+			children = append(children,
+				tok(n.Case, len("default")))
+		} else {
+			children = append(children,
+				tok(n.Case, len("case")))
+		}
+		children = append(children, tok(n.Colon, len(":")))
+
+	case *ast.ChanType:
+		switch n.Dir {
+		case ast.RECV:
+			children = append(children, tok(n.Begin, len("<-chan")))
+		case ast.SEND:
+			children = append(children, tok(n.Begin, len("chan<-")))
+		case ast.RECV | ast.SEND:
+			children = append(children, tok(n.Begin, len("chan")))
+		}
+
+	case *ast.CommClause:
+		if n.Comm == nil {
+			children = append(children,
+				tok(n.Case, len("default")))
+		} else {
+			children = append(children,
+				tok(n.Case, len("case")))
+		}
+		children = append(children, tok(n.Colon, len(":")))
+
+	case *ast.Comment:
+		// nop
+
+	case *ast.CommentGroup:
+		// nop
+
+	case *ast.CompositeLit:
+		children = append(children,
+			tok(n.Lbrace, len("{")),
+			tok(n.Rbrace, len("{")))
+
+	case *ast.DeclStmt:
+		// nop
+
+	case *ast.DeferStmt:
+		children = append(children,
+			tok(n.Defer, len("defer")))
+
+	case *ast.Ellipsis:
+		children = append(children,
+			tok(n.Ellipsis, len("...")))
+
+	case *ast.EmptyStmt:
+		// nop
+
+	case *ast.ExprStmt:
+		// nop
+
+	case *ast.Field:
+		// TODO(adonovan): Field.{Doc,Comment,Tag}?
+
+	case *ast.FieldList:
+		children = append(children,
+			tok(n.Opening, len("(")),
+			tok(n.Closing, len(")")))
+
+	case *ast.File:
+		// TODO test: Doc
+		children = append(children,
+			tok(n.Package, len("package")))
+
+	case *ast.ForStmt:
+		children = append(children,
+			tok(n.For, len("for")))
+
+	case *ast.FuncDecl:
+		// TODO(adonovan): FuncDecl.Comment?
+
+		// Uniquely, FuncDecl breaks the invariant that
+		// preorder traversal yields tokens in lexical order:
+		// in fact, FuncDecl.Recv precedes FuncDecl.Type.Func.
+		//
+		// As a workaround, we inline the case for FuncType
+		// here and order things correctly.
+		//
+		children = nil // discard ast.Walk(FuncDecl) info subtrees
+		children = append(children, tok(n.Type.Func, len("func")))
+		if n.Recv != nil {
+			children = append(children, n.Recv)
+		}
+		children = append(children, n.Name)
+		if n.Type.Params != nil {
+			children = append(children, n.Type.Params)
+		}
+		if n.Type.Results != nil {
+			children = append(children, n.Type.Results)
+		}
+		if n.Body != nil {
+			children = append(children, n.Body)
+		}
+
+	case *ast.FuncLit:
+		// nop
+
+	case *ast.FuncType:
+		if n.Func != 0 {
+			children = append(children,
+				tok(n.Func, len("func")))
+		}
+
+	case *ast.GenDecl:
+		children = append(children,
+			tok(n.TokPos, len(n.Tok.String())))
+		if n.Lparen != 0 {
+			children = append(children,
+				tok(n.Lparen, len("(")),
+				tok(n.Rparen, len(")")))
+		}
+
+	case *ast.GoStmt:
+		children = append(children,
+			tok(n.Go, len("go")))
+
+	case *ast.Ident:
+		children = append(children,
+			tok(n.NamePos, len(n.Name)))
+
+	case *ast.IfStmt:
+		children = append(children,
+			tok(n.If, len("if")))
+
+	case *ast.ImportSpec:
+		// TODO(adonovan): ImportSpec.{Doc,EndPos}?
+
+	case *ast.IncDecStmt:
+		children = append(children,
+			tok(n.TokPos, len(n.Tok.String())))
+
+	case *ast.IndexExpr:
+		children = append(children,
+			tok(n.Lbrack, len("{")),
+			tok(n.Rbrack, len("}")))
+
+	case *ast.InterfaceType:
+		children = append(children,
+			tok(n.Interface, len("interface")))
+
+	case *ast.KeyValueExpr:
+		children = append(children,
+			tok(n.Colon, len(":")))
+
+	case *ast.LabeledStmt:
+		children = append(children,
+			tok(n.Colon, len(":")))
+
+	case *ast.MapType:
+		children = append(children,
+			tok(n.Map, len("map")))
+
+	case *ast.ParenExpr:
+		children = append(children,
+			tok(n.Lparen, len("(")),
+			tok(n.Rparen, len(")")))
+
+	case *ast.RangeStmt:
+		children = append(children,
+			tok(n.For, len("for")),
+			tok(n.TokPos, len(n.Tok.String())))
+
+	case *ast.ReturnStmt:
+		children = append(children,
+			tok(n.Return, len("return")))
+
+	case *ast.SelectStmt:
+		children = append(children,
+			tok(n.Select, len("select")))
+
+	case *ast.SelectorExpr:
+		// nop
+
+	case *ast.SendStmt:
+		children = append(children,
+			tok(n.Arrow, len("<-")))
+
+	case *ast.SliceExpr:
+		children = append(children,
+			tok(n.Lbrack, len("[")),
+			tok(n.Rbrack, len("]")))
+
+	case *ast.StarExpr:
+		children = append(children, tok(n.Star, len("*")))
+
+	case *ast.StructType:
+		children = append(children, tok(n.Struct, len("struct")))
+
+	case *ast.SwitchStmt:
+		children = append(children, tok(n.Switch, len("switch")))
+
+	case *ast.TypeAssertExpr:
+		children = append(children,
+			tok(n.Lparen-1, len(".")),
+			tok(n.Lparen, len("(")),
+			tok(n.Rparen, len(")")))
+
+	case *ast.TypeSpec:
+		// TODO(adonovan): TypeSpec.{Doc,Comment}?
+
+	case *ast.TypeSwitchStmt:
+		children = append(children, tok(n.Switch, len("switch")))
+
+	case *ast.UnaryExpr:
+		children = append(children, tok(n.OpPos, len(n.Op.String())))
+
+	case *ast.ValueSpec:
+		// TODO(adonovan): ValueSpec.{Doc,Comment}?
+
+	default:
+		// Includes *ast.BadDecl, *ast.BadExpr, *ast.BadStmt.
+		panic(fmt.Sprintf("unexpected node type %T", n))
+	}
+
+	// TODO(adonovan): opt: merge the logic of ast.Inspect() into
+	// the switch above so we can make interleaved callbacks for
+	// both Nodes and Tokens in the right order and avoid the need
+	// to sort.
+	sort.Sort(byPos(children))
+
+	return children
+}
+
+type byPos []ast.Node
+
+func (sl byPos) Len() int {
+	return len(sl)
+}
+func (sl byPos) Less(i, j int) bool {
+	return sl[i].Pos() < sl[j].Pos()
+}
+func (sl byPos) Swap(i, j int) {
+	sl[i], sl[j] = sl[j], sl[i]
+}
+
+// NodeDescription returns a description of the concrete type of n suitable
+// for a user interface.
+//
+// TODO(adonovan): in some cases (e.g. Field, FieldList, Ident,
+// StarExpr) we could be much more specific given the path to the AST
+// root.  Perhaps we should do that.
+//
+func NodeDescription(n ast.Node) string {
+	switch n := n.(type) {
+	case *ast.ArrayType:
+		return "array type"
+	case *ast.AssignStmt:
+		return "assignment"
+	case *ast.BadDecl:
+		return "bad declaration"
+	case *ast.BadExpr:
+		return "bad expression"
+	case *ast.BadStmt:
+		return "bad statement"
+	case *ast.BasicLit:
+		return "basic literal"
+	case *ast.BinaryExpr:
+		return fmt.Sprintf("binary %s operation", n.Op)
+	case *ast.BlockStmt:
+		return "block"
+	case *ast.BranchStmt:
+		switch n.Tok {
+		case token.BREAK:
+			return "break statement"
+		case token.CONTINUE:
+			return "continue statement"
+		case token.GOTO:
+			return "goto statement"
+		case token.FALLTHROUGH:
+			return "fall-through statement"
+		}
+	case *ast.CallExpr:
+		return "function call (or conversion)"
+	case *ast.CaseClause:
+		return "case clause"
+	case *ast.ChanType:
+		return "channel type"
+	case *ast.CommClause:
+		return "communication clause"
+	case *ast.Comment:
+		return "comment"
+	case *ast.CommentGroup:
+		return "comment group"
+	case *ast.CompositeLit:
+		return "composite literal"
+	case *ast.DeclStmt:
+		return NodeDescription(n.Decl) + " statement"
+	case *ast.DeferStmt:
+		return "defer statement"
+	case *ast.Ellipsis:
+		return "ellipsis"
+	case *ast.EmptyStmt:
+		return "empty statement"
+	case *ast.ExprStmt:
+		return "expression statement"
+	case *ast.Field:
+		// Can be any of these:
+		// struct {x, y int}  -- struct field(s)
+		// struct {T}         -- anon struct field
+		// interface {I}      -- interface embedding
+		// interface {f()}    -- interface method
+		// func (A) func(B) C -- receiver, param(s), result(s)
+		return "field/method/parameter"
+	case *ast.FieldList:
+		return "field/method/parameter list"
+	case *ast.File:
+		return "source file"
+	case *ast.ForStmt:
+		return "for loop"
+	case *ast.FuncDecl:
+		return "function declaration"
+	case *ast.FuncLit:
+		return "function literal"
+	case *ast.FuncType:
+		return "function type"
+	case *ast.GenDecl:
+		switch n.Tok {
+		case token.IMPORT:
+			return "import declaration"
+		case token.CONST:
+			return "constant declaration"
+		case token.TYPE:
+			return "type declaration"
+		case token.VAR:
+			return "variable declaration"
+		}
+	case *ast.GoStmt:
+		return "go statement"
+	case *ast.Ident:
+		return "identifier"
+	case *ast.IfStmt:
+		return "if statement"
+	case *ast.ImportSpec:
+		return "import specification"
+	case *ast.IncDecStmt:
+		if n.Tok == token.INC {
+			return "increment statement"
+		}
+		return "decrement statement"
+	case *ast.IndexExpr:
+		return "index expression"
+	case *ast.InterfaceType:
+		return "interface type"
+	case *ast.KeyValueExpr:
+		return "key/value association"
+	case *ast.LabeledStmt:
+		return "statement label"
+	case *ast.MapType:
+		return "map type"
+	case *ast.Package:
+		return "package"
+	case *ast.ParenExpr:
+		return "parenthesized " + NodeDescription(n.X)
+	case *ast.RangeStmt:
+		return "range loop"
+	case *ast.ReturnStmt:
+		return "return statement"
+	case *ast.SelectStmt:
+		return "select statement"
+	case *ast.SelectorExpr:
+		return "selector"
+	case *ast.SendStmt:
+		return "channel send"
+	case *ast.SliceExpr:
+		return "slice expression"
+	case *ast.StarExpr:
+		return "*-operation" // load/store expr or pointer type
+	case *ast.StructType:
+		return "struct type"
+	case *ast.SwitchStmt:
+		return "switch statement"
+	case *ast.TypeAssertExpr:
+		return "type assertion"
+	case *ast.TypeSpec:
+		return "type specification"
+	case *ast.TypeSwitchStmt:
+		return "type switch"
+	case *ast.UnaryExpr:
+		return fmt.Sprintf("unary %s operation", n.Op)
+	case *ast.ValueSpec:
+		return "value specification"
+
+	}
+	panic(fmt.Sprintf("unexpected node type: %T", n))
+}
diff --git a/go/ast/astutil/enclosing_test.go b/go/ast/astutil/enclosing_test.go
new file mode 100644
index 0000000..107f87c
--- /dev/null
+++ b/go/ast/astutil/enclosing_test.go
@@ -0,0 +1,195 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package astutil_test
+
+// This file defines tests of PathEnclosingInterval.
+
+// TODO(adonovan): exhaustive tests that run over the whole input
+// tree, not just handcrafted examples.
+
+import (
+	"bytes"
+	"fmt"
+	"go/ast"
+	"go/parser"
+	"go/token"
+	"strings"
+	"testing"
+
+	"golang.org/x/tools/go/ast/astutil"
+)
+
+// pathToString returns a string containing the concrete types of the
+// nodes in path.
+func pathToString(path []ast.Node) string {
+	var buf bytes.Buffer
+	fmt.Fprint(&buf, "[")
+	for i, n := range path {
+		if i > 0 {
+			fmt.Fprint(&buf, " ")
+		}
+		fmt.Fprint(&buf, strings.TrimPrefix(fmt.Sprintf("%T", n), "*ast."))
+	}
+	fmt.Fprint(&buf, "]")
+	return buf.String()
+}
+
+// findInterval parses input and returns the [start, end) positions of
+// the first occurrence of substr in input.  f==nil indicates failure;
+// an error has already been reported in that case.
+//
+func findInterval(t *testing.T, fset *token.FileSet, input, substr string) (f *ast.File, start, end token.Pos) {
+	f, err := parser.ParseFile(fset, "<input>", input, 0)
+	if err != nil {
+		t.Errorf("parse error: %s", err)
+		return
+	}
+
+	i := strings.Index(input, substr)
+	if i < 0 {
+		t.Errorf("%q is not a substring of input", substr)
+		f = nil
+		return
+	}
+
+	filePos := fset.File(f.Package)
+	return f, filePos.Pos(i), filePos.Pos(i + len(substr))
+}
+
+// Common input for following tests.
+const input = `
+// Hello.
+package main
+import "fmt"
+func f() {}
+func main() {
+	z := (x + y) // add them
+        f() // NB: ExprStmt and its CallExpr have same Pos/End
+}
+`
+
+func TestPathEnclosingInterval_Exact(t *testing.T) {
+	// For the exact tests, we check that a substring is mapped to
+	// the canonical string for the node it denotes.
+	tests := []struct {
+		substr string // first occurrence of this string indicates interval
+		node   string // complete text of expected containing node
+	}{
+		{"package",
+			input[11 : len(input)-1]},
+		{"\npack",
+			input[11 : len(input)-1]},
+		{"main",
+			"main"},
+		{"import",
+			"import \"fmt\""},
+		{"\"fmt\"",
+			"\"fmt\""},
+		{"\nfunc f() {}\n",
+			"func f() {}"},
+		{"x ",
+			"x"},
+		{" y",
+			"y"},
+		{"z",
+			"z"},
+		{" + ",
+			"x + y"},
+		{" :=",
+			"z := (x + y)"},
+		{"x + y",
+			"x + y"},
+		{"(x + y)",
+			"(x + y)"},
+		{" (x + y) ",
+			"(x + y)"},
+		{" (x + y) // add",
+			"(x + y)"},
+		{"func",
+			"func f() {}"},
+		{"func f() {}",
+			"func f() {}"},
+		{"\nfun",
+			"func f() {}"},
+		{" f",
+			"f"},
+	}
+	for _, test := range tests {
+		f, start, end := findInterval(t, new(token.FileSet), input, test.substr)
+		if f == nil {
+			continue
+		}
+
+		path, exact := astutil.PathEnclosingInterval(f, start, end)
+		if !exact {
+			t.Errorf("PathEnclosingInterval(%q) not exact", test.substr)
+			continue
+		}
+
+		if len(path) == 0 {
+			if test.node != "" {
+				t.Errorf("PathEnclosingInterval(%q).path: got [], want %q",
+					test.substr, test.node)
+			}
+			continue
+		}
+
+		if got := input[path[0].Pos():path[0].End()]; got != test.node {
+			t.Errorf("PathEnclosingInterval(%q): got %q, want %q (path was %s)",
+				test.substr, got, test.node, pathToString(path))
+			continue
+		}
+	}
+}
+
+func TestPathEnclosingInterval_Paths(t *testing.T) {
+	// For these tests, we check only the path of the enclosing
+	// node, but not its complete text because it's often quite
+	// large when !exact.
+	tests := []struct {
+		substr string // first occurrence of this string indicates interval
+		path   string // the pathToString(),exact of the expected path
+	}{
+		{"// add",
+			"[BlockStmt FuncDecl File],false"},
+		{"(x + y",
+			"[ParenExpr AssignStmt BlockStmt FuncDecl File],false"},
+		{"x +",
+			"[BinaryExpr ParenExpr AssignStmt BlockStmt FuncDecl File],false"},
+		{"z := (x",
+			"[AssignStmt BlockStmt FuncDecl File],false"},
+		{"func f",
+			"[FuncDecl File],false"},
+		{"func f()",
+			"[FuncDecl File],false"},
+		{" f()",
+			"[FuncDecl File],false"},
+		{"() {}",
+			"[FuncDecl File],false"},
+		{"// Hello",
+			"[File],false"},
+		{" f",
+			"[Ident FuncDecl File],true"},
+		{"func ",
+			"[FuncDecl File],true"},
+		{"mai",
+			"[Ident File],true"},
+		{"f() // NB",
+			"[CallExpr ExprStmt BlockStmt FuncDecl File],true"},
+	}
+	for _, test := range tests {
+		f, start, end := findInterval(t, new(token.FileSet), input, test.substr)
+		if f == nil {
+			continue
+		}
+
+		path, exact := astutil.PathEnclosingInterval(f, start, end)
+		if got := fmt.Sprintf("%s,%v", pathToString(path), exact); got != test.path {
+			t.Errorf("PathEnclosingInterval(%q): got %q, want %q",
+				test.substr, got, test.path)
+			continue
+		}
+	}
+}
diff --git a/go/ast/astutil/imports.go b/go/ast/astutil/imports.go
new file mode 100644
index 0000000..7f9b162
--- /dev/null
+++ b/go/ast/astutil/imports.go
@@ -0,0 +1,359 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package astutil contains common utilities for working with the Go AST.
+package astutil // import "golang.org/x/tools/go/ast/astutil"
+
+import (
+	"fmt"
+	"go/ast"
+	"go/token"
+	"strconv"
+	"strings"
+)
+
+// AddImport adds the import path to the file f, if absent.
+func AddImport(fset *token.FileSet, f *ast.File, ipath string) (added bool) {
+	return AddNamedImport(fset, f, "", ipath)
+}
+
+// AddNamedImport adds the import path to the file f, if absent.
+// If name is not empty, it is used to rename the import.
+//
+// For example, calling
+//	AddNamedImport(fset, f, "pathpkg", "path")
+// adds
+//	import pathpkg "path"
+func AddNamedImport(fset *token.FileSet, f *ast.File, name, ipath string) (added bool) {
+	if imports(f, ipath) {
+		return false
+	}
+
+	newImport := &ast.ImportSpec{
+		Path: &ast.BasicLit{
+			Kind:  token.STRING,
+			Value: strconv.Quote(ipath),
+		},
+	}
+	if name != "" {
+		newImport.Name = &ast.Ident{Name: name}
+	}
+
+	// Find an import decl to add to.
+	// The goal is to find an existing import
+	// whose import path has the longest shared
+	// prefix with ipath.
+	var (
+		bestMatch  = -1         // length of longest shared prefix
+		lastImport = -1         // index in f.Decls of the file's final import decl
+		impDecl    *ast.GenDecl // import decl containing the best match
+		impIndex   = -1         // spec index in impDecl containing the best match
+	)
+	for i, decl := range f.Decls {
+		gen, ok := decl.(*ast.GenDecl)
+		if ok && gen.Tok == token.IMPORT {
+			lastImport = i
+			// Do not add to import "C", to avoid disrupting the
+			// association with its doc comment, breaking cgo.
+			if declImports(gen, "C") {
+				continue
+			}
+
+			// Match an empty import decl if that's all that is available.
+			if len(gen.Specs) == 0 && bestMatch == -1 {
+				impDecl = gen
+			}
+
+			// Compute longest shared prefix with imports in this group.
+			for j, spec := range gen.Specs {
+				impspec := spec.(*ast.ImportSpec)
+				n := matchLen(importPath(impspec), ipath)
+				if n > bestMatch {
+					bestMatch = n
+					impDecl = gen
+					impIndex = j
+				}
+			}
+		}
+	}
+
+	// If no import decl found, add one after the last import.
+	if impDecl == nil {
+		impDecl = &ast.GenDecl{
+			Tok: token.IMPORT,
+		}
+		if lastImport >= 0 {
+			impDecl.TokPos = f.Decls[lastImport].End()
+		} else {
+			// There are no existing imports.
+			// Our new import goes after the package declaration and after
+			// the comment, if any, that starts on the same line as the
+			// package declaration.
+			impDecl.TokPos = f.Package
+
+			file := fset.File(f.Package)
+			pkgLine := file.Line(f.Package)
+			for _, c := range f.Comments {
+				if file.Line(c.Pos()) > pkgLine {
+					break
+				}
+				impDecl.TokPos = c.End()
+			}
+		}
+		f.Decls = append(f.Decls, nil)
+		copy(f.Decls[lastImport+2:], f.Decls[lastImport+1:])
+		f.Decls[lastImport+1] = impDecl
+	}
+
+	// Insert new import at insertAt.
+	insertAt := 0
+	if impIndex >= 0 {
+		// insert after the found import
+		insertAt = impIndex + 1
+	}
+	impDecl.Specs = append(impDecl.Specs, nil)
+	copy(impDecl.Specs[insertAt+1:], impDecl.Specs[insertAt:])
+	impDecl.Specs[insertAt] = newImport
+	pos := impDecl.Pos()
+	if insertAt > 0 {
+		// Assign same position as the previous import,
+		// so that the sorter sees it as being in the same block.
+		pos = impDecl.Specs[insertAt-1].Pos()
+	}
+	if newImport.Name != nil {
+		newImport.Name.NamePos = pos
+	}
+	newImport.Path.ValuePos = pos
+	newImport.EndPos = pos
+
+	// Clean up parens. impDecl contains at least one spec.
+	if len(impDecl.Specs) == 1 {
+		// Remove unneeded parens.
+		impDecl.Lparen = token.NoPos
+	} else if !impDecl.Lparen.IsValid() {
+		// impDecl needs parens added.
+		impDecl.Lparen = impDecl.Specs[0].Pos()
+	}
+
+	f.Imports = append(f.Imports, newImport)
+	return true
+}
+
+// DeleteImport deletes the import path from the file f, if present.
+func DeleteImport(fset *token.FileSet, f *ast.File, path string) (deleted bool) {
+	var delspecs []*ast.ImportSpec
+
+	// Find the import nodes that import path, if any.
+	for i := 0; i < len(f.Decls); i++ {
+		decl := f.Decls[i]
+		gen, ok := decl.(*ast.GenDecl)
+		if !ok || gen.Tok != token.IMPORT {
+			continue
+		}
+		for j := 0; j < len(gen.Specs); j++ {
+			spec := gen.Specs[j]
+			impspec := spec.(*ast.ImportSpec)
+			if importPath(impspec) != path {
+				continue
+			}
+
+			// We found an import spec that imports path.
+			// Delete it.
+			delspecs = append(delspecs, impspec)
+			deleted = true
+			copy(gen.Specs[j:], gen.Specs[j+1:])
+			gen.Specs = gen.Specs[:len(gen.Specs)-1]
+
+			// If this was the last import spec in this decl,
+			// delete the decl, too.
+			if len(gen.Specs) == 0 {
+				copy(f.Decls[i:], f.Decls[i+1:])
+				f.Decls = f.Decls[:len(f.Decls)-1]
+				i--
+				break
+			} else if len(gen.Specs) == 1 {
+				gen.Lparen = token.NoPos // drop parens
+			}
+			if j > 0 {
+				lastImpspec := gen.Specs[j-1].(*ast.ImportSpec)
+				lastLine := fset.Position(lastImpspec.Path.ValuePos).Line
+				line := fset.Position(impspec.Path.ValuePos).Line
+
+				// We deleted an entry but now there may be
+				// a blank line-sized hole where the import was.
+				if line-lastLine > 1 {
+					// There was a blank line immediately preceding the deleted import,
+					// so there's no need to close the hole.
+					// Do nothing.
+				} else {
+					// There was no blank line. Close the hole.
+					fset.File(gen.Rparen).MergeLine(line)
+				}
+			}
+			j--
+		}
+	}
+
+	// Delete them from f.Imports.
+	for i := 0; i < len(f.Imports); i++ {
+		imp := f.Imports[i]
+		for j, del := range delspecs {
+			if imp == del {
+				copy(f.Imports[i:], f.Imports[i+1:])
+				f.Imports = f.Imports[:len(f.Imports)-1]
+				copy(delspecs[j:], delspecs[j+1:])
+				delspecs = delspecs[:len(delspecs)-1]
+				i--
+				break
+			}
+		}
+	}
+
+	if len(delspecs) > 0 {
+		panic(fmt.Sprintf("deleted specs from Decls but not Imports: %v", delspecs))
+	}
+
+	return
+}
+
+// RewriteImport rewrites any import of path oldPath to path newPath.
+func RewriteImport(fset *token.FileSet, f *ast.File, oldPath, newPath string) (rewrote bool) {
+	for _, imp := range f.Imports {
+		if importPath(imp) == oldPath {
+			rewrote = true
+			// record old End, because the default is to compute
+			// it using the length of imp.Path.Value.
+			imp.EndPos = imp.End()
+			imp.Path.Value = strconv.Quote(newPath)
+		}
+	}
+	return
+}
+
+// UsesImport reports whether a given import is used.
+func UsesImport(f *ast.File, path string) (used bool) {
+	spec := importSpec(f, path)
+	if spec == nil {
+		return
+	}
+
+	name := spec.Name.String()
+	switch name {
+	case "<nil>":
+		// If the package name is not explicitly specified,
+		// make an educated guess. This is not guaranteed to be correct.
+		lastSlash := strings.LastIndex(path, "/")
+		if lastSlash == -1 {
+			name = path
+		} else {
+			name = path[lastSlash+1:]
+		}
+	case "_", ".":
+		// Not sure if this import is used - err on the side of caution.
+		return true
+	}
+
+	ast.Walk(visitFn(func(n ast.Node) {
+		sel, ok := n.(*ast.SelectorExpr)
+		if ok && isTopName(sel.X, name) {
+			used = true
+		}
+	}), f)
+
+	return
+}
+
+type visitFn func(node ast.Node)
+
+func (fn visitFn) Visit(node ast.Node) ast.Visitor {
+	fn(node)
+	return fn
+}
+
+// imports returns true if f imports path.
+func imports(f *ast.File, path string) bool {
+	return importSpec(f, path) != nil
+}
+
+// importSpec returns the import spec if f imports path,
+// or nil otherwise.
+func importSpec(f *ast.File, path string) *ast.ImportSpec {
+	for _, s := range f.Imports {
+		if importPath(s) == path {
+			return s
+		}
+	}
+	return nil
+}
+
+// importPath returns the unquoted import path of s,
+// or "" if the path is not properly quoted.
+func importPath(s *ast.ImportSpec) string {
+	t, err := strconv.Unquote(s.Path.Value)
+	if err == nil {
+		return t
+	}
+	return ""
+}
+
+// declImports reports whether gen contains an import of path.
+func declImports(gen *ast.GenDecl, path string) bool {
+	if gen.Tok != token.IMPORT {
+		return false
+	}
+	for _, spec := range gen.Specs {
+		impspec := spec.(*ast.ImportSpec)
+		if importPath(impspec) == path {
+			return true
+		}
+	}
+	return false
+}
+
+// matchLen returns the length of the longest path segment prefix shared by x and y.
+func matchLen(x, y string) int {
+	n := 0
+	for i := 0; i < len(x) && i < len(y) && x[i] == y[i]; i++ {
+		if x[i] == '/' {
+			n++
+		}
+	}
+	return n
+}
+
+// isTopName returns true if n is a top-level unresolved identifier with the given name.
+func isTopName(n ast.Expr, name string) bool {
+	id, ok := n.(*ast.Ident)
+	return ok && id.Name == name && id.Obj == nil
+}
+
+// Imports returns the file imports grouped by paragraph.
+func Imports(fset *token.FileSet, f *ast.File) [][]*ast.ImportSpec {
+	var groups [][]*ast.ImportSpec
+
+	for _, decl := range f.Decls {
+		genDecl, ok := decl.(*ast.GenDecl)
+		if !ok || genDecl.Tok != token.IMPORT {
+			break
+		}
+
+		group := []*ast.ImportSpec{}
+
+		var lastLine int
+		for _, spec := range genDecl.Specs {
+			importSpec := spec.(*ast.ImportSpec)
+			pos := importSpec.Path.ValuePos
+			line := fset.Position(pos).Line
+			if lastLine > 0 && pos > 0 && line-lastLine > 1 {
+				groups = append(groups, group)
+				group = []*ast.ImportSpec{}
+			}
+			group = append(group, importSpec)
+			lastLine = line
+		}
+		groups = append(groups, group)
+	}
+
+	return groups
+}
diff --git a/go/ast/astutil/imports_test.go b/go/ast/astutil/imports_test.go
new file mode 100644
index 0000000..9134b19
--- /dev/null
+++ b/go/ast/astutil/imports_test.go
@@ -0,0 +1,946 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package astutil
+
+import (
+	"bytes"
+	"go/ast"
+	"go/format"
+	"go/parser"
+	"go/token"
+	"reflect"
+	"strconv"
+	"testing"
+)
+
+var fset = token.NewFileSet()
+
+func parse(t *testing.T, name, in string) *ast.File {
+	file, err := parser.ParseFile(fset, name, in, parser.ParseComments)
+	if err != nil {
+		t.Fatalf("%s parse: %v", name, err)
+	}
+	return file
+}
+
+func print(t *testing.T, name string, f *ast.File) string {
+	var buf bytes.Buffer
+	if err := format.Node(&buf, fset, f); err != nil {
+		t.Fatalf("%s gofmt: %v", name, err)
+	}
+	return string(buf.Bytes())
+}
+
+type test struct {
+	name       string
+	renamedPkg string
+	pkg        string
+	in         string
+	out        string
+	broken     bool // known broken
+}
+
+var addTests = []test{
+	{
+		name: "leave os alone",
+		pkg:  "os",
+		in: `package main
+
+import (
+	"os"
+)
+`,
+		out: `package main
+
+import (
+	"os"
+)
+`,
+	},
+	{
+		name: "import.1",
+		pkg:  "os",
+		in: `package main
+`,
+		out: `package main
+
+import "os"
+`,
+	},
+	{
+		name: "import.2",
+		pkg:  "os",
+		in: `package main
+
+// Comment
+import "C"
+`,
+		out: `package main
+
+// Comment
+import "C"
+import "os"
+`,
+	},
+	{
+		name: "import.3",
+		pkg:  "os",
+		in: `package main
+
+// Comment
+import "C"
+
+import (
+	"io"
+	"utf8"
+)
+`,
+		out: `package main
+
+// Comment
+import "C"
+
+import (
+	"io"
+	"os"
+	"utf8"
+)
+`,
+	},
+	{
+		name: "import.17",
+		pkg:  "x/y/z",
+		in: `package main
+
+// Comment
+import "C"
+
+import (
+	"a"
+	"b"
+
+	"x/w"
+
+	"d/f"
+)
+`,
+		out: `package main
+
+// Comment
+import "C"
+
+import (
+	"a"
+	"b"
+
+	"x/w"
+	"x/y/z"
+
+	"d/f"
+)
+`,
+	},
+	{
+		name: "import into singular group",
+		pkg:  "bytes",
+		in: `package main
+
+import "os"
+
+`,
+		out: `package main
+
+import (
+	"bytes"
+	"os"
+)
+`,
+	},
+	{
+		name: "import into singular group with comment",
+		pkg:  "bytes",
+		in: `package main
+
+import /* why */ /* comment here? */ "os"
+
+`,
+		out: `package main
+
+import /* why */ /* comment here? */ (
+	"bytes"
+	"os"
+)
+`,
+	},
+	{
+		name: "import into group with leading comment",
+		pkg:  "strings",
+		in: `package main
+
+import (
+	// comment before bytes
+	"bytes"
+	"os"
+)
+
+`,
+		out: `package main
+
+import (
+	// comment before bytes
+	"bytes"
+	"os"
+	"strings"
+)
+`,
+	},
+	{
+		name:       "",
+		renamedPkg: "fmtpkg",
+		pkg:        "fmt",
+		in: `package main
+
+import "os"
+
+`,
+		out: `package main
+
+import (
+	fmtpkg "fmt"
+	"os"
+)
+`,
+	},
+	{
+		name: "struct comment",
+		pkg:  "time",
+		in: `package main
+
+// This is a comment before a struct.
+type T struct {
+	t  time.Time
+}
+`,
+		out: `package main
+
+import "time"
+
+// This is a comment before a struct.
+type T struct {
+	t time.Time
+}
+`,
+	},
+	{
+		name: "issue 8729 import C",
+		pkg:  "time",
+		in: `package main
+
+import "C"
+
+// comment
+type T time.Time
+`,
+		out: `package main
+
+import "C"
+import "time"
+
+// comment
+type T time.Time
+`,
+	},
+	{
+		name: "issue 8729 empty import",
+		pkg:  "time",
+		in: `package main
+
+import ()
+
+// comment
+type T time.Time
+`,
+		out: `package main
+
+import "time"
+
+// comment
+type T time.Time
+`,
+	},
+	{
+		name: "issue 8729 comment on package line",
+		pkg:  "time",
+		in: `package main // comment
+
+type T time.Time
+`,
+		out: `package main // comment
+import "time"
+
+type T time.Time
+`,
+	},
+	{
+		name: "issue 8729 comment after package",
+		pkg:  "time",
+		in: `package main
+// comment
+
+type T time.Time
+`,
+		out: `package main
+
+import "time"
+
+// comment
+
+type T time.Time
+`,
+	},
+	{
+		name: "issue 8729 comment before and on package line",
+		pkg:  "time",
+		in: `// comment before
+package main // comment on
+
+type T time.Time
+`,
+		out: `// comment before
+package main // comment on
+import "time"
+
+type T time.Time
+`,
+	},
+
+	// Issue 9961: Match prefixes using path segments rather than bytes
+	{
+		name: "issue 9961",
+		pkg:  "regexp",
+		in: `package main
+
+import (
+	"flag"
+	"testing"
+
+	"rsc.io/p"
+)
+`,
+		out: `package main
+
+import (
+	"flag"
+	"regexp"
+	"testing"
+
+	"rsc.io/p"
+)
+`,
+	},
+}
+
+func TestAddImport(t *testing.T) {
+	for _, test := range addTests {
+		file := parse(t, test.name, test.in)
+		var before bytes.Buffer
+		ast.Fprint(&before, fset, file, nil)
+		AddNamedImport(fset, file, test.renamedPkg, test.pkg)
+		if got := print(t, test.name, file); got != test.out {
+			if test.broken {
+				t.Logf("%s is known broken:\ngot: %s\nwant: %s", test.name, got, test.out)
+			} else {
+				t.Errorf("%s:\ngot: %s\nwant: %s", test.name, got, test.out)
+			}
+			var after bytes.Buffer
+			ast.Fprint(&after, fset, file, nil)
+
+			t.Logf("AST before:\n%s\nAST after:\n%s\n", before.String(), after.String())
+		}
+	}
+}
+
+func TestDoubleAddImport(t *testing.T) {
+	file := parse(t, "doubleimport", "package main\n")
+	AddImport(fset, file, "os")
+	AddImport(fset, file, "bytes")
+	want := `package main
+
+import (
+	"bytes"
+	"os"
+)
+`
+	if got := print(t, "doubleimport", file); got != want {
+		t.Errorf("got: %s\nwant: %s", got, want)
+	}
+}
+
+func TestDoubleAddNamedImport(t *testing.T) {
+	file := parse(t, "doublenamedimport", "package main\n")
+	AddNamedImport(fset, file, "o", "os")
+	AddNamedImport(fset, file, "i", "io")
+	want := `package main
+
+import (
+	i "io"
+	o "os"
+)
+`
+	if got := print(t, "doublenamedimport", file); got != want {
+		t.Errorf("got: %s\nwant: %s", got, want)
+	}
+}
+
+// Part of issue 8729.
+func TestDoubleAddImportWithDeclComment(t *testing.T) {
+	file := parse(t, "doubleimport", `package main
+
+import (
+)
+
+// comment
+type I int
+`)
+	// The AddImport order here matters.
+	AddImport(fset, file, "golang.org/x/tools/go/ast/astutil")
+	AddImport(fset, file, "os")
+	want := `package main
+
+import (
+	"golang.org/x/tools/go/ast/astutil"
+	"os"
+)
+
+// comment
+type I int
+`
+	if got := print(t, "doubleimport_with_decl_comment", file); got != want {
+		t.Errorf("got: %s\nwant: %s", got, want)
+	}
+}
+
+var deleteTests = []test{
+	{
+		name: "import.4",
+		pkg:  "os",
+		in: `package main
+
+import (
+	"os"
+)
+`,
+		out: `package main
+`,
+	},
+	{
+		name: "import.5",
+		pkg:  "os",
+		in: `package main
+
+// Comment
+import "C"
+import "os"
+`,
+		out: `package main
+
+// Comment
+import "C"
+`,
+	},
+	{
+		name: "import.6",
+		pkg:  "os",
+		in: `package main
+
+// Comment
+import "C"
+
+import (
+	"io"
+	"os"
+	"utf8"
+)
+`,
+		out: `package main
+
+// Comment
+import "C"
+
+import (
+	"io"
+	"utf8"
+)
+`,
+	},
+	{
+		name: "import.7",
+		pkg:  "io",
+		in: `package main
+
+import (
+	"io"   // a
+	"os"   // b
+	"utf8" // c
+)
+`,
+		out: `package main
+
+import (
+	// a
+	"os"   // b
+	"utf8" // c
+)
+`,
+	},
+	{
+		name: "import.8",
+		pkg:  "os",
+		in: `package main
+
+import (
+	"io"   // a
+	"os"   // b
+	"utf8" // c
+)
+`,
+		out: `package main
+
+import (
+	"io" // a
+	// b
+	"utf8" // c
+)
+`,
+	},
+	{
+		name: "import.9",
+		pkg:  "utf8",
+		in: `package main
+
+import (
+	"io"   // a
+	"os"   // b
+	"utf8" // c
+)
+`,
+		out: `package main
+
+import (
+	"io" // a
+	"os" // b
+	// c
+)
+`,
+	},
+	{
+		name: "import.10",
+		pkg:  "io",
+		in: `package main
+
+import (
+	"io"
+	"os"
+	"utf8"
+)
+`,
+		out: `package main
+
+import (
+	"os"
+	"utf8"
+)
+`,
+	},
+	{
+		name: "import.11",
+		pkg:  "os",
+		in: `package main
+
+import (
+	"io"
+	"os"
+	"utf8"
+)
+`,
+		out: `package main
+
+import (
+	"io"
+	"utf8"
+)
+`,
+	},
+	{
+		name: "import.12",
+		pkg:  "utf8",
+		in: `package main
+
+import (
+	"io"
+	"os"
+	"utf8"
+)
+`,
+		out: `package main
+
+import (
+	"io"
+	"os"
+)
+`,
+	},
+	{
+		name: "handle.raw.quote.imports",
+		pkg:  "os",
+		in:   "package main\n\nimport `os`",
+		out: `package main
+`,
+	},
+	{
+		name: "import.13",
+		pkg:  "io",
+		in: `package main
+
+import (
+	"fmt"
+
+	"io"
+	"os"
+	"utf8"
+
+	"go/format"
+)
+`,
+		out: `package main
+
+import (
+	"fmt"
+
+	"os"
+	"utf8"
+
+	"go/format"
+)
+`,
+	},
+	{
+		name: "import.14",
+		pkg:  "io",
+		in: `package main
+
+import (
+	"fmt" // a
+
+	"io"   // b
+	"os"   // c
+	"utf8" // d
+
+	"go/format" // e
+)
+`,
+		out: `package main
+
+import (
+	"fmt" // a
+
+	// b
+	"os"   // c
+	"utf8" // d
+
+	"go/format" // e
+)
+`,
+	},
+	{
+		name: "import.15",
+		pkg:  "double",
+		in: `package main
+
+import (
+	"double"
+	"double"
+)
+`,
+		out: `package main
+`,
+	},
+	{
+		name: "import.16",
+		pkg:  "bubble",
+		in: `package main
+
+import (
+	"toil"
+	"bubble"
+	"bubble"
+	"trouble"
+)
+`,
+		out: `package main
+
+import (
+	"toil"
+	"trouble"
+)
+`,
+	},
+	{
+		name: "import.17",
+		pkg:  "quad",
+		in: `package main
+
+import (
+	"quad"
+	"quad"
+)
+
+import (
+	"quad"
+	"quad"
+)
+`,
+		out: `package main
+`,
+	},
+}
+
+func TestDeleteImport(t *testing.T) {
+	for _, test := range deleteTests {
+		file := parse(t, test.name, test.in)
+		DeleteImport(fset, file, test.pkg)
+		if got := print(t, test.name, file); got != test.out {
+			t.Errorf("%s:\ngot: %s\nwant: %s", test.name, got, test.out)
+		}
+	}
+}
+
+type rewriteTest struct {
+	name   string
+	srcPkg string
+	dstPkg string
+	in     string
+	out    string
+}
+
+var rewriteTests = []rewriteTest{
+	{
+		name:   "import.13",
+		srcPkg: "utf8",
+		dstPkg: "encoding/utf8",
+		in: `package main
+
+import (
+	"io"
+	"os"
+	"utf8" // thanks ken
+)
+`,
+		out: `package main
+
+import (
+	"encoding/utf8" // thanks ken
+	"io"
+	"os"
+)
+`,
+	},
+	{
+		name:   "import.14",
+		srcPkg: "asn1",
+		dstPkg: "encoding/asn1",
+		in: `package main
+
+import (
+	"asn1"
+	"crypto"
+	"crypto/rsa"
+	_ "crypto/sha1"
+	"crypto/x509"
+	"crypto/x509/pkix"
+	"time"
+)
+
+var x = 1
+`,
+		out: `package main
+
+import (
+	"crypto"
+	"crypto/rsa"
+	_ "crypto/sha1"
+	"crypto/x509"
+	"crypto/x509/pkix"
+	"encoding/asn1"
+	"time"
+)
+
+var x = 1
+`,
+	},
+	{
+		name:   "import.15",
+		srcPkg: "url",
+		dstPkg: "net/url",
+		in: `package main
+
+import (
+	"bufio"
+	"net"
+	"path"
+	"url"
+)
+
+var x = 1 // comment on x, not on url
+`,
+		out: `package main
+
+import (
+	"bufio"
+	"net"
+	"net/url"
+	"path"
+)
+
+var x = 1 // comment on x, not on url
+`,
+	},
+	{
+		name:   "import.16",
+		srcPkg: "http",
+		dstPkg: "net/http",
+		in: `package main
+
+import (
+	"flag"
+	"http"
+	"log"
+	"text/template"
+)
+
+var addr = flag.String("addr", ":1718", "http service address") // Q=17, R=18
+`,
+		out: `package main
+
+import (
+	"flag"
+	"log"
+	"net/http"
+	"text/template"
+)
+
+var addr = flag.String("addr", ":1718", "http service address") // Q=17, R=18
+`,
+	},
+}
+
+func TestRewriteImport(t *testing.T) {
+	for _, test := range rewriteTests {
+		file := parse(t, test.name, test.in)
+		RewriteImport(fset, file, test.srcPkg, test.dstPkg)
+		if got := print(t, test.name, file); got != test.out {
+			t.Errorf("%s:\ngot: %s\nwant: %s", test.name, got, test.out)
+		}
+	}
+}
+
+var importsTests = []struct {
+	name string
+	in   string
+	want [][]string
+}{
+	{
+		name: "no packages",
+		in: `package foo
+`,
+		want: nil,
+	},
+	{
+		name: "one group",
+		in: `package foo
+
+import (
+	"fmt"
+	"testing"
+)
+`,
+		want: [][]string{{"fmt", "testing"}},
+	},
+	{
+		name: "four groups",
+		in: `package foo
+
+import "C"
+import (
+	"fmt"
+	"testing"
+
+	"appengine"
+
+	"myproject/mylib1"
+	"myproject/mylib2"
+)
+`,
+		want: [][]string{
+			{"C"},
+			{"fmt", "testing"},
+			{"appengine"},
+			{"myproject/mylib1", "myproject/mylib2"},
+		},
+	},
+	{
+		name: "multiple factored groups",
+		in: `package foo
+
+import (
+	"fmt"
+	"testing"
+
+	"appengine"
+)
+import (
+	"reflect"
+
+	"bytes"
+)
+`,
+		want: [][]string{
+			{"fmt", "testing"},
+			{"appengine"},
+			{"reflect"},
+			{"bytes"},
+		},
+	},
+}
+
+func unquote(s string) string {
+	res, err := strconv.Unquote(s)
+	if err != nil {
+		return "could_not_unquote"
+	}
+	return res
+}
+
+func TestImports(t *testing.T) {
+	fset := token.NewFileSet()
+	for _, test := range importsTests {
+		f, err := parser.ParseFile(fset, "test.go", test.in, 0)
+		if err != nil {
+			t.Errorf("%s: %v", test.name, err)
+			continue
+		}
+		var got [][]string
+		for _, group := range Imports(fset, f) {
+			var b []string
+			for _, spec := range group {
+				b = append(b, unquote(spec.Path.Value))
+			}
+			got = append(got, b)
+		}
+		if !reflect.DeepEqual(got, test.want) {
+			t.Errorf("Imports(%s)=%v, want %v", test.name, got, test.want)
+		}
+	}
+}
diff --git a/go/ast/astutil/util.go b/go/ast/astutil/util.go
new file mode 100644
index 0000000..7630629
--- /dev/null
+++ b/go/ast/astutil/util.go
@@ -0,0 +1,14 @@
+package astutil
+
+import "go/ast"
+
+// Unparen returns e with any enclosing parentheses stripped.
+func Unparen(e ast.Expr) ast.Expr {
+	for {
+		p, ok := e.(*ast.ParenExpr)
+		if !ok {
+			return e
+		}
+		e = p.X
+	}
+}
diff --git a/go/buildutil/allpackages.go b/go/buildutil/allpackages.go
new file mode 100644
index 0000000..0f909ee
--- /dev/null
+++ b/go/buildutil/allpackages.go
@@ -0,0 +1,123 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package buildutil provides utilities related to the go/build
+// package in the standard library.
+//
+// All I/O is done via the build.Context file system interface, which must
+// be concurrency-safe.
+package buildutil // import "golang.org/x/tools/go/buildutil"
+
+import (
+	"go/build"
+	"os"
+	"path/filepath"
+	"sort"
+	"strings"
+	"sync"
+)
+
+// AllPackages returns the import path of each Go package in any source
+// directory of the specified build context (e.g. $GOROOT or an element
+// of $GOPATH).  Errors are ignored.  The results are sorted.
+//
+// The result may include import paths for directories that contain no
+// *.go files, such as "archive" (in $GOROOT/src).
+//
+// All I/O is done via the build.Context file system interface,
+// which must be concurrency-safe.
+//
+func AllPackages(ctxt *build.Context) []string {
+	var list []string
+	ForEachPackage(ctxt, func(pkg string, _ error) {
+		list = append(list, pkg)
+	})
+	sort.Strings(list)
+	return list
+}
+
+// ForEachPackage calls the found function with the import path of
+// each Go package it finds in any source directory of the specified
+// build context (e.g. $GOROOT or an element of $GOPATH).
+//
+// If the package directory exists but could not be read, the second
+// argument to the found function provides the error.
+//
+// All I/O is done via the build.Context file system interface,
+// which must be concurrency-safe.
+//
+func ForEachPackage(ctxt *build.Context, found func(importPath string, err error)) {
+	// We use a counting semaphore to limit
+	// the number of parallel calls to ReadDir.
+	sema := make(chan bool, 20)
+
+	ch := make(chan item)
+
+	var wg sync.WaitGroup
+	for _, root := range ctxt.SrcDirs() {
+		root := root
+		wg.Add(1)
+		go func() {
+			allPackages(ctxt, sema, root, ch)
+			wg.Done()
+		}()
+	}
+	go func() {
+		wg.Wait()
+		close(ch)
+	}()
+
+	// All calls to found occur in the caller's goroutine.
+	for i := range ch {
+		found(i.importPath, i.err)
+	}
+}
+
+type item struct {
+	importPath string
+	err        error // (optional)
+}
+
+func allPackages(ctxt *build.Context, sema chan bool, root string, ch chan<- item) {
+	root = filepath.Clean(root) + string(os.PathSeparator)
+
+	var wg sync.WaitGroup
+
+	var walkDir func(dir string)
+	walkDir = func(dir string) {
+		// Avoid .foo, _foo, and testdata directory trees.
+		base := filepath.Base(dir)
+		if base == "" || base[0] == '.' || base[0] == '_' || base == "testdata" {
+			return
+		}
+
+		pkg := filepath.ToSlash(strings.TrimPrefix(dir, root))
+
+		// Prune search if we encounter any of these import paths.
+		switch pkg {
+		case "builtin":
+			return
+		}
+
+		sema <- true
+		files, err := ReadDir(ctxt, dir)
+		<-sema
+		if pkg != "" || err != nil {
+			ch <- item{pkg, err}
+		}
+		for _, fi := range files {
+			fi := fi
+			if fi.IsDir() {
+				wg.Add(1)
+				go func() {
+					walkDir(filepath.Join(dir, fi.Name()))
+					wg.Done()
+				}()
+			}
+		}
+	}
+
+	walkDir(root)
+	wg.Wait()
+}
diff --git a/go/buildutil/allpackages_test.go b/go/buildutil/allpackages_test.go
new file mode 100644
index 0000000..d5bd964
--- /dev/null
+++ b/go/buildutil/allpackages_test.go
@@ -0,0 +1,36 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Incomplete source tree on Android.
+
+// +build !android
+
+package buildutil_test
+
+import (
+	"go/build"
+	"testing"
+
+	"golang.org/x/tools/go/buildutil"
+)
+
+func TestAllPackages(t *testing.T) {
+	all := buildutil.AllPackages(&build.Default)
+
+	set := make(map[string]bool)
+	for _, pkg := range all {
+		set[pkg] = true
+	}
+
+	const wantAtLeast = 250
+	if len(all) < wantAtLeast {
+		t.Errorf("Found only %d packages, want at least %d", len(all), wantAtLeast)
+	}
+
+	for _, want := range []string{"fmt", "crypto/sha256", "golang.org/x/tools/go/buildutil"} {
+		if !set[want] {
+			t.Errorf("Package %q not found; got %s", want, all)
+		}
+	}
+}
diff --git a/go/buildutil/fakecontext.go b/go/buildutil/fakecontext.go
new file mode 100644
index 0000000..24cbcbe
--- /dev/null
+++ b/go/buildutil/fakecontext.go
@@ -0,0 +1,108 @@
+package buildutil
+
+import (
+	"fmt"
+	"go/build"
+	"io"
+	"io/ioutil"
+	"os"
+	"path"
+	"path/filepath"
+	"sort"
+	"strings"
+	"time"
+)
+
+// FakeContext returns a build.Context for the fake file tree specified
+// by pkgs, which maps package import paths to a mapping from file base
+// names to contents.
+//
+// The fake Context has a GOROOT of "/go" and no GOPATH, and overrides
+// the necessary file access methods to read from memory instead of the
+// real file system.
+//
+// Unlike a real file tree, the fake one has only two levels---packages
+// and files---so ReadDir("/go/src/") returns all packages under
+// /go/src/ including, for instance, "math" and "math/big".
+// ReadDir("/go/src/math/big") would return all the files in the
+// "math/big" package.
+//
+func FakeContext(pkgs map[string]map[string]string) *build.Context {
+	clean := func(filename string) string {
+		f := path.Clean(filepath.ToSlash(filename))
+		// Removing "/go/src" while respecting segment
+		// boundaries has this unfortunate corner case:
+		if f == "/go/src" {
+			return ""
+		}
+		return strings.TrimPrefix(f, "/go/src/")
+	}
+
+	ctxt := build.Default // copy
+	ctxt.GOROOT = "/go"
+	ctxt.GOPATH = ""
+	ctxt.IsDir = func(dir string) bool {
+		dir = clean(dir)
+		if dir == "" {
+			return true // needed by (*build.Context).SrcDirs
+		}
+		return pkgs[dir] != nil
+	}
+	ctxt.ReadDir = func(dir string) ([]os.FileInfo, error) {
+		dir = clean(dir)
+		var fis []os.FileInfo
+		if dir == "" {
+			// enumerate packages
+			for importPath := range pkgs {
+				fis = append(fis, fakeDirInfo(importPath))
+			}
+		} else {
+			// enumerate files of package
+			for basename := range pkgs[dir] {
+				fis = append(fis, fakeFileInfo(basename))
+			}
+		}
+		sort.Sort(byName(fis))
+		return fis, nil
+	}
+	ctxt.OpenFile = func(filename string) (io.ReadCloser, error) {
+		filename = clean(filename)
+		dir, base := path.Split(filename)
+		content, ok := pkgs[path.Clean(dir)][base]
+		if !ok {
+			return nil, fmt.Errorf("file not found: %s", filename)
+		}
+		return ioutil.NopCloser(strings.NewReader(content)), nil
+	}
+	ctxt.IsAbsPath = func(path string) bool {
+		path = filepath.ToSlash(path)
+		// Don't rely on the default (filepath.Path) since on
+		// Windows, it reports virtual paths as non-absolute.
+		return strings.HasPrefix(path, "/")
+	}
+	return &ctxt
+}
+
+type byName []os.FileInfo
+
+func (s byName) Len() int           { return len(s) }
+func (s byName) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }
+func (s byName) Less(i, j int) bool { return s[i].Name() < s[j].Name() }
+
+type fakeFileInfo string
+
+func (fi fakeFileInfo) Name() string    { return string(fi) }
+func (fakeFileInfo) Sys() interface{}   { return nil }
+func (fakeFileInfo) ModTime() time.Time { return time.Time{} }
+func (fakeFileInfo) IsDir() bool        { return false }
+func (fakeFileInfo) Size() int64        { return 0 }
+func (fakeFileInfo) Mode() os.FileMode  { return 0644 }
+
+type fakeDirInfo string
+
+func (fd fakeDirInfo) Name() string    { return string(fd) }
+func (fakeDirInfo) Sys() interface{}   { return nil }
+func (fakeDirInfo) ModTime() time.Time { return time.Time{} }
+func (fakeDirInfo) IsDir() bool        { return true }
+func (fakeDirInfo) Size() int64        { return 0 }
+func (fakeDirInfo) Mode() os.FileMode  { return 0755 }
diff --git a/go/buildutil/tags.go b/go/buildutil/tags.go
new file mode 100644
index 0000000..9735094
--- /dev/null
+++ b/go/buildutil/tags.go
@@ -0,0 +1,73 @@
+package buildutil
+
+// This logic was copied from stringsFlag from $GOROOT/src/cmd/go/build.go.
+
+import "fmt"
+
+const TagsFlagDoc = "a list of `build tags` to consider satisfied during the build. " +
+	"For more information about build tags, see the description of " +
+	"build constraints in the documentation for the go/build package"
+
+// TagsFlag is an implementation of the flag.Value interface that parses
+// a flag value in the same manner as go build's -tags flag and
+// populates a []string slice.
+//
+// See $GOROOT/src/go/build/doc.go for description of build tags.
+// See $GOROOT/src/cmd/go/doc.go for description of 'go build -tags' flag.
+//
+// Example:
+//	flag.Var((*buildutil.TagsFlag)(&build.Default.BuildTags), "tags", buildutil.TagsDoc)
+type TagsFlag []string
+
+func (v *TagsFlag) Set(s string) error {
+	var err error
+	*v, err = splitQuotedFields(s)
+	if *v == nil {
+		*v = []string{}
+	}
+	return err
+}
+
+func splitQuotedFields(s string) ([]string, error) {
+	// Split fields allowing '' or "" around elements.
+	// Quotes further inside the string do not count.
+	var f []string
+	for len(s) > 0 {
+		for len(s) > 0 && isSpaceByte(s[0]) {
+			s = s[1:]
+		}
+		if len(s) == 0 {
+			break
+		}
+		// Accepted quoted string. No unescaping inside.
+		if s[0] == '"' || s[0] == '\'' {
+			quote := s[0]
+			s = s[1:]
+			i := 0
+			for i < len(s) && s[i] != quote {
+				i++
+			}
+			if i >= len(s) {
+				return nil, fmt.Errorf("unterminated %c string", quote)
+			}
+			f = append(f, s[:i])
+			s = s[i+1:]
+			continue
+		}
+		i := 0
+		for i < len(s) && !isSpaceByte(s[i]) {
+			i++
+		}
+		f = append(f, s[:i])
+		s = s[i:]
+	}
+	return f, nil
+}
+
+func (v *TagsFlag) String() string {
+	return "<tagsFlag>"
+}
+
+func isSpaceByte(c byte) bool {
+	return c == ' ' || c == '\t' || c == '\n' || c == '\r'
+}
diff --git a/go/buildutil/tags_test.go b/go/buildutil/tags_test.go
new file mode 100644
index 0000000..0fc2618
--- /dev/null
+++ b/go/buildutil/tags_test.go
@@ -0,0 +1,28 @@
+package buildutil_test
+
+import (
+	"flag"
+	"go/build"
+	"reflect"
+	"testing"
+
+	"golang.org/x/tools/go/buildutil"
+)
+
+func TestTags(t *testing.T) {
+	f := flag.NewFlagSet("TestTags", flag.PanicOnError)
+	var ctxt build.Context
+	f.Var((*buildutil.TagsFlag)(&ctxt.BuildTags), "tags", buildutil.TagsFlagDoc)
+	f.Parse([]string{"-tags", ` 'one'"two"	'three "four"'`, "rest"})
+
+	// BuildTags
+	want := []string{"one", "two", "three \"four\""}
+	if !reflect.DeepEqual(ctxt.BuildTags, want) {
+		t.Errorf("BuildTags = %q, want %q", ctxt.BuildTags, want)
+	}
+
+	// Args()
+	if want := []string{"rest"}; !reflect.DeepEqual(f.Args(), want) {
+		t.Errorf("f.Args() = %q, want %q", f.Args(), want)
+	}
+}
diff --git a/go/buildutil/util.go b/go/buildutil/util.go
new file mode 100644
index 0000000..60eeae2
--- /dev/null
+++ b/go/buildutil/util.go
@@ -0,0 +1,158 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package buildutil
+
+import (
+	"fmt"
+	"go/ast"
+	"go/build"
+	"go/parser"
+	"go/token"
+	"io"
+	"io/ioutil"
+	"os"
+	"path"
+	"path/filepath"
+	"strings"
+)
+
+// ParseFile behaves like parser.ParseFile,
+// but uses the build context's file system interface, if any.
+//
+// If file is not absolute (as defined by IsAbsPath), the (dir, file)
+// components are joined using JoinPath; dir must be absolute.
+//
+// The displayPath function, if provided, is used to transform the
+// filename that will be attached to the ASTs.
+//
+// TODO(adonovan): call this from go/loader.parseFiles when the tree thaws.
+//
+func ParseFile(fset *token.FileSet, ctxt *build.Context, displayPath func(string) string, dir string, file string, mode parser.Mode) (*ast.File, error) {
+	if !IsAbsPath(ctxt, file) {
+		file = JoinPath(ctxt, dir, file)
+	}
+	rd, err := OpenFile(ctxt, file)
+	if err != nil {
+		return nil, err
+	}
+	defer rd.Close() // ignore error
+	if displayPath != nil {
+		file = displayPath(file)
+	}
+	return parser.ParseFile(fset, file, rd, mode)
+}
+
+// ContainingPackage returns the package containing filename.
+//
+// If filename is not absolute, it is interpreted relative to working directory dir.
+// All I/O is via the build context's file system interface, if any.
+//
+// The '...Files []string' fields of the resulting build.Package are not
+// populated (build.FindOnly mode).
+//
+// TODO(adonovan): call this from oracle when the tree thaws.
+//
+func ContainingPackage(ctxt *build.Context, dir, filename string) (*build.Package, error) {
+	if !IsAbsPath(ctxt, filename) {
+		filename = JoinPath(ctxt, dir, filename)
+	}
+
+	// We must not assume the file tree uses
+	// "/" always,
+	// `\` always,
+	// or os.PathSeparator (which varies by platform),
+	// but to make any progress, we are forced to assume that
+	// paths will not use `\` unless the PathSeparator
+	// is also `\`, thus we can rely on filepath.ToSlash for some sanity.
+
+	dirSlash := path.Dir(filepath.ToSlash(filename)) + "/"
+
+	// We assume that no source root (GOPATH[i] or GOROOT) contains any other.
+	for _, srcdir := range ctxt.SrcDirs() {
+		srcdirSlash := filepath.ToSlash(srcdir) + "/"
+		if strings.HasPrefix(dirSlash, srcdirSlash) {
+			importPath := dirSlash[len(srcdirSlash) : len(dirSlash)-len("/")]
+			return ctxt.Import(importPath, dir, build.FindOnly)
+		}
+	}
+
+	return nil, fmt.Errorf("can't find package containing %s", filename)
+}
+
+// -- Effective methods of file system interface -------------------------
+
+// (go/build.Context defines these as methods, but does not export them.)
+
+// TODO(adonovan): HasSubdir?
+
+// FileExists returns true if the specified file exists,
+// using the build context's file system interface.
+func FileExists(ctxt *build.Context, path string) bool {
+	if ctxt.OpenFile != nil {
+		r, err := ctxt.OpenFile(path)
+		if err != nil {
+			return false
+		}
+		r.Close() // ignore error
+		return true
+	}
+	_, err := os.Stat(path)
+	return err == nil
+}
+
+// OpenFile behaves like os.Open,
+// but uses the build context's file system interface, if any.
+func OpenFile(ctxt *build.Context, path string) (io.ReadCloser, error) {
+	if ctxt.OpenFile != nil {
+		return ctxt.OpenFile(path)
+	}
+	return os.Open(path)
+}
+
+// IsAbsPath behaves like filepath.IsAbs,
+// but uses the build context's file system interface, if any.
+func IsAbsPath(ctxt *build.Context, path string) bool {
+	if ctxt.IsAbsPath != nil {
+		return ctxt.IsAbsPath(path)
+	}
+	return filepath.IsAbs(path)
+}
+
+// JoinPath behaves like filepath.Join,
+// but uses the build context's file system interface, if any.
+func JoinPath(ctxt *build.Context, path ...string) string {
+	if ctxt.JoinPath != nil {
+		return ctxt.JoinPath(path...)
+	}
+	return filepath.Join(path...)
+}
+
+// IsDir behaves like os.Stat plus IsDir,
+// but uses the build context's file system interface, if any.
+func IsDir(ctxt *build.Context, path string) bool {
+	if ctxt.IsDir != nil {
+		return ctxt.IsDir(path)
+	}
+	fi, err := os.Stat(path)
+	return err == nil && fi.IsDir()
+}
+
+// ReadDir behaves like ioutil.ReadDir,
+// but uses the build context's file system interface, if any.
+func ReadDir(ctxt *build.Context, path string) ([]os.FileInfo, error) {
+	if ctxt.ReadDir != nil {
+		return ctxt.ReadDir(path)
+	}
+	return ioutil.ReadDir(path)
+}
+
+// SplitPathList behaves like filepath.SplitList,
+// but uses the build context's file system interface, if any.
+func SplitPathList(ctxt *build.Context, s string) []string {
+	if ctxt.SplitPathList != nil {
+		return ctxt.SplitPathList(s)
+	}
+	return filepath.SplitList(s)
+}
diff --git a/go/buildutil/util_test.go b/go/buildutil/util_test.go
new file mode 100644
index 0000000..10dae17
--- /dev/null
+++ b/go/buildutil/util_test.go
@@ -0,0 +1,45 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Incomplete source tree on Android.
+
+// +build !android
+
+package buildutil_test
+
+import (
+	"go/build"
+	"os"
+	"path/filepath"
+	"runtime"
+	"testing"
+
+	"golang.org/x/tools/go/buildutil"
+)
+
+func TestContainingPackage(t *testing.T) {
+	// unvirtualized:
+	goroot := runtime.GOROOT()
+	gopath := filepath.SplitList(os.Getenv("GOPATH"))[0]
+
+	for _, test := range [][2]string{
+		{goroot + "/src/fmt/print.go", "fmt"},
+		{goroot + "/src/encoding/json/foo.go", "encoding/json"},
+		{goroot + "/src/encoding/missing/foo.go", "(not found)"},
+		{gopath + "/src/golang.org/x/tools/go/buildutil/util_test.go",
+			"golang.org/x/tools/go/buildutil"},
+	} {
+		file, want := test[0], test[1]
+		bp, err := buildutil.ContainingPackage(&build.Default, ".", file)
+		got := bp.ImportPath
+		if err != nil {
+			got = "(not found)"
+		}
+		if got != want {
+			t.Errorf("ContainingPackage(%q) = %s, want %s", file, got, want)
+		}
+	}
+
+	// TODO(adonovan): test on virtualized GOPATH too.
+}
diff --git a/go/callgraph/callgraph.go b/go/callgraph/callgraph.go
new file mode 100644
index 0000000..707a319
--- /dev/null
+++ b/go/callgraph/callgraph.go
@@ -0,0 +1,129 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+/*
+
+Package callgraph defines the call graph and various algorithms
+and utilities to operate on it.
+
+A call graph is a labelled directed graph whose nodes represent
+functions and whose edge labels represent syntactic function call
+sites.  The presence of a labelled edge (caller, site, callee)
+indicates that caller may call callee at the specified call site.
+
+A call graph is a multigraph: it may contain multiple edges (caller,
+*, callee) connecting the same pair of nodes, so long as the edges
+differ by label; this occurs when one function calls another function
+from multiple call sites.  Also, it may contain multiple edges
+(caller, site, *) that differ only by callee; this indicates a
+polymorphic call.
+
+A SOUND call graph is one that overapproximates the dynamic calling
+behaviors of the program in all possible executions.  One call graph
+is more PRECISE than another if it is a smaller overapproximation of
+the dynamic behavior.
+
+All call graphs have a synthetic root node which is responsible for
+calling main() and init().
+
+Calls to built-in functions (e.g. panic, println) are not represented
+in the call graph; they are treated like built-in operators of the
+language.
+
+*/
+package callgraph // import "golang.org/x/tools/go/callgraph"
+
+// TODO(adonovan): add a function to eliminate wrappers from the
+// callgraph, preserving topology.
+// More generally, we could eliminate "uninteresting" nodes such as
+// nodes from packages we don't care about.
+
+import (
+	"fmt"
+	"go/token"
+
+	"golang.org/x/tools/go/ssa"
+)
+
+// A Graph represents a call graph.
+//
+// A graph may contain nodes that are not reachable from the root.
+// If the call graph is sound, such nodes indicate unreachable
+// functions.
+//
+type Graph struct {
+	Root  *Node                   // the distinguished root node
+	Nodes map[*ssa.Function]*Node // all nodes by function
+}
+
+// New returns a new Graph with the specified root node.
+func New(root *ssa.Function) *Graph {
+	g := &Graph{Nodes: make(map[*ssa.Function]*Node)}
+	g.Root = g.CreateNode(root)
+	return g
+}
+
+// CreateNode returns the Node for fn, creating it if not present.
+func (g *Graph) CreateNode(fn *ssa.Function) *Node {
+	n, ok := g.Nodes[fn]
+	if !ok {
+		n = &Node{Func: fn, ID: len(g.Nodes)}
+		g.Nodes[fn] = n
+	}
+	return n
+}
+
+// A Node represents a node in a call graph.
+type Node struct {
+	Func *ssa.Function // the function this node represents
+	ID   int           // 0-based sequence number
+	In   []*Edge       // unordered set of incoming call edges (n.In[*].Callee == n)
+	Out  []*Edge       // unordered set of outgoing call edges (n.Out[*].Caller == n)
+}
+
+func (n *Node) String() string {
+	return fmt.Sprintf("n%d:%s", n.ID, n.Func)
+}
+
+// A Edge represents an edge in the call graph.
+//
+// Site is nil for edges originating in synthetic or intrinsic
+// functions, e.g. reflect.Call or the root of the call graph.
+type Edge struct {
+	Caller *Node
+	Site   ssa.CallInstruction
+	Callee *Node
+}
+
+func (e Edge) String() string {
+	return fmt.Sprintf("%s --> %s", e.Caller, e.Callee)
+}
+
+func (e Edge) Description() string {
+	var prefix string
+	switch e.Site.(type) {
+	case nil:
+		return "synthetic call"
+	case *ssa.Go:
+		prefix = "concurrent "
+	case *ssa.Defer:
+		prefix = "deferred "
+	}
+	return prefix + e.Site.Common().Description()
+}
+
+func (e Edge) Pos() token.Pos {
+	if e.Site == nil {
+		return token.NoPos
+	}
+	return e.Site.Pos()
+}
+
+// AddEdge adds the edge (caller, site, callee) to the call graph.
+// Elimination of duplicate edges is the caller's responsibility.
+func AddEdge(caller *Node, site ssa.CallInstruction, callee *Node) {
+	e := &Edge{caller, site, callee}
+	callee.In = append(callee.In, e)
+	caller.Out = append(caller.Out, e)
+}
diff --git a/go/callgraph/cha/cha.go b/go/callgraph/cha/cha.go
new file mode 100644
index 0000000..fcdf686
--- /dev/null
+++ b/go/callgraph/cha/cha.go
@@ -0,0 +1,120 @@
+// Package cha computes the call graph of a Go program using the Class
+// Hierarchy Analysis (CHA) algorithm.
+//
+// CHA was first described in "Optimization of Object-Oriented Programs
+// Using Static Class Hierarchy Analysis", Jeffrey Dean, David Grove,
+// and Craig Chambers, ECOOP'95.
+//
+// CHA is related to RTA (see go/callgraph/rta); the difference is that
+// CHA conservatively computes the entire "implements" relation between
+// interfaces and concrete types ahead of time, whereas RTA uses dynamic
+// programming to construct it on the fly as it encounters new functions
+// reachable from main.  CHA may thus include spurious call edges for
+// types that haven't been instantiated yet, or types that are never
+// instantiated.
+//
+// Since CHA conservatively assumes that all functions are address-taken
+// and all concrete types are put into interfaces, it is sound to run on
+// partial programs, such as libraries without a main or test function.
+//
+package cha // import "golang.org/x/tools/go/callgraph/cha"
+
+import (
+	"golang.org/x/tools/go/callgraph"
+	"golang.org/x/tools/go/ssa"
+	"golang.org/x/tools/go/ssa/ssautil"
+	"golang.org/x/tools/go/types"
+	"golang.org/x/tools/go/types/typeutil"
+)
+
+// CallGraph computes the call graph of the specified program using the
+// Class Hierarchy Analysis algorithm.
+//
+func CallGraph(prog *ssa.Program) *callgraph.Graph {
+	cg := callgraph.New(nil) // TODO(adonovan) eliminate concept of rooted callgraph
+
+	allFuncs := ssautil.AllFunctions(prog)
+
+	// funcsBySig contains all functions, keyed by signature.  It is
+	// the effective set of address-taken functions used to resolve
+	// a dynamic call of a particular signature.
+	var funcsBySig typeutil.Map // value is []*ssa.Function
+
+	// methodsByName contains all methods,
+	// grouped by name for efficient lookup.
+	methodsByName := make(map[string][]*ssa.Function)
+
+	// methodsMemo records, for every abstract method call call I.f on
+	// interface type I, the set of concrete methods C.f of all
+	// types C that satisfy interface I.
+	methodsMemo := make(map[*types.Func][]*ssa.Function)
+	lookupMethods := func(m *types.Func) []*ssa.Function {
+		methods, ok := methodsMemo[m]
+		if !ok {
+			I := m.Type().(*types.Signature).Recv().Type().Underlying().(*types.Interface)
+			for _, f := range methodsByName[m.Name()] {
+				C := f.Signature.Recv().Type() // named or *named
+				if types.Implements(C, I) {
+					methods = append(methods, f)
+				}
+			}
+			methodsMemo[m] = methods
+		}
+		return methods
+	}
+
+	for f := range allFuncs {
+		if f.Signature.Recv() == nil {
+			// Package initializers can never be address-taken.
+			if f.Name() == "init" && f.Synthetic == "package initializer" {
+				continue
+			}
+			funcs, _ := funcsBySig.At(f.Signature).([]*ssa.Function)
+			funcs = append(funcs, f)
+			funcsBySig.Set(f.Signature, funcs)
+		} else {
+			methodsByName[f.Name()] = append(methodsByName[f.Name()], f)
+		}
+	}
+
+	addEdge := func(fnode *callgraph.Node, site ssa.CallInstruction, g *ssa.Function) {
+		gnode := cg.CreateNode(g)
+		callgraph.AddEdge(fnode, site, gnode)
+	}
+
+	addEdges := func(fnode *callgraph.Node, site ssa.CallInstruction, callees []*ssa.Function) {
+		// Because every call to a highly polymorphic and
+		// frequently used abstract method such as
+		// (io.Writer).Write is assumed to call every concrete
+		// Write method in the program, the call graph can
+		// contain a lot of duplication.
+		//
+		// TODO(adonovan): opt: consider factoring the callgraph
+		// API so that the Callers component of each edge is a
+		// slice of nodes, not a singleton.
+		for _, g := range callees {
+			addEdge(fnode, site, g)
+		}
+	}
+
+	for f := range allFuncs {
+		fnode := cg.CreateNode(f)
+		for _, b := range f.Blocks {
+			for _, instr := range b.Instrs {
+				if site, ok := instr.(ssa.CallInstruction); ok {
+					call := site.Common()
+					if call.IsInvoke() {
+						addEdges(fnode, site, lookupMethods(call.Method))
+					} else if g := call.StaticCallee(); g != nil {
+						addEdge(fnode, site, g)
+					} else if _, ok := call.Value.(*ssa.Builtin); !ok {
+						callees, _ := funcsBySig.At(call.Signature()).([]*ssa.Function)
+						addEdges(fnode, site, callees)
+					}
+				}
+			}
+		}
+	}
+
+	return cg
+}
diff --git a/go/callgraph/cha/cha_test.go b/go/callgraph/cha/cha_test.go
new file mode 100644
index 0000000..38348c0
--- /dev/null
+++ b/go/callgraph/cha/cha_test.go
@@ -0,0 +1,110 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// No testdata on Android.
+
+// +build !android
+
+package cha_test
+
+import (
+	"bytes"
+	"fmt"
+	"go/ast"
+	"go/parser"
+	"go/token"
+	"io/ioutil"
+	"sort"
+	"strings"
+	"testing"
+
+	"golang.org/x/tools/go/callgraph"
+	"golang.org/x/tools/go/callgraph/cha"
+	"golang.org/x/tools/go/loader"
+	"golang.org/x/tools/go/ssa/ssautil"
+	"golang.org/x/tools/go/types"
+)
+
+var inputs = []string{
+	"testdata/func.go",
+	"testdata/iface.go",
+	"testdata/recv.go",
+}
+
+func expectation(f *ast.File) (string, token.Pos) {
+	for _, c := range f.Comments {
+		text := strings.TrimSpace(c.Text())
+		if t := strings.TrimPrefix(text, "WANT:\n"); t != text {
+			return t, c.Pos()
+		}
+	}
+	return "", token.NoPos
+}
+
+// TestCHA runs CHA on each file in inputs, prints the dynamic edges of
+// the call graph, and compares it with the golden results embedded in
+// the WANT comment at the end of the file.
+//
+func TestCHA(t *testing.T) {
+	for _, filename := range inputs {
+		content, err := ioutil.ReadFile(filename)
+		if err != nil {
+			t.Errorf("couldn't read file '%s': %s", filename, err)
+			continue
+		}
+
+		conf := loader.Config{
+			ParserMode: parser.ParseComments,
+		}
+		f, err := conf.ParseFile(filename, content)
+		if err != nil {
+			t.Error(err)
+			continue
+		}
+
+		want, pos := expectation(f)
+		if pos == token.NoPos {
+			t.Errorf("No WANT: comment in %s", filename)
+			continue
+		}
+
+		conf.CreateFromFiles("main", f)
+		iprog, err := conf.Load()
+		if err != nil {
+			t.Error(err)
+			continue
+		}
+
+		prog := ssautil.CreateProgram(iprog, 0)
+		mainPkg := prog.Package(iprog.Created[0].Pkg)
+		prog.BuildAll()
+
+		cg := cha.CallGraph(prog)
+
+		if got := printGraph(cg, mainPkg.Object); got != want {
+			t.Errorf("%s: got:\n%s\nwant:\n%s",
+				prog.Fset.Position(pos), got, want)
+		}
+	}
+}
+
+func printGraph(cg *callgraph.Graph, from *types.Package) string {
+	var edges []string
+	callgraph.GraphVisitEdges(cg, func(e *callgraph.Edge) error {
+		if strings.Contains(e.Description(), "dynamic") {
+			edges = append(edges, fmt.Sprintf("%s --> %s",
+				e.Caller.Func.RelString(from),
+				e.Callee.Func.RelString(from)))
+		}
+		return nil
+	})
+	sort.Strings(edges)
+
+	var buf bytes.Buffer
+	buf.WriteString("Dynamic calls\n")
+	for _, edge := range edges {
+		fmt.Fprintf(&buf, "  %s\n", edge)
+	}
+	return strings.TrimSpace(buf.String())
+}
diff --git a/go/callgraph/cha/testdata/func.go b/go/callgraph/cha/testdata/func.go
new file mode 100644
index 0000000..ad483f1
--- /dev/null
+++ b/go/callgraph/cha/testdata/func.go
@@ -0,0 +1,23 @@
+//+build ignore
+
+package main
+
+// Test of dynamic function calls; no interfaces.
+
+func A(int) {}
+
+var (
+	B = func(int) {}
+	C = func(int) {}
+)
+
+func f() {
+	pfn := B
+	pfn(0) // calls A, B, C, even though A is not even address-taken
+}
+
+// WANT:
+// Dynamic calls
+//   f --> A
+//   f --> init$1
+//   f --> init$2
diff --git a/go/callgraph/cha/testdata/iface.go b/go/callgraph/cha/testdata/iface.go
new file mode 100644
index 0000000..1622ec1
--- /dev/null
+++ b/go/callgraph/cha/testdata/iface.go
@@ -0,0 +1,65 @@
+//+build ignore
+
+package main
+
+// Test of interface calls.  None of the concrete types are ever
+// instantiated or converted to interfaces.
+
+type I interface {
+	f()
+}
+
+type J interface {
+	f()
+	g()
+}
+
+type C int // implements I
+
+func (*C) f()
+
+type D int // implements I and J
+
+func (*D) f()
+func (*D) g()
+
+func one(i I, j J) {
+	i.f() // calls *C and *D
+}
+
+func two(i I, j J) {
+	j.f() // calls *D (but not *C, even though it defines method f)
+}
+
+func three(i I, j J) {
+	j.g() // calls *D
+}
+
+func four(i I, j J) {
+	Jf := J.f
+	if unknown {
+		Jf = nil // suppress SSA constant propagation
+	}
+	Jf(nil) // calls *D
+}
+
+func five(i I, j J) {
+	jf := j.f
+	if unknown {
+		jf = nil // suppress SSA constant propagation
+	}
+	jf() // calls *D
+}
+
+var unknown bool
+
+// WANT:
+// Dynamic calls
+//   (J).f$bound --> (*D).f
+//   (J).f$thunk --> (*D).f
+//   five --> (J).f$bound
+//   four --> (J).f$thunk
+//   one --> (*C).f
+//   one --> (*D).f
+//   three --> (*D).g
+//   two --> (*D).f
diff --git a/go/callgraph/cha/testdata/recv.go b/go/callgraph/cha/testdata/recv.go
new file mode 100644
index 0000000..5ba48e9
--- /dev/null
+++ b/go/callgraph/cha/testdata/recv.go
@@ -0,0 +1,37 @@
+//+build ignore
+
+package main
+
+type I interface {
+	f()
+}
+
+type J interface {
+	g()
+}
+
+type C int // C and *C implement I; *C implements J
+
+func (C) f()
+func (*C) g()
+
+type D int // *D implements I and J
+
+func (*D) f()
+func (*D) g()
+
+func f(i I) {
+	i.f() // calls C, *C, *D
+}
+
+func g(j J) {
+	j.g() // calls *C, *D
+}
+
+// WANT:
+// Dynamic calls
+//   f --> (*C).f
+//   f --> (*D).f
+//   f --> (C).f
+//   g --> (*C).g
+//   g --> (*D).g
diff --git a/go/callgraph/rta/rta.go b/go/callgraph/rta/rta.go
new file mode 100644
index 0000000..8d22da6
--- /dev/null
+++ b/go/callgraph/rta/rta.go
@@ -0,0 +1,459 @@
+// Copyright 2013 The Go 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 package provides Rapid Type Analysis (RTA) for Go, a fast
+// algorithm for call graph construction and discovery of reachable code
+// (and hence dead code) and runtime types.  The algorithm was first
+// described in:
+//
+// David F. Bacon and Peter F. Sweeney. 1996.
+// Fast static analysis of C++ virtual function calls. (OOPSLA '96)
+// http://doi.acm.org/10.1145/236337.236371
+//
+// The algorithm uses dynamic programming to tabulate the cross-product
+// of the set of known "address taken" functions with the set of known
+// dynamic calls of the same type.  As each new address-taken function
+// is discovered, call graph edges are added from each known callsite,
+// and as each new call site is discovered, call graph edges are added
+// from it to each known address-taken function.
+//
+// A similar approach is used for dynamic calls via interfaces: it
+// tabulates the cross-product of the set of known "runtime types",
+// i.e. types that may appear in an interface value, or be derived from
+// one via reflection, with the set of known "invoke"-mode dynamic
+// calls.  As each new "runtime type" is discovered, call edges are
+// added from the known call sites, and as each new call site is
+// discovered, call graph edges are added to each compatible
+// method.
+//
+// In addition, we must consider all exported methods of any runtime type
+// as reachable, since they may be called via reflection.
+//
+// Each time a newly added call edge causes a new function to become
+// reachable, the code of that function is analyzed for more call sites,
+// address-taken functions, and runtime types.  The process continues
+// until a fixed point is achieved.
+//
+// The resulting call graph is less precise than one produced by pointer
+// analysis, but the algorithm is much faster.  For example, running the
+// cmd/callgraph tool on its own source takes ~2.1s for RTA and ~5.4s
+// for points-to analysis.
+//
+package rta // import "golang.org/x/tools/go/callgraph/rta"
+
+// TODO(adonovan): test it by connecting it to the interpreter and
+// replacing all "unreachable" functions by a special intrinsic, and
+// ensure that that intrinsic is never called.
+
+import (
+	"fmt"
+
+	"golang.org/x/tools/go/callgraph"
+	"golang.org/x/tools/go/ssa"
+	"golang.org/x/tools/go/types"
+	"golang.org/x/tools/go/types/typeutil"
+)
+
+// A Result holds the results of Rapid Type Analysis, which includes the
+// set of reachable functions/methods, runtime types, and the call graph.
+//
+type Result struct {
+	// CallGraph is the discovered callgraph.
+	// It does not include edges for calls made via reflection.
+	CallGraph *callgraph.Graph
+
+	// Reachable contains the set of reachable functions and methods.
+	// This includes exported methods of runtime types, since
+	// they may be accessed via reflection.
+	// The value indicates whether the function is address-taken.
+	//
+	// (We wrap the bool in a struct to avoid inadvertent use of
+	// "if Reachable[f] {" to test for set membership.)
+	Reachable map[*ssa.Function]struct{ AddrTaken bool }
+
+	// RuntimeTypes contains the set of types that are needed at
+	// runtime, for interfaces or reflection.
+	//
+	// The value indicates whether the type is inaccessible to reflection.
+	// Consider:
+	// 	type A struct{B}
+	// 	fmt.Println(new(A))
+	// Types *A, A and B are accessible to reflection, but the unnamed
+	// type struct{B} is not.
+	RuntimeTypes typeutil.Map
+}
+
+// Working state of the RTA algorithm.
+type rta struct {
+	result *Result
+
+	prog *ssa.Program
+
+	worklist []*ssa.Function // list of functions to visit
+
+	// addrTakenFuncsBySig contains all address-taken *Functions, grouped by signature.
+	// Keys are *types.Signature, values are map[*ssa.Function]bool sets.
+	addrTakenFuncsBySig typeutil.Map
+
+	// dynCallSites contains all dynamic "call"-mode call sites, grouped by signature.
+	// Keys are *types.Signature, values are unordered []ssa.CallInstruction.
+	dynCallSites typeutil.Map
+
+	// invokeSites contains all "invoke"-mode call sites, grouped by interface.
+	// Keys are *types.Interface (never *types.Named),
+	// Values are unordered []ssa.CallInstruction sets.
+	invokeSites typeutil.Map
+
+	// The following two maps together define the subset of the
+	// m:n "implements" relation needed by the algorithm.
+
+	// concreteTypes maps each concrete type to the set of interfaces that it implements.
+	// Keys are types.Type, values are unordered []*types.Interface.
+	// Only concrete types used as MakeInterface operands are included.
+	concreteTypes typeutil.Map
+
+	// interfaceTypes maps each interface type to
+	// the set of concrete types that implement it.
+	// Keys are *types.Interface, values are unordered []types.Type.
+	// Only interfaces used in "invoke"-mode CallInstructions are included.
+	interfaceTypes typeutil.Map
+}
+
+// addReachable marks a function as potentially callable at run-time,
+// and ensures that it gets processed.
+func (r *rta) addReachable(f *ssa.Function, addrTaken bool) {
+	reachable := r.result.Reachable
+	n := len(reachable)
+	v := reachable[f]
+	if addrTaken {
+		v.AddrTaken = true
+	}
+	reachable[f] = v
+	if len(reachable) > n {
+		// First time seeing f.  Add it to the worklist.
+		r.worklist = append(r.worklist, f)
+	}
+}
+
+// addEdge adds the specified call graph edge, and marks it reachable.
+// addrTaken indicates whether to mark the callee as "address-taken".
+func (r *rta) addEdge(site ssa.CallInstruction, callee *ssa.Function, addrTaken bool) {
+	r.addReachable(callee, addrTaken)
+
+	if g := r.result.CallGraph; g != nil {
+		if site.Parent() == nil {
+			panic(site)
+		}
+		from := g.CreateNode(site.Parent())
+		to := g.CreateNode(callee)
+		callgraph.AddEdge(from, site, to)
+	}
+}
+
+// ---------- addrTakenFuncs × dynCallSites ----------
+
+// visitAddrTakenFunc is called each time we encounter an address-taken function f.
+func (r *rta) visitAddrTakenFunc(f *ssa.Function) {
+	// Create two-level map (Signature -> Function -> bool).
+	S := f.Signature
+	funcs, _ := r.addrTakenFuncsBySig.At(S).(map[*ssa.Function]bool)
+	if funcs == nil {
+		funcs = make(map[*ssa.Function]bool)
+		r.addrTakenFuncsBySig.Set(S, funcs)
+	}
+	if !funcs[f] {
+		// First time seeing f.
+		funcs[f] = true
+
+		// If we've seen any dyncalls of this type, mark it reachable,
+		// and add call graph edges.
+		sites, _ := r.dynCallSites.At(S).([]ssa.CallInstruction)
+		for _, site := range sites {
+			r.addEdge(site, f, true)
+		}
+	}
+}
+
+// visitDynCall is called each time we encounter a dynamic "call"-mode call.
+func (r *rta) visitDynCall(site ssa.CallInstruction) {
+	S := site.Common().Signature()
+
+	// Record the call site.
+	sites, _ := r.dynCallSites.At(S).([]ssa.CallInstruction)
+	r.dynCallSites.Set(S, append(sites, site))
+
+	// For each function of signature S that we know is address-taken,
+	// mark it reachable.  We'll add the callgraph edges later.
+	funcs, _ := r.addrTakenFuncsBySig.At(S).(map[*ssa.Function]bool)
+	for g := range funcs {
+		r.addEdge(site, g, true)
+	}
+}
+
+// ---------- concrete types × invoke sites ----------
+
+// addInvokeEdge is called for each new pair (site, C) in the matrix.
+func (r *rta) addInvokeEdge(site ssa.CallInstruction, C types.Type) {
+	// Ascertain the concrete method of C to be called.
+	imethod := site.Common().Method
+	cmethod := r.prog.Method(r.prog.MethodSets.MethodSet(C).Lookup(imethod.Pkg(), imethod.Name()))
+	r.addEdge(site, cmethod, true)
+}
+
+// visitInvoke is called each time the algorithm encounters an "invoke"-mode call.
+func (r *rta) visitInvoke(site ssa.CallInstruction) {
+	I := site.Common().Value.Type().Underlying().(*types.Interface)
+
+	// Record the invoke site.
+	sites, _ := r.invokeSites.At(I).([]ssa.CallInstruction)
+	r.invokeSites.Set(I, append(sites, site))
+
+	// Add callgraph edge for each existing
+	// address-taken concrete type implementing I.
+	for _, C := range r.implementations(I) {
+		r.addInvokeEdge(site, C)
+	}
+}
+
+// ---------- main algorithm ----------
+
+// visitFunc processes function f.
+func (r *rta) visitFunc(f *ssa.Function) {
+	var space [32]*ssa.Value // preallocate space for common case
+
+	for _, b := range f.Blocks {
+		for _, instr := range b.Instrs {
+			rands := instr.Operands(space[:0])
+
+			switch instr := instr.(type) {
+			case ssa.CallInstruction:
+				call := instr.Common()
+				if call.IsInvoke() {
+					r.visitInvoke(instr)
+				} else if g := call.StaticCallee(); g != nil {
+					r.addEdge(instr, g, false)
+				} else if _, ok := call.Value.(*ssa.Builtin); !ok {
+					r.visitDynCall(instr)
+				}
+
+				// Ignore the call-position operand when
+				// looking for address-taken Functions.
+				// Hack: assume this is rands[0].
+				rands = rands[1:]
+
+			case *ssa.MakeInterface:
+				r.addRuntimeType(instr.X.Type(), false)
+			}
+
+			// Process all address-taken functions.
+			for _, op := range rands {
+				if g, ok := (*op).(*ssa.Function); ok {
+					r.visitAddrTakenFunc(g)
+				}
+			}
+		}
+	}
+}
+
+// Analyze performs Rapid Type Analysis, starting at the specified root
+// functions.  It returns nil if no roots were specified.
+//
+// If buildCallGraph is true, Result.CallGraph will contain a call
+// graph; otherwise, only the other fields (reachable functions) are
+// populated.
+//
+func Analyze(roots []*ssa.Function, buildCallGraph bool) *Result {
+	if len(roots) == 0 {
+		return nil
+	}
+
+	r := &rta{
+		result: &Result{Reachable: make(map[*ssa.Function]struct{ AddrTaken bool })},
+		prog:   roots[0].Prog,
+	}
+
+	if buildCallGraph {
+		// TODO(adonovan): change callgraph API to eliminate the
+		// notion of a distinguished root node.  Some callgraphs
+		// have many roots, or none.
+		r.result.CallGraph = callgraph.New(roots[0])
+	}
+
+	hasher := typeutil.MakeHasher()
+	r.result.RuntimeTypes.SetHasher(hasher)
+	r.addrTakenFuncsBySig.SetHasher(hasher)
+	r.dynCallSites.SetHasher(hasher)
+	r.invokeSites.SetHasher(hasher)
+	r.concreteTypes.SetHasher(hasher)
+	r.interfaceTypes.SetHasher(hasher)
+
+	// Visit functions, processing their instructions, and adding
+	// new functions to the worklist, until a fixed point is
+	// reached.
+	var shadow []*ssa.Function // for efficiency, we double-buffer the worklist
+	r.worklist = append(r.worklist, roots...)
+	for len(r.worklist) > 0 {
+		shadow, r.worklist = r.worklist, shadow[:0]
+		for _, f := range shadow {
+			r.visitFunc(f)
+		}
+	}
+	return r.result
+}
+
+// interfaces(C) returns all currently known interfaces implemented by C.
+func (r *rta) interfaces(C types.Type) []*types.Interface {
+	// Ascertain set of interfaces C implements
+	// and update 'implements' relation.
+	var ifaces []*types.Interface
+	r.interfaceTypes.Iterate(func(I types.Type, concs interface{}) {
+		if I := I.(*types.Interface); types.Implements(C, I) {
+			concs, _ := concs.([]types.Type)
+			r.interfaceTypes.Set(I, append(concs, C))
+			ifaces = append(ifaces, I)
+		}
+	})
+	r.concreteTypes.Set(C, ifaces)
+	return ifaces
+}
+
+// implementations(I) returns all currently known concrete types that implement I.
+func (r *rta) implementations(I *types.Interface) []types.Type {
+	var concs []types.Type
+	if v := r.interfaceTypes.At(I); v != nil {
+		concs = v.([]types.Type)
+	} else {
+		// First time seeing this interface.
+		// Update the 'implements' relation.
+		r.concreteTypes.Iterate(func(C types.Type, ifaces interface{}) {
+			if types.Implements(C, I) {
+				ifaces, _ := ifaces.([]*types.Interface)
+				r.concreteTypes.Set(C, append(ifaces, I))
+				concs = append(concs, C)
+			}
+		})
+		r.interfaceTypes.Set(I, concs)
+	}
+	return concs
+}
+
+// addRuntimeType is called for each concrete type that can be the
+// dynamic type of some interface or reflect.Value.
+// Adapted from needMethods in go/ssa/builder.go
+//
+func (r *rta) addRuntimeType(T types.Type, skip bool) {
+	if prev, ok := r.result.RuntimeTypes.At(T).(bool); ok {
+		if skip && !prev {
+			r.result.RuntimeTypes.Set(T, skip)
+		}
+		return
+	}
+	r.result.RuntimeTypes.Set(T, skip)
+
+	mset := r.prog.MethodSets.MethodSet(T)
+
+	if _, ok := T.Underlying().(*types.Interface); !ok {
+		// T is a new concrete type.
+		for i, n := 0, mset.Len(); i < n; i++ {
+			sel := mset.At(i)
+			m := sel.Obj()
+
+			if m.Exported() {
+				// Exported methods are always potentially callable via reflection.
+				r.addReachable(r.prog.Method(sel), true)
+			}
+		}
+
+		// Add callgraph edge for each existing dynamic
+		// "invoke"-mode call via that interface.
+		for _, I := range r.interfaces(T) {
+			sites, _ := r.invokeSites.At(I).([]ssa.CallInstruction)
+			for _, site := range sites {
+				r.addInvokeEdge(site, T)
+			}
+		}
+	}
+
+	// Precondition: T is not a method signature (*Signature with Recv()!=nil).
+	// Recursive case: skip => don't call makeMethods(T).
+	// Each package maintains its own set of types it has visited.
+
+	var n *types.Named
+	switch T := T.(type) {
+	case *types.Named:
+		n = T
+	case *types.Pointer:
+		n, _ = T.Elem().(*types.Named)
+	}
+	if n != nil {
+		owner := n.Obj().Pkg()
+		if owner == nil {
+			return // built-in error type
+		}
+	}
+
+	// Recursion over signatures of each exported method.
+	for i := 0; i < mset.Len(); i++ {
+		if mset.At(i).Obj().Exported() {
+			sig := mset.At(i).Type().(*types.Signature)
+			r.addRuntimeType(sig.Params(), true)  // skip the Tuple itself
+			r.addRuntimeType(sig.Results(), true) // skip the Tuple itself
+		}
+	}
+
+	switch t := T.(type) {
+	case *types.Basic:
+		// nop
+
+	case *types.Interface:
+		// nop---handled by recursion over method set.
+
+	case *types.Pointer:
+		r.addRuntimeType(t.Elem(), false)
+
+	case *types.Slice:
+		r.addRuntimeType(t.Elem(), false)
+
+	case *types.Chan:
+		r.addRuntimeType(t.Elem(), false)
+
+	case *types.Map:
+		r.addRuntimeType(t.Key(), false)
+		r.addRuntimeType(t.Elem(), false)
+
+	case *types.Signature:
+		if t.Recv() != nil {
+			panic(fmt.Sprintf("Signature %s has Recv %s", t, t.Recv()))
+		}
+		r.addRuntimeType(t.Params(), true)  // skip the Tuple itself
+		r.addRuntimeType(t.Results(), true) // skip the Tuple itself
+
+	case *types.Named:
+		// A pointer-to-named type can be derived from a named
+		// type via reflection.  It may have methods too.
+		r.addRuntimeType(types.NewPointer(T), false)
+
+		// Consider 'type T struct{S}' where S has methods.
+		// Reflection provides no way to get from T to struct{S},
+		// only to S, so the method set of struct{S} is unwanted,
+		// so set 'skip' flag during recursion.
+		r.addRuntimeType(t.Underlying(), true)
+
+	case *types.Array:
+		r.addRuntimeType(t.Elem(), false)
+
+	case *types.Struct:
+		for i, n := 0, t.NumFields(); i < n; i++ {
+			r.addRuntimeType(t.Field(i).Type(), false)
+		}
+
+	case *types.Tuple:
+		for i, n := 0, t.Len(); i < n; i++ {
+			r.addRuntimeType(t.At(i).Type(), false)
+		}
+
+	default:
+		panic(T)
+	}
+}
diff --git a/go/callgraph/rta/rta_test.go b/go/callgraph/rta/rta_test.go
new file mode 100644
index 0000000..e5aa846
--- /dev/null
+++ b/go/callgraph/rta/rta_test.go
@@ -0,0 +1,139 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// No testdata on Android.
+
+// +build !android
+
+package rta_test
+
+import (
+	"bytes"
+	"fmt"
+	"go/ast"
+	"go/parser"
+	"go/token"
+	"io/ioutil"
+	"sort"
+	"strings"
+	"testing"
+
+	"golang.org/x/tools/go/callgraph"
+	"golang.org/x/tools/go/callgraph/rta"
+	"golang.org/x/tools/go/loader"
+	"golang.org/x/tools/go/ssa"
+	"golang.org/x/tools/go/ssa/ssautil"
+	"golang.org/x/tools/go/types"
+)
+
+var inputs = []string{
+	"testdata/func.go",
+	"testdata/rtype.go",
+	"testdata/iface.go",
+}
+
+func expectation(f *ast.File) (string, token.Pos) {
+	for _, c := range f.Comments {
+		text := strings.TrimSpace(c.Text())
+		if t := strings.TrimPrefix(text, "WANT:\n"); t != text {
+			return t, c.Pos()
+		}
+	}
+	return "", token.NoPos
+}
+
+// TestRTA runs RTA on each file in inputs, prints the results, and
+// compares it with the golden results embedded in the WANT comment at
+// the end of the file.
+//
+// The results string consists of two parts: the set of dynamic call
+// edges, "f --> g", one per line, and the set of reachable functions,
+// one per line.  Each set is sorted.
+//
+func TestRTA(t *testing.T) {
+	for _, filename := range inputs {
+		content, err := ioutil.ReadFile(filename)
+		if err != nil {
+			t.Errorf("couldn't read file '%s': %s", filename, err)
+			continue
+		}
+
+		conf := loader.Config{
+			ParserMode: parser.ParseComments,
+		}
+		f, err := conf.ParseFile(filename, content)
+		if err != nil {
+			t.Error(err)
+			continue
+		}
+
+		want, pos := expectation(f)
+		if pos == token.NoPos {
+			t.Errorf("No WANT: comment in %s", filename)
+			continue
+		}
+
+		conf.CreateFromFiles("main", f)
+		iprog, err := conf.Load()
+		if err != nil {
+			t.Error(err)
+			continue
+		}
+
+		prog := ssautil.CreateProgram(iprog, 0)
+		mainPkg := prog.Package(iprog.Created[0].Pkg)
+		prog.BuildAll()
+
+		res := rta.Analyze([]*ssa.Function{
+			mainPkg.Func("main"),
+			mainPkg.Func("init"),
+		}, true)
+
+		if got := printResult(res, mainPkg.Object); got != want {
+			t.Errorf("%s: got:\n%s\nwant:\n%s",
+				prog.Fset.Position(pos), got, want)
+		}
+	}
+}
+
+func printResult(res *rta.Result, from *types.Package) string {
+	var buf bytes.Buffer
+
+	writeSorted := func(ss []string) {
+		sort.Strings(ss)
+		for _, s := range ss {
+			fmt.Fprintf(&buf, "  %s\n", s)
+		}
+	}
+
+	buf.WriteString("Dynamic calls\n")
+	var edges []string
+	callgraph.GraphVisitEdges(res.CallGraph, func(e *callgraph.Edge) error {
+		if strings.Contains(e.Description(), "dynamic") {
+			edges = append(edges, fmt.Sprintf("%s --> %s",
+				e.Caller.Func.RelString(from),
+				e.Callee.Func.RelString(from)))
+		}
+		return nil
+	})
+	writeSorted(edges)
+
+	buf.WriteString("Reachable functions\n")
+	var reachable []string
+	for f := range res.Reachable {
+		reachable = append(reachable, f.RelString(from))
+	}
+	writeSorted(reachable)
+
+	buf.WriteString("Reflect types\n")
+	var rtypes []string
+	res.RuntimeTypes.Iterate(func(key types.Type, value interface{}) {
+		if value == false { // accessible to reflection
+			rtypes = append(rtypes, types.TypeString(key, types.RelativeTo(from)))
+		}
+	})
+	writeSorted(rtypes)
+
+	return strings.TrimSpace(buf.String())
+}
diff --git a/go/callgraph/rta/testdata/func.go b/go/callgraph/rta/testdata/func.go
new file mode 100644
index 0000000..968c73d
--- /dev/null
+++ b/go/callgraph/rta/testdata/func.go
@@ -0,0 +1,37 @@
+//+build ignore
+
+package main
+
+// Test of dynamic function calls.
+// No interfaces, so no runtime/reflect types.
+
+func A1() {
+	A2(0)
+}
+
+func A2(int) {} // not address-taken
+
+func B() {} // unreachable
+
+var (
+	C = func(int) {}
+	D = func(int) {}
+)
+
+func main() {
+	A1()
+
+	pfn := C
+	pfn(0) // calls C and D but not A2 (same sig but not address-taken)
+}
+
+// WANT:
+// Dynamic calls
+//   main --> init$1
+//   main --> init$2
+// Reachable functions
+//   A1
+//   A2
+//   init$1
+//   init$2
+// Reflect types
diff --git a/go/callgraph/rta/testdata/iface.go b/go/callgraph/rta/testdata/iface.go
new file mode 100644
index 0000000..c3ee570
--- /dev/null
+++ b/go/callgraph/rta/testdata/iface.go
@@ -0,0 +1,79 @@
+//+build ignore
+
+package main
+
+// Test of interface calls.
+
+func use(interface{})
+
+type A byte // instantiated but not a reflect type
+
+func (A) f() {} // called directly
+func (A) F() {} // unreachable
+
+type B int // a reflect type
+
+func (*B) f() {} // reachable via interface invoke
+func (*B) F() {} // reachable: exported method of reflect type
+
+type B2 int // a reflect type, and *B2 also
+
+func (B2) f() {} // reachable via interface invoke
+func (B2) g() {} // reachable: exported method of reflect type
+
+type C string // not instantiated
+
+func (C) f() {} // unreachable
+func (C) F() {} // unreachable
+
+type D uint // instantiated only in dead code
+
+func (D) f() {} // unreachable
+func (D) F() {} // unreachable
+
+func main() {
+	A(0).f()
+
+	use(new(B))
+	use(B2(0))
+
+	var i interface {
+		f()
+	}
+	i.f() // calls (*B).f, (*B2).f and (B2.f)
+
+	live()
+}
+
+func live() {
+	var j interface {
+		f()
+		g()
+	}
+	j.f() // calls (B2).f and (*B2).f but not (*B).f (no g method).
+}
+
+func dead() {
+	use(D(0))
+}
+
+// WANT:
+// Dynamic calls
+//   live --> (*B2).f
+//   live --> (B2).f
+//   main --> (*B).f
+//   main --> (*B2).f
+//   main --> (B2).f
+// Reachable functions
+//   (*B).F
+//   (*B).f
+//   (*B2).f
+//   (A).f
+//   (B2).f
+//   live
+//   use
+// Reflect types
+//   *B
+//   *B2
+//   B
+//   B2
diff --git a/go/callgraph/rta/testdata/rtype.go b/go/callgraph/rta/testdata/rtype.go
new file mode 100644
index 0000000..85414e5
--- /dev/null
+++ b/go/callgraph/rta/testdata/rtype.go
@@ -0,0 +1,35 @@
+//+build ignore
+
+package main
+
+// Test of runtime types (types for which descriptors are needed).
+
+func use(interface{})
+
+type A byte // neither A nor byte are runtime types
+
+type B struct{ x uint } // B and uint are runtime types, but not the struct
+
+func main() {
+	var x int // not a runtime type
+	print(x)
+
+	var y string // runtime type due to interface conversion
+	use(y)
+
+	use(struct{ uint64 }{}) // struct is a runtime type
+
+	use(new(B)) // *B is a runtime type
+}
+
+// WANT:
+// Dynamic calls
+// Reachable functions
+//   use
+// Reflect types
+//   *B
+//   B
+//   string
+//   struct{uint64}
+//   uint
+//   uint64
diff --git a/go/callgraph/static/static.go b/go/callgraph/static/static.go
new file mode 100644
index 0000000..709bb7b
--- /dev/null
+++ b/go/callgraph/static/static.go
@@ -0,0 +1,35 @@
+// Package static computes the call graph of a Go program containing
+// only static call edges.
+package static // import "golang.org/x/tools/go/callgraph/static"
+
+import (
+	"golang.org/x/tools/go/callgraph"
+	"golang.org/x/tools/go/ssa"
+	"golang.org/x/tools/go/ssa/ssautil"
+)
+
+// CallGraph computes the call graph of the specified program
+// considering only static calls.
+//
+func CallGraph(prog *ssa.Program) *callgraph.Graph {
+	cg := callgraph.New(nil) // TODO(adonovan) eliminate concept of rooted callgraph
+
+	// TODO(adonovan): opt: use only a single pass over the ssa.Program.
+	// TODO(adonovan): opt: this is slower than RTA (perhaps because
+	// the lower precision means so many edges are allocated)!
+	for f := range ssautil.AllFunctions(prog) {
+		fnode := cg.CreateNode(f)
+		for _, b := range f.Blocks {
+			for _, instr := range b.Instrs {
+				if site, ok := instr.(ssa.CallInstruction); ok {
+					if g := site.Common().StaticCallee(); g != nil {
+						gnode := cg.CreateNode(g)
+						callgraph.AddEdge(fnode, site, gnode)
+					}
+				}
+			}
+		}
+	}
+
+	return cg
+}
diff --git a/go/callgraph/static/static_test.go b/go/callgraph/static/static_test.go
new file mode 100644
index 0000000..62297f7
--- /dev/null
+++ b/go/callgraph/static/static_test.go
@@ -0,0 +1,88 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package static_test
+
+import (
+	"fmt"
+	"go/parser"
+	"reflect"
+	"sort"
+	"testing"
+
+	"golang.org/x/tools/go/callgraph"
+	"golang.org/x/tools/go/callgraph/static"
+	"golang.org/x/tools/go/loader"
+	"golang.org/x/tools/go/ssa/ssautil"
+)
+
+const input = `package P
+
+type C int
+func (C) f()
+
+type I interface{f()}
+
+func f() {
+	p := func() {}
+	g()
+	p() // SSA constant propagation => static
+
+	if unknown {
+		p = h
+	}
+	p() // dynamic
+
+	C(0).f()
+}
+
+func g() {
+	var i I = C(0)
+	i.f()
+}
+
+func h()
+
+var unknown bool
+`
+
+func TestStatic(t *testing.T) {
+	conf := loader.Config{ParserMode: parser.ParseComments}
+	f, err := conf.ParseFile("P.go", input)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	conf.CreateFromFiles("P", f)
+	iprog, err := conf.Load()
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	P := iprog.Created[0].Pkg
+
+	prog := ssautil.CreateProgram(iprog, 0)
+	prog.BuildAll()
+
+	cg := static.CallGraph(prog)
+
+	var edges []string
+	callgraph.GraphVisitEdges(cg, func(e *callgraph.Edge) error {
+		edges = append(edges, fmt.Sprintf("%s -> %s",
+			e.Caller.Func.RelString(P),
+			e.Callee.Func.RelString(P)))
+		return nil
+	})
+	sort.Strings(edges)
+
+	want := []string{
+		"(*C).f -> (C).f",
+		"f -> (C).f",
+		"f -> f$1",
+		"f -> g",
+	}
+	if !reflect.DeepEqual(edges, want) {
+		t.Errorf("Got edges %v, want %v", edges, want)
+	}
+}
diff --git a/go/callgraph/util.go b/go/callgraph/util.go
new file mode 100644
index 0000000..a8f8903
--- /dev/null
+++ b/go/callgraph/util.go
@@ -0,0 +1,181 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package callgraph
+
+import "golang.org/x/tools/go/ssa"
+
+// This file provides various utilities over call graphs, such as
+// visitation and path search.
+
+// CalleesOf returns a new set containing all direct callees of the
+// caller node.
+//
+func CalleesOf(caller *Node) map[*Node]bool {
+	callees := make(map[*Node]bool)
+	for _, e := range caller.Out {
+		callees[e.Callee] = true
+	}
+	return callees
+}
+
+// GraphVisitEdges visits all the edges in graph g in depth-first order.
+// The edge function is called for each edge in postorder.  If it
+// returns non-nil, visitation stops and GraphVisitEdges returns that
+// value.
+//
+func GraphVisitEdges(g *Graph, edge func(*Edge) error) error {
+	seen := make(map[*Node]bool)
+	var visit func(n *Node) error
+	visit = func(n *Node) error {
+		if !seen[n] {
+			seen[n] = true
+			for _, e := range n.Out {
+				if err := visit(e.Callee); err != nil {
+					return err
+				}
+				if err := edge(e); err != nil {
+					return err
+				}
+			}
+		}
+		return nil
+	}
+	for _, n := range g.Nodes {
+		if err := visit(n); err != nil {
+			return err
+		}
+	}
+	return nil
+}
+
+// PathSearch finds an arbitrary path starting at node start and
+// ending at some node for which isEnd() returns true.  On success,
+// PathSearch returns the path as an ordered list of edges; on
+// failure, it returns nil.
+//
+func PathSearch(start *Node, isEnd func(*Node) bool) []*Edge {
+	stack := make([]*Edge, 0, 32)
+	seen := make(map[*Node]bool)
+	var search func(n *Node) []*Edge
+	search = func(n *Node) []*Edge {
+		if !seen[n] {
+			seen[n] = true
+			if isEnd(n) {
+				return stack
+			}
+			for _, e := range n.Out {
+				stack = append(stack, e) // push
+				if found := search(e.Callee); found != nil {
+					return found
+				}
+				stack = stack[:len(stack)-1] // pop
+			}
+		}
+		return nil
+	}
+	return search(start)
+}
+
+// DeleteSyntheticNodes removes from call graph g all nodes for
+// synthetic functions (except g.Root and package initializers),
+// preserving the topology.  In effect, calls to synthetic wrappers
+// are "inlined".
+//
+func (g *Graph) DeleteSyntheticNodes() {
+	// Measurements on the standard library and go.tools show that
+	// resulting graph has ~15% fewer nodes and 4-8% fewer edges
+	// than the input.
+	//
+	// Inlining a wrapper of in-degree m, out-degree n adds m*n
+	// and removes m+n edges.  Since most wrappers are monomorphic
+	// (n=1) this results in a slight reduction.  Polymorphic
+	// wrappers (n>1), e.g. from embedding an interface value
+	// inside a struct to satisfy some interface, cause an
+	// increase in the graph, but they seem to be uncommon.
+
+	// Hash all existing edges to avoid creating duplicates.
+	edges := make(map[Edge]bool)
+	for _, cgn := range g.Nodes {
+		for _, e := range cgn.Out {
+			edges[*e] = true
+		}
+	}
+	for fn, cgn := range g.Nodes {
+		if cgn == g.Root || fn.Synthetic == "" || isInit(cgn.Func) {
+			continue // keep
+		}
+		for _, eIn := range cgn.In {
+			for _, eOut := range cgn.Out {
+				newEdge := Edge{eIn.Caller, eIn.Site, eOut.Callee}
+				if edges[newEdge] {
+					continue // don't add duplicate
+				}
+				AddEdge(eIn.Caller, eIn.Site, eOut.Callee)
+				edges[newEdge] = true
+			}
+		}
+		g.DeleteNode(cgn)
+	}
+}
+
+func isInit(fn *ssa.Function) bool {
+	return fn.Pkg != nil && fn.Pkg.Func("init") == fn
+}
+
+// DeleteNode removes node n and its edges from the graph g.
+// (NB: not efficient for batch deletion.)
+func (g *Graph) DeleteNode(n *Node) {
+	n.deleteIns()
+	n.deleteOuts()
+	delete(g.Nodes, n.Func)
+}
+
+// deleteIns deletes all incoming edges to n.
+func (n *Node) deleteIns() {
+	for _, e := range n.In {
+		removeOutEdge(e)
+	}
+	n.In = nil
+}
+
+// deleteOuts deletes all outgoing edges from n.
+func (n *Node) deleteOuts() {
+	for _, e := range n.Out {
+		removeInEdge(e)
+	}
+	n.Out = nil
+}
+
+// removeOutEdge removes edge.Caller's outgoing edge 'edge'.
+func removeOutEdge(edge *Edge) {
+	caller := edge.Caller
+	n := len(caller.Out)
+	for i, e := range caller.Out {
+		if e == edge {
+			// Replace it with the final element and shrink the slice.
+			caller.Out[i] = caller.Out[n-1]
+			caller.Out[n-1] = nil // aid GC
+			caller.Out = caller.Out[:n-1]
+			return
+		}
+	}
+	panic("edge not found: " + edge.String())
+}
+
+// removeInEdge removes edge.Callee's incoming edge 'edge'.
+func removeInEdge(edge *Edge) {
+	caller := edge.Callee
+	n := len(caller.In)
+	for i, e := range caller.In {
+		if e == edge {
+			// Replace it with the final element and shrink the slice.
+			caller.In[i] = caller.In[n-1]
+			caller.In[n-1] = nil // aid GC
+			caller.In = caller.In[:n-1]
+			return
+		}
+	}
+	panic("edge not found: " + edge.String())
+}
diff --git a/go/exact/exact.go b/go/exact/exact.go
new file mode 100644
index 0000000..51c4906
--- /dev/null
+++ b/go/exact/exact.go
@@ -0,0 +1,920 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package exact implements Values representing untyped
+// Go constants and the corresponding operations. Values
+// and operations have unlimited precision.
+//
+// A special Unknown value may be used when a value
+// is unknown due to an error. Operations on unknown
+// values produce unknown values unless specified
+// otherwise.
+//
+package exact // import "golang.org/x/tools/go/exact"
+
+import (
+	"fmt"
+	"go/token"
+	"math/big"
+	"strconv"
+)
+
+// Kind specifies the kind of value represented by a Value.
+type Kind int
+
+// Implementation note: Kinds must be enumerated in
+// order of increasing "complexity" (used by match).
+
+const (
+	// unknown values
+	Unknown Kind = iota
+
+	// non-numeric values
+	Bool
+	String
+
+	// numeric values
+	Int
+	Float
+	Complex
+)
+
+// A Value represents a mathematically exact value of a given Kind.
+type Value interface {
+	// Kind returns the value kind; it is always the smallest
+	// kind in which the value can be represented exactly.
+	Kind() Kind
+
+	// String returns a human-readable form of the value.
+	String() string
+
+	// Prevent external implementations.
+	implementsValue()
+}
+
+// ----------------------------------------------------------------------------
+// Implementations
+
+type (
+	unknownVal struct{}
+	boolVal    bool
+	stringVal  string
+	int64Val   int64
+	intVal     struct{ val *big.Int }
+	floatVal   struct{ val *big.Rat }
+	complexVal struct{ re, im *big.Rat }
+)
+
+func (unknownVal) Kind() Kind { return Unknown }
+func (boolVal) Kind() Kind    { return Bool }
+func (stringVal) Kind() Kind  { return String }
+func (int64Val) Kind() Kind   { return Int }
+func (intVal) Kind() Kind     { return Int }
+func (floatVal) Kind() Kind   { return Float }
+func (complexVal) Kind() Kind { return Complex }
+
+func (unknownVal) String() string   { return "unknown" }
+func (x boolVal) String() string    { return fmt.Sprintf("%v", bool(x)) }
+func (x stringVal) String() string  { return strconv.Quote(string(x)) }
+func (x int64Val) String() string   { return strconv.FormatInt(int64(x), 10) }
+func (x intVal) String() string     { return x.val.String() }
+func (x floatVal) String() string   { return x.val.String() }
+func (x complexVal) String() string { return fmt.Sprintf("(%s + %si)", x.re, x.im) }
+
+func (unknownVal) implementsValue() {}
+func (boolVal) implementsValue()    {}
+func (stringVal) implementsValue()  {}
+func (int64Val) implementsValue()   {}
+func (intVal) implementsValue()     {}
+func (floatVal) implementsValue()   {}
+func (complexVal) implementsValue() {}
+
+// int64 bounds
+var (
+	minInt64 = big.NewInt(-1 << 63)
+	maxInt64 = big.NewInt(1<<63 - 1)
+)
+
+func normInt(x *big.Int) Value {
+	if minInt64.Cmp(x) <= 0 && x.Cmp(maxInt64) <= 0 {
+		return int64Val(x.Int64())
+	}
+	return intVal{x}
+}
+
+func normFloat(x *big.Rat) Value {
+	if x.IsInt() {
+		return normInt(x.Num())
+	}
+	return floatVal{x}
+}
+
+func normComplex(re, im *big.Rat) Value {
+	if im.Sign() == 0 {
+		return normFloat(re)
+	}
+	return complexVal{re, im}
+}
+
+// ----------------------------------------------------------------------------
+// Factories
+
+// MakeUnknown returns the Unknown value.
+func MakeUnknown() Value { return unknownVal{} }
+
+// MakeBool returns the Bool value for x.
+func MakeBool(b bool) Value { return boolVal(b) }
+
+// MakeString returns the String value for x.
+func MakeString(s string) Value { return stringVal(s) }
+
+// MakeInt64 returns the Int value for x.
+func MakeInt64(x int64) Value { return int64Val(x) }
+
+// MakeUint64 returns the Int value for x.
+func MakeUint64(x uint64) Value { return normInt(new(big.Int).SetUint64(x)) }
+
+// MakeFloat64 returns the numeric value for x.
+// If x is not finite, the result is unknown.
+func MakeFloat64(x float64) Value {
+	if f := new(big.Rat).SetFloat64(x); f != nil {
+		return normFloat(f)
+	}
+	return unknownVal{}
+}
+
+// MakeFromLiteral returns the corresponding integer, floating-point,
+// imaginary, character, or string value for a Go literal string. The
+// result is nil if the literal string is invalid.
+func MakeFromLiteral(lit string, tok token.Token) Value {
+	switch tok {
+	case token.INT:
+		if x, err := strconv.ParseInt(lit, 0, 64); err == nil {
+			return int64Val(x)
+		}
+		if x, ok := new(big.Int).SetString(lit, 0); ok {
+			return intVal{x}
+		}
+
+	case token.FLOAT:
+		if x, ok := new(big.Rat).SetString(lit); ok {
+			return normFloat(x)
+		}
+
+	case token.IMAG:
+		if n := len(lit); n > 0 && lit[n-1] == 'i' {
+			if im, ok := new(big.Rat).SetString(lit[0 : n-1]); ok {
+				return normComplex(big.NewRat(0, 1), im)
+			}
+		}
+
+	case token.CHAR:
+		if n := len(lit); n >= 2 {
+			if code, _, _, err := strconv.UnquoteChar(lit[1:n-1], '\''); err == nil {
+				return int64Val(code)
+			}
+		}
+
+	case token.STRING:
+		if s, err := strconv.Unquote(lit); err == nil {
+			return stringVal(s)
+		}
+	}
+
+	return nil
+}
+
+// ----------------------------------------------------------------------------
+// Accessors
+//
+// For unknown arguments the result is the zero value for the respective
+// accessor type, except for Sign, where the result is 1.
+
+// BoolVal returns the Go boolean value of x, which must be a Bool or an Unknown.
+// If x is Unknown, the result is false.
+func BoolVal(x Value) bool {
+	switch x := x.(type) {
+	case boolVal:
+		return bool(x)
+	case unknownVal:
+		return false
+	}
+	panic(fmt.Sprintf("%v not a Bool", x))
+}
+
+// StringVal returns the Go string value of x, which must be a String or an Unknown.
+// If x is Unknown, the result is "".
+func StringVal(x Value) string {
+	switch x := x.(type) {
+	case stringVal:
+		return string(x)
+	case unknownVal:
+		return ""
+	}
+	panic(fmt.Sprintf("%v not a String", x))
+}
+
+// Int64Val returns the Go int64 value of x and whether the result is exact;
+// x must be an Int or an Unknown. If the result is not exact, its value is undefined.
+// If x is Unknown, the result is (0, false).
+func Int64Val(x Value) (int64, bool) {
+	switch x := x.(type) {
+	case int64Val:
+		return int64(x), true
+	case intVal:
+		return x.val.Int64(), x.val.BitLen() <= 63
+	case unknownVal:
+		return 0, false
+	}
+	panic(fmt.Sprintf("%v not an Int", x))
+}
+
+// Uint64Val returns the Go uint64 value of x and whether the result is exact;
+// x must be an Int or an Unknown. If the result is not exact, its value is undefined.
+// If x is Unknown, the result is (0, false).
+func Uint64Val(x Value) (uint64, bool) {
+	switch x := x.(type) {
+	case int64Val:
+		return uint64(x), x >= 0
+	case intVal:
+		return x.val.Uint64(), x.val.Sign() >= 0 && x.val.BitLen() <= 64
+	case unknownVal:
+		return 0, false
+	}
+	panic(fmt.Sprintf("%v not an Int", x))
+}
+
+// Float32Val is like Float64Val but for float32 instead of float64.
+func Float32Val(x Value) (float32, bool) {
+	switch x := x.(type) {
+	case int64Val:
+		f := float32(x)
+		return f, int64Val(f) == x
+	case intVal:
+		return ratToFloat32(new(big.Rat).SetFrac(x.val, int1))
+	case floatVal:
+		return ratToFloat32(x.val)
+	case unknownVal:
+		return 0, false
+	}
+	panic(fmt.Sprintf("%v not a Float", x))
+}
+
+// Float64Val returns the nearest Go float64 value of x and whether the result is exact;
+// x must be numeric but not Complex, or Unknown. For values too small (too close to 0)
+// to represent as float64, Float64Val silently underflows to 0. The result sign always
+// matches the sign of x, even for 0.
+// If x is Unknown, the result is (0, false).
+func Float64Val(x Value) (float64, bool) {
+	switch x := x.(type) {
+	case int64Val:
+		f := float64(int64(x))
+		return f, int64Val(f) == x
+	case intVal:
+		return new(big.Rat).SetFrac(x.val, int1).Float64()
+	case floatVal:
+		return x.val.Float64()
+	case unknownVal:
+		return 0, false
+	}
+	panic(fmt.Sprintf("%v not a Float", x))
+}
+
+// BitLen returns the number of bits required to represent
+// the absolute value x in binary representation; x must be an Int or an Unknown.
+// If x is Unknown, the result is 0.
+func BitLen(x Value) int {
+	switch x := x.(type) {
+	case int64Val:
+		return new(big.Int).SetInt64(int64(x)).BitLen()
+	case intVal:
+		return x.val.BitLen()
+	case unknownVal:
+		return 0
+	}
+	panic(fmt.Sprintf("%v not an Int", x))
+}
+
+// Sign returns -1, 0, or 1 depending on whether x < 0, x == 0, or x > 0;
+// x must be numeric or Unknown. For complex values x, the sign is 0 if x == 0,
+// otherwise it is != 0. If x is Unknown, the result is 1.
+func Sign(x Value) int {
+	switch x := x.(type) {
+	case int64Val:
+		switch {
+		case x < 0:
+			return -1
+		case x > 0:
+			return 1
+		}
+		return 0
+	case intVal:
+		return x.val.Sign()
+	case floatVal:
+		return x.val.Sign()
+	case complexVal:
+		return x.re.Sign() | x.im.Sign()
+	case unknownVal:
+		return 1 // avoid spurious division by zero errors
+	}
+	panic(fmt.Sprintf("%v not numeric", x))
+}
+
+// ----------------------------------------------------------------------------
+// Support for serializing/deserializing integers
+
+const (
+	// Compute the size of a Word in bytes.
+	_m       = ^big.Word(0)
+	_log     = _m>>8&1 + _m>>16&1 + _m>>32&1
+	wordSize = 1 << _log
+)
+
+// Bytes returns the bytes for the absolute value of x in little-
+// endian binary representation; x must be an Int.
+func Bytes(x Value) []byte {
+	var val *big.Int
+	switch x := x.(type) {
+	case int64Val:
+		val = new(big.Int).SetInt64(int64(x))
+	case intVal:
+		val = x.val
+	default:
+		panic(fmt.Sprintf("%v not an Int", x))
+	}
+
+	words := val.Bits()
+	bytes := make([]byte, len(words)*wordSize)
+
+	i := 0
+	for _, w := range words {
+		for j := 0; j < wordSize; j++ {
+			bytes[i] = byte(w)
+			w >>= 8
+			i++
+		}
+	}
+	// remove leading 0's
+	for i > 0 && bytes[i-1] == 0 {
+		i--
+	}
+
+	return bytes[:i]
+}
+
+// MakeFromBytes returns the Int value given the bytes of its little-endian
+// binary representation. An empty byte slice argument represents 0.
+func MakeFromBytes(bytes []byte) Value {
+	words := make([]big.Word, (len(bytes)+(wordSize-1))/wordSize)
+
+	i := 0
+	var w big.Word
+	var s uint
+	for _, b := range bytes {
+		w |= big.Word(b) << s
+		if s += 8; s == wordSize*8 {
+			words[i] = w
+			i++
+			w = 0
+			s = 0
+		}
+	}
+	// store last word
+	if i < len(words) {
+		words[i] = w
+		i++
+	}
+	// remove leading 0's
+	for i > 0 && words[i-1] == 0 {
+		i--
+	}
+
+	return normInt(new(big.Int).SetBits(words[:i]))
+}
+
+// ----------------------------------------------------------------------------
+// Support for disassembling fractions
+
+// Num returns the numerator of x; x must be Int, Float, or Unknown.
+// If x is Unknown, the result is Unknown, otherwise it is an Int
+// with the same sign as x.
+func Num(x Value) Value {
+	switch x := x.(type) {
+	case unknownVal, int64Val, intVal:
+		return x
+	case floatVal:
+		return normInt(x.val.Num())
+	}
+	panic(fmt.Sprintf("%v not Int or Float", x))
+}
+
+// Denom returns the denominator of x; x must be Int, Float, or Unknown.
+// If x is Unknown, the result is Unknown, otherwise it is an Int >= 1.
+func Denom(x Value) Value {
+	switch x := x.(type) {
+	case unknownVal:
+		return x
+	case int64Val, intVal:
+		return int64Val(1)
+	case floatVal:
+		return normInt(x.val.Denom())
+	}
+	panic(fmt.Sprintf("%v not Int or Float", x))
+}
+
+// ----------------------------------------------------------------------------
+// Support for assembling/disassembling complex numbers
+
+// MakeImag returns the numeric value x*i (possibly 0);
+// x must be Int, Float, or Unknown.
+// If x is Unknown, the result is Unknown.
+func MakeImag(x Value) Value {
+	var im *big.Rat
+	switch x := x.(type) {
+	case unknownVal:
+		return x
+	case int64Val:
+		im = big.NewRat(int64(x), 1)
+	case intVal:
+		im = new(big.Rat).SetFrac(x.val, int1)
+	case floatVal:
+		im = x.val
+	default:
+		panic(fmt.Sprintf("%v not Int or Float", x))
+	}
+	return normComplex(rat0, im)
+}
+
+// Real returns the real part of x, which must be a numeric or unknown value.
+// If x is Unknown, the result is Unknown.
+func Real(x Value) Value {
+	switch x := x.(type) {
+	case unknownVal, int64Val, intVal, floatVal:
+		return x
+	case complexVal:
+		return normFloat(x.re)
+	}
+	panic(fmt.Sprintf("%v not numeric", x))
+}
+
+// Imag returns the imaginary part of x, which must be a numeric or unknown value.
+// If x is Unknown, the result is Unknown.
+func Imag(x Value) Value {
+	switch x := x.(type) {
+	case unknownVal:
+		return x
+	case int64Val, intVal, floatVal:
+		return int64Val(0)
+	case complexVal:
+		return normFloat(x.im)
+	}
+	panic(fmt.Sprintf("%v not numeric", x))
+}
+
+// ----------------------------------------------------------------------------
+// Operations
+
+// is32bit reports whether x can be represented using 32 bits.
+func is32bit(x int64) bool {
+	const s = 32
+	return -1<<(s-1) <= x && x <= 1<<(s-1)-1
+}
+
+// is63bit reports whether x can be represented using 63 bits.
+func is63bit(x int64) bool {
+	const s = 63
+	return -1<<(s-1) <= x && x <= 1<<(s-1)-1
+}
+
+// UnaryOp returns the result of the unary expression op y.
+// The operation must be defined for the operand.
+// If size >= 0 it specifies the ^ (xor) result size in bytes.
+// If y is Unknown, the result is Unknown.
+//
+func UnaryOp(op token.Token, y Value, size int) Value {
+	switch op {
+	case token.ADD:
+		switch y.(type) {
+		case unknownVal, int64Val, intVal, floatVal, complexVal:
+			return y
+		}
+
+	case token.SUB:
+		switch y := y.(type) {
+		case unknownVal:
+			return y
+		case int64Val:
+			if z := -y; z != y {
+				return z // no overflow
+			}
+			return normInt(new(big.Int).Neg(big.NewInt(int64(y))))
+		case intVal:
+			return normInt(new(big.Int).Neg(y.val))
+		case floatVal:
+			return normFloat(new(big.Rat).Neg(y.val))
+		case complexVal:
+			return normComplex(new(big.Rat).Neg(y.re), new(big.Rat).Neg(y.im))
+		}
+
+	case token.XOR:
+		var z big.Int
+		switch y := y.(type) {
+		case unknownVal:
+			return y
+		case int64Val:
+			z.Not(big.NewInt(int64(y)))
+		case intVal:
+			z.Not(y.val)
+		default:
+			goto Error
+		}
+		// For unsigned types, the result will be negative and
+		// thus "too large": We must limit the result size to
+		// the type's size.
+		if size >= 0 {
+			s := uint(size) * 8
+			z.AndNot(&z, new(big.Int).Lsh(big.NewInt(-1), s)) // z &^= (-1)<<s
+		}
+		return normInt(&z)
+
+	case token.NOT:
+		switch y := y.(type) {
+		case unknownVal:
+			return y
+		case boolVal:
+			return !y
+		}
+	}
+
+Error:
+	panic(fmt.Sprintf("invalid unary operation %s%v", op, y))
+}
+
+var (
+	int1 = big.NewInt(1)
+	rat0 = big.NewRat(0, 1)
+)
+
+func ord(x Value) int {
+	switch x.(type) {
+	default:
+		return 0
+	case boolVal, stringVal:
+		return 1
+	case int64Val:
+		return 2
+	case intVal:
+		return 3
+	case floatVal:
+		return 4
+	case complexVal:
+		return 5
+	}
+}
+
+// match returns the matching representation (same type) with the
+// smallest complexity for two values x and y. If one of them is
+// numeric, both of them must be numeric. If one of them is Unknown,
+// both results are Unknown.
+//
+func match(x, y Value) (_, _ Value) {
+	if ord(x) > ord(y) {
+		y, x = match(y, x)
+		return x, y
+	}
+	// ord(x) <= ord(y)
+
+	switch x := x.(type) {
+	case unknownVal:
+		return x, x
+
+	case boolVal, stringVal, complexVal:
+		return x, y
+
+	case int64Val:
+		switch y := y.(type) {
+		case int64Val:
+			return x, y
+		case intVal:
+			return intVal{big.NewInt(int64(x))}, y
+		case floatVal:
+			return floatVal{big.NewRat(int64(x), 1)}, y
+		case complexVal:
+			return complexVal{big.NewRat(int64(x), 1), rat0}, y
+		}
+
+	case intVal:
+		switch y := y.(type) {
+		case intVal:
+			return x, y
+		case floatVal:
+			return floatVal{new(big.Rat).SetFrac(x.val, int1)}, y
+		case complexVal:
+			return complexVal{new(big.Rat).SetFrac(x.val, int1), rat0}, y
+		}
+
+	case floatVal:
+		switch y := y.(type) {
+		case floatVal:
+			return x, y
+		case complexVal:
+			return complexVal{x.val, rat0}, y
+		}
+	}
+
+	panic("unreachable")
+}
+
+// BinaryOp returns the result of the binary expression x op y.
+// The operation must be defined for the operands. If one of the
+// operands is Unknown, the result is Unknown.
+// To force integer division of Int operands, use op == token.QUO_ASSIGN
+// instead of token.QUO; the result is guaranteed to be Int in this case.
+// Division by zero leads to a run-time panic.
+//
+func BinaryOp(x Value, op token.Token, y Value) Value {
+	x, y = match(x, y)
+
+	switch x := x.(type) {
+	case unknownVal:
+		return x
+
+	case boolVal:
+		y := y.(boolVal)
+		switch op {
+		case token.LAND:
+			return x && y
+		case token.LOR:
+			return x || y
+		}
+
+	case int64Val:
+		a := int64(x)
+		b := int64(y.(int64Val))
+		var c int64
+		switch op {
+		case token.ADD:
+			if !is63bit(a) || !is63bit(b) {
+				return normInt(new(big.Int).Add(big.NewInt(a), big.NewInt(b)))
+			}
+			c = a + b
+		case token.SUB:
+			if !is63bit(a) || !is63bit(b) {
+				return normInt(new(big.Int).Sub(big.NewInt(a), big.NewInt(b)))
+			}
+			c = a - b
+		case token.MUL:
+			if !is32bit(a) || !is32bit(b) {
+				return normInt(new(big.Int).Mul(big.NewInt(a), big.NewInt(b)))
+			}
+			c = a * b
+		case token.QUO:
+			return normFloat(new(big.Rat).SetFrac(big.NewInt(a), big.NewInt(b)))
+		case token.QUO_ASSIGN: // force integer division
+			c = a / b
+		case token.REM:
+			c = a % b
+		case token.AND:
+			c = a & b
+		case token.OR:
+			c = a | b
+		case token.XOR:
+			c = a ^ b
+		case token.AND_NOT:
+			c = a &^ b
+		default:
+			goto Error
+		}
+		return int64Val(c)
+
+	case intVal:
+		a := x.val
+		b := y.(intVal).val
+		var c big.Int
+		switch op {
+		case token.ADD:
+			c.Add(a, b)
+		case token.SUB:
+			c.Sub(a, b)
+		case token.MUL:
+			c.Mul(a, b)
+		case token.QUO:
+			return normFloat(new(big.Rat).SetFrac(a, b))
+		case token.QUO_ASSIGN: // force integer division
+			c.Quo(a, b)
+		case token.REM:
+			c.Rem(a, b)
+		case token.AND:
+			c.And(a, b)
+		case token.OR:
+			c.Or(a, b)
+		case token.XOR:
+			c.Xor(a, b)
+		case token.AND_NOT:
+			c.AndNot(a, b)
+		default:
+			goto Error
+		}
+		return normInt(&c)
+
+	case floatVal:
+		a := x.val
+		b := y.(floatVal).val
+		var c big.Rat
+		switch op {
+		case token.ADD:
+			c.Add(a, b)
+		case token.SUB:
+			c.Sub(a, b)
+		case token.MUL:
+			c.Mul(a, b)
+		case token.QUO:
+			c.Quo(a, b)
+		default:
+			goto Error
+		}
+		return normFloat(&c)
+
+	case complexVal:
+		y := y.(complexVal)
+		a, b := x.re, x.im
+		c, d := y.re, y.im
+		var re, im big.Rat
+		switch op {
+		case token.ADD:
+			// (a+c) + i(b+d)
+			re.Add(a, c)
+			im.Add(b, d)
+		case token.SUB:
+			// (a-c) + i(b-d)
+			re.Sub(a, c)
+			im.Sub(b, d)
+		case token.MUL:
+			// (ac-bd) + i(bc+ad)
+			var ac, bd, bc, ad big.Rat
+			ac.Mul(a, c)
+			bd.Mul(b, d)
+			bc.Mul(b, c)
+			ad.Mul(a, d)
+			re.Sub(&ac, &bd)
+			im.Add(&bc, &ad)
+		case token.QUO:
+			// (ac+bd)/s + i(bc-ad)/s, with s = cc + dd
+			var ac, bd, bc, ad, s, cc, dd big.Rat
+			ac.Mul(a, c)
+			bd.Mul(b, d)
+			bc.Mul(b, c)
+			ad.Mul(a, d)
+			cc.Mul(c, c)
+			dd.Mul(d, d)
+			s.Add(&cc, &dd)
+			re.Add(&ac, &bd)
+			re.Quo(&re, &s)
+			im.Sub(&bc, &ad)
+			im.Quo(&im, &s)
+		default:
+			goto Error
+		}
+		return normComplex(&re, &im)
+
+	case stringVal:
+		if op == token.ADD {
+			return x + y.(stringVal)
+		}
+	}
+
+Error:
+	panic(fmt.Sprintf("invalid binary operation %v %s %v", x, op, y))
+}
+
+// Shift returns the result of the shift expression x op s
+// with op == token.SHL or token.SHR (<< or >>). x must be
+// an Int or an Unknown. If x is Unknown, the result is x.
+//
+func Shift(x Value, op token.Token, s uint) Value {
+	switch x := x.(type) {
+	case unknownVal:
+		return x
+
+	case int64Val:
+		if s == 0 {
+			return x
+		}
+		switch op {
+		case token.SHL:
+			z := big.NewInt(int64(x))
+			return normInt(z.Lsh(z, s))
+		case token.SHR:
+			return x >> s
+		}
+
+	case intVal:
+		if s == 0 {
+			return x
+		}
+		var z big.Int
+		switch op {
+		case token.SHL:
+			return normInt(z.Lsh(x.val, s))
+		case token.SHR:
+			return normInt(z.Rsh(x.val, s))
+		}
+	}
+
+	panic(fmt.Sprintf("invalid shift %v %s %d", x, op, s))
+}
+
+func cmpZero(x int, op token.Token) bool {
+	switch op {
+	case token.EQL:
+		return x == 0
+	case token.NEQ:
+		return x != 0
+	case token.LSS:
+		return x < 0
+	case token.LEQ:
+		return x <= 0
+	case token.GTR:
+		return x > 0
+	case token.GEQ:
+		return x >= 0
+	}
+	panic("unreachable")
+}
+
+// Compare returns the result of the comparison x op y.
+// The comparison must be defined for the operands.
+// If one of the operands is Unknown, the result is
+// false.
+//
+func Compare(x Value, op token.Token, y Value) bool {
+	x, y = match(x, y)
+
+	switch x := x.(type) {
+	case unknownVal:
+		return false
+
+	case boolVal:
+		y := y.(boolVal)
+		switch op {
+		case token.EQL:
+			return x == y
+		case token.NEQ:
+			return x != y
+		}
+
+	case int64Val:
+		y := y.(int64Val)
+		switch op {
+		case token.EQL:
+			return x == y
+		case token.NEQ:
+			return x != y
+		case token.LSS:
+			return x < y
+		case token.LEQ:
+			return x <= y
+		case token.GTR:
+			return x > y
+		case token.GEQ:
+			return x >= y
+		}
+
+	case intVal:
+		return cmpZero(x.val.Cmp(y.(intVal).val), op)
+
+	case floatVal:
+		return cmpZero(x.val.Cmp(y.(floatVal).val), op)
+
+	case complexVal:
+		y := y.(complexVal)
+		re := x.re.Cmp(y.re)
+		im := x.im.Cmp(y.im)
+		switch op {
+		case token.EQL:
+			return re == 0 && im == 0
+		case token.NEQ:
+			return re != 0 || im != 0
+		}
+
+	case stringVal:
+		y := y.(stringVal)
+		switch op {
+		case token.EQL:
+			return x == y
+		case token.NEQ:
+			return x != y
+		case token.LSS:
+			return x < y
+		case token.LEQ:
+			return x <= y
+		case token.GTR:
+			return x > y
+		case token.GEQ:
+			return x >= y
+		}
+	}
+
+	panic(fmt.Sprintf("invalid comparison %v %s %v", x, op, y))
+}
diff --git a/go/exact/exact_test.go b/go/exact/exact_test.go
new file mode 100644
index 0000000..aa38a89
--- /dev/null
+++ b/go/exact/exact_test.go
@@ -0,0 +1,375 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package exact
+
+import (
+	"go/token"
+	"strings"
+	"testing"
+)
+
+// TODO(gri) expand this test framework
+
+var opTests = []string{
+	// unary operations
+	`+ 0 = 0`,
+	`+ ? = ?`,
+	`- 1 = -1`,
+	`- ? = ?`,
+	`^ 0 = -1`,
+	`^ ? = ?`,
+
+	`! true = false`,
+	`! false = true`,
+	`! ? = ?`,
+
+	// etc.
+
+	// binary operations
+	`"" + "" = ""`,
+	`"foo" + "" = "foo"`,
+	`"" + "bar" = "bar"`,
+	`"foo" + "bar" = "foobar"`,
+
+	`0 + 0 = 0`,
+	`0 + 0.1 = 0.1`,
+	`0 + 0.1i = 0.1i`,
+	`0.1 + 0.9 = 1`,
+	`1e100 + 1e100 = 2e100`,
+	`? + 0 = ?`,
+	`0 + ? = ?`,
+
+	`0 - 0 = 0`,
+	`0 - 0.1 = -0.1`,
+	`0 - 0.1i = -0.1i`,
+	`1e100 - 1e100 = 0`,
+	`? - 0 = ?`,
+	`0 - ? = ?`,
+
+	`0 * 0 = 0`,
+	`1 * 0.1 = 0.1`,
+	`1 * 0.1i = 0.1i`,
+	`1i * 1i = -1`,
+	`? * 0 = ?`,
+	`0 * ? = ?`,
+
+	`0 / 0 = "division_by_zero"`,
+	`10 / 2 = 5`,
+	`5 / 3 = 5/3`,
+	`5i / 3i = 5/3`,
+	`? / 0 = ?`,
+	`0 / ? = ?`,
+
+	`0 % 0 = "runtime_error:_integer_divide_by_zero"`, // TODO(gri) should be the same as for /
+	`10 % 3 = 1`,
+	`? % 0 = ?`,
+	`0 % ? = ?`,
+
+	`0 & 0 = 0`,
+	`12345 & 0 = 0`,
+	`0xff & 0xf = 0xf`,
+	`? & 0 = ?`,
+	`0 & ? = ?`,
+
+	`0 | 0 = 0`,
+	`12345 | 0 = 12345`,
+	`0xb | 0xa0 = 0xab`,
+	`? | 0 = ?`,
+	`0 | ? = ?`,
+
+	`0 ^ 0 = 0`,
+	`1 ^ -1 = -2`,
+	`? ^ 0 = ?`,
+	`0 ^ ? = ?`,
+
+	`0 &^ 0 = 0`,
+	`0xf &^ 1 = 0xe`,
+	`1 &^ 0xf = 0`,
+	// etc.
+
+	// shifts
+	`0 << 0 = 0`,
+	`1 << 10 = 1024`,
+	`0 >> 0 = 0`,
+	`1024 >> 10 == 1`,
+	`? << 0 == ?`,
+	`? >> 10 == ?`,
+	// etc.
+
+	// comparisons
+	`false == false = true`,
+	`false == true = false`,
+	`true == false = false`,
+	`true == true = true`,
+
+	`false != false = false`,
+	`false != true = true`,
+	`true != false = true`,
+	`true != true = false`,
+
+	`"foo" == "bar" = false`,
+	`"foo" != "bar" = true`,
+	`"foo" < "bar" = false`,
+	`"foo" <= "bar" = false`,
+	`"foo" > "bar" = true`,
+	`"foo" >= "bar" = true`,
+
+	`0 == 0 = true`,
+	`0 != 0 = false`,
+	`0 < 10 = true`,
+	`10 <= 10 = true`,
+	`0 > 10 = false`,
+	`10 >= 10 = true`,
+
+	`1/123456789 == 1/123456789 == true`,
+	`1/123456789 != 1/123456789 == false`,
+	`1/123456789 < 1/123456788 == true`,
+	`1/123456788 <= 1/123456789 == false`,
+	`0.11 > 0.11 = false`,
+	`0.11 >= 0.11 = true`,
+
+	`? == 0 = false`,
+	`? != 0 = false`,
+	`? < 10 = false`,
+	`? <= 10 = false`,
+	`? > 10 = false`,
+	`? >= 10 = false`,
+
+	`0 == ? = false`,
+	`0 != ? = false`,
+	`0 < ? = false`,
+	`10 <= ? = false`,
+	`0 > ? = false`,
+	`10 >= ? = false`,
+
+	// etc.
+}
+
+func TestOps(t *testing.T) {
+	for _, test := range opTests {
+		a := strings.Split(test, " ")
+		i := 0 // operator index
+
+		var x, x0 Value
+		switch len(a) {
+		case 4:
+			// unary operation
+		case 5:
+			// binary operation
+			x, x0 = val(a[0]), val(a[0])
+			i = 1
+		default:
+			t.Errorf("invalid test case: %s", test)
+			continue
+		}
+
+		op, ok := optab[a[i]]
+		if !ok {
+			panic("missing optab entry for " + a[i])
+		}
+
+		y, y0 := val(a[i+1]), val(a[i+1])
+
+		got := doOp(x, op, y)
+		want := val(a[i+3])
+		if !eql(got, want) {
+			t.Errorf("%s: got %s; want %s", test, got, want)
+		}
+		if x0 != nil && !eql(x, x0) {
+			t.Errorf("%s: x changed to %s", test, x)
+		}
+		if !eql(y, y0) {
+			t.Errorf("%s: y changed to %s", test, y)
+		}
+	}
+}
+
+func eql(x, y Value) bool {
+	_, ux := x.(unknownVal)
+	_, uy := y.(unknownVal)
+	if ux || uy {
+		return ux == uy
+	}
+	return Compare(x, token.EQL, y)
+}
+
+// ----------------------------------------------------------------------------
+// Support functions
+
+func val(lit string) Value {
+	if len(lit) == 0 {
+		return MakeUnknown()
+	}
+
+	switch lit {
+	case "?":
+		return MakeUnknown()
+	case "true":
+		return MakeBool(true)
+	case "false":
+		return MakeBool(false)
+	}
+
+	tok := token.INT
+	switch first, last := lit[0], lit[len(lit)-1]; {
+	case first == '"' || first == '`':
+		tok = token.STRING
+		lit = strings.Replace(lit, "_", " ", -1)
+	case first == '\'':
+		tok = token.CHAR
+	case last == 'i':
+		tok = token.IMAG
+	default:
+		if !strings.HasPrefix(lit, "0x") && strings.ContainsAny(lit, "./Ee") {
+			tok = token.FLOAT
+		}
+	}
+
+	return MakeFromLiteral(lit, tok)
+}
+
+var optab = map[string]token.Token{
+	"!": token.NOT,
+
+	"+": token.ADD,
+	"-": token.SUB,
+	"*": token.MUL,
+	"/": token.QUO,
+	"%": token.REM,
+
+	"<<": token.SHL,
+	">>": token.SHR,
+
+	"&":  token.AND,
+	"|":  token.OR,
+	"^":  token.XOR,
+	"&^": token.AND_NOT,
+
+	"==": token.EQL,
+	"!=": token.NEQ,
+	"<":  token.LSS,
+	"<=": token.LEQ,
+	">":  token.GTR,
+	">=": token.GEQ,
+}
+
+func panicHandler(v *Value) {
+	switch p := recover().(type) {
+	case nil:
+		// nothing to do
+	case string:
+		*v = MakeString(p)
+	case error:
+		*v = MakeString(p.Error())
+	default:
+		panic(p)
+	}
+}
+
+func doOp(x Value, op token.Token, y Value) (z Value) {
+	defer panicHandler(&z)
+
+	if x == nil {
+		return UnaryOp(op, y, -1)
+	}
+
+	switch op {
+	case token.EQL, token.NEQ, token.LSS, token.LEQ, token.GTR, token.GEQ:
+		return MakeBool(Compare(x, op, y))
+	case token.SHL, token.SHR:
+		s, _ := Int64Val(y)
+		return Shift(x, op, uint(s))
+	default:
+		return BinaryOp(x, op, y)
+	}
+}
+
+// ----------------------------------------------------------------------------
+// Other tests
+
+var fracTests = []string{
+	"0 0 1",
+	"1 1 1",
+	"-1 -1 1",
+	"1.2 6 5",
+	"-0.991 -991 1000",
+	"1e100 1e100 1",
+}
+
+func TestFractions(t *testing.T) {
+	for _, test := range fracTests {
+		a := strings.Split(test, " ")
+		if len(a) != 3 {
+			t.Errorf("invalid test case: %s", test)
+			continue
+		}
+
+		x := val(a[0])
+		n := val(a[1])
+		d := val(a[2])
+
+		if got := Num(x); !eql(got, n) {
+			t.Errorf("%s: got num = %s; want %s", test, got, n)
+		}
+
+		if got := Denom(x); !eql(got, d) {
+			t.Errorf("%s: got denom = %s; want %s", test, got, d)
+		}
+	}
+}
+
+var bytesTests = []string{
+	"0",
+	"1",
+	"123456789",
+	"123456789012345678901234567890123456789012345678901234567890",
+}
+
+func TestBytes(t *testing.T) {
+	for _, test := range bytesTests {
+		x := val(test)
+		bytes := Bytes(x)
+
+		// special case 0
+		if Sign(x) == 0 && len(bytes) != 0 {
+			t.Errorf("%s: got %v; want empty byte slice", test, bytes)
+		}
+
+		if n := len(bytes); n > 0 && bytes[n-1] == 0 {
+			t.Errorf("%s: got %v; want no leading 0 byte", test, bytes)
+		}
+
+		if got := MakeFromBytes(bytes); !eql(got, x) {
+			t.Errorf("%s: got %s; want %s (bytes = %v)", test, got, x, bytes)
+		}
+	}
+}
+
+func TestUnknown(t *testing.T) {
+	u := MakeUnknown()
+	var values = []Value{
+		u,
+		MakeBool(false), // token.ADD ok below, operation is never considered
+		MakeString(""),
+		MakeInt64(1),
+		MakeFromLiteral("-1234567890123456789012345678901234567890", token.INT),
+		MakeFloat64(1.2),
+		MakeImag(MakeFloat64(1.2)),
+	}
+	for _, val := range values {
+		x, y := val, u
+		for i := range [2]int{} {
+			if i == 1 {
+				x, y = y, x
+			}
+			if got := BinaryOp(x, token.ADD, y); got.Kind() != Unknown {
+				t.Errorf("%s + %s: got %s; want %s", x, y, got, u)
+			}
+			if got := Compare(x, token.EQL, y); got {
+				t.Errorf("%s == %s: got true; want false", x, y)
+			}
+		}
+	}
+}
diff --git a/go/exact/go13.go b/go/exact/go13.go
new file mode 100644
index 0000000..1016c14
--- /dev/null
+++ b/go/exact/go13.go
@@ -0,0 +1,24 @@
+// Copyright 2014 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !go1.4
+
+package exact
+
+import (
+	"math"
+	"math/big"
+)
+
+func ratToFloat32(x *big.Rat) (float32, bool) {
+	// Before 1.4, there's no Rat.Float32.
+	// Emulate it, albeit at the cost of
+	// imprecision in corner cases.
+	x64, exact := x.Float64()
+	x32 := float32(x64)
+	if math.IsInf(float64(x32), 0) {
+		exact = false
+	}
+	return x32, exact
+}
diff --git a/go/exact/go14.go b/go/exact/go14.go
new file mode 100644
index 0000000..b86e5d2
--- /dev/null
+++ b/go/exact/go14.go
@@ -0,0 +1,13 @@
+// Copyright 2014 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build go1.4
+
+package exact
+
+import "math/big"
+
+func ratToFloat32(x *big.Rat) (float32, bool) {
+	return x.Float32()
+}
diff --git a/go/gccgoimporter/gccgoinstallation.go b/go/gccgoimporter/gccgoinstallation.go
new file mode 100644
index 0000000..1c56cf5
--- /dev/null
+++ b/go/gccgoimporter/gccgoinstallation.go
@@ -0,0 +1,95 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package gccgoimporter
+
+import (
+	"bufio"
+	"os"
+	"os/exec"
+	"path/filepath"
+	"strings"
+
+	"golang.org/x/tools/go/types"
+)
+
+// Information about a specific installation of gccgo.
+type GccgoInstallation struct {
+	// Version of gcc (e.g. 4.8.0).
+	GccVersion string
+
+	// Target triple (e.g. x86_64-unknown-linux-gnu).
+	TargetTriple string
+
+	// Built-in library paths used by this installation.
+	LibPaths []string
+}
+
+// Ask the driver at the given path for information for this GccgoInstallation.
+func (inst *GccgoInstallation) InitFromDriver(gccgoPath string) (err error) {
+	cmd := exec.Command(gccgoPath, "-###", "-S", "-x", "go", "-")
+	stderr, err := cmd.StderrPipe()
+	if err != nil {
+		return
+	}
+
+	err = cmd.Start()
+	if err != nil {
+		return
+	}
+
+	scanner := bufio.NewScanner(stderr)
+	for scanner.Scan() {
+		line := scanner.Text()
+		switch {
+		case strings.HasPrefix(line, "Target: "):
+			inst.TargetTriple = line[8:]
+
+		case line[0] == ' ':
+			args := strings.Fields(line)
+			for _, arg := range args[1:] {
+				if strings.HasPrefix(arg, "-L") {
+					inst.LibPaths = append(inst.LibPaths, arg[2:])
+				}
+			}
+		}
+	}
+
+	stdout, err := exec.Command(gccgoPath, "-dumpversion").Output()
+	if err != nil {
+		return
+	}
+	inst.GccVersion = strings.TrimSpace(string(stdout))
+
+	return
+}
+
+// Return the list of export search paths for this GccgoInstallation.
+func (inst *GccgoInstallation) SearchPaths() (paths []string) {
+	for _, lpath := range inst.LibPaths {
+		spath := filepath.Join(lpath, "go", inst.GccVersion)
+		fi, err := os.Stat(spath)
+		if err != nil || !fi.IsDir() {
+			continue
+		}
+		paths = append(paths, spath)
+
+		spath = filepath.Join(spath, inst.TargetTriple)
+		fi, err = os.Stat(spath)
+		if err != nil || !fi.IsDir() {
+			continue
+		}
+		paths = append(paths, spath)
+	}
+
+	paths = append(paths, inst.LibPaths...)
+
+	return
+}
+
+// Return an importer that searches incpaths followed by the gcc installation's
+// built-in search paths and the current directory.
+func (inst *GccgoInstallation) GetImporter(incpaths []string, initmap map[*types.Package]InitData) types.Importer {
+	return GetImporter(append(append(incpaths, inst.SearchPaths()...), "."), initmap)
+}
diff --git a/go/gccgoimporter/gccgoinstallation_test.go b/go/gccgoimporter/gccgoinstallation_test.go
new file mode 100644
index 0000000..9ab928d
--- /dev/null
+++ b/go/gccgoimporter/gccgoinstallation_test.go
@@ -0,0 +1,194 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package gccgoimporter
+
+import (
+	"runtime"
+	"testing"
+
+	"golang.org/x/tools/go/types"
+)
+
+var importablePackages = [...]string{
+	"archive/tar",
+	"archive/zip",
+	"bufio",
+	"bytes",
+	"compress/bzip2",
+	"compress/flate",
+	"compress/gzip",
+	"compress/lzw",
+	"compress/zlib",
+	"container/heap",
+	"container/list",
+	"container/ring",
+	"crypto/aes",
+	"crypto/cipher",
+	"crypto/des",
+	"crypto/dsa",
+	"crypto/ecdsa",
+	"crypto/elliptic",
+	"crypto",
+	"crypto/hmac",
+	"crypto/md5",
+	"crypto/rand",
+	"crypto/rc4",
+	"crypto/rsa",
+	"crypto/sha1",
+	"crypto/sha256",
+	"crypto/sha512",
+	"crypto/subtle",
+	"crypto/tls",
+	"crypto/x509",
+	"crypto/x509/pkix",
+	"database/sql/driver",
+	"database/sql",
+	"debug/dwarf",
+	"debug/elf",
+	"debug/gosym",
+	"debug/macho",
+	"debug/pe",
+	"encoding/ascii85",
+	"encoding/asn1",
+	"encoding/base32",
+	"encoding/base64",
+	"encoding/binary",
+	"encoding/csv",
+	"encoding/gob",
+	"encoding",
+	"encoding/hex",
+	"encoding/json",
+	"encoding/pem",
+	"encoding/xml",
+	"errors",
+	"exp/proxy",
+	"exp/terminal",
+	"expvar",
+	"flag",
+	"fmt",
+	"go/ast",
+	"go/build",
+	"go/doc",
+	"go/format",
+	"go/parser",
+	"go/printer",
+	"go/scanner",
+	"go/token",
+	"hash/adler32",
+	"hash/crc32",
+	"hash/crc64",
+	"hash/fnv",
+	"hash",
+	"html",
+	"html/template",
+	"image/color",
+	"image/color/palette",
+	"image/draw",
+	"image/gif",
+	"image",
+	"image/jpeg",
+	"image/png",
+	"index/suffixarray",
+	"io",
+	"io/ioutil",
+	"log",
+	"log/syslog",
+	"math/big",
+	"math/cmplx",
+	"math",
+	"math/rand",
+	"mime",
+	"mime/multipart",
+	"net",
+	"net/http/cgi",
+	"net/http/cookiejar",
+	"net/http/fcgi",
+	"net/http",
+	"net/http/httptest",
+	"net/http/httputil",
+	"net/http/pprof",
+	"net/mail",
+	"net/rpc",
+	"net/rpc/jsonrpc",
+	"net/smtp",
+	"net/textproto",
+	"net/url",
+	"old/regexp",
+	"old/template",
+	"os/exec",
+	"os",
+	"os/signal",
+	"os/user",
+	"path/filepath",
+	"path",
+	"reflect",
+	"regexp",
+	"regexp/syntax",
+	"runtime/debug",
+	"runtime",
+	"runtime/pprof",
+	"sort",
+	"strconv",
+	"strings",
+	"sync/atomic",
+	"sync",
+	"syscall",
+	"testing",
+	"testing/iotest",
+	"testing/quick",
+	"text/scanner",
+	"text/tabwriter",
+	"text/template",
+	"text/template/parse",
+	"time",
+	"unicode",
+	"unicode/utf16",
+	"unicode/utf8",
+}
+
+func TestInstallationImporter(t *testing.T) {
+	// This test relies on gccgo being around, which it most likely will be if we
+	// were compiled with gccgo.
+	if runtime.Compiler != "gccgo" {
+		t.Skip("This test needs gccgo")
+		return
+	}
+
+	var inst GccgoInstallation
+	err := inst.InitFromDriver("gccgo")
+	if err != nil {
+		t.Fatal(err)
+	}
+	imp := inst.GetImporter(nil, nil)
+
+	// Ensure we don't regress the number of packages we can parse. First import
+	// all packages into the same map and then each individually.
+	pkgMap := make(map[string]*types.Package)
+	for _, pkg := range importablePackages {
+		_, err = imp(pkgMap, pkg)
+		if err != nil {
+			t.Error(err)
+		}
+	}
+
+	for _, pkg := range importablePackages {
+		_, err = imp(make(map[string]*types.Package), pkg)
+		if err != nil {
+			t.Error(err)
+		}
+	}
+
+	// Test for certain specific entities in the imported data.
+	for _, test := range [...]importerTest{
+		{pkgpath: "io", name: "Reader", want: "type Reader interface{Read(p []uint8) (n int, err error)}"},
+		{pkgpath: "io", name: "ReadWriter", want: "type ReadWriter interface{Reader; Writer}"},
+		{pkgpath: "math", name: "Pi", want: "const Pi untyped float"},
+		{pkgpath: "math", name: "Sin", want: "func Sin(x float64) float64"},
+		{pkgpath: "sort", name: "Ints", want: "func Ints(a []int)"},
+		{pkgpath: "unsafe", name: "Pointer", want: "type Pointer unsafe.Pointer"},
+	} {
+		runImporterTest(t, imp, nil, &test)
+	}
+}
diff --git a/go/gccgoimporter/importer.go b/go/gccgoimporter/importer.go
new file mode 100644
index 0000000..ac484af
--- /dev/null
+++ b/go/gccgoimporter/importer.go
@@ -0,0 +1,205 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package gccgoimporter implements Import for gccgo-generated object files.
+package gccgoimporter // import "golang.org/x/tools/go/gccgoimporter"
+
+import (
+	"bytes"
+	"debug/elf"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"os"
+	"os/exec"
+	"path/filepath"
+	"strings"
+
+	"golang.org/x/tools/go/importer"
+	"golang.org/x/tools/go/types"
+)
+
+// A PackageInit describes an imported package that needs initialization.
+type PackageInit struct {
+	Name     string // short package name
+	InitFunc string // name of init function
+	Priority int    // priority of init function, see InitData.Priority
+}
+
+// The gccgo-specific init data for a package.
+type InitData struct {
+	// Initialization priority of this package relative to other packages.
+	// This is based on the maximum depth of the package's dependency graph;
+	// it is guaranteed to be greater than that of its dependencies.
+	Priority int
+
+	// The list of packages which this package depends on to be initialized,
+	// including itself if needed. This is the subset of the transitive closure of
+	// the package's dependencies that need initialization.
+	Inits []PackageInit
+}
+
+// Locate the file from which to read export data.
+// This is intended to replicate the logic in gofrontend.
+func findExportFile(searchpaths []string, pkgpath string) (string, error) {
+	for _, spath := range searchpaths {
+		pkgfullpath := filepath.Join(spath, pkgpath)
+		pkgdir, name := filepath.Split(pkgfullpath)
+
+		for _, filepath := range [...]string{
+			pkgfullpath,
+			pkgfullpath + ".gox",
+			pkgdir + "lib" + name + ".so",
+			pkgdir + "lib" + name + ".a",
+			pkgfullpath + ".o",
+		} {
+			fi, err := os.Stat(filepath)
+			if err == nil && !fi.IsDir() {
+				return filepath, nil
+			}
+		}
+	}
+
+	return "", fmt.Errorf("%s: could not find export data (tried %s)", pkgpath, strings.Join(searchpaths, ":"))
+}
+
+const (
+	gccgov1Magic    = "v1;\n"
+	goimporterMagic = "\n$$ "
+	archiveMagic    = "!<ar"
+)
+
+// Opens the export data file at the given path. If this is an ELF file,
+// searches for and opens the .go_export section. If this is an archive,
+// reads the export data from the first member, which is assumed to be an ELF file.
+// This is intended to replicate the logic in gofrontend.
+func openExportFile(fpath string) (reader io.ReadSeeker, closer io.Closer, err error) {
+	f, err := os.Open(fpath)
+	if err != nil {
+		return
+	}
+	closer = f
+	defer func() {
+		if err != nil && closer != nil {
+			f.Close()
+		}
+	}()
+
+	var magic [4]byte
+	_, err = f.ReadAt(magic[:], 0)
+	if err != nil {
+		return
+	}
+	// reset to offset 0 - needed on Plan 9 (see issue #11265)
+	// TODO: remove once issue #11265 has been resolved.
+	_, err = f.Seek(0, 0)
+	if err != nil {
+		return
+	}
+
+	var elfreader io.ReaderAt
+	switch string(magic[:]) {
+	case gccgov1Magic, goimporterMagic:
+		// Raw export data.
+		reader = f
+		return
+
+	case archiveMagic:
+		// TODO(pcc): Read the archive directly instead of using "ar".
+		f.Close()
+		closer = nil
+
+		cmd := exec.Command("ar", "p", fpath)
+		var out []byte
+		out, err = cmd.Output()
+		if err != nil {
+			return
+		}
+
+		elfreader = bytes.NewReader(out)
+
+	default:
+		elfreader = f
+	}
+
+	ef, err := elf.NewFile(elfreader)
+	if err != nil {
+		return
+	}
+
+	sec := ef.Section(".go_export")
+	if sec == nil {
+		err = fmt.Errorf("%s: .go_export section not found", fpath)
+		return
+	}
+
+	reader = sec.Open()
+	return
+}
+
+func GetImporter(searchpaths []string, initmap map[*types.Package]InitData) types.Importer {
+	return func(imports map[string]*types.Package, pkgpath string) (pkg *types.Package, err error) {
+		if pkgpath == "unsafe" {
+			return types.Unsafe, nil
+		}
+
+		fpath, err := findExportFile(searchpaths, pkgpath)
+		if err != nil {
+			return
+		}
+
+		reader, closer, err := openExportFile(fpath)
+		if err != nil {
+			return
+		}
+		if closer != nil {
+			defer closer.Close()
+		}
+
+		var magic [4]byte
+		_, err = reader.Read(magic[:])
+		if err != nil {
+			return
+		}
+		_, err = reader.Seek(0, 0)
+		if err != nil {
+			return
+		}
+
+		switch string(magic[:]) {
+		case gccgov1Magic:
+			var p parser
+			p.init(fpath, reader, imports)
+			pkg = p.parsePackage()
+			if initmap != nil {
+				initmap[pkg] = p.initdata
+			}
+
+		case goimporterMagic:
+			var data []byte
+			data, err = ioutil.ReadAll(reader)
+			if err != nil {
+				return
+			}
+			var n int
+			n, pkg, err = importer.ImportData(imports, data)
+			if err != nil {
+				return
+			}
+
+			if initmap != nil {
+				suffixreader := bytes.NewReader(data[n:])
+				var p parser
+				p.init(fpath, suffixreader, nil)
+				p.parseInitData()
+				initmap[pkg] = p.initdata
+			}
+
+		default:
+			err = fmt.Errorf("unrecognized magic string: %q", string(magic[:]))
+		}
+
+		return
+	}
+}
diff --git a/go/gccgoimporter/importer_test.go b/go/gccgoimporter/importer_test.go
new file mode 100644
index 0000000..78b4349
--- /dev/null
+++ b/go/gccgoimporter/importer_test.go
@@ -0,0 +1,170 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package gccgoimporter
+
+import (
+	"io/ioutil"
+	"os"
+	"os/exec"
+	"path/filepath"
+	"runtime"
+	"testing"
+
+	"golang.org/x/tools/go/types"
+)
+
+type importerTest struct {
+	pkgpath, name, want, wantval string
+	wantinits                    []string
+}
+
+func runImporterTest(t *testing.T, imp types.Importer, initmap map[*types.Package]InitData, test *importerTest) {
+	pkg, err := imp(make(map[string]*types.Package), test.pkgpath)
+	if err != nil {
+		t.Error(err)
+		return
+	}
+
+	if test.name != "" {
+		obj := pkg.Scope().Lookup(test.name)
+		if obj == nil {
+			t.Errorf("%s: object not found", test.name)
+			return
+		}
+
+		got := types.ObjectString(obj, types.RelativeTo(pkg))
+		if got != test.want {
+			t.Errorf("%s: got %q; want %q", test.name, got, test.want)
+		}
+
+		if test.wantval != "" {
+			gotval := obj.(*types.Const).Val().String()
+			if gotval != test.wantval {
+				t.Errorf("%s: got val %q; want val %q", test.name, gotval, test.wantval)
+			}
+		}
+	}
+
+	if len(test.wantinits) > 0 {
+		initdata := initmap[pkg]
+		found := false
+		// Check that the package's own init function has the package's priority
+		for _, pkginit := range initdata.Inits {
+			if pkginit.InitFunc == test.wantinits[0] {
+				if initdata.Priority != pkginit.Priority {
+					t.Errorf("%s: got self priority %d; want %d", test.pkgpath, pkginit.Priority, initdata.Priority)
+				}
+				found = true
+				break
+			}
+		}
+
+		if !found {
+			t.Errorf("%s: could not find expected function %q", test.pkgpath, test.wantinits[0])
+		}
+
+		// Each init function in the list other than the first one is a
+		// dependency of the function immediately before it. Check that
+		// the init functions appear in descending priority order.
+		priority := initdata.Priority
+		for _, wantdepinit := range test.wantinits[1:] {
+			found = false
+			for _, pkginit := range initdata.Inits {
+				if pkginit.InitFunc == wantdepinit {
+					if priority <= pkginit.Priority {
+						t.Errorf("%s: got dep priority %d; want less than %d", test.pkgpath, pkginit.Priority, priority)
+					}
+					found = true
+					priority = pkginit.Priority
+					break
+				}
+			}
+
+			if !found {
+				t.Errorf("%s: could not find expected function %q", test.pkgpath, wantdepinit)
+			}
+		}
+	}
+}
+
+var importerTests = [...]importerTest{
+	{pkgpath: "pointer", name: "Int8Ptr", want: "type Int8Ptr *int8"},
+	{pkgpath: "complexnums", name: "NN", want: "const NN untyped complex", wantval: "(-1/1 + -1/1i)"},
+	{pkgpath: "complexnums", name: "NP", want: "const NP untyped complex", wantval: "(-1/1 + 1/1i)"},
+	{pkgpath: "complexnums", name: "PN", want: "const PN untyped complex", wantval: "(1/1 + -1/1i)"},
+	{pkgpath: "complexnums", name: "PP", want: "const PP untyped complex", wantval: "(1/1 + 1/1i)"},
+	// TODO: enable this entry once bug has been tracked down
+	//{pkgpath: "imports", wantinits: []string{"imports..import", "fmt..import", "math..import"}},
+}
+
+func TestGoxImporter(t *testing.T) {
+	if runtime.GOOS == "android" {
+		t.Skipf("no testdata directory on %s", runtime.GOOS)
+	}
+	initmap := make(map[*types.Package]InitData)
+	imp := GetImporter([]string{"testdata"}, initmap)
+
+	for _, test := range importerTests {
+		runImporterTest(t, imp, initmap, &test)
+	}
+}
+
+func TestObjImporter(t *testing.T) {
+	// This test relies on gccgo being around, which it most likely will be if we
+	// were compiled with gccgo.
+	if runtime.Compiler != "gccgo" {
+		t.Skip("This test needs gccgo")
+		return
+	}
+
+	tmpdir, err := ioutil.TempDir("", "")
+	if err != nil {
+		t.Fatal(err)
+	}
+	initmap := make(map[*types.Package]InitData)
+	imp := GetImporter([]string{tmpdir}, initmap)
+
+	artmpdir, err := ioutil.TempDir("", "")
+	if err != nil {
+		t.Fatal(err)
+	}
+	arinitmap := make(map[*types.Package]InitData)
+	arimp := GetImporter([]string{artmpdir}, arinitmap)
+
+	for _, test := range importerTests {
+		gofile := filepath.Join("testdata", test.pkgpath+".go")
+		ofile := filepath.Join(tmpdir, test.pkgpath+".o")
+		afile := filepath.Join(artmpdir, "lib"+test.pkgpath+".a")
+
+		cmd := exec.Command("gccgo", "-fgo-pkgpath="+test.pkgpath, "-c", "-o", ofile, gofile)
+		out, err := cmd.CombinedOutput()
+		if err != nil {
+			t.Logf("%s", out)
+			t.Fatalf("gccgo %s failed: %s", gofile, err)
+		}
+
+		runImporterTest(t, imp, initmap, &test)
+
+		cmd = exec.Command("ar", "cr", afile, ofile)
+		out, err = cmd.CombinedOutput()
+		if err != nil {
+			t.Logf("%s", out)
+			t.Fatalf("ar cr %s %s failed: %s", afile, ofile, err)
+		}
+
+		runImporterTest(t, arimp, arinitmap, &test)
+
+		if err = os.Remove(ofile); err != nil {
+			t.Fatal(err)
+		}
+		if err = os.Remove(afile); err != nil {
+			t.Fatal(err)
+		}
+	}
+
+	if err = os.Remove(tmpdir); err != nil {
+		t.Fatal(err)
+	}
+}
diff --git a/go/gccgoimporter/parser.go b/go/gccgoimporter/parser.go
new file mode 100644
index 0000000..d20a967
--- /dev/null
+++ b/go/gccgoimporter/parser.go
@@ -0,0 +1,856 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package gccgoimporter
+
+import (
+	"bytes"
+	"errors"
+	"fmt"
+	"go/token"
+	"io"
+	"strconv"
+	"strings"
+	"text/scanner"
+
+	"golang.org/x/tools/go/exact"
+	"golang.org/x/tools/go/types"
+)
+
+type parser struct {
+	scanner  scanner.Scanner
+	tok      rune                      // current token
+	lit      string                    // literal string; only valid for Ident, Int, String tokens
+	pkgpath  string                    // package path of imported package
+	pkgname  string                    // name of imported package
+	pkg      *types.Package            // reference to imported package
+	imports  map[string]*types.Package // package path -> package object
+	typeMap  map[int]types.Type        // type number -> type
+	initdata InitData                  // package init priority data
+}
+
+func (p *parser) init(filename string, src io.Reader, imports map[string]*types.Package) {
+	p.scanner.Init(src)
+	p.scanner.Error = func(_ *scanner.Scanner, msg string) { p.error(msg) }
+	p.scanner.Mode = scanner.ScanIdents | scanner.ScanInts | scanner.ScanFloats | scanner.ScanStrings | scanner.ScanComments | scanner.SkipComments
+	p.scanner.Whitespace = 1<<'\t' | 1<<'\n' | 1<<' '
+	p.scanner.Filename = filename // for good error messages
+	p.next()
+	p.imports = imports
+	p.typeMap = make(map[int]types.Type)
+}
+
+type importError struct {
+	pos scanner.Position
+	err error
+}
+
+func (e importError) Error() string {
+	return fmt.Sprintf("import error %s (byte offset = %d): %s", e.pos, e.pos.Offset, e.err)
+}
+
+func (p *parser) error(err interface{}) {
+	if s, ok := err.(string); ok {
+		err = errors.New(s)
+	}
+	// panic with a runtime.Error if err is not an error
+	panic(importError{p.scanner.Pos(), err.(error)})
+}
+
+func (p *parser) errorf(format string, args ...interface{}) {
+	p.error(fmt.Errorf(format, args...))
+}
+
+func (p *parser) expect(tok rune) string {
+	lit := p.lit
+	if p.tok != tok {
+		p.errorf("expected %s, got %s (%s)", scanner.TokenString(tok), scanner.TokenString(p.tok), lit)
+	}
+	p.next()
+	return lit
+}
+
+func (p *parser) expectKeyword(keyword string) {
+	lit := p.expect(scanner.Ident)
+	if lit != keyword {
+		p.errorf("expected keyword %s, got %q", keyword, lit)
+	}
+}
+
+func (p *parser) parseString() string {
+	str, err := strconv.Unquote(p.expect(scanner.String))
+	if err != nil {
+		p.error(err)
+	}
+	return str
+}
+
+// unquotedString     = { unquotedStringChar } .
+// unquotedStringChar = <neither a whitespace nor a ';' char> .
+func (p *parser) parseUnquotedString() string {
+	if p.tok == scanner.EOF {
+		p.error("unexpected EOF")
+	}
+	var buf bytes.Buffer
+	buf.WriteString(p.scanner.TokenText())
+	// This loop needs to examine each character before deciding whether to consume it. If we see a semicolon,
+	// we need to let it be consumed by p.next().
+	for ch := p.scanner.Peek(); ch != ';' && ch != scanner.EOF && p.scanner.Whitespace&(1<<uint(ch)) == 0; ch = p.scanner.Peek() {
+		buf.WriteRune(ch)
+		p.scanner.Next()
+	}
+	p.next()
+	return buf.String()
+}
+
+func (p *parser) next() {
+	p.tok = p.scanner.Scan()
+	switch p.tok {
+	case scanner.Ident, scanner.Int, scanner.Float, scanner.String, '·':
+		p.lit = p.scanner.TokenText()
+	default:
+		p.lit = ""
+	}
+}
+
+func (p *parser) parseQualifiedName() (path, name string) {
+	return p.parseQualifiedNameStr(p.parseString())
+}
+
+func (p *parser) parseUnquotedQualifiedName() (path, name string) {
+	return p.parseQualifiedNameStr(p.parseUnquotedString())
+}
+
+// qualifiedName = [ ["."] unquotedString "." ] unquotedString .
+//
+// The above production uses greedy matching.
+func (p *parser) parseQualifiedNameStr(unquotedName string) (pkgpath, name string) {
+	parts := strings.Split(unquotedName, ".")
+	if parts[0] == "" {
+		parts = parts[1:]
+	}
+
+	switch len(parts) {
+	case 0:
+		p.errorf("malformed qualified name: %q", unquotedName)
+	case 1:
+		// unqualified name
+		pkgpath = p.pkgpath
+		name = parts[0]
+	default:
+		// qualified name, which may contain periods
+		pkgpath = strings.Join(parts[0:len(parts)-1], ".")
+		name = parts[len(parts)-1]
+	}
+
+	return
+}
+
+// getPkg returns the package for a given path. If the package is
+// not found but we have a package name, create the package and
+// add it to the p.imports map.
+//
+func (p *parser) getPkg(pkgpath, name string) *types.Package {
+	// package unsafe is not in the imports map - handle explicitly
+	if pkgpath == "unsafe" {
+		return types.Unsafe
+	}
+	pkg := p.imports[pkgpath]
+	if pkg == nil && name != "" {
+		pkg = types.NewPackage(pkgpath, name)
+		p.imports[pkgpath] = pkg
+	}
+	return pkg
+}
+
+// parseExportedName is like parseQualifiedName, but
+// the package path is resolved to an imported *types.Package.
+//
+// ExportedName = string [string] .
+func (p *parser) parseExportedName() (pkg *types.Package, name string) {
+	path, name := p.parseQualifiedName()
+	var pkgname string
+	if p.tok == scanner.String {
+		pkgname = p.parseString()
+	}
+	pkg = p.getPkg(path, pkgname)
+	if pkg == nil {
+		p.errorf("package %s (path = %q) not found", name, path)
+	}
+	return
+}
+
+// Name = QualifiedName | "?" .
+func (p *parser) parseName() string {
+	if p.tok == '?' {
+		// Anonymous.
+		p.next()
+		return ""
+	}
+	// The package path is redundant for us. Don't try to parse it.
+	_, name := p.parseUnquotedQualifiedName()
+	return name
+}
+
+func deref(typ types.Type) types.Type {
+	if p, _ := typ.(*types.Pointer); p != nil {
+		typ = p.Elem()
+	}
+	return typ
+}
+
+// Field = Name Type [string] .
+func (p *parser) parseField(pkg *types.Package) (field *types.Var, tag string) {
+	name := p.parseName()
+	typ := p.parseType(pkg)
+	anon := false
+	if name == "" {
+		anon = true
+		switch typ := deref(typ).(type) {
+		case *types.Basic:
+			name = typ.Name()
+		case *types.Named:
+			name = typ.Obj().Name()
+		default:
+			p.error("anonymous field expected")
+		}
+	}
+	field = types.NewField(token.NoPos, pkg, name, typ, anon)
+	if p.tok == scanner.String {
+		tag = p.parseString()
+	}
+	return
+}
+
+// Param = Name ["..."] Type .
+func (p *parser) parseParam(pkg *types.Package) (param *types.Var, isVariadic bool) {
+	name := p.parseName()
+	if p.tok == '.' {
+		p.next()
+		p.expect('.')
+		p.expect('.')
+		isVariadic = true
+	}
+	typ := p.parseType(pkg)
+	if isVariadic {
+		typ = types.NewSlice(typ)
+	}
+	param = types.NewParam(token.NoPos, pkg, name, typ)
+	return
+}
+
+// Var = Name Type .
+func (p *parser) parseVar(pkg *types.Package) *types.Var {
+	name := p.parseName()
+	return types.NewVar(token.NoPos, pkg, name, p.parseType(pkg))
+}
+
+// ConstValue     = string | "false" | "true" | ["-"] (int ["'"] | FloatOrComplex) .
+// FloatOrComplex = float ["i" | ("+"|"-") float "i"] .
+func (p *parser) parseConstValue() (val exact.Value, typ types.Type) {
+	switch p.tok {
+	case scanner.String:
+		str := p.parseString()
+		val = exact.MakeString(str)
+		typ = types.Typ[types.UntypedString]
+		return
+
+	case scanner.Ident:
+		b := false
+		switch p.lit {
+		case "false":
+		case "true":
+			b = true
+
+		default:
+			p.errorf("expected const value, got %s (%q)", scanner.TokenString(p.tok), p.lit)
+		}
+
+		p.next()
+		val = exact.MakeBool(b)
+		typ = types.Typ[types.UntypedBool]
+		return
+	}
+
+	sign := ""
+	if p.tok == '-' {
+		p.next()
+		sign = "-"
+	}
+
+	switch p.tok {
+	case scanner.Int:
+		val = exact.MakeFromLiteral(sign+p.lit, token.INT)
+		if val == nil {
+			p.error("could not parse integer literal")
+		}
+
+		p.next()
+		if p.tok == '\'' {
+			p.next()
+			typ = types.Typ[types.UntypedRune]
+		} else {
+			typ = types.Typ[types.UntypedInt]
+		}
+
+	case scanner.Float:
+		re := sign + p.lit
+		p.next()
+
+		var im string
+		switch p.tok {
+		case '+':
+			p.next()
+			im = p.expect(scanner.Float)
+
+		case '-':
+			p.next()
+			im = "-" + p.expect(scanner.Float)
+
+		case scanner.Ident:
+			// re is in fact the imaginary component. Expect "i" below.
+			im = re
+			re = "0"
+
+		default:
+			val = exact.MakeFromLiteral(re, token.FLOAT)
+			if val == nil {
+				p.error("could not parse float literal")
+			}
+			typ = types.Typ[types.UntypedFloat]
+			return
+		}
+
+		p.expectKeyword("i")
+		reval := exact.MakeFromLiteral(re, token.FLOAT)
+		if reval == nil {
+			p.error("could not parse real component of complex literal")
+		}
+		imval := exact.MakeFromLiteral(im+"i", token.IMAG)
+		if imval == nil {
+			p.error("could not parse imag component of complex literal")
+		}
+		val = exact.BinaryOp(reval, token.ADD, imval)
+		typ = types.Typ[types.UntypedComplex]
+
+	default:
+		p.errorf("expected const value, got %s (%q)", scanner.TokenString(p.tok), p.lit)
+	}
+
+	return
+}
+
+// Const = Name [Type] "=" ConstValue .
+func (p *parser) parseConst(pkg *types.Package) *types.Const {
+	name := p.parseName()
+	var typ types.Type
+	if p.tok == '<' {
+		typ = p.parseType(pkg)
+	}
+	p.expect('=')
+	val, vtyp := p.parseConstValue()
+	if typ == nil {
+		typ = vtyp
+	}
+	return types.NewConst(token.NoPos, pkg, name, typ, val)
+}
+
+// TypeName = ExportedName .
+func (p *parser) parseTypeName() *types.TypeName {
+	pkg, name := p.parseExportedName()
+	scope := pkg.Scope()
+	if obj := scope.Lookup(name); obj != nil {
+		return obj.(*types.TypeName)
+	}
+	obj := types.NewTypeName(token.NoPos, pkg, name, nil)
+	// a named type may be referred to before the underlying type
+	// is known - set it up
+	types.NewNamed(obj, nil, nil)
+	scope.Insert(obj)
+	return obj
+}
+
+// NamedType = TypeName Type { Method } .
+// Method    = "func" "(" Param ")" Name ParamList ResultList ";" .
+func (p *parser) parseNamedType(n int) types.Type {
+	obj := p.parseTypeName()
+
+	pkg := obj.Pkg()
+	typ := obj.Type()
+	p.typeMap[n] = typ
+
+	nt, ok := typ.(*types.Named)
+	if !ok {
+		// This can happen for unsafe.Pointer, which is a TypeName holding a Basic type.
+		pt := p.parseType(pkg)
+		if pt != typ {
+			p.error("unexpected underlying type for non-named TypeName")
+		}
+		return typ
+	}
+
+	underlying := p.parseType(pkg)
+	if nt.Underlying() == nil {
+		nt.SetUnderlying(underlying.Underlying())
+	}
+
+	for p.tok == scanner.Ident {
+		// collect associated methods
+		p.expectKeyword("func")
+		p.expect('(')
+		receiver, _ := p.parseParam(pkg)
+		p.expect(')')
+		name := p.parseName()
+		params, isVariadic := p.parseParamList(pkg)
+		results := p.parseResultList(pkg)
+		p.expect(';')
+
+		sig := types.NewSignature(receiver, params, results, isVariadic)
+		nt.AddMethod(types.NewFunc(token.NoPos, pkg, name, sig))
+	}
+
+	return nt
+}
+
+func (p *parser) parseInt() int64 {
+	lit := p.expect(scanner.Int)
+	n, err := strconv.ParseInt(lit, 10, 0)
+	if err != nil {
+		p.error(err)
+	}
+	return n
+}
+
+// ArrayOrSliceType = "[" [ int ] "]" Type .
+func (p *parser) parseArrayOrSliceType(pkg *types.Package) types.Type {
+	p.expect('[')
+	if p.tok == ']' {
+		p.next()
+		return types.NewSlice(p.parseType(pkg))
+	}
+
+	n := p.parseInt()
+	p.expect(']')
+	return types.NewArray(p.parseType(pkg), n)
+}
+
+// MapType = "map" "[" Type "]" Type .
+func (p *parser) parseMapType(pkg *types.Package) types.Type {
+	p.expectKeyword("map")
+	p.expect('[')
+	key := p.parseType(pkg)
+	p.expect(']')
+	elem := p.parseType(pkg)
+	return types.NewMap(key, elem)
+}
+
+// ChanType = "chan" ["<-" | "-<"] Type .
+func (p *parser) parseChanType(pkg *types.Package) types.Type {
+	p.expectKeyword("chan")
+	dir := types.SendRecv
+	switch p.tok {
+	case '-':
+		p.next()
+		p.expect('<')
+		dir = types.SendOnly
+
+	case '<':
+		// don't consume '<' if it belongs to Type
+		if p.scanner.Peek() == '-' {
+			p.next()
+			p.expect('-')
+			dir = types.RecvOnly
+		}
+	}
+
+	return types.NewChan(dir, p.parseType(pkg))
+}
+
+// StructType = "struct" "{" { Field } "}" .
+func (p *parser) parseStructType(pkg *types.Package) types.Type {
+	p.expectKeyword("struct")
+
+	var fields []*types.Var
+	var tags []string
+
+	p.expect('{')
+	for p.tok != '}' && p.tok != scanner.EOF {
+		field, tag := p.parseField(pkg)
+		p.expect(';')
+		fields = append(fields, field)
+		tags = append(tags, tag)
+	}
+	p.expect('}')
+
+	return types.NewStruct(fields, tags)
+}
+
+// ParamList = "(" [ { Parameter "," } Parameter ] ")" .
+func (p *parser) parseParamList(pkg *types.Package) (*types.Tuple, bool) {
+	var list []*types.Var
+	isVariadic := false
+
+	p.expect('(')
+	for p.tok != ')' && p.tok != scanner.EOF {
+		if len(list) > 0 {
+			p.expect(',')
+		}
+		par, variadic := p.parseParam(pkg)
+		list = append(list, par)
+		if variadic {
+			if isVariadic {
+				p.error("... not on final argument")
+			}
+			isVariadic = true
+		}
+	}
+	p.expect(')')
+
+	return types.NewTuple(list...), isVariadic
+}
+
+// ResultList = Type | ParamList .
+func (p *parser) parseResultList(pkg *types.Package) *types.Tuple {
+	switch p.tok {
+	case '<':
+		return types.NewTuple(types.NewParam(token.NoPos, pkg, "", p.parseType(pkg)))
+
+	case '(':
+		params, _ := p.parseParamList(pkg)
+		return params
+
+	default:
+		return nil
+	}
+}
+
+// FunctionType = ParamList ResultList .
+func (p *parser) parseFunctionType(pkg *types.Package) *types.Signature {
+	params, isVariadic := p.parseParamList(pkg)
+	results := p.parseResultList(pkg)
+	return types.NewSignature(nil, params, results, isVariadic)
+}
+
+// Func = Name FunctionType .
+func (p *parser) parseFunc(pkg *types.Package) *types.Func {
+	name := p.parseName()
+	if strings.ContainsRune(name, '$') {
+		// This is a Type$equal or Type$hash function, which we don't want to parse,
+		// except for the types.
+		p.discardDirectiveWhileParsingTypes(pkg)
+		return nil
+	}
+	return types.NewFunc(token.NoPos, pkg, name, p.parseFunctionType(pkg))
+}
+
+// InterfaceType = "interface" "{" { ("?" Type | Func) ";" } "}" .
+func (p *parser) parseInterfaceType(pkg *types.Package) types.Type {
+	p.expectKeyword("interface")
+
+	var methods []*types.Func
+	var typs []*types.Named
+
+	p.expect('{')
+	for p.tok != '}' && p.tok != scanner.EOF {
+		if p.tok == '?' {
+			p.next()
+			typs = append(typs, p.parseType(pkg).(*types.Named))
+		} else {
+			method := p.parseFunc(pkg)
+			methods = append(methods, method)
+		}
+		p.expect(';')
+	}
+	p.expect('}')
+
+	return types.NewInterface(methods, typs)
+}
+
+// PointerType = "*" ("any" | Type) .
+func (p *parser) parsePointerType(pkg *types.Package) types.Type {
+	p.expect('*')
+	if p.tok == scanner.Ident {
+		p.expectKeyword("any")
+		return types.Typ[types.UnsafePointer]
+	}
+	return types.NewPointer(p.parseType(pkg))
+}
+
+// TypeDefinition = NamedType | MapType | ChanType | StructType | InterfaceType | PointerType | ArrayOrSliceType | FunctionType .
+func (p *parser) parseTypeDefinition(pkg *types.Package, n int) types.Type {
+	var t types.Type
+	switch p.tok {
+	case scanner.String:
+		t = p.parseNamedType(n)
+
+	case scanner.Ident:
+		switch p.lit {
+		case "map":
+			t = p.parseMapType(pkg)
+
+		case "chan":
+			t = p.parseChanType(pkg)
+
+		case "struct":
+			t = p.parseStructType(pkg)
+
+		case "interface":
+			t = p.parseInterfaceType(pkg)
+		}
+
+	case '*':
+		t = p.parsePointerType(pkg)
+
+	case '[':
+		t = p.parseArrayOrSliceType(pkg)
+
+	case '(':
+		t = p.parseFunctionType(pkg)
+	}
+
+	p.typeMap[n] = t
+	return t
+}
+
+const (
+	// From gofrontend/go/export.h
+	// Note that these values are negative in the gofrontend and have been made positive
+	// in the gccgoimporter.
+	gccgoBuiltinINT8       = 1
+	gccgoBuiltinINT16      = 2
+	gccgoBuiltinINT32      = 3
+	gccgoBuiltinINT64      = 4
+	gccgoBuiltinUINT8      = 5
+	gccgoBuiltinUINT16     = 6
+	gccgoBuiltinUINT32     = 7
+	gccgoBuiltinUINT64     = 8
+	gccgoBuiltinFLOAT32    = 9
+	gccgoBuiltinFLOAT64    = 10
+	gccgoBuiltinINT        = 11
+	gccgoBuiltinUINT       = 12
+	gccgoBuiltinUINTPTR    = 13
+	gccgoBuiltinBOOL       = 15
+	gccgoBuiltinSTRING     = 16
+	gccgoBuiltinCOMPLEX64  = 17
+	gccgoBuiltinCOMPLEX128 = 18
+	gccgoBuiltinERROR      = 19
+	gccgoBuiltinBYTE       = 20
+	gccgoBuiltinRUNE       = 21
+)
+
+func lookupBuiltinType(typ int) types.Type {
+	return [...]types.Type{
+		gccgoBuiltinINT8:       types.Typ[types.Int8],
+		gccgoBuiltinINT16:      types.Typ[types.Int16],
+		gccgoBuiltinINT32:      types.Typ[types.Int32],
+		gccgoBuiltinINT64:      types.Typ[types.Int64],
+		gccgoBuiltinUINT8:      types.Typ[types.Uint8],
+		gccgoBuiltinUINT16:     types.Typ[types.Uint16],
+		gccgoBuiltinUINT32:     types.Typ[types.Uint32],
+		gccgoBuiltinUINT64:     types.Typ[types.Uint64],
+		gccgoBuiltinFLOAT32:    types.Typ[types.Float32],
+		gccgoBuiltinFLOAT64:    types.Typ[types.Float64],
+		gccgoBuiltinINT:        types.Typ[types.Int],
+		gccgoBuiltinUINT:       types.Typ[types.Uint],
+		gccgoBuiltinUINTPTR:    types.Typ[types.Uintptr],
+		gccgoBuiltinBOOL:       types.Typ[types.Bool],
+		gccgoBuiltinSTRING:     types.Typ[types.String],
+		gccgoBuiltinCOMPLEX64:  types.Typ[types.Complex64],
+		gccgoBuiltinCOMPLEX128: types.Typ[types.Complex128],
+		gccgoBuiltinERROR:      types.Universe.Lookup("error").Type(),
+		gccgoBuiltinBYTE:       types.Universe.Lookup("byte").Type(),
+		gccgoBuiltinRUNE:       types.Universe.Lookup("rune").Type(),
+	}[typ]
+}
+
+// Type = "<" "type" ( "-" int | int [ TypeDefinition ] ) ">" .
+func (p *parser) parseType(pkg *types.Package) (t types.Type) {
+	p.expect('<')
+	p.expectKeyword("type")
+
+	switch p.tok {
+	case scanner.Int:
+		n := p.parseInt()
+
+		if p.tok == '>' {
+			t = p.typeMap[int(n)]
+		} else {
+			t = p.parseTypeDefinition(pkg, int(n))
+		}
+
+	case '-':
+		p.next()
+		n := p.parseInt()
+		t = lookupBuiltinType(int(n))
+
+	default:
+		p.errorf("expected type number, got %s (%q)", scanner.TokenString(p.tok), p.lit)
+		return nil
+	}
+
+	p.expect('>')
+	return
+}
+
+// PackageInit = unquotedString unquotedString int .
+func (p *parser) parsePackageInit() PackageInit {
+	name := p.parseUnquotedString()
+	initfunc := p.parseUnquotedString()
+	priority := int(p.parseInt())
+	return PackageInit{Name: name, InitFunc: initfunc, Priority: priority}
+}
+
+// Throw away tokens until we see a ';'. If we see a '<', attempt to parse as a type.
+func (p *parser) discardDirectiveWhileParsingTypes(pkg *types.Package) {
+	for {
+		switch p.tok {
+		case ';':
+			return
+		case '<':
+			p.parseType(p.pkg)
+		case scanner.EOF:
+			p.error("unexpected EOF")
+		default:
+			p.next()
+		}
+	}
+}
+
+// Create the package if we have parsed both the package path and package name.
+func (p *parser) maybeCreatePackage() {
+	if p.pkgname != "" && p.pkgpath != "" {
+		p.pkg = p.getPkg(p.pkgpath, p.pkgname)
+	}
+}
+
+// InitDataDirective = "v1" ";" |
+//                     "priority" int ";" |
+//                     "init" { PackageInit } ";" |
+//                     "checksum" unquotedString ";" .
+func (p *parser) parseInitDataDirective() {
+	if p.tok != scanner.Ident {
+		// unexpected token kind; panic
+		p.expect(scanner.Ident)
+	}
+
+	switch p.lit {
+	case "v1":
+		p.next()
+		p.expect(';')
+
+	case "priority":
+		p.next()
+		p.initdata.Priority = int(p.parseInt())
+		p.expect(';')
+
+	case "init":
+		p.next()
+		for p.tok != ';' && p.tok != scanner.EOF {
+			p.initdata.Inits = append(p.initdata.Inits, p.parsePackageInit())
+		}
+		p.expect(';')
+
+	case "checksum":
+		// Don't let the scanner try to parse the checksum as a number.
+		defer func(mode uint) {
+			p.scanner.Mode = mode
+		}(p.scanner.Mode)
+		p.scanner.Mode &^= scanner.ScanInts | scanner.ScanFloats
+		p.next()
+		p.parseUnquotedString()
+		p.expect(';')
+
+	default:
+		p.errorf("unexpected identifier: %q", p.lit)
+	}
+}
+
+// Directive = InitDataDirective |
+//             "package" unquotedString ";" |
+//             "pkgpath" unquotedString ";" |
+//             "import" unquotedString unquotedString string ";" |
+//             "func" Func ";" |
+//             "type" Type ";" |
+//             "var" Var ";" |
+//             "const" Const ";" .
+func (p *parser) parseDirective() {
+	if p.tok != scanner.Ident {
+		// unexpected token kind; panic
+		p.expect(scanner.Ident)
+	}
+
+	switch p.lit {
+	case "v1", "priority", "init", "checksum":
+		p.parseInitDataDirective()
+
+	case "package":
+		p.next()
+		p.pkgname = p.parseUnquotedString()
+		p.maybeCreatePackage()
+		p.expect(';')
+
+	case "pkgpath":
+		p.next()
+		p.pkgpath = p.parseUnquotedString()
+		p.maybeCreatePackage()
+		p.expect(';')
+
+	case "import":
+		p.next()
+		pkgname := p.parseUnquotedString()
+		pkgpath := p.parseUnquotedString()
+		p.getPkg(pkgpath, pkgname)
+		p.parseString()
+		p.expect(';')
+
+	case "func":
+		p.next()
+		fun := p.parseFunc(p.pkg)
+		if fun != nil {
+			p.pkg.Scope().Insert(fun)
+		}
+		p.expect(';')
+
+	case "type":
+		p.next()
+		p.parseType(p.pkg)
+		p.expect(';')
+
+	case "var":
+		p.next()
+		v := p.parseVar(p.pkg)
+		p.pkg.Scope().Insert(v)
+		p.expect(';')
+
+	case "const":
+		p.next()
+		c := p.parseConst(p.pkg)
+		p.pkg.Scope().Insert(c)
+		p.expect(';')
+
+	default:
+		p.errorf("unexpected identifier: %q", p.lit)
+	}
+}
+
+// Package = { Directive } .
+func (p *parser) parsePackage() *types.Package {
+	for p.tok != scanner.EOF {
+		p.parseDirective()
+	}
+	for _, typ := range p.typeMap {
+		if it, ok := typ.(*types.Interface); ok {
+			it.Complete()
+		}
+	}
+	p.pkg.MarkComplete()
+	return p.pkg
+}
+
+// InitData = { InitDataDirective } .
+func (p *parser) parseInitData() {
+	for p.tok != scanner.EOF {
+		p.parseInitDataDirective()
+	}
+}
diff --git a/go/gccgoimporter/parser_test.go b/go/gccgoimporter/parser_test.go
new file mode 100644
index 0000000..1f0f12a
--- /dev/null
+++ b/go/gccgoimporter/parser_test.go
@@ -0,0 +1,73 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package gccgoimporter
+
+import (
+	"bytes"
+	"strings"
+	"testing"
+	"text/scanner"
+
+	"golang.org/x/tools/go/types"
+)
+
+var typeParserTests = []struct {
+	id, typ, want, underlying, methods string
+}{
+	{id: "foo", typ: "<type -1>", want: "int8"},
+	{id: "foo", typ: "<type 1 *<type -19>>", want: "*error"},
+	{id: "foo", typ: "<type 1 *any>", want: "unsafe.Pointer"},
+	{id: "foo", typ: "<type 1 \"Bar\" <type 2 *<type 1>>>", want: "foo.Bar", underlying: "*foo.Bar"},
+	{id: "foo", typ: "<type 1 \"bar.Foo\" \"bar\" <type -1> func (? <type 1>) M (); >", want: "bar.Foo", underlying: "int8", methods: "func (bar.Foo).M()"},
+	{id: "foo", typ: "<type 1 \".bar.foo\" \"bar\" <type -1>>", want: "bar.foo", underlying: "int8"},
+	{id: "foo", typ: "<type 1 []<type -1>>", want: "[]int8"},
+	{id: "foo", typ: "<type 1 [42]<type -1>>", want: "[42]int8"},
+	{id: "foo", typ: "<type 1 map [<type -1>] <type -2>>", want: "map[int8]int16"},
+	{id: "foo", typ: "<type 1 chan <type -1>>", want: "chan int8"},
+	{id: "foo", typ: "<type 1 chan <- <type -1>>", want: "<-chan int8"},
+	{id: "foo", typ: "<type 1 chan -< <type -1>>", want: "chan<- int8"},
+	{id: "foo", typ: "<type 1 struct { I8 <type -1>; I16 <type -2> \"i16\"; }>", want: "struct{I8 int8; I16 int16 \"i16\"}"},
+	{id: "foo", typ: "<type 1 interface { Foo (a <type -1>, b <type -2>) <type -1>; Bar (? <type -2>, ? ...<type -1>) (? <type -2>, ? <type -1>); Baz (); }>", want: "interface{Bar(int16, ...int8) (int16, int8); Baz(); Foo(a int8, b int16) int8}"},
+	{id: "foo", typ: "<type 1 (? <type -1>) <type -2>>", want: "func(int8) int16"},
+}
+
+func TestTypeParser(t *testing.T) {
+	for _, test := range typeParserTests {
+		var p parser
+		p.init("test.gox", strings.NewReader(test.typ), make(map[string]*types.Package))
+		p.pkgname = test.id
+		p.pkgpath = test.id
+		p.maybeCreatePackage()
+		typ := p.parseType(p.pkg)
+
+		if p.tok != scanner.EOF {
+			t.Errorf("expected full parse, stopped at %q", p.lit)
+		}
+
+		got := typ.String()
+		if got != test.want {
+			t.Errorf("got type %q, expected %q", got, test.want)
+		}
+
+		if test.underlying != "" {
+			underlying := typ.Underlying().String()
+			if underlying != test.underlying {
+				t.Errorf("got underlying type %q, expected %q", underlying, test.underlying)
+			}
+		}
+
+		if test.methods != "" {
+			nt := typ.(*types.Named)
+			var buf bytes.Buffer
+			for i := 0; i != nt.NumMethods(); i++ {
+				buf.WriteString(nt.Method(i).String())
+			}
+			methods := buf.String()
+			if methods != test.methods {
+				t.Errorf("got methods %q, expected %q", methods, test.methods)
+			}
+		}
+	}
+}
diff --git a/go/gccgoimporter/testdata/complexnums.go b/go/gccgoimporter/testdata/complexnums.go
new file mode 100644
index 0000000..a51b6b0
--- /dev/null
+++ b/go/gccgoimporter/testdata/complexnums.go
@@ -0,0 +1,6 @@
+package complexnums
+
+const NN = -1 - 1i
+const NP = -1 + 1i
+const PN = 1 - 1i
+const PP = 1 + 1i
diff --git a/go/gccgoimporter/testdata/complexnums.gox b/go/gccgoimporter/testdata/complexnums.gox
new file mode 100644
index 0000000..b66524f
--- /dev/null
+++ b/go/gccgoimporter/testdata/complexnums.gox
@@ -0,0 +1,8 @@
+v1;
+package complexnums;
+pkgpath complexnums;
+priority 1;
+const NN = -0.1E1-0.1E1i ;
+const NP = -0.1E1+0.1E1i ;
+const PN = 0.1E1-0.1E1i ;
+const PP = 0.1E1+0.1E1i ;
diff --git a/go/gccgoimporter/testdata/imports.go b/go/gccgoimporter/testdata/imports.go
new file mode 100644
index 0000000..7907316
--- /dev/null
+++ b/go/gccgoimporter/testdata/imports.go
@@ -0,0 +1,5 @@
+package imports
+
+import "fmt"
+
+var Hello = fmt.Sprintf("Hello, world")
diff --git a/go/gccgoimporter/testdata/imports.gox b/go/gccgoimporter/testdata/imports.gox
new file mode 100644
index 0000000..958a4f5
--- /dev/null
+++ b/go/gccgoimporter/testdata/imports.gox
@@ -0,0 +1,7 @@
+v1;
+package imports;
+pkgpath imports;
+priority 7;
+import fmt fmt "fmt";
+init imports imports..import 7 math math..import 1 runtime runtime..import 1 strconv strconv..import 2 io io..import 3 reflect reflect..import 3 syscall syscall..import 3 time time..import 4 os os..import 5 fmt fmt..import 6;
+var Hello <type -16>;
diff --git a/go/gccgoimporter/testdata/pointer.go b/go/gccgoimporter/testdata/pointer.go
new file mode 100644
index 0000000..4ebc671
--- /dev/null
+++ b/go/gccgoimporter/testdata/pointer.go
@@ -0,0 +1,3 @@
+package pointer
+
+type Int8Ptr *int8
diff --git a/go/gccgoimporter/testdata/pointer.gox b/go/gccgoimporter/testdata/pointer.gox
new file mode 100644
index 0000000..d96ebbd
--- /dev/null
+++ b/go/gccgoimporter/testdata/pointer.gox
@@ -0,0 +1,4 @@
+v1;
+package pointer;
+pkgpath pointer;
+type <type 1 "Int8Ptr" <type 2 *<type -1>>>;
diff --git a/go/gcimporter/exportdata.go b/go/gcimporter/exportdata.go
new file mode 100644
index 0000000..657742b
--- /dev/null
+++ b/go/gcimporter/exportdata.go
@@ -0,0 +1,108 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file implements FindExportData.
+
+package gcimporter
+
+import (
+	"bufio"
+	"errors"
+	"fmt"
+	"io"
+	"strconv"
+	"strings"
+)
+
+func readGopackHeader(r *bufio.Reader) (name string, size int, err error) {
+	// See $GOROOT/include/ar.h.
+	hdr := make([]byte, 16+12+6+6+8+10+2)
+	_, err = io.ReadFull(r, hdr)
+	if err != nil {
+		return
+	}
+	// leave for debugging
+	if false {
+		fmt.Printf("header: %s", hdr)
+	}
+	s := strings.TrimSpace(string(hdr[16+12+6+6+8:][:10]))
+	size, err = strconv.Atoi(s)
+	if err != nil || hdr[len(hdr)-2] != '`' || hdr[len(hdr)-1] != '\n' {
+		err = errors.New("invalid archive header")
+		return
+	}
+	name = strings.TrimSpace(string(hdr[:16]))
+	return
+}
+
+// FindExportData positions the reader r at the beginning of the
+// export data section of an underlying GC-created object/archive
+// file by reading from it. The reader must be positioned at the
+// start of the file before calling this function.
+//
+func FindExportData(r *bufio.Reader) (err error) {
+	// Read first line to make sure this is an object file.
+	line, err := r.ReadSlice('\n')
+	if err != nil {
+		return
+	}
+	if string(line) == "!<arch>\n" {
+		// Archive file. Scan to __.PKGDEF.
+		var name string
+		var size int
+		if name, size, err = readGopackHeader(r); err != nil {
+			return
+		}
+
+		// Optional leading __.GOSYMDEF or __.SYMDEF.
+		// Read and discard.
+		if name == "__.SYMDEF" || name == "__.GOSYMDEF" {
+			const block = 4096
+			tmp := make([]byte, block)
+			for size > 0 {
+				n := size
+				if n > block {
+					n = block
+				}
+				if _, err = io.ReadFull(r, tmp[:n]); err != nil {
+					return
+				}
+				size -= n
+			}
+
+			if name, size, err = readGopackHeader(r); err != nil {
+				return
+			}
+		}
+
+		// First real entry should be __.PKGDEF.
+		if name != "__.PKGDEF" {
+			err = errors.New("go archive is missing __.PKGDEF")
+			return
+		}
+
+		// Read first line of __.PKGDEF data, so that line
+		// is once again the first line of the input.
+		if line, err = r.ReadSlice('\n'); err != nil {
+			return
+		}
+	}
+
+	// Now at __.PKGDEF in archive or still at beginning of file.
+	// Either way, line should begin with "go object ".
+	if !strings.HasPrefix(string(line), "go object ") {
+		err = errors.New("not a go object file")
+		return
+	}
+
+	// Skip over object header to export data.
+	// Begins after first line with $$.
+	for line[0] != '$' {
+		if line, err = r.ReadSlice('\n'); err != nil {
+			return
+		}
+	}
+
+	return
+}
diff --git a/go/gcimporter/gcimporter.go b/go/gcimporter/gcimporter.go
new file mode 100644
index 0000000..031e870
--- /dev/null
+++ b/go/gcimporter/gcimporter.go
@@ -0,0 +1,995 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package gcimporter implements Import for gc-generated object files.
+// Importing this package installs Import as go/types.DefaultImport.
+package gcimporter // import "golang.org/x/tools/go/gcimporter"
+
+import (
+	"bufio"
+	"errors"
+	"fmt"
+	"go/build"
+	"go/token"
+	"io"
+	"os"
+	"path/filepath"
+	"sort"
+	"strconv"
+	"strings"
+	"text/scanner"
+
+	"golang.org/x/tools/go/exact"
+	"golang.org/x/tools/go/types"
+)
+
+// debugging/development support
+const debug = false
+
+func init() {
+	types.DefaultImport = Import
+}
+
+var pkgExts = [...]string{".a", ".5", ".6", ".7", ".8", ".9"}
+
+// FindPkg returns the filename and unique package id for an import
+// path based on package information provided by build.Import (using
+// the build.Default build.Context).
+// If no file was found, an empty filename is returned.
+//
+func FindPkg(path, srcDir string) (filename, id string) {
+	if len(path) == 0 {
+		return
+	}
+
+	id = path
+	var noext string
+	switch {
+	default:
+		// "x" -> "$GOPATH/pkg/$GOOS_$GOARCH/x.ext", "x"
+		// Don't require the source files to be present.
+		bp, _ := build.Import(path, srcDir, build.FindOnly|build.AllowBinary)
+		if bp.PkgObj == "" {
+			return
+		}
+		noext = strings.TrimSuffix(bp.PkgObj, ".a")
+
+	case build.IsLocalImport(path):
+		// "./x" -> "/this/directory/x.ext", "/this/directory/x"
+		noext = filepath.Join(srcDir, path)
+		id = noext
+
+	case filepath.IsAbs(path):
+		// for completeness only - go/build.Import
+		// does not support absolute imports
+		// "/x" -> "/x.ext", "/x"
+		noext = path
+	}
+
+	// try extensions
+	for _, ext := range pkgExts {
+		filename = noext + ext
+		if f, err := os.Stat(filename); err == nil && !f.IsDir() {
+			return
+		}
+	}
+
+	filename = "" // not found
+	return
+}
+
+// ImportData imports a package by reading the gc-generated export data,
+// adds the corresponding package object to the packages map indexed by id,
+// and returns the object.
+//
+// The packages map must contains all packages already imported. The data
+// reader position must be the beginning of the export data section. The
+// filename is only used in error messages.
+//
+// If packages[id] contains the completely imported package, that package
+// can be used directly, and there is no need to call this function (but
+// there is also no harm but for extra time used).
+//
+func ImportData(packages map[string]*types.Package, filename, id string, data io.Reader) (pkg *types.Package, err error) {
+	// support for parser error handling
+	defer func() {
+		switch r := recover().(type) {
+		case nil:
+			// nothing to do
+		case importError:
+			err = r
+		default:
+			panic(r) // internal error
+		}
+	}()
+
+	var p parser
+	p.init(filename, id, data, packages)
+	pkg = p.parseExport()
+
+	return
+}
+
+// Import imports a gc-generated package given its import path, adds the
+// corresponding package object to the packages map, and returns the object.
+// Local import paths are interpreted relative to the current working directory.
+// The packages map must contains all packages already imported.
+//
+func Import(packages map[string]*types.Package, path string) (pkg *types.Package, err error) {
+	if path == "unsafe" {
+		return types.Unsafe, nil
+	}
+
+	srcDir := "."
+	if build.IsLocalImport(path) {
+		srcDir, err = os.Getwd()
+		if err != nil {
+			return
+		}
+	}
+
+	filename, id := FindPkg(path, srcDir)
+	if filename == "" {
+		err = fmt.Errorf("can't find import: %s", id)
+		return
+	}
+
+	// no need to re-import if the package was imported completely before
+	if pkg = packages[id]; pkg != nil && pkg.Complete() {
+		return
+	}
+
+	// open file
+	f, err := os.Open(filename)
+	if err != nil {
+		return
+	}
+	defer func() {
+		f.Close()
+		if err != nil {
+			// add file name to error
+			err = fmt.Errorf("reading export data: %s: %v", filename, err)
+		}
+	}()
+
+	buf := bufio.NewReader(f)
+	if err = FindExportData(buf); err != nil {
+		return
+	}
+
+	pkg, err = ImportData(packages, filename, id, buf)
+
+	return
+}
+
+// ----------------------------------------------------------------------------
+// Parser
+
+// TODO(gri) Imported objects don't have position information.
+//           Ideally use the debug table line info; alternatively
+//           create some fake position (or the position of the
+//           import). That way error messages referring to imported
+//           objects can print meaningful information.
+
+// parser parses the exports inside a gc compiler-produced
+// object/archive file and populates its scope with the results.
+type parser struct {
+	scanner    scanner.Scanner
+	tok        rune                      // current token
+	lit        string                    // literal string; only valid for Ident, Int, String tokens
+	id         string                    // package id of imported package
+	sharedPkgs map[string]*types.Package // package id -> package object (across importer)
+	localPkgs  map[string]*types.Package // package id -> package object (just this package)
+}
+
+func (p *parser) init(filename, id string, src io.Reader, packages map[string]*types.Package) {
+	p.scanner.Init(src)
+	p.scanner.Error = func(_ *scanner.Scanner, msg string) { p.error(msg) }
+	p.scanner.Mode = scanner.ScanIdents | scanner.ScanInts | scanner.ScanChars | scanner.ScanStrings | scanner.ScanComments | scanner.SkipComments
+	p.scanner.Whitespace = 1<<'\t' | 1<<' '
+	p.scanner.Filename = filename // for good error messages
+	p.next()
+	p.id = id
+	p.sharedPkgs = packages
+	if debug {
+		// check consistency of packages map
+		for _, pkg := range packages {
+			if pkg.Name() == "" {
+				fmt.Printf("no package name for %s\n", pkg.Path())
+			}
+		}
+	}
+}
+
+func (p *parser) next() {
+	p.tok = p.scanner.Scan()
+	switch p.tok {
+	case scanner.Ident, scanner.Int, scanner.Char, scanner.String, '·':
+		p.lit = p.scanner.TokenText()
+	default:
+		p.lit = ""
+	}
+	if debug {
+		fmt.Printf("%s: %q -> %q\n", scanner.TokenString(p.tok), p.scanner.TokenText(), p.lit)
+	}
+}
+
+func declTypeName(pkg *types.Package, name string) *types.TypeName {
+	scope := pkg.Scope()
+	if obj := scope.Lookup(name); obj != nil {
+		return obj.(*types.TypeName)
+	}
+	obj := types.NewTypeName(token.NoPos, pkg, name, nil)
+	// a named type may be referred to before the underlying type
+	// is known - set it up
+	types.NewNamed(obj, nil, nil)
+	scope.Insert(obj)
+	return obj
+}
+
+// ----------------------------------------------------------------------------
+// Error handling
+
+// Internal errors are boxed as importErrors.
+type importError struct {
+	pos scanner.Position
+	err error
+}
+
+func (e importError) Error() string {
+	return fmt.Sprintf("import error %s (byte offset = %d): %s", e.pos, e.pos.Offset, e.err)
+}
+
+func (p *parser) error(err interface{}) {
+	if s, ok := err.(string); ok {
+		err = errors.New(s)
+	}
+	// panic with a runtime.Error if err is not an error
+	panic(importError{p.scanner.Pos(), err.(error)})
+}
+
+func (p *parser) errorf(format string, args ...interface{}) {
+	p.error(fmt.Sprintf(format, args...))
+}
+
+func (p *parser) expect(tok rune) string {
+	lit := p.lit
+	if p.tok != tok {
+		p.errorf("expected %s, got %s (%s)", scanner.TokenString(tok), scanner.TokenString(p.tok), lit)
+	}
+	p.next()
+	return lit
+}
+
+func (p *parser) expectSpecial(tok string) {
+	sep := 'x' // not white space
+	i := 0
+	for i < len(tok) && p.tok == rune(tok[i]) && sep > ' ' {
+		sep = p.scanner.Peek() // if sep <= ' ', there is white space before the next token
+		p.next()
+		i++
+	}
+	if i < len(tok) {
+		p.errorf("expected %q, got %q", tok, tok[0:i])
+	}
+}
+
+func (p *parser) expectKeyword(keyword string) {
+	lit := p.expect(scanner.Ident)
+	if lit != keyword {
+		p.errorf("expected keyword %s, got %q", keyword, lit)
+	}
+}
+
+// ----------------------------------------------------------------------------
+// Qualified and unqualified names
+
+// PackageId = string_lit .
+//
+func (p *parser) parsePackageId() string {
+	id, err := strconv.Unquote(p.expect(scanner.String))
+	if err != nil {
+		p.error(err)
+	}
+	// id == "" stands for the imported package id
+	// (only known at time of package installation)
+	if id == "" {
+		id = p.id
+	}
+	return id
+}
+
+// PackageName = ident .
+//
+func (p *parser) parsePackageName() string {
+	return p.expect(scanner.Ident)
+}
+
+// dotIdentifier = ( ident | '·' ) { ident | int | '·' } .
+func (p *parser) parseDotIdent() string {
+	ident := ""
+	if p.tok != scanner.Int {
+		sep := 'x' // not white space
+		for (p.tok == scanner.Ident || p.tok == scanner.Int || p.tok == '·') && sep > ' ' {
+			ident += p.lit
+			sep = p.scanner.Peek() // if sep <= ' ', there is white space before the next token
+			p.next()
+		}
+	}
+	if ident == "" {
+		p.expect(scanner.Ident) // use expect() for error handling
+	}
+	return ident
+}
+
+// QualifiedName = "@" PackageId "." ( "?" | dotIdentifier ) .
+//
+func (p *parser) parseQualifiedName() (id, name string) {
+	p.expect('@')
+	id = p.parsePackageId()
+	p.expect('.')
+	// Per rev f280b8a485fd (10/2/2013), qualified names may be used for anonymous fields.
+	if p.tok == '?' {
+		p.next()
+	} else {
+		name = p.parseDotIdent()
+	}
+	return
+}
+
+// getPkg returns the package for a given id. If the package is
+// not found but we have a package name, create the package and
+// add it to the p.localPkgs and p.sharedPkgs maps.
+//
+// id identifies a package, usually by a canonical package path like
+// "encoding/json" but possibly by a non-canonical import path like
+// "./json".
+//
+func (p *parser) getPkg(id, name string) *types.Package {
+	// package unsafe is not in the packages maps - handle explicitly
+	if id == "unsafe" {
+		return types.Unsafe
+	}
+
+	pkg := p.localPkgs[id]
+	if pkg == nil && name != "" {
+		// first import of id from this package
+		pkg = p.sharedPkgs[id]
+		if pkg == nil {
+			// first import of id by this importer
+			pkg = types.NewPackage(id, name)
+			p.sharedPkgs[id] = pkg
+		}
+
+		if p.localPkgs == nil {
+			p.localPkgs = make(map[string]*types.Package)
+		}
+		p.localPkgs[id] = pkg
+	}
+	return pkg
+}
+
+// parseExportedName is like parseQualifiedName, but
+// the package id is resolved to an imported *types.Package.
+//
+func (p *parser) parseExportedName() (pkg *types.Package, name string) {
+	id, name := p.parseQualifiedName()
+	pkg = p.getPkg(id, "")
+	if pkg == nil {
+		p.errorf("%s package not found", id)
+	}
+	return
+}
+
+// ----------------------------------------------------------------------------
+// Types
+
+// BasicType = identifier .
+//
+func (p *parser) parseBasicType() types.Type {
+	id := p.expect(scanner.Ident)
+	obj := types.Universe.Lookup(id)
+	if obj, ok := obj.(*types.TypeName); ok {
+		return obj.Type()
+	}
+	p.errorf("not a basic type: %s", id)
+	return nil
+}
+
+// ArrayType = "[" int_lit "]" Type .
+//
+func (p *parser) parseArrayType() types.Type {
+	// "[" already consumed and lookahead known not to be "]"
+	lit := p.expect(scanner.Int)
+	p.expect(']')
+	elem := p.parseType()
+	n, err := strconv.ParseInt(lit, 10, 64)
+	if err != nil {
+		p.error(err)
+	}
+	return types.NewArray(elem, n)
+}
+
+// MapType = "map" "[" Type "]" Type .
+//
+func (p *parser) parseMapType() types.Type {
+	p.expectKeyword("map")
+	p.expect('[')
+	key := p.parseType()
+	p.expect(']')
+	elem := p.parseType()
+	return types.NewMap(key, elem)
+}
+
+// Name = identifier | "?" | QualifiedName .
+//
+// If materializePkg is set, the returned package is guaranteed to be set.
+// For fully qualified names, the returned package may be a fake package
+// (without name, scope, and not in the p.imports map), created for the
+// sole purpose of providing a package path. Fake packages are created
+// when the package id is not found in the p.imports map; in that case
+// we cannot create a real package because we don't have a package name.
+// For non-qualified names, the returned package is the imported package.
+//
+func (p *parser) parseName(materializePkg bool) (pkg *types.Package, name string) {
+	switch p.tok {
+	case scanner.Ident:
+		pkg = p.sharedPkgs[p.id]
+		name = p.lit
+		p.next()
+	case '?':
+		// anonymous
+		pkg = p.sharedPkgs[p.id]
+		p.next()
+	case '@':
+		// exported name prefixed with package path
+		var id string
+		id, name = p.parseQualifiedName()
+		if materializePkg {
+			// we don't have a package name - if the package
+			// doesn't exist yet, create a fake package instead
+			pkg = p.getPkg(id, "")
+			if pkg == nil {
+				pkg = types.NewPackage(id, "")
+			}
+		}
+	default:
+		p.error("name expected")
+	}
+	return
+}
+
+func deref(typ types.Type) types.Type {
+	if p, _ := typ.(*types.Pointer); p != nil {
+		return p.Elem()
+	}
+	return typ
+}
+
+// Field = Name Type [ string_lit ] .
+//
+func (p *parser) parseField() (*types.Var, string) {
+	pkg, name := p.parseName(true)
+	typ := p.parseType()
+	anonymous := false
+	if name == "" {
+		// anonymous field - typ must be T or *T and T must be a type name
+		switch typ := deref(typ).(type) {
+		case *types.Basic: // basic types are named types
+			pkg = nil
+			name = typ.Name()
+		case *types.Named:
+			name = typ.Obj().Name()
+		default:
+			p.errorf("anonymous field expected")
+		}
+		anonymous = true
+	}
+	tag := ""
+	if p.tok == scanner.String {
+		s := p.expect(scanner.String)
+		var err error
+		tag, err = strconv.Unquote(s)
+		if err != nil {
+			p.errorf("invalid struct tag %s: %s", s, err)
+		}
+	}
+	return types.NewField(token.NoPos, pkg, name, typ, anonymous), tag
+}
+
+// StructType = "struct" "{" [ FieldList ] "}" .
+// FieldList  = Field { ";" Field } .
+//
+func (p *parser) parseStructType() types.Type {
+	var fields []*types.Var
+	var tags []string
+
+	p.expectKeyword("struct")
+	p.expect('{')
+	for i := 0; p.tok != '}' && p.tok != scanner.EOF; i++ {
+		if i > 0 {
+			p.expect(';')
+		}
+		fld, tag := p.parseField()
+		if tag != "" && tags == nil {
+			tags = make([]string, i)
+		}
+		if tags != nil {
+			tags = append(tags, tag)
+		}
+		fields = append(fields, fld)
+	}
+	p.expect('}')
+
+	return types.NewStruct(fields, tags)
+}
+
+// Parameter = ( identifier | "?" ) [ "..." ] Type [ string_lit ] .
+//
+func (p *parser) parseParameter() (par *types.Var, isVariadic bool) {
+	_, name := p.parseName(false)
+	// remove gc-specific parameter numbering
+	if i := strings.Index(name, "·"); i >= 0 {
+		name = name[:i]
+	}
+	if p.tok == '.' {
+		p.expectSpecial("...")
+		isVariadic = true
+	}
+	typ := p.parseType()
+	if isVariadic {
+		typ = types.NewSlice(typ)
+	}
+	// ignore argument tag (e.g. "noescape")
+	if p.tok == scanner.String {
+		p.next()
+	}
+	// TODO(gri) should we provide a package?
+	par = types.NewVar(token.NoPos, nil, name, typ)
+	return
+}
+
+// Parameters    = "(" [ ParameterList ] ")" .
+// ParameterList = { Parameter "," } Parameter .
+//
+func (p *parser) parseParameters() (list []*types.Var, isVariadic bool) {
+	p.expect('(')
+	for p.tok != ')' && p.tok != scanner.EOF {
+		if len(list) > 0 {
+			p.expect(',')
+		}
+		par, variadic := p.parseParameter()
+		list = append(list, par)
+		if variadic {
+			if isVariadic {
+				p.error("... not on final argument")
+			}
+			isVariadic = true
+		}
+	}
+	p.expect(')')
+
+	return
+}
+
+// Signature = Parameters [ Result ] .
+// Result    = Type | Parameters .
+//
+func (p *parser) parseSignature(recv *types.Var) *types.Signature {
+	params, isVariadic := p.parseParameters()
+
+	// optional result type
+	var results []*types.Var
+	if p.tok == '(' {
+		var variadic bool
+		results, variadic = p.parseParameters()
+		if variadic {
+			p.error("... not permitted on result type")
+		}
+	}
+
+	return types.NewSignature(recv, types.NewTuple(params...), types.NewTuple(results...), isVariadic)
+}
+
+// InterfaceType = "interface" "{" [ MethodList ] "}" .
+// MethodList    = Method { ";" Method } .
+// Method        = Name Signature .
+//
+// The methods of embedded interfaces are always "inlined"
+// by the compiler and thus embedded interfaces are never
+// visible in the export data.
+//
+func (p *parser) parseInterfaceType() types.Type {
+	var methods []*types.Func
+
+	p.expectKeyword("interface")
+	p.expect('{')
+	for i := 0; p.tok != '}' && p.tok != scanner.EOF; i++ {
+		if i > 0 {
+			p.expect(';')
+		}
+		pkg, name := p.parseName(true)
+		sig := p.parseSignature(nil)
+		methods = append(methods, types.NewFunc(token.NoPos, pkg, name, sig))
+	}
+	p.expect('}')
+
+	// Complete requires the type's embedded interfaces to be fully defined,
+	// but we do not define any
+	return types.NewInterface(methods, nil).Complete()
+}
+
+// ChanType = ( "chan" [ "<-" ] | "<-" "chan" ) Type .
+//
+func (p *parser) parseChanType() types.Type {
+	dir := types.SendRecv
+	if p.tok == scanner.Ident {
+		p.expectKeyword("chan")
+		if p.tok == '<' {
+			p.expectSpecial("<-")
+			dir = types.SendOnly
+		}
+	} else {
+		p.expectSpecial("<-")
+		p.expectKeyword("chan")
+		dir = types.RecvOnly
+	}
+	elem := p.parseType()
+	return types.NewChan(dir, elem)
+}
+
+// Type =
+//	BasicType | TypeName | ArrayType | SliceType | StructType |
+//      PointerType | FuncType | InterfaceType | MapType | ChanType |
+//      "(" Type ")" .
+//
+// BasicType   = ident .
+// TypeName    = ExportedName .
+// SliceType   = "[" "]" Type .
+// PointerType = "*" Type .
+// FuncType    = "func" Signature .
+//
+func (p *parser) parseType() types.Type {
+	switch p.tok {
+	case scanner.Ident:
+		switch p.lit {
+		default:
+			return p.parseBasicType()
+		case "struct":
+			return p.parseStructType()
+		case "func":
+			// FuncType
+			p.next()
+			return p.parseSignature(nil)
+		case "interface":
+			return p.parseInterfaceType()
+		case "map":
+			return p.parseMapType()
+		case "chan":
+			return p.parseChanType()
+		}
+	case '@':
+		// TypeName
+		pkg, name := p.parseExportedName()
+		return declTypeName(pkg, name).Type()
+	case '[':
+		p.next() // look ahead
+		if p.tok == ']' {
+			// SliceType
+			p.next()
+			return types.NewSlice(p.parseType())
+		}
+		return p.parseArrayType()
+	case '*':
+		// PointerType
+		p.next()
+		return types.NewPointer(p.parseType())
+	case '<':
+		return p.parseChanType()
+	case '(':
+		// "(" Type ")"
+		p.next()
+		typ := p.parseType()
+		p.expect(')')
+		return typ
+	}
+	p.errorf("expected type, got %s (%q)", scanner.TokenString(p.tok), p.lit)
+	return nil
+}
+
+// ----------------------------------------------------------------------------
+// Declarations
+
+// ImportDecl = "import" PackageName PackageId .
+//
+func (p *parser) parseImportDecl() {
+	p.expectKeyword("import")
+	name := p.parsePackageName()
+	p.getPkg(p.parsePackageId(), name)
+}
+
+// int_lit = [ "+" | "-" ] { "0" ... "9" } .
+//
+func (p *parser) parseInt() string {
+	s := ""
+	switch p.tok {
+	case '-':
+		s = "-"
+		p.next()
+	case '+':
+		p.next()
+	}
+	return s + p.expect(scanner.Int)
+}
+
+// number = int_lit [ "p" int_lit ] .
+//
+func (p *parser) parseNumber() (typ *types.Basic, val exact.Value) {
+	// mantissa
+	mant := exact.MakeFromLiteral(p.parseInt(), token.INT)
+	if mant == nil {
+		panic("invalid mantissa")
+	}
+
+	if p.lit == "p" {
+		// exponent (base 2)
+		p.next()
+		exp, err := strconv.ParseInt(p.parseInt(), 10, 0)
+		if err != nil {
+			p.error(err)
+		}
+		if exp < 0 {
+			denom := exact.MakeInt64(1)
+			denom = exact.Shift(denom, token.SHL, uint(-exp))
+			typ = types.Typ[types.UntypedFloat]
+			val = exact.BinaryOp(mant, token.QUO, denom)
+			return
+		}
+		if exp > 0 {
+			mant = exact.Shift(mant, token.SHL, uint(exp))
+		}
+		typ = types.Typ[types.UntypedFloat]
+		val = mant
+		return
+	}
+
+	typ = types.Typ[types.UntypedInt]
+	val = mant
+	return
+}
+
+// ConstDecl   = "const" ExportedName [ Type ] "=" Literal .
+// Literal     = bool_lit | int_lit | float_lit | complex_lit | rune_lit | string_lit .
+// bool_lit    = "true" | "false" .
+// complex_lit = "(" float_lit "+" float_lit "i" ")" .
+// rune_lit    = "(" int_lit "+" int_lit ")" .
+// string_lit  = `"` { unicode_char } `"` .
+//
+func (p *parser) parseConstDecl() {
+	p.expectKeyword("const")
+	pkg, name := p.parseExportedName()
+
+	var typ0 types.Type
+	if p.tok != '=' {
+		typ0 = p.parseType()
+	}
+
+	p.expect('=')
+	var typ types.Type
+	var val exact.Value
+	switch p.tok {
+	case scanner.Ident:
+		// bool_lit
+		if p.lit != "true" && p.lit != "false" {
+			p.error("expected true or false")
+		}
+		typ = types.Typ[types.UntypedBool]
+		val = exact.MakeBool(p.lit == "true")
+		p.next()
+
+	case '-', scanner.Int:
+		// int_lit
+		typ, val = p.parseNumber()
+
+	case '(':
+		// complex_lit or rune_lit
+		p.next()
+		if p.tok == scanner.Char {
+			p.next()
+			p.expect('+')
+			typ = types.Typ[types.UntypedRune]
+			_, val = p.parseNumber()
+			p.expect(')')
+			break
+		}
+		_, re := p.parseNumber()
+		p.expect('+')
+		_, im := p.parseNumber()
+		p.expectKeyword("i")
+		p.expect(')')
+		typ = types.Typ[types.UntypedComplex]
+		val = exact.BinaryOp(re, token.ADD, exact.MakeImag(im))
+
+	case scanner.Char:
+		// rune_lit
+		typ = types.Typ[types.UntypedRune]
+		val = exact.MakeFromLiteral(p.lit, token.CHAR)
+		p.next()
+
+	case scanner.String:
+		// string_lit
+		typ = types.Typ[types.UntypedString]
+		val = exact.MakeFromLiteral(p.lit, token.STRING)
+		p.next()
+
+	default:
+		p.errorf("expected literal got %s", scanner.TokenString(p.tok))
+	}
+
+	if typ0 == nil {
+		typ0 = typ
+	}
+
+	pkg.Scope().Insert(types.NewConst(token.NoPos, pkg, name, typ0, val))
+}
+
+// TypeDecl = "type" ExportedName Type .
+//
+func (p *parser) parseTypeDecl() {
+	p.expectKeyword("type")
+	pkg, name := p.parseExportedName()
+	obj := declTypeName(pkg, name)
+
+	// The type object may have been imported before and thus already
+	// have a type associated with it. We still need to parse the type
+	// structure, but throw it away if the object already has a type.
+	// This ensures that all imports refer to the same type object for
+	// a given type declaration.
+	typ := p.parseType()
+
+	if name := obj.Type().(*types.Named); name.Underlying() == nil {
+		name.SetUnderlying(typ)
+	}
+}
+
+// VarDecl = "var" ExportedName Type .
+//
+func (p *parser) parseVarDecl() {
+	p.expectKeyword("var")
+	pkg, name := p.parseExportedName()
+	typ := p.parseType()
+	pkg.Scope().Insert(types.NewVar(token.NoPos, pkg, name, typ))
+}
+
+// Func = Signature [ Body ] .
+// Body = "{" ... "}" .
+//
+func (p *parser) parseFunc(recv *types.Var) *types.Signature {
+	sig := p.parseSignature(recv)
+	if p.tok == '{' {
+		p.next()
+		for i := 1; i > 0; p.next() {
+			switch p.tok {
+			case '{':
+				i++
+			case '}':
+				i--
+			}
+		}
+	}
+	return sig
+}
+
+// MethodDecl = "func" Receiver Name Func .
+// Receiver   = "(" ( identifier | "?" ) [ "*" ] ExportedName ")" .
+//
+func (p *parser) parseMethodDecl() {
+	// "func" already consumed
+	p.expect('(')
+	recv, _ := p.parseParameter() // receiver
+	p.expect(')')
+
+	// determine receiver base type object
+	base := deref(recv.Type()).(*types.Named)
+
+	// parse method name, signature, and possibly inlined body
+	_, name := p.parseName(true)
+	sig := p.parseFunc(recv)
+
+	// methods always belong to the same package as the base type object
+	pkg := base.Obj().Pkg()
+
+	// add method to type unless type was imported before
+	// and method exists already
+	// TODO(gri) This leads to a quadratic algorithm - ok for now because method counts are small.
+	base.AddMethod(types.NewFunc(token.NoPos, pkg, name, sig))
+}
+
+// FuncDecl = "func" ExportedName Func .
+//
+func (p *parser) parseFuncDecl() {
+	// "func" already consumed
+	pkg, name := p.parseExportedName()
+	typ := p.parseFunc(nil)
+	pkg.Scope().Insert(types.NewFunc(token.NoPos, pkg, name, typ))
+}
+
+// Decl = [ ImportDecl | ConstDecl | TypeDecl | VarDecl | FuncDecl | MethodDecl ] "\n" .
+//
+func (p *parser) parseDecl() {
+	if p.tok == scanner.Ident {
+		switch p.lit {
+		case "import":
+			p.parseImportDecl()
+		case "const":
+			p.parseConstDecl()
+		case "type":
+			p.parseTypeDecl()
+		case "var":
+			p.parseVarDecl()
+		case "func":
+			p.next() // look ahead
+			if p.tok == '(' {
+				p.parseMethodDecl()
+			} else {
+				p.parseFuncDecl()
+			}
+		}
+	}
+	p.expect('\n')
+}
+
+// ----------------------------------------------------------------------------
+// Export
+
+// Export        = "PackageClause { Decl } "$$" .
+// PackageClause = "package" PackageName [ "safe" ] "\n" .
+//
+func (p *parser) parseExport() *types.Package {
+	p.expectKeyword("package")
+	name := p.parsePackageName()
+	if p.tok == scanner.Ident && p.lit == "safe" {
+		// package was compiled with -u option - ignore
+		p.next()
+	}
+	p.expect('\n')
+
+	pkg := p.getPkg(p.id, name)
+
+	for p.tok != '$' && p.tok != scanner.EOF {
+		p.parseDecl()
+	}
+
+	if ch := p.scanner.Peek(); p.tok != '$' || ch != '$' {
+		// don't call next()/expect() since reading past the
+		// export data may cause scanner errors (e.g. NUL chars)
+		p.errorf("expected '$$', got %s %c", scanner.TokenString(p.tok), ch)
+	}
+
+	if n := p.scanner.ErrorCount; n != 0 {
+		p.errorf("expected no scanner errors, got %d", n)
+	}
+
+	// Record all referenced packages as imports.
+	var imports []*types.Package
+	for id, pkg2 := range p.localPkgs {
+		if id == p.id {
+			continue // avoid self-edge
+		}
+		imports = append(imports, pkg2)
+	}
+	sort.Sort(byPath(imports))
+	pkg.SetImports(imports)
+
+	// package was imported completely and without errors
+	pkg.MarkComplete()
+
+	return pkg
+}
+
+type byPath []*types.Package
+
+func (a byPath) Len() int           { return len(a) }
+func (a byPath) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
+func (a byPath) Less(i, j int) bool { return a[i].Path() < a[j].Path() }
diff --git a/go/gcimporter/gcimporter_test.go b/go/gcimporter/gcimporter_test.go
new file mode 100644
index 0000000..73a4747
--- /dev/null
+++ b/go/gcimporter/gcimporter_test.go
@@ -0,0 +1,242 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package gcimporter
+
+import (
+	"fmt"
+	"go/build"
+	"io/ioutil"
+	"os"
+	"os/exec"
+	"path/filepath"
+	"runtime"
+	"strings"
+	"testing"
+	"time"
+
+	"golang.org/x/tools/go/types"
+)
+
+// skipSpecialPlatforms causes the test to be skipped for platforms where
+// builders (build.golang.org) don't have access to compiled packages for
+// import.
+func skipSpecialPlatforms(t *testing.T) {
+	switch platform := runtime.GOOS + "-" + runtime.GOARCH; platform {
+	case "nacl-amd64p32",
+		"nacl-386",
+		"nacl-arm",
+		"darwin-arm",
+		"darwin-arm64":
+		t.Skipf("no compiled packages available for import on %s", platform)
+	}
+}
+
+var gcPath string // Go compiler path
+
+func init() {
+	if char, err := build.ArchChar(runtime.GOARCH); err == nil {
+		gcPath = filepath.Join(build.ToolDir, char+"g")
+		return
+	}
+	gcPath = "unknown-GOARCH-compiler"
+}
+
+func compile(t *testing.T, dirname, filename string) string {
+	cmd := exec.Command(gcPath, filename)
+	cmd.Dir = dirname
+	out, err := cmd.CombinedOutput()
+	if err != nil {
+		t.Logf("%s", out)
+		t.Fatalf("%s %s failed: %s", gcPath, filename, err)
+	}
+	archCh, _ := build.ArchChar(runtime.GOARCH)
+	// filename should end with ".go"
+	return filepath.Join(dirname, filename[:len(filename)-2]+archCh)
+}
+
+// Use the same global imports map for all tests. The effect is
+// as if all tested packages were imported into a single package.
+var imports = make(map[string]*types.Package)
+
+func testPath(t *testing.T, path string) *types.Package {
+	t0 := time.Now()
+	pkg, err := Import(imports, path)
+	if err != nil {
+		t.Errorf("testPath(%s): %s", path, err)
+		return nil
+	}
+	t.Logf("testPath(%s): %v", path, time.Since(t0))
+	return pkg
+}
+
+const maxTime = 30 * time.Second
+
+func testDir(t *testing.T, dir string, endTime time.Time) (nimports int) {
+	dirname := filepath.Join(runtime.GOROOT(), "pkg", runtime.GOOS+"_"+runtime.GOARCH, dir)
+	list, err := ioutil.ReadDir(dirname)
+	if err != nil {
+		t.Fatalf("testDir(%s): %s", dirname, err)
+	}
+	for _, f := range list {
+		if time.Now().After(endTime) {
+			t.Log("testing time used up")
+			return
+		}
+		switch {
+		case !f.IsDir():
+			// try extensions
+			for _, ext := range pkgExts {
+				if strings.HasSuffix(f.Name(), ext) {
+					name := f.Name()[0 : len(f.Name())-len(ext)] // remove extension
+					if testPath(t, filepath.Join(dir, name)) != nil {
+						nimports++
+					}
+				}
+			}
+		case f.IsDir():
+			nimports += testDir(t, filepath.Join(dir, f.Name()), endTime)
+		}
+	}
+	return
+}
+
+func TestImport(t *testing.T) {
+	// This package only handles gc export data.
+	if runtime.Compiler != "gc" {
+		t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler)
+		return
+	}
+
+	// On cross-compile builds, the path will not exist.
+	// Need to use GOHOSTOS, which is not available.
+	if _, err := os.Stat(gcPath); err != nil {
+		t.Skipf("skipping test: %v", err)
+	}
+
+	if outFn := compile(t, "testdata", "exports.go"); outFn != "" {
+		defer os.Remove(outFn)
+	}
+
+	nimports := 0
+	if pkg := testPath(t, "./testdata/exports"); pkg != nil {
+		nimports++
+		// The package's Imports should include all the types
+		// referenced by the exportdata, which may be more than
+		// the import statements in the package's source, but
+		// fewer than the transitive closure of dependencies.
+		want := `[package ast ("go/ast") package token ("go/token") package runtime ("runtime")]`
+		got := fmt.Sprint(pkg.Imports())
+		if got != want {
+			t.Errorf(`Package("exports").Imports() = %s, want %s`, got, want)
+		}
+	}
+	nimports += testDir(t, "", time.Now().Add(maxTime)) // installed packages
+	t.Logf("tested %d imports", nimports)
+}
+
+var importedObjectTests = []struct {
+	name string
+	want string
+}{
+	{"unsafe.Pointer", "type Pointer unsafe.Pointer"},
+	{"math.Pi", "const Pi untyped float"},
+	{"io.Reader", "type Reader interface{Read(p []byte) (n int, err error)}"},
+	{"io.ReadWriter", "type ReadWriter interface{Read(p []byte) (n int, err error); Write(p []byte) (n int, err error)}"},
+	{"math.Sin", "func Sin(x float64) float64"},
+	// TODO(gri) add more tests
+}
+
+func TestImportedTypes(t *testing.T) {
+	skipSpecialPlatforms(t)
+
+	// This package only handles gc export data.
+	if runtime.Compiler != "gc" {
+		t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler)
+		return
+	}
+
+	for _, test := range importedObjectTests {
+		s := strings.Split(test.name, ".")
+		if len(s) != 2 {
+			t.Fatal("inconsistent test data")
+		}
+		importPath := s[0]
+		objName := s[1]
+
+		pkg, err := Import(imports, importPath)
+		if err != nil {
+			t.Error(err)
+			continue
+		}
+
+		obj := pkg.Scope().Lookup(objName)
+		if obj == nil {
+			t.Errorf("%s: object not found", test.name)
+			continue
+		}
+
+		got := types.ObjectString(obj, types.RelativeTo(pkg))
+		if got != test.want {
+			t.Errorf("%s: got %q; want %q", test.name, got, test.want)
+		}
+	}
+}
+
+func TestIssue5815(t *testing.T) {
+	skipSpecialPlatforms(t)
+
+	// This package only handles gc export data.
+	if runtime.Compiler != "gc" {
+		t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler)
+		return
+	}
+
+	pkg, err := Import(make(map[string]*types.Package), "strings")
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	scope := pkg.Scope()
+	for _, name := range scope.Names() {
+		obj := scope.Lookup(name)
+		if obj.Pkg() == nil {
+			t.Errorf("no pkg for %s", obj)
+		}
+		if tname, _ := obj.(*types.TypeName); tname != nil {
+			named := tname.Type().(*types.Named)
+			for i := 0; i < named.NumMethods(); i++ {
+				m := named.Method(i)
+				if m.Pkg() == nil {
+					t.Errorf("no pkg for %s", m)
+				}
+			}
+		}
+	}
+}
+
+// Smoke test to ensure that imported methods get the correct package.
+func TestCorrectMethodPackage(t *testing.T) {
+	skipSpecialPlatforms(t)
+
+	// This package only handles gc export data.
+	if runtime.Compiler != "gc" {
+		t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler)
+		return
+	}
+
+	imports := make(map[string]*types.Package)
+	_, err := Import(imports, "net/http")
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	mutex := imports["sync"].Scope().Lookup("Mutex").(*types.TypeName).Type()
+	mset := types.NewMethodSet(types.NewPointer(mutex)) // methods of *sync.Mutex
+	sel := mset.Lookup(nil, "Lock")
+	lock := sel.Obj().(*types.Func)
+	if got, want := lock.Pkg().Path(), "sync"; got != want {
+		t.Errorf("got package path %q; want %q", got, want)
+	}
+}
diff --git a/go/gcimporter/testdata/exports.go b/go/gcimporter/testdata/exports.go
new file mode 100644
index 0000000..8ee28b0
--- /dev/null
+++ b/go/gcimporter/testdata/exports.go
@@ -0,0 +1,89 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file is used to generate an object file which
+// serves as test file for gcimporter_test.go.
+
+package exports
+
+import (
+	"go/ast"
+)
+
+// Issue 3682: Correctly read dotted identifiers from export data.
+const init1 = 0
+
+func init() {}
+
+const (
+	C0 int = 0
+	C1     = 3.14159265
+	C2     = 2.718281828i
+	C3     = -123.456e-789
+	C4     = +123.456E+789
+	C5     = 1234i
+	C6     = "foo\n"
+	C7     = `bar\n`
+)
+
+type (
+	T1  int
+	T2  [10]int
+	T3  []int
+	T4  *int
+	T5  chan int
+	T6a chan<- int
+	T6b chan (<-chan int)
+	T6c chan<- (chan int)
+	T7  <-chan *ast.File
+	T8  struct{}
+	T9  struct {
+		a    int
+		b, c float32
+		d    []string `go:"tag"`
+	}
+	T10 struct {
+		T8
+		T9
+		_ *T10
+	}
+	T11 map[int]string
+	T12 interface{}
+	T13 interface {
+		m1()
+		m2(int) float32
+	}
+	T14 interface {
+		T12
+		T13
+		m3(x ...struct{}) []T9
+	}
+	T15 func()
+	T16 func(int)
+	T17 func(x int)
+	T18 func() float32
+	T19 func() (x float32)
+	T20 func(...interface{})
+	T21 struct{ next *T21 }
+	T22 struct{ link *T23 }
+	T23 struct{ link *T22 }
+	T24 *T24
+	T25 *T26
+	T26 *T27
+	T27 *T25
+	T28 func(T28) T28
+)
+
+var (
+	V0 int
+	V1 = -991.0
+)
+
+func F1()         {}
+func F2(x int)    {}
+func F3() int     { return 0 }
+func F4() float32 { return 0 }
+func F5(a, b, c int, u, v, w struct{ x, y T1 }, more ...interface{}) (p, q, r chan<- T10)
+
+func (p *T1) M1()
diff --git a/go/importer/export.go b/go/importer/export.go
new file mode 100644
index 0000000..5930eaf
--- /dev/null
+++ b/go/importer/export.go
@@ -0,0 +1,462 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package importer
+
+import (
+	"bytes"
+	"encoding/binary"
+	"fmt"
+	"go/ast"
+	"strings"
+
+	"golang.org/x/tools/go/exact"
+	"golang.org/x/tools/go/types"
+)
+
+// debugging support
+const (
+	debug = false // emit debugging data
+	trace = false // print emitted data
+)
+
+// format returns a byte indicating the low-level encoding/decoding format
+// (debug vs product).
+func format() byte {
+	if debug {
+		return 'd'
+	}
+	return 'p'
+}
+
+// ExportData serializes the interface (exported package objects)
+// of package pkg and returns the corresponding data. The export
+// format is described elsewhere (TODO).
+func ExportData(pkg *types.Package) []byte {
+	p := exporter{
+		data:     append([]byte(magic), format()),
+		pkgIndex: make(map[*types.Package]int),
+		typIndex: make(map[types.Type]int),
+	}
+
+	// populate typIndex with predeclared types
+	for _, t := range predeclared {
+		p.typIndex[t] = len(p.typIndex)
+	}
+
+	if trace {
+		p.tracef("export %s\n", pkg.Name())
+		defer p.tracef("\n")
+	}
+
+	p.string(version)
+
+	p.pkg(pkg)
+
+	// collect exported objects from package scope
+	var list []types.Object
+	scope := pkg.Scope()
+	for _, name := range scope.Names() {
+		if exported(name) {
+			list = append(list, scope.Lookup(name))
+		}
+	}
+
+	// write objects
+	p.int(len(list))
+	for _, obj := range list {
+		p.obj(obj)
+	}
+
+	return p.data
+}
+
+type exporter struct {
+	data     []byte
+	pkgIndex map[*types.Package]int
+	typIndex map[types.Type]int
+
+	// tracing support
+	indent string
+}
+
+func (p *exporter) pkg(pkg *types.Package) {
+	if trace {
+		p.tracef("package { ")
+		defer p.tracef("} ")
+	}
+
+	if pkg == nil {
+		panic("unexpected nil pkg")
+	}
+
+	// if the package was seen before, write its index (>= 0)
+	if i, ok := p.pkgIndex[pkg]; ok {
+		p.int(i)
+		return
+	}
+	p.pkgIndex[pkg] = len(p.pkgIndex)
+
+	// otherwise, write the package tag (< 0) and package data
+	p.int(packageTag)
+	p.string(pkg.Name())
+	p.string(pkg.Path())
+}
+
+func (p *exporter) obj(obj types.Object) {
+	if trace {
+		p.tracef("object %s {\n", obj.Name())
+		defer p.tracef("}\n")
+	}
+
+	switch obj := obj.(type) {
+	case *types.Const:
+		p.int(constTag)
+		p.string(obj.Name())
+		p.typ(obj.Type())
+		p.value(obj.Val())
+	case *types.TypeName:
+		p.int(typeTag)
+		// name is written by corresponding named type
+		p.typ(obj.Type().(*types.Named))
+	case *types.Var:
+		p.int(varTag)
+		p.string(obj.Name())
+		p.typ(obj.Type())
+	case *types.Func:
+		p.int(funcTag)
+		p.string(obj.Name())
+		p.typ(obj.Type())
+	default:
+		panic(fmt.Sprintf("unexpected object type %T", obj))
+	}
+}
+
+func (p *exporter) value(x exact.Value) {
+	if trace {
+		p.tracef("value { ")
+		defer p.tracef("} ")
+	}
+
+	switch kind := x.Kind(); kind {
+	case exact.Bool:
+		tag := falseTag
+		if exact.BoolVal(x) {
+			tag = trueTag
+		}
+		p.int(tag)
+	case exact.Int:
+		if i, ok := exact.Int64Val(x); ok {
+			p.int(int64Tag)
+			p.int64(i)
+			return
+		}
+		p.int(floatTag)
+		p.float(x)
+	case exact.Float:
+		p.int(fractionTag)
+		p.fraction(x)
+	case exact.Complex:
+		p.int(complexTag)
+		p.fraction(exact.Real(x))
+		p.fraction(exact.Imag(x))
+	case exact.String:
+		p.int(stringTag)
+		p.string(exact.StringVal(x))
+	default:
+		panic(fmt.Sprintf("unexpected value kind %d", kind))
+	}
+}
+
+func (p *exporter) float(x exact.Value) {
+	sign := exact.Sign(x)
+	p.int(sign)
+	if sign == 0 {
+		return
+	}
+
+	p.ufloat(x)
+}
+
+func (p *exporter) fraction(x exact.Value) {
+	sign := exact.Sign(x)
+	p.int(sign)
+	if sign == 0 {
+		return
+	}
+
+	p.ufloat(exact.Num(x))
+	p.ufloat(exact.Denom(x))
+}
+
+// ufloat writes abs(x) in form of a binary exponent
+// followed by its mantissa bytes; x must be != 0.
+func (p *exporter) ufloat(x exact.Value) {
+	mant := exact.Bytes(x)
+	exp8 := -1
+	for i, b := range mant {
+		if b != 0 {
+			exp8 = i
+			break
+		}
+	}
+	if exp8 < 0 {
+		panic(fmt.Sprintf("%s has no mantissa", x))
+	}
+	p.int(exp8 * 8)
+	p.bytes(mant[exp8:])
+}
+
+func (p *exporter) typ(typ types.Type) {
+	if trace {
+		p.tracef("type {\n")
+		defer p.tracef("}\n")
+	}
+
+	// if the type was seen before, write its index (>= 0)
+	if i, ok := p.typIndex[typ]; ok {
+		p.int(i)
+		return
+	}
+	p.typIndex[typ] = len(p.typIndex)
+
+	// otherwise, write the type tag (< 0) and type data
+	switch t := typ.(type) {
+	case *types.Array:
+		p.int(arrayTag)
+		p.int64(t.Len())
+		p.typ(t.Elem())
+
+	case *types.Slice:
+		p.int(sliceTag)
+		p.typ(t.Elem())
+
+	case *types.Struct:
+		p.int(structTag)
+		n := t.NumFields()
+		p.int(n)
+		for i := 0; i < n; i++ {
+			p.field(t.Field(i))
+			p.string(t.Tag(i))
+		}
+
+	case *types.Pointer:
+		p.int(pointerTag)
+		p.typ(t.Elem())
+
+	case *types.Signature:
+		p.int(signatureTag)
+		p.signature(t)
+
+	case *types.Interface:
+		p.int(interfaceTag)
+
+		// write embedded interfaces
+		m := t.NumEmbeddeds()
+		p.int(m)
+		for i := 0; i < m; i++ {
+			p.typ(t.Embedded(i))
+		}
+
+		// write methods
+		n := t.NumExplicitMethods()
+		p.int(n)
+		for i := 0; i < n; i++ {
+			m := t.ExplicitMethod(i)
+			p.qualifiedName(m.Pkg(), m.Name())
+			p.typ(m.Type())
+		}
+
+	case *types.Map:
+		p.int(mapTag)
+		p.typ(t.Key())
+		p.typ(t.Elem())
+
+	case *types.Chan:
+		p.int(chanTag)
+		p.int(int(t.Dir()))
+		p.typ(t.Elem())
+
+	case *types.Named:
+		p.int(namedTag)
+
+		// write type object
+		obj := t.Obj()
+		p.string(obj.Name())
+		p.pkg(obj.Pkg())
+
+		// write underlying type
+		p.typ(t.Underlying())
+
+		// write associated methods
+		n := t.NumMethods()
+		p.int(n)
+		for i := 0; i < n; i++ {
+			m := t.Method(i)
+			p.string(m.Name())
+			p.typ(m.Type())
+		}
+
+	default:
+		panic("unreachable")
+	}
+}
+
+func (p *exporter) field(f *types.Var) {
+	// anonymous fields have "" name
+	name := ""
+	if !f.Anonymous() {
+		name = f.Name()
+	}
+
+	// qualifiedName will always emit the field package for
+	// anonymous fields because "" is not an exported name.
+	p.qualifiedName(f.Pkg(), name)
+	p.typ(f.Type())
+}
+
+func (p *exporter) qualifiedName(pkg *types.Package, name string) {
+	p.string(name)
+	// exported names don't need package
+	if !exported(name) {
+		if pkg == nil {
+			panic(fmt.Sprintf("nil package for unexported qualified name %s", name))
+		}
+		p.pkg(pkg)
+	}
+}
+
+func (p *exporter) signature(sig *types.Signature) {
+	// We need the receiver information (T vs *T)
+	// for methods associated with named types.
+	// We do not record interface receiver types in the
+	// export data because 1) the importer can derive them
+	// from the interface type and 2) they create cycles
+	// in the type graph.
+	if recv := sig.Recv(); recv != nil {
+		if _, ok := recv.Type().Underlying().(*types.Interface); !ok {
+			// 1-element tuple
+			p.int(1)
+			p.param(recv)
+		} else {
+			// 0-element tuple
+			p.int(0)
+		}
+	} else {
+		// 0-element tuple
+		p.int(0)
+	}
+	p.tuple(sig.Params())
+	p.tuple(sig.Results())
+	if sig.Variadic() {
+		p.int(1)
+	} else {
+		p.int(0)
+	}
+}
+
+func (p *exporter) param(v *types.Var) {
+	p.string(v.Name())
+	p.typ(v.Type())
+}
+
+func (p *exporter) tuple(t *types.Tuple) {
+	n := t.Len()
+	p.int(n)
+	for i := 0; i < n; i++ {
+		p.param(t.At(i))
+	}
+}
+
+// ----------------------------------------------------------------------------
+// encoders
+
+func (p *exporter) string(s string) {
+	p.bytes([]byte(s)) // (could be inlined if extra allocation matters)
+}
+
+func (p *exporter) int(x int) {
+	p.int64(int64(x))
+}
+
+func (p *exporter) int64(x int64) {
+	if debug {
+		p.marker('i')
+	}
+
+	if trace {
+		p.tracef("%d ", x)
+	}
+
+	p.rawInt64(x)
+}
+
+func (p *exporter) bytes(b []byte) {
+	if debug {
+		p.marker('b')
+	}
+
+	if trace {
+		p.tracef("%q ", b)
+	}
+
+	p.rawInt64(int64(len(b)))
+	if len(b) > 0 {
+		p.data = append(p.data, b...)
+	}
+}
+
+// marker emits a marker byte and position information which makes
+// it easy for a reader to detect if it is "out of sync". Used for
+// debug format only.
+func (p *exporter) marker(m byte) {
+	if debug {
+		p.data = append(p.data, m)
+		p.rawInt64(int64(len(p.data)))
+	}
+}
+
+// rawInt64 should only be used by low-level encoders
+func (p *exporter) rawInt64(x int64) {
+	var tmp [binary.MaxVarintLen64]byte
+	n := binary.PutVarint(tmp[:], x)
+	p.data = append(p.data, tmp[:n]...)
+}
+
+// utility functions
+
+func (p *exporter) tracef(format string, args ...interface{}) {
+	// rewrite format string to take care of indentation
+	const indent = ".  "
+	if strings.IndexAny(format, "{}\n") >= 0 {
+		var buf bytes.Buffer
+		for i := 0; i < len(format); i++ {
+			// no need to deal with runes
+			ch := format[i]
+			switch ch {
+			case '{':
+				p.indent += indent
+			case '}':
+				p.indent = p.indent[:len(p.indent)-len(indent)]
+				if i+1 < len(format) && format[i+1] == '\n' {
+					buf.WriteByte('\n')
+					buf.WriteString(p.indent)
+					buf.WriteString("} ")
+					i++
+					continue
+				}
+			}
+			buf.WriteByte(ch)
+			if ch == '\n' {
+				buf.WriteString(p.indent)
+			}
+		}
+		format = buf.String()
+	}
+	fmt.Printf(format, args...)
+}
+
+func exported(name string) bool {
+	return ast.IsExported(name)
+}
diff --git a/go/importer/import.go b/go/importer/import.go
new file mode 100644
index 0000000..3fa37a5
--- /dev/null
+++ b/go/importer/import.go
@@ -0,0 +1,456 @@
+// Copyright 2013 The Go 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 implementation is loosely based on the algorithm described
+// in: "On the linearization of graphs and writing symbol files",
+// by R. Griesemer, Technical Report 156, ETH Zürich, 1991.
+
+// package importer implements an exporter and importer for Go export data.
+package importer // import "golang.org/x/tools/go/importer"
+
+import (
+	"encoding/binary"
+	"fmt"
+	"go/token"
+
+	"golang.org/x/tools/go/exact"
+	"golang.org/x/tools/go/types"
+)
+
+// ImportData imports a package from the serialized package data
+// and returns the number of bytes consumed and a reference to the package.
+// If data is obviously malformed, an error is returned but in
+// general it is not recommended to call ImportData on untrusted
+// data.
+func ImportData(imports map[string]*types.Package, data []byte) (int, *types.Package, error) {
+	datalen := len(data)
+
+	// check magic string
+	var s string
+	if len(data) >= len(magic) {
+		s = string(data[:len(magic)])
+		data = data[len(magic):]
+	}
+	if s != magic {
+		return 0, nil, fmt.Errorf("incorrect magic string: got %q; want %q", s, magic)
+	}
+
+	// check low-level encoding format
+	var m byte = 'm' // missing format
+	if len(data) > 0 {
+		m = data[0]
+		data = data[1:]
+	}
+	if m != format() {
+		return 0, nil, fmt.Errorf("incorrect low-level encoding format: got %c; want %c", m, format())
+	}
+
+	p := importer{
+		data:    data,
+		datalen: datalen,
+		imports: imports,
+	}
+
+	// populate typList with predeclared types
+	for _, t := range predeclared {
+		p.typList = append(p.typList, t)
+	}
+
+	if v := p.string(); v != version {
+		return 0, nil, fmt.Errorf("unknown version: got %s; want %s", v, version)
+	}
+
+	pkg := p.pkg()
+	if debug && p.pkgList[0] != pkg {
+		panic("imported packaged not found in pkgList[0]")
+	}
+
+	// read objects
+	n := p.int()
+	for i := 0; i < n; i++ {
+		p.obj(pkg)
+	}
+
+	// complete interfaces
+	for _, typ := range p.typList {
+		if it, ok := typ.(*types.Interface); ok {
+			it.Complete()
+		}
+	}
+
+	// package was imported completely and without errors
+	pkg.MarkComplete()
+
+	return p.consumed(), pkg, nil
+}
+
+type importer struct {
+	data    []byte
+	datalen int
+	imports map[string]*types.Package
+	pkgList []*types.Package
+	typList []types.Type
+}
+
+func (p *importer) pkg() *types.Package {
+	// if the package was seen before, i is its index (>= 0)
+	i := p.int()
+	if i >= 0 {
+		return p.pkgList[i]
+	}
+
+	// otherwise, i is the package tag (< 0)
+	if i != packageTag {
+		panic(fmt.Sprintf("unexpected package tag %d", i))
+	}
+
+	// read package data
+	name := p.string()
+	path := p.string()
+
+	// if the package was imported before, use that one; otherwise create a new one
+	pkg := p.imports[path]
+	if pkg == nil {
+		pkg = types.NewPackage(path, name)
+		p.imports[path] = pkg
+	}
+	p.pkgList = append(p.pkgList, pkg)
+
+	return pkg
+}
+
+func (p *importer) obj(pkg *types.Package) {
+	var obj types.Object
+	switch tag := p.int(); tag {
+	case constTag:
+		obj = types.NewConst(token.NoPos, pkg, p.string(), p.typ(), p.value())
+	case typeTag:
+		// type object is added to scope via respective named type
+		_ = p.typ().(*types.Named)
+		return
+	case varTag:
+		obj = types.NewVar(token.NoPos, pkg, p.string(), p.typ())
+	case funcTag:
+		obj = types.NewFunc(token.NoPos, pkg, p.string(), p.typ().(*types.Signature))
+	default:
+		panic(fmt.Sprintf("unexpected object tag %d", tag))
+	}
+
+	if alt := pkg.Scope().Insert(obj); alt != nil {
+		panic(fmt.Sprintf("%s already declared", alt.Name()))
+	}
+}
+
+func (p *importer) value() exact.Value {
+	switch kind := exact.Kind(p.int()); kind {
+	case falseTag:
+		return exact.MakeBool(false)
+	case trueTag:
+		return exact.MakeBool(true)
+	case int64Tag:
+		return exact.MakeInt64(p.int64())
+	case floatTag:
+		return p.float()
+	case fractionTag:
+		return p.fraction()
+	case complexTag:
+		re := p.fraction()
+		im := p.fraction()
+		return exact.BinaryOp(re, token.ADD, exact.MakeImag(im))
+	case stringTag:
+		return exact.MakeString(p.string())
+	default:
+		panic(fmt.Sprintf("unexpected value kind %d", kind))
+	}
+}
+
+func (p *importer) float() exact.Value {
+	sign := p.int()
+	if sign == 0 {
+		return exact.MakeInt64(0)
+	}
+
+	x := p.ufloat()
+	if sign < 0 {
+		x = exact.UnaryOp(token.SUB, x, 0)
+	}
+	return x
+}
+
+func (p *importer) fraction() exact.Value {
+	sign := p.int()
+	if sign == 0 {
+		return exact.MakeInt64(0)
+	}
+
+	x := exact.BinaryOp(p.ufloat(), token.QUO, p.ufloat())
+	if sign < 0 {
+		x = exact.UnaryOp(token.SUB, x, 0)
+	}
+	return x
+}
+
+func (p *importer) ufloat() exact.Value {
+	exp := p.int()
+	x := exact.MakeFromBytes(p.bytes())
+	switch {
+	case exp < 0:
+		d := exact.Shift(exact.MakeInt64(1), token.SHL, uint(-exp))
+		x = exact.BinaryOp(x, token.QUO, d)
+	case exp > 0:
+		x = exact.Shift(x, token.SHL, uint(exp))
+	}
+	return x
+}
+
+func (p *importer) record(t types.Type) {
+	p.typList = append(p.typList, t)
+}
+
+func (p *importer) typ() types.Type {
+	// if the type was seen before, i is its index (>= 0)
+	i := p.int()
+	if i >= 0 {
+		return p.typList[i]
+	}
+
+	// otherwise, i is the type tag (< 0)
+	switch i {
+	case arrayTag:
+		t := new(types.Array)
+		p.record(t)
+
+		n := p.int64()
+		*t = *types.NewArray(p.typ(), n)
+		return t
+
+	case sliceTag:
+		t := new(types.Slice)
+		p.record(t)
+
+		*t = *types.NewSlice(p.typ())
+		return t
+
+	case structTag:
+		t := new(types.Struct)
+		p.record(t)
+
+		n := p.int()
+		fields := make([]*types.Var, n)
+		tags := make([]string, n)
+		for i := range fields {
+			fields[i] = p.field()
+			tags[i] = p.string()
+		}
+		*t = *types.NewStruct(fields, tags)
+		return t
+
+	case pointerTag:
+		t := new(types.Pointer)
+		p.record(t)
+
+		*t = *types.NewPointer(p.typ())
+		return t
+
+	case signatureTag:
+		t := new(types.Signature)
+		p.record(t)
+
+		*t = *p.signature()
+		return t
+
+	case interfaceTag:
+		// Create a dummy entry in the type list. This is safe because we
+		// cannot expect the interface type to appear in a cycle, as any
+		// such cycle must contain a named type which would have been
+		// first defined earlier.
+		n := len(p.typList)
+		p.record(nil)
+
+		// read embedded interfaces
+		embeddeds := make([]*types.Named, p.int())
+		for i := range embeddeds {
+			embeddeds[i] = p.typ().(*types.Named)
+		}
+
+		// read methods
+		methods := make([]*types.Func, p.int())
+		for i := range methods {
+			pkg, name := p.qualifiedName()
+			methods[i] = types.NewFunc(token.NoPos, pkg, name, p.typ().(*types.Signature))
+		}
+
+		t := types.NewInterface(methods, embeddeds)
+		p.typList[n] = t
+		return t
+
+	case mapTag:
+		t := new(types.Map)
+		p.record(t)
+
+		*t = *types.NewMap(p.typ(), p.typ())
+		return t
+
+	case chanTag:
+		t := new(types.Chan)
+		p.record(t)
+
+		*t = *types.NewChan(types.ChanDir(p.int()), p.typ())
+		return t
+
+	case namedTag:
+		// read type object
+		name := p.string()
+		pkg := p.pkg()
+		scope := pkg.Scope()
+		obj := scope.Lookup(name)
+
+		// if the object doesn't exist yet, create and insert it
+		if obj == nil {
+			obj = types.NewTypeName(token.NoPos, pkg, name, nil)
+			scope.Insert(obj)
+		}
+
+		// associate new named type with obj if it doesn't exist yet
+		t0 := types.NewNamed(obj.(*types.TypeName), nil, nil)
+
+		// but record the existing type, if any
+		t := obj.Type().(*types.Named)
+		p.record(t)
+
+		// read underlying type
+		t0.SetUnderlying(p.typ())
+
+		// read associated methods
+		for i, n := 0, p.int(); i < n; i++ {
+			t0.AddMethod(types.NewFunc(token.NoPos, pkg, p.string(), p.typ().(*types.Signature)))
+		}
+
+		return t
+
+	default:
+		panic(fmt.Sprintf("unexpected type tag %d", i))
+	}
+}
+
+func deref(typ types.Type) types.Type {
+	if p, _ := typ.(*types.Pointer); p != nil {
+		return p.Elem()
+	}
+	return typ
+}
+
+func (p *importer) field() *types.Var {
+	pkg, name := p.qualifiedName()
+	typ := p.typ()
+
+	anonymous := false
+	if name == "" {
+		// anonymous field - typ must be T or *T and T must be a type name
+		switch typ := deref(typ).(type) {
+		case *types.Basic: // basic types are named types
+			pkg = nil
+			name = typ.Name()
+		case *types.Named:
+			obj := typ.Obj()
+			name = obj.Name()
+			// correct the field package for anonymous fields
+			if exported(name) {
+				pkg = p.pkgList[0]
+			}
+		default:
+			panic("anonymous field expected")
+		}
+		anonymous = true
+	}
+
+	return types.NewField(token.NoPos, pkg, name, typ, anonymous)
+}
+
+func (p *importer) qualifiedName() (*types.Package, string) {
+	name := p.string()
+	pkg := p.pkgList[0] // exported names assume current package
+	if !exported(name) {
+		pkg = p.pkg()
+	}
+	return pkg, name
+}
+
+func (p *importer) signature() *types.Signature {
+	var recv *types.Var
+	if p.int() != 0 {
+		recv = p.param()
+	}
+	return types.NewSignature(recv, p.tuple(), p.tuple(), p.int() != 0)
+}
+
+func (p *importer) param() *types.Var {
+	return types.NewVar(token.NoPos, nil, p.string(), p.typ())
+}
+
+func (p *importer) tuple() *types.Tuple {
+	vars := make([]*types.Var, p.int())
+	for i := range vars {
+		vars[i] = p.param()
+	}
+	return types.NewTuple(vars...)
+}
+
+// ----------------------------------------------------------------------------
+// decoders
+
+func (p *importer) string() string {
+	return string(p.bytes())
+}
+
+func (p *importer) int() int {
+	return int(p.int64())
+}
+
+func (p *importer) int64() int64 {
+	if debug {
+		p.marker('i')
+	}
+
+	return p.rawInt64()
+}
+
+// Note: bytes() returns the respective byte slice w/o copy.
+func (p *importer) bytes() []byte {
+	if debug {
+		p.marker('b')
+	}
+
+	var b []byte
+	if n := int(p.rawInt64()); n > 0 {
+		b = p.data[:n]
+		p.data = p.data[n:]
+	}
+	return b
+}
+
+func (p *importer) marker(want byte) {
+	if debug {
+		if got := p.data[0]; got != want {
+			panic(fmt.Sprintf("incorrect marker: got %c; want %c (pos = %d)", got, want, p.consumed()))
+		}
+		p.data = p.data[1:]
+
+		pos := p.consumed()
+		if n := int(p.rawInt64()); n != pos {
+			panic(fmt.Sprintf("incorrect position: got %d; want %d", n, pos))
+		}
+	}
+}
+
+// rawInt64 should only be used by low-level decoders
+func (p *importer) rawInt64() int64 {
+	i, n := binary.Varint(p.data)
+	p.data = p.data[n:]
+	return i
+}
+
+func (p *importer) consumed() int {
+	return p.datalen - len(p.data)
+}
diff --git a/go/importer/import_test.go b/go/importer/import_test.go
new file mode 100644
index 0000000..3a2560c
--- /dev/null
+++ b/go/importer/import_test.go
@@ -0,0 +1,382 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package importer
+
+import (
+	"bufio"
+	"bytes"
+	"fmt"
+	"go/ast"
+	"go/build"
+	"go/parser"
+	"go/token"
+	"os"
+	"path/filepath"
+	"runtime"
+	"sort"
+	"strconv"
+	"testing"
+	"time"
+
+	"golang.org/x/tools/go/gcimporter"
+	"golang.org/x/tools/go/types"
+)
+
+var fset = token.NewFileSet()
+
+var tests = []string{
+	`package p`,
+
+	// consts
+	`package p; const X = true`,
+	`package p; const X, y, Z = true, false, 0 != 0`,
+	`package p; const ( A float32 = 1<<iota; B; C; D)`,
+	`package p; const X = "foo"`,
+	`package p; const X string = "foo"`,
+	`package p; const X = 0`,
+	`package p; const X = -42`,
+	`package p; const X = 3.14159265`,
+	`package p; const X = -1e-10`,
+	`package p; const X = 1.2 + 2.3i`,
+	`package p; const X = -1i`,
+	`package p; import "math"; const Pi = math.Pi`,
+	`package p; import m "math"; const Pi = m.Pi`,
+
+	// types
+	`package p; type T int`,
+	`package p; type T [10]int`,
+	`package p; type T []int`,
+	`package p; type T struct{}`,
+	`package p; type T struct{x int}`,
+	`package p; type T *int`,
+	`package p; type T func()`,
+	`package p; type T *T`,
+	`package p; type T interface{}`,
+	`package p; type T interface{ foo() }`,
+	`package p; type T interface{ m() T }`,
+	// TODO(gri) disabled for now - import/export works but
+	// types.Type.String() used in the test cannot handle cases
+	// like this yet
+	// `package p; type T interface{ m() interface{T} }`,
+	`package p; type T map[string]bool`,
+	`package p; type T chan int`,
+	`package p; type T <-chan complex64`,
+	`package p; type T chan<- map[int]string`,
+	// test case for issue 8177
+	`package p; type T1 interface { F(T2) }; type T2 interface { T1 }`,
+
+	// vars
+	`package p; var X int`,
+	`package p; var X, Y, Z struct{f int "tag"}`,
+
+	// funcs
+	`package p; func F()`,
+	`package p; func F(x int, y struct{}) bool`,
+	`package p; type T int; func (*T) F(x int, y struct{}) T`,
+
+	// selected special cases
+	`package p; type T int`,
+	`package p; type T uint8`,
+	`package p; type T byte`,
+	`package p; type T error`,
+	`package p; import "net/http"; type T http.Client`,
+	`package p; import "net/http"; type ( T1 http.Client; T2 struct { http.Client } )`,
+	`package p; import "unsafe"; type ( T1 unsafe.Pointer; T2 unsafe.Pointer )`,
+	`package p; import "unsafe"; type T struct { p unsafe.Pointer }`,
+}
+
+func TestImportSrc(t *testing.T) {
+	for _, src := range tests {
+		pkg, err := pkgForSource(src)
+		if err != nil {
+			t.Errorf("typecheck failed: %s", err)
+			continue
+		}
+		testExportImport(t, pkg, "")
+	}
+}
+
+func TestImportStdLib(t *testing.T) {
+	start := time.Now()
+
+	libs, err := stdLibs()
+	if err != nil {
+		t.Fatalf("could not compute list of std libraries: %s", err)
+	}
+	if len(libs) < 100 {
+		t.Fatalf("only %d std libraries found - something's not right", len(libs))
+	}
+
+	// make sure printed go/types types and gc-imported types
+	// can be compared reasonably well
+	types.GcCompatibilityMode = true
+
+	var totSize, totGcSize int
+	for _, lib := range libs {
+		// limit run time for short tests
+		if testing.Short() && time.Since(start) >= 750*time.Millisecond {
+			return
+		}
+
+		pkg, err := pkgForPath(lib)
+		switch err := err.(type) {
+		case nil:
+			// ok
+		case *build.NoGoError:
+			// no Go files - ignore
+			continue
+		default:
+			t.Errorf("typecheck failed: %s", err)
+			continue
+		}
+
+		size, gcsize := testExportImport(t, pkg, lib)
+		if gcsize == 0 {
+			// if gc import didn't happen, assume same size
+			// (and avoid division by zero below)
+			gcsize = size
+		}
+
+		if testing.Verbose() {
+			fmt.Printf("%s\t%d\t%d\t%d%%\n", lib, size, gcsize, int(float64(size)*100/float64(gcsize)))
+		}
+		totSize += size
+		totGcSize += gcsize
+	}
+
+	if testing.Verbose() {
+		fmt.Printf("\n%d\t%d\t%d%%\n", totSize, totGcSize, int(float64(totSize)*100/float64(totGcSize)))
+	}
+
+	types.GcCompatibilityMode = false
+}
+
+func testExportImport(t *testing.T, pkg0 *types.Package, path string) (size, gcsize int) {
+	data := ExportData(pkg0)
+	size = len(data)
+
+	imports := make(map[string]*types.Package)
+	n, pkg1, err := ImportData(imports, data)
+	if err != nil {
+		t.Errorf("package %s: import failed: %s", pkg0.Name(), err)
+		return
+	}
+	if n != size {
+		t.Errorf("package %s: not all input data consumed", pkg0.Name())
+		return
+	}
+
+	s0 := pkgString(pkg0)
+	s1 := pkgString(pkg1)
+	if s1 != s0 {
+		t.Errorf("package %s: \nimport got:\n%s\nwant:\n%s\n", pkg0.Name(), s1, s0)
+	}
+
+	// If we have a standard library, compare also against the gcimported package.
+	if path == "" {
+		return // not std library
+	}
+
+	gcdata, err := gcExportData(path)
+	if err != nil {
+		if pkg0.Name() == "main" {
+			return // no export data present for main package
+		}
+		t.Errorf("package %s: couldn't get export data: %s", pkg0.Name(), err)
+	}
+	gcsize = len(gcdata)
+
+	imports = make(map[string]*types.Package)
+	pkg2, err := gcImportData(imports, gcdata, path)
+	if err != nil {
+		t.Errorf("package %s: gcimport failed: %s", pkg0.Name(), err)
+		return
+	}
+
+	s2 := pkgString(pkg2)
+	if s2 != s0 {
+		t.Errorf("package %s: \ngcimport got:\n%s\nwant:\n%s\n", pkg0.Name(), s2, s0)
+	}
+
+	return
+}
+
+func pkgForSource(src string) (*types.Package, error) {
+	f, err := parser.ParseFile(fset, "", src, 0)
+	if err != nil {
+		return nil, err
+	}
+	return typecheck("import-test", f)
+}
+
+func pkgForPath(path string) (*types.Package, error) {
+	// collect filenames
+	ctxt := build.Default
+	pkginfo, err := ctxt.Import(path, "", 0)
+	if err != nil {
+		return nil, err
+	}
+	filenames := append(pkginfo.GoFiles, pkginfo.CgoFiles...)
+
+	// parse files
+	files := make([]*ast.File, len(filenames))
+	for i, filename := range filenames {
+		var err error
+		files[i], err = parser.ParseFile(fset, filepath.Join(pkginfo.Dir, filename), nil, 0)
+		if err != nil {
+			return nil, err
+		}
+	}
+
+	return typecheck(path, files...)
+}
+
+var defaultConf = types.Config{
+	// we only care about exports and thus can ignore function bodies
+	IgnoreFuncBodies: true,
+	// work around C imports if possible
+	FakeImportC: true,
+	// strconv exports IntSize as a constant. The type-checker must
+	// use the same word size otherwise the result of the type-checker
+	// and gc imports is different. We don't care about alignment
+	// since none of the tests have exported constants depending
+	// on alignment (see also issue 8366).
+	Sizes: &types.StdSizes{WordSize: strconv.IntSize / 8, MaxAlign: 8},
+}
+
+func typecheck(path string, files ...*ast.File) (*types.Package, error) {
+	return defaultConf.Check(path, fset, files, nil)
+}
+
+// pkgString returns a string representation of a package's exported interface.
+func pkgString(pkg *types.Package) string {
+	var buf bytes.Buffer
+
+	fmt.Fprintf(&buf, "package %s\n", pkg.Name())
+
+	scope := pkg.Scope()
+	for _, name := range scope.Names() {
+		if exported(name) {
+			obj := scope.Lookup(name)
+			buf.WriteString(obj.String())
+
+			switch obj := obj.(type) {
+			case *types.Const:
+				// For now only print constant values if they are not float
+				// or complex. This permits comparing go/types results with
+				// gc-generated gcimported package interfaces.
+				info := obj.Type().Underlying().(*types.Basic).Info()
+				if info&types.IsFloat == 0 && info&types.IsComplex == 0 {
+					fmt.Fprintf(&buf, " = %s", obj.Val())
+				}
+
+			case *types.TypeName:
+				// Print associated methods.
+				// Basic types (e.g., unsafe.Pointer) have *types.Basic
+				// type rather than *types.Named; so we need to check.
+				if typ, _ := obj.Type().(*types.Named); typ != nil {
+					if n := typ.NumMethods(); n > 0 {
+						// Sort methods by name so that we get the
+						// same order independent of whether the
+						// methods got imported or coming directly
+						// for the source.
+						// TODO(gri) This should probably be done
+						// in go/types.
+						list := make([]*types.Func, n)
+						for i := 0; i < n; i++ {
+							list[i] = typ.Method(i)
+						}
+						sort.Sort(byName(list))
+
+						buf.WriteString("\nmethods (\n")
+						for _, m := range list {
+							fmt.Fprintf(&buf, "\t%s\n", m)
+						}
+						buf.WriteString(")")
+					}
+				}
+			}
+			buf.WriteByte('\n')
+		}
+	}
+
+	return buf.String()
+}
+
+var stdLibRoot = filepath.Join(runtime.GOROOT(), "src") + string(filepath.Separator)
+
+// The following std libraries are excluded from the stdLibs list.
+var excluded = map[string]bool{
+	"builtin": true, // contains type declarations with cycles
+	"unsafe":  true, // contains fake declarations
+}
+
+// stdLibs returns the list of standard library package paths.
+func stdLibs() (list []string, err error) {
+	err = filepath.Walk(stdLibRoot, func(path string, info os.FileInfo, err error) error {
+		if err == nil && info.IsDir() {
+			// testdata directories don't contain importable libraries
+			if info.Name() == "testdata" {
+				return filepath.SkipDir
+			}
+			pkgPath := path[len(stdLibRoot):] // remove stdLibRoot
+			if len(pkgPath) > 0 && !excluded[pkgPath] {
+				list = append(list, pkgPath)
+			}
+		}
+		return nil
+	})
+	return
+}
+
+type byName []*types.Func
+
+func (a byName) Len() int           { return len(a) }
+func (a byName) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
+func (a byName) Less(i, j int) bool { return a[i].Name() < a[j].Name() }
+
+// gcExportData returns the gc-generated export data for the given path.
+// It is based on a trimmed-down version of gcimporter.Import which does
+// not do the actual import, does not handle package unsafe, and assumes
+// that path is a correct standard library package path (no canonicalization,
+// or handling of local import paths).
+func gcExportData(path string) ([]byte, error) {
+	filename, id := gcimporter.FindPkg(path, "")
+	if filename == "" {
+		return nil, fmt.Errorf("can't find import: %s", path)
+	}
+	if id != path {
+		panic("path should be canonicalized")
+	}
+
+	f, err := os.Open(filename)
+	if err != nil {
+		return nil, err
+	}
+	defer f.Close()
+
+	buf := bufio.NewReader(f)
+	if err = gcimporter.FindExportData(buf); err != nil {
+		return nil, err
+	}
+
+	var data []byte
+	for {
+		line, err := buf.ReadBytes('\n')
+		if err != nil {
+			return nil, err
+		}
+		data = append(data, line...)
+		// export data ends in "$$\n"
+		if len(line) == 3 && line[0] == '$' && line[1] == '$' {
+			return data, nil
+		}
+	}
+}
+
+func gcImportData(imports map[string]*types.Package, data []byte, path string) (*types.Package, error) {
+	filename := fmt.Sprintf("<filename for %s>", path) // so we have a decent error message if necessary
+	return gcimporter.ImportData(imports, filename, path, bufio.NewReader(bytes.NewBuffer(data)))
+}
diff --git a/go/importer/predefined.go b/go/importer/predefined.go
new file mode 100644
index 0000000..b23dfcb
--- /dev/null
+++ b/go/importer/predefined.go
@@ -0,0 +1,84 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package importer
+
+import "golang.org/x/tools/go/types"
+
+const (
+	magic   = "\n$$ exports $$\n"
+	version = "v0"
+)
+
+// Tags. Must be < 0.
+const (
+	// Packages
+	packageTag = -(iota + 1)
+
+	// Objects
+	constTag
+	typeTag
+	varTag
+	funcTag
+
+	// Types
+	arrayTag
+	sliceTag
+	structTag
+	pointerTag
+	signatureTag
+	interfaceTag
+	mapTag
+	chanTag
+	namedTag
+
+	// Values
+	falseTag
+	trueTag
+	int64Tag
+	floatTag
+	fractionTag
+	complexTag
+	stringTag
+)
+
+var predeclared = []types.Type{
+	// basic types
+	types.Typ[types.Bool],
+	types.Typ[types.Int],
+	types.Typ[types.Int8],
+	types.Typ[types.Int16],
+	types.Typ[types.Int32],
+	types.Typ[types.Int64],
+	types.Typ[types.Uint],
+	types.Typ[types.Uint8],
+	types.Typ[types.Uint16],
+	types.Typ[types.Uint32],
+	types.Typ[types.Uint64],
+	types.Typ[types.Uintptr],
+	types.Typ[types.Float32],
+	types.Typ[types.Float64],
+	types.Typ[types.Complex64],
+	types.Typ[types.Complex128],
+	types.Typ[types.String],
+
+	// untyped types
+	types.Typ[types.UntypedBool],
+	types.Typ[types.UntypedInt],
+	types.Typ[types.UntypedRune],
+	types.Typ[types.UntypedFloat],
+	types.Typ[types.UntypedComplex],
+	types.Typ[types.UntypedString],
+	types.Typ[types.UntypedNil],
+
+	// package unsafe
+	types.Typ[types.UnsafePointer],
+
+	// aliases
+	types.Universe.Lookup("byte").Type(),
+	types.Universe.Lookup("rune").Type(),
+
+	// error
+	types.Universe.Lookup("error").Type(),
+}
diff --git a/go/loader/cgo.go b/go/loader/cgo.go
new file mode 100644
index 0000000..fb39e53
--- /dev/null
+++ b/go/loader/cgo.go
@@ -0,0 +1,199 @@
+package loader
+
+// This file handles cgo preprocessing of files containing `import "C"`.
+//
+// DESIGN
+//
+// The approach taken is to run the cgo processor on the package's
+// CgoFiles and parse the output, faking the filenames of the
+// resulting ASTs so that the synthetic file containing the C types is
+// called "C" (e.g. "~/go/src/net/C") and the preprocessed files
+// have their original names (e.g. "~/go/src/net/cgo_unix.go"),
+// not the names of the actual temporary files.
+//
+// The advantage of this approach is its fidelity to 'go build'.  The
+// downside is that the token.Position.Offset for each AST node is
+// incorrect, being an offset within the temporary file.  Line numbers
+// should still be correct because of the //line comments.
+//
+// The logic of this file is mostly plundered from the 'go build'
+// tool, which also invokes the cgo preprocessor.
+//
+//
+// REJECTED ALTERNATIVE
+//
+// An alternative approach that we explored is to extend go/types'
+// Importer mechanism to provide the identity of the importing package
+// so that each time `import "C"` appears it resolves to a different
+// synthetic package containing just the objects needed in that case.
+// The loader would invoke cgo but parse only the cgo_types.go file
+// defining the package-level objects, discarding the other files
+// resulting from preprocessing.
+//
+// The benefit of this approach would have been that source-level
+// syntax information would correspond exactly to the original cgo
+// file, with no preprocessing involved, making source tools like
+// godoc, oracle, and eg happy.  However, the approach was rejected
+// due to the additional complexity it would impose on go/types.  (It
+// made for a beautiful demo, though.)
+//
+// cgo files, despite their *.go extension, are not legal Go source
+// files per the specification since they may refer to unexported
+// members of package "C" such as C.int.  Also, a function such as
+// C.getpwent has in effect two types, one matching its C type and one
+// which additionally returns (errno C.int).  The cgo preprocessor
+// uses name mangling to distinguish these two functions in the
+// processed code, but go/types would need to duplicate this logic in
+// its handling of function calls, analogous to the treatment of map
+// lookups in which y=m[k] and y,ok=m[k] are both legal.
+
+import (
+	"fmt"
+	"go/ast"
+	"go/build"
+	"go/parser"
+	"go/token"
+	"io/ioutil"
+	"log"
+	"os"
+	"os/exec"
+	"path/filepath"
+	"regexp"
+	"strings"
+)
+
+// processCgoFiles invokes the cgo preprocessor on bp.CgoFiles, parses
+// the output and returns the resulting ASTs.
+//
+func processCgoFiles(bp *build.Package, fset *token.FileSet, DisplayPath func(path string) string, mode parser.Mode) ([]*ast.File, error) {
+	tmpdir, err := ioutil.TempDir("", strings.Replace(bp.ImportPath, "/", "_", -1)+"_C")
+	if err != nil {
+		return nil, err
+	}
+	defer os.RemoveAll(tmpdir)
+
+	pkgdir := bp.Dir
+	if DisplayPath != nil {
+		pkgdir = DisplayPath(pkgdir)
+	}
+
+	cgoFiles, cgoDisplayFiles, err := runCgo(bp, pkgdir, tmpdir)
+	if err != nil {
+		return nil, err
+	}
+	var files []*ast.File
+	for i := range cgoFiles {
+		rd, err := os.Open(cgoFiles[i])
+		if err != nil {
+			return nil, err
+		}
+		display := filepath.Join(bp.Dir, cgoDisplayFiles[i])
+		f, err := parser.ParseFile(fset, display, rd, mode)
+		rd.Close()
+		if err != nil {
+			return nil, err
+		}
+		files = append(files, f)
+	}
+	return files, nil
+}
+
+var cgoRe = regexp.MustCompile(`[/\\:]`)
+
+// runCgo invokes the cgo preprocessor on bp.CgoFiles and returns two
+// lists of files: the resulting processed files (in temporary
+// directory tmpdir) and the corresponding names of the unprocessed files.
+//
+// runCgo is adapted from (*builder).cgo in
+// $GOROOT/src/cmd/go/build.go, but these features are unsupported:
+// pkg-config, Objective C, CGOPKGPATH, CGO_FLAGS.
+//
+func runCgo(bp *build.Package, pkgdir, tmpdir string) (files, displayFiles []string, err error) {
+	cgoCPPFLAGS, _, _, _ := cflags(bp, true)
+	_, cgoexeCFLAGS, _, _ := cflags(bp, false)
+
+	if len(bp.CgoPkgConfig) > 0 {
+		return nil, nil, fmt.Errorf("cgo pkg-config not supported")
+	}
+
+	// Allows including _cgo_export.h from .[ch] files in the package.
+	cgoCPPFLAGS = append(cgoCPPFLAGS, "-I", tmpdir)
+
+	// _cgo_gotypes.go (displayed "C") contains the type definitions.
+	files = append(files, filepath.Join(tmpdir, "_cgo_gotypes.go"))
+	displayFiles = append(displayFiles, "C")
+	for _, fn := range bp.CgoFiles {
+		// "foo.cgo1.go" (displayed "foo.go") is the processed Go source.
+		f := cgoRe.ReplaceAllString(fn[:len(fn)-len("go")], "_")
+		files = append(files, filepath.Join(tmpdir, f+"cgo1.go"))
+		displayFiles = append(displayFiles, fn)
+	}
+
+	var cgoflags []string
+	if bp.Goroot && bp.ImportPath == "runtime/cgo" {
+		cgoflags = append(cgoflags, "-import_runtime_cgo=false")
+	}
+	if bp.Goroot && bp.ImportPath == "runtime/race" || bp.ImportPath == "runtime/cgo" {
+		cgoflags = append(cgoflags, "-import_syscall=false")
+	}
+
+	args := stringList(
+		"go", "tool", "cgo", "-objdir", tmpdir, cgoflags, "--",
+		cgoCPPFLAGS, cgoexeCFLAGS, bp.CgoFiles,
+	)
+	if false {
+		log.Printf("Running cgo for package %q: %s (dir=%s)", bp.ImportPath, args, pkgdir)
+	}
+	cmd := exec.Command(args[0], args[1:]...)
+	cmd.Dir = pkgdir
+	cmd.Stdout = os.Stderr
+	cmd.Stderr = os.Stderr
+	if err := cmd.Run(); err != nil {
+		return nil, nil, fmt.Errorf("cgo failed: %s: %s", args, err)
+	}
+
+	return files, displayFiles, nil
+}
+
+// -- unmodified from 'go build' ---------------------------------------
+
+// Return the flags to use when invoking the C or C++ compilers, or cgo.
+func cflags(p *build.Package, def bool) (cppflags, cflags, cxxflags, ldflags []string) {
+	var defaults string
+	if def {
+		defaults = "-g -O2"
+	}
+
+	cppflags = stringList(envList("CGO_CPPFLAGS", ""), p.CgoCPPFLAGS)
+	cflags = stringList(envList("CGO_CFLAGS", defaults), p.CgoCFLAGS)
+	cxxflags = stringList(envList("CGO_CXXFLAGS", defaults), p.CgoCXXFLAGS)
+	ldflags = stringList(envList("CGO_LDFLAGS", defaults), p.CgoLDFLAGS)
+	return
+}
+
+// envList returns the value of the given environment variable broken
+// into fields, using the default value when the variable is empty.
+func envList(key, def string) []string {
+	v := os.Getenv(key)
+	if v == "" {
+		v = def
+	}
+	return strings.Fields(v)
+}
+
+// stringList's arguments should be a sequence of string or []string values.
+// stringList flattens them into a single []string.
+func stringList(args ...interface{}) []string {
+	var x []string
+	for _, arg := range args {
+		switch arg := arg.(type) {
+		case []string:
+			x = append(x, arg...)
+		case string:
+			x = append(x, arg)
+		default:
+			panic("stringList: invalid argument")
+		}
+	}
+	return x
+}
diff --git a/go/loader/doc.go b/go/loader/doc.go
new file mode 100644
index 0000000..1ff4b15
--- /dev/null
+++ b/go/loader/doc.go
@@ -0,0 +1,189 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package loader loads a complete Go program from source code, parsing
+// and type-checking the initial packages plus their transitive closure
+// of dependencies.  The ASTs and the derived facts are retained for
+// later use.
+//
+// THIS INTERFACE IS EXPERIMENTAL AND IS LIKELY TO CHANGE.
+//
+// The package defines two primary types: Config, which specifies a
+// set of initial packages to load and various other options; and
+// Program, which is the result of successfully loading the packages
+// specified by a configuration.
+//
+// The configuration can be set directly, but *Config provides various
+// convenience methods to simplify the common cases, each of which can
+// be called any number of times.  Finally, these are followed by a
+// call to Load() to actually load and type-check the program.
+//
+//      var conf loader.Config
+//
+//      // Use the command-line arguments to specify
+//      // a set of initial packages to load from source.
+//      // See FromArgsUsage for help.
+//      rest, err := conf.FromArgs(os.Args[1:], wantTests)
+//
+//      // Parse the specified files and create an ad hoc package with path "foo".
+//      // All files must have the same 'package' declaration.
+//      conf.CreateFromFilenames("foo", "foo.go", "bar.go")
+//
+//      // Create an ad hoc package with path "foo" from
+//      // the specified already-parsed files.
+//      // All ASTs must have the same 'package' declaration.
+//      conf.CreateFromFiles("foo", parsedFiles)
+//
+//      // Add "runtime" to the set of packages to be loaded.
+//      conf.Import("runtime")
+//
+//      // Adds "fmt" and "fmt_test" to the set of packages
+//      // to be loaded.  "fmt" will include *_test.go files.
+//      conf.ImportWithTests("fmt")
+//
+//      // Finally, load all the packages specified by the configuration.
+//      prog, err := conf.Load()
+//
+// See examples_test.go for examples of API usage.
+//
+//
+// CONCEPTS AND TERMINOLOGY
+//
+// An AD HOC package is one specified as a set of source files on the
+// command line.  In the simplest case, it may consist of a single file
+// such as $GOROOT/src/net/http/triv.go.
+//
+// EXTERNAL TEST packages are those comprised of a set of *_test.go
+// files all with the same 'package foo_test' declaration, all in the
+// same directory.  (go/build.Package calls these files XTestFiles.)
+//
+// An IMPORTABLE package is one that can be referred to by some import
+// spec.  The Path() of each importable package is unique within a
+// Program.
+//
+// ad hoc packages and external test packages are NON-IMPORTABLE.  The
+// Path() of an ad hoc package is inferred from the package
+// declarations of its files and is therefore not a unique package key.
+// For example, Config.CreatePkgs may specify two initial ad hoc
+// packages both called "main".
+//
+// An AUGMENTED package is an importable package P plus all the
+// *_test.go files with same 'package foo' declaration as P.
+// (go/build.Package calls these files TestFiles.)
+//
+// The INITIAL packages are those specified in the configuration.  A
+// DEPENDENCY is a package loaded to satisfy an import in an initial
+// package or another dependency.
+//
+package loader
+
+// IMPLEMENTATION NOTES
+//
+// 'go test', in-package test files, and import cycles
+// ---------------------------------------------------
+//
+// An external test package may depend upon members of the augmented
+// package that are not in the unaugmented package, such as functions
+// that expose internals.  (See bufio/export_test.go for an example.)
+// So, the loader must ensure that for each external test package
+// it loads, it also augments the corresponding non-test package.
+//
+// The import graph over n unaugmented packages must be acyclic; the
+// import graph over n-1 unaugmented packages plus one augmented
+// package must also be acyclic.  ('go test' relies on this.)  But the
+// import graph over n augmented packages may contain cycles.
+//
+// First, all the (unaugmented) non-test packages and their
+// dependencies are imported in the usual way; the loader reports an
+// error if it detects an import cycle.
+//
+// Then, each package P for which testing is desired is augmented by
+// the list P' of its in-package test files, by calling
+// (*types.Checker).Files.  This arrangement ensures that P' may
+// reference definitions within P, but P may not reference definitions
+// within P'.  Furthermore, P' may import any other package, including
+// ones that depend upon P, without an import cycle error.
+//
+// Consider two packages A and B, both of which have lists of
+// in-package test files we'll call A' and B', and which have the
+// following import graph edges:
+//    B  imports A
+//    B' imports A
+//    A' imports B
+// This last edge would be expected to create an error were it not
+// for the special type-checking discipline above.
+// Cycles of size greater than two are possible.  For example:
+//   compress/bzip2/bzip2_test.go (package bzip2)  imports "io/ioutil"
+//   io/ioutil/tempfile_test.go   (package ioutil) imports "regexp"
+//   regexp/exec_test.go          (package regexp) imports "compress/bzip2"
+//
+//
+// Concurrency
+// -----------
+//
+// Let us define the import dependency graph as follows.  Each node is a
+// list of files passed to (Checker).Files at once.  Many of these lists
+// are the production code of an importable Go package, so those nodes
+// are labelled by the package's import path.  The remaining nodes are
+// ad hoc packages and lists of in-package *_test.go files that augment
+// an importable package; those nodes have no label.
+//
+// The edges of the graph represent import statements appearing within a
+// file.  An edge connects a node (a list of files) to the node it
+// imports, which is importable and thus always labelled.
+//
+// Loading is controlled by this dependency graph.
+//
+// To reduce I/O latency, we start loading a package's dependencies
+// asynchronously as soon as we've parsed its files and enumerated its
+// imports (scanImports).  This performs a preorder traversal of the
+// import dependency graph.
+//
+// To exploit hardware parallelism, we type-check unrelated packages in
+// parallel, where "unrelated" means not ordered by the partial order of
+// the import dependency graph.
+//
+// We use a concurrency-safe blocking cache (importer.imported) to
+// record the results of type-checking, whether success or failure.  An
+// entry is created in this cache by startLoad the first time the
+// package is imported.  The first goroutine to request an entry becomes
+// responsible for completing the task and broadcasting completion to
+// subsequent requestors, which block until then.
+//
+// Type checking occurs in (parallel) postorder: we cannot type-check a
+// set of files until we have loaded and type-checked all of their
+// immediate dependencies (and thus all of their transitive
+// dependencies). If the input were guaranteed free of import cycles,
+// this would be trivial: we could simply wait for completion of the
+// dependencies and then invoke the typechecker.
+//
+// But as we saw in the 'go test' section above, some cycles in the
+// import graph over packages are actually legal, so long as the
+// cycle-forming edge originates in the in-package test files that
+// augment the package.  This explains why the nodes of the import
+// dependency graph are not packages, but lists of files: the unlabelled
+// nodes avoid the cycles.  Consider packages A and B where B imports A
+// and A's in-package tests AT import B.  The naively constructed import
+// graph over packages would contain a cycle (A+AT) --> B --> (A+AT) but
+// the graph over lists of files is AT --> B --> A, where AT is an
+// unlabelled node.
+//
+// Awaiting completion of the dependencies in a cyclic graph would
+// deadlock, so we must materialize the import dependency graph (as
+// importer.graph) and check whether each import edge forms a cycle.  If
+// x imports y, and the graph already contains a path from y to x, then
+// there is an import cycle, in which case the processing of x must not
+// wait for the completion of processing of y.
+//
+// When the type-checker makes a callback (doImport) to the loader for a
+// given import edge, there are two possible cases.  In the normal case,
+// the dependency has already been completely type-checked; doImport
+// does a cache lookup and returns it.  In the cyclic case, the entry in
+// the cache is still necessarily incomplete, indicating a cycle.  We
+// perform the cycle check again to obtain the error message, and return
+// the error.
+//
+// The result of using concurrency is about a 2.5x speedup for stdlib_test.
+
+// TODO(adonovan): overhaul the package documentation.
diff --git a/go/loader/example14_test.go b/go/loader/example14_test.go
new file mode 100644
index 0000000..76d5ea6
--- /dev/null
+++ b/go/loader/example14_test.go
@@ -0,0 +1,173 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !go1.5
+// +build !windows
+
+package loader_test
+
+import (
+	"fmt"
+	"go/token"
+	"log"
+	"path/filepath"
+	"runtime"
+	"sort"
+
+	"golang.org/x/tools/go/loader"
+)
+
+func printProgram(prog *loader.Program) {
+	// Created packages are the initial packages specified by a call
+	// to CreateFromFilenames or CreateFromFiles.
+	var names []string
+	for _, info := range prog.Created {
+		names = append(names, info.Pkg.Path())
+	}
+	fmt.Printf("created: %s\n", names)
+
+	// Imported packages are the initial packages specified by a
+	// call to Import or ImportWithTests.
+	names = nil
+	for _, info := range prog.Imported {
+		names = append(names, info.Pkg.Path())
+	}
+	sort.Strings(names)
+	fmt.Printf("imported: %s\n", names)
+
+	// InitialPackages contains the union of created and imported.
+	names = nil
+	for _, info := range prog.InitialPackages() {
+		names = append(names, info.Pkg.Path())
+	}
+	sort.Strings(names)
+	fmt.Printf("initial: %s\n", names)
+
+	// AllPackages contains all initial packages and their dependencies.
+	names = nil
+	for pkg := range prog.AllPackages {
+		names = append(names, pkg.Path())
+	}
+	sort.Strings(names)
+	fmt.Printf("all: %s\n", names)
+}
+
+func printFilenames(fset *token.FileSet, info *loader.PackageInfo) {
+	var names []string
+	for _, f := range info.Files {
+		names = append(names, filepath.Base(fset.File(f.Pos()).Name()))
+	}
+	fmt.Printf("%s.Files: %s\n", info.Pkg.Path(), names)
+}
+
+// This example loads a set of packages and all of their dependencies
+// from a typical command-line.  FromArgs parses a command line and
+// makes calls to the other methods of Config shown in the examples that
+// follow.
+func ExampleConfig_FromArgs() {
+	args := []string{"mytool", "unicode/utf8", "errors", "runtime", "--", "foo", "bar"}
+	const wantTests = false
+
+	var conf loader.Config
+	rest, err := conf.FromArgs(args[1:], wantTests)
+	prog, err := conf.Load()
+	if err != nil {
+		log.Fatal(err)
+	}
+
+	fmt.Printf("rest: %s\n", rest)
+	printProgram(prog)
+	// Output:
+	// rest: [foo bar]
+	// created: []
+	// imported: [errors runtime unicode/utf8]
+	// initial: [errors runtime unicode/utf8]
+	// all: [errors runtime unicode/utf8]
+}
+
+// This example creates and type-checks a single package (without tests)
+// from a list of filenames, and loads all of its dependencies.
+func ExampleConfig_CreateFromFilenames() {
+	var conf loader.Config
+	filename := filepath.Join(runtime.GOROOT(), "src/container/heap/heap.go")
+	conf.CreateFromFilenames("container/heap", filename)
+	prog, err := conf.Load()
+	if err != nil {
+		log.Fatal(err)
+	}
+
+	printProgram(prog)
+	// Output:
+	// created: [container/heap]
+	// imported: []
+	// initial: [container/heap]
+	// all: [container/heap sort]
+}
+
+// In the examples below, for stability, the chosen packages are
+// relatively small, platform-independent, and low-level (and thus
+// infrequently changing).
+// The strconv package has internal and external tests.
+
+const hello = `package main
+
+import "fmt"
+
+func main() {
+	fmt.Println("Hello, world.")
+}
+`
+
+// This example creates and type-checks a package from a list of
+// already-parsed files, and loads all its dependencies.
+func ExampleConfig_CreateFromFiles() {
+	var conf loader.Config
+	f, err := conf.ParseFile("hello.go", hello)
+	if err != nil {
+		log.Fatal(err)
+	}
+	conf.CreateFromFiles("hello", f)
+	prog, err := conf.Load()
+	if err != nil {
+		log.Fatal(err)
+	}
+
+	printProgram(prog)
+	printFilenames(prog.Fset, prog.Package("strconv"))
+	// Output:
+	// created: [hello]
+	// imported: []
+	// initial: [hello]
+	// all: [errors fmt hello io math os reflect runtime strconv sync sync/atomic syscall time unicode/utf8]
+	// strconv.Files: [atob.go atof.go atoi.go decimal.go extfloat.go ftoa.go isprint.go itoa.go quote.go]
+}
+
+// This example imports three packages, including the tests for one of
+// them, and loads all their dependencies.
+func ExampleConfig_Import() {
+	// ImportWithTest("strconv") causes strconv to include
+	// internal_test.go, and creates an external test package,
+	// strconv_test.
+	// (Compare with the example of CreateFromFiles.)
+
+	var conf loader.Config
+	conf.Import("unicode/utf8")
+	conf.Import("errors")
+	conf.ImportWithTests("strconv")
+	prog, err := conf.Load()
+	if err != nil {
+		log.Fatal(err)
+	}
+
+	printProgram(prog)
+	printFilenames(prog.Fset, prog.Package("strconv"))
+	printFilenames(prog.Fset, prog.Package("strconv_test"))
+	// Output:
+	// created: [strconv_test]
+	// imported: [errors strconv unicode/utf8]
+	// initial: [errors strconv strconv_test unicode/utf8]
+	// all: [bufio bytes errors flag fmt io math math/rand os reflect runtime runtime/pprof sort strconv strconv_test strings sync sync/atomic syscall testing text/tabwriter time unicode unicode/utf8]
+	// strconv.Files: [atob.go atof.go atoi.go decimal.go extfloat.go ftoa.go isprint.go itoa.go quote.go internal_test.go]
+	// strconv_test.Files: [atob_test.go atof_test.go atoi_test.go decimal_test.go fp_test.go ftoa_test.go itoa_test.go quote_example_test.go quote_test.go strconv_test.go]
+}
diff --git a/go/loader/example_test.go b/go/loader/example_test.go
new file mode 100644
index 0000000..ce5afdb
--- /dev/null
+++ b/go/loader/example_test.go
@@ -0,0 +1,173 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build go1.5
+// +build !windows
+
+package loader_test
+
+import (
+	"fmt"
+	"go/token"
+	"log"
+	"path/filepath"
+	"runtime"
+	"sort"
+
+	"golang.org/x/tools/go/loader"
+)
+
+func printProgram(prog *loader.Program) {
+	// Created packages are the initial packages specified by a call
+	// to CreateFromFilenames or CreateFromFiles.
+	var names []string
+	for _, info := range prog.Created {
+		names = append(names, info.Pkg.Path())
+	}
+	fmt.Printf("created: %s\n", names)
+
+	// Imported packages are the initial packages specified by a
+	// call to Import or ImportWithTests.
+	names = nil
+	for _, info := range prog.Imported {
+		names = append(names, info.Pkg.Path())
+	}
+	sort.Strings(names)
+	fmt.Printf("imported: %s\n", names)
+
+	// InitialPackages contains the union of created and imported.
+	names = nil
+	for _, info := range prog.InitialPackages() {
+		names = append(names, info.Pkg.Path())
+	}
+	sort.Strings(names)
+	fmt.Printf("initial: %s\n", names)
+
+	// AllPackages contains all initial packages and their dependencies.
+	names = nil
+	for pkg := range prog.AllPackages {
+		names = append(names, pkg.Path())
+	}
+	sort.Strings(names)
+	fmt.Printf("all: %s\n", names)
+}
+
+func printFilenames(fset *token.FileSet, info *loader.PackageInfo) {
+	var names []string
+	for _, f := range info.Files {
+		names = append(names, filepath.Base(fset.File(f.Pos()).Name()))
+	}
+	fmt.Printf("%s.Files: %s\n", info.Pkg.Path(), names)
+}
+
+// This example loads a set of packages and all of their dependencies
+// from a typical command-line.  FromArgs parses a command line and
+// makes calls to the other methods of Config shown in the examples that
+// follow.
+func ExampleConfig_FromArgs() {
+	args := []string{"mytool", "unicode/utf8", "errors", "runtime", "--", "foo", "bar"}
+	const wantTests = false
+
+	var conf loader.Config
+	rest, err := conf.FromArgs(args[1:], wantTests)
+	prog, err := conf.Load()
+	if err != nil {
+		log.Fatal(err)
+	}
+
+	fmt.Printf("rest: %s\n", rest)
+	printProgram(prog)
+	// Output:
+	// rest: [foo bar]
+	// created: []
+	// imported: [errors runtime unicode/utf8]
+	// initial: [errors runtime unicode/utf8]
+	// all: [errors runtime unicode/utf8]
+}
+
+// This example creates and type-checks a single package (without tests)
+// from a list of filenames, and loads all of its dependencies.
+func ExampleConfig_CreateFromFilenames() {
+	var conf loader.Config
+	filename := filepath.Join(runtime.GOROOT(), "src/container/heap/heap.go")
+	conf.CreateFromFilenames("container/heap", filename)
+	prog, err := conf.Load()
+	if err != nil {
+		log.Fatal(err)
+	}
+
+	printProgram(prog)
+	// Output:
+	// created: [container/heap]
+	// imported: []
+	// initial: [container/heap]
+	// all: [container/heap sort]
+}
+
+// In the examples below, for stability, the chosen packages are
+// relatively small, platform-independent, and low-level (and thus
+// infrequently changing).
+// The strconv package has internal and external tests.
+
+const hello = `package main
+
+import "fmt"
+
+func main() {
+	fmt.Println("Hello, world.")
+}
+`
+
+// This example creates and type-checks a package from a list of
+// already-parsed files, and loads all its dependencies.
+func ExampleConfig_CreateFromFiles() {
+	var conf loader.Config
+	f, err := conf.ParseFile("hello.go", hello)
+	if err != nil {
+		log.Fatal(err)
+	}
+	conf.CreateFromFiles("hello", f)
+	prog, err := conf.Load()
+	if err != nil {
+		log.Fatal(err)
+	}
+
+	printProgram(prog)
+	printFilenames(prog.Fset, prog.Package("strconv"))
+	// Output:
+	// created: [hello]
+	// imported: []
+	// initial: [hello]
+	// all: [errors fmt hello io math os reflect runtime strconv sync sync/atomic syscall time unicode/utf8]
+	// strconv.Files: [atob.go atof.go atoi.go decimal.go doc.go extfloat.go ftoa.go isprint.go itoa.go quote.go]
+}
+
+// This example imports three packages, including the tests for one of
+// them, and loads all their dependencies.
+func ExampleConfig_Import() {
+	// ImportWithTest("strconv") causes strconv to include
+	// internal_test.go, and creates an external test package,
+	// strconv_test.
+	// (Compare with the example of CreateFromFiles.)
+
+	var conf loader.Config
+	conf.Import("unicode/utf8")
+	conf.Import("errors")
+	conf.ImportWithTests("strconv")
+	prog, err := conf.Load()
+	if err != nil {
+		log.Fatal(err)
+	}
+
+	printProgram(prog)
+	printFilenames(prog.Fset, prog.Package("strconv"))
+	printFilenames(prog.Fset, prog.Package("strconv_test"))
+	// Output:
+	// created: [strconv_test]
+	// imported: [errors strconv unicode/utf8]
+	// initial: [errors strconv strconv_test unicode/utf8]
+	// all: [bufio bytes errors flag fmt io log math math/rand os reflect runtime runtime/pprof runtime/trace sort strconv strconv_test strings sync sync/atomic syscall testing text/tabwriter time unicode unicode/utf8]
+	// strconv.Files: [atob.go atof.go atoi.go decimal.go doc.go extfloat.go ftoa.go isprint.go itoa.go quote.go internal_test.go]
+	// strconv_test.Files: [atob_test.go atof_test.go atoi_test.go decimal_test.go example_test.go fp_test.go ftoa_test.go itoa_test.go quote_test.go strconv_test.go]
+}
diff --git a/go/loader/loader.go b/go/loader/loader.go
new file mode 100644
index 0000000..1d3ead0
--- /dev/null
+++ b/go/loader/loader.go
@@ -0,0 +1,968 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package loader
+
+// See doc.go for package documentation and implementation notes.
+
+import (
+	"errors"
+	"fmt"
+	"go/ast"
+	"go/build"
+	"go/parser"
+	"go/token"
+	"os"
+	"sort"
+	"strings"
+	"sync"
+	"time"
+
+	"golang.org/x/tools/go/ast/astutil"
+	"golang.org/x/tools/go/types"
+)
+
+const trace = false // show timing info for type-checking
+
+// Config specifies the configuration for loading a whole program from
+// Go source code.
+// The zero value for Config is a ready-to-use default configuration.
+type Config struct {
+	// Fset is the file set for the parser to use when loading the
+	// program.  If nil, it may be lazily initialized by any
+	// method of Config.
+	Fset *token.FileSet
+
+	// ParserMode specifies the mode to be used by the parser when
+	// loading source packages.
+	ParserMode parser.Mode
+
+	// TypeChecker contains options relating to the type checker.
+	//
+	// The supplied IgnoreFuncBodies is not used; the effective
+	// value comes from the TypeCheckFuncBodies func below.
+	// The supplied Import function is not used either.
+	TypeChecker types.Config
+
+	// TypeCheckFuncBodies is a predicate over package import
+	// paths.  A package for which the predicate is false will
+	// have its package-level declarations type checked, but not
+	// its function bodies; this can be used to quickly load
+	// dependencies from source.  If nil, all func bodies are type
+	// checked.
+	TypeCheckFuncBodies func(string) bool
+
+	// If Build is non-nil, it is used to locate source packages.
+	// Otherwise &build.Default is used.
+	//
+	// By default, cgo is invoked to preprocess Go files that
+	// import the fake package "C".  This behaviour can be
+	// disabled by setting CGO_ENABLED=0 in the environment prior
+	// to startup, or by setting Build.CgoEnabled=false.
+	Build *build.Context
+
+	// The current directory, used for resolving relative package
+	// references such as "./go/loader".  If empty, os.Getwd will be
+	// used instead.
+	Cwd string
+
+	// If DisplayPath is non-nil, it is used to transform each
+	// file name obtained from Build.Import().  This can be used
+	// to prevent a virtualized build.Config's file names from
+	// leaking into the user interface.
+	DisplayPath func(path string) string
+
+	// If AllowErrors is true, Load will return a Program even
+	// if some of the its packages contained I/O, parser or type
+	// errors; such errors are accessible via PackageInfo.Errors.  If
+	// false, Load will fail if any package had an error.
+	AllowErrors bool
+
+	// CreatePkgs specifies a list of non-importable initial
+	// packages to create.  The resulting packages will appear in
+	// the corresponding elements of the Program.Created slice.
+	CreatePkgs []PkgSpec
+
+	// ImportPkgs specifies a set of initial packages to load from
+	// source.  The map keys are package import paths, used to
+	// locate the package relative to $GOROOT.
+	//
+	// The map value indicates whether to load tests.  If true, Load
+	// will add and type-check two lists of files to the package:
+	// non-test files followed by in-package *_test.go files.  In
+	// addition, it will append the external test package (if any)
+	// to Program.Created.
+	ImportPkgs map[string]bool
+
+	// FindPackage is called during Load to create the build.Package
+	// for a given import path.  If nil, a default implementation
+	// based on ctxt.Import is used.  A client may use this hook to
+	// adapt to a proprietary build system that does not follow the
+	// "go build" layout conventions, for example.
+	//
+	// It must be safe to call concurrently from multiple goroutines.
+	FindPackage func(ctxt *build.Context, importPath string) (*build.Package, error)
+}
+
+// A PkgSpec specifies a non-importable package to be created by Load.
+// Files are processed first, but typically only one of Files and
+// Filenames is provided.  The path needn't be globally unique.
+//
+type PkgSpec struct {
+	Path      string      // import path ("" => use package declaration)
+	Files     []*ast.File // ASTs of already-parsed files
+	Filenames []string    // names of files to be parsed
+}
+
+// A Program is a Go program loaded from source as specified by a Config.
+type Program struct {
+	Fset *token.FileSet // the file set for this program
+
+	// Created[i] contains the initial package whose ASTs or
+	// filenames were supplied by Config.CreatePkgs[i], followed by
+	// the external test package, if any, of each package in
+	// Config.ImportPkgs ordered by ImportPath.
+	Created []*PackageInfo
+
+	// Imported contains the initially imported packages,
+	// as specified by Config.ImportPkgs.
+	Imported map[string]*PackageInfo
+
+	// AllPackages contains the PackageInfo of every package
+	// encountered by Load: all initial packages and all
+	// dependencies, including incomplete ones.
+	AllPackages map[*types.Package]*PackageInfo
+
+	// importMap is the canonical mapping of import paths to
+	// packages.  It contains all Imported initial packages, but not
+	// Created ones, and all imported dependencies.
+	importMap map[string]*types.Package
+}
+
+// PackageInfo holds the ASTs and facts derived by the type-checker
+// for a single package.
+//
+// Not mutated once exposed via the API.
+//
+type PackageInfo struct {
+	Pkg                   *types.Package
+	Importable            bool        // true if 'import "Pkg.Path()"' would resolve to this
+	TransitivelyErrorFree bool        // true if Pkg and all its dependencies are free of errors
+	Files                 []*ast.File // syntax trees for the package's files
+	Errors                []error     // non-nil if the package had errors
+	types.Info                        // type-checker deductions.
+
+	checker   *types.Checker // transient type-checker state
+	errorFunc func(error)
+}
+
+func (info *PackageInfo) String() string { return info.Pkg.Path() }
+
+func (info *PackageInfo) appendError(err error) {
+	if info.errorFunc != nil {
+		info.errorFunc(err)
+	} else {
+		fmt.Fprintln(os.Stderr, err)
+	}
+	info.Errors = append(info.Errors, err)
+}
+
+func (conf *Config) fset() *token.FileSet {
+	if conf.Fset == nil {
+		conf.Fset = token.NewFileSet()
+	}
+	return conf.Fset
+}
+
+// ParseFile is a convenience function (intended for testing) that invokes
+// the parser using the Config's FileSet, which is initialized if nil.
+//
+// src specifies the parser input as a string, []byte, or io.Reader, and
+// filename is its apparent name.  If src is nil, the contents of
+// filename are read from the file system.
+//
+func (conf *Config) ParseFile(filename string, src interface{}) (*ast.File, error) {
+	// TODO(adonovan): use conf.build() etc like parseFiles does.
+	return parser.ParseFile(conf.fset(), filename, src, conf.ParserMode)
+}
+
+// FromArgsUsage is a partial usage message that applications calling
+// FromArgs may wish to include in their -help output.
+const FromArgsUsage = `
+<args> is a list of arguments denoting a set of initial packages.
+It may take one of two forms:
+
+1. A list of *.go source files.
+
+   All of the specified files are loaded, parsed and type-checked
+   as a single package.  All the files must belong to the same directory.
+
+2. A list of import paths, each denoting a package.
+
+   The package's directory is found relative to the $GOROOT and
+   $GOPATH using similar logic to 'go build', and the *.go files in
+   that directory are loaded, parsed and type-checked as a single
+   package.
+
+   In addition, all *_test.go files in the directory are then loaded
+   and parsed.  Those files whose package declaration equals that of
+   the non-*_test.go files are included in the primary package.  Test
+   files whose package declaration ends with "_test" are type-checked
+   as another package, the 'external' test package, so that a single
+   import path may denote two packages.  (Whether this behaviour is
+   enabled is tool-specific, and may depend on additional flags.)
+
+A '--' argument terminates the list of packages.
+`
+
+// FromArgs interprets args as a set of initial packages to load from
+// source and updates the configuration.  It returns the list of
+// unconsumed arguments.
+//
+// It is intended for use in command-line interfaces that require a
+// set of initial packages to be specified; see FromArgsUsage message
+// for details.
+//
+// Only superficial errors are reported at this stage; errors dependent
+// on I/O are detected during Load.
+//
+func (conf *Config) FromArgs(args []string, xtest bool) ([]string, error) {
+	var rest []string
+	for i, arg := range args {
+		if arg == "--" {
+			rest = args[i+1:]
+			args = args[:i]
+			break // consume "--" and return the remaining args
+		}
+	}
+
+	if len(args) > 0 && strings.HasSuffix(args[0], ".go") {
+		// Assume args is a list of a *.go files
+		// denoting a single ad hoc package.
+		for _, arg := range args {
+			if !strings.HasSuffix(arg, ".go") {
+				return nil, fmt.Errorf("named files must be .go files: %s", arg)
+			}
+		}
+		conf.CreateFromFilenames("", args...)
+	} else {
+		// Assume args are directories each denoting a
+		// package and (perhaps) an external test, iff xtest.
+		for _, arg := range args {
+			if xtest {
+				conf.ImportWithTests(arg)
+			} else {
+				conf.Import(arg)
+			}
+		}
+	}
+
+	return rest, nil
+}
+
+// CreateFromFilenames is a convenience function that adds
+// a conf.CreatePkgs entry to create a package of the specified *.go
+// files.
+//
+func (conf *Config) CreateFromFilenames(path string, filenames ...string) {
+	conf.CreatePkgs = append(conf.CreatePkgs, PkgSpec{Path: path, Filenames: filenames})
+}
+
+// CreateFromFiles is a convenience function that adds a conf.CreatePkgs
+// entry to create package of the specified path and parsed files.
+//
+func (conf *Config) CreateFromFiles(path string, files ...*ast.File) {
+	conf.CreatePkgs = append(conf.CreatePkgs, PkgSpec{Path: path, Files: files})
+}
+
+// ImportWithTests is a convenience function that adds path to
+// ImportPkgs, the set of initial source packages located relative to
+// $GOPATH.  The package will be augmented by any *_test.go files in
+// its directory that contain a "package x" (not "package x_test")
+// declaration.
+//
+// In addition, if any *_test.go files contain a "package x_test"
+// declaration, an additional package comprising just those files will
+// be added to CreatePkgs.
+//
+func (conf *Config) ImportWithTests(path string) { conf.addImport(path, true) }
+
+// Import is a convenience function that adds path to ImportPkgs, the
+// set of initial packages that will be imported from source.
+//
+func (conf *Config) Import(path string) { conf.addImport(path, false) }
+
+func (conf *Config) addImport(path string, tests bool) {
+	if path == "C" || path == "unsafe" {
+		return // ignore; not a real package
+	}
+	if conf.ImportPkgs == nil {
+		conf.ImportPkgs = make(map[string]bool)
+	}
+	conf.ImportPkgs[path] = conf.ImportPkgs[path] || tests
+}
+
+// PathEnclosingInterval returns the PackageInfo and ast.Node that
+// contain source interval [start, end), and all the node's ancestors
+// up to the AST root.  It searches all ast.Files of all packages in prog.
+// exact is defined as for astutil.PathEnclosingInterval.
+//
+// The zero value is returned if not found.
+//
+func (prog *Program) PathEnclosingInterval(start, end token.Pos) (pkg *PackageInfo, path []ast.Node, exact bool) {
+	for _, info := range prog.AllPackages {
+		for _, f := range info.Files {
+			if f.Pos() == token.NoPos {
+				// This can happen if the parser saw
+				// too many errors and bailed out.
+				// (Use parser.AllErrors to prevent that.)
+				continue
+			}
+			if !tokenFileContainsPos(prog.Fset.File(f.Pos()), start) {
+				continue
+			}
+			if path, exact := astutil.PathEnclosingInterval(f, start, end); path != nil {
+				return info, path, exact
+			}
+		}
+	}
+	return nil, nil, false
+}
+
+// InitialPackages returns a new slice containing the set of initial
+// packages (Created + Imported) in unspecified order.
+//
+func (prog *Program) InitialPackages() []*PackageInfo {
+	infos := make([]*PackageInfo, 0, len(prog.Created)+len(prog.Imported))
+	infos = append(infos, prog.Created...)
+	for _, info := range prog.Imported {
+		infos = append(infos, info)
+	}
+	return infos
+}
+
+// Package returns the ASTs and results of type checking for the
+// specified package.
+func (prog *Program) Package(path string) *PackageInfo {
+	if info, ok := prog.AllPackages[prog.importMap[path]]; ok {
+		return info
+	}
+	for _, info := range prog.Created {
+		if path == info.Pkg.Path() {
+			return info
+		}
+	}
+	return nil
+}
+
+// ---------- Implementation ----------
+
+// importer holds the working state of the algorithm.
+type importer struct {
+	conf  *Config   // the client configuration
+	start time.Time // for logging
+
+	progMu sync.Mutex // guards prog
+	prog   *Program   // the resulting program
+
+	importedMu sync.Mutex             // guards imported
+	imported   map[string]*importInfo // all imported packages (incl. failures) by import path
+
+	// import dependency graph: graph[x][y] => x imports y
+	//
+	// Since non-importable packages cannot be cyclic, we ignore
+	// their imports, thus we only need the subgraph over importable
+	// packages.  Nodes are identified by their import paths.
+	graphMu sync.Mutex
+	graph   map[string]map[string]bool
+}
+
+// importInfo tracks the success or failure of a single import.
+//
+// Upon completion, exactly one of info and err is non-nil:
+// info on successful creation of a package, err otherwise.
+// A successful package may still contain type errors.
+//
+type importInfo struct {
+	path     string       // import path
+	mu       sync.Mutex   // guards the following fields prior to completion
+	info     *PackageInfo // results of typechecking (including errors)
+	err      error        // reason for failure to create a package
+	complete sync.Cond    // complete condition is that one of info, err is non-nil.
+}
+
+// awaitCompletion blocks until ii is complete,
+// i.e. the info and err fields are safe to inspect without a lock.
+// It is concurrency-safe and idempotent.
+func (ii *importInfo) awaitCompletion() {
+	ii.mu.Lock()
+	for ii.info == nil && ii.err == nil {
+		ii.complete.Wait()
+	}
+	ii.mu.Unlock()
+}
+
+// Complete marks ii as complete.
+// Its info and err fields will not be subsequently updated.
+func (ii *importInfo) Complete(info *PackageInfo, err error) {
+	if info == nil && err == nil {
+		panic("Complete(nil, nil)")
+	}
+	ii.mu.Lock()
+	ii.info = info
+	ii.err = err
+	ii.complete.Broadcast()
+	ii.mu.Unlock()
+}
+
+// Load creates the initial packages specified by conf.{Create,Import}Pkgs,
+// loading their dependencies packages as needed.
+//
+// On success, Load returns a Program containing a PackageInfo for
+// each package.  On failure, it returns an error.
+//
+// If AllowErrors is true, Load will return a Program even if some
+// packages contained I/O, parser or type errors, or if dependencies
+// were missing.  (Such errors are accessible via PackageInfo.Errors.  If
+// false, Load will fail if any package had an error.
+//
+// It is an error if no packages were loaded.
+//
+func (conf *Config) Load() (*Program, error) {
+	// Create a simple default error handler for parse/type errors.
+	if conf.TypeChecker.Error == nil {
+		conf.TypeChecker.Error = func(e error) { fmt.Fprintln(os.Stderr, e) }
+	}
+
+	// Set default working directory for relative package references.
+	if conf.Cwd == "" {
+		var err error
+		conf.Cwd, err = os.Getwd()
+		if err != nil {
+			return nil, err
+		}
+	}
+
+	// Install default FindPackage hook using go/build logic.
+	if conf.FindPackage == nil {
+		conf.FindPackage = func(ctxt *build.Context, path string) (*build.Package, error) {
+			// TODO(adonovan): cache calls to build.Import
+			// so we don't do it three times per test package.
+			ioLimit <- true
+			bp, err := ctxt.Import(path, conf.Cwd, 0)
+			<-ioLimit
+			if _, ok := err.(*build.NoGoError); ok {
+				return bp, nil // empty directory is not an error
+			}
+			return bp, err
+		}
+	}
+
+	prog := &Program{
+		Fset:        conf.fset(),
+		Imported:    make(map[string]*PackageInfo),
+		importMap:   make(map[string]*types.Package),
+		AllPackages: make(map[*types.Package]*PackageInfo),
+	}
+
+	imp := importer{
+		conf:     conf,
+		prog:     prog,
+		imported: make(map[string]*importInfo),
+		start:    time.Now(),
+		graph:    make(map[string]map[string]bool),
+	}
+
+	// -- loading proper (concurrent phase) --------------------------------
+
+	var errpkgs []string // packages that contained errors
+
+	// Load the initially imported packages and their dependencies,
+	// in parallel.
+	for _, ii := range imp.loadAll("", conf.ImportPkgs) {
+		if ii.err != nil {
+			conf.TypeChecker.Error(ii.err) // failed to create package
+			errpkgs = append(errpkgs, ii.path)
+			continue
+		}
+		prog.Imported[ii.info.Pkg.Path()] = ii.info
+	}
+
+	// Augment the designated initial packages by their tests.
+	// Dependencies are loaded in parallel.
+	var xtestPkgs []*build.Package
+	for path, augment := range conf.ImportPkgs {
+		if !augment {
+			continue
+		}
+
+		bp, err := conf.FindPackage(conf.build(), path)
+		if err != nil {
+			// Package not found, or can't even parse package declaration.
+			// Already reported by previous loop; ignore it.
+			continue
+		}
+
+		// Needs external test package?
+		if len(bp.XTestGoFiles) > 0 {
+			xtestPkgs = append(xtestPkgs, bp)
+		}
+
+		imp.importedMu.Lock() // (unnecessary, we're sequential here)
+		ii, ok := imp.imported[path]
+		// Paranoid checks added due to issue #11012.
+		if !ok {
+			// Unreachable.
+			// The previous loop called loadAll and thus
+			// startLoad for each path in ImportPkgs, which
+			// populates imp.imported[path] with a non-zero value.
+			panic(fmt.Sprintf("imported[%q] not found", path))
+		}
+		if ii == nil {
+			// Unreachable.
+			// The ii values in this loop are the same as in
+			// the previous loop, which enforced the invariant
+			// that at least one of ii.err and ii.info is non-nil.
+			panic(fmt.Sprintf("imported[%q] == nil", path))
+		}
+		if ii.err != nil {
+			// The sole possible cause is failure of the
+			// FindPackage call in (*importer).load,
+			// but we rechecked that condition above.
+			// Perhaps the state of the file system changed
+			// in between?  Seems unlikely.
+			panic(fmt.Sprintf("imported[%q].err = %v", path, ii.err))
+		}
+		if ii.info == nil {
+			// Unreachable.
+			// Complete has this postcondition:
+			// 	ii.err != nil || ii.info != nil
+			// and we know that ii.err == nil here.
+			panic(fmt.Sprintf("imported[%q].info = nil", path))
+		}
+		info := ii.info
+		imp.importedMu.Unlock()
+
+		// Parse the in-package test files.
+		files, errs := imp.conf.parsePackageFiles(bp, 't')
+		for _, err := range errs {
+			info.appendError(err)
+		}
+
+		// The test files augmenting package P cannot be imported,
+		// but may import packages that import P,
+		// so we must disable the cycle check.
+		imp.addFiles(info, files, false)
+	}
+
+	createPkg := func(path string, files []*ast.File, errs []error) {
+		info := imp.newPackageInfo(path)
+		for _, err := range errs {
+			info.appendError(err)
+		}
+
+		// Ad hoc packages are non-importable,
+		// so no cycle check is needed.
+		// addFiles loads dependencies in parallel.
+		imp.addFiles(info, files, false)
+		prog.Created = append(prog.Created, info)
+	}
+
+	// Create packages specified by conf.CreatePkgs.
+	for _, cp := range conf.CreatePkgs {
+		files, errs := parseFiles(conf.fset(), conf.build(), nil, ".", cp.Filenames, conf.ParserMode)
+		files = append(files, cp.Files...)
+
+		path := cp.Path
+		if path == "" {
+			if len(files) > 0 {
+				path = files[0].Name.Name
+			} else {
+				path = "(unnamed)"
+			}
+		}
+		createPkg(path, files, errs)
+	}
+
+	// Create external test packages.
+	sort.Sort(byImportPath(xtestPkgs))
+	for _, bp := range xtestPkgs {
+		files, errs := imp.conf.parsePackageFiles(bp, 'x')
+		createPkg(bp.ImportPath+"_test", files, errs)
+	}
+
+	// -- finishing up (sequential) ----------------------------------------
+
+	if len(prog.Imported)+len(prog.Created) == 0 {
+		return nil, errors.New("no initial packages were loaded")
+	}
+
+	// Create infos for indirectly imported packages.
+	// e.g. incomplete packages without syntax, loaded from export data.
+	for _, obj := range prog.importMap {
+		info := prog.AllPackages[obj]
+		if info == nil {
+			prog.AllPackages[obj] = &PackageInfo{Pkg: obj, Importable: true}
+		} else {
+			// finished
+			info.checker = nil
+			info.errorFunc = nil
+		}
+	}
+
+	if !conf.AllowErrors {
+		// Report errors in indirectly imported packages.
+		for _, info := range prog.AllPackages {
+			if len(info.Errors) > 0 {
+				errpkgs = append(errpkgs, info.Pkg.Path())
+			}
+		}
+		if errpkgs != nil {
+			var more string
+			if len(errpkgs) > 3 {
+				more = fmt.Sprintf(" and %d more", len(errpkgs)-3)
+				errpkgs = errpkgs[:3]
+			}
+			return nil, fmt.Errorf("couldn't load packages due to errors: %s%s",
+				strings.Join(errpkgs, ", "), more)
+		}
+	}
+
+	markErrorFreePackages(prog.AllPackages)
+
+	return prog, nil
+}
+
+type byImportPath []*build.Package
+
+func (b byImportPath) Len() int           { return len(b) }
+func (b byImportPath) Less(i, j int) bool { return b[i].ImportPath < b[j].ImportPath }
+func (b byImportPath) Swap(i, j int)      { b[i], b[j] = b[j], b[i] }
+
+// markErrorFreePackages sets the TransitivelyErrorFree flag on all
+// applicable packages.
+func markErrorFreePackages(allPackages map[*types.Package]*PackageInfo) {
+	// Build the transpose of the import graph.
+	importedBy := make(map[*types.Package]map[*types.Package]bool)
+	for P := range allPackages {
+		for _, Q := range P.Imports() {
+			clients, ok := importedBy[Q]
+			if !ok {
+				clients = make(map[*types.Package]bool)
+				importedBy[Q] = clients
+			}
+			clients[P] = true
+		}
+	}
+
+	// Find all packages reachable from some error package.
+	reachable := make(map[*types.Package]bool)
+	var visit func(*types.Package)
+	visit = func(p *types.Package) {
+		if !reachable[p] {
+			reachable[p] = true
+			for q := range importedBy[p] {
+				visit(q)
+			}
+		}
+	}
+	for _, info := range allPackages {
+		if len(info.Errors) > 0 {
+			visit(info.Pkg)
+		}
+	}
+
+	// Mark the others as "transitively error-free".
+	for _, info := range allPackages {
+		if !reachable[info.Pkg] {
+			info.TransitivelyErrorFree = true
+		}
+	}
+}
+
+// build returns the effective build context.
+func (conf *Config) build() *build.Context {
+	if conf.Build != nil {
+		return conf.Build
+	}
+	return &build.Default
+}
+
+// parsePackageFiles enumerates the files belonging to package path,
+// then loads, parses and returns them, plus a list of I/O or parse
+// errors that were encountered.
+//
+// 'which' indicates which files to include:
+//    'g': include non-test *.go source files (GoFiles + processed CgoFiles)
+//    't': include in-package *_test.go source files (TestGoFiles)
+//    'x': include external *_test.go source files. (XTestGoFiles)
+//
+func (conf *Config) parsePackageFiles(bp *build.Package, which rune) ([]*ast.File, []error) {
+	var filenames []string
+	switch which {
+	case 'g':
+		filenames = bp.GoFiles
+	case 't':
+		filenames = bp.TestGoFiles
+	case 'x':
+		filenames = bp.XTestGoFiles
+	default:
+		panic(which)
+	}
+
+	files, errs := parseFiles(conf.fset(), conf.build(), conf.DisplayPath, bp.Dir, filenames, conf.ParserMode)
+
+	// Preprocess CgoFiles and parse the outputs (sequentially).
+	if which == 'g' && bp.CgoFiles != nil {
+		cgofiles, err := processCgoFiles(bp, conf.fset(), conf.DisplayPath, conf.ParserMode)
+		if err != nil {
+			errs = append(errs, err)
+		} else {
+			files = append(files, cgofiles...)
+		}
+	}
+
+	return files, errs
+}
+
+// doImport imports the package denoted by path.
+// It implements the types.Importer signature.
+//
+// imports is the type-checker's package canonicalization map.
+//
+// It returns an error if a package could not be created
+// (e.g. go/build or parse error), but type errors are reported via
+// the types.Config.Error callback (the first of which is also saved
+// in the package's PackageInfo).
+//
+// Idempotent.
+//
+func (imp *importer) doImport(from *PackageInfo, to string) (*types.Package, error) {
+	// Package unsafe is handled specially, and has no PackageInfo.
+	// TODO(adonovan): move this check into go/types?
+	if to == "unsafe" {
+		return types.Unsafe, nil
+	}
+	if to == "C" {
+		// This should be unreachable, but ad hoc packages are
+		// not currently subject to cgo preprocessing.
+		// See https://github.com/golang/go/issues/11627.
+		return nil, fmt.Errorf(`the loader doesn't cgo-process ad hoc packages like %q; see Go issue 11627`,
+			from.Pkg.Path())
+	}
+
+	imp.importedMu.Lock()
+	ii := imp.imported[to]
+	imp.importedMu.Unlock()
+	if ii == nil {
+		panic("internal error: unexpected import: " + to)
+	}
+	if ii.err != nil {
+		return nil, ii.err
+	}
+	if ii.info != nil {
+		return ii.info.Pkg, nil
+	}
+
+	// Import of incomplete package: this indicates a cycle.
+	fromPath := from.Pkg.Path()
+	if cycle := imp.findPath(to, fromPath); cycle != nil {
+		cycle = append([]string{fromPath}, cycle...)
+		return nil, fmt.Errorf("import cycle: %s", strings.Join(cycle, " -> "))
+	}
+
+	panic("internal error: import of incomplete (yet acyclic) package: " + fromPath)
+}
+
+// loadAll loads, parses, and type-checks the specified packages in
+// parallel and returns their completed importInfos in unspecified order.
+//
+// fromPath is the import path of the importing package, if it is
+// importable, "" otherwise.  It is used for cycle detection.
+//
+func (imp *importer) loadAll(fromPath string, paths map[string]bool) []*importInfo {
+	result := make([]*importInfo, 0, len(paths))
+	for path := range paths {
+		result = append(result, imp.startLoad(path))
+	}
+
+	if fromPath != "" {
+		// We're loading a set of imports.
+		//
+		// We must record graph edges from the importing package
+		// to its dependencies, and check for cycles.
+		imp.graphMu.Lock()
+		deps, ok := imp.graph[fromPath]
+		if !ok {
+			deps = make(map[string]bool)
+			imp.graph[fromPath] = deps
+		}
+		for path := range paths {
+			deps[path] = true
+		}
+		imp.graphMu.Unlock()
+	}
+
+	for _, ii := range result {
+		if fromPath != "" {
+			if cycle := imp.findPath(ii.path, fromPath); cycle != nil {
+				// Cycle-forming import: we must not await its
+				// completion since it would deadlock.
+				//
+				// We don't record the error in ii since
+				// the error is really associated with the
+				// cycle-forming edge, not the package itself.
+				// (Also it would complicate the
+				// invariants of importPath completion.)
+				if trace {
+					fmt.Fprintln(os.Stderr, "import cycle: %q", cycle)
+				}
+				continue
+			}
+		}
+		ii.awaitCompletion()
+	}
+	return result
+}
+
+// findPath returns an arbitrary path from 'from' to 'to' in the import
+// graph, or nil if there was none.
+func (imp *importer) findPath(from, to string) []string {
+	imp.graphMu.Lock()
+	defer imp.graphMu.Unlock()
+
+	seen := make(map[string]bool)
+	var search func(stack []string, importPath string) []string
+	search = func(stack []string, importPath string) []string {
+		if !seen[importPath] {
+			seen[importPath] = true
+			stack = append(stack, importPath)
+			if importPath == to {
+				return stack
+			}
+			for x := range imp.graph[importPath] {
+				if p := search(stack, x); p != nil {
+					return p
+				}
+			}
+		}
+		return nil
+	}
+	return search(make([]string, 0, 20), from)
+}
+
+// startLoad initiates the loading, parsing and type-checking of the
+// specified package and its dependencies, if it has not already begun.
+//
+// It returns an importInfo, not necessarily in a completed state.  The
+// caller must call awaitCompletion() before accessing its info and err
+// fields.
+//
+// startLoad is concurrency-safe and idempotent.
+//
+func (imp *importer) startLoad(path string) *importInfo {
+	imp.importedMu.Lock()
+	ii, ok := imp.imported[path]
+	if !ok {
+		ii = &importInfo{path: path}
+		ii.complete.L = &ii.mu
+		imp.imported[path] = ii
+		go func() {
+			ii.Complete(imp.load(path))
+		}()
+	}
+	imp.importedMu.Unlock()
+
+	return ii
+}
+
+// load implements package loading by parsing Go source files
+// located by go/build.
+//
+func (imp *importer) load(path string) (*PackageInfo, error) {
+	bp, err := imp.conf.FindPackage(imp.conf.build(), path)
+	if err != nil {
+		return nil, err // package not found
+	}
+	info := imp.newPackageInfo(bp.ImportPath)
+	info.Importable = true
+	files, errs := imp.conf.parsePackageFiles(bp, 'g')
+	for _, err := range errs {
+		info.appendError(err)
+	}
+
+	imp.addFiles(info, files, true)
+
+	imp.progMu.Lock()
+	imp.prog.importMap[path] = info.Pkg
+	imp.progMu.Unlock()
+
+	return info, nil
+}
+
+// addFiles adds and type-checks the specified files to info, loading
+// their dependencies if needed.  The order of files determines the
+// package initialization order.  It may be called multiple times on the
+// same package.  Errors are appended to the info.Errors field.
+//
+// cycleCheck determines whether the imports within files create
+// dependency edges that should be checked for potential cycles.
+//
+func (imp *importer) addFiles(info *PackageInfo, files []*ast.File, cycleCheck bool) {
+	info.Files = append(info.Files, files...)
+
+	// Ensure the dependencies are loaded, in parallel.
+	var fromPath string
+	if cycleCheck {
+		fromPath = info.Pkg.Path()
+	}
+	imp.loadAll(fromPath, scanImports(files))
+
+	if trace {
+		fmt.Fprintf(os.Stderr, "%s: start %q (%d)\n",
+			time.Since(imp.start), info.Pkg.Path(), len(files))
+	}
+
+	// Ignore the returned (first) error since we
+	// already collect them all in the PackageInfo.
+	info.checker.Files(files)
+
+	if trace {
+		fmt.Fprintf(os.Stderr, "%s: stop %q\n",
+			time.Since(imp.start), info.Pkg.Path())
+	}
+}
+
+func (imp *importer) newPackageInfo(path string) *PackageInfo {
+	pkg := types.NewPackage(path, "")
+	info := &PackageInfo{
+		Pkg: pkg,
+		Info: types.Info{
+			Types:      make(map[ast.Expr]types.TypeAndValue),
+			Defs:       make(map[*ast.Ident]types.Object),
+			Uses:       make(map[*ast.Ident]types.Object),
+			Implicits:  make(map[ast.Node]types.Object),
+			Scopes:     make(map[ast.Node]*types.Scope),
+			Selections: make(map[*ast.SelectorExpr]*types.Selection),
+		},
+		errorFunc: imp.conf.TypeChecker.Error,
+	}
+
+	// Copy the types.Config so we can vary it across PackageInfos.
+	tc := imp.conf.TypeChecker
+	tc.IgnoreFuncBodies = false
+	if f := imp.conf.TypeCheckFuncBodies; f != nil {
+		tc.IgnoreFuncBodies = !f(path)
+	}
+	tc.Import = func(_ map[string]*types.Package, to string) (*types.Package, error) {
+		return imp.doImport(info, to)
+	}
+	tc.Error = info.appendError // appendError wraps the user's Error function
+
+	info.checker = types.NewChecker(&tc, imp.conf.fset(), pkg, &info.Info)
+	imp.progMu.Lock()
+	imp.prog.AllPackages[pkg] = info
+	imp.progMu.Unlock()
+	return info
+}
diff --git a/go/loader/loader_test.go b/go/loader/loader_test.go
new file mode 100644
index 0000000..602590e
--- /dev/null
+++ b/go/loader/loader_test.go
@@ -0,0 +1,674 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// No testdata on Android.
+
+// +build !android
+
+package loader_test
+
+import (
+	"fmt"
+	"go/build"
+	"path/filepath"
+	"reflect"
+	"sort"
+	"strings"
+	"sync"
+	"testing"
+
+	"golang.org/x/tools/go/buildutil"
+	"golang.org/x/tools/go/loader"
+)
+
+// TestFromArgs checks that conf.FromArgs populates conf correctly.
+// It does no I/O.
+func TestFromArgs(t *testing.T) {
+	type result struct {
+		Err        string
+		Rest       []string
+		ImportPkgs map[string]bool
+		CreatePkgs []loader.PkgSpec
+	}
+	for _, test := range []struct {
+		args  []string
+		tests bool
+		want  result
+	}{
+		// Mix of existing and non-existent packages.
+		{
+			args: []string{"nosuchpkg", "errors"},
+			want: result{
+				ImportPkgs: map[string]bool{"errors": false, "nosuchpkg": false},
+			},
+		},
+		// Same, with -test flag.
+		{
+			args:  []string{"nosuchpkg", "errors"},
+			tests: true,
+			want: result{
+				ImportPkgs: map[string]bool{"errors": true, "nosuchpkg": true},
+			},
+		},
+		// Surplus arguments.
+		{
+			args: []string{"fmt", "errors", "--", "surplus"},
+			want: result{
+				Rest:       []string{"surplus"},
+				ImportPkgs: map[string]bool{"errors": false, "fmt": false},
+			},
+		},
+		// Ad hoc package specified as *.go files.
+		{
+			args: []string{"foo.go", "bar.go"},
+			want: result{CreatePkgs: []loader.PkgSpec{{
+				Filenames: []string{"foo.go", "bar.go"},
+			}}},
+		},
+		// Mixture of *.go and import paths.
+		{
+			args: []string{"foo.go", "fmt"},
+			want: result{
+				Err: "named files must be .go files: fmt",
+			},
+		},
+	} {
+		var conf loader.Config
+		rest, err := conf.FromArgs(test.args, test.tests)
+		got := result{
+			Rest:       rest,
+			ImportPkgs: conf.ImportPkgs,
+			CreatePkgs: conf.CreatePkgs,
+		}
+		if err != nil {
+			got.Err = err.Error()
+		}
+		if !reflect.DeepEqual(got, test.want) {
+			t.Errorf("FromArgs(%q) = %+v, want %+v", test.args, got, test.want)
+		}
+	}
+}
+
+func TestLoad_NoInitialPackages(t *testing.T) {
+	var conf loader.Config
+
+	const wantErr = "no initial packages were loaded"
+
+	prog, err := conf.Load()
+	if err == nil {
+		t.Errorf("Load succeeded unexpectedly, want %q", wantErr)
+	} else if err.Error() != wantErr {
+		t.Errorf("Load failed with wrong error %q, want %q", err, wantErr)
+	}
+	if prog != nil {
+		t.Errorf("Load unexpectedly returned a Program")
+	}
+}
+
+func TestLoad_MissingInitialPackage(t *testing.T) {
+	var conf loader.Config
+	conf.Import("nosuchpkg")
+	conf.Import("errors")
+
+	const wantErr = "couldn't load packages due to errors: nosuchpkg"
+
+	prog, err := conf.Load()
+	if err == nil {
+		t.Errorf("Load succeeded unexpectedly, want %q", wantErr)
+	} else if err.Error() != wantErr {
+		t.Errorf("Load failed with wrong error %q, want %q", err, wantErr)
+	}
+	if prog != nil {
+		t.Errorf("Load unexpectedly returned a Program")
+	}
+}
+
+func TestLoad_MissingInitialPackage_AllowErrors(t *testing.T) {
+	var conf loader.Config
+	conf.AllowErrors = true
+	conf.Import("nosuchpkg")
+	conf.ImportWithTests("errors")
+
+	prog, err := conf.Load()
+	if err != nil {
+		t.Errorf("Load failed unexpectedly: %v", err)
+	}
+	if prog == nil {
+		t.Fatalf("Load returned a nil Program")
+	}
+	if got, want := created(prog), "errors_test"; got != want {
+		t.Errorf("Created = %s, want %s", got, want)
+	}
+	if got, want := imported(prog), "errors"; got != want {
+		t.Errorf("Imported = %s, want %s", got, want)
+	}
+}
+
+func TestCreateUnnamedPackage(t *testing.T) {
+	var conf loader.Config
+	conf.CreateFromFilenames("")
+	prog, err := conf.Load()
+	if err != nil {
+		t.Fatalf("Load failed: %v", err)
+	}
+	if got, want := fmt.Sprint(prog.InitialPackages()), "[(unnamed)]"; got != want {
+		t.Errorf("InitialPackages = %s, want %s", got, want)
+	}
+}
+
+func TestLoad_MissingFileInCreatedPackage(t *testing.T) {
+	var conf loader.Config
+	conf.CreateFromFilenames("", "missing.go")
+
+	const wantErr = "couldn't load packages due to errors: (unnamed)"
+
+	prog, err := conf.Load()
+	if prog != nil {
+		t.Errorf("Load unexpectedly returned a Program")
+	}
+	if err == nil {
+		t.Fatalf("Load succeeded unexpectedly, want %q", wantErr)
+	}
+	if err.Error() != wantErr {
+		t.Fatalf("Load failed with wrong error %q, want %q", err, wantErr)
+	}
+}
+
+func TestLoad_MissingFileInCreatedPackage_AllowErrors(t *testing.T) {
+	conf := loader.Config{AllowErrors: true}
+	conf.CreateFromFilenames("", "missing.go")
+
+	prog, err := conf.Load()
+	if err != nil {
+		t.Errorf("Load failed: %v", err)
+	}
+	if got, want := fmt.Sprint(prog.InitialPackages()), "[(unnamed)]"; got != want {
+		t.Fatalf("InitialPackages = %s, want %s", got, want)
+	}
+}
+
+func TestLoad_ParseError(t *testing.T) {
+	var conf loader.Config
+	conf.CreateFromFilenames("badpkg", "testdata/badpkgdecl.go")
+
+	const wantErr = "couldn't load packages due to errors: badpkg"
+
+	prog, err := conf.Load()
+	if prog != nil {
+		t.Errorf("Load unexpectedly returned a Program")
+	}
+	if err == nil {
+		t.Fatalf("Load succeeded unexpectedly, want %q", wantErr)
+	}
+	if err.Error() != wantErr {
+		t.Fatalf("Load failed with wrong error %q, want %q", err, wantErr)
+	}
+}
+
+func TestLoad_ParseError_AllowErrors(t *testing.T) {
+	var conf loader.Config
+	conf.AllowErrors = true
+	conf.CreateFromFilenames("badpkg", "testdata/badpkgdecl.go")
+
+	prog, err := conf.Load()
+	if err != nil {
+		t.Errorf("Load failed unexpectedly: %v", err)
+	}
+	if prog == nil {
+		t.Fatalf("Load returned a nil Program")
+	}
+	if got, want := created(prog), "badpkg"; got != want {
+		t.Errorf("Created = %s, want %s", got, want)
+	}
+
+	badpkg := prog.Created[0]
+	if len(badpkg.Files) != 1 {
+		t.Errorf("badpkg has %d files, want 1", len(badpkg.Files))
+	}
+	wantErr := filepath.Join("testdata", "badpkgdecl.go") + ":1:34: expected 'package', found 'EOF'"
+	if !hasError(badpkg.Errors, wantErr) {
+		t.Errorf("badpkg.Errors = %v, want %s", badpkg.Errors, wantErr)
+	}
+}
+
+func TestLoad_FromSource_Success(t *testing.T) {
+	var conf loader.Config
+	conf.CreateFromFilenames("P", "testdata/a.go", "testdata/b.go")
+
+	prog, err := conf.Load()
+	if err != nil {
+		t.Errorf("Load failed unexpectedly: %v", err)
+	}
+	if prog == nil {
+		t.Fatalf("Load returned a nil Program")
+	}
+	if got, want := created(prog), "P"; got != want {
+		t.Errorf("Created = %s, want %s", got, want)
+	}
+}
+
+func TestLoad_FromImports_Success(t *testing.T) {
+	var conf loader.Config
+	conf.ImportWithTests("fmt")
+	conf.ImportWithTests("errors")
+
+	prog, err := conf.Load()
+	if err != nil {
+		t.Errorf("Load failed unexpectedly: %v", err)
+	}
+	if prog == nil {
+		t.Fatalf("Load returned a nil Program")
+	}
+	if got, want := created(prog), "errors_test fmt_test"; got != want {
+		t.Errorf("Created = %q, want %s", got, want)
+	}
+	if got, want := imported(prog), "errors fmt"; got != want {
+		t.Errorf("Imported = %s, want %s", got, want)
+	}
+	// Check set of transitive packages.
+	// There are >30 and the set may grow over time, so only check a few.
+	want := map[string]bool{
+		"strings": true,
+		"time":    true,
+		"runtime": true,
+		"testing": true,
+		"unicode": true,
+	}
+	for _, path := range all(prog) {
+		delete(want, path)
+	}
+	if len(want) > 0 {
+		t.Errorf("AllPackages is missing these keys: %q", keys(want))
+	}
+}
+
+func TestLoad_MissingIndirectImport(t *testing.T) {
+	pkgs := map[string]string{
+		"a": `package a; import _ "b"`,
+		"b": `package b; import _ "c"`,
+	}
+	conf := loader.Config{Build: fakeContext(pkgs)}
+	conf.Import("a")
+
+	const wantErr = "couldn't load packages due to errors: b"
+
+	prog, err := conf.Load()
+	if err == nil {
+		t.Errorf("Load succeeded unexpectedly, want %q", wantErr)
+	} else if err.Error() != wantErr {
+		t.Errorf("Load failed with wrong error %q, want %q", err, wantErr)
+	}
+	if prog != nil {
+		t.Errorf("Load unexpectedly returned a Program")
+	}
+}
+
+func TestLoad_BadDependency_AllowErrors(t *testing.T) {
+	for _, test := range []struct {
+		descr    string
+		pkgs     map[string]string
+		wantPkgs string
+	}{
+
+		{
+			descr: "missing dependency",
+			pkgs: map[string]string{
+				"a": `package a; import _ "b"`,
+				"b": `package b; import _ "c"`,
+			},
+			wantPkgs: "a b",
+		},
+		{
+			descr: "bad package decl in dependency",
+			pkgs: map[string]string{
+				"a": `package a; import _ "b"`,
+				"b": `package b; import _ "c"`,
+				"c": `package`,
+			},
+			wantPkgs: "a b",
+		},
+		{
+			descr: "parse error in dependency",
+			pkgs: map[string]string{
+				"a": `package a; import _ "b"`,
+				"b": `package b; import _ "c"`,
+				"c": `package c; var x = `,
+			},
+			wantPkgs: "a b c",
+		},
+	} {
+		conf := loader.Config{
+			AllowErrors: true,
+			Build:       fakeContext(test.pkgs),
+		}
+		conf.Import("a")
+
+		prog, err := conf.Load()
+		if err != nil {
+			t.Errorf("%s: Load failed unexpectedly: %v", test.descr, err)
+		}
+		if prog == nil {
+			t.Fatalf("%s: Load returned a nil Program", test.descr)
+		}
+
+		if got, want := imported(prog), "a"; got != want {
+			t.Errorf("%s: Imported = %s, want %s", test.descr, got, want)
+		}
+		if got := all(prog); strings.Join(got, " ") != test.wantPkgs {
+			t.Errorf("%s: AllPackages = %s, want %s", test.descr, got, test.wantPkgs)
+		}
+	}
+}
+
+func TestCwd(t *testing.T) {
+	ctxt := fakeContext(map[string]string{"one/two/three": `package three`})
+	for _, test := range []struct {
+		cwd, arg, want string
+	}{
+		{cwd: "/go/src/one", arg: "./two/three", want: "one/two/three"},
+		{cwd: "/go/src/one", arg: "../one/two/three", want: "one/two/three"},
+		{cwd: "/go/src/one", arg: "one/two/three", want: "one/two/three"},
+		{cwd: "/go/src/one/two/three", arg: ".", want: "one/two/three"},
+		{cwd: "/go/src/one", arg: "two/three", want: ""},
+	} {
+		conf := loader.Config{
+			Cwd:   test.cwd,
+			Build: ctxt,
+		}
+		conf.Import(test.arg)
+
+		var got string
+		prog, err := conf.Load()
+		if prog != nil {
+			got = imported(prog)
+		}
+		if got != test.want {
+			t.Errorf("Load(%s) from %s: Imported = %s, want %s",
+				test.arg, test.cwd, got, test.want)
+			if err != nil {
+				t.Errorf("Load failed: %v", err)
+			}
+		}
+	}
+}
+
+// TODO(adonovan): more Load tests:
+//
+// failures:
+// - to parse package decl of *_test.go files
+// - to parse package decl of external *_test.go files
+// - to parse whole of *_test.go files
+// - to parse whole of external *_test.go files
+// - to open a *.go file during import scanning
+// - to import from binary
+
+// features:
+// - InitialPackages
+// - PackageCreated hook
+// - TypeCheckFuncBodies hook
+
+func TestTransitivelyErrorFreeFlag(t *testing.T) {
+	// Create an minimal custom build.Context
+	// that fakes the following packages:
+	//
+	// a --> b --> c!   c has an error
+	//   \              d and e are transitively error-free.
+	//    e --> d
+	//
+	// Each package [a-e] consists of one file, x.go.
+	pkgs := map[string]string{
+		"a": `package a; import (_ "b"; _ "e")`,
+		"b": `package b; import _ "c"`,
+		"c": `package c; func f() { _ = int(false) }`, // type error within function body
+		"d": `package d;`,
+		"e": `package e; import _ "d"`,
+	}
+	conf := loader.Config{
+		AllowErrors: true,
+		Build:       fakeContext(pkgs),
+	}
+	conf.Import("a")
+
+	prog, err := conf.Load()
+	if err != nil {
+		t.Errorf("Load failed: %s", err)
+	}
+	if prog == nil {
+		t.Fatalf("Load returned nil *Program")
+	}
+
+	for pkg, info := range prog.AllPackages {
+		var wantErr, wantTEF bool
+		switch pkg.Path() {
+		case "a", "b":
+		case "c":
+			wantErr = true
+		case "d", "e":
+			wantTEF = true
+		default:
+			t.Errorf("unexpected package: %q", pkg.Path())
+			continue
+		}
+
+		if (info.Errors != nil) != wantErr {
+			if wantErr {
+				t.Errorf("Package %q.Error = nil, want error", pkg.Path())
+			} else {
+				t.Errorf("Package %q has unexpected Errors: %v",
+					pkg.Path(), info.Errors)
+			}
+		}
+
+		if info.TransitivelyErrorFree != wantTEF {
+			t.Errorf("Package %q.TransitivelyErrorFree=%t, want %t",
+				pkg.Path(), info.TransitivelyErrorFree, wantTEF)
+		}
+	}
+}
+
+// Test that syntax (scan/parse), type, and loader errors are recorded
+// (in PackageInfo.Errors) and reported (via Config.TypeChecker.Error).
+func TestErrorReporting(t *testing.T) {
+	pkgs := map[string]string{
+		"a": `package a; import (_ "b"; _ "c"); var x int = false`,
+		"b": `package b; 'syntax error!`,
+	}
+	conf := loader.Config{
+		AllowErrors: true,
+		Build:       fakeContext(pkgs),
+	}
+	var mu sync.Mutex
+	var allErrors []error
+	conf.TypeChecker.Error = func(err error) {
+		mu.Lock()
+		allErrors = append(allErrors, err)
+		mu.Unlock()
+	}
+	conf.Import("a")
+
+	prog, err := conf.Load()
+	if err != nil {
+		t.Errorf("Load failed: %s", err)
+	}
+	if prog == nil {
+		t.Fatalf("Load returned nil *Program")
+	}
+
+	// TODO(adonovan): test keys of ImportMap.
+
+	// Check errors recorded in each PackageInfo.
+	for pkg, info := range prog.AllPackages {
+		switch pkg.Path() {
+		case "a":
+			if !hasError(info.Errors, "cannot convert false") {
+				t.Errorf("a.Errors = %v, want bool conversion (type) error", info.Errors)
+			}
+			if !hasError(info.Errors, "could not import c") {
+				t.Errorf("a.Errors = %v, want import (loader) error", info.Errors)
+			}
+		case "b":
+			if !hasError(info.Errors, "rune literal not terminated") {
+				t.Errorf("b.Errors = %v, want unterminated literal (syntax) error", info.Errors)
+			}
+		}
+	}
+
+	// Check errors reported via error handler.
+	if !hasError(allErrors, "cannot convert false") ||
+		!hasError(allErrors, "rune literal not terminated") ||
+		!hasError(allErrors, "could not import c") {
+		t.Errorf("allErrors = %v, want syntax, type and loader errors", allErrors)
+	}
+}
+
+func TestCycles(t *testing.T) {
+	for _, test := range []struct {
+		descr   string
+		ctxt    *build.Context
+		wantErr string
+	}{
+		{
+			"self-cycle",
+			fakeContext(map[string]string{
+				"main":      `package main; import _ "selfcycle"`,
+				"selfcycle": `package selfcycle; import _ "selfcycle"`,
+			}),
+			`import cycle: selfcycle -> selfcycle`,
+		},
+		{
+			"three-package cycle",
+			fakeContext(map[string]string{
+				"main": `package main; import _ "a"`,
+				"a":    `package a; import _ "b"`,
+				"b":    `package b; import _ "c"`,
+				"c":    `package c; import _ "a"`,
+			}),
+			`import cycle: c -> a -> b -> c`,
+		},
+		{
+			"self-cycle in dependency of test file",
+			buildutil.FakeContext(map[string]map[string]string{
+				"main": {
+					"main.go":      `package main`,
+					"main_test.go": `package main; import _ "a"`,
+				},
+				"a": {
+					"a.go": `package a; import _ "a"`,
+				},
+			}),
+			`import cycle: a -> a`,
+		},
+		// TODO(adonovan): fix: these fail
+		// {
+		// 	"two-package cycle in dependency of test file",
+		// 	buildutil.FakeContext(map[string]map[string]string{
+		// 		"main": {
+		// 			"main.go":      `package main`,
+		// 			"main_test.go": `package main; import _ "a"`,
+		// 		},
+		// 		"a": {
+		// 			"a.go": `package a; import _ "main"`,
+		// 		},
+		// 	}),
+		// 	`import cycle: main -> a -> main`,
+		// },
+		// {
+		// 	"self-cycle in augmented package",
+		// 	buildutil.FakeContext(map[string]map[string]string{
+		// 		"main": {
+		// 			"main.go":      `package main`,
+		// 			"main_test.go": `package main; import _ "main"`,
+		// 		},
+		// 	}),
+		// 	`import cycle: main -> main`,
+		// },
+	} {
+		conf := loader.Config{
+			AllowErrors: true,
+			Build:       test.ctxt,
+		}
+		var mu sync.Mutex
+		var allErrors []error
+		conf.TypeChecker.Error = func(err error) {
+			mu.Lock()
+			allErrors = append(allErrors, err)
+			mu.Unlock()
+		}
+		conf.ImportWithTests("main")
+
+		prog, err := conf.Load()
+		if err != nil {
+			t.Errorf("%s: Load failed: %s", test.descr, err)
+		}
+		if prog == nil {
+			t.Fatalf("%s: Load returned nil *Program", test.descr)
+		}
+
+		if !hasError(allErrors, test.wantErr) {
+			t.Errorf("%s: Load() errors = %q, want %q",
+				test.descr, allErrors, test.wantErr)
+		}
+	}
+
+	// TODO(adonovan):
+	// - Test that in a legal test cycle, none of the symbols
+	//   defined by augmentation are visible via import.
+}
+
+// ---- utilities ----
+
+// Simplifying wrapper around buildutil.FakeContext for single-file packages.
+func fakeContext(pkgs map[string]string) *build.Context {
+	pkgs2 := make(map[string]map[string]string)
+	for path, content := range pkgs {
+		pkgs2[path] = map[string]string{"x.go": content}
+	}
+	return buildutil.FakeContext(pkgs2)
+}
+
+func hasError(errors []error, substr string) bool {
+	for _, err := range errors {
+		if strings.Contains(err.Error(), substr) {
+			return true
+		}
+	}
+	return false
+}
+
+func keys(m map[string]bool) (keys []string) {
+	for key := range m {
+		keys = append(keys, key)
+	}
+	sort.Strings(keys)
+	return
+}
+
+// Returns all loaded packages.
+func all(prog *loader.Program) []string {
+	var pkgs []string
+	for _, info := range prog.AllPackages {
+		pkgs = append(pkgs, info.Pkg.Path())
+	}
+	sort.Strings(pkgs)
+	return pkgs
+}
+
+// Returns initially imported packages, as a string.
+func imported(prog *loader.Program) string {
+	var pkgs []string
+	for _, info := range prog.Imported {
+		pkgs = append(pkgs, info.Pkg.Path())
+	}
+	sort.Strings(pkgs)
+	return strings.Join(pkgs, " ")
+}
+
+// Returns initially created packages, as a string.
+func created(prog *loader.Program) string {
+	var pkgs []string
+	for _, info := range prog.Created {
+		pkgs = append(pkgs, info.Pkg.Path())
+	}
+	return strings.Join(pkgs, " ")
+}
diff --git a/go/loader/stdlib_test.go b/go/loader/stdlib_test.go
new file mode 100644
index 0000000..b62ecfb
--- /dev/null
+++ b/go/loader/stdlib_test.go
@@ -0,0 +1,197 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package loader_test
+
+// This file enumerates all packages beneath $GOROOT, loads them, plus
+// their external tests if any, runs the type checker on them, and
+// prints some summary information.
+//
+// Run test with GOMAXPROCS=8.
+
+import (
+	"bytes"
+	"fmt"
+	"go/ast"
+	"go/build"
+	"go/token"
+	"io/ioutil"
+	"path/filepath"
+	"runtime"
+	"strings"
+	"testing"
+	"time"
+
+	"golang.org/x/tools/go/buildutil"
+	"golang.org/x/tools/go/loader"
+	"golang.org/x/tools/go/types"
+)
+
+func TestStdlib(t *testing.T) {
+	if runtime.GOOS == "android" {
+		t.Skipf("incomplete std lib on %s", runtime.GOOS)
+	}
+
+	runtime.GC()
+	t0 := time.Now()
+	var memstats runtime.MemStats
+	runtime.ReadMemStats(&memstats)
+	alloc := memstats.Alloc
+
+	// Load, parse and type-check the program.
+	ctxt := build.Default // copy
+	ctxt.GOPATH = ""      // disable GOPATH
+	conf := loader.Config{Build: &ctxt}
+	for _, path := range buildutil.AllPackages(conf.Build) {
+		conf.ImportWithTests(path)
+	}
+
+	prog, err := conf.Load()
+	if err != nil {
+		t.Fatalf("Load failed: %v", err)
+	}
+
+	t1 := time.Now()
+	runtime.GC()
+	runtime.ReadMemStats(&memstats)
+
+	numPkgs := len(prog.AllPackages)
+	if want := 205; numPkgs < want {
+		t.Errorf("Loaded only %d packages, want at least %d", numPkgs, want)
+	}
+
+	// Dump package members.
+	if false {
+		for pkg := range prog.AllPackages {
+			fmt.Printf("Package %s:\n", pkg.Path())
+			scope := pkg.Scope()
+			qualifier := types.RelativeTo(pkg)
+			for _, name := range scope.Names() {
+				if ast.IsExported(name) {
+					fmt.Printf("\t%s\n", types.ObjectString(scope.Lookup(name), qualifier))
+				}
+			}
+			fmt.Println()
+		}
+	}
+
+	// Check that Test functions for io/ioutil, regexp and
+	// compress/bzip2 are all simultaneously present.
+	// (The apparent cycle formed when augmenting all three of
+	// these packages by their tests was the original motivation
+	// for reporting b/7114.)
+	//
+	// compress/bzip2.TestBitReader in bzip2_test.go    imports io/ioutil
+	// io/ioutil.TestTempFile       in tempfile_test.go imports regexp
+	// regexp.TestRE2Search         in exec_test.go     imports compress/bzip2
+	for _, test := range []struct{ pkg, fn string }{
+		{"io/ioutil", "TestTempFile"},
+		{"regexp", "TestRE2Search"},
+		{"compress/bzip2", "TestBitReader"},
+	} {
+		info := prog.Imported[test.pkg]
+		if info == nil {
+			t.Errorf("failed to load package %q", test.pkg)
+			continue
+		}
+		obj, _ := info.Pkg.Scope().Lookup(test.fn).(*types.Func)
+		if obj == nil {
+			t.Errorf("package %q has no func %q", test.pkg, test.fn)
+			continue
+		}
+	}
+
+	// Dump some statistics.
+
+	// determine line count
+	var lineCount int
+	prog.Fset.Iterate(func(f *token.File) bool {
+		lineCount += f.LineCount()
+		return true
+	})
+
+	t.Log("GOMAXPROCS:           ", runtime.GOMAXPROCS(0))
+	t.Log("#Source lines:        ", lineCount)
+	t.Log("Load/parse/typecheck: ", t1.Sub(t0))
+	t.Log("#MB:                  ", int64(memstats.Alloc-alloc)/1000000)
+}
+
+func TestCgoOption(t *testing.T) {
+	switch runtime.GOOS {
+	// On these systems, the net and os/user packages don't use cgo
+	// or the std library is incomplete (Android).
+	case "android", "plan9", "solaris", "windows":
+		t.Skipf("no cgo or incomplete std lib on %s", runtime.GOOS)
+	}
+	// In nocgo builds (e.g. linux-amd64-nocgo),
+	// there is no "runtime/cgo" package,
+	// so cgo-generated Go files will have a failing import.
+	if !build.Default.CgoEnabled {
+		return
+	}
+	// Test that we can load cgo-using packages with
+	// CGO_ENABLED=[01], which causes go/build to select pure
+	// Go/native implementations, respectively, based on build
+	// tags.
+	//
+	// Each entry specifies a package-level object and the generic
+	// file expected to define it when cgo is disabled.
+	// When cgo is enabled, the exact file is not specified (since
+	// it varies by platform), but must differ from the generic one.
+	//
+	// The test also loads the actual file to verify that the
+	// object is indeed defined at that location.
+	for _, test := range []struct {
+		pkg, name, genericFile string
+	}{
+		{"net", "cgoLookupHost", "cgo_stub.go"},
+		{"os/user", "lookupId", "lookup_stubs.go"},
+	} {
+		ctxt := build.Default
+		for _, ctxt.CgoEnabled = range []bool{false, true} {
+			conf := loader.Config{Build: &ctxt}
+			conf.Import(test.pkg)
+			prog, err := conf.Load()
+			if err != nil {
+				t.Errorf("Load failed: %v", err)
+				continue
+			}
+			info := prog.Imported[test.pkg]
+			if info == nil {
+				t.Errorf("package %s not found", test.pkg)
+				continue
+			}
+			obj := info.Pkg.Scope().Lookup(test.name)
+			if obj == nil {
+				t.Errorf("no object %s.%s", test.pkg, test.name)
+				continue
+			}
+			posn := prog.Fset.Position(obj.Pos())
+			t.Logf("%s: %s (CgoEnabled=%t)", posn, obj, ctxt.CgoEnabled)
+
+			gotFile := filepath.Base(posn.Filename)
+			filesMatch := gotFile == test.genericFile
+
+			if ctxt.CgoEnabled && filesMatch {
+				t.Errorf("CGO_ENABLED=1: %s found in %s, want native file",
+					obj, gotFile)
+			} else if !ctxt.CgoEnabled && !filesMatch {
+				t.Errorf("CGO_ENABLED=0: %s found in %s, want %s",
+					obj, gotFile, test.genericFile)
+			}
+
+			// Load the file and check the object is declared at the right place.
+			b, err := ioutil.ReadFile(posn.Filename)
+			if err != nil {
+				t.Errorf("can't read %s: %s", posn.Filename, err)
+				continue
+			}
+			line := string(bytes.Split(b, []byte("\n"))[posn.Line-1])
+			ident := line[posn.Column-1:]
+			if !strings.HasPrefix(ident, test.name) {
+				t.Errorf("%s: %s not declared here (looking at %q)", posn, obj, ident)
+			}
+		}
+	}
+}
diff --git a/go/loader/testdata/a.go b/go/loader/testdata/a.go
new file mode 100644
index 0000000..bae3955
--- /dev/null
+++ b/go/loader/testdata/a.go
@@ -0,0 +1 @@
+package P
diff --git a/go/loader/testdata/b.go b/go/loader/testdata/b.go
new file mode 100644
index 0000000..bae3955
--- /dev/null
+++ b/go/loader/testdata/b.go
@@ -0,0 +1 @@
+package P
diff --git a/go/loader/testdata/badpkgdecl.go b/go/loader/testdata/badpkgdecl.go
new file mode 100644
index 0000000..1e39359
--- /dev/null
+++ b/go/loader/testdata/badpkgdecl.go
@@ -0,0 +1 @@
+// this file has no package decl
diff --git a/go/loader/util.go b/go/loader/util.go
new file mode 100644
index 0000000..3b64856
--- /dev/null
+++ b/go/loader/util.go
@@ -0,0 +1,124 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package loader
+
+import (
+	"go/ast"
+	"go/build"
+	"go/parser"
+	"go/token"
+	"io"
+	"os"
+	"strconv"
+	"sync"
+
+	"golang.org/x/tools/go/buildutil"
+)
+
+// We use a counting semaphore to limit
+// the number of parallel I/O calls per process.
+var ioLimit = make(chan bool, 10)
+
+// parseFiles parses the Go source files within directory dir and
+// returns the ASTs of the ones that could be at least partially parsed,
+// along with a list of I/O and parse errors encountered.
+//
+// I/O is done via ctxt, which may specify a virtual file system.
+// displayPath is used to transform the filenames attached to the ASTs.
+//
+func parseFiles(fset *token.FileSet, ctxt *build.Context, displayPath func(string) string, dir string, files []string, mode parser.Mode) ([]*ast.File, []error) {
+	if displayPath == nil {
+		displayPath = func(path string) string { return path }
+	}
+	var wg sync.WaitGroup
+	n := len(files)
+	parsed := make([]*ast.File, n)
+	errors := make([]error, n)
+	for i, file := range files {
+		if !buildutil.IsAbsPath(ctxt, file) {
+			file = buildutil.JoinPath(ctxt, dir, file)
+		}
+		wg.Add(1)
+		go func(i int, file string) {
+			ioLimit <- true // wait
+			defer func() {
+				wg.Done()
+				<-ioLimit // signal
+			}()
+			var rd io.ReadCloser
+			var err error
+			if ctxt.OpenFile != nil {
+				rd, err = ctxt.OpenFile(file)
+			} else {
+				rd, err = os.Open(file)
+			}
+			if err != nil {
+				errors[i] = err // open failed
+				return
+			}
+
+			// ParseFile may return both an AST and an error.
+			parsed[i], errors[i] = parser.ParseFile(fset, displayPath(file), rd, mode)
+			rd.Close()
+		}(i, file)
+	}
+	wg.Wait()
+
+	// Eliminate nils, preserving order.
+	var o int
+	for _, f := range parsed {
+		if f != nil {
+			parsed[o] = f
+			o++
+		}
+	}
+	parsed = parsed[:o]
+
+	o = 0
+	for _, err := range errors {
+		if err != nil {
+			errors[o] = err
+			o++
+		}
+	}
+	errors = errors[:o]
+
+	return parsed, errors
+}
+
+// scanImports returns the set of all package import paths from all
+// import specs in the specified files.
+func scanImports(files []*ast.File) map[string]bool {
+	imports := make(map[string]bool)
+	for _, f := range files {
+		for _, decl := range f.Decls {
+			if decl, ok := decl.(*ast.GenDecl); ok && decl.Tok == token.IMPORT {
+				for _, spec := range decl.Specs {
+					spec := spec.(*ast.ImportSpec)
+
+					// NB: do not assume the program is well-formed!
+					path, err := strconv.Unquote(spec.Path.Value)
+					if err != nil {
+						continue // quietly ignore the error
+					}
+					if path == "C" || path == "unsafe" {
+						continue // skip pseudo packages
+					}
+					imports[path] = true
+				}
+			}
+		}
+	}
+	return imports
+}
+
+// ---------- Internal helpers ----------
+
+// TODO(adonovan): make this a method: func (*token.File) Contains(token.Pos)
+func tokenFileContainsPos(f *token.File, pos token.Pos) bool {
+	p := int(pos)
+	base := f.Base()
+	return base <= p && p < base+f.Size()
+}
diff --git a/go/pointer/TODO b/go/pointer/TODO
new file mode 100644
index 0000000..f95e706
--- /dev/null
+++ b/go/pointer/TODO
@@ -0,0 +1,33 @@
+-*- text -*-
+
+Pointer analysis to-do list
+===========================
+
+CONSTRAINT GENERATION:
+- support reflection:
+  - a couple of operators are missing
+  - reflect.Values may contain lvalues (CanAddr)
+- implement native intrinsics.  These vary by platform.
+- add to pts(a.panic) a label representing all runtime panics, e.g.
+  runtime.{TypeAssertionError,errorString,errorCString}.
+
+OPTIMISATIONS
+- pre-solver: 
+  pointer equivalence: extend HVN to HRU
+  location equivalence
+- solver: HCD, LCD.
+- experiment with map+slice worklist in lieu of bitset.
+  It may have faster insert.
+
+MISC:
+- Test on all platforms.  
+  Currently we assume these go/build tags: linux, amd64, !cgo.
+
+MAINTAINABILITY
+- Think about ways to make debugging this code easier.  PTA logs
+  routinely exceed a million lines and require training to read.
+
+BUGS: 
+- There's a crash bug in stdlib_test + reflection, rVCallConstraint.
+
+
diff --git a/go/pointer/analysis.go b/go/pointer/analysis.go
new file mode 100644
index 0000000..d02e536
--- /dev/null
+++ b/go/pointer/analysis.go
@@ -0,0 +1,447 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package pointer
+
+// This file defines the main datatypes and Analyze function of the pointer analysis.
+
+import (
+	"fmt"
+	"go/token"
+	"io"
+	"os"
+	"reflect"
+	"runtime"
+	"runtime/debug"
+	"sort"
+
+	"golang.org/x/tools/go/callgraph"
+	"golang.org/x/tools/go/ssa"
+	"golang.org/x/tools/go/types"
+	"golang.org/x/tools/go/types/typeutil"
+)
+
+const (
+	// optimization options; enable all when committing
+	optRenumber = true // enable renumbering optimization (makes logs hard to read)
+	optHVN      = true // enable pointer equivalence via Hash-Value Numbering
+
+	// debugging options; disable all when committing
+	debugHVN           = false // enable assertions in HVN
+	debugHVNVerbose    = false // enable extra HVN logging
+	debugHVNCrossCheck = false // run solver with/without HVN and compare (caveats below)
+	debugTimers        = false // show running time of each phase
+)
+
+// object.flags bitmask values.
+const (
+	otTagged   = 1 << iota // type-tagged object
+	otIndirect             // type-tagged object with indirect payload
+	otFunction             // function object
+)
+
+// An object represents a contiguous block of memory to which some
+// (generalized) pointer may point.
+//
+// (Note: most variables called 'obj' are not *objects but nodeids
+// such that a.nodes[obj].obj != nil.)
+//
+type object struct {
+	// flags is a bitset of the node type (ot*) flags defined above.
+	flags uint32
+
+	// Number of following nodes belonging to the same "object"
+	// allocation.  Zero for all other nodes.
+	size uint32
+
+	// data describes this object; it has one of these types:
+	//
+	// ssa.Value	for an object allocated by an SSA operation.
+	// types.Type	for an rtype instance object or *rtype-tagged object.
+	// string	for an instrinsic object, e.g. the array behind os.Args.
+	// nil		for an object allocated by an instrinsic.
+	//		(cgn provides the identity of the intrinsic.)
+	data interface{}
+
+	// The call-graph node (=context) in which this object was allocated.
+	// May be nil for global objects: Global, Const, some Functions.
+	cgn *cgnode
+}
+
+// nodeid denotes a node.
+// It is an index within analysis.nodes.
+// We use small integers, not *node pointers, for many reasons:
+// - they are smaller on 64-bit systems.
+// - sets of them can be represented compactly in bitvectors or BDDs.
+// - order matters; a field offset can be computed by simple addition.
+type nodeid uint32
+
+// A node is an equivalence class of memory locations.
+// Nodes may be pointers, pointed-to locations, neither, or both.
+//
+// Nodes that are pointed-to locations ("labels") have an enclosing
+// object (see analysis.enclosingObject).
+//
+type node struct {
+	// If non-nil, this node is the start of an object
+	// (addressable memory location).
+	// The following obj.size nodes implicitly belong to the object;
+	// they locate their object by scanning back.
+	obj *object
+
+	// The type of the field denoted by this node.  Non-aggregate,
+	// unless this is an tagged.T node (i.e. the thing
+	// pointed to by an interface) in which case typ is that type.
+	typ types.Type
+
+	// subelement indicates which directly embedded subelement of
+	// an object of aggregate type (struct, tuple, array) this is.
+	subelement *fieldInfo // e.g. ".a.b[*].c"
+
+	// Solver state for the canonical node of this pointer-
+	// equivalence class.  Each node is created with its own state
+	// but they become shared after HVN.
+	solve *solverState
+}
+
+// An analysis instance holds the state of a single pointer analysis problem.
+type analysis struct {
+	config      *Config                     // the client's control/observer interface
+	prog        *ssa.Program                // the program being analyzed
+	log         io.Writer                   // log stream; nil to disable
+	panicNode   nodeid                      // sink for panic, source for recover
+	nodes       []*node                     // indexed by nodeid
+	flattenMemo map[types.Type][]*fieldInfo // memoization of flatten()
+	trackTypes  map[types.Type]bool         // memoization of shouldTrack()
+	constraints []constraint                // set of constraints
+	cgnodes     []*cgnode                   // all cgnodes
+	genq        []*cgnode                   // queue of functions to generate constraints for
+	intrinsics  map[*ssa.Function]intrinsic // non-nil values are summaries for intrinsic fns
+	globalval   map[ssa.Value]nodeid        // node for each global ssa.Value
+	globalobj   map[ssa.Value]nodeid        // maps v to sole member of pts(v), if singleton
+	localval    map[ssa.Value]nodeid        // node for each local ssa.Value
+	localobj    map[ssa.Value]nodeid        // maps v to sole member of pts(v), if singleton
+	atFuncs     map[*ssa.Function]bool      // address-taken functions (for presolver)
+	mapValues   []nodeid                    // values of makemap objects (indirect in HVN)
+	work        nodeset                     // solver's worklist
+	result      *Result                     // results of the analysis
+	track       track                       // pointerlike types whose aliasing we track
+	deltaSpace  []int                       // working space for iterating over PTS deltas
+
+	// Reflection & intrinsics:
+	hasher              typeutil.Hasher // cache of type hashes
+	reflectValueObj     types.Object    // type symbol for reflect.Value (if present)
+	reflectValueCall    *ssa.Function   // (reflect.Value).Call
+	reflectRtypeObj     types.Object    // *types.TypeName for reflect.rtype (if present)
+	reflectRtypePtr     *types.Pointer  // *reflect.rtype
+	reflectType         *types.Named    // reflect.Type
+	rtypes              typeutil.Map    // nodeid of canonical *rtype-tagged object for type T
+	reflectZeros        typeutil.Map    // nodeid of canonical T-tagged object for zero value
+	runtimeSetFinalizer *ssa.Function   // runtime.SetFinalizer
+}
+
+// enclosingObj returns the first node of the addressable memory
+// object that encloses node id.  Panic ensues if that node does not
+// belong to any object.
+func (a *analysis) enclosingObj(id nodeid) nodeid {
+	// Find previous node with obj != nil.
+	for i := id; i >= 0; i-- {
+		n := a.nodes[i]
+		if obj := n.obj; obj != nil {
+			if i+nodeid(obj.size) <= id {
+				break // out of bounds
+			}
+			return i
+		}
+	}
+	panic("node has no enclosing object")
+}
+
+// labelFor returns the Label for node id.
+// Panic ensues if that node is not addressable.
+func (a *analysis) labelFor(id nodeid) *Label {
+	return &Label{
+		obj:        a.nodes[a.enclosingObj(id)].obj,
+		subelement: a.nodes[id].subelement,
+	}
+}
+
+func (a *analysis) warnf(pos token.Pos, format string, args ...interface{}) {
+	msg := fmt.Sprintf(format, args...)
+	if a.log != nil {
+		fmt.Fprintf(a.log, "%s: warning: %s\n", a.prog.Fset.Position(pos), msg)
+	}
+	a.result.Warnings = append(a.result.Warnings, Warning{pos, msg})
+}
+
+// computeTrackBits sets a.track to the necessary 'track' bits for the pointer queries.
+func (a *analysis) computeTrackBits() {
+	var queryTypes []types.Type
+	for v := range a.config.Queries {
+		queryTypes = append(queryTypes, v.Type())
+	}
+	for v := range a.config.IndirectQueries {
+		queryTypes = append(queryTypes, mustDeref(v.Type()))
+	}
+	for _, t := range queryTypes {
+		switch t.Underlying().(type) {
+		case *types.Chan:
+			a.track |= trackChan
+		case *types.Map:
+			a.track |= trackMap
+		case *types.Pointer:
+			a.track |= trackPtr
+		case *types.Slice:
+			a.track |= trackSlice
+		case *types.Interface:
+			a.track = trackAll
+			return
+		}
+		if rVObj := a.reflectValueObj; rVObj != nil && types.Identical(t, rVObj.Type()) {
+			a.track = trackAll
+			return
+		}
+	}
+}
+
+// Analyze runs the pointer analysis with the scope and options
+// specified by config, and returns the (synthetic) root of the callgraph.
+//
+// Pointer analysis of a transitively closed well-typed program should
+// always succeed.  An error can occur only due to an internal bug.
+//
+func Analyze(config *Config) (result *Result, err error) {
+	if config.Mains == nil {
+		return nil, fmt.Errorf("no main/test packages to analyze (check $GOROOT/$GOPATH)")
+	}
+	defer func() {
+		if p := recover(); p != nil {
+			err = fmt.Errorf("internal error in pointer analysis: %v (please report this bug)", p)
+			fmt.Fprintln(os.Stderr, "Internal panic in pointer analysis:")
+			debug.PrintStack()
+		}
+	}()
+
+	a := &analysis{
+		config:      config,
+		log:         config.Log,
+		prog:        config.prog(),
+		globalval:   make(map[ssa.Value]nodeid),
+		globalobj:   make(map[ssa.Value]nodeid),
+		flattenMemo: make(map[types.Type][]*fieldInfo),
+		trackTypes:  make(map[types.Type]bool),
+		atFuncs:     make(map[*ssa.Function]bool),
+		hasher:      typeutil.MakeHasher(),
+		intrinsics:  make(map[*ssa.Function]intrinsic),
+		result: &Result{
+			Queries:         make(map[ssa.Value]Pointer),
+			IndirectQueries: make(map[ssa.Value]Pointer),
+		},
+		deltaSpace: make([]int, 0, 100),
+	}
+
+	if false {
+		a.log = os.Stderr // for debugging crashes; extremely verbose
+	}
+
+	if a.log != nil {
+		fmt.Fprintln(a.log, "==== Starting analysis")
+	}
+
+	// Pointer analysis requires a complete program for soundness.
+	// Check to prevent accidental misconfiguration.
+	for _, pkg := range a.prog.AllPackages() {
+		// (This only checks that the package scope is complete,
+		// not that func bodies exist, but it's a good signal.)
+		if !pkg.Object.Complete() {
+			return nil, fmt.Errorf(`pointer analysis requires a complete program yet package %q was incomplete`, pkg.Object.Path())
+		}
+	}
+
+	if reflect := a.prog.ImportedPackage("reflect"); reflect != nil {
+		rV := reflect.Object.Scope().Lookup("Value")
+		a.reflectValueObj = rV
+		a.reflectValueCall = a.prog.LookupMethod(rV.Type(), nil, "Call")
+		a.reflectType = reflect.Object.Scope().Lookup("Type").Type().(*types.Named)
+		a.reflectRtypeObj = reflect.Object.Scope().Lookup("rtype")
+		a.reflectRtypePtr = types.NewPointer(a.reflectRtypeObj.Type())
+
+		// Override flattening of reflect.Value, treating it like a basic type.
+		tReflectValue := a.reflectValueObj.Type()
+		a.flattenMemo[tReflectValue] = []*fieldInfo{{typ: tReflectValue}}
+
+		// Override shouldTrack of reflect.Value and *reflect.rtype.
+		// Always track pointers of these types.
+		a.trackTypes[tReflectValue] = true
+		a.trackTypes[a.reflectRtypePtr] = true
+
+		a.rtypes.SetHasher(a.hasher)
+		a.reflectZeros.SetHasher(a.hasher)
+	}
+	if runtime := a.prog.ImportedPackage("runtime"); runtime != nil {
+		a.runtimeSetFinalizer = runtime.Func("SetFinalizer")
+	}
+	a.computeTrackBits()
+
+	a.generate()
+	a.showCounts()
+
+	if optRenumber {
+		a.renumber()
+	}
+
+	N := len(a.nodes) // excludes solver-created nodes
+
+	if optHVN {
+		if debugHVNCrossCheck {
+			// Cross-check: run the solver once without
+			// optimization, once with, and compare the
+			// solutions.
+			savedConstraints := a.constraints
+
+			a.solve()
+			a.dumpSolution("A.pts", N)
+
+			// Restore.
+			a.constraints = savedConstraints
+			for _, n := range a.nodes {
+				n.solve = new(solverState)
+			}
+			a.nodes = a.nodes[:N]
+
+			// rtypes is effectively part of the solver state.
+			a.rtypes = typeutil.Map{}
+			a.rtypes.SetHasher(a.hasher)
+		}
+
+		a.hvn()
+	}
+
+	if debugHVNCrossCheck {
+		runtime.GC()
+		runtime.GC()
+	}
+
+	a.solve()
+
+	// Compare solutions.
+	if optHVN && debugHVNCrossCheck {
+		a.dumpSolution("B.pts", N)
+
+		if !diff("A.pts", "B.pts") {
+			return nil, fmt.Errorf("internal error: optimization changed solution")
+		}
+	}
+
+	// Create callgraph.Nodes in deterministic order.
+	if cg := a.result.CallGraph; cg != nil {
+		for _, caller := range a.cgnodes {
+			cg.CreateNode(caller.fn)
+		}
+	}
+
+	// Add dynamic edges to call graph.
+	var space [100]int
+	for _, caller := range a.cgnodes {
+		for _, site := range caller.sites {
+			for _, callee := range a.nodes[site.targets].solve.pts.AppendTo(space[:0]) {
+				a.callEdge(caller, site, nodeid(callee))
+			}
+		}
+	}
+
+	return a.result, nil
+}
+
+// callEdge is called for each edge in the callgraph.
+// calleeid is the callee's object node (has otFunction flag).
+//
+func (a *analysis) callEdge(caller *cgnode, site *callsite, calleeid nodeid) {
+	obj := a.nodes[calleeid].obj
+	if obj.flags&otFunction == 0 {
+		panic(fmt.Sprintf("callEdge %s -> n%d: not a function object", site, calleeid))
+	}
+	callee := obj.cgn
+
+	if cg := a.result.CallGraph; cg != nil {
+		// TODO(adonovan): opt: I would expect duplicate edges
+		// (to wrappers) to arise due to the elimination of
+		// context information, but I haven't observed any.
+		// Understand this better.
+		callgraph.AddEdge(cg.CreateNode(caller.fn), site.instr, cg.CreateNode(callee.fn))
+	}
+
+	if a.log != nil {
+		fmt.Fprintf(a.log, "\tcall edge %s -> %s\n", site, callee)
+	}
+
+	// Warn about calls to non-intrinsic external functions.
+	// TODO(adonovan): de-dup these messages.
+	if fn := callee.fn; fn.Blocks == nil && a.findIntrinsic(fn) == nil {
+		a.warnf(site.pos(), "unsound call to unknown intrinsic: %s", fn)
+		a.warnf(fn.Pos(), " (declared here)")
+	}
+}
+
+// dumpSolution writes the PTS solution to the specified file.
+//
+// It only dumps the nodes that existed before solving.  The order in
+// which solver-created nodes are created depends on pre-solver
+// optimization, so we can't include them in the cross-check.
+//
+func (a *analysis) dumpSolution(filename string, N int) {
+	f, err := os.Create(filename)
+	if err != nil {
+		panic(err)
+	}
+	for id, n := range a.nodes[:N] {
+		if _, err := fmt.Fprintf(f, "pts(n%d) = {", id); err != nil {
+			panic(err)
+		}
+		var sep string
+		for _, l := range n.solve.pts.AppendTo(a.deltaSpace) {
+			if l >= N {
+				break
+			}
+			fmt.Fprintf(f, "%s%d", sep, l)
+			sep = " "
+		}
+		fmt.Fprintf(f, "} : %s\n", n.typ)
+	}
+	if err := f.Close(); err != nil {
+		panic(err)
+	}
+}
+
+// showCounts logs the size of the constraint system.  A typical
+// optimized distribution is 65% copy, 13% load, 11% addr, 5%
+// offsetAddr, 4% store, 2% others.
+//
+func (a *analysis) showCounts() {
+	if a.log != nil {
+		counts := make(map[reflect.Type]int)
+		for _, c := range a.constraints {
+			counts[reflect.TypeOf(c)]++
+		}
+		fmt.Fprintf(a.log, "# constraints:\t%d\n", len(a.constraints))
+		var lines []string
+		for t, n := range counts {
+			line := fmt.Sprintf("%7d  (%2d%%)\t%s", n, 100*n/len(a.constraints), t)
+			lines = append(lines, line)
+		}
+		sort.Sort(sort.Reverse(sort.StringSlice(lines)))
+		for _, line := range lines {
+			fmt.Fprintf(a.log, "\t%s\n", line)
+		}
+
+		fmt.Fprintf(a.log, "# nodes:\t%d\n", len(a.nodes))
+
+		// Show number of pointer equivalence classes.
+		m := make(map[*solverState]bool)
+		for _, n := range a.nodes {
+			m[n.solve] = true
+		}
+		fmt.Fprintf(a.log, "# ptsets:\t%d\n", len(m))
+	}
+}
diff --git a/go/pointer/api.go b/go/pointer/api.go
new file mode 100644
index 0000000..8f9ae0a
--- /dev/null
+++ b/go/pointer/api.go
@@ -0,0 +1,245 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package pointer
+
+import (
+	"bytes"
+	"fmt"
+	"go/token"
+	"io"
+
+	"golang.org/x/tools/container/intsets"
+	"golang.org/x/tools/go/callgraph"
+	"golang.org/x/tools/go/ssa"
+	"golang.org/x/tools/go/types/typeutil"
+)
+
+// A Config formulates a pointer analysis problem for Analyze().
+type Config struct {
+	// Mains contains the set of 'main' packages to analyze
+	// Clients must provide the analysis with at least one
+	// package defining a main() function.
+	//
+	// Non-main packages in the ssa.Program that are not
+	// dependencies of any main package may still affect the
+	// analysis result, because they contribute runtime types and
+	// thus methods.
+	// TODO(adonovan): investigate whether this is desirable.
+	Mains []*ssa.Package
+
+	// Reflection determines whether to handle reflection
+	// operators soundly, which is currently rather slow since it
+	// causes constraint to be generated during solving
+	// proportional to the number of constraint variables, which
+	// has not yet been reduced by presolver optimisation.
+	Reflection bool
+
+	// BuildCallGraph determines whether to construct a callgraph.
+	// If enabled, the graph will be available in Result.CallGraph.
+	BuildCallGraph bool
+
+	// The client populates Queries[v] or IndirectQueries[v]
+	// for each ssa.Value v of interest, to request that the
+	// points-to sets pts(v) or pts(*v) be computed.  If the
+	// client needs both points-to sets, v may appear in both
+	// maps.
+	//
+	// (IndirectQueries is typically used for Values corresponding
+	// to source-level lvalues, e.g. an *ssa.Global.)
+	//
+	// The analysis populates the corresponding
+	// Result.{Indirect,}Queries map when it creates the pointer
+	// variable for v or *v.  Upon completion the client can
+	// inspect that map for the results.
+	//
+	// TODO(adonovan): this API doesn't scale well for batch tools
+	// that want to dump the entire solution.  Perhaps optionally
+	// populate a map[*ssa.DebugRef]Pointer in the Result, one
+	// entry per source expression.
+	//
+	Queries         map[ssa.Value]struct{}
+	IndirectQueries map[ssa.Value]struct{}
+
+	// If Log is non-nil, log messages are written to it.
+	// Logging is extremely verbose.
+	Log io.Writer
+}
+
+type track uint32
+
+const (
+	trackChan  track = 1 << iota // track 'chan' references
+	trackMap                     // track 'map' references
+	trackPtr                     // track regular pointers
+	trackSlice                   // track slice references
+
+	trackAll = ^track(0)
+)
+
+// AddQuery adds v to Config.Queries.
+// Precondition: CanPoint(v.Type()).
+// TODO(adonovan): consider returning a new Pointer for this query,
+// which will be initialized during analysis.  That avoids the needs
+// for the corresponding ssa.Value-keyed maps in Config and Result.
+func (c *Config) AddQuery(v ssa.Value) {
+	if !CanPoint(v.Type()) {
+		panic(fmt.Sprintf("%s is not a pointer-like value: %s", v, v.Type()))
+	}
+	if c.Queries == nil {
+		c.Queries = make(map[ssa.Value]struct{})
+	}
+	c.Queries[v] = struct{}{}
+}
+
+// AddQuery adds v to Config.IndirectQueries.
+// Precondition: CanPoint(v.Type().Underlying().(*types.Pointer).Elem()).
+func (c *Config) AddIndirectQuery(v ssa.Value) {
+	if c.IndirectQueries == nil {
+		c.IndirectQueries = make(map[ssa.Value]struct{})
+	}
+	if !CanPoint(mustDeref(v.Type())) {
+		panic(fmt.Sprintf("%s is not the address of a pointer-like value: %s", v, v.Type()))
+	}
+	c.IndirectQueries[v] = struct{}{}
+}
+
+func (c *Config) prog() *ssa.Program {
+	for _, main := range c.Mains {
+		return main.Prog
+	}
+	panic("empty scope")
+}
+
+type Warning struct {
+	Pos     token.Pos
+	Message string
+}
+
+// A Result contains the results of a pointer analysis.
+//
+// See Config for how to request the various Result components.
+//
+type Result struct {
+	CallGraph       *callgraph.Graph      // discovered call graph
+	Queries         map[ssa.Value]Pointer // pts(v) for each v in Config.Queries.
+	IndirectQueries map[ssa.Value]Pointer // pts(*v) for each v in Config.IndirectQueries.
+	Warnings        []Warning             // warnings of unsoundness
+}
+
+// A Pointer is an equivalence class of pointer-like values.
+//
+// A Pointer doesn't have a unique type because pointers of distinct
+// types may alias the same object.
+//
+type Pointer struct {
+	a *analysis
+	n nodeid
+}
+
+// A PointsToSet is a set of labels (locations or allocations).
+type PointsToSet struct {
+	a   *analysis // may be nil if pts is nil
+	pts *nodeset
+}
+
+func (s PointsToSet) String() string {
+	var buf bytes.Buffer
+	buf.WriteByte('[')
+	if s.pts != nil {
+		var space [50]int
+		for i, l := range s.pts.AppendTo(space[:0]) {
+			if i > 0 {
+				buf.WriteString(", ")
+			}
+			buf.WriteString(s.a.labelFor(nodeid(l)).String())
+		}
+	}
+	buf.WriteByte(']')
+	return buf.String()
+}
+
+// PointsTo returns the set of labels that this points-to set
+// contains.
+func (s PointsToSet) Labels() []*Label {
+	var labels []*Label
+	if s.pts != nil {
+		var space [50]int
+		for _, l := range s.pts.AppendTo(space[:0]) {
+			labels = append(labels, s.a.labelFor(nodeid(l)))
+		}
+	}
+	return labels
+}
+
+// If this PointsToSet came from a Pointer of interface kind
+// or a reflect.Value, DynamicTypes returns the set of dynamic
+// types that it may contain.  (For an interface, they will
+// always be concrete types.)
+//
+// The result is a mapping whose keys are the dynamic types to which
+// it may point.  For each pointer-like key type, the corresponding
+// map value is the PointsToSet for pointers of that type.
+//
+// The result is empty unless CanHaveDynamicTypes(T).
+//
+func (s PointsToSet) DynamicTypes() *typeutil.Map {
+	var tmap typeutil.Map
+	tmap.SetHasher(s.a.hasher)
+	if s.pts != nil {
+		var space [50]int
+		for _, x := range s.pts.AppendTo(space[:0]) {
+			ifaceObjId := nodeid(x)
+			if !s.a.isTaggedObject(ifaceObjId) {
+				continue // !CanHaveDynamicTypes(tDyn)
+			}
+			tDyn, v, indirect := s.a.taggedValue(ifaceObjId)
+			if indirect {
+				panic("indirect tagged object") // implement later
+			}
+			pts, ok := tmap.At(tDyn).(PointsToSet)
+			if !ok {
+				pts = PointsToSet{s.a, new(nodeset)}
+				tmap.Set(tDyn, pts)
+			}
+			pts.pts.addAll(&s.a.nodes[v].solve.pts)
+		}
+	}
+	return &tmap
+}
+
+// Intersects reports whether this points-to set and the
+// argument points-to set contain common members.
+func (x PointsToSet) Intersects(y PointsToSet) bool {
+	if x.pts == nil || y.pts == nil {
+		return false
+	}
+	// This takes Θ(|x|+|y|) time.
+	var z intsets.Sparse
+	z.Intersection(&x.pts.Sparse, &y.pts.Sparse)
+	return !z.IsEmpty()
+}
+
+func (p Pointer) String() string {
+	return fmt.Sprintf("n%d", p.n)
+}
+
+// PointsTo returns the points-to set of this pointer.
+func (p Pointer) PointsTo() PointsToSet {
+	if p.n == 0 {
+		return PointsToSet{}
+	}
+	return PointsToSet{p.a, &p.a.nodes[p.n].solve.pts}
+}
+
+// MayAlias reports whether the receiver pointer may alias
+// the argument pointer.
+func (p Pointer) MayAlias(q Pointer) bool {
+	return p.PointsTo().Intersects(q.PointsTo())
+}
+
+// DynamicTypes returns p.PointsTo().DynamicTypes().
+func (p Pointer) DynamicTypes() *typeutil.Map {
+	return p.PointsTo().DynamicTypes()
+}
diff --git a/go/pointer/callgraph.go b/go/pointer/callgraph.go
new file mode 100644
index 0000000..48e152e
--- /dev/null
+++ b/go/pointer/callgraph.go
@@ -0,0 +1,61 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package pointer
+
+// This file defines the internal (context-sensitive) call graph.
+
+import (
+	"fmt"
+	"go/token"
+
+	"golang.org/x/tools/go/ssa"
+)
+
+type cgnode struct {
+	fn         *ssa.Function
+	obj        nodeid      // start of this contour's object block
+	sites      []*callsite // ordered list of callsites within this function
+	callersite *callsite   // where called from, if known; nil for shared contours
+}
+
+// contour returns a description of this node's contour.
+func (n *cgnode) contour() string {
+	if n.callersite == nil {
+		return "shared contour"
+	}
+	if n.callersite.instr != nil {
+		return fmt.Sprintf("as called from %s", n.callersite.instr.Parent())
+	}
+	return fmt.Sprintf("as called from intrinsic (targets=n%d)", n.callersite.targets)
+}
+
+func (n *cgnode) String() string {
+	return fmt.Sprintf("cg%d:%s", n.obj, n.fn)
+}
+
+// A callsite represents a single call site within a cgnode;
+// it is implicitly context-sensitive.
+// callsites never represent calls to built-ins;
+// they are handled as intrinsics.
+//
+type callsite struct {
+	targets nodeid              // pts(·) contains objects for dynamically called functions
+	instr   ssa.CallInstruction // the call instruction; nil for synthetic/intrinsic
+}
+
+func (c *callsite) String() string {
+	if c.instr != nil {
+		return c.instr.Common().Description()
+	}
+	return "synthetic function call"
+}
+
+// pos returns the source position of this callsite, or token.NoPos if implicit.
+func (c *callsite) pos() token.Pos {
+	if c.instr != nil {
+		return c.instr.Pos()
+	}
+	return token.NoPos
+}
diff --git a/go/pointer/constraint.go b/go/pointer/constraint.go
new file mode 100644
index 0000000..e6371cc
--- /dev/null
+++ b/go/pointer/constraint.go
@@ -0,0 +1,151 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package pointer
+
+import (
+	"golang.org/x/tools/go/types"
+)
+
+type constraint interface {
+	// For a complex constraint, returns the nodeid of the pointer
+	// to which it is attached.   For addr and copy, returns dst.
+	ptr() nodeid
+
+	// renumber replaces each nodeid n in the constraint by mapping[n].
+	renumber(mapping []nodeid)
+
+	// presolve is a hook for constraint-specific behaviour during
+	// pre-solver optimization.  Typical implementations mark as
+	// indirect the set of nodes to which the solver will add copy
+	// edges or PTS labels.
+	presolve(h *hvn)
+
+	// solve is called for complex constraints when the pts for
+	// the node to which they are attached has changed.
+	solve(a *analysis, delta *nodeset)
+
+	String() string
+}
+
+// dst = &src
+// pts(dst) ⊇ {src}
+// A base constraint used to initialize the solver's pt sets
+type addrConstraint struct {
+	dst nodeid // (ptr)
+	src nodeid
+}
+
+func (c *addrConstraint) ptr() nodeid { return c.dst }
+func (c *addrConstraint) renumber(mapping []nodeid) {
+	c.dst = mapping[c.dst]
+	c.src = mapping[c.src]
+}
+
+// dst = src
+// A simple constraint represented directly as a copyTo graph edge.
+type copyConstraint struct {
+	dst nodeid // (ptr)
+	src nodeid
+}
+
+func (c *copyConstraint) ptr() nodeid { return c.dst }
+func (c *copyConstraint) renumber(mapping []nodeid) {
+	c.dst = mapping[c.dst]
+	c.src = mapping[c.src]
+}
+
+// dst = src[offset]
+// A complex constraint attached to src (the pointer)
+type loadConstraint struct {
+	offset uint32
+	dst    nodeid
+	src    nodeid // (ptr)
+}
+
+func (c *loadConstraint) ptr() nodeid { return c.src }
+func (c *loadConstraint) renumber(mapping []nodeid) {
+	c.dst = mapping[c.dst]
+	c.src = mapping[c.src]
+}
+
+// dst[offset] = src
+// A complex constraint attached to dst (the pointer)
+type storeConstraint struct {
+	offset uint32
+	dst    nodeid // (ptr)
+	src    nodeid
+}
+
+func (c *storeConstraint) ptr() nodeid { return c.dst }
+func (c *storeConstraint) renumber(mapping []nodeid) {
+	c.dst = mapping[c.dst]
+	c.src = mapping[c.src]
+}
+
+// dst = &src.f  or  dst = &src[0]
+// A complex constraint attached to dst (the pointer)
+type offsetAddrConstraint struct {
+	offset uint32
+	dst    nodeid
+	src    nodeid // (ptr)
+}
+
+func (c *offsetAddrConstraint) ptr() nodeid { return c.src }
+func (c *offsetAddrConstraint) renumber(mapping []nodeid) {
+	c.dst = mapping[c.dst]
+	c.src = mapping[c.src]
+}
+
+// dst = src.(typ)  where typ is an interface
+// A complex constraint attached to src (the interface).
+// No representation change: pts(dst) and pts(src) contains tagged objects.
+type typeFilterConstraint struct {
+	typ types.Type // an interface type
+	dst nodeid
+	src nodeid // (ptr)
+}
+
+func (c *typeFilterConstraint) ptr() nodeid { return c.src }
+func (c *typeFilterConstraint) renumber(mapping []nodeid) {
+	c.dst = mapping[c.dst]
+	c.src = mapping[c.src]
+}
+
+// dst = src.(typ)  where typ is a concrete type
+// A complex constraint attached to src (the interface).
+//
+// If exact, only tagged objects identical to typ are untagged.
+// If !exact, tagged objects assignable to typ are untagged too.
+// The latter is needed for various reflect operators, e.g. Send.
+//
+// This entails a representation change:
+// pts(src) contains tagged objects,
+// pts(dst) contains their payloads.
+type untagConstraint struct {
+	typ   types.Type // a concrete type
+	dst   nodeid
+	src   nodeid // (ptr)
+	exact bool
+}
+
+func (c *untagConstraint) ptr() nodeid { return c.src }
+func (c *untagConstraint) renumber(mapping []nodeid) {
+	c.dst = mapping[c.dst]
+	c.src = mapping[c.src]
+}
+
+// src.method(params...)
+// A complex constraint attached to iface.
+type invokeConstraint struct {
+	method *types.Func // the abstract method
+	iface  nodeid      // (ptr) the interface
+	params nodeid      // the start of the identity/params/results block
+}
+
+func (c *invokeConstraint) ptr() nodeid { return c.iface }
+func (c *invokeConstraint) renumber(mapping []nodeid) {
+	c.iface = mapping[c.iface]
+	c.params = mapping[c.params]
+}
diff --git a/go/pointer/doc.go b/go/pointer/doc.go
new file mode 100644
index 0000000..22e569c
--- /dev/null
+++ b/go/pointer/doc.go
@@ -0,0 +1,610 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+/*
+
+Package pointer implements Andersen's analysis, an inclusion-based
+pointer analysis algorithm first described in (Andersen, 1994).
+
+A pointer analysis relates every pointer expression in a whole program
+to the set of memory locations to which it might point.  This
+information can be used to construct a call graph of the program that
+precisely represents the destinations of dynamic function and method
+calls.  It can also be used to determine, for example, which pairs of
+channel operations operate on the same channel.
+
+The package allows the client to request a set of expressions of
+interest for which the points-to information will be returned once the
+analysis is complete.  In addition, the client may request that a
+callgraph is constructed.  The example program in example_test.go
+demonstrates both of these features.  Clients should not request more
+information than they need since it may increase the cost of the
+analysis significantly.
+
+
+CLASSIFICATION
+
+Our algorithm is INCLUSION-BASED: the points-to sets for x and y will
+be related by pts(y) ⊇ pts(x) if the program contains the statement
+y = x.
+
+It is FLOW-INSENSITIVE: it ignores all control flow constructs and the
+order of statements in a program.  It is therefore a "MAY ALIAS"
+analysis: its facts are of the form "P may/may not point to L",
+not "P must point to L".
+
+It is FIELD-SENSITIVE: it builds separate points-to sets for distinct
+fields, such as x and y in struct { x, y *int }.
+
+It is mostly CONTEXT-INSENSITIVE: most functions are analyzed once,
+so values can flow in at one call to the function and return out at
+another.  Only some smaller functions are analyzed with consideration
+of their calling context.
+
+It has a CONTEXT-SENSITIVE HEAP: objects are named by both allocation
+site and context, so the objects returned by two distinct calls to f:
+   func f() *T { return new(T) }
+are distinguished up to the limits of the calling context.
+
+It is a WHOLE PROGRAM analysis: it requires SSA-form IR for the
+complete Go program and summaries for native code.
+
+See the (Hind, PASTE'01) survey paper for an explanation of these terms.
+
+
+SOUNDNESS
+
+The analysis is fully sound when invoked on pure Go programs that do not
+use reflection or unsafe.Pointer conversions.  In other words, if there
+is any possible execution of the program in which pointer P may point to
+object O, the analysis will report that fact.
+
+
+REFLECTION
+
+By default, the "reflect" library is ignored by the analysis, as if all
+its functions were no-ops, but if the client enables the Reflection flag,
+the analysis will make a reasonable attempt to model the effects of
+calls into this library.  However, this comes at a significant
+performance cost, and not all features of that library are yet
+implemented.  In addition, some simplifying approximations must be made
+to ensure that the analysis terminates; for example, reflection can be
+used to construct an infinite set of types and values of those types,
+but the analysis arbitrarily bounds the depth of such types.
+
+Most but not all reflection operations are supported.
+In particular, addressable reflect.Values are not yet implemented, so
+operations such as (reflect.Value).Set have no analytic effect.
+
+
+UNSAFE POINTER CONVERSIONS
+
+The pointer analysis makes no attempt to understand aliasing between the
+operand x and result y of an unsafe.Pointer conversion:
+   y = (*T)(unsafe.Pointer(x))
+It is as if the conversion allocated an entirely new object:
+   y = new(T)
+
+
+NATIVE CODE
+
+The analysis cannot model the aliasing effects of functions written in
+languages other than Go, such as runtime intrinsics in C or assembly, or
+code accessed via cgo.  The result is as if such functions are no-ops.
+However, various important intrinsics are understood by the analysis,
+along with built-ins such as append.
+
+The analysis currently provides no way for users to specify the aliasing
+effects of native code.
+
+------------------------------------------------------------------------
+
+IMPLEMENTATION
+
+The remaining documentation is intended for package maintainers and
+pointer analysis specialists.  Maintainers should have a solid
+understanding of the referenced papers (especially those by H&L and PKH)
+before making making significant changes.
+
+The implementation is similar to that described in (Pearce et al,
+PASTE'04).  Unlike many algorithms which interleave constraint
+generation and solving, constructing the callgraph as they go, this
+implementation for the most part observes a phase ordering (generation
+before solving), with only simple (copy) constraints being generated
+during solving.  (The exception is reflection, which creates various
+constraints during solving as new types flow to reflect.Value
+operations.)  This improves the traction of presolver optimisations,
+but imposes certain restrictions, e.g. potential context sensitivity
+is limited since all variants must be created a priori.
+
+
+TERMINOLOGY
+
+A type is said to be "pointer-like" if it is a reference to an object.
+Pointer-like types include pointers and also interfaces, maps, channels,
+functions and slices.
+
+We occasionally use C's x->f notation to distinguish the case where x
+is a struct pointer from x.f where is a struct value.
+
+Pointer analysis literature (and our comments) often uses the notation
+dst=*src+offset to mean something different than what it means in Go.
+It means: for each node index p in pts(src), the node index p+offset is
+in pts(dst).  Similarly *dst+offset=src is used for store constraints
+and dst=src+offset for offset-address constraints.
+
+
+NODES
+
+Nodes are the key datastructure of the analysis, and have a dual role:
+they represent both constraint variables (equivalence classes of
+pointers) and members of points-to sets (things that can be pointed
+at, i.e. "labels").
+
+Nodes are naturally numbered.  The numbering enables compact
+representations of sets of nodes such as bitvectors (or BDDs); and the
+ordering enables a very cheap way to group related nodes together.  For
+example, passing n parameters consists of generating n parallel
+constraints from caller+i to callee+i for 0<=i<n.
+
+The zero nodeid means "not a pointer".  For simplicity, we generate flow
+constraints even for non-pointer types such as int.  The pointer
+equivalence (PE) presolver optimization detects which variables cannot
+point to anything; this includes not only all variables of non-pointer
+types (such as int) but also variables of pointer-like types if they are
+always nil, or are parameters to a function that is never called.
+
+Each node represents a scalar part of a value or object.
+Aggregate types (structs, tuples, arrays) are recursively flattened
+out into a sequential list of scalar component types, and all the
+elements of an array are represented by a single node.  (The
+flattening of a basic type is a list containing a single node.)
+
+Nodes are connected into a graph with various kinds of labelled edges:
+simple edges (or copy constraints) represent value flow.  Complex
+edges (load, store, etc) trigger the creation of new simple edges
+during the solving phase.
+
+
+OBJECTS
+
+Conceptually, an "object" is a contiguous sequence of nodes denoting
+an addressable location: something that a pointer can point to.  The
+first node of an object has a non-nil obj field containing information
+about the allocation: its size, context, and ssa.Value.
+
+Objects include:
+   - functions and globals;
+   - variable allocations in the stack frame or heap;
+   - maps, channels and slices created by calls to make();
+   - allocations to construct an interface;
+   - allocations caused by conversions, e.g. []byte(str).
+   - arrays allocated by calls to append();
+
+Many objects have no Go types.  For example, the func, map and chan type
+kinds in Go are all varieties of pointers, but their respective objects
+are actual functions (executable code), maps (hash tables), and channels
+(synchronized queues).  Given the way we model interfaces, they too are
+pointers to "tagged" objects with no Go type.  And an *ssa.Global denotes
+the address of a global variable, but the object for a Global is the
+actual data.  So, the types of an ssa.Value that creates an object is
+"off by one indirection": a pointer to the object.
+
+The individual nodes of an object are sometimes referred to as "labels".
+
+For uniformity, all objects have a non-zero number of fields, even those
+of the empty type struct{}.  (All arrays are treated as if of length 1,
+so there are no empty arrays.  The empty tuple is never address-taken,
+so is never an object.)
+
+
+TAGGED OBJECTS
+
+An tagged object has the following layout:
+
+    T          -- obj.flags ⊇ {otTagged}
+    v
+    ...
+
+The T node's typ field is the dynamic type of the "payload": the value
+v which follows, flattened out.  The T node's obj has the otTagged
+flag.
+
+Tagged objects are needed when generalizing across types: interfaces,
+reflect.Values, reflect.Types.  Each of these three types is modelled
+as a pointer that exclusively points to tagged objects.
+
+Tagged objects may be indirect (obj.flags ⊇ {otIndirect}) meaning that
+the value v is not of type T but *T; this is used only for
+reflect.Values that represent lvalues.  (These are not implemented yet.)
+
+
+ANALYSIS ABSTRACTION OF EACH TYPE
+
+Variables of the following "scalar" types may be represented by a
+single node: basic types, pointers, channels, maps, slices, 'func'
+pointers, interfaces.
+
+Pointers
+  Nothing to say here, oddly.
+
+Basic types (bool, string, numbers, unsafe.Pointer)
+  Currently all fields in the flattening of a type, including
+  non-pointer basic types such as int, are represented in objects and
+  values.  Though non-pointer nodes within values are uninteresting,
+  non-pointer nodes in objects may be useful (if address-taken)
+  because they permit the analysis to deduce, in this example,
+
+     var s struct{ ...; x int; ... }
+     p := &s.x
+
+  that p points to s.x.  If we ignored such object fields, we could only
+  say that p points somewhere within s.
+
+  All other basic types are ignored.  Expressions of these types have
+  zero nodeid, and fields of these types within aggregate other types
+  are omitted.
+
+  unsafe.Pointers are not modelled as pointers, so a conversion of an
+  unsafe.Pointer to *T is (unsoundly) treated equivalent to new(T).
+
+Channels
+  An expression of type 'chan T' is a kind of pointer that points
+  exclusively to channel objects, i.e. objects created by MakeChan (or
+  reflection).
+
+  'chan T' is treated like *T.
+  *ssa.MakeChan is treated as equivalent to new(T).
+  *ssa.Send and receive (*ssa.UnOp(ARROW)) and are equivalent to store
+   and load.
+
+Maps
+  An expression of type 'map[K]V' is a kind of pointer that points
+  exclusively to map objects, i.e. objects created by MakeMap (or
+  reflection).
+
+  map K[V] is treated like *M where M = struct{k K; v V}.
+  *ssa.MakeMap is equivalent to new(M).
+  *ssa.MapUpdate is equivalent to *y=x where *y and x have type M.
+  *ssa.Lookup is equivalent to y=x.v where x has type *M.
+
+Slices
+  A slice []T, which dynamically resembles a struct{array *T, len, cap int},
+  is treated as if it were just a *T pointer; the len and cap fields are
+  ignored.
+
+  *ssa.MakeSlice is treated like new([1]T): an allocation of a
+   singleton array.
+  *ssa.Index on a slice is equivalent to a load.
+  *ssa.IndexAddr on a slice returns the address of the sole element of the
+  slice, i.e. the same address.
+  *ssa.Slice is treated as a simple copy.
+
+Functions
+  An expression of type 'func...' is a kind of pointer that points
+  exclusively to function objects.
+
+  A function object has the following layout:
+
+     identity         -- typ:*types.Signature; obj.flags ⊇ {otFunction}
+     params_0         -- (the receiver, if a method)
+     ...
+     params_n-1
+     results_0
+     ...
+     results_m-1
+
+  There may be multiple function objects for the same *ssa.Function
+  due to context-sensitive treatment of some functions.
+
+  The first node is the function's identity node.
+  Associated with every callsite is a special "targets" variable,
+  whose pts() contains the identity node of each function to which
+  the call may dispatch.  Identity words are not otherwise used during
+  the analysis, but we construct the call graph from the pts()
+  solution for such nodes.
+
+  The following block of contiguous nodes represents the flattened-out
+  types of the parameters ("P-block") and results ("R-block") of the
+  function object.
+
+  The treatment of free variables of closures (*ssa.FreeVar) is like
+  that of global variables; it is not context-sensitive.
+  *ssa.MakeClosure instructions create copy edges to Captures.
+
+  A Go value of type 'func' (i.e. a pointer to one or more functions)
+  is a pointer whose pts() contains function objects.  The valueNode()
+  for an *ssa.Function returns a singleton for that function.
+
+Interfaces
+  An expression of type 'interface{...}' is a kind of pointer that
+  points exclusively to tagged objects.  All tagged objects pointed to
+  by an interface are direct (the otIndirect flag is clear) and
+  concrete (the tag type T is not itself an interface type).  The
+  associated ssa.Value for an interface's tagged objects may be an
+  *ssa.MakeInterface instruction, or nil if the tagged object was
+  created by an instrinsic (e.g. reflection).
+
+  Constructing an interface value causes generation of constraints for
+  all of the concrete type's methods; we can't tell a priori which
+  ones may be called.
+
+  TypeAssert y = x.(T) is implemented by a dynamic constraint
+  triggered by each tagged object O added to pts(x): a typeFilter
+  constraint if T is an interface type, or an untag constraint if T is
+  a concrete type.  A typeFilter tests whether O.typ implements T; if
+  so, O is added to pts(y).  An untagFilter tests whether O.typ is
+  assignable to T,and if so, a copy edge O.v -> y is added.
+
+  ChangeInterface is a simple copy because the representation of
+  tagged objects is independent of the interface type (in contrast
+  to the "method tables" approach used by the gc runtime).
+
+  y := Invoke x.m(...) is implemented by allocating contiguous P/R
+  blocks for the callsite and adding a dynamic rule triggered by each
+  tagged object added to pts(x).  The rule adds param/results copy
+  edges to/from each discovered concrete method.
+
+  (Q. Why do we model an interface as a pointer to a pair of type and
+  value, rather than as a pair of a pointer to type and a pointer to
+  value?
+  A. Control-flow joins would merge interfaces ({T1}, {V1}) and ({T2},
+  {V2}) to make ({T1,T2}, {V1,V2}), leading to the infeasible and
+  type-unsafe combination (T1,V2).  Treating the value and its concrete
+  type as inseparable makes the analysis type-safe.)
+
+reflect.Value
+  A reflect.Value is modelled very similar to an interface{}, i.e. as
+  a pointer exclusively to tagged objects, but with two generalizations.
+
+  1) a reflect.Value that represents an lvalue points to an indirect
+     (obj.flags ⊇ {otIndirect}) tagged object, which has a similar
+     layout to an tagged object except that the value is a pointer to
+     the dynamic type.  Indirect tagged objects preserve the correct
+     aliasing so that mutations made by (reflect.Value).Set can be
+     observed.
+
+     Indirect objects only arise when an lvalue is derived from an
+     rvalue by indirection, e.g. the following code:
+
+        type S struct { X T }
+        var s S
+        var i interface{} = &s    // i points to a *S-tagged object (from MakeInterface)
+        v1 := reflect.ValueOf(i)  // v1 points to same *S-tagged object as i
+        v2 := v1.Elem()           // v2 points to an indirect S-tagged object, pointing to s
+        v3 := v2.FieldByName("X") // v3 points to an indirect int-tagged object, pointing to s.X
+        v3.Set(y)                 // pts(s.X) ⊇ pts(y)
+
+     Whether indirect or not, the concrete type of the tagged object
+     corresponds to the user-visible dynamic type, and the existence
+     of a pointer is an implementation detail.
+
+     (NB: indirect tagged objects are not yet implemented)
+
+  2) The dynamic type tag of a tagged object pointed to by a
+     reflect.Value may be an interface type; it need not be concrete.
+
+     This arises in code such as this:
+        tEface := reflect.TypeOf(new(interface{}).Elem() // interface{}
+        eface := reflect.Zero(tEface)
+     pts(eface) is a singleton containing an interface{}-tagged
+     object.  That tagged object's payload is an interface{} value,
+     i.e. the pts of the payload contains only concrete-tagged
+     objects, although in this example it's the zero interface{} value,
+     so its pts is empty.
+
+reflect.Type
+  Just as in the real "reflect" library, we represent a reflect.Type
+  as an interface whose sole implementation is the concrete type,
+  *reflect.rtype.  (This choice is forced on us by go/types: clients
+  cannot fabricate types with arbitrary method sets.)
+
+  rtype instances are canonical: there is at most one per dynamic
+  type.  (rtypes are in fact large structs but since identity is all
+  that matters, we represent them by a single node.)
+
+  The payload of each *rtype-tagged object is an *rtype pointer that
+  points to exactly one such canonical rtype object.  We exploit this
+  by setting the node.typ of the payload to the dynamic type, not
+  '*rtype'.  This saves us an indirection in each resolution rule.  As
+  an optimisation, *rtype-tagged objects are canonicalized too.
+
+
+Aggregate types:
+
+Aggregate types are treated as if all directly contained
+aggregates are recursively flattened out.
+
+Structs
+  *ssa.Field y = x.f creates a simple edge to y from x's node at f's offset.
+
+  *ssa.FieldAddr y = &x->f requires a dynamic closure rule to create
+   simple edges for each struct discovered in pts(x).
+
+  The nodes of a struct consist of a special 'identity' node (whose
+  type is that of the struct itself), followed by the nodes for all
+  the struct's fields, recursively flattened out.  A pointer to the
+  struct is a pointer to its identity node.  That node allows us to
+  distinguish a pointer to a struct from a pointer to its first field.
+
+  Field offsets are logical field offsets (plus one for the identity
+  node), so the sizes of the fields can be ignored by the analysis.
+
+  (The identity node is non-traditional but enables the distiction
+  described above, which is valuable for code comprehension tools.
+  Typical pointer analyses for C, whose purpose is compiler
+  optimization, must soundly model unsafe.Pointer (void*) conversions,
+  and this requires fidelity to the actual memory layout using physical
+  field offsets.)
+
+  *ssa.Field y = x.f creates a simple edge to y from x's node at f's offset.
+
+  *ssa.FieldAddr y = &x->f requires a dynamic closure rule to create
+   simple edges for each struct discovered in pts(x).
+
+Arrays
+  We model an array by an identity node (whose type is that of the
+  array itself) followed by a node representing all the elements of
+  the array; the analysis does not distinguish elements with different
+  indices.  Effectively, an array is treated like struct{elem T}, a
+  load y=x[i] like y=x.elem, and a store x[i]=y like x.elem=y; the
+  index i is ignored.
+
+  A pointer to an array is pointer to its identity node.  (A slice is
+  also a pointer to an array's identity node.)  The identity node
+  allows us to distinguish a pointer to an array from a pointer to one
+  of its elements, but it is rather costly because it introduces more
+  offset constraints into the system.  Furthermore, sound treatment of
+  unsafe.Pointer would require us to dispense with this node.
+
+  Arrays may be allocated by Alloc, by make([]T), by calls to append,
+  and via reflection.
+
+Tuples (T, ...)
+  Tuples are treated like structs with naturally numbered fields.
+  *ssa.Extract is analogous to *ssa.Field.
+
+  However, tuples have no identity field since by construction, they
+  cannot be address-taken.
+
+
+FUNCTION CALLS
+
+  There are three kinds of function call:
+  (1) static "call"-mode calls of functions.
+  (2) dynamic "call"-mode calls of functions.
+  (3) dynamic "invoke"-mode calls of interface methods.
+  Cases 1 and 2 apply equally to methods and standalone functions.
+
+  Static calls.
+    A static call consists three steps:
+    - finding the function object of the callee;
+    - creating copy edges from the actual parameter value nodes to the
+      P-block in the function object (this includes the receiver if
+      the callee is a method);
+    - creating copy edges from the R-block in the function object to
+      the value nodes for the result of the call.
+
+    A static function call is little more than two struct value copies
+    between the P/R blocks of caller and callee:
+
+       callee.P = caller.P
+       caller.R = callee.R
+
+    Context sensitivity
+
+      Static calls (alone) may be treated context sensitively,
+      i.e. each callsite may cause a distinct re-analysis of the
+      callee, improving precision.  Our current context-sensitivity
+      policy treats all intrinsics and getter/setter methods in this
+      manner since such functions are small and seem like an obvious
+      source of spurious confluences, though this has not yet been
+      evaluated.
+
+  Dynamic function calls
+
+    Dynamic calls work in a similar manner except that the creation of
+    copy edges occurs dynamically, in a similar fashion to a pair of
+    struct copies in which the callee is indirect:
+
+       callee->P = caller.P
+       caller.R = callee->R
+
+    (Recall that the function object's P- and R-blocks are contiguous.)
+
+  Interface method invocation
+
+    For invoke-mode calls, we create a params/results block for the
+    callsite and attach a dynamic closure rule to the interface.  For
+    each new tagged object that flows to the interface, we look up
+    the concrete method, find its function object, and connect its P/R
+    blocks to the callsite's P/R blocks, adding copy edges to the graph
+    during solving.
+
+  Recording call targets
+
+    The analysis notifies its clients of each callsite it encounters,
+    passing a CallSite interface.  Among other things, the CallSite
+    contains a synthetic constraint variable ("targets") whose
+    points-to solution includes the set of all function objects to
+    which the call may dispatch.
+
+    It is via this mechanism that the callgraph is made available.
+    Clients may also elect to be notified of callgraph edges directly;
+    internally this just iterates all "targets" variables' pts(·)s.
+
+
+PRESOLVER
+
+We implement Hash-Value Numbering (HVN), a pre-solver constraint
+optimization described in Hardekopf & Lin, SAS'07.  This is documented
+in more detail in hvn.go.  We intend to add its cousins HR and HU in
+future.
+
+
+SOLVER
+
+The solver is currently a naive Andersen-style implementation; it does
+not perform online cycle detection, though we plan to add solver
+optimisations such as Hybrid- and Lazy- Cycle Detection from (Hardekopf
+& Lin, PLDI'07).
+
+It uses difference propagation (Pearce et al, SQC'04) to avoid
+redundant re-triggering of closure rules for values already seen.
+
+Points-to sets are represented using sparse bit vectors (similar to
+those used in LLVM and gcc), which are more space- and time-efficient
+than sets based on Go's built-in map type or dense bit vectors.
+
+Nodes are permuted prior to solving so that object nodes (which may
+appear in points-to sets) are lower numbered than non-object (var)
+nodes.  This improves the density of the set over which the PTSs
+range, and thus the efficiency of the representation.
+
+Partly thanks to avoiding map iteration, the execution of the solver is
+100% deterministic, a great help during debugging.
+
+
+FURTHER READING
+
+Andersen, L. O. 1994. Program analysis and specialization for the C
+programming language. Ph.D. dissertation. DIKU, University of
+Copenhagen.
+
+David J. Pearce, Paul H. J. Kelly, and Chris Hankin. 2004.  Efficient
+field-sensitive pointer analysis for C. In Proceedings of the 5th ACM
+SIGPLAN-SIGSOFT workshop on Program analysis for software tools and
+engineering (PASTE '04). ACM, New York, NY, USA, 37-42.
+http://doi.acm.org/10.1145/996821.996835
+
+David J. Pearce, Paul H. J. Kelly, and Chris Hankin. 2004. Online
+Cycle Detection and Difference Propagation: Applications to Pointer
+Analysis. Software Quality Control 12, 4 (December 2004), 311-337.
+http://dx.doi.org/10.1023/B:SQJO.0000039791.93071.a2
+
+David Grove and Craig Chambers. 2001. A framework for call graph
+construction algorithms. ACM Trans. Program. Lang. Syst. 23, 6
+(November 2001), 685-746.
+http://doi.acm.org/10.1145/506315.506316
+
+Ben Hardekopf and Calvin Lin. 2007. The ant and the grasshopper: fast
+and accurate pointer analysis for millions of lines of code. In
+Proceedings of the 2007 ACM SIGPLAN conference on Programming language
+design and implementation (PLDI '07). ACM, New York, NY, USA, 290-299.
+http://doi.acm.org/10.1145/1250734.1250767
+
+Ben Hardekopf and Calvin Lin. 2007. Exploiting pointer and location
+equivalence to optimize pointer analysis. In Proceedings of the 14th
+international conference on Static Analysis (SAS'07), Hanne Riis
+Nielson and Gilberto Filé (Eds.). Springer-Verlag, Berlin, Heidelberg,
+265-280.
+
+Atanas Rountev and Satish Chandra. 2000. Off-line variable substitution
+for scaling points-to analysis. In Proceedings of the ACM SIGPLAN 2000
+conference on Programming language design and implementation (PLDI '00).
+ACM, New York, NY, USA, 47-56. DOI=10.1145/349299.349310
+http://doi.acm.org/10.1145/349299.349310
+
+*/
+package pointer // import "golang.org/x/tools/go/pointer"
diff --git a/go/pointer/example_test.go b/go/pointer/example_test.go
new file mode 100644
index 0000000..ba70557
--- /dev/null
+++ b/go/pointer/example_test.go
@@ -0,0 +1,126 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package pointer_test
+
+import (
+	"fmt"
+	"sort"
+
+	"golang.org/x/tools/go/callgraph"
+	"golang.org/x/tools/go/loader"
+	"golang.org/x/tools/go/pointer"
+	"golang.org/x/tools/go/ssa"
+	"golang.org/x/tools/go/ssa/ssautil"
+)
+
+// This program demonstrates how to use the pointer analysis to
+// obtain a conservative call-graph of a Go program.
+// It also shows how to compute the points-to set of a variable,
+// in this case, (C).f's ch parameter.
+//
+func Example() {
+	const myprog = `
+package main
+
+import "fmt"
+
+type I interface {
+	f(map[string]int)
+}
+
+type C struct{}
+
+func (C) f(m map[string]int) {
+	fmt.Println("C.f()")
+}
+
+func main() {
+	var i I = C{}
+	x := map[string]int{"one":1}
+	i.f(x) // dynamic method call
+}
+`
+	var conf loader.Config
+
+	// Parse the input file, a string.
+	// (Command-line tools should use conf.FromArgs.)
+	file, err := conf.ParseFile("myprog.go", myprog)
+	if err != nil {
+		fmt.Print(err) // parse error
+		return
+	}
+
+	// Create single-file main package and import its dependencies.
+	conf.CreateFromFiles("main", file)
+
+	iprog, err := conf.Load()
+	if err != nil {
+		fmt.Print(err) // type error in some package
+		return
+	}
+
+	// Create SSA-form program representation.
+	prog := ssautil.CreateProgram(iprog, 0)
+	mainPkg := prog.Package(iprog.Created[0].Pkg)
+
+	// Build SSA code for bodies of all functions in the whole program.
+	prog.BuildAll()
+
+	// Configure the pointer analysis to build a call-graph.
+	config := &pointer.Config{
+		Mains:          []*ssa.Package{mainPkg},
+		BuildCallGraph: true,
+	}
+
+	// Query points-to set of (C).f's parameter m, a map.
+	C := mainPkg.Type("C").Type()
+	Cfm := prog.LookupMethod(C, mainPkg.Object, "f").Params[1]
+	config.AddQuery(Cfm)
+
+	// Run the pointer analysis.
+	result, err := pointer.Analyze(config)
+	if err != nil {
+		panic(err) // internal error in pointer analysis
+	}
+
+	// Find edges originating from the main package.
+	// By converting to strings, we de-duplicate nodes
+	// representing the same function due to context sensitivity.
+	var edges []string
+	callgraph.GraphVisitEdges(result.CallGraph, func(edge *callgraph.Edge) error {
+		caller := edge.Caller.Func
+		if caller.Pkg == mainPkg {
+			edges = append(edges, fmt.Sprint(caller, " --> ", edge.Callee.Func))
+		}
+		return nil
+	})
+
+	// Print the edges in sorted order.
+	sort.Strings(edges)
+	for _, edge := range edges {
+		fmt.Println(edge)
+	}
+	fmt.Println()
+
+	// Print the labels of (C).f(m)'s points-to set.
+	fmt.Println("m may point to:")
+	var labels []string
+	for _, l := range result.Queries[Cfm].PointsTo().Labels() {
+		label := fmt.Sprintf("  %s: %s", prog.Fset.Position(l.Pos()), l)
+		labels = append(labels, label)
+	}
+	sort.Strings(labels)
+	for _, label := range labels {
+		fmt.Println(label)
+	}
+
+	// Output:
+	// (main.C).f --> fmt.Println
+	// main.init --> fmt.init
+	// main.main --> (main.C).f
+	//
+	// m may point to:
+	//   myprog.go:18:21: makemap
+}
diff --git a/go/pointer/gen.go b/go/pointer/gen.go
new file mode 100644
index 0000000..6c256ac
--- /dev/null
+++ b/go/pointer/gen.go
@@ -0,0 +1,1292 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package pointer
+
+// This file defines the constraint generation phase.
+
+// TODO(adonovan): move the constraint definitions and the store() etc
+// functions which add them (and are also used by the solver) into a
+// new file, constraints.go.
+
+import (
+	"fmt"
+	"go/token"
+
+	"golang.org/x/tools/go/callgraph"
+	"golang.org/x/tools/go/ssa"
+	"golang.org/x/tools/go/types"
+)
+
+var (
+	tEface     = types.NewInterface(nil, nil).Complete()
+	tInvalid   = types.Typ[types.Invalid]
+	tUnsafePtr = types.Typ[types.UnsafePointer]
+)
+
+// ---------- Node creation ----------
+
+// nextNode returns the index of the next unused node.
+func (a *analysis) nextNode() nodeid {
+	return nodeid(len(a.nodes))
+}
+
+// addNodes creates nodes for all scalar elements in type typ, and
+// returns the id of the first one, or zero if the type was
+// analytically uninteresting.
+//
+// comment explains the origin of the nodes, as a debugging aid.
+//
+func (a *analysis) addNodes(typ types.Type, comment string) nodeid {
+	id := a.nextNode()
+	for _, fi := range a.flatten(typ) {
+		a.addOneNode(fi.typ, comment, fi)
+	}
+	if id == a.nextNode() {
+		return 0 // type contained no pointers
+	}
+	return id
+}
+
+// addOneNode creates a single node with type typ, and returns its id.
+//
+// typ should generally be scalar (except for tagged.T nodes
+// and struct/array identity nodes).  Use addNodes for non-scalar types.
+//
+// comment explains the origin of the nodes, as a debugging aid.
+// subelement indicates the subelement, e.g. ".a.b[*].c".
+//
+func (a *analysis) addOneNode(typ types.Type, comment string, subelement *fieldInfo) nodeid {
+	id := a.nextNode()
+	a.nodes = append(a.nodes, &node{typ: typ, subelement: subelement, solve: new(solverState)})
+	if a.log != nil {
+		fmt.Fprintf(a.log, "\tcreate n%d %s for %s%s\n",
+			id, typ, comment, subelement.path())
+	}
+	return id
+}
+
+// setValueNode associates node id with the value v.
+// cgn identifies the context iff v is a local variable.
+//
+func (a *analysis) setValueNode(v ssa.Value, id nodeid, cgn *cgnode) {
+	if cgn != nil {
+		a.localval[v] = id
+	} else {
+		a.globalval[v] = id
+	}
+	if a.log != nil {
+		fmt.Fprintf(a.log, "\tval[%s] = n%d  (%T)\n", v.Name(), id, v)
+	}
+
+	// Due to context-sensitivity, we may encounter the same Value
+	// in many contexts. We merge them to a canonical node, since
+	// that's what all clients want.
+
+	// Record the (v, id) relation if the client has queried pts(v).
+	if _, ok := a.config.Queries[v]; ok {
+		t := v.Type()
+		ptr, ok := a.result.Queries[v]
+		if !ok {
+			// First time?  Create the canonical query node.
+			ptr = Pointer{a, a.addNodes(t, "query")}
+			a.result.Queries[v] = ptr
+		}
+		a.result.Queries[v] = ptr
+		a.copy(ptr.n, id, a.sizeof(t))
+	}
+
+	// Record the (*v, id) relation if the client has queried pts(*v).
+	if _, ok := a.config.IndirectQueries[v]; ok {
+		t := v.Type()
+		ptr, ok := a.result.IndirectQueries[v]
+		if !ok {
+			// First time? Create the canonical indirect query node.
+			ptr = Pointer{a, a.addNodes(v.Type(), "query.indirect")}
+			a.result.IndirectQueries[v] = ptr
+		}
+		a.genLoad(cgn, ptr.n, v, 0, a.sizeof(t))
+	}
+}
+
+// endObject marks the end of a sequence of calls to addNodes denoting
+// a single object allocation.
+//
+// obj is the start node of the object, from a prior call to nextNode.
+// Its size, flags and optional data will be updated.
+//
+func (a *analysis) endObject(obj nodeid, cgn *cgnode, data interface{}) *object {
+	// Ensure object is non-empty by padding;
+	// the pad will be the object node.
+	size := uint32(a.nextNode() - obj)
+	if size == 0 {
+		a.addOneNode(tInvalid, "padding", nil)
+	}
+	objNode := a.nodes[obj]
+	o := &object{
+		size: size, // excludes padding
+		cgn:  cgn,
+		data: data,
+	}
+	objNode.obj = o
+
+	return o
+}
+
+// makeFunctionObject creates and returns a new function object
+// (contour) for fn, and returns the id of its first node.  It also
+// enqueues fn for subsequent constraint generation.
+//
+// For a context-sensitive contour, callersite identifies the sole
+// callsite; for shared contours, caller is nil.
+//
+func (a *analysis) makeFunctionObject(fn *ssa.Function, callersite *callsite) nodeid {
+	if a.log != nil {
+		fmt.Fprintf(a.log, "\t---- makeFunctionObject %s\n", fn)
+	}
+
+	// obj is the function object (identity, params, results).
+	obj := a.nextNode()
+	cgn := a.makeCGNode(fn, obj, callersite)
+	sig := fn.Signature
+	a.addOneNode(sig, "func.cgnode", nil) // (scalar with Signature type)
+	if recv := sig.Recv(); recv != nil {
+		a.addNodes(recv.Type(), "func.recv")
+	}
+	a.addNodes(sig.Params(), "func.params")
+	a.addNodes(sig.Results(), "func.results")
+	a.endObject(obj, cgn, fn).flags |= otFunction
+
+	if a.log != nil {
+		fmt.Fprintf(a.log, "\t----\n")
+	}
+
+	// Queue it up for constraint processing.
+	a.genq = append(a.genq, cgn)
+
+	return obj
+}
+
+// makeTagged creates a tagged object of type typ.
+func (a *analysis) makeTagged(typ types.Type, cgn *cgnode, data interface{}) nodeid {
+	obj := a.addOneNode(typ, "tagged.T", nil) // NB: type may be non-scalar!
+	a.addNodes(typ, "tagged.v")
+	a.endObject(obj, cgn, data).flags |= otTagged
+	return obj
+}
+
+// makeRtype returns the canonical tagged object of type *rtype whose
+// payload points to the sole rtype object for T.
+//
+// TODO(adonovan): move to reflect.go; it's part of the solver really.
+//
+func (a *analysis) makeRtype(T types.Type) nodeid {
+	if v := a.rtypes.At(T); v != nil {
+		return v.(nodeid)
+	}
+
+	// Create the object for the reflect.rtype itself, which is
+	// ordinarily a large struct but here a single node will do.
+	obj := a.nextNode()
+	a.addOneNode(T, "reflect.rtype", nil)
+	a.endObject(obj, nil, T)
+
+	id := a.makeTagged(a.reflectRtypePtr, nil, T)
+	a.nodes[id+1].typ = T // trick (each *rtype tagged object is a singleton)
+	a.addressOf(a.reflectRtypePtr, id+1, obj)
+
+	a.rtypes.Set(T, id)
+	return id
+}
+
+// rtypeValue returns the type of the *reflect.rtype-tagged object obj.
+func (a *analysis) rtypeTaggedValue(obj nodeid) types.Type {
+	tDyn, t, _ := a.taggedValue(obj)
+	if tDyn != a.reflectRtypePtr {
+		panic(fmt.Sprintf("not a *reflect.rtype-tagged object: obj=n%d tag=%v payload=n%d", obj, tDyn, t))
+	}
+	return a.nodes[t].typ
+}
+
+// valueNode returns the id of the value node for v, creating it (and
+// the association) as needed.  It may return zero for uninteresting
+// values containing no pointers.
+//
+func (a *analysis) valueNode(v ssa.Value) nodeid {
+	// Value nodes for locals are created en masse by genFunc.
+	if id, ok := a.localval[v]; ok {
+		return id
+	}
+
+	// Value nodes for globals are created on demand.
+	id, ok := a.globalval[v]
+	if !ok {
+		var comment string
+		if a.log != nil {
+			comment = v.String()
+		}
+		id = a.addNodes(v.Type(), comment)
+		if obj := a.objectNode(nil, v); obj != 0 {
+			a.addressOf(v.Type(), id, obj)
+		}
+		a.setValueNode(v, id, nil)
+	}
+	return id
+}
+
+// valueOffsetNode ascertains the node for tuple/struct value v,
+// then returns the node for its subfield #index.
+//
+func (a *analysis) valueOffsetNode(v ssa.Value, index int) nodeid {
+	id := a.valueNode(v)
+	if id == 0 {
+		panic(fmt.Sprintf("cannot offset within n0: %s = %s", v.Name(), v))
+	}
+	return id + nodeid(a.offsetOf(v.Type(), index))
+}
+
+// isTaggedObject reports whether object obj is a tagged object.
+func (a *analysis) isTaggedObject(obj nodeid) bool {
+	return a.nodes[obj].obj.flags&otTagged != 0
+}
+
+// taggedValue returns the dynamic type tag, the (first node of the)
+// payload, and the indirect flag of the tagged object starting at id.
+// Panic ensues if !isTaggedObject(id).
+//
+func (a *analysis) taggedValue(obj nodeid) (tDyn types.Type, v nodeid, indirect bool) {
+	n := a.nodes[obj]
+	flags := n.obj.flags
+	if flags&otTagged == 0 {
+		panic(fmt.Sprintf("not a tagged object: n%d", obj))
+	}
+	return n.typ, obj + 1, flags&otIndirect != 0
+}
+
+// funcParams returns the first node of the params (P) block of the
+// function whose object node (obj.flags&otFunction) is id.
+//
+func (a *analysis) funcParams(id nodeid) nodeid {
+	n := a.nodes[id]
+	if n.obj == nil || n.obj.flags&otFunction == 0 {
+		panic(fmt.Sprintf("funcParams(n%d): not a function object block", id))
+	}
+	return id + 1
+}
+
+// funcResults returns the first node of the results (R) block of the
+// function whose object node (obj.flags&otFunction) is id.
+//
+func (a *analysis) funcResults(id nodeid) nodeid {
+	n := a.nodes[id]
+	if n.obj == nil || n.obj.flags&otFunction == 0 {
+		panic(fmt.Sprintf("funcResults(n%d): not a function object block", id))
+	}
+	sig := n.typ.(*types.Signature)
+	id += 1 + nodeid(a.sizeof(sig.Params()))
+	if sig.Recv() != nil {
+		id += nodeid(a.sizeof(sig.Recv().Type()))
+	}
+	return id
+}
+
+// ---------- Constraint creation ----------
+
+// copy creates a constraint of the form dst = src.
+// sizeof is the width (in logical fields) of the copied type.
+//
+func (a *analysis) copy(dst, src nodeid, sizeof uint32) {
+	if src == dst || sizeof == 0 {
+		return // trivial
+	}
+	if src == 0 || dst == 0 {
+		panic(fmt.Sprintf("ill-typed copy dst=n%d src=n%d", dst, src))
+	}
+	for i := uint32(0); i < sizeof; i++ {
+		a.addConstraint(&copyConstraint{dst, src})
+		src++
+		dst++
+	}
+}
+
+// addressOf creates a constraint of the form id = &obj.
+// T is the type of the address.
+func (a *analysis) addressOf(T types.Type, id, obj nodeid) {
+	if id == 0 {
+		panic("addressOf: zero id")
+	}
+	if obj == 0 {
+		panic("addressOf: zero obj")
+	}
+	if a.shouldTrack(T) {
+		a.addConstraint(&addrConstraint{id, obj})
+	}
+}
+
+// load creates a load constraint of the form dst = src[offset].
+// offset is the pointer offset in logical fields.
+// sizeof is the width (in logical fields) of the loaded type.
+//
+func (a *analysis) load(dst, src nodeid, offset, sizeof uint32) {
+	if dst == 0 {
+		return // load of non-pointerlike value
+	}
+	if src == 0 && dst == 0 {
+		return // non-pointerlike operation
+	}
+	if src == 0 || dst == 0 {
+		panic(fmt.Sprintf("ill-typed load dst=n%d src=n%d", dst, src))
+	}
+	for i := uint32(0); i < sizeof; i++ {
+		a.addConstraint(&loadConstraint{offset, dst, src})
+		offset++
+		dst++
+	}
+}
+
+// store creates a store constraint of the form dst[offset] = src.
+// offset is the pointer offset in logical fields.
+// sizeof is the width (in logical fields) of the stored type.
+//
+func (a *analysis) store(dst, src nodeid, offset uint32, sizeof uint32) {
+	if src == 0 {
+		return // store of non-pointerlike value
+	}
+	if src == 0 && dst == 0 {
+		return // non-pointerlike operation
+	}
+	if src == 0 || dst == 0 {
+		panic(fmt.Sprintf("ill-typed store dst=n%d src=n%d", dst, src))
+	}
+	for i := uint32(0); i < sizeof; i++ {
+		a.addConstraint(&storeConstraint{offset, dst, src})
+		offset++
+		src++
+	}
+}
+
+// offsetAddr creates an offsetAddr constraint of the form dst = &src.#offset.
+// offset is the field offset in logical fields.
+// T is the type of the address.
+//
+func (a *analysis) offsetAddr(T types.Type, dst, src nodeid, offset uint32) {
+	if !a.shouldTrack(T) {
+		return
+	}
+	if offset == 0 {
+		// Simplify  dst = &src->f0
+		//       to  dst = src
+		// (NB: this optimisation is defeated by the identity
+		// field prepended to struct and array objects.)
+		a.copy(dst, src, 1)
+	} else {
+		a.addConstraint(&offsetAddrConstraint{offset, dst, src})
+	}
+}
+
+// typeAssert creates a typeFilter or untag constraint of the form dst = src.(T):
+// typeFilter for an interface, untag for a concrete type.
+// The exact flag is specified as for untagConstraint.
+//
+func (a *analysis) typeAssert(T types.Type, dst, src nodeid, exact bool) {
+	if isInterface(T) {
+		a.addConstraint(&typeFilterConstraint{T, dst, src})
+	} else {
+		a.addConstraint(&untagConstraint{T, dst, src, exact})
+	}
+}
+
+// addConstraint adds c to the constraint set.
+func (a *analysis) addConstraint(c constraint) {
+	a.constraints = append(a.constraints, c)
+	if a.log != nil {
+		fmt.Fprintf(a.log, "\t%s\n", c)
+	}
+}
+
+// copyElems generates load/store constraints for *dst = *src,
+// where src and dst are slices or *arrays.
+//
+func (a *analysis) copyElems(cgn *cgnode, typ types.Type, dst, src ssa.Value) {
+	tmp := a.addNodes(typ, "copy")
+	sz := a.sizeof(typ)
+	a.genLoad(cgn, tmp, src, 1, sz)
+	a.genStore(cgn, dst, tmp, 1, sz)
+}
+
+// ---------- Constraint generation ----------
+
+// genConv generates constraints for the conversion operation conv.
+func (a *analysis) genConv(conv *ssa.Convert, cgn *cgnode) {
+	res := a.valueNode(conv)
+	if res == 0 {
+		return // result is non-pointerlike
+	}
+
+	tSrc := conv.X.Type()
+	tDst := conv.Type()
+
+	switch utSrc := tSrc.Underlying().(type) {
+	case *types.Slice:
+		// []byte/[]rune -> string?
+		return
+
+	case *types.Pointer:
+		// *T -> unsafe.Pointer?
+		if tDst.Underlying() == tUnsafePtr {
+			return // we don't model unsafe aliasing (unsound)
+		}
+
+	case *types.Basic:
+		switch tDst.Underlying().(type) {
+		case *types.Pointer:
+			// Treat unsafe.Pointer->*T conversions like
+			// new(T) and create an unaliased object.
+			if utSrc == tUnsafePtr {
+				obj := a.addNodes(mustDeref(tDst), "unsafe.Pointer conversion")
+				a.endObject(obj, cgn, conv)
+				a.addressOf(tDst, res, obj)
+				return
+			}
+
+		case *types.Slice:
+			// string -> []byte/[]rune (or named aliases)?
+			if utSrc.Info()&types.IsString != 0 {
+				obj := a.addNodes(sliceToArray(tDst), "convert")
+				a.endObject(obj, cgn, conv)
+				a.addressOf(tDst, res, obj)
+				return
+			}
+
+		case *types.Basic:
+			// All basic-to-basic type conversions are no-ops.
+			// This includes uintptr<->unsafe.Pointer conversions,
+			// which we (unsoundly) ignore.
+			return
+		}
+	}
+
+	panic(fmt.Sprintf("illegal *ssa.Convert %s -> %s: %s", tSrc, tDst, conv.Parent()))
+}
+
+// genAppend generates constraints for a call to append.
+func (a *analysis) genAppend(instr *ssa.Call, cgn *cgnode) {
+	// Consider z = append(x, y).   y is optional.
+	// This may allocate a new [1]T array; call its object w.
+	// We get the following constraints:
+	// 	z = x
+	// 	z = &w
+	//     *z = *y
+
+	x := instr.Call.Args[0]
+
+	z := instr
+	a.copy(a.valueNode(z), a.valueNode(x), 1) // z = x
+
+	if len(instr.Call.Args) == 1 {
+		return // no allocation for z = append(x) or _ = append(x).
+	}
+
+	// TODO(adonovan): test append([]byte, ...string) []byte.
+
+	y := instr.Call.Args[1]
+	tArray := sliceToArray(instr.Call.Args[0].Type())
+
+	var w nodeid
+	w = a.nextNode()
+	a.addNodes(tArray, "append")
+	a.endObject(w, cgn, instr)
+
+	a.copyElems(cgn, tArray.Elem(), z, y)        // *z = *y
+	a.addressOf(instr.Type(), a.valueNode(z), w) //  z = &w
+}
+
+// genBuiltinCall generates contraints for a call to a built-in.
+func (a *analysis) genBuiltinCall(instr ssa.CallInstruction, cgn *cgnode) {
+	call := instr.Common()
+	switch call.Value.(*ssa.Builtin).Name() {
+	case "append":
+		// Safe cast: append cannot appear in a go or defer statement.
+		a.genAppend(instr.(*ssa.Call), cgn)
+
+	case "copy":
+		tElem := call.Args[0].Type().Underlying().(*types.Slice).Elem()
+		a.copyElems(cgn, tElem, call.Args[0], call.Args[1])
+
+	case "panic":
+		a.copy(a.panicNode, a.valueNode(call.Args[0]), 1)
+
+	case "recover":
+		if v := instr.Value(); v != nil {
+			a.copy(a.valueNode(v), a.panicNode, 1)
+		}
+
+	case "print":
+		// In the tests, the probe might be the sole reference
+		// to its arg, so make sure we create nodes for it.
+		if len(call.Args) > 0 {
+			a.valueNode(call.Args[0])
+		}
+
+	case "ssa:wrapnilchk":
+		a.copy(a.valueNode(instr.Value()), a.valueNode(call.Args[0]), 1)
+
+	default:
+		// No-ops: close len cap real imag complex print println delete.
+	}
+}
+
+// shouldUseContext defines the context-sensitivity policy.  It
+// returns true if we should analyse all static calls to fn anew.
+//
+// Obviously this interface rather limits how much freedom we have to
+// choose a policy.  The current policy, rather arbitrarily, is true
+// for intrinsics and accessor methods (actually: short, single-block,
+// call-free functions).  This is just a starting point.
+//
+func (a *analysis) shouldUseContext(fn *ssa.Function) bool {
+	if a.findIntrinsic(fn) != nil {
+		return true // treat intrinsics context-sensitively
+	}
+	if len(fn.Blocks) != 1 {
+		return false // too expensive
+	}
+	blk := fn.Blocks[0]
+	if len(blk.Instrs) > 10 {
+		return false // too expensive
+	}
+	if fn.Synthetic != "" && (fn.Pkg == nil || fn != fn.Pkg.Func("init")) {
+		return true // treat synthetic wrappers context-sensitively
+	}
+	for _, instr := range blk.Instrs {
+		switch instr := instr.(type) {
+		case ssa.CallInstruction:
+			// Disallow function calls (except to built-ins)
+			// because of the danger of unbounded recursion.
+			if _, ok := instr.Common().Value.(*ssa.Builtin); !ok {
+				return false
+			}
+		}
+	}
+	return true
+}
+
+// genStaticCall generates constraints for a statically dispatched function call.
+func (a *analysis) genStaticCall(caller *cgnode, site *callsite, call *ssa.CallCommon, result nodeid) {
+	fn := call.StaticCallee()
+
+	// Special cases for inlined intrinsics.
+	switch fn {
+	case a.runtimeSetFinalizer:
+		// Inline SetFinalizer so the call appears direct.
+		site.targets = a.addOneNode(tInvalid, "SetFinalizer.targets", nil)
+		a.addConstraint(&runtimeSetFinalizerConstraint{
+			targets: site.targets,
+			x:       a.valueNode(call.Args[0]),
+			f:       a.valueNode(call.Args[1]),
+		})
+		return
+
+	case a.reflectValueCall:
+		// Inline (reflect.Value).Call so the call appears direct.
+		dotdotdot := false
+		ret := reflectCallImpl(a, caller, site, a.valueNode(call.Args[0]), a.valueNode(call.Args[1]), dotdotdot)
+		if result != 0 {
+			a.addressOf(fn.Signature.Results().At(0).Type(), result, ret)
+		}
+		return
+	}
+
+	// Ascertain the context (contour/cgnode) for a particular call.
+	var obj nodeid
+	if a.shouldUseContext(fn) {
+		obj = a.makeFunctionObject(fn, site) // new contour
+	} else {
+		obj = a.objectNode(nil, fn) // shared contour
+	}
+	a.callEdge(caller, site, obj)
+
+	sig := call.Signature()
+
+	// Copy receiver, if any.
+	params := a.funcParams(obj)
+	args := call.Args
+	if sig.Recv() != nil {
+		sz := a.sizeof(sig.Recv().Type())
+		a.copy(params, a.valueNode(args[0]), sz)
+		params += nodeid(sz)
+		args = args[1:]
+	}
+
+	// Copy actual parameters into formal params block.
+	// Must loop, since the actuals aren't contiguous.
+	for i, arg := range args {
+		sz := a.sizeof(sig.Params().At(i).Type())
+		a.copy(params, a.valueNode(arg), sz)
+		params += nodeid(sz)
+	}
+
+	// Copy formal results block to actual result.
+	if result != 0 {
+		a.copy(result, a.funcResults(obj), a.sizeof(sig.Results()))
+	}
+}
+
+// genDynamicCall generates constraints for a dynamic function call.
+func (a *analysis) genDynamicCall(caller *cgnode, site *callsite, call *ssa.CallCommon, result nodeid) {
+	// pts(targets) will be the set of possible call targets.
+	site.targets = a.valueNode(call.Value)
+
+	// We add dynamic closure rules that store the arguments into
+	// the P-block and load the results from the R-block of each
+	// function discovered in pts(targets).
+
+	sig := call.Signature()
+	var offset uint32 = 1 // P/R block starts at offset 1
+	for i, arg := range call.Args {
+		sz := a.sizeof(sig.Params().At(i).Type())
+		a.genStore(caller, call.Value, a.valueNode(arg), offset, sz)
+		offset += sz
+	}
+	if result != 0 {
+		a.genLoad(caller, result, call.Value, offset, a.sizeof(sig.Results()))
+	}
+}
+
+// genInvoke generates constraints for a dynamic method invocation.
+func (a *analysis) genInvoke(caller *cgnode, site *callsite, call *ssa.CallCommon, result nodeid) {
+	if call.Value.Type() == a.reflectType {
+		a.genInvokeReflectType(caller, site, call, result)
+		return
+	}
+
+	sig := call.Signature()
+
+	// Allocate a contiguous targets/params/results block for this call.
+	block := a.nextNode()
+	// pts(targets) will be the set of possible call targets
+	site.targets = a.addOneNode(sig, "invoke.targets", nil)
+	p := a.addNodes(sig.Params(), "invoke.params")
+	r := a.addNodes(sig.Results(), "invoke.results")
+
+	// Copy the actual parameters into the call's params block.
+	for i, n := 0, sig.Params().Len(); i < n; i++ {
+		sz := a.sizeof(sig.Params().At(i).Type())
+		a.copy(p, a.valueNode(call.Args[i]), sz)
+		p += nodeid(sz)
+	}
+	// Copy the call's results block to the actual results.
+	if result != 0 {
+		a.copy(result, r, a.sizeof(sig.Results()))
+	}
+
+	// We add a dynamic invoke constraint that will connect the
+	// caller's and the callee's P/R blocks for each discovered
+	// call target.
+	a.addConstraint(&invokeConstraint{call.Method, a.valueNode(call.Value), block})
+}
+
+// genInvokeReflectType is a specialization of genInvoke where the
+// receiver type is a reflect.Type, under the assumption that there
+// can be at most one implementation of this interface, *reflect.rtype.
+//
+// (Though this may appear to be an instance of a pattern---method
+// calls on interfaces known to have exactly one implementation---in
+// practice it occurs rarely, so we special case for reflect.Type.)
+//
+// In effect we treat this:
+//    var rt reflect.Type = ...
+//    rt.F()
+// as this:
+//    rt.(*reflect.rtype).F()
+//
+func (a *analysis) genInvokeReflectType(caller *cgnode, site *callsite, call *ssa.CallCommon, result nodeid) {
+	// Unpack receiver into rtype
+	rtype := a.addOneNode(a.reflectRtypePtr, "rtype.recv", nil)
+	recv := a.valueNode(call.Value)
+	a.typeAssert(a.reflectRtypePtr, rtype, recv, true)
+
+	// Look up the concrete method.
+	fn := a.prog.LookupMethod(a.reflectRtypePtr, call.Method.Pkg(), call.Method.Name())
+
+	obj := a.makeFunctionObject(fn, site) // new contour for this call
+	a.callEdge(caller, site, obj)
+
+	// From now on, it's essentially a static call, but little is
+	// gained by factoring together the code for both cases.
+
+	sig := fn.Signature // concrete method
+	targets := a.addOneNode(sig, "call.targets", nil)
+	a.addressOf(sig, targets, obj) // (a singleton)
+
+	// Copy receiver.
+	params := a.funcParams(obj)
+	a.copy(params, rtype, 1)
+	params++
+
+	// Copy actual parameters into formal P-block.
+	// Must loop, since the actuals aren't contiguous.
+	for i, arg := range call.Args {
+		sz := a.sizeof(sig.Params().At(i).Type())
+		a.copy(params, a.valueNode(arg), sz)
+		params += nodeid(sz)
+	}
+
+	// Copy formal R-block to actual R-block.
+	if result != 0 {
+		a.copy(result, a.funcResults(obj), a.sizeof(sig.Results()))
+	}
+}
+
+// genCall generates constraints for call instruction instr.
+func (a *analysis) genCall(caller *cgnode, instr ssa.CallInstruction) {
+	call := instr.Common()
+
+	// Intrinsic implementations of built-in functions.
+	if _, ok := call.Value.(*ssa.Builtin); ok {
+		a.genBuiltinCall(instr, caller)
+		return
+	}
+
+	var result nodeid
+	if v := instr.Value(); v != nil {
+		result = a.valueNode(v)
+	}
+
+	site := &callsite{instr: instr}
+	if call.StaticCallee() != nil {
+		a.genStaticCall(caller, site, call, result)
+	} else if call.IsInvoke() {
+		a.genInvoke(caller, site, call, result)
+	} else {
+		a.genDynamicCall(caller, site, call, result)
+	}
+
+	caller.sites = append(caller.sites, site)
+
+	if a.log != nil {
+		// TODO(adonovan): debug: improve log message.
+		fmt.Fprintf(a.log, "\t%s to targets %s from %s\n", site, site.targets, caller)
+	}
+}
+
+// objectNode returns the object to which v points, if known.
+// In other words, if the points-to set of v is a singleton, it
+// returns the sole label, zero otherwise.
+//
+// We exploit this information to make the generated constraints less
+// dynamic.  For example, a complex load constraint can be replaced by
+// a simple copy constraint when the sole destination is known a priori.
+//
+// Some SSA instructions always have singletons points-to sets:
+// 	Alloc, Function, Global, MakeChan, MakeClosure,  MakeInterface,  MakeMap,  MakeSlice.
+// Others may be singletons depending on their operands:
+// 	FreeVar, Const, Convert, FieldAddr, IndexAddr, Slice.
+//
+// Idempotent.  Objects are created as needed, possibly via recursion
+// down the SSA value graph, e.g IndexAddr(FieldAddr(Alloc))).
+//
+func (a *analysis) objectNode(cgn *cgnode, v ssa.Value) nodeid {
+	switch v.(type) {
+	case *ssa.Global, *ssa.Function, *ssa.Const, *ssa.FreeVar:
+		// Global object.
+		obj, ok := a.globalobj[v]
+		if !ok {
+			switch v := v.(type) {
+			case *ssa.Global:
+				obj = a.nextNode()
+				a.addNodes(mustDeref(v.Type()), "global")
+				a.endObject(obj, nil, v)
+
+			case *ssa.Function:
+				obj = a.makeFunctionObject(v, nil)
+
+			case *ssa.Const:
+				// not addressable
+
+			case *ssa.FreeVar:
+				// not addressable
+			}
+
+			if a.log != nil {
+				fmt.Fprintf(a.log, "\tglobalobj[%s] = n%d\n", v, obj)
+			}
+			a.globalobj[v] = obj
+		}
+		return obj
+	}
+
+	// Local object.
+	obj, ok := a.localobj[v]
+	if !ok {
+		switch v := v.(type) {
+		case *ssa.Alloc:
+			obj = a.nextNode()
+			a.addNodes(mustDeref(v.Type()), "alloc")
+			a.endObject(obj, cgn, v)
+
+		case *ssa.MakeSlice:
+			obj = a.nextNode()
+			a.addNodes(sliceToArray(v.Type()), "makeslice")
+			a.endObject(obj, cgn, v)
+
+		case *ssa.MakeChan:
+			obj = a.nextNode()
+			a.addNodes(v.Type().Underlying().(*types.Chan).Elem(), "makechan")
+			a.endObject(obj, cgn, v)
+
+		case *ssa.MakeMap:
+			obj = a.nextNode()
+			tmap := v.Type().Underlying().(*types.Map)
+			a.addNodes(tmap.Key(), "makemap.key")
+			elem := a.addNodes(tmap.Elem(), "makemap.value")
+
+			// To update the value field, MapUpdate
+			// generates store-with-offset constraints which
+			// the presolver can't model, so we must mark
+			// those nodes indirect.
+			for id, end := elem, elem+nodeid(a.sizeof(tmap.Elem())); id < end; id++ {
+				a.mapValues = append(a.mapValues, id)
+			}
+			a.endObject(obj, cgn, v)
+
+		case *ssa.MakeInterface:
+			tConc := v.X.Type()
+			obj = a.makeTagged(tConc, cgn, v)
+
+			// Copy the value into it, if nontrivial.
+			if x := a.valueNode(v.X); x != 0 {
+				a.copy(obj+1, x, a.sizeof(tConc))
+			}
+
+		case *ssa.FieldAddr:
+			if xobj := a.objectNode(cgn, v.X); xobj != 0 {
+				obj = xobj + nodeid(a.offsetOf(mustDeref(v.X.Type()), v.Field))
+			}
+
+		case *ssa.IndexAddr:
+			if xobj := a.objectNode(cgn, v.X); xobj != 0 {
+				obj = xobj + 1
+			}
+
+		case *ssa.Slice:
+			obj = a.objectNode(cgn, v.X)
+
+		case *ssa.Convert:
+			// TODO(adonovan): opt: handle these cases too:
+			// - unsafe.Pointer->*T conversion acts like Alloc
+			// - string->[]byte/[]rune conversion acts like MakeSlice
+		}
+
+		if a.log != nil {
+			fmt.Fprintf(a.log, "\tlocalobj[%s] = n%d\n", v.Name(), obj)
+		}
+		a.localobj[v] = obj
+	}
+	return obj
+}
+
+// genLoad generates constraints for result = *(ptr + val).
+func (a *analysis) genLoad(cgn *cgnode, result nodeid, ptr ssa.Value, offset, sizeof uint32) {
+	if obj := a.objectNode(cgn, ptr); obj != 0 {
+		// Pre-apply loadConstraint.solve().
+		a.copy(result, obj+nodeid(offset), sizeof)
+	} else {
+		a.load(result, a.valueNode(ptr), offset, sizeof)
+	}
+}
+
+// genOffsetAddr generates constraints for a 'v=ptr.field' (FieldAddr)
+// or 'v=ptr[*]' (IndexAddr) instruction v.
+func (a *analysis) genOffsetAddr(cgn *cgnode, v ssa.Value, ptr nodeid, offset uint32) {
+	dst := a.valueNode(v)
+	if obj := a.objectNode(cgn, v); obj != 0 {
+		// Pre-apply offsetAddrConstraint.solve().
+		a.addressOf(v.Type(), dst, obj)
+	} else {
+		a.offsetAddr(v.Type(), dst, ptr, offset)
+	}
+}
+
+// genStore generates constraints for *(ptr + offset) = val.
+func (a *analysis) genStore(cgn *cgnode, ptr ssa.Value, val nodeid, offset, sizeof uint32) {
+	if obj := a.objectNode(cgn, ptr); obj != 0 {
+		// Pre-apply storeConstraint.solve().
+		a.copy(obj+nodeid(offset), val, sizeof)
+	} else {
+		a.store(a.valueNode(ptr), val, offset, sizeof)
+	}
+}
+
+// genInstr generates constraints for instruction instr in context cgn.
+func (a *analysis) genInstr(cgn *cgnode, instr ssa.Instruction) {
+	if a.log != nil {
+		var prefix string
+		if val, ok := instr.(ssa.Value); ok {
+			prefix = val.Name() + " = "
+		}
+		fmt.Fprintf(a.log, "; %s%s\n", prefix, instr)
+	}
+
+	switch instr := instr.(type) {
+	case *ssa.DebugRef:
+		// no-op.
+
+	case *ssa.UnOp:
+		switch instr.Op {
+		case token.ARROW: // <-x
+			// We can ignore instr.CommaOk because the node we're
+			// altering is always at zero offset relative to instr
+			tElem := instr.X.Type().Underlying().(*types.Chan).Elem()
+			a.genLoad(cgn, a.valueNode(instr), instr.X, 0, a.sizeof(tElem))
+
+		case token.MUL: // *x
+			a.genLoad(cgn, a.valueNode(instr), instr.X, 0, a.sizeof(instr.Type()))
+
+		default:
+			// NOT, SUB, XOR: no-op.
+		}
+
+	case *ssa.BinOp:
+		// All no-ops.
+
+	case ssa.CallInstruction: // *ssa.Call, *ssa.Go, *ssa.Defer
+		a.genCall(cgn, instr)
+
+	case *ssa.ChangeType:
+		a.copy(a.valueNode(instr), a.valueNode(instr.X), 1)
+
+	case *ssa.Convert:
+		a.genConv(instr, cgn)
+
+	case *ssa.Extract:
+		a.copy(a.valueNode(instr),
+			a.valueOffsetNode(instr.Tuple, instr.Index),
+			a.sizeof(instr.Type()))
+
+	case *ssa.FieldAddr:
+		a.genOffsetAddr(cgn, instr, a.valueNode(instr.X),
+			a.offsetOf(mustDeref(instr.X.Type()), instr.Field))
+
+	case *ssa.IndexAddr:
+		a.genOffsetAddr(cgn, instr, a.valueNode(instr.X), 1)
+
+	case *ssa.Field:
+		a.copy(a.valueNode(instr),
+			a.valueOffsetNode(instr.X, instr.Field),
+			a.sizeof(instr.Type()))
+
+	case *ssa.Index:
+		a.copy(a.valueNode(instr), 1+a.valueNode(instr.X), a.sizeof(instr.Type()))
+
+	case *ssa.Select:
+		recv := a.valueOffsetNode(instr, 2) // instr : (index, recvOk, recv0, ... recv_n-1)
+		for _, st := range instr.States {
+			elemSize := a.sizeof(st.Chan.Type().Underlying().(*types.Chan).Elem())
+			switch st.Dir {
+			case types.RecvOnly:
+				a.genLoad(cgn, recv, st.Chan, 0, elemSize)
+				recv += nodeid(elemSize)
+
+			case types.SendOnly:
+				a.genStore(cgn, st.Chan, a.valueNode(st.Send), 0, elemSize)
+			}
+		}
+
+	case *ssa.Return:
+		results := a.funcResults(cgn.obj)
+		for _, r := range instr.Results {
+			sz := a.sizeof(r.Type())
+			a.copy(results, a.valueNode(r), sz)
+			results += nodeid(sz)
+		}
+
+	case *ssa.Send:
+		a.genStore(cgn, instr.Chan, a.valueNode(instr.X), 0, a.sizeof(instr.X.Type()))
+
+	case *ssa.Store:
+		a.genStore(cgn, instr.Addr, a.valueNode(instr.Val), 0, a.sizeof(instr.Val.Type()))
+
+	case *ssa.Alloc, *ssa.MakeSlice, *ssa.MakeChan, *ssa.MakeMap, *ssa.MakeInterface:
+		v := instr.(ssa.Value)
+		a.addressOf(v.Type(), a.valueNode(v), a.objectNode(cgn, v))
+
+	case *ssa.ChangeInterface:
+		a.copy(a.valueNode(instr), a.valueNode(instr.X), 1)
+
+	case *ssa.TypeAssert:
+		a.typeAssert(instr.AssertedType, a.valueNode(instr), a.valueNode(instr.X), true)
+
+	case *ssa.Slice:
+		a.copy(a.valueNode(instr), a.valueNode(instr.X), 1)
+
+	case *ssa.If, *ssa.Jump:
+		// no-op.
+
+	case *ssa.Phi:
+		sz := a.sizeof(instr.Type())
+		for _, e := range instr.Edges {
+			a.copy(a.valueNode(instr), a.valueNode(e), sz)
+		}
+
+	case *ssa.MakeClosure:
+		fn := instr.Fn.(*ssa.Function)
+		a.copy(a.valueNode(instr), a.valueNode(fn), 1)
+		// Free variables are treated like global variables.
+		for i, b := range instr.Bindings {
+			a.copy(a.valueNode(fn.FreeVars[i]), a.valueNode(b), a.sizeof(b.Type()))
+		}
+
+	case *ssa.RunDefers:
+		// The analysis is flow insensitive, so we just "call"
+		// defers as we encounter them.
+
+	case *ssa.Range:
+		// Do nothing.  Next{Iter: *ssa.Range} handles this case.
+
+	case *ssa.Next:
+		if !instr.IsString { // map
+			// Assumes that Next is always directly applied to a Range result.
+			theMap := instr.Iter.(*ssa.Range).X
+			tMap := theMap.Type().Underlying().(*types.Map)
+			ksize := a.sizeof(tMap.Key())
+			vsize := a.sizeof(tMap.Elem())
+
+			// Load from the map's (k,v) into the tuple's (ok, k, v).
+			a.genLoad(cgn, a.valueNode(instr)+1, theMap, 0, ksize+vsize)
+		}
+
+	case *ssa.Lookup:
+		if tMap, ok := instr.X.Type().Underlying().(*types.Map); ok {
+			// CommaOk can be ignored: field 0 is a no-op.
+			ksize := a.sizeof(tMap.Key())
+			vsize := a.sizeof(tMap.Elem())
+			a.genLoad(cgn, a.valueNode(instr), instr.X, ksize, vsize)
+		}
+
+	case *ssa.MapUpdate:
+		tmap := instr.Map.Type().Underlying().(*types.Map)
+		ksize := a.sizeof(tmap.Key())
+		vsize := a.sizeof(tmap.Elem())
+		a.genStore(cgn, instr.Map, a.valueNode(instr.Key), 0, ksize)
+		a.genStore(cgn, instr.Map, a.valueNode(instr.Value), ksize, vsize)
+
+	case *ssa.Panic:
+		a.copy(a.panicNode, a.valueNode(instr.X), 1)
+
+	default:
+		panic(fmt.Sprintf("unimplemented: %T", instr))
+	}
+}
+
+func (a *analysis) makeCGNode(fn *ssa.Function, obj nodeid, callersite *callsite) *cgnode {
+	cgn := &cgnode{fn: fn, obj: obj, callersite: callersite}
+	a.cgnodes = append(a.cgnodes, cgn)
+	return cgn
+}
+
+// genRootCalls generates the synthetic root of the callgraph and the
+// initial calls from it to the analysis scope, such as main, a test
+// or a library.
+//
+func (a *analysis) genRootCalls() *cgnode {
+	r := a.prog.NewFunction("<root>", new(types.Signature), "root of callgraph")
+	root := a.makeCGNode(r, 0, nil)
+
+	// TODO(adonovan): make an ssa utility to construct an actual
+	// root function so we don't need to special-case site-less
+	// call edges.
+
+	// For each main package, call main.init(), main.main().
+	for _, mainPkg := range a.config.Mains {
+		main := mainPkg.Func("main")
+		if main == nil {
+			panic(fmt.Sprintf("%s has no main function", mainPkg))
+		}
+
+		targets := a.addOneNode(main.Signature, "root.targets", nil)
+		site := &callsite{targets: targets}
+		root.sites = append(root.sites, site)
+		for _, fn := range [2]*ssa.Function{mainPkg.Func("init"), main} {
+			if a.log != nil {
+				fmt.Fprintf(a.log, "\troot call to %s:\n", fn)
+			}
+			a.copy(targets, a.valueNode(fn), 1)
+		}
+	}
+
+	return root
+}
+
+// genFunc generates constraints for function fn.
+func (a *analysis) genFunc(cgn *cgnode) {
+	fn := cgn.fn
+
+	impl := a.findIntrinsic(fn)
+
+	if a.log != nil {
+		fmt.Fprintf(a.log, "\n\n==== Generating constraints for %s, %s\n", cgn, cgn.contour())
+
+		// Hack: don't display body if intrinsic.
+		if impl != nil {
+			fn2 := *cgn.fn // copy
+			fn2.Locals = nil
+			fn2.Blocks = nil
+			fn2.WriteTo(a.log)
+		} else {
+			cgn.fn.WriteTo(a.log)
+		}
+	}
+
+	if impl != nil {
+		impl(a, cgn)
+		return
+	}
+
+	if fn.Blocks == nil {
+		// External function with no intrinsic treatment.
+		// We'll warn about calls to such functions at the end.
+		return
+	}
+
+	if a.log != nil {
+		fmt.Fprintln(a.log, "; Creating nodes for local values")
+	}
+
+	a.localval = make(map[ssa.Value]nodeid)
+	a.localobj = make(map[ssa.Value]nodeid)
+
+	// The value nodes for the params are in the func object block.
+	params := a.funcParams(cgn.obj)
+	for _, p := range fn.Params {
+		a.setValueNode(p, params, cgn)
+		params += nodeid(a.sizeof(p.Type()))
+	}
+
+	// Free variables have global cardinality:
+	// the outer function sets them with MakeClosure;
+	// the inner function accesses them with FreeVar.
+	//
+	// TODO(adonovan): treat free vars context-sensitively.
+
+	// Create value nodes for all value instructions
+	// since SSA may contain forward references.
+	var space [10]*ssa.Value
+	for _, b := range fn.Blocks {
+		for _, instr := range b.Instrs {
+			switch instr := instr.(type) {
+			case *ssa.Range:
+				// do nothing: it has a funky type,
+				// and *ssa.Next does all the work.
+
+			case ssa.Value:
+				var comment string
+				if a.log != nil {
+					comment = instr.Name()
+				}
+				id := a.addNodes(instr.Type(), comment)
+				a.setValueNode(instr, id, cgn)
+			}
+
+			// Record all address-taken functions (for presolver).
+			rands := instr.Operands(space[:0])
+			if call, ok := instr.(ssa.CallInstruction); ok && !call.Common().IsInvoke() {
+				// Skip CallCommon.Value in "call" mode.
+				// TODO(adonovan): fix: relies on unspecified ordering.  Specify it.
+				rands = rands[1:]
+			}
+			for _, rand := range rands {
+				if atf, ok := (*rand).(*ssa.Function); ok {
+					a.atFuncs[atf] = true
+				}
+			}
+		}
+	}
+
+	// Generate constraints for instructions.
+	for _, b := range fn.Blocks {
+		for _, instr := range b.Instrs {
+			a.genInstr(cgn, instr)
+		}
+	}
+
+	a.localval = nil
+	a.localobj = nil
+}
+
+// genMethodsOf generates nodes and constraints for all methods of type T.
+func (a *analysis) genMethodsOf(T types.Type) {
+	itf := isInterface(T)
+
+	// TODO(adonovan): can we skip this entirely if itf is true?
+	// I think so, but the answer may depend on reflection.
+	mset := a.prog.MethodSets.MethodSet(T)
+	for i, n := 0, mset.Len(); i < n; i++ {
+		m := a.prog.Method(mset.At(i))
+		a.valueNode(m)
+
+		if !itf {
+			// Methods of concrete types are address-taken functions.
+			a.atFuncs[m] = true
+		}
+	}
+}
+
+// generate generates offline constraints for the entire program.
+func (a *analysis) generate() {
+	start("Constraint generation")
+	if a.log != nil {
+		fmt.Fprintln(a.log, "==== Generating constraints")
+	}
+
+	// Create a dummy node since we use the nodeid 0 for
+	// non-pointerlike variables.
+	a.addNodes(tInvalid, "(zero)")
+
+	// Create the global node for panic values.
+	a.panicNode = a.addNodes(tEface, "panic")
+
+	// Create nodes and constraints for all methods of reflect.rtype.
+	// (Shared contours are used by dynamic calls to reflect.Type
+	// methods---typically just String().)
+	if rtype := a.reflectRtypePtr; rtype != nil {
+		a.genMethodsOf(rtype)
+	}
+
+	root := a.genRootCalls()
+
+	if a.config.BuildCallGraph {
+		a.result.CallGraph = callgraph.New(root.fn)
+	}
+
+	// Create nodes and constraints for all methods of all types
+	// that are dynamically accessible via reflection or interfaces.
+	for _, T := range a.prog.RuntimeTypes() {
+		a.genMethodsOf(T)
+	}
+
+	// Generate constraints for entire program.
+	for len(a.genq) > 0 {
+		cgn := a.genq[0]
+		a.genq = a.genq[1:]
+		a.genFunc(cgn)
+	}
+
+	// The runtime magically allocates os.Args; so should we.
+	if os := a.prog.ImportedPackage("os"); os != nil {
+		// In effect:  os.Args = new([1]string)[:]
+		T := types.NewSlice(types.Typ[types.String])
+		obj := a.addNodes(sliceToArray(T), "<command-line args>")
+		a.endObject(obj, nil, "<command-line args>")
+		a.addressOf(T, a.objectNode(nil, os.Var("Args")), obj)
+	}
+
+	// Discard generation state, to avoid confusion after node renumbering.
+	a.panicNode = 0
+	a.globalval = nil
+	a.localval = nil
+	a.localobj = nil
+
+	stop("Constraint generation")
+}
diff --git a/go/pointer/hvn.go b/go/pointer/hvn.go
new file mode 100644
index 0000000..a3ef1f3
--- /dev/null
+++ b/go/pointer/hvn.go
@@ -0,0 +1,969 @@
+package pointer
+
+// This file implements Hash-Value Numbering (HVN), a pre-solver
+// constraint optimization described in Hardekopf & Lin, SAS'07 (see
+// doc.go) that analyses the graph topology to determine which sets of
+// variables are "pointer equivalent" (PE), i.e. must have identical
+// points-to sets in the solution.
+//
+// A separate ("offline") graph is constructed.  Its nodes are those of
+// the main-graph, plus an additional node *X for each pointer node X.
+// With this graph we can reason about the unknown points-to set of
+// dereferenced pointers.  (We do not generalize this to represent
+// unknown fields x->f, perhaps because such fields would be numerous,
+// though it might be worth an experiment.)
+//
+// Nodes whose points-to relations are not entirely captured by the
+// graph are marked as "indirect": the *X nodes, the parameters of
+// address-taken functions (which includes all functions in method
+// sets), or nodes updated by the solver rules for reflection, etc.
+//
+// All addr (y=&x) nodes are initially assigned a pointer-equivalence
+// (PE) label equal to x's nodeid in the main graph.  (These are the
+// only PE labels that are less than len(a.nodes).)
+//
+// All offsetAddr (y=&x.f) constraints are initially assigned a PE
+// label; such labels are memoized, keyed by (x, f), so that equivalent
+// nodes y as assigned the same label.
+//
+// Then we process each strongly connected component (SCC) of the graph
+// in topological order, assigning it a PE label based on the set P of
+// PE labels that flow to it from its immediate dependencies.
+//
+// If any node in P is "indirect", the entire SCC is assigned a fresh PE
+// label.  Otherwise:
+//
+// |P|=0  if P is empty, all nodes in the SCC are non-pointers (e.g.
+//        uninitialized variables, or formal params of dead functions)
+//        and the SCC is assigned the PE label of zero.
+//
+// |P|=1  if P is a singleton, the SCC is assigned the same label as the
+//        sole element of P.
+//
+// |P|>1  if P contains multiple labels, a unique label representing P is
+//        invented and recorded in an hash table, so that other
+//        equivalent SCCs may also be assigned this label, akin to
+//        conventional hash-value numbering in a compiler.
+//
+// Finally, a renumbering is computed such that each node is replaced by
+// the lowest-numbered node with the same PE label.  All constraints are
+// renumbered, and any resulting duplicates are eliminated.
+//
+// The only nodes that are not renumbered are the objects x in addr
+// (y=&x) constraints, since the ids of these nodes (and fields derived
+// from them via offsetAddr rules) are the elements of all points-to
+// sets, so they must remain as they are if we want the same solution.
+//
+// The solverStates (node.solve) for nodes in the same equivalence class
+// are linked together so that all nodes in the class have the same
+// solution.  This avoids the need to renumber nodeids buried in
+// Queries, cgnodes, etc (like (*analysis).renumber() does) since only
+// the solution is needed.
+//
+// The result of HVN is that the number of distinct nodes and
+// constraints is reduced, but the solution is identical (almost---see
+// CROSS-CHECK below).  In particular, both linear and cyclic chains of
+// copies are each replaced by a single node.
+//
+// Nodes and constraints created "online" (e.g. while solving reflection
+// constraints) are not subject to this optimization.
+//
+// PERFORMANCE
+//
+// In two benchmarks (oracle and godoc), HVN eliminates about two thirds
+// of nodes, the majority accounted for by non-pointers: nodes of
+// non-pointer type, pointers that remain nil, formal parameters of dead
+// functions, nodes of untracked types, etc.  It also reduces the number
+// of constraints, also by about two thirds, and the solving time by
+// 30--42%, although we must pay about 15% for the running time of HVN
+// itself.  The benefit is greater for larger applications.
+//
+// There are many possible optimizations to improve the performance:
+// * Use fewer than 1:1 onodes to main graph nodes: many of the onodes
+//   we create are not needed.
+// * HU (HVN with Union---see paper): coalesce "union" peLabels when
+//   their expanded-out sets are equal.
+// * HR (HVN with deReference---see paper): this will require that we
+//   apply HVN until fixed point, which may need more bookkeeping of the
+//   correspondance of main nodes to onodes.
+// * Location Equivalence (see paper): have points-to sets contain not
+//   locations but location-equivalence class labels, each representing
+//   a set of locations.
+// * HVN with field-sensitive ref: model each of the fields of a
+//   pointer-to-struct.
+//
+// CROSS-CHECK
+//
+// To verify the soundness of the optimization, when the
+// debugHVNCrossCheck option is enabled, we run the solver twice, once
+// before and once after running HVN, dumping the solution to disk, and
+// then we compare the results.  If they are not identical, the analysis
+// panics.
+//
+// The solution dumped to disk includes only the N*N submatrix of the
+// complete solution where N is the number of nodes after generation.
+// In other words, we ignore pointer variables and objects created by
+// the solver itself, since their numbering depends on the solver order,
+// which is affected by the optimization.  In any case, that's the only
+// part the client cares about.
+//
+// The cross-check is too strict and may fail spuriously.  Although the
+// H&L paper describing HVN states that the solutions obtained should be
+// identical, this is not the case in practice because HVN can collapse
+// cycles involving *p even when pts(p)={}.  Consider this example
+// distilled from testdata/hello.go:
+//
+//	var x T
+//	func f(p **T) {
+//		t0 = *p
+//		...
+//		t1 = φ(t0, &x)
+//		*p = t1
+//	}
+//
+// If f is dead code, we get:
+// 	unoptimized:  pts(p)={} pts(t0)={} pts(t1)={&x}
+// 	optimized:    pts(p)={} pts(t0)=pts(t1)=pts(*p)={&x}
+//
+// It's hard to argue that this is a bug: the result is sound and the
+// loss of precision is inconsequential---f is dead code, after all.
+// But unfortunately it limits the usefulness of the cross-check since
+// failures must be carefully analyzed.  Ben Hardekopf suggests (in
+// personal correspondence) some approaches to mitigating it:
+//
+// 	If there is a node with an HVN points-to set that is a superset
+// 	of the NORM points-to set, then either it's a bug or it's a
+// 	result of this issue. If it's a result of this issue, then in
+// 	the offline constraint graph there should be a REF node inside
+// 	some cycle that reaches this node, and in the NORM solution the
+// 	pointer being dereferenced by that REF node should be the empty
+// 	set. If that isn't true then this is a bug. If it is true, then
+// 	you can further check that in the NORM solution the "extra"
+// 	points-to info in the HVN solution does in fact come from that
+// 	purported cycle (if it doesn't, then this is still a bug). If
+// 	you're doing the further check then you'll need to do it for
+// 	each "extra" points-to element in the HVN points-to set.
+//
+// 	There are probably ways to optimize these checks by taking
+// 	advantage of graph properties. For example, extraneous points-to
+// 	info will flow through the graph and end up in many
+// 	nodes. Rather than checking every node with extra info, you
+// 	could probably work out the "origin point" of the extra info and
+// 	just check there. Note that the check in the first bullet is
+// 	looking for soundness bugs, while the check in the second bullet
+// 	is looking for precision bugs; depending on your needs, you may
+// 	care more about one than the other.
+//
+// which we should evaluate.  The cross-check is nonetheless invaluable
+// for all but one of the programs in the pointer_test suite.
+
+import (
+	"fmt"
+	"io"
+	"reflect"
+
+	"golang.org/x/tools/container/intsets"
+	"golang.org/x/tools/go/types"
+)
+
+// A peLabel is a pointer-equivalence label: two nodes with the same
+// peLabel have identical points-to solutions.
+//
+// The numbers are allocated consecutively like so:
+// 	0	not a pointer
+//	1..N-1	addrConstraints (equals the constraint's .src field, hence sparse)
+//	...	offsetAddr constraints
+//	...	SCCs (with indirect nodes or multiple inputs)
+//
+// Each PE label denotes a set of pointers containing a single addr, a
+// single offsetAddr, or some set of other PE labels.
+//
+type peLabel int
+
+type hvn struct {
+	a        *analysis
+	N        int                // len(a.nodes) immediately after constraint generation
+	log      io.Writer          // (optional) log of HVN lemmas
+	onodes   []*onode           // nodes of the offline graph
+	label    peLabel            // the next available PE label
+	hvnLabel map[string]peLabel // hash-value numbering (PE label) for each set of onodeids
+	stack    []onodeid          // DFS stack
+	index    int32              // next onode.index, from Tarjan's SCC algorithm
+
+	// For each distinct offsetAddrConstraint (src, offset) pair,
+	// offsetAddrLabels records a unique PE label >= N.
+	offsetAddrLabels map[offsetAddr]peLabel
+}
+
+// The index of an node in the offline graph.
+// (Currently the first N align with the main nodes,
+// but this may change with HRU.)
+type onodeid uint32
+
+// An onode is a node in the offline constraint graph.
+// (Where ambiguous, members of analysis.nodes are referred to as
+// "main graph" nodes.)
+//
+// Edges in the offline constraint graph (edges and implicit) point to
+// the source, i.e. against the flow of values: they are dependencies.
+// Implicit edges are used for SCC computation, but not for gathering
+// incoming labels.
+//
+type onode struct {
+	rep onodeid // index of representative of SCC in offline constraint graph
+
+	edges    intsets.Sparse // constraint edges X-->Y (this onode is X)
+	implicit intsets.Sparse // implicit edges *X-->*Y (this onode is X)
+	peLabels intsets.Sparse // set of peLabels are pointer-equivalent to this one
+	indirect bool           // node has points-to relations not represented in graph
+
+	// Tarjan's SCC algorithm
+	index, lowlink int32 // Tarjan numbering
+	scc            int32 // -ve => on stack; 0 => unvisited; +ve => node is root of a found SCC
+}
+
+type offsetAddr struct {
+	ptr    nodeid
+	offset uint32
+}
+
+// nextLabel issues the next unused pointer-equivalence label.
+func (h *hvn) nextLabel() peLabel {
+	h.label++
+	return h.label
+}
+
+// ref(X) returns the index of the onode for *X.
+func (h *hvn) ref(id onodeid) onodeid {
+	return id + onodeid(len(h.a.nodes))
+}
+
+// hvn computes pointer-equivalence labels (peLabels) using the Hash-based
+// Value Numbering (HVN) algorithm described in Hardekopf & Lin, SAS'07.
+//
+func (a *analysis) hvn() {
+	start("HVN")
+
+	if a.log != nil {
+		fmt.Fprintf(a.log, "\n\n==== Pointer equivalence optimization\n\n")
+	}
+
+	h := hvn{
+		a:                a,
+		N:                len(a.nodes),
+		log:              a.log,
+		hvnLabel:         make(map[string]peLabel),
+		offsetAddrLabels: make(map[offsetAddr]peLabel),
+	}
+
+	if h.log != nil {
+		fmt.Fprintf(h.log, "\nCreating offline graph nodes...\n")
+	}
+
+	// Create offline nodes.  The first N nodes correspond to main
+	// graph nodes; the next N are their corresponding ref() nodes.
+	h.onodes = make([]*onode, 2*h.N)
+	for id := range a.nodes {
+		id := onodeid(id)
+		h.onodes[id] = &onode{}
+		h.onodes[h.ref(id)] = &onode{indirect: true}
+	}
+
+	// Each node initially represents just itself.
+	for id, o := range h.onodes {
+		o.rep = onodeid(id)
+	}
+
+	h.markIndirectNodes()
+
+	// Reserve the first N PE labels for addrConstraints.
+	h.label = peLabel(h.N)
+
+	// Add offline constraint edges.
+	if h.log != nil {
+		fmt.Fprintf(h.log, "\nAdding offline graph edges...\n")
+	}
+	for _, c := range a.constraints {
+		if debugHVNVerbose && h.log != nil {
+			fmt.Fprintf(h.log, "; %s\n", c)
+		}
+		c.presolve(&h)
+	}
+
+	// Find and collapse SCCs.
+	if h.log != nil {
+		fmt.Fprintf(h.log, "\nFinding SCCs...\n")
+	}
+	h.index = 1
+	for id, o := range h.onodes {
+		if id > 0 && o.index == 0 {
+			// Start depth-first search at each unvisited node.
+			h.visit(onodeid(id))
+		}
+	}
+
+	// Dump the solution
+	// (NB: somewhat redundant with logging from simplify().)
+	if debugHVNVerbose && h.log != nil {
+		fmt.Fprintf(h.log, "\nPointer equivalences:\n")
+		for id, o := range h.onodes {
+			if id == 0 {
+				continue
+			}
+			if id == int(h.N) {
+				fmt.Fprintf(h.log, "---\n")
+			}
+			fmt.Fprintf(h.log, "o%d\t", id)
+			if o.rep != onodeid(id) {
+				fmt.Fprintf(h.log, "rep=o%d", o.rep)
+			} else {
+				fmt.Fprintf(h.log, "p%d", o.peLabels.Min())
+				if o.indirect {
+					fmt.Fprint(h.log, " indirect")
+				}
+			}
+			fmt.Fprintln(h.log)
+		}
+	}
+
+	// Simplify the main constraint graph
+	h.simplify()
+
+	a.showCounts()
+
+	stop("HVN")
+}
+
+// ---- constraint-specific rules ----
+
+// dst := &src
+func (c *addrConstraint) presolve(h *hvn) {
+	// Each object (src) is an initial PE label.
+	label := peLabel(c.src) // label < N
+	if debugHVNVerbose && h.log != nil {
+		// duplicate log messages are possible
+		fmt.Fprintf(h.log, "\tcreate p%d: {&n%d}\n", label, c.src)
+	}
+	odst := onodeid(c.dst)
+	osrc := onodeid(c.src)
+
+	// Assign dst this label.
+	h.onodes[odst].peLabels.Insert(int(label))
+	if debugHVNVerbose && h.log != nil {
+		fmt.Fprintf(h.log, "\to%d has p%d\n", odst, label)
+	}
+
+	h.addImplicitEdge(h.ref(odst), osrc) // *dst ~~> src.
+}
+
+// dst = src
+func (c *copyConstraint) presolve(h *hvn) {
+	odst := onodeid(c.dst)
+	osrc := onodeid(c.src)
+	h.addEdge(odst, osrc)                       //  dst -->  src
+	h.addImplicitEdge(h.ref(odst), h.ref(osrc)) // *dst ~~> *src
+}
+
+// dst = *src + offset
+func (c *loadConstraint) presolve(h *hvn) {
+	odst := onodeid(c.dst)
+	osrc := onodeid(c.src)
+	if c.offset == 0 {
+		h.addEdge(odst, h.ref(osrc)) // dst --> *src
+	} else {
+		// We don't interpret load-with-offset, e.g. results
+		// of map value lookup, R-block of dynamic call, slice
+		// copy/append, reflection.
+		h.markIndirect(odst, "load with offset")
+	}
+}
+
+// *dst + offset = src
+func (c *storeConstraint) presolve(h *hvn) {
+	odst := onodeid(c.dst)
+	osrc := onodeid(c.src)
+	if c.offset == 0 {
+		h.onodes[h.ref(odst)].edges.Insert(int(osrc)) // *dst --> src
+		if debugHVNVerbose && h.log != nil {
+			fmt.Fprintf(h.log, "\to%d --> o%d\n", h.ref(odst), osrc)
+		}
+	} else {
+		// We don't interpret store-with-offset.
+		// See discussion of soundness at markIndirectNodes.
+	}
+}
+
+// dst = &src.offset
+func (c *offsetAddrConstraint) presolve(h *hvn) {
+	// Give each distinct (addr, offset) pair a fresh PE label.
+	// The cache performs CSE, effectively.
+	key := offsetAddr{c.src, c.offset}
+	label, ok := h.offsetAddrLabels[key]
+	if !ok {
+		label = h.nextLabel()
+		h.offsetAddrLabels[key] = label
+		if debugHVNVerbose && h.log != nil {
+			fmt.Fprintf(h.log, "\tcreate p%d: {&n%d.#%d}\n",
+				label, c.src, c.offset)
+		}
+	}
+
+	// Assign dst this label.
+	h.onodes[c.dst].peLabels.Insert(int(label))
+	if debugHVNVerbose && h.log != nil {
+		fmt.Fprintf(h.log, "\to%d has p%d\n", c.dst, label)
+	}
+}
+
+// dst = src.(typ)  where typ is an interface
+func (c *typeFilterConstraint) presolve(h *hvn) {
+	h.markIndirect(onodeid(c.dst), "typeFilter result")
+}
+
+// dst = src.(typ)  where typ is concrete
+func (c *untagConstraint) presolve(h *hvn) {
+	odst := onodeid(c.dst)
+	for end := odst + onodeid(h.a.sizeof(c.typ)); odst < end; odst++ {
+		h.markIndirect(odst, "untag result")
+	}
+}
+
+// dst = src.method(c.params...)
+func (c *invokeConstraint) presolve(h *hvn) {
+	// All methods are address-taken functions, so
+	// their formal P-blocks were already marked indirect.
+
+	// Mark the caller's targets node as indirect.
+	sig := c.method.Type().(*types.Signature)
+	id := c.params
+	h.markIndirect(onodeid(c.params), "invoke targets node")
+	id++
+
+	id += nodeid(h.a.sizeof(sig.Params()))
+
+	// Mark the caller's R-block as indirect.
+	end := id + nodeid(h.a.sizeof(sig.Results()))
+	for id < end {
+		h.markIndirect(onodeid(id), "invoke R-block")
+		id++
+	}
+}
+
+// markIndirectNodes marks as indirect nodes whose points-to relations
+// are not entirely captured by the offline graph, including:
+//
+//    (a) All address-taken nodes (including the following nodes within
+//        the same object).  This is described in the paper.
+//
+// The most subtle cause of indirect nodes is the generation of
+// store-with-offset constraints since the offline graph doesn't
+// represent them.  A global audit of constraint generation reveals the
+// following uses of store-with-offset:
+//
+//    (b) genDynamicCall, for P-blocks of dynamically called functions,
+//        to which dynamic copy edges will be added to them during
+//        solving: from storeConstraint for standalone functions,
+//        and from invokeConstraint for methods.
+//        All such P-blocks must be marked indirect.
+//    (c) MakeUpdate, to update the value part of a map object.
+//        All MakeMap objects's value parts must be marked indirect.
+//    (d) copyElems, to update the destination array.
+//        All array elements must be marked indirect.
+//
+// Not all indirect marking happens here.  ref() nodes are marked
+// indirect at construction, and each constraint's presolve() method may
+// mark additional nodes.
+//
+func (h *hvn) markIndirectNodes() {
+	// (a) all address-taken nodes, plus all nodes following them
+	//     within the same object, since these may be indirectly
+	//     stored or address-taken.
+	for _, c := range h.a.constraints {
+		if c, ok := c.(*addrConstraint); ok {
+			start := h.a.enclosingObj(c.src)
+			end := start + nodeid(h.a.nodes[start].obj.size)
+			for id := c.src; id < end; id++ {
+				h.markIndirect(onodeid(id), "A-T object")
+			}
+		}
+	}
+
+	// (b) P-blocks of all address-taken functions.
+	for id := 0; id < h.N; id++ {
+		obj := h.a.nodes[id].obj
+
+		// TODO(adonovan): opt: if obj.cgn.fn is a method and
+		// obj.cgn is not its shared contour, this is an
+		// "inlined" static method call.  We needn't consider it
+		// address-taken since no invokeConstraint will affect it.
+
+		if obj != nil && obj.flags&otFunction != 0 && h.a.atFuncs[obj.cgn.fn] {
+			// address-taken function
+			if debugHVNVerbose && h.log != nil {
+				fmt.Fprintf(h.log, "n%d is address-taken: %s\n", id, obj.cgn.fn)
+			}
+			h.markIndirect(onodeid(id), "A-T func identity")
+			id++
+			sig := obj.cgn.fn.Signature
+			psize := h.a.sizeof(sig.Params())
+			if sig.Recv() != nil {
+				psize += h.a.sizeof(sig.Recv().Type())
+			}
+			for end := id + int(psize); id < end; id++ {
+				h.markIndirect(onodeid(id), "A-T func P-block")
+			}
+			id--
+			continue
+		}
+	}
+
+	// (c) all map objects' value fields.
+	for _, id := range h.a.mapValues {
+		h.markIndirect(onodeid(id), "makemap.value")
+	}
+
+	// (d) all array element objects.
+	// TODO(adonovan): opt: can we do better?
+	for id := 0; id < h.N; id++ {
+		// Identity node for an object of array type?
+		if tArray, ok := h.a.nodes[id].typ.(*types.Array); ok {
+			// Mark the array element nodes indirect.
+			// (Skip past the identity field.)
+			for _ = range h.a.flatten(tArray.Elem()) {
+				id++
+				h.markIndirect(onodeid(id), "array elem")
+			}
+		}
+	}
+}
+
+func (h *hvn) markIndirect(oid onodeid, comment string) {
+	h.onodes[oid].indirect = true
+	if debugHVNVerbose && h.log != nil {
+		fmt.Fprintf(h.log, "\to%d is indirect: %s\n", oid, comment)
+	}
+}
+
+// Adds an edge dst-->src.
+// Note the unusual convention: edges are dependency (contraflow) edges.
+func (h *hvn) addEdge(odst, osrc onodeid) {
+	h.onodes[odst].edges.Insert(int(osrc))
+	if debugHVNVerbose && h.log != nil {
+		fmt.Fprintf(h.log, "\to%d --> o%d\n", odst, osrc)
+	}
+}
+
+func (h *hvn) addImplicitEdge(odst, osrc onodeid) {
+	h.onodes[odst].implicit.Insert(int(osrc))
+	if debugHVNVerbose && h.log != nil {
+		fmt.Fprintf(h.log, "\to%d ~~> o%d\n", odst, osrc)
+	}
+}
+
+// visit implements the depth-first search of Tarjan's SCC algorithm.
+// Precondition: x is canonical.
+func (h *hvn) visit(x onodeid) {
+	h.checkCanonical(x)
+	xo := h.onodes[x]
+	xo.index = h.index
+	xo.lowlink = h.index
+	h.index++
+
+	h.stack = append(h.stack, x) // push
+	assert(xo.scc == 0, "node revisited")
+	xo.scc = -1
+
+	var deps []int
+	deps = xo.edges.AppendTo(deps)
+	deps = xo.implicit.AppendTo(deps)
+
+	for _, y := range deps {
+		// Loop invariant: x is canonical.
+
+		y := h.find(onodeid(y))
+
+		if x == y {
+			continue // nodes already coalesced
+		}
+
+		xo := h.onodes[x]
+		yo := h.onodes[y]
+
+		switch {
+		case yo.scc > 0:
+			// y is already a collapsed SCC
+
+		case yo.scc < 0:
+			// y is on the stack, and thus in the current SCC.
+			if yo.index < xo.lowlink {
+				xo.lowlink = yo.index
+			}
+
+		default:
+			// y is unvisited; visit it now.
+			h.visit(y)
+			// Note: x and y are now non-canonical.
+
+			x = h.find(onodeid(x))
+
+			if yo.lowlink < xo.lowlink {
+				xo.lowlink = yo.lowlink
+			}
+		}
+	}
+	h.checkCanonical(x)
+
+	// Is x the root of an SCC?
+	if xo.lowlink == xo.index {
+		// Coalesce all nodes in the SCC.
+		if debugHVNVerbose && h.log != nil {
+			fmt.Fprintf(h.log, "scc o%d\n", x)
+		}
+		for {
+			// Pop y from stack.
+			i := len(h.stack) - 1
+			y := h.stack[i]
+			h.stack = h.stack[:i]
+
+			h.checkCanonical(x)
+			xo := h.onodes[x]
+			h.checkCanonical(y)
+			yo := h.onodes[y]
+
+			if xo == yo {
+				// SCC is complete.
+				xo.scc = 1
+				h.labelSCC(x)
+				break
+			}
+			h.coalesce(x, y)
+		}
+	}
+}
+
+// Precondition: x is canonical.
+func (h *hvn) labelSCC(x onodeid) {
+	h.checkCanonical(x)
+	xo := h.onodes[x]
+	xpe := &xo.peLabels
+
+	// All indirect nodes get new labels.
+	if xo.indirect {
+		label := h.nextLabel()
+		if debugHVNVerbose && h.log != nil {
+			fmt.Fprintf(h.log, "\tcreate p%d: indirect SCC\n", label)
+			fmt.Fprintf(h.log, "\to%d has p%d\n", x, label)
+		}
+
+		// Remove pre-labeling, in case a direct pre-labeled node was
+		// merged with an indirect one.
+		xpe.Clear()
+		xpe.Insert(int(label))
+
+		return
+	}
+
+	// Invariant: all peLabels sets are non-empty.
+	// Those that are logically empty contain zero as their sole element.
+	// No other sets contains zero.
+
+	// Find all labels coming in to the coalesced SCC node.
+	for _, y := range xo.edges.AppendTo(nil) {
+		y := h.find(onodeid(y))
+		if y == x {
+			continue // already coalesced
+		}
+		ype := &h.onodes[y].peLabels
+		if debugHVNVerbose && h.log != nil {
+			fmt.Fprintf(h.log, "\tedge from o%d = %s\n", y, ype)
+		}
+
+		if ype.IsEmpty() {
+			if debugHVNVerbose && h.log != nil {
+				fmt.Fprintf(h.log, "\tnode has no PE label\n")
+			}
+		}
+		assert(!ype.IsEmpty(), "incoming node has no PE label")
+
+		if ype.Has(0) {
+			// {0} represents a non-pointer.
+			assert(ype.Len() == 1, "PE set contains {0, ...}")
+		} else {
+			xpe.UnionWith(ype)
+		}
+	}
+
+	switch xpe.Len() {
+	case 0:
+		// SCC has no incoming non-zero PE labels: it is a non-pointer.
+		xpe.Insert(0)
+
+	case 1:
+		// already a singleton
+
+	default:
+		// SCC has multiple incoming non-zero PE labels.
+		// Find the canonical label representing this set.
+		// We use String() as a fingerprint consistent with Equals().
+		key := xpe.String()
+		label, ok := h.hvnLabel[key]
+		if !ok {
+			label = h.nextLabel()
+			if debugHVNVerbose && h.log != nil {
+				fmt.Fprintf(h.log, "\tcreate p%d: union %s\n", label, xpe.String())
+			}
+			h.hvnLabel[key] = label
+		}
+		xpe.Clear()
+		xpe.Insert(int(label))
+	}
+
+	if debugHVNVerbose && h.log != nil {
+		fmt.Fprintf(h.log, "\to%d has p%d\n", x, xpe.Min())
+	}
+}
+
+// coalesce combines two nodes in the offline constraint graph.
+// Precondition: x and y are canonical.
+func (h *hvn) coalesce(x, y onodeid) {
+	xo := h.onodes[x]
+	yo := h.onodes[y]
+
+	// x becomes y's canonical representative.
+	yo.rep = x
+
+	if debugHVNVerbose && h.log != nil {
+		fmt.Fprintf(h.log, "\tcoalesce o%d into o%d\n", y, x)
+	}
+
+	// x accumulates y's edges.
+	xo.edges.UnionWith(&yo.edges)
+	yo.edges.Clear()
+
+	// x accumulates y's implicit edges.
+	xo.implicit.UnionWith(&yo.implicit)
+	yo.implicit.Clear()
+
+	// x accumulates y's pointer-equivalence labels.
+	xo.peLabels.UnionWith(&yo.peLabels)
+	yo.peLabels.Clear()
+
+	// x accumulates y's indirect flag.
+	if yo.indirect {
+		xo.indirect = true
+	}
+}
+
+// simplify computes a degenerate renumbering of nodeids from the PE
+// labels assigned by the hvn, and uses it to simplify the main
+// constraint graph, eliminating non-pointer nodes and duplicate
+// constraints.
+//
+func (h *hvn) simplify() {
+	// canon maps each peLabel to its canonical main node.
+	canon := make([]nodeid, h.label)
+	for i := range canon {
+		canon[i] = nodeid(h.N) // indicates "unset"
+	}
+
+	// mapping maps each main node index to the index of the canonical node.
+	mapping := make([]nodeid, len(h.a.nodes))
+
+	for id := range h.a.nodes {
+		id := nodeid(id)
+		if id == 0 {
+			canon[0] = 0
+			mapping[0] = 0
+			continue
+		}
+		oid := h.find(onodeid(id))
+		peLabels := &h.onodes[oid].peLabels
+		assert(peLabels.Len() == 1, "PE class is not a singleton")
+		label := peLabel(peLabels.Min())
+
+		canonId := canon[label]
+		if canonId == nodeid(h.N) {
+			// id becomes the representative of the PE label.
+			canonId = id
+			canon[label] = canonId
+
+			if h.a.log != nil {
+				fmt.Fprintf(h.a.log, "\tpts(n%d) is canonical : \t(%s)\n",
+					id, h.a.nodes[id].typ)
+			}
+
+		} else {
+			// Link the solver states for the two nodes.
+			assert(h.a.nodes[canonId].solve != nil, "missing solver state")
+			h.a.nodes[id].solve = h.a.nodes[canonId].solve
+
+			if h.a.log != nil {
+				// TODO(adonovan): debug: reorganize the log so it prints
+				// one line:
+				// 	pe y = x1, ..., xn
+				// for each canonical y.  Requires allocation.
+				fmt.Fprintf(h.a.log, "\tpts(n%d) = pts(n%d) : %s\n",
+					id, canonId, h.a.nodes[id].typ)
+			}
+		}
+
+		mapping[id] = canonId
+	}
+
+	// Renumber the constraints, eliminate duplicates, and eliminate
+	// any containing non-pointers (n0).
+	addrs := make(map[addrConstraint]bool)
+	copys := make(map[copyConstraint]bool)
+	loads := make(map[loadConstraint]bool)
+	stores := make(map[storeConstraint]bool)
+	offsetAddrs := make(map[offsetAddrConstraint]bool)
+	untags := make(map[untagConstraint]bool)
+	typeFilters := make(map[typeFilterConstraint]bool)
+	invokes := make(map[invokeConstraint]bool)
+
+	nbefore := len(h.a.constraints)
+	cc := h.a.constraints[:0] // in-situ compaction
+	for _, c := range h.a.constraints {
+		// Renumber.
+		switch c := c.(type) {
+		case *addrConstraint:
+			// Don't renumber c.src since it is the label of
+			// an addressable object and will appear in PT sets.
+			c.dst = mapping[c.dst]
+		default:
+			c.renumber(mapping)
+		}
+
+		if c.ptr() == 0 {
+			continue // skip: constraint attached to non-pointer
+		}
+
+		var dup bool
+		switch c := c.(type) {
+		case *addrConstraint:
+			_, dup = addrs[*c]
+			addrs[*c] = true
+
+		case *copyConstraint:
+			if c.src == c.dst {
+				continue // skip degenerate copies
+			}
+			if c.src == 0 {
+				continue // skip copy from non-pointer
+			}
+			_, dup = copys[*c]
+			copys[*c] = true
+
+		case *loadConstraint:
+			if c.src == 0 {
+				continue // skip load from non-pointer
+			}
+			_, dup = loads[*c]
+			loads[*c] = true
+
+		case *storeConstraint:
+			if c.src == 0 {
+				continue // skip store from non-pointer
+			}
+			_, dup = stores[*c]
+			stores[*c] = true
+
+		case *offsetAddrConstraint:
+			if c.src == 0 {
+				continue // skip offset from non-pointer
+			}
+			_, dup = offsetAddrs[*c]
+			offsetAddrs[*c] = true
+
+		case *untagConstraint:
+			if c.src == 0 {
+				continue // skip untag of non-pointer
+			}
+			_, dup = untags[*c]
+			untags[*c] = true
+
+		case *typeFilterConstraint:
+			if c.src == 0 {
+				continue // skip filter of non-pointer
+			}
+			_, dup = typeFilters[*c]
+			typeFilters[*c] = true
+
+		case *invokeConstraint:
+			if c.params == 0 {
+				panic("non-pointer invoke.params")
+			}
+			if c.iface == 0 {
+				continue // skip invoke on non-pointer
+			}
+			_, dup = invokes[*c]
+			invokes[*c] = true
+
+		default:
+			// We don't bother de-duping advanced constraints
+			// (e.g. reflection) since they are uncommon.
+
+			// Eliminate constraints containing non-pointer nodeids.
+			//
+			// We use reflection to find the fields to avoid
+			// adding yet another method to constraint.
+			//
+			// TODO(adonovan): experiment with a constraint
+			// method that returns a slice of pointers to
+			// nodeids fields to enable uniform iteration;
+			// the renumber() method could be removed and
+			// implemented using the new one.
+			//
+			// TODO(adonovan): opt: this is unsound since
+			// some constraints still have an effect if one
+			// of the operands is zero: rVCall, rVMapIndex,
+			// rvSetMapIndex.  Handle them specially.
+			rtNodeid := reflect.TypeOf(nodeid(0))
+			x := reflect.ValueOf(c).Elem()
+			for i, nf := 0, x.NumField(); i < nf; i++ {
+				f := x.Field(i)
+				if f.Type() == rtNodeid {
+					if f.Uint() == 0 {
+						dup = true // skip it
+						break
+					}
+				}
+			}
+		}
+		if dup {
+			continue // skip duplicates
+		}
+
+		cc = append(cc, c)
+	}
+	h.a.constraints = cc
+
+	if h.log != nil {
+		fmt.Fprintf(h.log, "#constraints: was %d, now %d\n", nbefore, len(h.a.constraints))
+	}
+}
+
+// find returns the canonical onodeid for x.
+// (The onodes form a disjoint set forest.)
+func (h *hvn) find(x onodeid) onodeid {
+	// TODO(adonovan): opt: this is a CPU hotspot.  Try "union by rank".
+	xo := h.onodes[x]
+	rep := xo.rep
+	if rep != x {
+		rep = h.find(rep) // simple path compression
+		xo.rep = rep
+	}
+	return rep
+}
+
+func (h *hvn) checkCanonical(x onodeid) {
+	if debugHVN {
+		assert(x == h.find(x), "not canonical")
+	}
+}
+
+func assert(p bool, msg string) {
+	if debugHVN && !p {
+		panic("assertion failed: " + msg)
+	}
+}
diff --git a/go/pointer/intrinsics.go b/go/pointer/intrinsics.go
new file mode 100644
index 0000000..251c0e2
--- /dev/null
+++ b/go/pointer/intrinsics.go
@@ -0,0 +1,380 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package pointer
+
+// This package defines the treatment of intrinsics, i.e. library
+// functions requiring special analytical treatment.
+//
+// Most of these are C or assembly functions, but even some Go
+// functions require may special treatment if the analysis completely
+// replaces the implementation of an API such as reflection.
+
+// TODO(adonovan): support a means of writing analytic summaries in
+// the target code, so that users can summarise the effects of their
+// own C functions using a snippet of Go.
+
+import (
+	"fmt"
+
+	"golang.org/x/tools/go/ssa"
+	"golang.org/x/tools/go/types"
+)
+
+// Instances of 'intrinsic' generate analysis constraints for calls to
+// intrinsic functions.
+// Implementations may exploit information from the calling site
+// via cgn.callersite; for shared contours this is nil.
+type intrinsic func(a *analysis, cgn *cgnode)
+
+// Initialized in explicit init() to defeat (spurious) initialization
+// cycle error.
+var intrinsicsByName = make(map[string]intrinsic)
+
+func init() {
+	// Key strings are from Function.String().
+	// That little dot ۰ is an Arabic zero numeral (U+06F0),
+	// categories [Nd].
+	for name, fn := range map[string]intrinsic{
+		// Other packages.
+		"bytes.Equal":                           ext۰NoEffect,
+		"bytes.IndexByte":                       ext۰NoEffect,
+		"crypto/aes.decryptBlockAsm":            ext۰NoEffect,
+		"crypto/aes.encryptBlockAsm":            ext۰NoEffect,
+		"crypto/aes.expandKeyAsm":               ext۰NoEffect,
+		"crypto/aes.hasAsm":                     ext۰NoEffect,
+		"crypto/md5.block":                      ext۰NoEffect,
+		"crypto/rc4.xorKeyStream":               ext۰NoEffect,
+		"crypto/sha1.block":                     ext۰NoEffect,
+		"crypto/sha256.block":                   ext۰NoEffect,
+		"hash/crc32.castagnoliSSE42":            ext۰NoEffect,
+		"hash/crc32.haveSSE42":                  ext۰NoEffect,
+		"math.Abs":                              ext۰NoEffect,
+		"math.Acos":                             ext۰NoEffect,
+		"math.Asin":                             ext۰NoEffect,
+		"math.Atan":                             ext۰NoEffect,
+		"math.Atan2":                            ext۰NoEffect,
+		"math.Ceil":                             ext۰NoEffect,
+		"math.Cos":                              ext۰NoEffect,
+		"math.Dim":                              ext۰NoEffect,
+		"math.Exp":                              ext۰NoEffect,
+		"math.Exp2":                             ext۰NoEffect,
+		"math.Expm1":                            ext۰NoEffect,
+		"math.Float32bits":                      ext۰NoEffect,
+		"math.Float32frombits":                  ext۰NoEffect,
+		"math.Float64bits":                      ext۰NoEffect,
+		"math.Float64frombits":                  ext۰NoEffect,
+		"math.Floor":                            ext۰NoEffect,
+		"math.Frexp":                            ext۰NoEffect,
+		"math.Hypot":                            ext۰NoEffect,
+		"math.Ldexp":                            ext۰NoEffect,
+		"math.Log":                              ext۰NoEffect,
+		"math.Log10":                            ext۰NoEffect,
+		"math.Log1p":                            ext۰NoEffect,
+		"math.Log2":                             ext۰NoEffect,
+		"math.Max":                              ext۰NoEffect,
+		"math.Min":                              ext۰NoEffect,
+		"math.Mod":                              ext۰NoEffect,
+		"math.Modf":                             ext۰NoEffect,
+		"math.Remainder":                        ext۰NoEffect,
+		"math.Sin":                              ext۰NoEffect,
+		"math.Sincos":                           ext۰NoEffect,
+		"math.Sqrt":                             ext۰NoEffect,
+		"math.Tan":                              ext۰NoEffect,
+		"math.Trunc":                            ext۰NoEffect,
+		"math/big.addMulVVW":                    ext۰NoEffect,
+		"math/big.addVV":                        ext۰NoEffect,
+		"math/big.addVW":                        ext۰NoEffect,
+		"math/big.bitLen":                       ext۰NoEffect,
+		"math/big.divWVW":                       ext۰NoEffect,
+		"math/big.divWW":                        ext۰NoEffect,
+		"math/big.mulAddVWW":                    ext۰NoEffect,
+		"math/big.mulWW":                        ext۰NoEffect,
+		"math/big.shlVU":                        ext۰NoEffect,
+		"math/big.shrVU":                        ext۰NoEffect,
+		"math/big.subVV":                        ext۰NoEffect,
+		"math/big.subVW":                        ext۰NoEffect,
+		"net.runtime_Semacquire":                ext۰NoEffect,
+		"net.runtime_Semrelease":                ext۰NoEffect,
+		"net.runtime_pollClose":                 ext۰NoEffect,
+		"net.runtime_pollOpen":                  ext۰NoEffect,
+		"net.runtime_pollReset":                 ext۰NoEffect,
+		"net.runtime_pollServerInit":            ext۰NoEffect,
+		"net.runtime_pollSetDeadline":           ext۰NoEffect,
+		"net.runtime_pollUnblock":               ext۰NoEffect,
+		"net.runtime_pollWait":                  ext۰NoEffect,
+		"net.runtime_pollWaitCanceled":          ext۰NoEffect,
+		"os.epipecheck":                         ext۰NoEffect,
+		"runtime.BlockProfile":                  ext۰NoEffect,
+		"runtime.Breakpoint":                    ext۰NoEffect,
+		"runtime.CPUProfile":                    ext۰NoEffect, // good enough
+		"runtime.Caller":                        ext۰NoEffect,
+		"runtime.Callers":                       ext۰NoEffect, // good enough
+		"runtime.FuncForPC":                     ext۰NoEffect,
+		"runtime.GC":                            ext۰NoEffect,
+		"runtime.GOMAXPROCS":                    ext۰NoEffect,
+		"runtime.Goexit":                        ext۰NoEffect,
+		"runtime.GoroutineProfile":              ext۰NoEffect,
+		"runtime.Gosched":                       ext۰NoEffect,
+		"runtime.MemProfile":                    ext۰NoEffect,
+		"runtime.NumCPU":                        ext۰NoEffect,
+		"runtime.NumGoroutine":                  ext۰NoEffect,
+		"runtime.ReadMemStats":                  ext۰NoEffect,
+		"runtime.SetBlockProfileRate":           ext۰NoEffect,
+		"runtime.SetCPUProfileRate":             ext۰NoEffect,
+		"runtime.SetFinalizer":                  ext۰runtime۰SetFinalizer,
+		"runtime.Stack":                         ext۰NoEffect,
+		"runtime.ThreadCreateProfile":           ext۰NoEffect,
+		"runtime.cstringToGo":                   ext۰NoEffect,
+		"runtime.funcentry_go":                  ext۰NoEffect,
+		"runtime.funcline_go":                   ext۰NoEffect,
+		"runtime.funcname_go":                   ext۰NoEffect,
+		"runtime.getgoroot":                     ext۰NoEffect,
+		"runtime/pprof.runtime_cyclesPerSecond": ext۰NoEffect,
+		"strings.IndexByte":                     ext۰NoEffect,
+		"sync.runtime_Semacquire":               ext۰NoEffect,
+		"sync.runtime_Semrelease":               ext۰NoEffect,
+		"sync.runtime_Syncsemacquire":           ext۰NoEffect,
+		"sync.runtime_Syncsemcheck":             ext۰NoEffect,
+		"sync.runtime_Syncsemrelease":           ext۰NoEffect,
+		"sync.runtime_procPin":                  ext۰NoEffect,
+		"sync.runtime_procUnpin":                ext۰NoEffect,
+		"sync.runtime_registerPool":             ext۰NoEffect,
+		"sync/atomic.AddInt32":                  ext۰NoEffect,
+		"sync/atomic.AddInt64":                  ext۰NoEffect,
+		"sync/atomic.AddUint32":                 ext۰NoEffect,
+		"sync/atomic.AddUint64":                 ext۰NoEffect,
+		"sync/atomic.AddUintptr":                ext۰NoEffect,
+		"sync/atomic.CompareAndSwapInt32":       ext۰NoEffect,
+		"sync/atomic.CompareAndSwapUint32":      ext۰NoEffect,
+		"sync/atomic.CompareAndSwapUint64":      ext۰NoEffect,
+		"sync/atomic.CompareAndSwapUintptr":     ext۰NoEffect,
+		"sync/atomic.LoadInt32":                 ext۰NoEffect,
+		"sync/atomic.LoadInt64":                 ext۰NoEffect,
+		"sync/atomic.LoadPointer":               ext۰NoEffect, // ignore unsafe.Pointers
+		"sync/atomic.LoadUint32":                ext۰NoEffect,
+		"sync/atomic.LoadUint64":                ext۰NoEffect,
+		"sync/atomic.LoadUintptr":               ext۰NoEffect,
+		"sync/atomic.StoreInt32":                ext۰NoEffect,
+		"sync/atomic.StorePointer":              ext۰NoEffect, // ignore unsafe.Pointers
+		"sync/atomic.StoreUint32":               ext۰NoEffect,
+		"sync/atomic.StoreUintptr":              ext۰NoEffect,
+		"syscall.Close":                         ext۰NoEffect,
+		"syscall.Exit":                          ext۰NoEffect,
+		"syscall.Getpid":                        ext۰NoEffect,
+		"syscall.Getwd":                         ext۰NoEffect,
+		"syscall.Kill":                          ext۰NoEffect,
+		"syscall.RawSyscall":                    ext۰NoEffect,
+		"syscall.RawSyscall6":                   ext۰NoEffect,
+		"syscall.Syscall":                       ext۰NoEffect,
+		"syscall.Syscall6":                      ext۰NoEffect,
+		"syscall.runtime_AfterFork":             ext۰NoEffect,
+		"syscall.runtime_BeforeFork":            ext۰NoEffect,
+		"syscall.setenv_c":                      ext۰NoEffect,
+		"time.Sleep":                            ext۰NoEffect,
+		"time.now":                              ext۰NoEffect,
+		"time.startTimer":                       ext۰time۰startTimer,
+		"time.stopTimer":                        ext۰NoEffect,
+	} {
+		intrinsicsByName[name] = fn
+	}
+}
+
+// findIntrinsic returns the constraint generation function for an
+// intrinsic function fn, or nil if the function should be handled normally.
+//
+func (a *analysis) findIntrinsic(fn *ssa.Function) intrinsic {
+	// Consult the *Function-keyed cache.
+	// A cached nil indicates a normal non-intrinsic function.
+	impl, ok := a.intrinsics[fn]
+	if !ok {
+		impl = intrinsicsByName[fn.String()] // may be nil
+
+		if a.isReflect(fn) {
+			if !a.config.Reflection {
+				impl = ext۰NoEffect // reflection disabled
+			} else if impl == nil {
+				// Ensure all "reflect" code is treated intrinsically.
+				impl = ext۰NotYetImplemented
+			}
+		}
+
+		a.intrinsics[fn] = impl
+	}
+	return impl
+}
+
+// isReflect reports whether fn belongs to the "reflect" package.
+func (a *analysis) isReflect(fn *ssa.Function) bool {
+	if a.reflectValueObj == nil {
+		return false // "reflect" package not loaded
+	}
+	reflectPackage := a.reflectValueObj.Pkg()
+	if fn.Pkg != nil && fn.Pkg.Object == reflectPackage {
+		return true
+	}
+	// Synthetic wrappers have a nil Pkg, so they slip through the
+	// previous check.  Check the receiver package.
+	// TODO(adonovan): should synthetic wrappers have a non-nil Pkg?
+	if recv := fn.Signature.Recv(); recv != nil {
+		if named, ok := deref(recv.Type()).(*types.Named); ok {
+			if named.Obj().Pkg() == reflectPackage {
+				return true // e.g. wrapper of (reflect.Value).f
+			}
+		}
+	}
+	return false
+}
+
+// A trivial intrinsic suitable for any function that does not:
+// 1) induce aliases between its arguments or any global variables;
+// 2) call any functions; or
+// 3) create any labels.
+//
+// Many intrinsics (such as CompareAndSwapInt32) have a fourth kind of
+// effect: loading or storing through a pointer.  Though these could
+// be significant, we deliberately ignore them because they are
+// generally not worth the effort.
+//
+// We sometimes violate condition #3 if the function creates only
+// non-function labels, as the control-flow graph is still sound.
+//
+func ext۰NoEffect(a *analysis, cgn *cgnode) {}
+
+func ext۰NotYetImplemented(a *analysis, cgn *cgnode) {
+	fn := cgn.fn
+	a.warnf(fn.Pos(), "unsound: intrinsic treatment of %s not yet implemented", fn)
+}
+
+// ---------- func runtime.SetFinalizer(x, f interface{}) ----------
+
+// runtime.SetFinalizer(x, f)
+type runtimeSetFinalizerConstraint struct {
+	targets nodeid // (indirect)
+	f       nodeid // (ptr)
+	x       nodeid
+}
+
+func (c *runtimeSetFinalizerConstraint) ptr() nodeid { return c.f }
+func (c *runtimeSetFinalizerConstraint) presolve(h *hvn) {
+	h.markIndirect(onodeid(c.targets), "SetFinalizer.targets")
+}
+func (c *runtimeSetFinalizerConstraint) renumber(mapping []nodeid) {
+	c.targets = mapping[c.targets]
+	c.f = mapping[c.f]
+	c.x = mapping[c.x]
+}
+
+func (c *runtimeSetFinalizerConstraint) String() string {
+	return fmt.Sprintf("runtime.SetFinalizer(n%d, n%d)", c.x, c.f)
+}
+
+func (c *runtimeSetFinalizerConstraint) solve(a *analysis, delta *nodeset) {
+	for _, fObj := range delta.AppendTo(a.deltaSpace) {
+		tDyn, f, indirect := a.taggedValue(nodeid(fObj))
+		if indirect {
+			// TODO(adonovan): we'll need to implement this
+			// when we start creating indirect tagged objects.
+			panic("indirect tagged object")
+		}
+
+		tSig, ok := tDyn.Underlying().(*types.Signature)
+		if !ok {
+			continue // not a function
+		}
+		if tSig.Recv() != nil {
+			panic(tSig)
+		}
+		if tSig.Params().Len() != 1 {
+			continue //  not a unary function
+		}
+
+		// Extract x to tmp.
+		tx := tSig.Params().At(0).Type()
+		tmp := a.addNodes(tx, "SetFinalizer.tmp")
+		a.typeAssert(tx, tmp, c.x, false)
+
+		// Call f(tmp).
+		a.store(f, tmp, 1, a.sizeof(tx))
+
+		// Add dynamic call target.
+		if a.onlineCopy(c.targets, f) {
+			a.addWork(c.targets)
+		}
+	}
+}
+
+func ext۰runtime۰SetFinalizer(a *analysis, cgn *cgnode) {
+	// This is the shared contour, used for dynamic calls.
+	targets := a.addOneNode(tInvalid, "SetFinalizer.targets", nil)
+	cgn.sites = append(cgn.sites, &callsite{targets: targets})
+	params := a.funcParams(cgn.obj)
+	a.addConstraint(&runtimeSetFinalizerConstraint{
+		targets: targets,
+		x:       params,
+		f:       params + 1,
+	})
+}
+
+// ---------- func time.startTimer(t *runtimeTimer) ----------
+
+// time.StartTimer(t)
+type timeStartTimerConstraint struct {
+	targets nodeid // (indirect)
+	t       nodeid // (ptr)
+}
+
+func (c *timeStartTimerConstraint) ptr() nodeid { return c.t }
+func (c *timeStartTimerConstraint) presolve(h *hvn) {
+	h.markIndirect(onodeid(c.targets), "StartTimer.targets")
+}
+func (c *timeStartTimerConstraint) renumber(mapping []nodeid) {
+	c.targets = mapping[c.targets]
+	c.t = mapping[c.t]
+}
+
+func (c *timeStartTimerConstraint) String() string {
+	return fmt.Sprintf("time.startTimer(n%d)", c.t)
+}
+
+func (c *timeStartTimerConstraint) solve(a *analysis, delta *nodeset) {
+	for _, tObj := range delta.AppendTo(a.deltaSpace) {
+		t := nodeid(tObj)
+
+		// We model startTimer as if it was defined thus:
+		// 	func startTimer(t *runtimeTimer) { t.f(t.arg) }
+
+		// We hard-code the field offsets of time.runtimeTimer:
+		// type runtimeTimer struct {
+		//  0     __identity__
+		//  1    i      int32
+		//  2    when   int64
+		//  3    period int64
+		//  4    f      func(int64, interface{})
+		//  5    arg    interface{}
+		// }
+		f := t + 4
+		arg := t + 5
+
+		// store t.arg to t.f.params[0]
+		// (offset 1 => skip identity)
+		a.store(f, arg, 1, 1)
+
+		// Add dynamic call target.
+		if a.onlineCopy(c.targets, f) {
+			a.addWork(c.targets)
+		}
+	}
+}
+
+func ext۰time۰startTimer(a *analysis, cgn *cgnode) {
+	// This is the shared contour, used for dynamic calls.
+	targets := a.addOneNode(tInvalid, "startTimer.targets", nil)
+	cgn.sites = append(cgn.sites, &callsite{targets: targets})
+	params := a.funcParams(cgn.obj)
+	a.addConstraint(&timeStartTimerConstraint{
+		targets: targets,
+		t:       params,
+	})
+}
diff --git a/go/pointer/labels.go b/go/pointer/labels.go
new file mode 100644
index 0000000..cf6ef20
--- /dev/null
+++ b/go/pointer/labels.go
@@ -0,0 +1,152 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package pointer
+
+import (
+	"fmt"
+	"go/token"
+	"strings"
+
+	"golang.org/x/tools/go/ssa"
+	"golang.org/x/tools/go/types"
+)
+
+// A Label is an entity that may be pointed to by a pointer, map,
+// channel, 'func', slice or interface.
+//
+// Labels include:
+//      - functions
+//      - globals
+//      - tagged objects, representing interfaces and reflect.Values
+//      - arrays created by conversions (e.g. []byte("foo"), []byte(s))
+//      - stack- and heap-allocated variables (including composite literals)
+//      - channels, maps and arrays created by make()
+//      - intrinsic or reflective operations that allocate (e.g. append, reflect.New)
+//      - intrinsic objects, e.g. the initial array behind os.Args.
+//      - and their subelements, e.g. "alloc.y[*].z"
+//
+// Labels are so varied that they defy good generalizations;
+// some have no value, no callgraph node, or no position.
+// Many objects have types that are inexpressible in Go:
+// maps, channels, functions, tagged objects.
+//
+// At most one of Value() or ReflectType() may return non-nil.
+//
+type Label struct {
+	obj        *object    // the addressable memory location containing this label
+	subelement *fieldInfo // subelement path within obj, e.g. ".a.b[*].c"
+}
+
+// Value returns the ssa.Value that allocated this label's object, if any.
+func (l Label) Value() ssa.Value {
+	val, _ := l.obj.data.(ssa.Value)
+	return val
+}
+
+// ReflectType returns the type represented by this label if it is an
+// reflect.rtype instance object or *reflect.rtype-tagged object.
+//
+func (l Label) ReflectType() types.Type {
+	rtype, _ := l.obj.data.(types.Type)
+	return rtype
+}
+
+// Path returns the path to the subelement of the object containing
+// this label.  For example, ".x[*].y".
+//
+func (l Label) Path() string {
+	return l.subelement.path()
+}
+
+// Pos returns the position of this label, if known, zero otherwise.
+func (l Label) Pos() token.Pos {
+	switch data := l.obj.data.(type) {
+	case ssa.Value:
+		return data.Pos()
+	case types.Type:
+		if nt, ok := deref(data).(*types.Named); ok {
+			return nt.Obj().Pos()
+		}
+	}
+	if cgn := l.obj.cgn; cgn != nil {
+		return cgn.fn.Pos()
+	}
+	return token.NoPos
+}
+
+// String returns the printed form of this label.
+//
+// Examples:                                    Object type:
+//      x                                       (a variable)
+//      (sync.Mutex).Lock                       (a function)
+//      convert                                 (array created by conversion)
+//      makemap                                 (map allocated via make)
+//      makechan                                (channel allocated via make)
+//      makeinterface                           (tagged object allocated by makeinterface)
+//      <alloc in reflect.Zero>                 (allocation in instrinsic)
+//      sync.Mutex                              (a reflect.rtype instance)
+//      <command-line arguments>                (an intrinsic object)
+//
+// Labels within compound objects have subelement paths:
+//      x.y[*].z                                (a struct variable, x)
+//      append.y[*].z                           (array allocated by append)
+//      makeslice.y[*].z                        (array allocated via make)
+//
+// TODO(adonovan): expose func LabelString(*types.Package, Label).
+//
+func (l Label) String() string {
+	var s string
+	switch v := l.obj.data.(type) {
+	case types.Type:
+		return v.String()
+
+	case string:
+		s = v // an intrinsic object (e.g. os.Args[*])
+
+	case nil:
+		if l.obj.cgn != nil {
+			// allocation by intrinsic or reflective operation
+			s = fmt.Sprintf("<alloc in %s>", l.obj.cgn.fn)
+		} else {
+			s = "<unknown>" // should be unreachable
+		}
+
+	case *ssa.Function:
+		s = v.String()
+
+	case *ssa.Global:
+		s = v.String()
+
+	case *ssa.Const:
+		s = v.Name()
+
+	case *ssa.Alloc:
+		s = v.Comment
+		if s == "" {
+			s = "alloc"
+		}
+
+	case *ssa.Call:
+		// Currently only calls to append can allocate objects.
+		if v.Call.Value.(*ssa.Builtin).Object().Name() != "append" {
+			panic("unhandled *ssa.Call label: " + v.Name())
+		}
+		s = "append"
+
+	case *ssa.MakeMap, *ssa.MakeChan, *ssa.MakeSlice, *ssa.Convert:
+		s = strings.ToLower(strings.TrimPrefix(fmt.Sprintf("%T", v), "*ssa."))
+
+	case *ssa.MakeInterface:
+		// MakeInterface is usually implicit in Go source (so
+		// Pos()==0), and tagged objects may be allocated
+		// synthetically (so no *MakeInterface data).
+		s = "makeinterface:" + v.X.Type().String()
+
+	default:
+		panic(fmt.Sprintf("unhandled object data type: %T", v))
+	}
+
+	return s + l.subelement.path()
+}
diff --git a/go/pointer/opt.go b/go/pointer/opt.go
new file mode 100644
index 0000000..2620cc0
--- /dev/null
+++ b/go/pointer/opt.go
@@ -0,0 +1,125 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package pointer
+
+// This file implements renumbering, a pre-solver optimization to
+// improve the efficiency of the solver's points-to set representation.
+//
+// TODO(adonovan): rename file "renumber.go"
+
+import "fmt"
+
+// renumber permutes a.nodes so that all nodes within an addressable
+// object appear before all non-addressable nodes, maintaining the
+// order of nodes within the same object (as required by offsetAddr).
+//
+// renumber must update every nodeid in the analysis (constraints,
+// Pointers, callgraph, etc) to reflect the new ordering.
+//
+// This is an optimisation to increase the locality and efficiency of
+// sparse representations of points-to sets.  (Typically only about
+// 20% of nodes are within an object.)
+//
+// NB: nodes added during solving (e.g. for reflection, SetFinalizer)
+// will be appended to the end.
+//
+// Renumbering makes the PTA log inscrutable.  To aid debugging, later
+// phases (e.g. HVN) must not rely on it having occurred.
+//
+func (a *analysis) renumber() {
+	if a.log != nil {
+		fmt.Fprintf(a.log, "\n\n==== Renumbering\n\n")
+	}
+
+	N := nodeid(len(a.nodes))
+	newNodes := make([]*node, N, N)
+	renumbering := make([]nodeid, N, N) // maps old to new
+
+	var i, j nodeid
+
+	// The zero node is special.
+	newNodes[j] = a.nodes[i]
+	renumbering[i] = j
+	i++
+	j++
+
+	// Pass 1: object nodes.
+	for i < N {
+		obj := a.nodes[i].obj
+		if obj == nil {
+			i++
+			continue
+		}
+
+		end := i + nodeid(obj.size)
+		for i < end {
+			newNodes[j] = a.nodes[i]
+			renumbering[i] = j
+			i++
+			j++
+		}
+	}
+	nobj := j
+
+	// Pass 2: non-object nodes.
+	for i = 1; i < N; {
+		obj := a.nodes[i].obj
+		if obj != nil {
+			i += nodeid(obj.size)
+			continue
+		}
+
+		newNodes[j] = a.nodes[i]
+		renumbering[i] = j
+		i++
+		j++
+	}
+
+	if j != N {
+		panic(fmt.Sprintf("internal error: j=%d, N=%d", j, N))
+	}
+
+	// Log the remapping table.
+	if a.log != nil {
+		fmt.Fprintf(a.log, "Renumbering nodes to improve density:\n")
+		fmt.Fprintf(a.log, "(%d object nodes of %d total)\n", nobj, N)
+		for old, new := range renumbering {
+			fmt.Fprintf(a.log, "\tn%d -> n%d\n", old, new)
+		}
+	}
+
+	// Now renumber all existing nodeids to use the new node permutation.
+	// It is critical that all reachable nodeids are accounted for!
+
+	// Renumber nodeids in queried Pointers.
+	for v, ptr := range a.result.Queries {
+		ptr.n = renumbering[ptr.n]
+		a.result.Queries[v] = ptr
+	}
+	for v, ptr := range a.result.IndirectQueries {
+		ptr.n = renumbering[ptr.n]
+		a.result.IndirectQueries[v] = ptr
+	}
+
+	// Renumber nodeids in global objects.
+	for v, id := range a.globalobj {
+		a.globalobj[v] = renumbering[id]
+	}
+
+	// Renumber nodeids in constraints.
+	for _, c := range a.constraints {
+		c.renumber(renumbering)
+	}
+
+	// Renumber nodeids in the call graph.
+	for _, cgn := range a.cgnodes {
+		cgn.obj = renumbering[cgn.obj]
+		for _, site := range cgn.sites {
+			site.targets = renumbering[site.targets]
+		}
+	}
+
+	a.nodes = newNodes
+}
diff --git a/go/pointer/pointer_test.go b/go/pointer/pointer_test.go
new file mode 100644
index 0000000..2744d4f
--- /dev/null
+++ b/go/pointer/pointer_test.go
@@ -0,0 +1,576 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// No testdata on Android.
+
+// +build !android
+
+package pointer_test
+
+// This test uses 'expectation' comments embedded within testdata/*.go
+// files to specify the expected pointer analysis behaviour.
+// See below for grammar.
+
+import (
+	"bytes"
+	"errors"
+	"fmt"
+	"go/token"
+	"io/ioutil"
+	"os"
+	"regexp"
+	"strconv"
+	"strings"
+	"testing"
+
+	"golang.org/x/tools/go/callgraph"
+	"golang.org/x/tools/go/loader"
+	"golang.org/x/tools/go/pointer"
+	"golang.org/x/tools/go/ssa"
+	"golang.org/x/tools/go/ssa/ssautil"
+	"golang.org/x/tools/go/types"
+	"golang.org/x/tools/go/types/typeutil"
+)
+
+var inputs = []string{
+	"testdata/a_test.go",
+	"testdata/another.go",
+	"testdata/arrayreflect.go",
+	"testdata/arrays.go",
+	"testdata/channels.go",
+	"testdata/chanreflect.go",
+	"testdata/context.go",
+	"testdata/conv.go",
+	"testdata/finalizer.go",
+	"testdata/flow.go",
+	"testdata/fmtexcerpt.go",
+	"testdata/func.go",
+	"testdata/funcreflect.go",
+	"testdata/hello.go", // NB: causes spurious failure of HVN cross-check
+	"testdata/interfaces.go",
+	"testdata/issue9002.go",
+	"testdata/mapreflect.go",
+	"testdata/maps.go",
+	"testdata/panic.go",
+	"testdata/recur.go",
+	"testdata/reflect.go",
+	"testdata/rtti.go",
+	"testdata/structreflect.go",
+	"testdata/structs.go",
+	"testdata/timer.go",
+}
+
+// Expectation grammar:
+//
+// @calls f -> g
+//
+//   A 'calls' expectation asserts that edge (f, g) appears in the
+//   callgraph.  f and g are notated as per Function.String(), which
+//   may contain spaces (e.g. promoted method in anon struct).
+//
+// @pointsto a | b | c
+//
+//   A 'pointsto' expectation asserts that the points-to set of its
+//   operand contains exactly the set of labels {a,b,c} notated as per
+//   labelString.
+//
+//   A 'pointsto' expectation must appear on the same line as a
+//   print(x) statement; the expectation's operand is x.
+//
+//   If one of the strings is "...", the expectation asserts that the
+//   points-to set at least the other labels.
+//
+//   We use '|' because label names may contain spaces, e.g.  methods
+//   of anonymous structs.
+//
+//   From a theoretical perspective, concrete types in interfaces are
+//   labels too, but they are represented differently and so have a
+//   different expectation, @types, below.
+//
+// @types t | u | v
+//
+//   A 'types' expectation asserts that the set of possible dynamic
+//   types of its interface operand is exactly {t,u,v}, notated per
+//   go/types.Type.String(). In other words, it asserts that the type
+//   component of the interface may point to that set of concrete type
+//   literals.  It also works for reflect.Value, though the types
+//   needn't be concrete in that case.
+//
+//   A 'types' expectation must appear on the same line as a
+//   print(x) statement; the expectation's operand is x.
+//
+//   If one of the strings is "...", the expectation asserts that the
+//   interface's type may point to at least the other types.
+//
+//   We use '|' because type names may contain spaces.
+//
+// @warning "regexp"
+//
+//   A 'warning' expectation asserts that the analysis issues a
+//   warning that matches the regular expression within the string
+//   literal.
+//
+// @line id
+//
+//   A line directive associates the name "id" with the current
+//   file:line.  The string form of labels will use this id instead of
+//   a file:line, making @pointsto expectations more robust against
+//   perturbations in the source file.
+//   (NB, anon functions still include line numbers.)
+//
+type expectation struct {
+	kind     string // "pointsto" | "types" | "calls" | "warning"
+	filename string
+	linenum  int // source line number, 1-based
+	args     []string
+	types    []types.Type // for types
+}
+
+func (e *expectation) String() string {
+	return fmt.Sprintf("@%s[%s]", e.kind, strings.Join(e.args, " | "))
+}
+
+func (e *expectation) errorf(format string, args ...interface{}) {
+	fmt.Printf("%s:%d: ", e.filename, e.linenum)
+	fmt.Printf(format, args...)
+	fmt.Println()
+}
+
+func (e *expectation) needsProbe() bool {
+	return e.kind == "pointsto" || e.kind == "types"
+}
+
+// Find probe (call to print(x)) of same source file/line as expectation.
+func findProbe(prog *ssa.Program, probes map[*ssa.CallCommon]bool, queries map[ssa.Value]pointer.Pointer, e *expectation) (site *ssa.CallCommon, pts pointer.PointsToSet) {
+	for call := range probes {
+		pos := prog.Fset.Position(call.Pos())
+		if pos.Line == e.linenum && pos.Filename == e.filename {
+			// TODO(adonovan): send this to test log (display only on failure).
+			// fmt.Printf("%s:%d: info: found probe for %s: %s\n",
+			// 	e.filename, e.linenum, e, p.arg0) // debugging
+			return call, queries[call.Args[0]].PointsTo()
+		}
+	}
+	return // e.g. analysis didn't reach this call
+}
+
+func doOneInput(input, filename string) bool {
+	var conf loader.Config
+
+	// Parsing.
+	f, err := conf.ParseFile(filename, input)
+	if err != nil {
+		fmt.Println(err)
+		return false
+	}
+
+	// Create single-file main package and import its dependencies.
+	conf.CreateFromFiles("main", f)
+	iprog, err := conf.Load()
+	if err != nil {
+		fmt.Println(err)
+		return false
+	}
+	mainPkgInfo := iprog.Created[0].Pkg
+
+	// SSA creation + building.
+	prog := ssautil.CreateProgram(iprog, ssa.SanityCheckFunctions)
+	prog.BuildAll()
+
+	mainpkg := prog.Package(mainPkgInfo)
+	ptrmain := mainpkg // main package for the pointer analysis
+	if mainpkg.Func("main") == nil {
+		// No main function; assume it's a test.
+		ptrmain = prog.CreateTestMainPackage(mainpkg)
+	}
+
+	// Find all calls to the built-in print(x).  Analytically,
+	// print is a no-op, but it's a convenient hook for testing
+	// the PTS of an expression, so our tests use it.
+	probes := make(map[*ssa.CallCommon]bool)
+	for fn := range ssautil.AllFunctions(prog) {
+		if fn.Pkg == mainpkg {
+			for _, b := range fn.Blocks {
+				for _, instr := range b.Instrs {
+					if instr, ok := instr.(ssa.CallInstruction); ok {
+						call := instr.Common()
+						if b, ok := call.Value.(*ssa.Builtin); ok && b.Name() == "print" && len(call.Args) == 1 {
+							probes[instr.Common()] = true
+						}
+					}
+				}
+			}
+		}
+	}
+
+	ok := true
+
+	lineMapping := make(map[string]string) // maps "file:line" to @line tag
+
+	// Parse expectations in this input.
+	var exps []*expectation
+	re := regexp.MustCompile("// *@([a-z]*) *(.*)$")
+	lines := strings.Split(input, "\n")
+	for linenum, line := range lines {
+		linenum++ // make it 1-based
+		if matches := re.FindAllStringSubmatch(line, -1); matches != nil {
+			match := matches[0]
+			kind, rest := match[1], match[2]
+			e := &expectation{kind: kind, filename: filename, linenum: linenum}
+
+			if kind == "line" {
+				if rest == "" {
+					ok = false
+					e.errorf("@%s expectation requires identifier", kind)
+				} else {
+					lineMapping[fmt.Sprintf("%s:%d", filename, linenum)] = rest
+				}
+				continue
+			}
+
+			if e.needsProbe() && !strings.Contains(line, "print(") {
+				ok = false
+				e.errorf("@%s expectation must follow call to print(x)", kind)
+				continue
+			}
+
+			switch kind {
+			case "pointsto":
+				e.args = split(rest, "|")
+
+			case "types":
+				for _, typstr := range split(rest, "|") {
+					var t types.Type = types.Typ[types.Invalid] // means "..."
+					if typstr != "..." {
+						tv, err := types.Eval(prog.Fset, mainpkg.Object, f.Pos(), typstr)
+						if err != nil {
+							ok = false
+							// Don't print err since its location is bad.
+							e.errorf("'%s' is not a valid type: %s", typstr, err)
+							continue
+						}
+						t = tv.Type
+					}
+					e.types = append(e.types, t)
+				}
+
+			case "calls":
+				e.args = split(rest, "->")
+				// TODO(adonovan): eagerly reject the
+				// expectation if fn doesn't denote
+				// existing function, rather than fail
+				// the expectation after analysis.
+				if len(e.args) != 2 {
+					ok = false
+					e.errorf("@calls expectation wants 'caller -> callee' arguments")
+					continue
+				}
+
+			case "warning":
+				lit, err := strconv.Unquote(strings.TrimSpace(rest))
+				if err != nil {
+					ok = false
+					e.errorf("couldn't parse @warning operand: %s", err.Error())
+					continue
+				}
+				e.args = append(e.args, lit)
+
+			default:
+				ok = false
+				e.errorf("unknown expectation kind: %s", e)
+				continue
+			}
+			exps = append(exps, e)
+		}
+	}
+
+	var log bytes.Buffer
+	fmt.Fprintf(&log, "Input: %s\n", filename)
+
+	// Run the analysis.
+	config := &pointer.Config{
+		Reflection:     true,
+		BuildCallGraph: true,
+		Mains:          []*ssa.Package{ptrmain},
+		Log:            &log,
+	}
+	for probe := range probes {
+		v := probe.Args[0]
+		if pointer.CanPoint(v.Type()) {
+			config.AddQuery(v)
+		}
+	}
+
+	// Print the log is there was an error or a panic.
+	complete := false
+	defer func() {
+		if !complete || !ok {
+			log.WriteTo(os.Stderr)
+		}
+	}()
+
+	result, err := pointer.Analyze(config)
+	if err != nil {
+		panic(err) // internal error in pointer analysis
+	}
+
+	// Check the expectations.
+	for _, e := range exps {
+		var call *ssa.CallCommon
+		var pts pointer.PointsToSet
+		var tProbe types.Type
+		if e.needsProbe() {
+			if call, pts = findProbe(prog, probes, result.Queries, e); call == nil {
+				ok = false
+				e.errorf("unreachable print() statement has expectation %s", e)
+				continue
+			}
+			tProbe = call.Args[0].Type()
+			if !pointer.CanPoint(tProbe) {
+				ok = false
+				e.errorf("expectation on non-pointerlike operand: %s", tProbe)
+				continue
+			}
+		}
+
+		switch e.kind {
+		case "pointsto":
+			if !checkPointsToExpectation(e, pts, lineMapping, prog) {
+				ok = false
+			}
+
+		case "types":
+			if !checkTypesExpectation(e, pts, tProbe) {
+				ok = false
+			}
+
+		case "calls":
+			if !checkCallsExpectation(prog, e, result.CallGraph) {
+				ok = false
+			}
+
+		case "warning":
+			if !checkWarningExpectation(prog, e, result.Warnings) {
+				ok = false
+			}
+		}
+	}
+
+	complete = true
+
+	// ok = false // debugging: uncomment to always see log
+
+	return ok
+}
+
+func labelString(l *pointer.Label, lineMapping map[string]string, prog *ssa.Program) string {
+	// Functions and Globals need no pos suffix,
+	// nor do allocations in intrinsic operations
+	// (for which we'll print the function name).
+	switch l.Value().(type) {
+	case nil, *ssa.Function, *ssa.Global:
+		return l.String()
+	}
+
+	str := l.String()
+	if pos := l.Pos(); pos != token.NoPos {
+		// Append the position, using a @line tag instead of a line number, if defined.
+		posn := prog.Fset.Position(pos)
+		s := fmt.Sprintf("%s:%d", posn.Filename, posn.Line)
+		if tag, ok := lineMapping[s]; ok {
+			return fmt.Sprintf("%s@%s:%d", str, tag, posn.Column)
+		}
+		str = fmt.Sprintf("%s@%s", str, posn)
+	}
+	return str
+}
+
+func checkPointsToExpectation(e *expectation, pts pointer.PointsToSet, lineMapping map[string]string, prog *ssa.Program) bool {
+	expected := make(map[string]int)
+	surplus := make(map[string]int)
+	exact := true
+	for _, g := range e.args {
+		if g == "..." {
+			exact = false
+			continue
+		}
+		expected[g]++
+	}
+	// Find the set of labels that the probe's
+	// argument (x in print(x)) may point to.
+	for _, label := range pts.Labels() {
+		name := labelString(label, lineMapping, prog)
+		if expected[name] > 0 {
+			expected[name]--
+		} else if exact {
+			surplus[name]++
+		}
+	}
+	// Report multiset difference:
+	ok := true
+	for _, count := range expected {
+		if count > 0 {
+			ok = false
+			e.errorf("value does not alias these expected labels: %s", join(expected))
+			break
+		}
+	}
+	for _, count := range surplus {
+		if count > 0 {
+			ok = false
+			e.errorf("value may additionally alias these labels: %s", join(surplus))
+			break
+		}
+	}
+	return ok
+}
+
+func checkTypesExpectation(e *expectation, pts pointer.PointsToSet, typ types.Type) bool {
+	var expected typeutil.Map
+	var surplus typeutil.Map
+	exact := true
+	for _, g := range e.types {
+		if g == types.Typ[types.Invalid] {
+			exact = false
+			continue
+		}
+		expected.Set(g, struct{}{})
+	}
+
+	if !pointer.CanHaveDynamicTypes(typ) {
+		e.errorf("@types expectation requires an interface- or reflect.Value-typed operand, got %s", typ)
+		return false
+	}
+
+	// Find the set of types that the probe's
+	// argument (x in print(x)) may contain.
+	for _, T := range pts.DynamicTypes().Keys() {
+		if expected.At(T) != nil {
+			expected.Delete(T)
+		} else if exact {
+			surplus.Set(T, struct{}{})
+		}
+	}
+	// Report set difference:
+	ok := true
+	if expected.Len() > 0 {
+		ok = false
+		e.errorf("interface cannot contain these types: %s", expected.KeysString())
+	}
+	if surplus.Len() > 0 {
+		ok = false
+		e.errorf("interface may additionally contain these types: %s", surplus.KeysString())
+	}
+	return ok
+}
+
+var errOK = errors.New("OK")
+
+func checkCallsExpectation(prog *ssa.Program, e *expectation, cg *callgraph.Graph) bool {
+	found := make(map[string]int)
+	err := callgraph.GraphVisitEdges(cg, func(edge *callgraph.Edge) error {
+		// Name-based matching is inefficient but it allows us to
+		// match functions whose names that would not appear in an
+		// index ("<root>") or which are not unique ("func@1.2").
+		if edge.Caller.Func.String() == e.args[0] {
+			calleeStr := edge.Callee.Func.String()
+			if calleeStr == e.args[1] {
+				return errOK // expectation satisified; stop the search
+			}
+			found[calleeStr]++
+		}
+		return nil
+	})
+	if err == errOK {
+		return true
+	}
+	if len(found) == 0 {
+		e.errorf("didn't find any calls from %s", e.args[0])
+	}
+	e.errorf("found no call from %s to %s, but only to %s",
+		e.args[0], e.args[1], join(found))
+	return false
+}
+
+func checkWarningExpectation(prog *ssa.Program, e *expectation, warnings []pointer.Warning) bool {
+	// TODO(adonovan): check the position part of the warning too?
+	re, err := regexp.Compile(e.args[0])
+	if err != nil {
+		e.errorf("invalid regular expression in @warning expectation: %s", err.Error())
+		return false
+	}
+
+	if len(warnings) == 0 {
+		e.errorf("@warning %s expectation, but no warnings", strconv.Quote(e.args[0]))
+		return false
+	}
+
+	for _, w := range warnings {
+		if re.MatchString(w.Message) {
+			return true
+		}
+	}
+
+	e.errorf("@warning %s expectation not satised; found these warnings though:", strconv.Quote(e.args[0]))
+	for _, w := range warnings {
+		fmt.Printf("%s: warning: %s\n", prog.Fset.Position(w.Pos), w.Message)
+	}
+	return false
+}
+
+func TestInput(t *testing.T) {
+	ok := true
+
+	wd, err := os.Getwd()
+	if err != nil {
+		t.Errorf("os.Getwd: %s", err)
+		return
+	}
+
+	// 'go test' does a chdir so that relative paths in
+	// diagnostics no longer make sense relative to the invoking
+	// shell's cwd.  We print a special marker so that Emacs can
+	// make sense of them.
+	fmt.Fprintf(os.Stderr, "Entering directory `%s'\n", wd)
+
+	for _, filename := range inputs {
+		content, err := ioutil.ReadFile(filename)
+		if err != nil {
+			t.Errorf("couldn't read file '%s': %s", filename, err)
+			continue
+		}
+
+		if !doOneInput(string(content), filename) {
+			ok = false
+		}
+	}
+	if !ok {
+		t.Fail()
+	}
+}
+
+// join joins the elements of multiset with " | "s.
+func join(set map[string]int) string {
+	var buf bytes.Buffer
+	sep := ""
+	for name, count := range set {
+		for i := 0; i < count; i++ {
+			buf.WriteString(sep)
+			sep = " | "
+			buf.WriteString(name)
+		}
+	}
+	return buf.String()
+}
+
+// split returns the list of sep-delimited non-empty strings in s.
+func split(s, sep string) (r []string) {
+	for _, elem := range strings.Split(s, sep) {
+		elem = strings.TrimSpace(elem)
+		if elem != "" {
+			r = append(r, elem)
+		}
+	}
+	return
+}
diff --git a/go/pointer/print.go b/go/pointer/print.go
new file mode 100644
index 0000000..4f2f4c7
--- /dev/null
+++ b/go/pointer/print.go
@@ -0,0 +1,43 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package pointer
+
+import "fmt"
+
+func (c *addrConstraint) String() string {
+	return fmt.Sprintf("addr n%d <- {&n%d}", c.dst, c.src)
+}
+
+func (c *copyConstraint) String() string {
+	return fmt.Sprintf("copy n%d <- n%d", c.dst, c.src)
+}
+
+func (c *loadConstraint) String() string {
+	return fmt.Sprintf("load n%d <- n%d[%d]", c.dst, c.src, c.offset)
+}
+
+func (c *storeConstraint) String() string {
+	return fmt.Sprintf("store n%d[%d] <- n%d", c.dst, c.offset, c.src)
+}
+
+func (c *offsetAddrConstraint) String() string {
+	return fmt.Sprintf("offsetAddr n%d <- n%d.#%d", c.dst, c.src, c.offset)
+}
+
+func (c *typeFilterConstraint) String() string {
+	return fmt.Sprintf("typeFilter n%d <- n%d.(%s)", c.dst, c.src, c.typ)
+}
+
+func (c *untagConstraint) String() string {
+	return fmt.Sprintf("untag n%d <- n%d.(%s)", c.dst, c.src, c.typ)
+}
+
+func (c *invokeConstraint) String() string {
+	return fmt.Sprintf("invoke n%d.%s(n%d ...)", c.iface, c.method.Name(), c.params)
+}
+
+func (n nodeid) String() string {
+	return fmt.Sprintf("n%d", n)
+}
diff --git a/go/pointer/reflect.go b/go/pointer/reflect.go
new file mode 100644
index 0000000..466995c
--- /dev/null
+++ b/go/pointer/reflect.go
@@ -0,0 +1,1971 @@
+package pointer
+
+// This file implements the generation and resolution rules for
+// constraints arising from the use of reflection in the target
+// program.  See doc.go for explanation of the representation.
+//
+// For consistency, the names of all parameters match those of the
+// actual functions in the "reflect" package.
+//
+// To avoid proliferation of equivalent labels, intrinsics should
+// memoize as much as possible, like TypeOf and Zero do for their
+// tagged objects.
+//
+// TODO(adonovan): this file is rather subtle.  Explain how we derive
+// the implementation of each reflect operator from its spec,
+// including the subtleties of reflect.flag{Addr,RO,Indir}.
+// [Hint: our implementation is as if reflect.flagIndir was always
+// true, i.e. reflect.Values are pointers to tagged objects, there is
+// no inline allocation optimization; and indirect tagged objects (not
+// yet implemented) correspond to reflect.Values with
+// reflect.flagAddr.]
+// A picture would help too.
+//
+// TODO(adonovan): try factoring up the common parts of the majority of
+// these constraints that are single input, single output.
+
+import (
+	"fmt"
+	"reflect"
+
+	"golang.org/x/tools/go/exact"
+	"golang.org/x/tools/go/ssa"
+	"golang.org/x/tools/go/types"
+)
+
+func init() {
+	for name, fn := range map[string]intrinsic{
+		// reflect.Value methods.
+		"(reflect.Value).Addr":            ext۰reflect۰Value۰Addr,
+		"(reflect.Value).Bool":            ext۰NoEffect,
+		"(reflect.Value).Bytes":           ext۰reflect۰Value۰Bytes,
+		"(reflect.Value).Call":            ext۰reflect۰Value۰Call,
+		"(reflect.Value).CallSlice":       ext۰reflect۰Value۰CallSlice,
+		"(reflect.Value).CanAddr":         ext۰NoEffect,
+		"(reflect.Value).CanInterface":    ext۰NoEffect,
+		"(reflect.Value).CanSet":          ext۰NoEffect,
+		"(reflect.Value).Cap":             ext۰NoEffect,
+		"(reflect.Value).Close":           ext۰NoEffect,
+		"(reflect.Value).Complex":         ext۰NoEffect,
+		"(reflect.Value).Convert":         ext۰reflect۰Value۰Convert,
+		"(reflect.Value).Elem":            ext۰reflect۰Value۰Elem,
+		"(reflect.Value).Field":           ext۰reflect۰Value۰Field,
+		"(reflect.Value).FieldByIndex":    ext۰reflect۰Value۰FieldByIndex,
+		"(reflect.Value).FieldByName":     ext۰reflect۰Value۰FieldByName,
+		"(reflect.Value).FieldByNameFunc": ext۰reflect۰Value۰FieldByNameFunc,
+		"(reflect.Value).Float":           ext۰NoEffect,
+		"(reflect.Value).Index":           ext۰reflect۰Value۰Index,
+		"(reflect.Value).Int":             ext۰NoEffect,
+		"(reflect.Value).Interface":       ext۰reflect۰Value۰Interface,
+		"(reflect.Value).InterfaceData":   ext۰NoEffect,
+		"(reflect.Value).IsNil":           ext۰NoEffect,
+		"(reflect.Value).IsValid":         ext۰NoEffect,
+		"(reflect.Value).Kind":            ext۰NoEffect,
+		"(reflect.Value).Len":             ext۰NoEffect,
+		"(reflect.Value).MapIndex":        ext۰reflect۰Value۰MapIndex,
+		"(reflect.Value).MapKeys":         ext۰reflect۰Value۰MapKeys,
+		"(reflect.Value).Method":          ext۰reflect۰Value۰Method,
+		"(reflect.Value).MethodByName":    ext۰reflect۰Value۰MethodByName,
+		"(reflect.Value).NumField":        ext۰NoEffect,
+		"(reflect.Value).NumMethod":       ext۰NoEffect,
+		"(reflect.Value).OverflowComplex": ext۰NoEffect,
+		"(reflect.Value).OverflowFloat":   ext۰NoEffect,
+		"(reflect.Value).OverflowInt":     ext۰NoEffect,
+		"(reflect.Value).OverflowUint":    ext۰NoEffect,
+		"(reflect.Value).Pointer":         ext۰NoEffect,
+		"(reflect.Value).Recv":            ext۰reflect۰Value۰Recv,
+		"(reflect.Value).Send":            ext۰reflect۰Value۰Send,
+		"(reflect.Value).Set":             ext۰reflect۰Value۰Set,
+		"(reflect.Value).SetBool":         ext۰NoEffect,
+		"(reflect.Value).SetBytes":        ext۰reflect۰Value۰SetBytes,
+		"(reflect.Value).SetComplex":      ext۰NoEffect,
+		"(reflect.Value).SetFloat":        ext۰NoEffect,
+		"(reflect.Value).SetInt":          ext۰NoEffect,
+		"(reflect.Value).SetLen":          ext۰NoEffect,
+		"(reflect.Value).SetMapIndex":     ext۰reflect۰Value۰SetMapIndex,
+		"(reflect.Value).SetPointer":      ext۰reflect۰Value۰SetPointer,
+		"(reflect.Value).SetString":       ext۰NoEffect,
+		"(reflect.Value).SetUint":         ext۰NoEffect,
+		"(reflect.Value).Slice":           ext۰reflect۰Value۰Slice,
+		"(reflect.Value).String":          ext۰NoEffect,
+		"(reflect.Value).TryRecv":         ext۰reflect۰Value۰Recv,
+		"(reflect.Value).TrySend":         ext۰reflect۰Value۰Send,
+		"(reflect.Value).Type":            ext۰NoEffect,
+		"(reflect.Value).Uint":            ext۰NoEffect,
+		"(reflect.Value).UnsafeAddr":      ext۰NoEffect,
+
+		// Standalone reflect.* functions.
+		"reflect.Append":      ext۰reflect۰Append,
+		"reflect.AppendSlice": ext۰reflect۰AppendSlice,
+		"reflect.Copy":        ext۰reflect۰Copy,
+		"reflect.ChanOf":      ext۰reflect۰ChanOf,
+		"reflect.DeepEqual":   ext۰NoEffect,
+		"reflect.Indirect":    ext۰reflect۰Indirect,
+		"reflect.MakeChan":    ext۰reflect۰MakeChan,
+		"reflect.MakeFunc":    ext۰reflect۰MakeFunc,
+		"reflect.MakeMap":     ext۰reflect۰MakeMap,
+		"reflect.MakeSlice":   ext۰reflect۰MakeSlice,
+		"reflect.MapOf":       ext۰reflect۰MapOf,
+		"reflect.New":         ext۰reflect۰New,
+		"reflect.NewAt":       ext۰reflect۰NewAt,
+		"reflect.PtrTo":       ext۰reflect۰PtrTo,
+		"reflect.Select":      ext۰reflect۰Select,
+		"reflect.SliceOf":     ext۰reflect۰SliceOf,
+		"reflect.TypeOf":      ext۰reflect۰TypeOf,
+		"reflect.ValueOf":     ext۰reflect۰ValueOf,
+		"reflect.Zero":        ext۰reflect۰Zero,
+		"reflect.init":        ext۰NoEffect,
+
+		// *reflect.rtype methods
+		"(*reflect.rtype).Align":           ext۰NoEffect,
+		"(*reflect.rtype).AssignableTo":    ext۰NoEffect,
+		"(*reflect.rtype).Bits":            ext۰NoEffect,
+		"(*reflect.rtype).ChanDir":         ext۰NoEffect,
+		"(*reflect.rtype).ConvertibleTo":   ext۰NoEffect,
+		"(*reflect.rtype).Elem":            ext۰reflect۰rtype۰Elem,
+		"(*reflect.rtype).Field":           ext۰reflect۰rtype۰Field,
+		"(*reflect.rtype).FieldAlign":      ext۰NoEffect,
+		"(*reflect.rtype).FieldByIndex":    ext۰reflect۰rtype۰FieldByIndex,
+		"(*reflect.rtype).FieldByName":     ext۰reflect۰rtype۰FieldByName,
+		"(*reflect.rtype).FieldByNameFunc": ext۰reflect۰rtype۰FieldByNameFunc,
+		"(*reflect.rtype).Implements":      ext۰NoEffect,
+		"(*reflect.rtype).In":              ext۰reflect۰rtype۰In,
+		"(*reflect.rtype).IsVariadic":      ext۰NoEffect,
+		"(*reflect.rtype).Key":             ext۰reflect۰rtype۰Key,
+		"(*reflect.rtype).Kind":            ext۰NoEffect,
+		"(*reflect.rtype).Len":             ext۰NoEffect,
+		"(*reflect.rtype).Method":          ext۰reflect۰rtype۰Method,
+		"(*reflect.rtype).MethodByName":    ext۰reflect۰rtype۰MethodByName,
+		"(*reflect.rtype).Name":            ext۰NoEffect,
+		"(*reflect.rtype).NumField":        ext۰NoEffect,
+		"(*reflect.rtype).NumIn":           ext۰NoEffect,
+		"(*reflect.rtype).NumMethod":       ext۰NoEffect,
+		"(*reflect.rtype).NumOut":          ext۰NoEffect,
+		"(*reflect.rtype).Out":             ext۰reflect۰rtype۰Out,
+		"(*reflect.rtype).PkgPath":         ext۰NoEffect,
+		"(*reflect.rtype).Size":            ext۰NoEffect,
+		"(*reflect.rtype).String":          ext۰NoEffect,
+	} {
+		intrinsicsByName[name] = fn
+	}
+}
+
+// -------------------- (reflect.Value) --------------------
+
+func ext۰reflect۰Value۰Addr(a *analysis, cgn *cgnode) {} // TODO(adonovan)
+
+// ---------- func (Value).Bytes() Value ----------
+
+// result = v.Bytes()
+type rVBytesConstraint struct {
+	v      nodeid // (ptr)
+	result nodeid // (indirect)
+}
+
+func (c *rVBytesConstraint) ptr() nodeid { return c.v }
+func (c *rVBytesConstraint) presolve(h *hvn) {
+	h.markIndirect(onodeid(c.result), "rVBytes.result")
+}
+func (c *rVBytesConstraint) renumber(mapping []nodeid) {
+	c.v = mapping[c.v]
+	c.result = mapping[c.result]
+}
+
+func (c *rVBytesConstraint) String() string {
+	return fmt.Sprintf("n%d = reflect n%d.Bytes()", c.result, c.v)
+}
+
+func (c *rVBytesConstraint) solve(a *analysis, delta *nodeset) {
+	changed := false
+	for _, x := range delta.AppendTo(a.deltaSpace) {
+		vObj := nodeid(x)
+		tDyn, slice, indirect := a.taggedValue(vObj)
+		if indirect {
+			// TODO(adonovan): we'll need to implement this
+			// when we start creating indirect tagged objects.
+			panic("indirect tagged object")
+		}
+
+		tSlice, ok := tDyn.Underlying().(*types.Slice)
+		if ok && types.Identical(tSlice.Elem(), types.Typ[types.Uint8]) {
+			if a.onlineCopy(c.result, slice) {
+				changed = true
+			}
+		}
+	}
+	if changed {
+		a.addWork(c.result)
+	}
+}
+
+func ext۰reflect۰Value۰Bytes(a *analysis, cgn *cgnode) {
+	a.addConstraint(&rVBytesConstraint{
+		v:      a.funcParams(cgn.obj),
+		result: a.funcResults(cgn.obj),
+	})
+}
+
+// ---------- func (Value).Call(in []Value) []Value ----------
+
+// result = v.Call(in)
+type rVCallConstraint struct {
+	cgn       *cgnode
+	targets   nodeid // (indirect)
+	v         nodeid // (ptr)
+	arg       nodeid // = in[*]
+	result    nodeid // (indirect)
+	dotdotdot bool   // interpret last arg as a "..." slice
+}
+
+func (c *rVCallConstraint) ptr() nodeid { return c.v }
+func (c *rVCallConstraint) presolve(h *hvn) {
+	h.markIndirect(onodeid(c.targets), "rVCall.targets")
+	h.markIndirect(onodeid(c.result), "rVCall.result")
+}
+func (c *rVCallConstraint) renumber(mapping []nodeid) {
+	c.targets = mapping[c.targets]
+	c.v = mapping[c.v]
+	c.arg = mapping[c.arg]
+	c.result = mapping[c.result]
+}
+
+func (c *rVCallConstraint) String() string {
+	return fmt.Sprintf("n%d = reflect n%d.Call(n%d)", c.result, c.v, c.arg)
+}
+
+func (c *rVCallConstraint) solve(a *analysis, delta *nodeset) {
+	if c.targets == 0 {
+		panic("no targets")
+	}
+
+	changed := false
+	for _, x := range delta.AppendTo(a.deltaSpace) {
+		vObj := nodeid(x)
+		tDyn, fn, indirect := a.taggedValue(vObj)
+		if indirect {
+			// TODO(adonovan): we'll need to implement this
+			// when we start creating indirect tagged objects.
+			panic("indirect tagged object")
+		}
+
+		tSig, ok := tDyn.Underlying().(*types.Signature)
+		if !ok {
+			continue // not a function
+		}
+		if tSig.Recv() != nil {
+			panic(tSig) // TODO(adonovan): rethink when we implement Method()
+		}
+
+		// Add dynamic call target.
+		if a.onlineCopy(c.targets, fn) {
+			a.addWork(c.targets)
+			// TODO(adonovan): is 'else continue' a sound optimisation here?
+		}
+
+		// Allocate a P/R block.
+		tParams := tSig.Params()
+		tResults := tSig.Results()
+		params := a.addNodes(tParams, "rVCall.params")
+		results := a.addNodes(tResults, "rVCall.results")
+
+		// Make a dynamic call to 'fn'.
+		a.store(fn, params, 1, a.sizeof(tParams))
+		a.load(results, fn, 1+a.sizeof(tParams), a.sizeof(tResults))
+
+		// Populate P by type-asserting each actual arg (all merged in c.arg).
+		for i, n := 0, tParams.Len(); i < n; i++ {
+			T := tParams.At(i).Type()
+			a.typeAssert(T, params, c.arg, false)
+			params += nodeid(a.sizeof(T))
+		}
+
+		// Use R by tagging and copying each actual result to c.result.
+		for i, n := 0, tResults.Len(); i < n; i++ {
+			T := tResults.At(i).Type()
+			// Convert from an arbitrary type to a reflect.Value
+			// (like MakeInterface followed by reflect.ValueOf).
+			if isInterface(T) {
+				// (don't tag)
+				if a.onlineCopy(c.result, results) {
+					changed = true
+				}
+			} else {
+				obj := a.makeTagged(T, c.cgn, nil)
+				a.onlineCopyN(obj+1, results, a.sizeof(T))
+				if a.addLabel(c.result, obj) { // (true)
+					changed = true
+				}
+			}
+			results += nodeid(a.sizeof(T))
+		}
+	}
+	if changed {
+		a.addWork(c.result)
+	}
+}
+
+// Common code for direct (inlined) and indirect calls to (reflect.Value).Call.
+func reflectCallImpl(a *analysis, cgn *cgnode, site *callsite, recv, arg nodeid, dotdotdot bool) nodeid {
+	// Allocate []reflect.Value array for the result.
+	ret := a.nextNode()
+	a.addNodes(types.NewArray(a.reflectValueObj.Type(), 1), "rVCall.ret")
+	a.endObject(ret, cgn, nil)
+
+	// pts(targets) will be the set of possible call targets.
+	site.targets = a.addOneNode(tInvalid, "rvCall.targets", nil)
+
+	// All arguments are merged since they arrive in a slice.
+	argelts := a.addOneNode(a.reflectValueObj.Type(), "rVCall.args", nil)
+	a.load(argelts, arg, 1, 1) // slice elements
+
+	a.addConstraint(&rVCallConstraint{
+		cgn:       cgn,
+		targets:   site.targets,
+		v:         recv,
+		arg:       argelts,
+		result:    ret + 1, // results go into elements of ret
+		dotdotdot: dotdotdot,
+	})
+	return ret
+}
+
+func reflectCall(a *analysis, cgn *cgnode, dotdotdot bool) {
+	// This is the shared contour implementation of (reflect.Value).Call
+	// and CallSlice, as used by indirect calls (rare).
+	// Direct calls are inlined in gen.go, eliding the
+	// intermediate cgnode for Call.
+	site := new(callsite)
+	cgn.sites = append(cgn.sites, site)
+	recv := a.funcParams(cgn.obj)
+	arg := recv + 1
+	ret := reflectCallImpl(a, cgn, site, recv, arg, dotdotdot)
+	a.addressOf(cgn.fn.Signature.Results().At(0).Type(), a.funcResults(cgn.obj), ret)
+}
+
+func ext۰reflect۰Value۰Call(a *analysis, cgn *cgnode) {
+	reflectCall(a, cgn, false)
+}
+
+func ext۰reflect۰Value۰CallSlice(a *analysis, cgn *cgnode) {
+	// TODO(adonovan): implement.  Also, inline direct calls in gen.go too.
+	if false {
+		reflectCall(a, cgn, true)
+	}
+}
+
+func ext۰reflect۰Value۰Convert(a *analysis, cgn *cgnode) {} // TODO(adonovan)
+
+// ---------- func (Value).Elem() Value ----------
+
+// result = v.Elem()
+type rVElemConstraint struct {
+	cgn    *cgnode
+	v      nodeid // (ptr)
+	result nodeid // (indirect)
+}
+
+func (c *rVElemConstraint) ptr() nodeid { return c.v }
+func (c *rVElemConstraint) presolve(h *hvn) {
+	h.markIndirect(onodeid(c.result), "rVElem.result")
+}
+func (c *rVElemConstraint) renumber(mapping []nodeid) {
+	c.v = mapping[c.v]
+	c.result = mapping[c.result]
+}
+
+func (c *rVElemConstraint) String() string {
+	return fmt.Sprintf("n%d = reflect n%d.Elem()", c.result, c.v)
+}
+
+func (c *rVElemConstraint) solve(a *analysis, delta *nodeset) {
+	changed := false
+	for _, x := range delta.AppendTo(a.deltaSpace) {
+		vObj := nodeid(x)
+		tDyn, payload, indirect := a.taggedValue(vObj)
+		if indirect {
+			// TODO(adonovan): we'll need to implement this
+			// when we start creating indirect tagged objects.
+			panic("indirect tagged object")
+		}
+
+		switch t := tDyn.Underlying().(type) {
+		case *types.Interface:
+			if a.onlineCopy(c.result, payload) {
+				changed = true
+			}
+
+		case *types.Pointer:
+			obj := a.makeTagged(t.Elem(), c.cgn, nil)
+			a.load(obj+1, payload, 0, a.sizeof(t.Elem()))
+			if a.addLabel(c.result, obj) {
+				changed = true
+			}
+		}
+	}
+	if changed {
+		a.addWork(c.result)
+	}
+}
+
+func ext۰reflect۰Value۰Elem(a *analysis, cgn *cgnode) {
+	a.addConstraint(&rVElemConstraint{
+		cgn:    cgn,
+		v:      a.funcParams(cgn.obj),
+		result: a.funcResults(cgn.obj),
+	})
+}
+
+func ext۰reflect۰Value۰Field(a *analysis, cgn *cgnode)           {} // TODO(adonovan)
+func ext۰reflect۰Value۰FieldByIndex(a *analysis, cgn *cgnode)    {} // TODO(adonovan)
+func ext۰reflect۰Value۰FieldByName(a *analysis, cgn *cgnode)     {} // TODO(adonovan)
+func ext۰reflect۰Value۰FieldByNameFunc(a *analysis, cgn *cgnode) {} // TODO(adonovan)
+
+// ---------- func (Value).Index() Value ----------
+
+// result = v.Index()
+type rVIndexConstraint struct {
+	cgn    *cgnode
+	v      nodeid // (ptr)
+	result nodeid // (indirect)
+}
+
+func (c *rVIndexConstraint) ptr() nodeid { return c.v }
+func (c *rVIndexConstraint) presolve(h *hvn) {
+	h.markIndirect(onodeid(c.result), "rVIndex.result")
+}
+func (c *rVIndexConstraint) renumber(mapping []nodeid) {
+	c.v = mapping[c.v]
+	c.result = mapping[c.result]
+}
+
+func (c *rVIndexConstraint) String() string {
+	return fmt.Sprintf("n%d = reflect n%d.Index()", c.result, c.v)
+}
+
+func (c *rVIndexConstraint) solve(a *analysis, delta *nodeset) {
+	changed := false
+	for _, x := range delta.AppendTo(a.deltaSpace) {
+		vObj := nodeid(x)
+		tDyn, payload, indirect := a.taggedValue(vObj)
+		if indirect {
+			// TODO(adonovan): we'll need to implement this
+			// when we start creating indirect tagged objects.
+			panic("indirect tagged object")
+		}
+
+		var res nodeid
+		switch t := tDyn.Underlying().(type) {
+		case *types.Array:
+			res = a.makeTagged(t.Elem(), c.cgn, nil)
+			a.onlineCopyN(res+1, payload+1, a.sizeof(t.Elem()))
+
+		case *types.Slice:
+			res = a.makeTagged(t.Elem(), c.cgn, nil)
+			a.load(res+1, payload, 1, a.sizeof(t.Elem()))
+
+		case *types.Basic:
+			if t.Kind() == types.String {
+				res = a.makeTagged(types.Typ[types.Rune], c.cgn, nil)
+			}
+		}
+		if res != 0 && a.addLabel(c.result, res) {
+			changed = true
+		}
+	}
+	if changed {
+		a.addWork(c.result)
+	}
+}
+
+func ext۰reflect۰Value۰Index(a *analysis, cgn *cgnode) {
+	a.addConstraint(&rVIndexConstraint{
+		cgn:    cgn,
+		v:      a.funcParams(cgn.obj),
+		result: a.funcResults(cgn.obj),
+	})
+}
+
+// ---------- func (Value).Interface() Value ----------
+
+// result = v.Interface()
+type rVInterfaceConstraint struct {
+	v      nodeid // (ptr)
+	result nodeid // (indirect)
+}
+
+func (c *rVInterfaceConstraint) ptr() nodeid { return c.v }
+func (c *rVInterfaceConstraint) presolve(h *hvn) {
+	h.markIndirect(onodeid(c.result), "rVInterface.result")
+}
+func (c *rVInterfaceConstraint) renumber(mapping []nodeid) {
+	c.v = mapping[c.v]
+	c.result = mapping[c.result]
+}
+
+func (c *rVInterfaceConstraint) String() string {
+	return fmt.Sprintf("n%d = reflect n%d.Interface()", c.result, c.v)
+}
+
+func (c *rVInterfaceConstraint) solve(a *analysis, delta *nodeset) {
+	changed := false
+	for _, x := range delta.AppendTo(a.deltaSpace) {
+		vObj := nodeid(x)
+		tDyn, payload, indirect := a.taggedValue(vObj)
+		if indirect {
+			// TODO(adonovan): we'll need to implement this
+			// when we start creating indirect tagged objects.
+			panic("indirect tagged object")
+		}
+
+		if isInterface(tDyn) {
+			if a.onlineCopy(c.result, payload) {
+				a.addWork(c.result)
+			}
+		} else {
+			if a.addLabel(c.result, vObj) {
+				changed = true
+			}
+		}
+	}
+	if changed {
+		a.addWork(c.result)
+	}
+}
+
+func ext۰reflect۰Value۰Interface(a *analysis, cgn *cgnode) {
+	a.addConstraint(&rVInterfaceConstraint{
+		v:      a.funcParams(cgn.obj),
+		result: a.funcResults(cgn.obj),
+	})
+}
+
+// ---------- func (Value).MapIndex(Value) Value ----------
+
+// result = v.MapIndex(_)
+type rVMapIndexConstraint struct {
+	cgn    *cgnode
+	v      nodeid // (ptr)
+	result nodeid // (indirect)
+}
+
+func (c *rVMapIndexConstraint) ptr() nodeid { return c.v }
+func (c *rVMapIndexConstraint) presolve(h *hvn) {
+	h.markIndirect(onodeid(c.result), "rVMapIndex.result")
+}
+func (c *rVMapIndexConstraint) renumber(mapping []nodeid) {
+	c.v = mapping[c.v]
+	c.result = mapping[c.result]
+}
+
+func (c *rVMapIndexConstraint) String() string {
+	return fmt.Sprintf("n%d = reflect n%d.MapIndex(_)", c.result, c.v)
+}
+
+func (c *rVMapIndexConstraint) solve(a *analysis, delta *nodeset) {
+	changed := false
+	for _, x := range delta.AppendTo(a.deltaSpace) {
+		vObj := nodeid(x)
+		tDyn, m, indirect := a.taggedValue(vObj)
+		tMap, _ := tDyn.Underlying().(*types.Map)
+		if tMap == nil {
+			continue // not a map
+		}
+		if indirect {
+			// TODO(adonovan): we'll need to implement this
+			// when we start creating indirect tagged objects.
+			panic("indirect tagged object")
+		}
+
+		obj := a.makeTagged(tMap.Elem(), c.cgn, nil)
+		a.load(obj+1, m, a.sizeof(tMap.Key()), a.sizeof(tMap.Elem()))
+		if a.addLabel(c.result, obj) {
+			changed = true
+		}
+	}
+	if changed {
+		a.addWork(c.result)
+	}
+}
+
+func ext۰reflect۰Value۰MapIndex(a *analysis, cgn *cgnode) {
+	a.addConstraint(&rVMapIndexConstraint{
+		cgn:    cgn,
+		v:      a.funcParams(cgn.obj),
+		result: a.funcResults(cgn.obj),
+	})
+}
+
+// ---------- func (Value).MapKeys() []Value ----------
+
+// result = v.MapKeys()
+type rVMapKeysConstraint struct {
+	cgn    *cgnode
+	v      nodeid // (ptr)
+	result nodeid // (indirect)
+}
+
+func (c *rVMapKeysConstraint) ptr() nodeid { return c.v }
+func (c *rVMapKeysConstraint) presolve(h *hvn) {
+	h.markIndirect(onodeid(c.result), "rVMapKeys.result")
+}
+func (c *rVMapKeysConstraint) renumber(mapping []nodeid) {
+	c.v = mapping[c.v]
+	c.result = mapping[c.result]
+}
+
+func (c *rVMapKeysConstraint) String() string {
+	return fmt.Sprintf("n%d = reflect n%d.MapKeys()", c.result, c.v)
+}
+
+func (c *rVMapKeysConstraint) solve(a *analysis, delta *nodeset) {
+	changed := false
+	for _, x := range delta.AppendTo(a.deltaSpace) {
+		vObj := nodeid(x)
+		tDyn, m, indirect := a.taggedValue(vObj)
+		tMap, _ := tDyn.Underlying().(*types.Map)
+		if tMap == nil {
+			continue // not a map
+		}
+		if indirect {
+			// TODO(adonovan): we'll need to implement this
+			// when we start creating indirect tagged objects.
+			panic("indirect tagged object")
+		}
+
+		kObj := a.makeTagged(tMap.Key(), c.cgn, nil)
+		a.load(kObj+1, m, 0, a.sizeof(tMap.Key()))
+		if a.addLabel(c.result, kObj) {
+			changed = true
+		}
+	}
+	if changed {
+		a.addWork(c.result)
+	}
+}
+
+func ext۰reflect۰Value۰MapKeys(a *analysis, cgn *cgnode) {
+	// Allocate an array for the result.
+	obj := a.nextNode()
+	T := types.NewSlice(a.reflectValueObj.Type())
+	a.addNodes(sliceToArray(T), "reflect.MapKeys result")
+	a.endObject(obj, cgn, nil)
+	a.addressOf(T, a.funcResults(cgn.obj), obj)
+
+	a.addConstraint(&rVMapKeysConstraint{
+		cgn:    cgn,
+		v:      a.funcParams(cgn.obj),
+		result: obj + 1, // result is stored in array elems
+	})
+}
+
+func ext۰reflect۰Value۰Method(a *analysis, cgn *cgnode)       {} // TODO(adonovan)
+func ext۰reflect۰Value۰MethodByName(a *analysis, cgn *cgnode) {} // TODO(adonovan)
+
+// ---------- func (Value).Recv(Value) Value ----------
+
+// result, _ = v.Recv()
+type rVRecvConstraint struct {
+	cgn    *cgnode
+	v      nodeid // (ptr)
+	result nodeid // (indirect)
+}
+
+func (c *rVRecvConstraint) ptr() nodeid { return c.v }
+func (c *rVRecvConstraint) presolve(h *hvn) {
+	h.markIndirect(onodeid(c.result), "rVRecv.result")
+}
+func (c *rVRecvConstraint) renumber(mapping []nodeid) {
+	c.v = mapping[c.v]
+	c.result = mapping[c.result]
+}
+
+func (c *rVRecvConstraint) String() string {
+	return fmt.Sprintf("n%d = reflect n%d.Recv()", c.result, c.v)
+}
+
+func (c *rVRecvConstraint) solve(a *analysis, delta *nodeset) {
+	changed := false
+	for _, x := range delta.AppendTo(a.deltaSpace) {
+		vObj := nodeid(x)
+		tDyn, ch, indirect := a.taggedValue(vObj)
+		tChan, _ := tDyn.Underlying().(*types.Chan)
+		if tChan == nil {
+			continue // not a channel
+		}
+		if indirect {
+			// TODO(adonovan): we'll need to implement this
+			// when we start creating indirect tagged objects.
+			panic("indirect tagged object")
+		}
+
+		tElem := tChan.Elem()
+		elemObj := a.makeTagged(tElem, c.cgn, nil)
+		a.load(elemObj+1, ch, 0, a.sizeof(tElem))
+		if a.addLabel(c.result, elemObj) {
+			changed = true
+		}
+	}
+	if changed {
+		a.addWork(c.result)
+	}
+}
+
+func ext۰reflect۰Value۰Recv(a *analysis, cgn *cgnode) {
+	a.addConstraint(&rVRecvConstraint{
+		cgn:    cgn,
+		v:      a.funcParams(cgn.obj),
+		result: a.funcResults(cgn.obj),
+	})
+}
+
+// ---------- func (Value).Send(Value) ----------
+
+// v.Send(x)
+type rVSendConstraint struct {
+	cgn *cgnode
+	v   nodeid // (ptr)
+	x   nodeid
+}
+
+func (c *rVSendConstraint) ptr() nodeid   { return c.v }
+func (c *rVSendConstraint) presolve(*hvn) {}
+func (c *rVSendConstraint) renumber(mapping []nodeid) {
+	c.v = mapping[c.v]
+	c.x = mapping[c.x]
+}
+
+func (c *rVSendConstraint) String() string {
+	return fmt.Sprintf("reflect n%d.Send(n%d)", c.v, c.x)
+}
+
+func (c *rVSendConstraint) solve(a *analysis, delta *nodeset) {
+	for _, x := range delta.AppendTo(a.deltaSpace) {
+		vObj := nodeid(x)
+		tDyn, ch, indirect := a.taggedValue(vObj)
+		tChan, _ := tDyn.Underlying().(*types.Chan)
+		if tChan == nil {
+			continue // not a channel
+		}
+		if indirect {
+			// TODO(adonovan): we'll need to implement this
+			// when we start creating indirect tagged objects.
+			panic("indirect tagged object")
+		}
+
+		// Extract x's payload to xtmp, then store to channel.
+		tElem := tChan.Elem()
+		xtmp := a.addNodes(tElem, "Send.xtmp")
+		a.typeAssert(tElem, xtmp, c.x, false)
+		a.store(ch, xtmp, 0, a.sizeof(tElem))
+	}
+}
+
+func ext۰reflect۰Value۰Send(a *analysis, cgn *cgnode) {
+	params := a.funcParams(cgn.obj)
+	a.addConstraint(&rVSendConstraint{
+		cgn: cgn,
+		v:   params,
+		x:   params + 1,
+	})
+}
+
+func ext۰reflect۰Value۰Set(a *analysis, cgn *cgnode) {} // TODO(adonovan)
+
+// ---------- func (Value).SetBytes(x []byte) ----------
+
+// v.SetBytes(x)
+type rVSetBytesConstraint struct {
+	cgn *cgnode
+	v   nodeid // (ptr)
+	x   nodeid
+}
+
+func (c *rVSetBytesConstraint) ptr() nodeid   { return c.v }
+func (c *rVSetBytesConstraint) presolve(*hvn) {}
+func (c *rVSetBytesConstraint) renumber(mapping []nodeid) {
+	c.v = mapping[c.v]
+	c.x = mapping[c.x]
+}
+
+func (c *rVSetBytesConstraint) String() string {
+	return fmt.Sprintf("reflect n%d.SetBytes(n%d)", c.v, c.x)
+}
+
+func (c *rVSetBytesConstraint) solve(a *analysis, delta *nodeset) {
+	for _, x := range delta.AppendTo(a.deltaSpace) {
+		vObj := nodeid(x)
+		tDyn, slice, indirect := a.taggedValue(vObj)
+		if indirect {
+			// TODO(adonovan): we'll need to implement this
+			// when we start creating indirect tagged objects.
+			panic("indirect tagged object")
+		}
+
+		tSlice, ok := tDyn.Underlying().(*types.Slice)
+		if ok && types.Identical(tSlice.Elem(), types.Typ[types.Uint8]) {
+			if a.onlineCopy(slice, c.x) {
+				a.addWork(slice)
+			}
+		}
+	}
+}
+
+func ext۰reflect۰Value۰SetBytes(a *analysis, cgn *cgnode) {
+	params := a.funcParams(cgn.obj)
+	a.addConstraint(&rVSetBytesConstraint{
+		cgn: cgn,
+		v:   params,
+		x:   params + 1,
+	})
+}
+
+// ---------- func (Value).SetMapIndex(k Value, v Value) ----------
+
+// v.SetMapIndex(key, val)
+type rVSetMapIndexConstraint struct {
+	cgn *cgnode
+	v   nodeid // (ptr)
+	key nodeid
+	val nodeid
+}
+
+func (c *rVSetMapIndexConstraint) ptr() nodeid   { return c.v }
+func (c *rVSetMapIndexConstraint) presolve(*hvn) {}
+func (c *rVSetMapIndexConstraint) renumber(mapping []nodeid) {
+	c.v = mapping[c.v]
+	c.key = mapping[c.key]
+	c.val = mapping[c.val]
+}
+
+func (c *rVSetMapIndexConstraint) String() string {
+	return fmt.Sprintf("reflect n%d.SetMapIndex(n%d, n%d)", c.v, c.key, c.val)
+}
+
+func (c *rVSetMapIndexConstraint) solve(a *analysis, delta *nodeset) {
+	for _, x := range delta.AppendTo(a.deltaSpace) {
+		vObj := nodeid(x)
+		tDyn, m, indirect := a.taggedValue(vObj)
+		tMap, _ := tDyn.Underlying().(*types.Map)
+		if tMap == nil {
+			continue // not a map
+		}
+		if indirect {
+			// TODO(adonovan): we'll need to implement this
+			// when we start creating indirect tagged objects.
+			panic("indirect tagged object")
+		}
+
+		keysize := a.sizeof(tMap.Key())
+
+		// Extract key's payload to keytmp, then store to map key.
+		keytmp := a.addNodes(tMap.Key(), "SetMapIndex.keytmp")
+		a.typeAssert(tMap.Key(), keytmp, c.key, false)
+		a.store(m, keytmp, 0, keysize)
+
+		// Extract val's payload to vtmp, then store to map value.
+		valtmp := a.addNodes(tMap.Elem(), "SetMapIndex.valtmp")
+		a.typeAssert(tMap.Elem(), valtmp, c.val, false)
+		a.store(m, valtmp, keysize, a.sizeof(tMap.Elem()))
+	}
+}
+
+func ext۰reflect۰Value۰SetMapIndex(a *analysis, cgn *cgnode) {
+	params := a.funcParams(cgn.obj)
+	a.addConstraint(&rVSetMapIndexConstraint{
+		cgn: cgn,
+		v:   params,
+		key: params + 1,
+		val: params + 2,
+	})
+}
+
+func ext۰reflect۰Value۰SetPointer(a *analysis, cgn *cgnode) {} // TODO(adonovan)
+
+// ---------- func (Value).Slice(v Value, i, j int) Value ----------
+
+// result = v.Slice(_, _)
+type rVSliceConstraint struct {
+	cgn    *cgnode
+	v      nodeid // (ptr)
+	result nodeid // (indirect)
+}
+
+func (c *rVSliceConstraint) ptr() nodeid { return c.v }
+func (c *rVSliceConstraint) presolve(h *hvn) {
+	h.markIndirect(onodeid(c.result), "rVSlice.result")
+}
+func (c *rVSliceConstraint) renumber(mapping []nodeid) {
+	c.v = mapping[c.v]
+	c.result = mapping[c.result]
+}
+
+func (c *rVSliceConstraint) String() string {
+	return fmt.Sprintf("n%d = reflect n%d.Slice(_, _)", c.result, c.v)
+}
+
+func (c *rVSliceConstraint) solve(a *analysis, delta *nodeset) {
+	changed := false
+	for _, x := range delta.AppendTo(a.deltaSpace) {
+		vObj := nodeid(x)
+		tDyn, payload, indirect := a.taggedValue(vObj)
+		if indirect {
+			// TODO(adonovan): we'll need to implement this
+			// when we start creating indirect tagged objects.
+			panic("indirect tagged object")
+		}
+
+		var res nodeid
+		switch t := tDyn.Underlying().(type) {
+		case *types.Pointer:
+			if tArr, ok := t.Elem().Underlying().(*types.Array); ok {
+				// pointer to array
+				res = a.makeTagged(types.NewSlice(tArr.Elem()), c.cgn, nil)
+				if a.onlineCopy(res+1, payload) {
+					a.addWork(res + 1)
+				}
+			}
+
+		case *types.Array:
+			// TODO(adonovan): implement addressable
+			// arrays when we do indirect tagged objects.
+
+		case *types.Slice:
+			res = vObj
+
+		case *types.Basic:
+			if t == types.Typ[types.String] {
+				res = vObj
+			}
+		}
+
+		if res != 0 && a.addLabel(c.result, res) {
+			changed = true
+		}
+	}
+	if changed {
+		a.addWork(c.result)
+	}
+}
+
+func ext۰reflect۰Value۰Slice(a *analysis, cgn *cgnode) {
+	a.addConstraint(&rVSliceConstraint{
+		cgn:    cgn,
+		v:      a.funcParams(cgn.obj),
+		result: a.funcResults(cgn.obj),
+	})
+}
+
+// -------------------- Standalone reflect functions --------------------
+
+func ext۰reflect۰Append(a *analysis, cgn *cgnode)      {} // TODO(adonovan)
+func ext۰reflect۰AppendSlice(a *analysis, cgn *cgnode) {} // TODO(adonovan)
+func ext۰reflect۰Copy(a *analysis, cgn *cgnode)        {} // TODO(adonovan)
+
+// ---------- func ChanOf(ChanDir, Type) Type ----------
+
+// result = ChanOf(dir, t)
+type reflectChanOfConstraint struct {
+	cgn    *cgnode
+	t      nodeid // (ptr)
+	result nodeid // (indirect)
+	dirs   []types.ChanDir
+}
+
+func (c *reflectChanOfConstraint) ptr() nodeid { return c.t }
+func (c *reflectChanOfConstraint) presolve(h *hvn) {
+	h.markIndirect(onodeid(c.result), "reflectChanOf.result")
+}
+func (c *reflectChanOfConstraint) renumber(mapping []nodeid) {
+	c.t = mapping[c.t]
+	c.result = mapping[c.result]
+}
+
+func (c *reflectChanOfConstraint) String() string {
+	return fmt.Sprintf("n%d = reflect.ChanOf(n%d)", c.result, c.t)
+}
+
+func (c *reflectChanOfConstraint) solve(a *analysis, delta *nodeset) {
+	changed := false
+	for _, x := range delta.AppendTo(a.deltaSpace) {
+		tObj := nodeid(x)
+		T := a.rtypeTaggedValue(tObj)
+
+		if typeTooHigh(T) {
+			continue
+		}
+
+		for _, dir := range c.dirs {
+			if a.addLabel(c.result, a.makeRtype(types.NewChan(dir, T))) {
+				changed = true
+			}
+		}
+	}
+	if changed {
+		a.addWork(c.result)
+	}
+}
+
+// dirMap maps reflect.ChanDir to the set of channel types generated by ChanOf.
+var dirMap = [...][]types.ChanDir{
+	0:               {types.SendOnly, types.RecvOnly, types.SendRecv}, // unknown
+	reflect.RecvDir: {types.RecvOnly},
+	reflect.SendDir: {types.SendOnly},
+	reflect.BothDir: {types.SendRecv},
+}
+
+func ext۰reflect۰ChanOf(a *analysis, cgn *cgnode) {
+	// If we have access to the callsite,
+	// and the channel argument is a constant (as is usual),
+	// only generate the requested direction.
+	var dir reflect.ChanDir // unknown
+	if site := cgn.callersite; site != nil {
+		if c, ok := site.instr.Common().Args[0].(*ssa.Const); ok {
+			v, _ := exact.Int64Val(c.Value)
+			if 0 <= v && v <= int64(reflect.BothDir) {
+				dir = reflect.ChanDir(v)
+			}
+		}
+	}
+
+	params := a.funcParams(cgn.obj)
+	a.addConstraint(&reflectChanOfConstraint{
+		cgn:    cgn,
+		t:      params + 1,
+		result: a.funcResults(cgn.obj),
+		dirs:   dirMap[dir],
+	})
+}
+
+// ---------- func Indirect(v Value) Value ----------
+
+// result = Indirect(v)
+type reflectIndirectConstraint struct {
+	cgn    *cgnode
+	v      nodeid // (ptr)
+	result nodeid // (indirect)
+}
+
+func (c *reflectIndirectConstraint) ptr() nodeid { return c.v }
+func (c *reflectIndirectConstraint) presolve(h *hvn) {
+	h.markIndirect(onodeid(c.result), "reflectIndirect.result")
+}
+func (c *reflectIndirectConstraint) renumber(mapping []nodeid) {
+	c.v = mapping[c.v]
+	c.result = mapping[c.result]
+}
+
+func (c *reflectIndirectConstraint) String() string {
+	return fmt.Sprintf("n%d = reflect.Indirect(n%d)", c.result, c.v)
+}
+
+func (c *reflectIndirectConstraint) solve(a *analysis, delta *nodeset) {
+	changed := false
+	for _, x := range delta.AppendTo(a.deltaSpace) {
+		vObj := nodeid(x)
+		tDyn, _, _ := a.taggedValue(vObj)
+		var res nodeid
+		if tPtr, ok := tDyn.Underlying().(*types.Pointer); ok {
+			// load the payload of the pointer's tagged object
+			// into a new tagged object
+			res = a.makeTagged(tPtr.Elem(), c.cgn, nil)
+			a.load(res+1, vObj+1, 0, a.sizeof(tPtr.Elem()))
+		} else {
+			res = vObj
+		}
+
+		if a.addLabel(c.result, res) {
+			changed = true
+		}
+	}
+	if changed {
+		a.addWork(c.result)
+	}
+}
+
+func ext۰reflect۰Indirect(a *analysis, cgn *cgnode) {
+	a.addConstraint(&reflectIndirectConstraint{
+		cgn:    cgn,
+		v:      a.funcParams(cgn.obj),
+		result: a.funcResults(cgn.obj),
+	})
+}
+
+// ---------- func MakeChan(Type) Value ----------
+
+// result = MakeChan(typ)
+type reflectMakeChanConstraint struct {
+	cgn    *cgnode
+	typ    nodeid // (ptr)
+	result nodeid // (indirect)
+}
+
+func (c *reflectMakeChanConstraint) ptr() nodeid { return c.typ }
+func (c *reflectMakeChanConstraint) presolve(h *hvn) {
+	h.markIndirect(onodeid(c.result), "reflectMakeChan.result")
+}
+func (c *reflectMakeChanConstraint) renumber(mapping []nodeid) {
+	c.typ = mapping[c.typ]
+	c.result = mapping[c.result]
+}
+
+func (c *reflectMakeChanConstraint) String() string {
+	return fmt.Sprintf("n%d = reflect.MakeChan(n%d)", c.result, c.typ)
+}
+
+func (c *reflectMakeChanConstraint) solve(a *analysis, delta *nodeset) {
+	changed := false
+	for _, x := range delta.AppendTo(a.deltaSpace) {
+		typObj := nodeid(x)
+		T := a.rtypeTaggedValue(typObj)
+		tChan, ok := T.Underlying().(*types.Chan)
+		if !ok || tChan.Dir() != types.SendRecv {
+			continue // not a bidirectional channel type
+		}
+
+		obj := a.nextNode()
+		a.addNodes(tChan.Elem(), "reflect.MakeChan.value")
+		a.endObject(obj, c.cgn, nil)
+
+		// put its address in a new T-tagged object
+		id := a.makeTagged(T, c.cgn, nil)
+		a.addLabel(id+1, obj)
+
+		// flow the T-tagged object to the result
+		if a.addLabel(c.result, id) {
+			changed = true
+		}
+	}
+	if changed {
+		a.addWork(c.result)
+	}
+}
+
+func ext۰reflect۰MakeChan(a *analysis, cgn *cgnode) {
+	a.addConstraint(&reflectMakeChanConstraint{
+		cgn:    cgn,
+		typ:    a.funcParams(cgn.obj),
+		result: a.funcResults(cgn.obj),
+	})
+}
+
+func ext۰reflect۰MakeFunc(a *analysis, cgn *cgnode) {} // TODO(adonovan)
+
+// ---------- func MakeMap(Type) Value ----------
+
+// result = MakeMap(typ)
+type reflectMakeMapConstraint struct {
+	cgn    *cgnode
+	typ    nodeid // (ptr)
+	result nodeid // (indirect)
+}
+
+func (c *reflectMakeMapConstraint) ptr() nodeid { return c.typ }
+func (c *reflectMakeMapConstraint) presolve(h *hvn) {
+	h.markIndirect(onodeid(c.result), "reflectMakeMap.result")
+}
+func (c *reflectMakeMapConstraint) renumber(mapping []nodeid) {
+	c.typ = mapping[c.typ]
+	c.result = mapping[c.result]
+}
+
+func (c *reflectMakeMapConstraint) String() string {
+	return fmt.Sprintf("n%d = reflect.MakeMap(n%d)", c.result, c.typ)
+}
+
+func (c *reflectMakeMapConstraint) solve(a *analysis, delta *nodeset) {
+	changed := false
+	for _, x := range delta.AppendTo(a.deltaSpace) {
+		typObj := nodeid(x)
+		T := a.rtypeTaggedValue(typObj)
+		tMap, ok := T.Underlying().(*types.Map)
+		if !ok {
+			continue // not a map type
+		}
+
+		mapObj := a.nextNode()
+		a.addNodes(tMap.Key(), "reflect.MakeMap.key")
+		a.addNodes(tMap.Elem(), "reflect.MakeMap.value")
+		a.endObject(mapObj, c.cgn, nil)
+
+		// put its address in a new T-tagged object
+		id := a.makeTagged(T, c.cgn, nil)
+		a.addLabel(id+1, mapObj)
+
+		// flow the T-tagged object to the result
+		if a.addLabel(c.result, id) {
+			changed = true
+		}
+	}
+	if changed {
+		a.addWork(c.result)
+	}
+}
+
+func ext۰reflect۰MakeMap(a *analysis, cgn *cgnode) {
+	a.addConstraint(&reflectMakeMapConstraint{
+		cgn:    cgn,
+		typ:    a.funcParams(cgn.obj),
+		result: a.funcResults(cgn.obj),
+	})
+}
+
+// ---------- func MakeSlice(Type) Value ----------
+
+// result = MakeSlice(typ)
+type reflectMakeSliceConstraint struct {
+	cgn    *cgnode
+	typ    nodeid // (ptr)
+	result nodeid // (indirect)
+}
+
+func (c *reflectMakeSliceConstraint) ptr() nodeid { return c.typ }
+func (c *reflectMakeSliceConstraint) presolve(h *hvn) {
+	h.markIndirect(onodeid(c.result), "reflectMakeSlice.result")
+}
+func (c *reflectMakeSliceConstraint) renumber(mapping []nodeid) {
+	c.typ = mapping[c.typ]
+	c.result = mapping[c.result]
+}
+
+func (c *reflectMakeSliceConstraint) String() string {
+	return fmt.Sprintf("n%d = reflect.MakeSlice(n%d)", c.result, c.typ)
+}
+
+func (c *reflectMakeSliceConstraint) solve(a *analysis, delta *nodeset) {
+	changed := false
+	for _, x := range delta.AppendTo(a.deltaSpace) {
+		typObj := nodeid(x)
+		T := a.rtypeTaggedValue(typObj)
+		if _, ok := T.Underlying().(*types.Slice); !ok {
+			continue // not a slice type
+		}
+
+		obj := a.nextNode()
+		a.addNodes(sliceToArray(T), "reflect.MakeSlice")
+		a.endObject(obj, c.cgn, nil)
+
+		// put its address in a new T-tagged object
+		id := a.makeTagged(T, c.cgn, nil)
+		a.addLabel(id+1, obj)
+
+		// flow the T-tagged object to the result
+		if a.addLabel(c.result, id) {
+			changed = true
+		}
+	}
+	if changed {
+		a.addWork(c.result)
+	}
+}
+
+func ext۰reflect۰MakeSlice(a *analysis, cgn *cgnode) {
+	a.addConstraint(&reflectMakeSliceConstraint{
+		cgn:    cgn,
+		typ:    a.funcParams(cgn.obj),
+		result: a.funcResults(cgn.obj),
+	})
+}
+
+func ext۰reflect۰MapOf(a *analysis, cgn *cgnode) {} // TODO(adonovan)
+
+// ---------- func New(Type) Value ----------
+
+// result = New(typ)
+type reflectNewConstraint struct {
+	cgn    *cgnode
+	typ    nodeid // (ptr)
+	result nodeid // (indirect)
+}
+
+func (c *reflectNewConstraint) ptr() nodeid { return c.typ }
+func (c *reflectNewConstraint) presolve(h *hvn) {
+	h.markIndirect(onodeid(c.result), "reflectNew.result")
+}
+func (c *reflectNewConstraint) renumber(mapping []nodeid) {
+	c.typ = mapping[c.typ]
+	c.result = mapping[c.result]
+}
+
+func (c *reflectNewConstraint) String() string {
+	return fmt.Sprintf("n%d = reflect.New(n%d)", c.result, c.typ)
+}
+
+func (c *reflectNewConstraint) solve(a *analysis, delta *nodeset) {
+	changed := false
+	for _, x := range delta.AppendTo(a.deltaSpace) {
+		typObj := nodeid(x)
+		T := a.rtypeTaggedValue(typObj)
+
+		// allocate new T object
+		newObj := a.nextNode()
+		a.addNodes(T, "reflect.New")
+		a.endObject(newObj, c.cgn, nil)
+
+		// put its address in a new *T-tagged object
+		id := a.makeTagged(types.NewPointer(T), c.cgn, nil)
+		a.addLabel(id+1, newObj)
+
+		// flow the pointer to the result
+		if a.addLabel(c.result, id) {
+			changed = true
+		}
+	}
+	if changed {
+		a.addWork(c.result)
+	}
+}
+
+func ext۰reflect۰New(a *analysis, cgn *cgnode) {
+	a.addConstraint(&reflectNewConstraint{
+		cgn:    cgn,
+		typ:    a.funcParams(cgn.obj),
+		result: a.funcResults(cgn.obj),
+	})
+}
+
+func ext۰reflect۰NewAt(a *analysis, cgn *cgnode) {
+	ext۰reflect۰New(a, cgn)
+
+	// TODO(adonovan): also report dynamic calls to unsound intrinsics.
+	if site := cgn.callersite; site != nil {
+		a.warnf(site.pos(), "unsound: %s contains a reflect.NewAt() call", site.instr.Parent())
+	}
+}
+
+// ---------- func PtrTo(Type) Type ----------
+
+// result = PtrTo(t)
+type reflectPtrToConstraint struct {
+	cgn    *cgnode
+	t      nodeid // (ptr)
+	result nodeid // (indirect)
+}
+
+func (c *reflectPtrToConstraint) ptr() nodeid { return c.t }
+func (c *reflectPtrToConstraint) presolve(h *hvn) {
+	h.markIndirect(onodeid(c.result), "reflectPtrTo.result")
+}
+func (c *reflectPtrToConstraint) renumber(mapping []nodeid) {
+	c.t = mapping[c.t]
+	c.result = mapping[c.result]
+}
+
+func (c *reflectPtrToConstraint) String() string {
+	return fmt.Sprintf("n%d = reflect.PtrTo(n%d)", c.result, c.t)
+}
+
+func (c *reflectPtrToConstraint) solve(a *analysis, delta *nodeset) {
+	changed := false
+	for _, x := range delta.AppendTo(a.deltaSpace) {
+		tObj := nodeid(x)
+		T := a.rtypeTaggedValue(tObj)
+
+		if typeTooHigh(T) {
+			continue
+		}
+
+		if a.addLabel(c.result, a.makeRtype(types.NewPointer(T))) {
+			changed = true
+		}
+	}
+	if changed {
+		a.addWork(c.result)
+	}
+}
+
+func ext۰reflect۰PtrTo(a *analysis, cgn *cgnode) {
+	a.addConstraint(&reflectPtrToConstraint{
+		cgn:    cgn,
+		t:      a.funcParams(cgn.obj),
+		result: a.funcResults(cgn.obj),
+	})
+}
+
+func ext۰reflect۰Select(a *analysis, cgn *cgnode) {} // TODO(adonovan)
+
+// ---------- func SliceOf(Type) Type ----------
+
+// result = SliceOf(t)
+type reflectSliceOfConstraint struct {
+	cgn    *cgnode
+	t      nodeid // (ptr)
+	result nodeid // (indirect)
+}
+
+func (c *reflectSliceOfConstraint) ptr() nodeid { return c.t }
+func (c *reflectSliceOfConstraint) presolve(h *hvn) {
+	h.markIndirect(onodeid(c.result), "reflectSliceOf.result")
+}
+func (c *reflectSliceOfConstraint) renumber(mapping []nodeid) {
+	c.t = mapping[c.t]
+	c.result = mapping[c.result]
+}
+
+func (c *reflectSliceOfConstraint) String() string {
+	return fmt.Sprintf("n%d = reflect.SliceOf(n%d)", c.result, c.t)
+}
+
+func (c *reflectSliceOfConstraint) solve(a *analysis, delta *nodeset) {
+	changed := false
+	for _, x := range delta.AppendTo(a.deltaSpace) {
+		tObj := nodeid(x)
+		T := a.rtypeTaggedValue(tObj)
+
+		if typeTooHigh(T) {
+			continue
+		}
+
+		if a.addLabel(c.result, a.makeRtype(types.NewSlice(T))) {
+			changed = true
+		}
+	}
+	if changed {
+		a.addWork(c.result)
+	}
+}
+
+func ext۰reflect۰SliceOf(a *analysis, cgn *cgnode) {
+	a.addConstraint(&reflectSliceOfConstraint{
+		cgn:    cgn,
+		t:      a.funcParams(cgn.obj),
+		result: a.funcResults(cgn.obj),
+	})
+}
+
+// ---------- func TypeOf(v Value) Type ----------
+
+// result = TypeOf(i)
+type reflectTypeOfConstraint struct {
+	cgn    *cgnode
+	i      nodeid // (ptr)
+	result nodeid // (indirect)
+}
+
+func (c *reflectTypeOfConstraint) ptr() nodeid { return c.i }
+func (c *reflectTypeOfConstraint) presolve(h *hvn) {
+	h.markIndirect(onodeid(c.result), "reflectTypeOf.result")
+}
+func (c *reflectTypeOfConstraint) renumber(mapping []nodeid) {
+	c.i = mapping[c.i]
+	c.result = mapping[c.result]
+}
+
+func (c *reflectTypeOfConstraint) String() string {
+	return fmt.Sprintf("n%d = reflect.TypeOf(n%d)", c.result, c.i)
+}
+
+func (c *reflectTypeOfConstraint) solve(a *analysis, delta *nodeset) {
+	changed := false
+	for _, x := range delta.AppendTo(a.deltaSpace) {
+		iObj := nodeid(x)
+		tDyn, _, _ := a.taggedValue(iObj)
+		if a.addLabel(c.result, a.makeRtype(tDyn)) {
+			changed = true
+		}
+	}
+	if changed {
+		a.addWork(c.result)
+	}
+}
+
+func ext۰reflect۰TypeOf(a *analysis, cgn *cgnode) {
+	a.addConstraint(&reflectTypeOfConstraint{
+		cgn:    cgn,
+		i:      a.funcParams(cgn.obj),
+		result: a.funcResults(cgn.obj),
+	})
+}
+
+// ---------- func ValueOf(interface{}) Value ----------
+
+func ext۰reflect۰ValueOf(a *analysis, cgn *cgnode) {
+	// TODO(adonovan): when we start creating indirect tagged
+	// objects, we'll need to handle them specially here since
+	// they must never appear in the PTS of an interface{}.
+	a.copy(a.funcResults(cgn.obj), a.funcParams(cgn.obj), 1)
+}
+
+// ---------- func Zero(Type) Value ----------
+
+// result = Zero(typ)
+type reflectZeroConstraint struct {
+	cgn    *cgnode
+	typ    nodeid // (ptr)
+	result nodeid // (indirect)
+}
+
+func (c *reflectZeroConstraint) ptr() nodeid { return c.typ }
+func (c *reflectZeroConstraint) presolve(h *hvn) {
+	h.markIndirect(onodeid(c.result), "reflectZero.result")
+}
+func (c *reflectZeroConstraint) renumber(mapping []nodeid) {
+	c.typ = mapping[c.typ]
+	c.result = mapping[c.result]
+}
+
+func (c *reflectZeroConstraint) String() string {
+	return fmt.Sprintf("n%d = reflect.Zero(n%d)", c.result, c.typ)
+}
+
+func (c *reflectZeroConstraint) solve(a *analysis, delta *nodeset) {
+	changed := false
+	for _, x := range delta.AppendTo(a.deltaSpace) {
+		typObj := nodeid(x)
+		T := a.rtypeTaggedValue(typObj)
+
+		// TODO(adonovan): if T is an interface type, we need
+		// to create an indirect tagged object containing
+		// new(T).  To avoid updates of such shared values,
+		// we'll need another flag on indirect tagged objects
+		// that marks whether they are addressable or
+		// readonly, just like the reflect package does.
+
+		// memoize using a.reflectZeros[T]
+		var id nodeid
+		if z := a.reflectZeros.At(T); false && z != nil {
+			id = z.(nodeid)
+		} else {
+			id = a.makeTagged(T, c.cgn, nil)
+			a.reflectZeros.Set(T, id)
+		}
+		if a.addLabel(c.result, id) {
+			changed = true
+		}
+	}
+	if changed {
+		a.addWork(c.result)
+	}
+}
+
+func ext۰reflect۰Zero(a *analysis, cgn *cgnode) {
+	a.addConstraint(&reflectZeroConstraint{
+		cgn:    cgn,
+		typ:    a.funcParams(cgn.obj),
+		result: a.funcResults(cgn.obj),
+	})
+}
+
+// -------------------- (*reflect.rtype) methods --------------------
+
+// ---------- func (*rtype) Elem() Type ----------
+
+// result = Elem(t)
+type rtypeElemConstraint struct {
+	cgn    *cgnode
+	t      nodeid // (ptr)
+	result nodeid // (indirect)
+}
+
+func (c *rtypeElemConstraint) ptr() nodeid { return c.t }
+func (c *rtypeElemConstraint) presolve(h *hvn) {
+	h.markIndirect(onodeid(c.result), "rtypeElem.result")
+}
+func (c *rtypeElemConstraint) renumber(mapping []nodeid) {
+	c.t = mapping[c.t]
+	c.result = mapping[c.result]
+}
+
+func (c *rtypeElemConstraint) String() string {
+	return fmt.Sprintf("n%d = (*reflect.rtype).Elem(n%d)", c.result, c.t)
+}
+
+func (c *rtypeElemConstraint) solve(a *analysis, delta *nodeset) {
+	// Implemented by *types.{Map,Chan,Array,Slice,Pointer}.
+	type hasElem interface {
+		Elem() types.Type
+	}
+	changed := false
+	for _, x := range delta.AppendTo(a.deltaSpace) {
+		tObj := nodeid(x)
+		T := a.nodes[tObj].obj.data.(types.Type)
+		if tHasElem, ok := T.Underlying().(hasElem); ok {
+			if a.addLabel(c.result, a.makeRtype(tHasElem.Elem())) {
+				changed = true
+			}
+		}
+	}
+	if changed {
+		a.addWork(c.result)
+	}
+}
+
+func ext۰reflect۰rtype۰Elem(a *analysis, cgn *cgnode) {
+	a.addConstraint(&rtypeElemConstraint{
+		cgn:    cgn,
+		t:      a.funcParams(cgn.obj),
+		result: a.funcResults(cgn.obj),
+	})
+}
+
+// ---------- func (*rtype) Field(int) StructField ----------
+// ---------- func (*rtype) FieldByName(string) (StructField, bool) ----------
+
+// result = FieldByName(t, name)
+// result = Field(t, _)
+type rtypeFieldByNameConstraint struct {
+	cgn    *cgnode
+	name   string // name of field; "" for unknown
+	t      nodeid // (ptr)
+	result nodeid // (indirect)
+}
+
+func (c *rtypeFieldByNameConstraint) ptr() nodeid { return c.t }
+func (c *rtypeFieldByNameConstraint) presolve(h *hvn) {
+	h.markIndirect(onodeid(c.result+3), "rtypeFieldByName.result.Type")
+}
+func (c *rtypeFieldByNameConstraint) renumber(mapping []nodeid) {
+	c.t = mapping[c.t]
+	c.result = mapping[c.result]
+}
+
+func (c *rtypeFieldByNameConstraint) String() string {
+	return fmt.Sprintf("n%d = (*reflect.rtype).FieldByName(n%d, %q)", c.result, c.t, c.name)
+}
+
+func (c *rtypeFieldByNameConstraint) solve(a *analysis, delta *nodeset) {
+	// type StructField struct {
+	// 0	__identity__
+	// 1	Name      string
+	// 2	PkgPath   string
+	// 3	Type      Type
+	// 4	Tag       StructTag
+	// 5	Offset    uintptr
+	// 6	Index     []int
+	// 7	Anonymous bool
+	// }
+
+	for _, x := range delta.AppendTo(a.deltaSpace) {
+		tObj := nodeid(x)
+		T := a.nodes[tObj].obj.data.(types.Type)
+		tStruct, ok := T.Underlying().(*types.Struct)
+		if !ok {
+			continue // not a struct type
+		}
+
+		n := tStruct.NumFields()
+		for i := 0; i < n; i++ {
+			f := tStruct.Field(i)
+			if c.name == "" || c.name == f.Name() {
+
+				// a.offsetOf(Type) is 3.
+				if id := c.result + 3; a.addLabel(id, a.makeRtype(f.Type())) {
+					a.addWork(id)
+				}
+				// TODO(adonovan): StructField.Index should be non-nil.
+			}
+		}
+	}
+}
+
+func ext۰reflect۰rtype۰FieldByName(a *analysis, cgn *cgnode) {
+	// If we have access to the callsite,
+	// and the argument is a string constant,
+	// return only that field.
+	var name string
+	if site := cgn.callersite; site != nil {
+		if c, ok := site.instr.Common().Args[0].(*ssa.Const); ok {
+			name = exact.StringVal(c.Value)
+		}
+	}
+
+	a.addConstraint(&rtypeFieldByNameConstraint{
+		cgn:    cgn,
+		name:   name,
+		t:      a.funcParams(cgn.obj),
+		result: a.funcResults(cgn.obj),
+	})
+}
+
+func ext۰reflect۰rtype۰Field(a *analysis, cgn *cgnode) {
+	// No-one ever calls Field with a constant argument,
+	// so we don't specialize that case.
+	a.addConstraint(&rtypeFieldByNameConstraint{
+		cgn:    cgn,
+		t:      a.funcParams(cgn.obj),
+		result: a.funcResults(cgn.obj),
+	})
+}
+
+func ext۰reflect۰rtype۰FieldByIndex(a *analysis, cgn *cgnode)    {} // TODO(adonovan)
+func ext۰reflect۰rtype۰FieldByNameFunc(a *analysis, cgn *cgnode) {} // TODO(adonovan)
+
+// ---------- func (*rtype) In/Out(i int) Type ----------
+
+// result = In/Out(t, i)
+type rtypeInOutConstraint struct {
+	cgn    *cgnode
+	t      nodeid // (ptr)
+	result nodeid // (indirect)
+	out    bool
+	i      int // -ve if not a constant
+}
+
+func (c *rtypeInOutConstraint) ptr() nodeid { return c.t }
+func (c *rtypeInOutConstraint) presolve(h *hvn) {
+	h.markIndirect(onodeid(c.result), "rtypeInOut.result")
+}
+func (c *rtypeInOutConstraint) renumber(mapping []nodeid) {
+	c.t = mapping[c.t]
+	c.result = mapping[c.result]
+}
+
+func (c *rtypeInOutConstraint) String() string {
+	return fmt.Sprintf("n%d = (*reflect.rtype).InOut(n%d, %d)", c.result, c.t, c.i)
+}
+
+func (c *rtypeInOutConstraint) solve(a *analysis, delta *nodeset) {
+	changed := false
+	for _, x := range delta.AppendTo(a.deltaSpace) {
+		tObj := nodeid(x)
+		T := a.nodes[tObj].obj.data.(types.Type)
+		sig, ok := T.Underlying().(*types.Signature)
+		if !ok {
+			continue // not a func type
+		}
+
+		tuple := sig.Params()
+		if c.out {
+			tuple = sig.Results()
+		}
+		for i, n := 0, tuple.Len(); i < n; i++ {
+			if c.i < 0 || c.i == i {
+				if a.addLabel(c.result, a.makeRtype(tuple.At(i).Type())) {
+					changed = true
+				}
+			}
+		}
+	}
+	if changed {
+		a.addWork(c.result)
+	}
+}
+
+func ext۰reflect۰rtype۰InOut(a *analysis, cgn *cgnode, out bool) {
+	// If we have access to the callsite,
+	// and the argument is an int constant,
+	// return only that parameter.
+	index := -1
+	if site := cgn.callersite; site != nil {
+		if c, ok := site.instr.Common().Args[0].(*ssa.Const); ok {
+			v, _ := exact.Int64Val(c.Value)
+			index = int(v)
+		}
+	}
+	a.addConstraint(&rtypeInOutConstraint{
+		cgn:    cgn,
+		t:      a.funcParams(cgn.obj),
+		result: a.funcResults(cgn.obj),
+		out:    out,
+		i:      index,
+	})
+}
+
+func ext۰reflect۰rtype۰In(a *analysis, cgn *cgnode) {
+	ext۰reflect۰rtype۰InOut(a, cgn, false)
+}
+
+func ext۰reflect۰rtype۰Out(a *analysis, cgn *cgnode) {
+	ext۰reflect۰rtype۰InOut(a, cgn, true)
+}
+
+// ---------- func (*rtype) Key() Type ----------
+
+// result = Key(t)
+type rtypeKeyConstraint struct {
+	cgn    *cgnode
+	t      nodeid // (ptr)
+	result nodeid // (indirect)
+}
+
+func (c *rtypeKeyConstraint) ptr() nodeid { return c.t }
+func (c *rtypeKeyConstraint) presolve(h *hvn) {
+	h.markIndirect(onodeid(c.result), "rtypeKey.result")
+}
+func (c *rtypeKeyConstraint) renumber(mapping []nodeid) {
+	c.t = mapping[c.t]
+	c.result = mapping[c.result]
+}
+
+func (c *rtypeKeyConstraint) String() string {
+	return fmt.Sprintf("n%d = (*reflect.rtype).Key(n%d)", c.result, c.t)
+}
+
+func (c *rtypeKeyConstraint) solve(a *analysis, delta *nodeset) {
+	changed := false
+	for _, x := range delta.AppendTo(a.deltaSpace) {
+		tObj := nodeid(x)
+		T := a.nodes[tObj].obj.data.(types.Type)
+		if tMap, ok := T.Underlying().(*types.Map); ok {
+			if a.addLabel(c.result, a.makeRtype(tMap.Key())) {
+				changed = true
+			}
+		}
+	}
+	if changed {
+		a.addWork(c.result)
+	}
+}
+
+func ext۰reflect۰rtype۰Key(a *analysis, cgn *cgnode) {
+	a.addConstraint(&rtypeKeyConstraint{
+		cgn:    cgn,
+		t:      a.funcParams(cgn.obj),
+		result: a.funcResults(cgn.obj),
+	})
+}
+
+// ---------- func (*rtype) Method(int) (Method, bool) ----------
+// ---------- func (*rtype) MethodByName(string) (Method, bool) ----------
+
+// result = MethodByName(t, name)
+// result = Method(t, _)
+type rtypeMethodByNameConstraint struct {
+	cgn    *cgnode
+	name   string // name of method; "" for unknown
+	t      nodeid // (ptr)
+	result nodeid // (indirect)
+}
+
+func (c *rtypeMethodByNameConstraint) ptr() nodeid { return c.t }
+func (c *rtypeMethodByNameConstraint) presolve(h *hvn) {
+	h.markIndirect(onodeid(c.result+3), "rtypeMethodByName.result.Type")
+	h.markIndirect(onodeid(c.result+4), "rtypeMethodByName.result.Func")
+}
+func (c *rtypeMethodByNameConstraint) renumber(mapping []nodeid) {
+	c.t = mapping[c.t]
+	c.result = mapping[c.result]
+}
+
+func (c *rtypeMethodByNameConstraint) String() string {
+	return fmt.Sprintf("n%d = (*reflect.rtype).MethodByName(n%d, %q)", c.result, c.t, c.name)
+}
+
+// changeRecv returns sig with Recv prepended to Params().
+func changeRecv(sig *types.Signature) *types.Signature {
+	params := sig.Params()
+	n := params.Len()
+	p2 := make([]*types.Var, n+1)
+	p2[0] = sig.Recv()
+	for i := 0; i < n; i++ {
+		p2[i+1] = params.At(i)
+	}
+	return types.NewSignature(nil, types.NewTuple(p2...), sig.Results(), sig.Variadic())
+}
+
+func (c *rtypeMethodByNameConstraint) solve(a *analysis, delta *nodeset) {
+	for _, x := range delta.AppendTo(a.deltaSpace) {
+		tObj := nodeid(x)
+		T := a.nodes[tObj].obj.data.(types.Type)
+
+		isIface := isInterface(T)
+
+		// We don't use Lookup(c.name) when c.name != "" to avoid
+		// ambiguity: >1 unexported methods could match.
+		mset := a.prog.MethodSets.MethodSet(T)
+		for i, n := 0, mset.Len(); i < n; i++ {
+			sel := mset.At(i)
+			if c.name == "" || c.name == sel.Obj().Name() {
+				// type Method struct {
+				// 0     __identity__
+				// 1	Name    string
+				// 2	PkgPath string
+				// 3	Type    Type
+				// 4	Func    Value
+				// 5	Index   int
+				// }
+
+				var sig *types.Signature
+				var fn *ssa.Function
+				if isIface {
+					sig = sel.Type().(*types.Signature)
+				} else {
+					fn = a.prog.Method(sel)
+					// move receiver to params[0]
+					sig = changeRecv(fn.Signature)
+				}
+
+				// a.offsetOf(Type) is 3.
+				if id := c.result + 3; a.addLabel(id, a.makeRtype(sig)) {
+					a.addWork(id)
+				}
+				if fn != nil {
+					// a.offsetOf(Func) is 4.
+					if id := c.result + 4; a.addLabel(id, a.objectNode(nil, fn)) {
+						a.addWork(id)
+					}
+				}
+			}
+		}
+	}
+}
+
+func ext۰reflect۰rtype۰MethodByName(a *analysis, cgn *cgnode) {
+	// If we have access to the callsite,
+	// and the argument is a string constant,
+	// return only that method.
+	var name string
+	if site := cgn.callersite; site != nil {
+		if c, ok := site.instr.Common().Args[0].(*ssa.Const); ok {
+			name = exact.StringVal(c.Value)
+		}
+	}
+
+	a.addConstraint(&rtypeMethodByNameConstraint{
+		cgn:    cgn,
+		name:   name,
+		t:      a.funcParams(cgn.obj),
+		result: a.funcResults(cgn.obj),
+	})
+}
+
+func ext۰reflect۰rtype۰Method(a *analysis, cgn *cgnode) {
+	// No-one ever calls Method with a constant argument,
+	// so we don't specialize that case.
+	a.addConstraint(&rtypeMethodByNameConstraint{
+		cgn:    cgn,
+		t:      a.funcParams(cgn.obj),
+		result: a.funcResults(cgn.obj),
+	})
+}
+
+// typeHeight returns the "height" of the type, which is roughly
+// speaking the number of chan, map, pointer and slice type constructors
+// at the root of T; these are the four type kinds that can be created
+// via reflection.  Chan and map constructors are counted as double the
+// height of slice and pointer constructors since they are less often
+// deeply nested.
+//
+// The solver rules for type constructors must somehow bound the set of
+// types they create to ensure termination of the algorithm in cases
+// where the output of a type constructor flows to its input, e.g.
+//
+// 	func f(t reflect.Type) {
+// 		f(reflect.PtrTo(t))
+// 	}
+//
+// It does this by limiting the type height to k, but this still leaves
+// a potentially exponential (4^k) number of of types that may be
+// enumerated in pathological cases.
+//
+func typeHeight(T types.Type) int {
+	switch T := T.(type) {
+	case *types.Chan:
+		return 2 + typeHeight(T.Elem())
+	case *types.Map:
+		k := typeHeight(T.Key())
+		v := typeHeight(T.Elem())
+		if v > k {
+			k = v // max(k, v)
+		}
+		return 2 + k
+	case *types.Slice:
+		return 1 + typeHeight(T.Elem())
+	case *types.Pointer:
+		return 1 + typeHeight(T.Elem())
+	}
+	return 0
+}
+
+func typeTooHigh(T types.Type) bool {
+	return typeHeight(T) > 3
+}
diff --git a/go/pointer/solve.go b/go/pointer/solve.go
new file mode 100644
index 0000000..ad1a65f
--- /dev/null
+++ b/go/pointer/solve.go
@@ -0,0 +1,371 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package pointer
+
+// This file defines a naive Andersen-style solver for the inclusion
+// constraint system.
+
+import (
+	"fmt"
+
+	"golang.org/x/tools/go/types"
+)
+
+type solverState struct {
+	complex []constraint // complex constraints attached to this node
+	copyTo  nodeset      // simple copy constraint edges
+	pts     nodeset      // points-to set of this node
+	prevPTS nodeset      // pts(n) in previous iteration (for difference propagation)
+}
+
+func (a *analysis) solve() {
+	start("Solving")
+	if a.log != nil {
+		fmt.Fprintf(a.log, "\n\n==== Solving constraints\n\n")
+	}
+
+	// Solver main loop.
+	var delta nodeset
+	for {
+		// Add new constraints to the graph:
+		// static constraints from SSA on round 1,
+		// dynamic constraints from reflection thereafter.
+		a.processNewConstraints()
+
+		var x int
+		if !a.work.TakeMin(&x) {
+			break // empty
+		}
+		id := nodeid(x)
+		if a.log != nil {
+			fmt.Fprintf(a.log, "\tnode n%d\n", id)
+		}
+
+		n := a.nodes[id]
+
+		// Difference propagation.
+		delta.Difference(&n.solve.pts.Sparse, &n.solve.prevPTS.Sparse)
+		if delta.IsEmpty() {
+			continue
+		}
+		if a.log != nil {
+			fmt.Fprintf(a.log, "\t\tpts(n%d : %s) = %s + %s\n",
+				id, n.typ, &delta, &n.solve.prevPTS)
+		}
+		n.solve.prevPTS.Copy(&n.solve.pts.Sparse)
+
+		// Apply all resolution rules attached to n.
+		a.solveConstraints(n, &delta)
+
+		if a.log != nil {
+			fmt.Fprintf(a.log, "\t\tpts(n%d) = %s\n", id, &n.solve.pts)
+		}
+	}
+
+	if !a.nodes[0].solve.pts.IsEmpty() {
+		panic(fmt.Sprintf("pts(0) is nonempty: %s", &a.nodes[0].solve.pts))
+	}
+
+	// Release working state (but keep final PTS).
+	for _, n := range a.nodes {
+		n.solve.complex = nil
+		n.solve.copyTo.Clear()
+		n.solve.prevPTS.Clear()
+	}
+
+	if a.log != nil {
+		fmt.Fprintf(a.log, "Solver done\n")
+
+		// Dump solution.
+		for i, n := range a.nodes {
+			if !n.solve.pts.IsEmpty() {
+				fmt.Fprintf(a.log, "pts(n%d) = %s : %s\n", i, &n.solve.pts, n.typ)
+			}
+		}
+	}
+	stop("Solving")
+}
+
+// processNewConstraints takes the new constraints from a.constraints
+// and adds them to the graph, ensuring
+// that new constraints are applied to pre-existing labels and
+// that pre-existing constraints are applied to new labels.
+//
+func (a *analysis) processNewConstraints() {
+	// Take the slice of new constraints.
+	// (May grow during call to solveConstraints.)
+	constraints := a.constraints
+	a.constraints = nil
+
+	// Initialize points-to sets from addr-of (base) constraints.
+	for _, c := range constraints {
+		if c, ok := c.(*addrConstraint); ok {
+			dst := a.nodes[c.dst]
+			dst.solve.pts.add(c.src)
+
+			// Populate the worklist with nodes that point to
+			// something initially (due to addrConstraints) and
+			// have other constraints attached.
+			// (A no-op in round 1.)
+			if !dst.solve.copyTo.IsEmpty() || len(dst.solve.complex) > 0 {
+				a.addWork(c.dst)
+			}
+		}
+	}
+
+	// Attach simple (copy) and complex constraints to nodes.
+	var stale nodeset
+	for _, c := range constraints {
+		var id nodeid
+		switch c := c.(type) {
+		case *addrConstraint:
+			// base constraints handled in previous loop
+			continue
+		case *copyConstraint:
+			// simple (copy) constraint
+			id = c.src
+			a.nodes[id].solve.copyTo.add(c.dst)
+		default:
+			// complex constraint
+			id = c.ptr()
+			solve := a.nodes[id].solve
+			solve.complex = append(solve.complex, c)
+		}
+
+		if n := a.nodes[id]; !n.solve.pts.IsEmpty() {
+			if !n.solve.prevPTS.IsEmpty() {
+				stale.add(id)
+			}
+			a.addWork(id)
+		}
+	}
+	// Apply new constraints to pre-existing PTS labels.
+	var space [50]int
+	for _, id := range stale.AppendTo(space[:0]) {
+		n := a.nodes[nodeid(id)]
+		a.solveConstraints(n, &n.solve.prevPTS)
+	}
+}
+
+// solveConstraints applies each resolution rule attached to node n to
+// the set of labels delta.  It may generate new constraints in
+// a.constraints.
+//
+func (a *analysis) solveConstraints(n *node, delta *nodeset) {
+	if delta.IsEmpty() {
+		return
+	}
+
+	// Process complex constraints dependent on n.
+	for _, c := range n.solve.complex {
+		if a.log != nil {
+			fmt.Fprintf(a.log, "\t\tconstraint %s\n", c)
+		}
+		c.solve(a, delta)
+	}
+
+	// Process copy constraints.
+	var copySeen nodeset
+	for _, x := range n.solve.copyTo.AppendTo(a.deltaSpace) {
+		mid := nodeid(x)
+		if copySeen.add(mid) {
+			if a.nodes[mid].solve.pts.addAll(delta) {
+				a.addWork(mid)
+			}
+		}
+	}
+}
+
+// addLabel adds label to the points-to set of ptr and reports whether the set grew.
+func (a *analysis) addLabel(ptr, label nodeid) bool {
+	b := a.nodes[ptr].solve.pts.add(label)
+	if b && a.log != nil {
+		fmt.Fprintf(a.log, "\t\tpts(n%d) += n%d\n", ptr, label)
+	}
+	return b
+}
+
+func (a *analysis) addWork(id nodeid) {
+	a.work.Insert(int(id))
+	if a.log != nil {
+		fmt.Fprintf(a.log, "\t\twork: n%d\n", id)
+	}
+}
+
+// onlineCopy adds a copy edge.  It is called online, i.e. during
+// solving, so it adds edges and pts members directly rather than by
+// instantiating a 'constraint'.
+//
+// The size of the copy is implicitly 1.
+// It returns true if pts(dst) changed.
+//
+func (a *analysis) onlineCopy(dst, src nodeid) bool {
+	if dst != src {
+		if nsrc := a.nodes[src]; nsrc.solve.copyTo.add(dst) {
+			if a.log != nil {
+				fmt.Fprintf(a.log, "\t\t\tdynamic copy n%d <- n%d\n", dst, src)
+			}
+			// TODO(adonovan): most calls to onlineCopy
+			// are followed by addWork, possibly batched
+			// via a 'changed' flag; see if there's a
+			// noticeable penalty to calling addWork here.
+			return a.nodes[dst].solve.pts.addAll(&nsrc.solve.pts)
+		}
+	}
+	return false
+}
+
+// Returns sizeof.
+// Implicitly adds nodes to worklist.
+//
+// TODO(adonovan): now that we support a.copy() during solving, we
+// could eliminate onlineCopyN, but it's much slower.  Investigate.
+//
+func (a *analysis) onlineCopyN(dst, src nodeid, sizeof uint32) uint32 {
+	for i := uint32(0); i < sizeof; i++ {
+		if a.onlineCopy(dst, src) {
+			a.addWork(dst)
+		}
+		src++
+		dst++
+	}
+	return sizeof
+}
+
+func (c *loadConstraint) solve(a *analysis, delta *nodeset) {
+	var changed bool
+	for _, x := range delta.AppendTo(a.deltaSpace) {
+		k := nodeid(x)
+		koff := k + nodeid(c.offset)
+		if a.onlineCopy(c.dst, koff) {
+			changed = true
+		}
+	}
+	if changed {
+		a.addWork(c.dst)
+	}
+}
+
+func (c *storeConstraint) solve(a *analysis, delta *nodeset) {
+	for _, x := range delta.AppendTo(a.deltaSpace) {
+		k := nodeid(x)
+		koff := k + nodeid(c.offset)
+		if a.onlineCopy(koff, c.src) {
+			a.addWork(koff)
+		}
+	}
+}
+
+func (c *offsetAddrConstraint) solve(a *analysis, delta *nodeset) {
+	dst := a.nodes[c.dst]
+	for _, x := range delta.AppendTo(a.deltaSpace) {
+		k := nodeid(x)
+		if dst.solve.pts.add(k + nodeid(c.offset)) {
+			a.addWork(c.dst)
+		}
+	}
+}
+
+func (c *typeFilterConstraint) solve(a *analysis, delta *nodeset) {
+	for _, x := range delta.AppendTo(a.deltaSpace) {
+		ifaceObj := nodeid(x)
+		tDyn, _, indirect := a.taggedValue(ifaceObj)
+		if indirect {
+			// TODO(adonovan): we'll need to implement this
+			// when we start creating indirect tagged objects.
+			panic("indirect tagged object")
+		}
+
+		if types.AssignableTo(tDyn, c.typ) {
+			if a.addLabel(c.dst, ifaceObj) {
+				a.addWork(c.dst)
+			}
+		}
+	}
+}
+
+func (c *untagConstraint) solve(a *analysis, delta *nodeset) {
+	predicate := types.AssignableTo
+	if c.exact {
+		predicate = types.Identical
+	}
+	for _, x := range delta.AppendTo(a.deltaSpace) {
+		ifaceObj := nodeid(x)
+		tDyn, v, indirect := a.taggedValue(ifaceObj)
+		if indirect {
+			// TODO(adonovan): we'll need to implement this
+			// when we start creating indirect tagged objects.
+			panic("indirect tagged object")
+		}
+
+		if predicate(tDyn, c.typ) {
+			// Copy payload sans tag to dst.
+			//
+			// TODO(adonovan): opt: if tDyn is
+			// nonpointerlike we can skip this entire
+			// constraint, perhaps.  We only care about
+			// pointers among the fields.
+			a.onlineCopyN(c.dst, v, a.sizeof(tDyn))
+		}
+	}
+}
+
+func (c *invokeConstraint) solve(a *analysis, delta *nodeset) {
+	for _, x := range delta.AppendTo(a.deltaSpace) {
+		ifaceObj := nodeid(x)
+		tDyn, v, indirect := a.taggedValue(ifaceObj)
+		if indirect {
+			// TODO(adonovan): we may need to implement this if
+			// we ever apply invokeConstraints to reflect.Value PTSs,
+			// e.g. for (reflect.Value).Call.
+			panic("indirect tagged object")
+		}
+
+		// Look up the concrete method.
+		fn := a.prog.LookupMethod(tDyn, c.method.Pkg(), c.method.Name())
+		if fn == nil {
+			panic(fmt.Sprintf("n%d: no ssa.Function for %s", c.iface, c.method))
+		}
+		sig := fn.Signature
+
+		fnObj := a.globalobj[fn] // dynamic calls use shared contour
+		if fnObj == 0 {
+			// a.objectNode(fn) was not called during gen phase.
+			panic(fmt.Sprintf("a.globalobj[%s]==nil", fn))
+		}
+
+		// Make callsite's fn variable point to identity of
+		// concrete method.  (There's no need to add it to
+		// worklist since it never has attached constraints.)
+		a.addLabel(c.params, fnObj)
+
+		// Extract value and connect to method's receiver.
+		// Copy payload to method's receiver param (arg0).
+		arg0 := a.funcParams(fnObj)
+		recvSize := a.sizeof(sig.Recv().Type())
+		a.onlineCopyN(arg0, v, recvSize)
+
+		src := c.params + 1 // skip past identity
+		dst := arg0 + nodeid(recvSize)
+
+		// Copy caller's argument block to method formal parameters.
+		paramsSize := a.sizeof(sig.Params())
+		a.onlineCopyN(dst, src, paramsSize)
+		src += nodeid(paramsSize)
+		dst += nodeid(paramsSize)
+
+		// Copy method results to caller's result block.
+		resultsSize := a.sizeof(sig.Results())
+		a.onlineCopyN(src, dst, resultsSize)
+	}
+}
+
+func (c *addrConstraint) solve(a *analysis, delta *nodeset) {
+	panic("addr is not a complex constraint")
+}
+
+func (c *copyConstraint) solve(a *analysis, delta *nodeset) {
+	panic("copy is not a complex constraint")
+}
diff --git a/go/pointer/stdlib_test.go b/go/pointer/stdlib_test.go
new file mode 100644
index 0000000..ef7c652
--- /dev/null
+++ b/go/pointer/stdlib_test.go
@@ -0,0 +1,109 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Incomplete source tree on Android.
+
+// +build !android
+
+package pointer
+
+// This file runs the pointer analysis on all packages and tests beneath
+// $GOROOT.  It provides a "smoke test" that the analysis doesn't crash
+// on a large input, and a benchmark for performance measurement.
+//
+// Because it is relatively slow, the --stdlib flag must be enabled for
+// this test to run:
+//    % go test -v golang.org/x/tools/go/pointer --stdlib
+
+import (
+	"flag"
+	"go/build"
+	"go/token"
+	"testing"
+	"time"
+
+	"golang.org/x/tools/go/buildutil"
+	"golang.org/x/tools/go/loader"
+	"golang.org/x/tools/go/ssa"
+	"golang.org/x/tools/go/ssa/ssautil"
+)
+
+var runStdlibTest = flag.Bool("stdlib", false, "Run the (slow) stdlib test")
+
+func TestStdlib(t *testing.T) {
+	if !*runStdlibTest {
+		t.Skip("skipping (slow) stdlib test (use --stdlib)")
+	}
+
+	// Load, parse and type-check the program.
+	ctxt := build.Default // copy
+	ctxt.GOPATH = ""      // disable GOPATH
+	conf := loader.Config{Build: &ctxt}
+	if _, err := conf.FromArgs(buildutil.AllPackages(conf.Build), true); err != nil {
+		t.Errorf("FromArgs failed: %v", err)
+		return
+	}
+
+	iprog, err := conf.Load()
+	if err != nil {
+		t.Fatalf("Load failed: %v", err)
+	}
+
+	// Create SSA packages.
+	prog := ssautil.CreateProgram(iprog, 0)
+	prog.BuildAll()
+
+	numPkgs := len(prog.AllPackages())
+	if want := 240; numPkgs < want {
+		t.Errorf("Loaded only %d packages, want at least %d", numPkgs, want)
+	}
+
+	// Determine the set of packages/tests to analyze.
+	var testPkgs []*ssa.Package
+	for _, info := range iprog.InitialPackages() {
+		testPkgs = append(testPkgs, prog.Package(info.Pkg))
+	}
+	testmain := prog.CreateTestMainPackage(testPkgs...)
+	if testmain == nil {
+		t.Fatal("analysis scope has tests")
+	}
+
+	// Run the analysis.
+	config := &Config{
+		Reflection:     false, // TODO(adonovan): fix remaining bug in rVCallConstraint, then enable.
+		BuildCallGraph: true,
+		Mains:          []*ssa.Package{testmain},
+	}
+	// TODO(adonovan): add some query values (affects track bits).
+
+	t0 := time.Now()
+
+	result, err := Analyze(config)
+	if err != nil {
+		t.Fatal(err) // internal error in pointer analysis
+	}
+	_ = result // TODO(adonovan): measure something
+
+	t1 := time.Now()
+
+	// Dump some statistics.
+	allFuncs := ssautil.AllFunctions(prog)
+	var numInstrs int
+	for fn := range allFuncs {
+		for _, b := range fn.Blocks {
+			numInstrs += len(b.Instrs)
+		}
+	}
+
+	// determine line count
+	var lineCount int
+	prog.Fset.Iterate(func(f *token.File) bool {
+		lineCount += f.LineCount()
+		return true
+	})
+
+	t.Log("#Source lines:          ", lineCount)
+	t.Log("#Instructions:          ", numInstrs)
+	t.Log("Pointer analysis:       ", t1.Sub(t0))
+}
diff --git a/go/pointer/testdata/a_test.go b/go/pointer/testdata/a_test.go
new file mode 100644
index 0000000..3baa9ac
--- /dev/null
+++ b/go/pointer/testdata/a_test.go
@@ -0,0 +1,42 @@
+// +build ignore
+
+package a
+
+// This test exercises the synthesis of testmain packages for tests.
+// The test framework doesn't directly let us perform negative
+// assertions (i.e. that TestingQuux isn't called, or that its
+// parameter's PTS is empty) so this test is rather roundabout.
+
+import "testing"
+
+func log(f func(*testing.T)) {
+	// The PTS of f is the set of called tests.  TestingQuux is not present.
+	print(f) // @pointsto main.Test | main.TestFoo
+}
+
+func Test(t *testing.T) {
+	// Don't assert @pointsto(t) since its label contains a fragile line number.
+	log(Test)
+}
+
+func TestFoo(t *testing.T) {
+	// Don't assert @pointsto(t) since its label contains a fragile line number.
+	log(TestFoo)
+}
+
+func TestingQuux(t *testing.T) {
+	// We can't assert @pointsto(t) since this is dead code.
+	log(TestingQuux)
+}
+
+func BenchmarkFoo(b *testing.B) {
+}
+
+func ExampleBar() {
+}
+
+// Excludes TestingQuux.
+// @calls testing.tRunner -> main.Test
+// @calls testing.tRunner -> main.TestFoo
+// @calls testing.runExample -> main.ExampleBar
+// @calls (*testing.B).runN -> main.BenchmarkFoo
diff --git a/go/pointer/testdata/another.go b/go/pointer/testdata/another.go
new file mode 100644
index 0000000..12ed690
--- /dev/null
+++ b/go/pointer/testdata/another.go
@@ -0,0 +1,36 @@
+// +build ignore
+
+package main
+
+var unknown bool
+
+type S string
+
+func incr(x int) int { return x + 1 }
+
+func main() {
+	var i interface{}
+	i = 1
+	if unknown {
+		i = S("foo")
+	}
+	if unknown {
+		i = (func(int, int))(nil) // NB type compares equal to that below.
+	}
+	// Look, the test harness can handle equal-but-not-String-equal
+	// types because we parse types and using a typemap.
+	if unknown {
+		i = (func(x int, y int))(nil)
+	}
+	if unknown {
+		i = incr
+	}
+	print(i) // @types int | S | func(int, int) | func(int) int
+
+	// NB, an interface may never directly alias any global
+	// labels, even though it may contain pointers that do.
+	print(i)                 // @pointsto makeinterface:func(x int) int | makeinterface:func(x int, y int) | makeinterface:func(int, int) | makeinterface:int | makeinterface:main.S
+	print(i.(func(int) int)) // @pointsto main.incr
+
+	print() // regression test for crash
+}
diff --git a/go/pointer/testdata/arrayreflect.go b/go/pointer/testdata/arrayreflect.go
new file mode 100644
index 0000000..2b23674
--- /dev/null
+++ b/go/pointer/testdata/arrayreflect.go
@@ -0,0 +1,191 @@
+// +build ignore
+
+package main
+
+// Test of arrays & slices with reflection.
+
+import "reflect"
+
+var a, b int
+
+type S string
+
+func reflectValueSlice() {
+	// reflect.Value contains a slice.
+	slice := make([]*int, 10) // @line slice
+	slice[0] = &a
+	rvsl := reflect.ValueOf(slice).Slice(0, 0)
+	print(rvsl.Interface())              // @types []*int
+	print(rvsl.Interface().([]*int))     // @pointsto makeslice@slice:15
+	print(rvsl.Interface().([]*int)[42]) // @pointsto main.a
+
+	// reflect.Value contains an array (non-addressable).
+	array := [10]*int{&a} // @line array
+	rvarray := reflect.ValueOf(array).Slice(0, 0)
+	print(rvarray.Interface())              // @types
+	print(rvarray.Interface().([]*int))     // @pointsto
+	print(rvarray.Interface().([]*int)[42]) // @pointsto
+
+	// reflect.Value contains a pointer-to-array
+	rvparray := reflect.ValueOf(&array).Slice(0, 0)
+	print(rvparray.Interface())              // @types []*int
+	print(rvparray.Interface().([]*int))     // @pointsto array@array:2
+	print(rvparray.Interface().([]*int)[42]) // @pointsto main.a
+
+	// reflect.Value contains a string.
+	rvstring := reflect.ValueOf("hi").Slice(0, 0)
+	print(rvstring.Interface()) // @types string
+
+	// reflect.Value contains a (named) string type.
+	rvS := reflect.ValueOf(S("hi")).Slice(0, 0)
+	print(rvS.Interface()) // @types S
+
+	// reflect.Value contains a non-array pointer.
+	rvptr := reflect.ValueOf(new(int)).Slice(0, 0)
+	print(rvptr.Interface()) // @types
+
+	// reflect.Value contains a non-string basic type.
+	rvint := reflect.ValueOf(3).Slice(0, 0)
+	print(rvint.Interface()) // @types
+}
+
+func reflectValueBytes() {
+	sl1 := make([]byte, 0) // @line ar5sl1
+	sl2 := make([]byte, 0) // @line ar5sl2
+
+	rvsl1 := reflect.ValueOf(sl1)
+	print(rvsl1.Interface())          // @types []byte
+	print(rvsl1.Interface().([]byte)) // @pointsto makeslice@ar5sl1:13
+	print(rvsl1.Bytes())              // @pointsto makeslice@ar5sl1:13
+
+	rvsl2 := reflect.ValueOf(123)
+	rvsl2.SetBytes(sl2)
+	print(rvsl2.Interface())          // @types int
+	print(rvsl2.Interface().([]byte)) // @pointsto
+	print(rvsl2.Bytes())              // @pointsto
+
+	rvsl3 := reflect.ValueOf([]byte(nil))
+	rvsl3.SetBytes(sl2)
+	print(rvsl3.Interface())          // @types []byte
+	print(rvsl3.Interface().([]byte)) // @pointsto makeslice@ar5sl2:13
+	print(rvsl3.Bytes())              // @pointsto makeslice@ar5sl2:13
+}
+
+func reflectValueIndex() {
+	slice := []*int{&a} // @line ar6slice
+	rv1 := reflect.ValueOf(slice)
+	print(rv1.Index(42).Interface())        // @types *int
+	print(rv1.Index(42).Interface().(*int)) // @pointsto main.a
+
+	array := [10]*int{&a}
+	rv2 := reflect.ValueOf(array)
+	print(rv2.Index(42).Interface())        // @types *int
+	print(rv2.Index(42).Interface().(*int)) // @pointsto main.a
+
+	rv3 := reflect.ValueOf("string")
+	print(rv3.Index(42).Interface()) // @types rune
+
+	rv4 := reflect.ValueOf(&array)
+	print(rv4.Index(42).Interface()) // @types
+
+	rv5 := reflect.ValueOf(3)
+	print(rv5.Index(42).Interface()) // @types
+}
+
+func reflectValueElem() {
+	// Interface.
+	var iface interface{} = &a
+	rv1 := reflect.ValueOf(&iface).Elem()
+	print(rv1.Interface())               // @types *int
+	print(rv1.Interface().(*int))        // @pointsto main.a
+	print(rv1.Elem().Interface())        // @types *int
+	print(rv1.Elem().Interface().(*int)) // @pointsto main.a
+
+	print(reflect.ValueOf(new(interface{})).Elem().Elem()) // @types
+
+	// Pointer.
+	ptr := &a
+	rv2 := reflect.ValueOf(&ptr)
+	print(rv2.Elem().Interface())        // @types *int
+	print(rv2.Elem().Interface().(*int)) // @pointsto main.a
+
+	// No other type works with (rV).Elem, not even those that
+	// work with (rT).Elem: slice, array, map, chan.
+
+	rv3 := reflect.ValueOf([]*int{&a})
+	print(rv3.Elem().Interface()) // @types
+
+	rv4 := reflect.ValueOf([10]*int{&a})
+	print(rv4.Elem().Interface()) // @types
+
+	rv5 := reflect.ValueOf(map[*int]*int{&a: &b})
+	print(rv5.Elem().Interface()) // @types
+
+	ch := make(chan *int)
+	ch <- &a
+	rv6 := reflect.ValueOf(ch)
+	print(rv6.Elem().Interface()) // @types
+
+	rv7 := reflect.ValueOf(3)
+	print(rv7.Elem().Interface()) // @types
+}
+
+func reflectTypeElem() {
+	rt1 := reflect.TypeOf(make([]*int, 0))
+	print(reflect.Zero(rt1.Elem())) // @types *int
+
+	rt2 := reflect.TypeOf([10]*int{})
+	print(reflect.Zero(rt2.Elem())) // @types *int
+
+	rt3 := reflect.TypeOf(map[*int]*int{})
+	print(reflect.Zero(rt3.Elem())) // @types *int
+
+	rt4 := reflect.TypeOf(make(chan *int))
+	print(reflect.Zero(rt4.Elem())) // @types *int
+
+	ptr := &a
+	rt5 := reflect.TypeOf(&ptr)
+	print(reflect.Zero(rt5.Elem())) // @types *int
+
+	rt6 := reflect.TypeOf(3)
+	print(reflect.Zero(rt6.Elem())) // @types
+}
+
+func reflectPtrTo() {
+	tInt := reflect.TypeOf(3)
+	tPtrInt := reflect.PtrTo(tInt)
+	print(reflect.Zero(tPtrInt)) // @types *int
+	tPtrPtrInt := reflect.PtrTo(tPtrInt)
+	print(reflect.Zero(tPtrPtrInt)) // @types **int
+}
+
+func reflectSliceOf() {
+	tInt := reflect.TypeOf(3)
+	tSliceInt := reflect.SliceOf(tInt)
+	print(reflect.Zero(tSliceInt)) // @types []int
+}
+
+type T struct{ x int }
+
+func reflectMakeSlice() {
+	rt := []reflect.Type{
+		reflect.TypeOf(3),
+		reflect.TypeOf([]int{}),
+		reflect.TypeOf([]T{}),
+	}[0]
+	sl := reflect.MakeSlice(rt, 0, 0)
+	print(sl)                         // @types []int | []T
+	print(sl)                         // @pointsto <alloc in reflect.MakeSlice> | <alloc in reflect.MakeSlice>
+	print(&sl.Interface().([]T)[0].x) // @pointsto <alloc in reflect.MakeSlice>[*].x
+}
+
+func main() {
+	reflectValueSlice()
+	reflectValueBytes()
+	reflectValueIndex()
+	reflectValueElem()
+	reflectTypeElem()
+	reflectPtrTo()
+	reflectSliceOf()
+	reflectMakeSlice()
+}
diff --git a/go/pointer/testdata/arrays.go b/go/pointer/testdata/arrays.go
new file mode 100644
index 0000000..e57a15b
--- /dev/null
+++ b/go/pointer/testdata/arrays.go
@@ -0,0 +1,97 @@
+// +build ignore
+
+package main
+
+var unknown bool // defeat dead-code elimination
+
+var a, b int
+
+func array1() {
+	sliceA := make([]*int, 10) // @line a1make
+	sliceA[0] = &a
+
+	var sliceB []*int
+	sliceB = append(sliceB, &b) // @line a1append
+
+	print(sliceA)    // @pointsto makeslice@a1make:16
+	print(sliceA[0]) // @pointsto main.a
+
+	print(sliceB)      // @pointsto append@a1append:17
+	print(sliceB[100]) // @pointsto main.b
+}
+
+func array2() {
+	sliceA := make([]*int, 10) // @line a2make
+	sliceA[0] = &a
+
+	sliceB := sliceA[:]
+
+	print(sliceA)    // @pointsto makeslice@a2make:16
+	print(sliceA[0]) // @pointsto main.a
+
+	print(sliceB)    // @pointsto makeslice@a2make:16
+	print(sliceB[0]) // @pointsto main.a
+}
+
+func array3() {
+	a := []interface{}{"", 1}
+	b := []interface{}{true, func() {}}
+	print(a[0]) // @types string | int
+	print(b[0]) // @types bool | func()
+}
+
+// Test of append, copy, slice.
+func array4() {
+	var s2 struct { // @line a4L0
+		a [3]int
+		b struct{ c, d int }
+	}
+	var sl1 = make([]*int, 10) // @line a4make
+	var someint int            // @line a4L1
+	sl1[1] = &someint
+	sl2 := append(sl1, &s2.a[1]) // @line a4append1
+	print(sl1)                   // @pointsto makeslice@a4make:16
+	print(sl2)                   // @pointsto append@a4append1:15 | makeslice@a4make:16
+	print(sl1[0])                // @pointsto someint@a4L1:6 | s2.a[*]@a4L0:6
+	print(sl2[0])                // @pointsto someint@a4L1:6 | s2.a[*]@a4L0:6
+
+	// In z=append(x,y) we should observe flow from y[*] to x[*].
+	var sl3 = make([]*int, 10) // @line a4L2
+	_ = append(sl3, &s2.a[1])
+	print(sl3)    // @pointsto makeslice@a4L2:16
+	print(sl3[0]) // @pointsto s2.a[*]@a4L0:6
+
+	var sl4 = []*int{&a} // @line a4L3
+	sl4a := append(sl4)  // @line a4L4
+	print(sl4a)          // @pointsto slicelit@a4L3:18 | append@a4L4:16
+	print(&sl4a[0])      // @pointsto slicelit[*]@a4L3:18 | append[*]@a4L4:16
+	print(sl4a[0])       // @pointsto main.a
+
+	var sl5 = []*int{&b} // @line a4L5
+	copy(sl5, sl4)
+	print(sl5)     // @pointsto slicelit@a4L5:18
+	print(&sl5[0]) // @pointsto slicelit[*]@a4L5:18
+	print(sl5[0])  // @pointsto main.b | main.a
+
+	var sl6 = sl5[:0]
+	print(sl6)     // @pointsto slicelit@a4L5:18
+	print(&sl6[0]) // @pointsto slicelit[*]@a4L5:18
+	print(sl6[0])  // @pointsto main.b | main.a
+}
+
+func array5() {
+	var arr [2]*int
+	arr[0] = &a
+	arr[1] = &b
+
+	var n int
+	print(arr[n]) // @pointsto main.a | main.b
+}
+
+func main() {
+	array1()
+	array2()
+	array3()
+	array4()
+	array5()
+}
diff --git a/go/pointer/testdata/channels.go b/go/pointer/testdata/channels.go
new file mode 100644
index 0000000..76eb5f8
--- /dev/null
+++ b/go/pointer/testdata/channels.go
@@ -0,0 +1,118 @@
+// +build ignore
+
+package main
+
+func incr(x int) int { return x + 1 }
+
+func decr(x int) int { return x - 1 }
+
+var unknown bool // defeat dead-code elimination
+
+func chan1() {
+	chA := make(chan func(int) int, 0) // @line c1makeA
+	chB := make(chan func(int) int, 0) // @line c1makeB
+	chA <- incr
+	chB <- decr
+	chB <- func(int) int { return 1 }
+
+	print(chA)   // @pointsto makechan@c1makeA:13
+	print(<-chA) // @pointsto main.incr
+
+	print(chB)   // @pointsto makechan@c1makeB:13
+	print(<-chB) // @pointsto main.decr | main.chan1$1
+}
+
+func chan2() {
+	chA := make(chan func(int) int, 0) // @line c2makeA
+	chB := make(chan func(int) int, 0) // @line c2makeB
+	chA <- incr
+	chB <- decr
+	chB <- func(int) int { return 1 }
+
+	// Channels flow together.
+	// Labelsets remain distinct but elements are merged.
+	chAB := chA
+	if unknown {
+		chAB = chB
+	}
+
+	print(chA)   // @pointsto makechan@c2makeA:13
+	print(<-chA) // @pointsto main.incr
+
+	print(chB)   // @pointsto makechan@c2makeB:13
+	print(<-chB) // @pointsto main.decr | main.chan2$1
+
+	print(chAB)   // @pointsto makechan@c2makeA:13 | makechan@c2makeB:13
+	print(<-chAB) // @pointsto main.incr | main.decr | main.chan2$1
+
+	(<-chA)(3)
+}
+
+// @calls main.chan2 -> main.incr
+
+func chan3() {
+	chA := make(chan func(int) int, 0) // @line c3makeA
+	chB := make(chan func(int) int, 0) // @line c3makeB
+	chA <- incr
+	chB <- decr
+	chB <- func(int) int { return 1 }
+	print(chA)   // @pointsto makechan@c3makeA:13
+	print(<-chA) // @pointsto main.incr
+	print(chB)   // @pointsto makechan@c3makeB:13
+	print(<-chB) // @pointsto main.decr | main.chan3$1
+
+	(<-chA)(3)
+}
+
+// @calls main.chan3 -> main.incr
+
+func chan4() {
+	chA := make(chan func(int) int, 0) // @line c4makeA
+	chB := make(chan func(int) int, 0) // @line c4makeB
+
+	select {
+	case chA <- incr:
+	case chB <- decr:
+	case a := <-chA:
+		print(a) // @pointsto main.incr
+	case b := <-chB:
+		print(b) // @pointsto main.decr
+	default:
+		print(chA) // @pointsto makechan@c4makeA:13
+		print(chB) // @pointsto makechan@c4makeB:13
+	}
+
+	for k := range chA {
+		print(k) // @pointsto main.incr
+	}
+	// Exercise constraint generation (regtest for a crash).
+	for _ = range chA {
+	}
+}
+
+// Multi-word channel value in select with multiple receive cases.
+// (Regtest for a crash.)
+func chan5() {
+	type T struct {
+		x *int
+		y interface{}
+	}
+	ch := make(chan T)
+	ch <- T{new(int), incr} // @line ch5new
+	select {
+	case a := <-ch:
+		print(a.x) // @pointsto new@ch5new:13
+		print(a.y) // @types func(x int) int
+	case b := <-ch:
+		print(b.x) // @pointsto new@ch5new:13
+		print(b.y) // @types func(x int) int
+	}
+}
+
+func main() {
+	chan1()
+	chan2()
+	chan3()
+	chan4()
+	chan5()
+}
diff --git a/go/pointer/testdata/chanreflect.go b/go/pointer/testdata/chanreflect.go
new file mode 100644
index 0000000..7d22efe
--- /dev/null
+++ b/go/pointer/testdata/chanreflect.go
@@ -0,0 +1,85 @@
+// +build ignore
+
+package main
+
+import "reflect"
+
+// Test of channels with reflection.
+
+var a, b int
+
+func chanreflect1() {
+	ch := make(chan *int, 0) // @line cr1make
+	crv := reflect.ValueOf(ch)
+	crv.Send(reflect.ValueOf(&a))
+	print(crv.Interface())             // @types chan *int
+	print(crv.Interface().(chan *int)) // @pointsto makechan@cr1make:12
+	print(<-ch)                        // @pointsto main.a
+}
+
+func chanreflect1i() {
+	// Exercises reflect.Value conversions to/from interfaces:
+	// a different code path than for concrete types.
+	ch := make(chan interface{}, 0)
+	reflect.ValueOf(ch).Send(reflect.ValueOf(&a))
+	v := <-ch
+	print(v)        // @types *int
+	print(v.(*int)) // @pointsto main.a
+}
+
+func chanreflect2() {
+	ch := make(chan *int, 0)
+	ch <- &b
+	crv := reflect.ValueOf(ch)
+	r, _ := crv.Recv()
+	print(r.Interface())        // @types *int
+	print(r.Interface().(*int)) // @pointsto main.b
+}
+
+func chanOfRecv() {
+	// MakeChan(<-chan) is a no-op.
+	t := reflect.ChanOf(reflect.RecvDir, reflect.TypeOf(&a))
+	print(reflect.Zero(t).Interface())                      // @types <-chan *int
+	print(reflect.MakeChan(t, 0).Interface().(<-chan *int)) // @pointsto
+	print(reflect.MakeChan(t, 0).Interface().(chan *int))   // @pointsto
+}
+
+func chanOfSend() {
+	// MakeChan(chan<-) is a no-op.
+	t := reflect.ChanOf(reflect.SendDir, reflect.TypeOf(&a))
+	print(reflect.Zero(t).Interface())                      // @types chan<- *int
+	print(reflect.MakeChan(t, 0).Interface().(chan<- *int)) // @pointsto
+	print(reflect.MakeChan(t, 0).Interface().(chan *int))   // @pointsto
+}
+
+func chanOfBoth() {
+	t := reflect.ChanOf(reflect.BothDir, reflect.TypeOf(&a))
+	print(reflect.Zero(t).Interface()) // @types chan *int
+	ch := reflect.MakeChan(t, 0)
+	print(ch.Interface().(chan *int)) // @pointsto <alloc in reflect.MakeChan>
+	ch.Send(reflect.ValueOf(&b))
+	ch.Interface().(chan *int) <- &a
+	r, _ := ch.Recv()
+	print(r.Interface().(*int))         // @pointsto main.a | main.b
+	print(<-ch.Interface().(chan *int)) // @pointsto main.a | main.b
+}
+
+var unknownDir reflect.ChanDir // not a constant
+
+func chanOfUnknown() {
+	// Unknown channel direction: assume all three.
+	// MakeChan only works on the bi-di channel type.
+	t := reflect.ChanOf(unknownDir, reflect.TypeOf(&a))
+	print(reflect.Zero(t).Interface())        // @types <-chan *int | chan<- *int | chan *int
+	print(reflect.MakeChan(t, 0).Interface()) // @types chan *int
+}
+
+func main() {
+	chanreflect1()
+	chanreflect1i()
+	chanreflect2()
+	chanOfRecv()
+	chanOfSend()
+	chanOfBoth()
+	chanOfUnknown()
+}
diff --git a/go/pointer/testdata/chanreflect1.go b/go/pointer/testdata/chanreflect1.go
new file mode 100644
index 0000000..c5e2587
--- /dev/null
+++ b/go/pointer/testdata/chanreflect1.go
@@ -0,0 +1,35 @@
+// +build ignore
+
+package main
+
+import "reflect"
+
+//
+// This test is very sensitive to line-number perturbations!
+
+// Test of channels with reflection.
+
+var a, b int
+
+func chanreflect1() {
+	ch := make(chan *int, 0)
+	crv := reflect.ValueOf(ch)
+	crv.Send(reflect.ValueOf(&a))
+	print(crv.Interface())             // @types chan *int
+	print(crv.Interface().(chan *int)) // @pointsto makechan@testdata/chanreflect.go:15:12
+	print(<-ch)                        // @pointsto main.a
+}
+
+func chanreflect2() {
+	ch := make(chan *int, 0)
+	ch <- &b
+	crv := reflect.ValueOf(ch)
+	r, _ := crv.Recv()
+	print(r.Interface())        // @types *int
+	print(r.Interface().(*int)) // @pointsto main.b
+}
+
+func main() {
+	chanreflect1()
+	chanreflect2()
+}
diff --git a/go/pointer/testdata/context.go b/go/pointer/testdata/context.go
new file mode 100644
index 0000000..ed616e7
--- /dev/null
+++ b/go/pointer/testdata/context.go
@@ -0,0 +1,48 @@
+// +build ignore
+
+package main
+
+// Test of context-sensitive treatment of certain function calls,
+// e.g. static calls to simple accessor methods.
+
+var a, b int
+
+type T struct{ x *int }
+
+func (t *T) SetX(x *int) { t.x = x }
+func (t *T) GetX() *int  { return t.x }
+
+func context1() {
+	var t1, t2 T
+	t1.SetX(&a)
+	t2.SetX(&b)
+	print(t1.GetX()) // @pointsto main.a
+	print(t2.GetX()) // @pointsto main.b
+}
+
+func context2() {
+	id := func(x *int) *int {
+		print(x) // @pointsto main.a | main.b
+		return x
+	}
+	print(id(&a)) // @pointsto main.a
+	print(id(&b)) // @pointsto main.b
+
+	// Same again, but anon func has free vars.
+	var c int // @line context2c
+	id2 := func(x *int) (*int, *int) {
+		print(x) // @pointsto main.a | main.b
+		return x, &c
+	}
+	p, q := id2(&a)
+	print(p) // @pointsto main.a
+	print(q) // @pointsto c@context2c:6
+	r, s := id2(&b)
+	print(r) // @pointsto main.b
+	print(s) // @pointsto c@context2c:6
+}
+
+func main() {
+	context1()
+	context2()
+}
diff --git a/go/pointer/testdata/conv.go b/go/pointer/testdata/conv.go
new file mode 100644
index 0000000..692f0ce
--- /dev/null
+++ b/go/pointer/testdata/conv.go
@@ -0,0 +1,63 @@
+// +build ignore
+
+package main
+
+import "unsafe"
+
+var a int
+
+func conv1() {
+	// Conversions of channel direction.
+	ch := make(chan int)    // @line c1make
+	print((<-chan int)(ch)) // @pointsto makechan@c1make:12
+	print((chan<- int)(ch)) // @pointsto makechan@c1make:12
+}
+
+func conv2() {
+	// string -> []byte/[]rune conversion
+	s := "foo"
+	ba := []byte(s) // @line c2ba
+	ra := []rune(s) // @line c2ra
+	print(ba)       // @pointsto convert@c2ba:14
+	print(ra)       // @pointsto convert@c2ra:14
+}
+
+func conv3() {
+	// Conversion of same underlying types.
+	type PI *int
+	pi := PI(&a)
+	print(pi) // @pointsto main.a
+
+	pint := (*int)(pi)
+	print(pint) // @pointsto main.a
+
+	// Conversions between pointers to identical base types.
+	var y *PI = &pi
+	var x **int = (**int)(y)
+	print(*x) // @pointsto main.a
+	print(*y) // @pointsto main.a
+	y = (*PI)(x)
+	print(*y) // @pointsto main.a
+}
+
+func conv4() {
+	// Handling of unsafe.Pointer conversion is unsound:
+	// we lose the alias to main.a and get something like new(int) instead.
+	p := (*int)(unsafe.Pointer(&a)) // @line c2p
+	print(p)                        // @pointsto convert@c2p:13
+}
+
+// Regression test for b/8231.
+func conv5() {
+	type P unsafe.Pointer
+	var i *struct{}
+	_ = P(i)
+}
+
+func main() {
+	conv1()
+	conv2()
+	conv3()
+	conv4()
+	conv5()
+}
diff --git a/go/pointer/testdata/finalizer.go b/go/pointer/testdata/finalizer.go
new file mode 100644
index 0000000..97f25c9
--- /dev/null
+++ b/go/pointer/testdata/finalizer.go
@@ -0,0 +1,89 @@
+package main
+
+import "runtime"
+
+func final1a(x *int) int {
+	print(x) // @pointsto new@newint:10
+	return *x
+}
+
+func final1b(x *bool) {
+	print(x) // @pointsto
+}
+
+func runtimeSetFinalizer1() {
+	x := new(int)                    // @line newint
+	runtime.SetFinalizer(x, final1a) // ok: final1a's result is ignored
+	runtime.SetFinalizer(x, final1b) // param type mismatch: no effect
+}
+
+// @calls main.runtimeSetFinalizer1 -> main.final1a
+// @calls main.runtimeSetFinalizer1 -> main.final1b
+
+func final2a(x *bool) {
+	print(x) // @pointsto new@newbool1:10 | new@newbool2:10
+}
+
+func final2b(x *bool) {
+	print(x) // @pointsto new@newbool1:10 | new@newbool2:10
+}
+
+func runtimeSetFinalizer2() {
+	x := new(bool) // @line newbool1
+	f := final2a
+	if unknown {
+		x = new(bool) // @line newbool2
+		f = final2b
+	}
+	runtime.SetFinalizer(x, f)
+}
+
+// @calls main.runtimeSetFinalizer2 -> main.final2a
+// @calls main.runtimeSetFinalizer2 -> main.final2b
+
+type T int
+
+func (t *T) finalize() {
+	print(t) // @pointsto new@final3:10
+}
+
+func runtimeSetFinalizer3() {
+	x := new(T) // @line final3
+	runtime.SetFinalizer(x, (*T).finalize)
+}
+
+// @calls main.runtimeSetFinalizer3 -> (*main.T).finalize$thunk
+
+// I hope I never live to see this code in the wild.
+var setFinalizer = runtime.SetFinalizer
+
+func final4(x *int) {
+	print(x) // @pointsto new@finalIndirect:10
+}
+
+func runtimeSetFinalizerIndirect() {
+	// In an indirect call, the shared contour for SetFinalizer is
+	// used, i.e. the call is not inlined and appears in the call graph.
+	x := new(int) // @line finalIndirect
+	setFinalizer(x, final4)
+}
+
+// Exercise the elimination of SetFinalizer
+// constraints with non-pointer operands.
+func runtimeSetFinalizerNonpointer() {
+	runtime.SetFinalizer(nil, (*T).finalize) // x is a non-pointer
+	runtime.SetFinalizer((*T).finalize, nil) // f is a non-pointer
+}
+
+// @calls main.runtimeSetFinalizerIndirect -> runtime.SetFinalizer
+// @calls runtime.SetFinalizer -> main.final4
+
+func main() {
+	runtimeSetFinalizer1()
+	runtimeSetFinalizer2()
+	runtimeSetFinalizer3()
+	runtimeSetFinalizerIndirect()
+	runtimeSetFinalizerNonpointer()
+}
+
+var unknown bool // defeat dead-code elimination
diff --git a/go/pointer/testdata/flow.go b/go/pointer/testdata/flow.go
new file mode 100644
index 0000000..6fb599e
--- /dev/null
+++ b/go/pointer/testdata/flow.go
@@ -0,0 +1,63 @@
+// +build ignore
+
+package main
+
+// Demonstration of directionality of flow edges.
+
+func f1() {}
+func f2() {}
+
+var somepred bool
+
+// Tracking functions.
+func flow1() {
+	s := f1
+	p := f2
+	q := p
+	r := q
+	if somepred {
+		r = s
+	}
+	print(s) // @pointsto main.f1
+	print(p) // @pointsto main.f2
+	print(q) // @pointsto main.f2
+	print(r) // @pointsto main.f1 | main.f2
+}
+
+// Tracking concrete types in interfaces.
+func flow2() {
+	var s interface{} = 1
+	var p interface{} = "foo"
+	q := p
+	r := q
+	if somepred {
+		r = s
+	}
+	print(s) // @types int
+	print(p) // @types string
+	print(q) // @types string
+	print(r) // @types int | string
+}
+
+var g1, g2 int
+
+// Tracking addresses of globals.
+func flow3() {
+	s := &g1
+	p := &g2
+	q := p
+	r := q
+	if somepred {
+		r = s
+	}
+	print(s) // @pointsto main.g1
+	print(p) // @pointsto main.g2
+	print(q) // @pointsto main.g2
+	print(r) // @pointsto main.g2 | main.g1
+}
+
+func main() {
+	flow1()
+	flow2()
+	flow3()
+}
diff --git a/go/pointer/testdata/fmtexcerpt.go b/go/pointer/testdata/fmtexcerpt.go
new file mode 100644
index 0000000..ee2a0e7
--- /dev/null
+++ b/go/pointer/testdata/fmtexcerpt.go
@@ -0,0 +1,42 @@
+// +build ignore
+
+// This is a slice of the fmt package.
+
+package main
+
+type pp struct {
+	field interface{}
+}
+
+func newPrinter() *pp {
+	return new(pp)
+}
+
+func Fprintln(a ...interface{}) {
+	p := newPrinter()
+	p.doPrint(a, true, true)
+}
+
+func Println(a ...interface{}) {
+	Fprintln(a...)
+}
+
+func (p *pp) doPrint(a []interface{}, addspace, addnewline bool) {
+	print(a[0]) // @types S | string
+	stringer := a[0].(interface {
+		String() string
+	})
+
+	stringer.String()
+	print(stringer) // @types S
+}
+
+type S int
+
+func (S) String() string { return "" }
+
+func main() {
+	Println("Hello, World!", S(0))
+}
+
+// @calls (*main.pp).doPrint -> (main.S).String
diff --git a/go/pointer/testdata/func.go b/go/pointer/testdata/func.go
new file mode 100644
index 0000000..2155f8e
--- /dev/null
+++ b/go/pointer/testdata/func.go
@@ -0,0 +1,205 @@
+// +build ignore
+
+package main
+
+var a, b, c int
+
+var unknown bool // defeat dead-code elimination
+
+func func1() {
+	var h int // @line f1h
+	f := func(x *int) *int {
+		if unknown {
+			return &b
+		}
+		return x
+	}
+
+	// FV(g) = {f, h}
+	g := func(x *int) *int {
+		if unknown {
+			return &h
+		}
+		return f(x)
+	}
+
+	print(g(&a)) // @pointsto main.a | main.b | h@f1h:6
+	print(f(&a)) // @pointsto main.a | main.b
+	print(&a)    // @pointsto main.a
+}
+
+// @calls main.func1 -> main.func1$2
+// @calls main.func1 -> main.func1$1
+// @calls main.func1$2 ->  main.func1$1
+
+func func2() {
+	var x, y *int
+	defer func() {
+		x = &a
+	}()
+	go func() {
+		y = &b
+	}()
+	print(x) // @pointsto main.a
+	print(y) // @pointsto main.b
+}
+
+func func3() {
+	x, y := func() (x, y *int) {
+		x = &a
+		y = &b
+		if unknown {
+			return nil, &c
+		}
+		return
+	}()
+	print(x) // @pointsto main.a
+	print(y) // @pointsto main.b | main.c
+}
+
+func swap(x, y *int) (*int, *int) { // @line swap
+	print(&x) // @pointsto x@swap:11
+	print(x)  // @pointsto makeslice[*]@func4make:11
+	print(&y) // @pointsto y@swap:14
+	print(y)  // @pointsto j@f4j:5
+	return y, x
+}
+
+func func4() {
+	a := make([]int, 10) // @line func4make
+	i, j := 123, 456     // @line f4j
+	_ = i
+	p, q := swap(&a[3], &j)
+	print(p) // @pointsto j@f4j:5
+	print(q) // @pointsto makeslice[*]@func4make:11
+
+	f := &b
+	print(f) // @pointsto main.b
+}
+
+type T int
+
+func (t *T) f(x *int) *int {
+	print(t) // @pointsto main.a
+	print(x) // @pointsto main.c
+	return &b
+}
+
+func (t *T) g(x *int) *int {
+	print(t) // @pointsto main.a
+	print(x) // @pointsto main.b
+	return &c
+}
+
+func (t *T) h(x *int) *int {
+	print(t) // @pointsto main.a
+	print(x) // @pointsto main.b
+	return &c
+}
+
+var h func(*T, *int) *int
+
+func func5() {
+	// Static call of method.
+	t := (*T)(&a)
+	print(t.f(&c)) // @pointsto main.b
+
+	// Static call of method as function
+	print((*T).g(t, &b)) // @pointsto main.c
+
+	// Dynamic call (not invoke) of method.
+	h = (*T).h
+	print(h(t, &b)) // @pointsto main.c
+}
+
+// @calls main.func5 -> (*main.T).f
+// @calls main.func5 -> (*main.T).g$thunk
+// @calls main.func5 -> (*main.T).h$thunk
+
+func func6() {
+	A := &a
+	f := func() *int {
+		return A // (free variable)
+	}
+	print(f()) // @pointsto main.a
+}
+
+// @calls main.func6 -> main.func6$1
+
+type I interface {
+	f()
+}
+
+type D struct{}
+
+func (D) f() {}
+
+func func7() {
+	var i I = D{}
+	imethodClosure := i.f
+	imethodClosure()
+	// @calls main.func7 -> (main.I).f$bound
+	// @calls (main.I).f$bound -> (main.D).f
+
+	var d D
+	cmethodClosure := d.f
+	cmethodClosure()
+	// @calls main.func7 -> (main.D).f$bound
+	// @calls (main.D).f$bound ->(main.D).f
+
+	methodExpr := D.f
+	methodExpr(d)
+	// @calls main.func7 -> (main.D).f$thunk
+}
+
+func func8(x ...int) {
+	print(&x[0]) // @pointsto varargs[*]@varargs:15
+}
+
+type E struct {
+	x1, x2, x3, x4, x5 *int
+}
+
+func (e E) f() {}
+
+func func9() {
+	// Regression test for bug reported by Jon Valdes on golang-dev, Jun 19 2014.
+	// The receiver of a bound method closure may be of a multi-node type, E.
+	// valueNode was reserving only a single node for it, so the
+	// nodes used by the immediately following constraints
+	// (e.g. param 'i') would get clobbered.
+
+	var e E
+	e.x1 = &a
+	e.x2 = &a
+	e.x3 = &a
+	e.x4 = &a
+	e.x5 = &a
+
+	_ = e.f // form a closure---must reserve sizeof(E) nodes
+
+	func(i I) {
+		i.f() // must not crash the solver
+	}(new(D))
+
+	print(e.x1) // @pointsto main.a
+	print(e.x2) // @pointsto main.a
+	print(e.x3) // @pointsto main.a
+	print(e.x4) // @pointsto main.a
+	print(e.x5) // @pointsto main.a
+}
+
+func main() {
+	func1()
+	func2()
+	func3()
+	func4()
+	func5()
+	func6()
+	func7()
+	func8(1, 2, 3) // @line varargs
+	func9()
+}
+
+// @calls <root> -> main.main
+// @calls <root> -> main.init
diff --git a/go/pointer/testdata/funcreflect.go b/go/pointer/testdata/funcreflect.go
new file mode 100644
index 0000000..a0a9a5f
--- /dev/null
+++ b/go/pointer/testdata/funcreflect.go
@@ -0,0 +1,130 @@
+// +build ignore
+
+package main
+
+import "reflect"
+
+var zero, a, b int
+var false2 bool
+
+func f(p *int, q hasF) *int {
+	print(p)      // @pointsto main.a
+	print(q)      // @types *T
+	print(q.(*T)) // @pointsto new@newT1:22
+	return &b
+}
+
+func g(p *bool) (*int, *bool, hasF) {
+	return &b, p, new(T) // @line newT2
+}
+
+func reflectValueCall() {
+	rvf := reflect.ValueOf(f)
+	res := rvf.Call([]reflect.Value{
+		// argument order is not significant:
+		reflect.ValueOf(new(T)), // @line newT1
+		reflect.ValueOf(&a),
+	})
+	print(res[0].Interface())        // @types *int
+	print(res[0].Interface().(*int)) // @pointsto main.b
+}
+
+// @calls main.reflectValueCall -> main.f
+
+func reflectValueCallIndirect() {
+	rvf := reflect.ValueOf(g)
+	call := rvf.Call // kids, don't try this at home
+
+	// Indirect call uses shared contour.
+	//
+	// Also notice that argument position doesn't matter, and args
+	// of inappropriate type (e.g. 'a') are ignored.
+	res := call([]reflect.Value{
+		reflect.ValueOf(&a),
+		reflect.ValueOf(&false2),
+	})
+	res0 := res[0].Interface()
+	print(res0)         // @types *int | *bool | *T
+	print(res0.(*int))  // @pointsto main.b
+	print(res0.(*bool)) // @pointsto main.false2
+	print(res0.(hasF))  // @types *T
+	print(res0.(*T))    // @pointsto new@newT2:19
+}
+
+// @calls main.reflectValueCallIndirect -> (reflect.Value).Call$bound
+// @calls (reflect.Value).Call$bound -> main.g
+
+func reflectTypeInOut() {
+	var f func(float64, bool) (string, int)
+	print(reflect.Zero(reflect.TypeOf(f).In(0)).Interface())    // @types float64
+	print(reflect.Zero(reflect.TypeOf(f).In(1)).Interface())    // @types bool
+	print(reflect.Zero(reflect.TypeOf(f).In(-1)).Interface())   // @types float64 | bool
+	print(reflect.Zero(reflect.TypeOf(f).In(zero)).Interface()) // @types float64 | bool
+
+	print(reflect.Zero(reflect.TypeOf(f).Out(0)).Interface()) // @types string
+	print(reflect.Zero(reflect.TypeOf(f).Out(1)).Interface()) // @types int
+	print(reflect.Zero(reflect.TypeOf(f).Out(2)).Interface()) // @types
+
+	print(reflect.Zero(reflect.TypeOf(3).Out(0)).Interface()) // @types
+}
+
+type hasF interface {
+	F()
+}
+
+type T struct{}
+
+func (T) F()    {}
+func (T) g(int) {}
+
+type U struct{}
+
+func (U) F(int)    {}
+func (U) g(string) {}
+
+type I interface {
+	f()
+}
+
+var nonconst string
+
+func reflectTypeMethodByName() {
+	TU := reflect.TypeOf([]interface{}{T{}, U{}}[0])
+	print(reflect.Zero(TU)) // @types T | U
+
+	F, _ := TU.MethodByName("F")
+	print(reflect.Zero(F.Type)) // @types func(T) | func(U, int)
+	print(F.Func)               // @pointsto (main.T).F | (main.U).F
+
+	g, _ := TU.MethodByName("g")
+	print(reflect.Zero(g.Type)) // @types func(T, int) | func(U, string)
+	print(g.Func)               // @pointsto (main.T).g | (main.U).g
+
+	// Non-literal method names are treated less precisely.
+	U := reflect.TypeOf(U{})
+	X, _ := U.MethodByName(nonconst)
+	print(reflect.Zero(X.Type)) // @types func(U, int) | func(U, string)
+	print(X.Func)               // @pointsto (main.U).F | (main.U).g
+
+	// Interface methods.
+	rThasF := reflect.TypeOf(new(hasF)).Elem()
+	print(reflect.Zero(rThasF)) // @types hasF
+	F2, _ := rThasF.MethodByName("F")
+	print(reflect.Zero(F2.Type)) // @types func()
+	print(F2.Func)               // @pointsto
+
+}
+
+func reflectTypeMethod() {
+	m := reflect.TypeOf(T{}).Method(0)
+	print(reflect.Zero(m.Type)) // @types func(T) | func(T, int)
+	print(m.Func)               // @pointsto (main.T).F | (main.T).g
+}
+
+func main() {
+	reflectValueCall()
+	reflectValueCallIndirect()
+	reflectTypeInOut()
+	reflectTypeMethodByName()
+	reflectTypeMethod()
+}
diff --git a/go/pointer/testdata/hello.go b/go/pointer/testdata/hello.go
new file mode 100644
index 0000000..b81784b
--- /dev/null
+++ b/go/pointer/testdata/hello.go
@@ -0,0 +1,27 @@
+// +build ignore
+
+package main
+
+import (
+	"fmt"
+	"os"
+)
+
+type S int
+
+var theS S
+
+func (s *S) String() string {
+	print(s) // @pointsto main.theS
+	return ""
+}
+
+func main() {
+	// os.Args is considered intrinsically allocated,
+	// but may also be set explicitly (e.g. on Windows), hence '...'.
+	print(os.Args) // @pointsto <command-line args> | ...
+	fmt.Println("Hello, World!", &theS)
+}
+
+// @calls main.main               -> fmt.Println
+// @calls (*fmt.pp).handleMethods -> (*main.S).String
diff --git a/go/pointer/testdata/interfaces.go b/go/pointer/testdata/interfaces.go
new file mode 100644
index 0000000..91c0fa9
--- /dev/null
+++ b/go/pointer/testdata/interfaces.go
@@ -0,0 +1,152 @@
+// +build ignore
+
+package main
+
+type I interface {
+	f()
+}
+
+type C int
+
+func (*C) f() {}
+
+type D struct{ ptr *int }
+
+func (D) f() {}
+
+type E struct{}
+
+func (*E) f() {}
+
+var a, b int
+
+var unknown bool // defeat dead-code elimination
+
+func interface1() {
+	var i interface{} = &a
+	var j interface{} = D{&b}
+	k := j
+	if unknown {
+		k = i
+	}
+
+	print(i) // @types *int
+	print(j) // @types D
+	print(k) // @types *int | D
+
+	print(i.(*int)) // @pointsto main.a
+	print(j.(*int)) // @pointsto
+	print(k.(*int)) // @pointsto main.a
+
+	print(i.(D).ptr) // @pointsto
+	print(j.(D).ptr) // @pointsto main.b
+	print(k.(D).ptr) // @pointsto main.b
+}
+
+func interface2() {
+	var i I = (*C)(&a)
+	var j I = D{&a}
+	k := j
+	if unknown {
+		k = i
+	}
+
+	print(i) // @types *C
+	print(j) // @types D
+	print(k) // @types *C | D
+	print(k) // @pointsto makeinterface:main.D | makeinterface:*main.C
+
+	k.f()
+	// @calls main.interface2 -> (*main.C).f
+	// @calls main.interface2 -> (main.D).f
+
+	print(i.(*C))    // @pointsto main.a
+	print(j.(D).ptr) // @pointsto main.a
+	print(k.(*C))    // @pointsto main.a
+
+	switch x := k.(type) {
+	case *C:
+		print(x) // @pointsto main.a
+	case D:
+		print(x.ptr) // @pointsto main.a
+	case *E:
+		print(x) // @pointsto
+	}
+}
+
+func interface3() {
+	// There should be no backflow of concrete types from the type-switch to x.
+	var x interface{} = 0
+	print(x) // @types int
+	switch x.(type) {
+	case int:
+	case string:
+	}
+}
+
+func interface4() {
+	var i interface{} = D{&a}
+	if unknown {
+		i = 123
+	}
+
+	print(i) // @types int | D
+
+	j := i.(I)       // interface narrowing type-assertion
+	print(j)         // @types D
+	print(j.(D).ptr) // @pointsto main.a
+
+	var l interface{} = j // interface widening assignment.
+	print(l)              // @types D
+	print(l.(D).ptr)      // @pointsto main.a
+
+	m := j.(interface{}) // interface widening type-assertion.
+	print(m)             // @types D
+	print(m.(D).ptr)     // @pointsto main.a
+}
+
+// Interface method calls and value flow:
+
+type J interface {
+	f(*int) *int
+}
+
+type P struct {
+	x int
+}
+
+func (p *P) f(pi *int) *int {
+	print(p)  // @pointsto p@i5p:6
+	print(pi) // @pointsto i@i5i:6
+	return &p.x
+}
+
+func interface5() {
+	var p P // @line i5p
+	var j J = &p
+	var i int      // @line i5i
+	print(j.f(&i)) // @pointsto p.x@i5p:6
+	print(&i)      // @pointsto i@i5i:6
+
+	print(j) // @pointsto makeinterface:*main.P
+}
+
+// @calls main.interface5 -> (*main.P).f
+
+func interface6() {
+	f := I.f
+	print(f) // @pointsto (main.I).f$thunk
+	f(new(struct{ D }))
+}
+
+// @calls main.interface6 -> (main.I).f$thunk
+// @calls (main.I).f$thunk -> (*struct{main.D}).f
+
+func main() {
+	interface1()
+	interface2()
+	interface3()
+	interface4()
+	interface5()
+	interface6()
+}
diff --git a/go/pointer/testdata/issue9002.go b/go/pointer/testdata/issue9002.go
new file mode 100644
index 0000000..b7c2c61
--- /dev/null
+++ b/go/pointer/testdata/issue9002.go
@@ -0,0 +1,17 @@
+package main
+
+func main() {
+	// Regression test for golang issue 9002.
+	//
+	// The two-result "value,ok" receive operation generated a
+	// too-wide constraint loading (value int, ok bool), not bool,
+	// from the channel.
+	//
+	// This bug manifested itself in an out-of-bounds array access
+	// when the makechan object was the highest-numbered node, as in
+	// this program.
+	//
+	// In more realistic programs it silently resulted in bogus
+	// constraints.
+	_, _ = <-make(chan int)
+}
diff --git a/go/pointer/testdata/mapreflect.go b/go/pointer/testdata/mapreflect.go
new file mode 100644
index 0000000..bc5e7e6
--- /dev/null
+++ b/go/pointer/testdata/mapreflect.go
@@ -0,0 +1,117 @@
+// +build ignore
+
+package main
+
+// Test of maps with reflection.
+
+import "reflect"
+
+var a int
+var b bool
+
+func reflectMapKeysIndex() {
+	m := make(map[*int]*bool) // @line mr1make
+	m[&a] = &b
+
+	mrv := reflect.ValueOf(m)
+	print(mrv.Interface())                  // @types map[*int]*bool
+	print(mrv.Interface().(map[*int]*bool)) // @pointsto makemap@mr1make:11
+	print(mrv)                              // @pointsto makeinterface:map[*int]*bool
+	print(mrv)                              // @types map[*int]*bool
+
+	keys := mrv.MapKeys()
+	print(keys) // @pointsto <alloc in (reflect.Value).MapKeys>
+	for _, k := range keys {
+		print(k)                    // @pointsto <alloc in (reflect.Value).MapKeys>
+		print(k)                    // @types *int
+		print(k.Interface())        // @types *int
+		print(k.Interface().(*int)) // @pointsto main.a
+
+		v := mrv.MapIndex(k)
+		print(v.Interface())         // @types *bool
+		print(v.Interface().(*bool)) // @pointsto main.b
+	}
+}
+
+func reflectSetMapIndex() {
+	m := make(map[*int]*bool)
+	mrv := reflect.ValueOf(m)
+	mrv.SetMapIndex(reflect.ValueOf(&a), reflect.ValueOf(&b))
+
+	print(m[nil]) // @pointsto main.b
+
+	for _, k := range mrv.MapKeys() {
+		print(k.Interface())        // @types *int
+		print(k.Interface().(*int)) // @pointsto main.a
+	}
+
+	tmap := reflect.TypeOf(m)
+	// types.EvalNode won't let us refer to non-exported types:
+	// print(tmap) // #@types *reflect.rtype
+	print(tmap) // @pointsto map[*int]*bool
+
+	zmap := reflect.Zero(tmap)
+	print(zmap)             // @pointsto <alloc in reflect.Zero>
+	print(zmap.Interface()) // @pointsto <alloc in reflect.Zero>
+
+	print(tmap.Key())                            // @pointsto *int
+	print(tmap.Elem())                           // @pointsto *bool
+	print(reflect.Zero(tmap.Key()))              // @pointsto <alloc in reflect.Zero>
+	print(reflect.Zero(tmap.Key()).Interface())  // @pointsto <alloc in reflect.Zero>
+	print(reflect.Zero(tmap.Key()).Interface())  // @types *int
+	print(reflect.Zero(tmap.Elem()))             // @pointsto <alloc in reflect.Zero>
+	print(reflect.Zero(tmap.Elem()).Interface()) // @pointsto <alloc in reflect.Zero>
+	print(reflect.Zero(tmap.Elem()).Interface()) // @types *bool
+}
+
+func reflectSetMapIndexInterface() {
+	// Exercises reflect.Value conversions to/from interfaces:
+	// a different code path than for concrete types.
+	m := make(map[interface{}]interface{})
+	reflect.ValueOf(m).SetMapIndex(reflect.ValueOf(&a), reflect.ValueOf(&b))
+	for k, v := range m {
+		print(k)         // @types *int
+		print(k.(*int))  // @pointsto main.a
+		print(v)         // @types *bool
+		print(v.(*bool)) // @pointsto main.b
+	}
+}
+
+func reflectSetMapIndexAssignable() {
+	// SetMapIndex performs implicit assignability conversions.
+	type I *int
+	type J *int
+
+	str := reflect.ValueOf("")
+
+	// *int is assignable to I.
+	m1 := make(map[string]I)
+	reflect.ValueOf(m1).SetMapIndex(str, reflect.ValueOf(new(int))) // @line int
+	print(m1[""])                                                   // @pointsto new@int:58
+
+	// I is assignable to I.
+	m2 := make(map[string]I)
+	reflect.ValueOf(m2).SetMapIndex(str, reflect.ValueOf(I(new(int)))) // @line I
+	print(m2[""])                                                      // @pointsto new@I:60
+
+	// J is not assignable to I.
+	m3 := make(map[string]I)
+	reflect.ValueOf(m3).SetMapIndex(str, reflect.ValueOf(J(new(int))))
+	print(m3[""]) // @pointsto
+}
+
+func reflectMakeMap() {
+	t := reflect.TypeOf(map[*int]*bool(nil))
+	v := reflect.MakeMap(t)
+	print(v) // @types map[*int]*bool
+	print(v) // @pointsto <alloc in reflect.MakeMap>
+}
+
+func main() {
+	reflectMapKeysIndex()
+	reflectSetMapIndex()
+	reflectSetMapIndexInterface()
+	reflectSetMapIndexAssignable()
+	reflectMakeMap()
+	// TODO(adonovan): reflect.MapOf(Type)
+}
diff --git a/go/pointer/testdata/maps.go b/go/pointer/testdata/maps.go
new file mode 100644
index 0000000..6f3751d
--- /dev/null
+++ b/go/pointer/testdata/maps.go
@@ -0,0 +1,51 @@
+// +build ignore
+
+package main
+
+// Test of maps.
+
+var a, b, c int
+
+func maps1() {
+	m1 := map[*int]*int{&a: &b} // @line m1m1
+	m2 := make(map[*int]*int)   // @line m1m2
+	m2[&b] = &a
+
+	print(m1[nil]) // @pointsto main.b | main.c
+	print(m2[nil]) // @pointsto main.a
+
+	print(m1) // @pointsto makemap@m1m1:21
+	print(m2) // @pointsto makemap@m1m2:12
+
+	m1[&b] = &c
+
+	for k, v := range m1 {
+		print(k) // @pointsto main.a | main.b
+		print(v) // @pointsto main.b | main.c
+	}
+
+	for k, v := range m2 {
+		print(k) // @pointsto main.b
+		print(v) // @pointsto main.a
+	}
+
+	// Lookup doesn't create any aliases.
+	print(m2[&c]) // @pointsto main.a
+	if _, ok := m2[&a]; ok {
+		print(m2[&c]) // @pointsto main.a
+	}
+}
+
+func maps2() {
+	m1 := map[*int]*int{&a: &b}
+	m2 := map[*int]*int{&b: &c}
+	_ = []map[*int]*int{m1, m2} // (no spurious merging of m1, m2)
+
+	print(m1[nil]) // @pointsto main.b
+	print(m2[nil]) // @pointsto main.c
+}
+
+func main() {
+	maps1()
+	maps2()
+}
diff --git a/go/pointer/testdata/panic.go b/go/pointer/testdata/panic.go
new file mode 100644
index 0000000..ee8a766
--- /dev/null
+++ b/go/pointer/testdata/panic.go
@@ -0,0 +1,36 @@
+// +build ignore
+
+package main
+
+// Test of value flow from panic() to recover().
+// We model them as stores/loads of a global location.
+// We ignore concrete panic types originating from the runtime.
+
+var someval int
+
+type myPanic struct{}
+
+func f(int) {}
+
+func g() string { return "" }
+
+func deadcode() {
+	panic(123) // not reached
+}
+
+func main() {
+	switch someval {
+	case 0:
+		panic("oops")
+	case 1:
+		panic(myPanic{})
+	case 2:
+		panic(f)
+	case 3:
+		panic(g)
+	}
+	ex := recover()
+	print(ex)                 // @types myPanic | string | func(int) | func() string
+	print(ex.(func(int)))     // @pointsto main.f
+	print(ex.(func() string)) // @pointsto main.g
+}
diff --git a/go/pointer/testdata/recur.go b/go/pointer/testdata/recur.go
new file mode 100644
index 0000000..4c7229d
--- /dev/null
+++ b/go/pointer/testdata/recur.go
@@ -0,0 +1,11 @@
+// +build ignore
+
+package main
+
+// Analysis abstraction of recursive calls is finite.
+
+func main() {
+	main()
+}
+
+// @calls main.main -> main.main
diff --git a/go/pointer/testdata/reflect.go b/go/pointer/testdata/reflect.go
new file mode 100644
index 0000000..6b8d0f2
--- /dev/null
+++ b/go/pointer/testdata/reflect.go
@@ -0,0 +1,115 @@
+// +build ignore
+
+package main
+
+import "reflect"
+import "unsafe"
+
+var a, b int
+var unknown bool
+
+func reflectIndirect() {
+	ptr := &a
+	// Pointer:
+	print(reflect.Indirect(reflect.ValueOf(&ptr)).Interface().(*int)) // @pointsto main.a
+	// Non-pointer:
+	print(reflect.Indirect(reflect.ValueOf([]*int{ptr})).Interface().([]*int)[0]) // @pointsto main.a
+}
+
+func reflectNewAt() {
+	var x [8]byte
+	print(reflect.NewAt(reflect.TypeOf(3), unsafe.Pointer(&x)).Interface()) // @types *int
+}
+
+// @warning "unsound: main.reflectNewAt contains a reflect.NewAt.. call"
+
+func reflectTypeOf() {
+	t := reflect.TypeOf(3)
+	if unknown {
+		t = reflect.TypeOf("foo")
+	}
+	// TODO(adonovan): make types.Eval let us refer to unexported types.
+	print(t)                             // #@types *reflect.rtype
+	print(reflect.Zero(t).Interface())   // @types int | string
+	newint := reflect.New(t).Interface() // @line rtonew
+	print(newint)                        // @types *int | *string
+	print(newint.(*int))                 // @pointsto <alloc in reflect.New>
+	print(newint.(*string))              // @pointsto <alloc in reflect.New>
+}
+
+func reflectTypeElem() {
+	print(reflect.Zero(reflect.TypeOf(&a).Elem()).Interface())                       // @types int
+	print(reflect.Zero(reflect.TypeOf([]string{}).Elem()).Interface())               // @types string
+	print(reflect.Zero(reflect.TypeOf(make(chan bool)).Elem()).Interface())          // @types bool
+	print(reflect.Zero(reflect.TypeOf(make(map[string]float64)).Elem()).Interface()) // @types float64
+	print(reflect.Zero(reflect.TypeOf([3]complex64{}).Elem()).Interface())           // @types complex64
+	print(reflect.Zero(reflect.TypeOf(3).Elem()).Interface())                        // @types
+	print(reflect.Zero(reflect.TypeOf(new(interface{})).Elem()))                     // @types interface{}
+	print(reflect.Zero(reflect.TypeOf(new(interface{})).Elem()).Interface())         // @types
+}
+
+// reflect.Values within reflect.Values.
+func metareflection() {
+	// "box" a *int twice, unbox it twice.
+	v0 := reflect.ValueOf(&a)
+	print(v0)                              // @types *int
+	v1 := reflect.ValueOf(v0)              // box
+	print(v1)                              // @types reflect.Value
+	v2 := reflect.ValueOf(v1)              // box
+	print(v2)                              // @types reflect.Value
+	v1a := v2.Interface().(reflect.Value)  // unbox
+	print(v1a)                             // @types reflect.Value
+	v0a := v1a.Interface().(reflect.Value) // unbox
+	print(v0a)                             // @types *int
+	print(v0a.Interface().(*int))          // @pointsto main.a
+
+	// "box" an interface{} lvalue twice, unbox it twice.
+	var iface interface{} = 3
+	x0 := reflect.ValueOf(&iface).Elem()
+	print(x0)                              // @types interface{}
+	x1 := reflect.ValueOf(x0)              // box
+	print(x1)                              // @types reflect.Value
+	x2 := reflect.ValueOf(x1)              // box
+	print(x2)                              // @types reflect.Value
+	x1a := x2.Interface().(reflect.Value)  // unbox
+	print(x1a)                             // @types reflect.Value
+	x0a := x1a.Interface().(reflect.Value) // unbox
+	print(x0a)                             // @types interface{}
+	print(x0a.Interface())                 // @types int
+}
+
+type T struct{}
+
+// When the output of a type constructor flows to its input, we must
+// bound the set of types created to ensure termination of the algorithm.
+func typeCycle() {
+	t := reflect.TypeOf(0)
+	u := reflect.TypeOf("")
+	v := reflect.TypeOf(T{})
+	for unknown {
+		t = reflect.PtrTo(t)
+		t = reflect.SliceOf(t)
+
+		u = reflect.SliceOf(u)
+
+		if unknown {
+			v = reflect.ChanOf(reflect.BothDir, v)
+		} else {
+			v = reflect.PtrTo(v)
+		}
+	}
+
+	// Type height is bounded to about 4 map/slice/chan/pointer constructors.
+	print(reflect.Zero(t).Interface()) // @types int | []*int | []*[]*int
+	print(reflect.Zero(u).Interface()) // @types string | []string | [][]string | [][][]string | [][][][]string
+	print(reflect.Zero(v).Interface()) // @types T | *T | **T | ***T | ****T | chan T | *chan T | **chan T | chan *T | *chan *T | chan **T | chan ***T | chan chan T | chan *chan T | chan chan *T
+}
+
+func main() {
+	reflectIndirect()
+	reflectNewAt()
+	reflectTypeOf()
+	reflectTypeElem()
+	metareflection()
+	typeCycle()
+}
diff --git a/go/pointer/testdata/rtti.go b/go/pointer/testdata/rtti.go
new file mode 100644
index 0000000..826936d
--- /dev/null
+++ b/go/pointer/testdata/rtti.go
@@ -0,0 +1,29 @@
+package main
+
+// Regression test for oracle crash
+// https://code.google.com/p/go/issues/detail?id=6605
+//
+// Using reflection, methods may be called on types that are not the
+// operand of any ssa.MakeInterface instruction.  In this example,
+// (Y).F is called by deriving the type Y from *Y.  Prior to the fix,
+// no RTTI (or method set) for type Y was included in the program, so
+// the F() call would crash.
+
+import "reflect"
+
+var a int
+
+type X struct{}
+
+func (X) F() *int {
+	return &a
+}
+
+type I interface {
+	F() *int
+}
+
+func main() {
+	type Y struct{ X }
+	print(reflect.Indirect(reflect.ValueOf(new(Y))).Interface().(I).F()) // @pointsto main.a
+}
diff --git a/go/pointer/testdata/structreflect.go b/go/pointer/testdata/structreflect.go
new file mode 100644
index 0000000..9fb49f5
--- /dev/null
+++ b/go/pointer/testdata/structreflect.go
@@ -0,0 +1,45 @@
+// +build ignore
+
+package main
+
+import "reflect"
+
+type A struct {
+	f *int
+	g interface{}
+	h bool
+}
+
+var dyn string
+
+func reflectTypeFieldByName() {
+	f, _ := reflect.TypeOf(A{}).FieldByName("f")
+	print(f.Type) // @pointsto *int
+
+	g, _ := reflect.TypeOf(A{}).FieldByName("g")
+	print(g.Type)               // @pointsto interface{}
+	print(reflect.Zero(g.Type)) // @pointsto <alloc in reflect.Zero>
+	print(reflect.Zero(g.Type)) // @types interface{}
+
+	print(reflect.Zero(g.Type).Interface()) // @pointsto
+	print(reflect.Zero(g.Type).Interface()) // @types
+
+	h, _ := reflect.TypeOf(A{}).FieldByName("h")
+	print(h.Type) // @pointsto bool
+
+	missing, _ := reflect.TypeOf(A{}).FieldByName("missing")
+	print(missing.Type) // @pointsto
+
+	dyn, _ := reflect.TypeOf(A{}).FieldByName(dyn)
+	print(dyn.Type) // @pointsto *int | bool | interface{}
+}
+
+func reflectTypeField() {
+	fld := reflect.TypeOf(A{}).Field(0)
+	print(fld.Type) // @pointsto *int | bool | interface{}
+}
+
+func main() {
+	reflectTypeFieldByName()
+	reflectTypeField()
+}
diff --git a/go/pointer/testdata/structs.go b/go/pointer/testdata/structs.go
new file mode 100644
index 0000000..9036d60
--- /dev/null
+++ b/go/pointer/testdata/structs.go
@@ -0,0 +1,100 @@
+// +build ignore
+
+package main
+
+var unknown bool // defeat dead-code elimination
+
+var p, q int
+
+type A struct {
+	f *int
+	g interface{}
+}
+
+func (a A) m1() {
+	print(a.f) // @pointsto main.p
+}
+
+func (a *A) m2() {
+	print(a)   // @pointsto complit.A@struct1s:9
+	print(a.f) // @pointsto main.p
+}
+
+type B struct {
+	h *int
+	A
+}
+
+func structs1() {
+	b := &B{ // @line struct1s
+		h: &q,
+	}
+	b.f = &p
+	b.g = b
+
+	print(b.h) // @pointsto main.q
+	print(b.f) // @pointsto main.p
+	print(b.g) // @types *B
+
+	ptr := &b.f
+	print(*ptr) // @pointsto main.p
+
+	b.m1()
+	b.m2()
+}
+
+// @calls main.structs1 -> (main.A).m1
+// @calls main.structs1 -> (*main.A).m2
+// @calls (*main.B).m1 -> (main.A).m1
+// @calls (*main.B).m2 -> (*main.A).m2
+
+type T struct {
+	x int
+	y int
+}
+
+type S struct {
+	a [3]T
+	b *[3]T
+	c [3]*T
+}
+
+func structs2() {
+	var s S          // @line s2s
+	print(&s)        // @pointsto s@s2s:6
+	print(&s.a)      // @pointsto s.a@s2s:6
+	print(&s.a[0])   // @pointsto s.a[*]@s2s:6
+	print(&s.a[0].x) // @pointsto s.a[*].x@s2s:6
+	print(&s.a[0].y) // @pointsto s.a[*].y@s2s:6
+	print(&s.b)      // @pointsto s.b@s2s:6
+	print(&s.b[0])   // @pointsto
+	print(&s.b[0].x) // @pointsto
+	print(&s.b[0].y) // @pointsto
+	print(&s.c)      // @pointsto s.c@s2s:6
+	print(&s.c[0])   // @pointsto s.c[*]@s2s:6
+	print(&s.c[0].x) // @pointsto
+	print(&s.c[0].y) // @pointsto
+
+	var s2 S          // @line s2s2
+	s2.b = new([3]T)  // @line s2s2b
+	print(s2.b)       // @pointsto new@s2s2b:12
+	print(&s2.b)      // @pointsto s2.b@s2s2:6
+	print(&s2.b[0])   // @pointsto new[*]@s2s2b:12
+	print(&s2.b[0].x) // @pointsto new[*].x@s2s2b:12
+	print(&s2.b[0].y) // @pointsto new[*].y@s2s2b:12
+	print(&s2.c[0].x) // @pointsto
+	print(&s2.c[0].y) // @pointsto
+
+	var s3 S          // @line s2s3
+	s3.c[2] = new(T)  // @line s2s3c
+	print(&s3.c)      // @pointsto s3.c@s2s3:6
+	print(s3.c[1])    // @pointsto new@s2s3c:15
+	print(&s3.c[1])   // @pointsto s3.c[*]@s2s3:6
+	print(&s3.c[1].x) // @pointsto new.x@s2s3c:15
+	print(&s3.c[1].y) // @pointsto new.y@s2s3c:15
+}
+
+func main() {
+	structs1()
+	structs2()
+}
diff --git a/go/pointer/testdata/timer.go b/go/pointer/testdata/timer.go
new file mode 100644
index 0000000..465d081
--- /dev/null
+++ b/go/pointer/testdata/timer.go
@@ -0,0 +1,24 @@
+// +build ignore
+
+package main
+
+import "time"
+
+func after() {}
+
+func main() {
+	// @calls time.startTimer -> time.sendTime
+	ticker := time.NewTicker(1)
+	<-ticker.C
+
+	// @calls time.startTimer -> time.sendTime
+	timer := time.NewTimer(time.Second)
+	<-timer.C
+
+	// @calls time.startTimer -> time.goFunc
+	// @calls time.goFunc -> main.after
+	timer = time.AfterFunc(time.Second, after)
+	<-timer.C
+}
+
+// @calls time.sendTime -> time.Now
diff --git a/go/pointer/util.go b/go/pointer/util.go
new file mode 100644
index 0000000..d4ccbb5
--- /dev/null
+++ b/go/pointer/util.go
@@ -0,0 +1,314 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package pointer
+
+import (
+	"bytes"
+	"fmt"
+	"log"
+	"os"
+	"os/exec"
+	"runtime"
+	"time"
+
+	"golang.org/x/tools/container/intsets"
+	"golang.org/x/tools/go/types"
+)
+
+// CanPoint reports whether the type T is pointerlike,
+// for the purposes of this analysis.
+func CanPoint(T types.Type) bool {
+	switch T := T.(type) {
+	case *types.Named:
+		if obj := T.Obj(); obj.Name() == "Value" && obj.Pkg().Path() == "reflect" {
+			return true // treat reflect.Value like interface{}
+		}
+		return CanPoint(T.Underlying())
+
+	case *types.Pointer, *types.Interface, *types.Map, *types.Chan, *types.Signature, *types.Slice:
+		return true
+	}
+
+	return false // array struct tuple builtin basic
+}
+
+// CanHaveDynamicTypes reports whether the type T can "hold" dynamic types,
+// i.e. is an interface (incl. reflect.Type) or a reflect.Value.
+//
+func CanHaveDynamicTypes(T types.Type) bool {
+	switch T := T.(type) {
+	case *types.Named:
+		if obj := T.Obj(); obj.Name() == "Value" && obj.Pkg().Path() == "reflect" {
+			return true // reflect.Value
+		}
+		return CanHaveDynamicTypes(T.Underlying())
+	case *types.Interface:
+		return true
+	}
+	return false
+}
+
+func isInterface(T types.Type) bool { return types.IsInterface(T) }
+
+// mustDeref returns the element type of its argument, which must be a
+// pointer; panic ensues otherwise.
+func mustDeref(typ types.Type) types.Type {
+	return typ.Underlying().(*types.Pointer).Elem()
+}
+
+// deref returns a pointer's element type; otherwise it returns typ.
+func deref(typ types.Type) types.Type {
+	if p, ok := typ.Underlying().(*types.Pointer); ok {
+		return p.Elem()
+	}
+	return typ
+}
+
+// A fieldInfo describes one subelement (node) of the flattening-out
+// of a type T: the subelement's type and its path from the root of T.
+//
+// For example, for this type:
+//     type line struct{ points []struct{x, y int} }
+// flatten() of the inner struct yields the following []fieldInfo:
+//    struct{ x, y int }                      ""
+//    int                                     ".x"
+//    int                                     ".y"
+// and flatten(line) yields:
+//    struct{ points []struct{x, y int} }     ""
+//    struct{ x, y int }                      ".points[*]"
+//    int                                     ".points[*].x
+//    int                                     ".points[*].y"
+//
+type fieldInfo struct {
+	typ types.Type
+
+	// op and tail describe the path to the element (e.g. ".a#2.b[*].c").
+	op   interface{} // *Array: true; *Tuple: int; *Struct: *types.Var; *Named: nil
+	tail *fieldInfo
+}
+
+// path returns a user-friendly string describing the subelement path.
+//
+func (fi *fieldInfo) path() string {
+	var buf bytes.Buffer
+	for p := fi; p != nil; p = p.tail {
+		switch op := p.op.(type) {
+		case bool:
+			fmt.Fprintf(&buf, "[*]")
+		case int:
+			fmt.Fprintf(&buf, "#%d", op)
+		case *types.Var:
+			fmt.Fprintf(&buf, ".%s", op.Name())
+		}
+	}
+	return buf.String()
+}
+
+// flatten returns a list of directly contained fields in the preorder
+// traversal of the type tree of t.  The resulting elements are all
+// scalars (basic types or pointerlike types), except for struct/array
+// "identity" nodes, whose type is that of the aggregate.
+//
+// reflect.Value is considered pointerlike, similar to interface{}.
+//
+// Callers must not mutate the result.
+//
+func (a *analysis) flatten(t types.Type) []*fieldInfo {
+	fl, ok := a.flattenMemo[t]
+	if !ok {
+		switch t := t.(type) {
+		case *types.Named:
+			u := t.Underlying()
+			if isInterface(u) {
+				// Debuggability hack: don't remove
+				// the named type from interfaces as
+				// they're very verbose.
+				fl = append(fl, &fieldInfo{typ: t})
+			} else {
+				fl = a.flatten(u)
+			}
+
+		case *types.Basic,
+			*types.Signature,
+			*types.Chan,
+			*types.Map,
+			*types.Interface,
+			*types.Slice,
+			*types.Pointer:
+			fl = append(fl, &fieldInfo{typ: t})
+
+		case *types.Array:
+			fl = append(fl, &fieldInfo{typ: t}) // identity node
+			for _, fi := range a.flatten(t.Elem()) {
+				fl = append(fl, &fieldInfo{typ: fi.typ, op: true, tail: fi})
+			}
+
+		case *types.Struct:
+			fl = append(fl, &fieldInfo{typ: t}) // identity node
+			for i, n := 0, t.NumFields(); i < n; i++ {
+				f := t.Field(i)
+				for _, fi := range a.flatten(f.Type()) {
+					fl = append(fl, &fieldInfo{typ: fi.typ, op: f, tail: fi})
+				}
+			}
+
+		case *types.Tuple:
+			// No identity node: tuples are never address-taken.
+			n := t.Len()
+			if n == 1 {
+				// Don't add a fieldInfo link for singletons,
+				// e.g. in params/results.
+				fl = append(fl, a.flatten(t.At(0).Type())...)
+			} else {
+				for i := 0; i < n; i++ {
+					f := t.At(i)
+					for _, fi := range a.flatten(f.Type()) {
+						fl = append(fl, &fieldInfo{typ: fi.typ, op: i, tail: fi})
+					}
+				}
+			}
+
+		default:
+			panic(t)
+		}
+
+		a.flattenMemo[t] = fl
+	}
+
+	return fl
+}
+
+// sizeof returns the number of pointerlike abstractions (nodes) in the type t.
+func (a *analysis) sizeof(t types.Type) uint32 {
+	return uint32(len(a.flatten(t)))
+}
+
+// shouldTrack reports whether object type T contains (recursively)
+// any fields whose addresses should be tracked.
+func (a *analysis) shouldTrack(T types.Type) bool {
+	if a.track == trackAll {
+		return true // fast path
+	}
+	track, ok := a.trackTypes[T]
+	if !ok {
+		a.trackTypes[T] = true // break cycles conservatively
+		// NB: reflect.Value, reflect.Type are pre-populated to true.
+		for _, fi := range a.flatten(T) {
+			switch ft := fi.typ.Underlying().(type) {
+			case *types.Interface, *types.Signature:
+				track = true // needed for callgraph
+			case *types.Basic:
+				// no-op
+			case *types.Chan:
+				track = a.track&trackChan != 0 || a.shouldTrack(ft.Elem())
+			case *types.Map:
+				track = a.track&trackMap != 0 || a.shouldTrack(ft.Key()) || a.shouldTrack(ft.Elem())
+			case *types.Slice:
+				track = a.track&trackSlice != 0 || a.shouldTrack(ft.Elem())
+			case *types.Pointer:
+				track = a.track&trackPtr != 0 || a.shouldTrack(ft.Elem())
+			case *types.Array, *types.Struct:
+				// No need to look at field types since they will follow (flattened).
+			default:
+				// Includes *types.Tuple, which are never address-taken.
+				panic(ft)
+			}
+			if track {
+				break
+			}
+		}
+		a.trackTypes[T] = track
+		if !track && a.log != nil {
+			fmt.Fprintf(a.log, "\ttype not tracked: %s\n", T)
+		}
+	}
+	return track
+}
+
+// offsetOf returns the (abstract) offset of field index within struct
+// or tuple typ.
+func (a *analysis) offsetOf(typ types.Type, index int) uint32 {
+	var offset uint32
+	switch t := typ.Underlying().(type) {
+	case *types.Tuple:
+		for i := 0; i < index; i++ {
+			offset += a.sizeof(t.At(i).Type())
+		}
+	case *types.Struct:
+		offset++ // the node for the struct itself
+		for i := 0; i < index; i++ {
+			offset += a.sizeof(t.Field(i).Type())
+		}
+	default:
+		panic(fmt.Sprintf("offsetOf(%s : %T)", typ, typ))
+	}
+	return offset
+}
+
+// sliceToArray returns the type representing the arrays to which
+// slice type slice points.
+func sliceToArray(slice types.Type) *types.Array {
+	return types.NewArray(slice.Underlying().(*types.Slice).Elem(), 1)
+}
+
+// Node set -------------------------------------------------------------------
+
+type nodeset struct {
+	intsets.Sparse
+}
+
+func (ns *nodeset) String() string {
+	var buf bytes.Buffer
+	buf.WriteRune('{')
+	var space [50]int
+	for i, n := range ns.AppendTo(space[:0]) {
+		if i > 0 {
+			buf.WriteString(", ")
+		}
+		buf.WriteRune('n')
+		fmt.Fprintf(&buf, "%d", n)
+	}
+	buf.WriteRune('}')
+	return buf.String()
+}
+
+func (ns *nodeset) add(n nodeid) bool {
+	return ns.Sparse.Insert(int(n))
+}
+
+func (x *nodeset) addAll(y *nodeset) bool {
+	return x.UnionWith(&y.Sparse)
+}
+
+// Profiling & debugging -------------------------------------------------------
+
+var timers = make(map[string]time.Time)
+
+func start(name string) {
+	if debugTimers {
+		timers[name] = time.Now()
+		log.Printf("%s...\n", name)
+	}
+}
+
+func stop(name string) {
+	if debugTimers {
+		log.Printf("%s took %s\n", name, time.Since(timers[name]))
+	}
+}
+
+// diff runs the command "diff a b" and reports its success.
+func diff(a, b string) bool {
+	var cmd *exec.Cmd
+	switch runtime.GOOS {
+	case "plan9":
+		cmd = exec.Command("/bin/diff", "-c", a, b)
+	default:
+		cmd = exec.Command("/usr/bin/diff", "-u", a, b)
+	}
+	cmd.Stdout = os.Stderr
+	cmd.Stderr = os.Stderr
+	return cmd.Run() == nil
+}
diff --git a/go/ssa/blockopt.go b/go/ssa/blockopt.go
new file mode 100644
index 0000000..e79260a
--- /dev/null
+++ b/go/ssa/blockopt.go
@@ -0,0 +1,187 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssa
+
+// Simple block optimizations to simplify the control flow graph.
+
+// TODO(adonovan): opt: instead of creating several "unreachable" blocks
+// per function in the Builder, reuse a single one (e.g. at Blocks[1])
+// to reduce garbage.
+
+import (
+	"fmt"
+	"os"
+)
+
+// If true, perform sanity checking and show progress at each
+// successive iteration of optimizeBlocks.  Very verbose.
+const debugBlockOpt = false
+
+// markReachable sets Index=-1 for all blocks reachable from b.
+func markReachable(b *BasicBlock) {
+	b.Index = -1
+	for _, succ := range b.Succs {
+		if succ.Index == 0 {
+			markReachable(succ)
+		}
+	}
+}
+
+// deleteUnreachableBlocks marks all reachable blocks of f and
+// eliminates (nils) all others, including possibly cyclic subgraphs.
+//
+func deleteUnreachableBlocks(f *Function) {
+	const white, black = 0, -1
+	// We borrow b.Index temporarily as the mark bit.
+	for _, b := range f.Blocks {
+		b.Index = white
+	}
+	markReachable(f.Blocks[0])
+	if f.Recover != nil {
+		markReachable(f.Recover)
+	}
+	for i, b := range f.Blocks {
+		if b.Index == white {
+			for _, c := range b.Succs {
+				if c.Index == black {
+					c.removePred(b) // delete white->black edge
+				}
+			}
+			if debugBlockOpt {
+				fmt.Fprintln(os.Stderr, "unreachable", b)
+			}
+			f.Blocks[i] = nil // delete b
+		}
+	}
+	f.removeNilBlocks()
+}
+
+// jumpThreading attempts to apply simple jump-threading to block b,
+// in which a->b->c become a->c if b is just a Jump.
+// The result is true if the optimization was applied.
+//
+func jumpThreading(f *Function, b *BasicBlock) bool {
+	if b.Index == 0 {
+		return false // don't apply to entry block
+	}
+	if b.Instrs == nil {
+		return false
+	}
+	if _, ok := b.Instrs[0].(*Jump); !ok {
+		return false // not just a jump
+	}
+	c := b.Succs[0]
+	if c == b {
+		return false // don't apply to degenerate jump-to-self.
+	}
+	if c.hasPhi() {
+		return false // not sound without more effort
+	}
+	for j, a := range b.Preds {
+		a.replaceSucc(b, c)
+
+		// If a now has two edges to c, replace its degenerate If by Jump.
+		if len(a.Succs) == 2 && a.Succs[0] == c && a.Succs[1] == c {
+			jump := new(Jump)
+			jump.setBlock(a)
+			a.Instrs[len(a.Instrs)-1] = jump
+			a.Succs = a.Succs[:1]
+			c.removePred(b)
+		} else {
+			if j == 0 {
+				c.replacePred(b, a)
+			} else {
+				c.Preds = append(c.Preds, a)
+			}
+		}
+
+		if debugBlockOpt {
+			fmt.Fprintln(os.Stderr, "jumpThreading", a, b, c)
+		}
+	}
+	f.Blocks[b.Index] = nil // delete b
+	return true
+}
+
+// fuseBlocks attempts to apply the block fusion optimization to block
+// a, in which a->b becomes ab if len(a.Succs)==len(b.Preds)==1.
+// The result is true if the optimization was applied.
+//
+func fuseBlocks(f *Function, a *BasicBlock) bool {
+	if len(a.Succs) != 1 {
+		return false
+	}
+	b := a.Succs[0]
+	if len(b.Preds) != 1 {
+		return false
+	}
+
+	// Degenerate &&/|| ops may result in a straight-line CFG
+	// containing φ-nodes. (Ideally we'd replace such them with
+	// their sole operand but that requires Referrers, built later.)
+	if b.hasPhi() {
+		return false // not sound without further effort
+	}
+
+	// Eliminate jump at end of A, then copy all of B across.
+	a.Instrs = append(a.Instrs[:len(a.Instrs)-1], b.Instrs...)
+	for _, instr := range b.Instrs {
+		instr.setBlock(a)
+	}
+
+	// A inherits B's successors
+	a.Succs = append(a.succs2[:0], b.Succs...)
+
+	// Fix up Preds links of all successors of B.
+	for _, c := range b.Succs {
+		c.replacePred(b, a)
+	}
+
+	if debugBlockOpt {
+		fmt.Fprintln(os.Stderr, "fuseBlocks", a, b)
+	}
+
+	f.Blocks[b.Index] = nil // delete b
+	return true
+}
+
+// optimizeBlocks() performs some simple block optimizations on a
+// completed function: dead block elimination, block fusion, jump
+// threading.
+//
+func optimizeBlocks(f *Function) {
+	deleteUnreachableBlocks(f)
+
+	// Loop until no further progress.
+	changed := true
+	for changed {
+		changed = false
+
+		if debugBlockOpt {
+			f.WriteTo(os.Stderr)
+			mustSanityCheck(f, nil)
+		}
+
+		for _, b := range f.Blocks {
+			// f.Blocks will temporarily contain nils to indicate
+			// deleted blocks; we remove them at the end.
+			if b == nil {
+				continue
+			}
+
+			// Fuse blocks.  b->c becomes bc.
+			if fuseBlocks(f, b) {
+				changed = true
+			}
+
+			// a->b->c becomes a->c if b contains only a Jump.
+			if jumpThreading(f, b) {
+				changed = true
+				continue // (b was disconnected)
+			}
+		}
+	}
+	f.removeNilBlocks()
+}
diff --git a/go/ssa/builder.go b/go/ssa/builder.go
new file mode 100644
index 0000000..5b8ce0e
--- /dev/null
+++ b/go/ssa/builder.go
@@ -0,0 +1,2370 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssa
+
+// This file implements the BUILD phase of SSA construction.
+//
+// SSA construction has two phases, CREATE and BUILD.  In the CREATE phase
+// (create.go), all packages are constructed and type-checked and
+// definitions of all package members are created, method-sets are
+// computed, and wrapper methods are synthesized.
+// ssa.Packages are created in arbitrary order.
+//
+// In the BUILD phase (builder.go), the builder traverses the AST of
+// each Go source function and generates SSA instructions for the
+// function body.  Initializer expressions for package-level variables
+// are emitted to the package's init() function in the order specified
+// by go/types.Info.InitOrder, then code for each function in the
+// package is generated in lexical order.
+// The BUILD phases for distinct packages are independent and are
+// executed in parallel.
+//
+// TODO(adonovan): indeed, building functions is now embarrassingly parallel.
+// Audit for concurrency then benchmark using more goroutines.
+//
+// The builder's and Program's indices (maps) are populated and
+// mutated during the CREATE phase, but during the BUILD phase they
+// remain constant.  The sole exception is Prog.methodSets and its
+// related maps, which are protected by a dedicated mutex.
+
+import (
+	"fmt"
+	"go/ast"
+	"go/token"
+	"os"
+	"sync"
+	"sync/atomic"
+
+	"golang.org/x/tools/go/exact"
+	"golang.org/x/tools/go/types"
+)
+
+type opaqueType struct {
+	types.Type
+	name string
+}
+
+func (t *opaqueType) String() string { return t.name }
+
+var (
+	varOk    = newVar("ok", tBool)
+	varIndex = newVar("index", tInt)
+
+	// Type constants.
+	tBool       = types.Typ[types.Bool]
+	tByte       = types.Typ[types.Byte]
+	tInt        = types.Typ[types.Int]
+	tInvalid    = types.Typ[types.Invalid]
+	tString     = types.Typ[types.String]
+	tUntypedNil = types.Typ[types.UntypedNil]
+	tRangeIter  = &opaqueType{nil, "iter"} // the type of all "range" iterators
+	tEface      = new(types.Interface)
+
+	// SSA Value constants.
+	vZero = intConst(0)
+	vOne  = intConst(1)
+	vTrue = NewConst(exact.MakeBool(true), tBool)
+)
+
+// builder holds state associated with the package currently being built.
+// Its methods contain all the logic for AST-to-SSA conversion.
+type builder struct{}
+
+// cond emits to fn code to evaluate boolean condition e and jump
+// to t or f depending on its value, performing various simplifications.
+//
+// Postcondition: fn.currentBlock is nil.
+//
+func (b *builder) cond(fn *Function, e ast.Expr, t, f *BasicBlock) {
+	switch e := e.(type) {
+	case *ast.ParenExpr:
+		b.cond(fn, e.X, t, f)
+		return
+
+	case *ast.BinaryExpr:
+		switch e.Op {
+		case token.LAND:
+			ltrue := fn.newBasicBlock("cond.true")
+			b.cond(fn, e.X, ltrue, f)
+			fn.currentBlock = ltrue
+			b.cond(fn, e.Y, t, f)
+			return
+
+		case token.LOR:
+			lfalse := fn.newBasicBlock("cond.false")
+			b.cond(fn, e.X, t, lfalse)
+			fn.currentBlock = lfalse
+			b.cond(fn, e.Y, t, f)
+			return
+		}
+
+	case *ast.UnaryExpr:
+		if e.Op == token.NOT {
+			b.cond(fn, e.X, f, t)
+			return
+		}
+	}
+
+	// A traditional compiler would simplify "if false" (etc) here
+	// but we do not, for better fidelity to the source code.
+	//
+	// The value of a constant condition may be platform-specific,
+	// and may cause blocks that are reachable in some configuration
+	// to be hidden from subsequent analyses such as bug-finding tools.
+	emitIf(fn, b.expr(fn, e), t, f)
+}
+
+// logicalBinop emits code to fn to evaluate e, a &&- or
+// ||-expression whose reified boolean value is wanted.
+// The value is returned.
+//
+func (b *builder) logicalBinop(fn *Function, e *ast.BinaryExpr) Value {
+	rhs := fn.newBasicBlock("binop.rhs")
+	done := fn.newBasicBlock("binop.done")
+
+	// T(e) = T(e.X) = T(e.Y) after untyped constants have been
+	// eliminated.
+	// TODO(adonovan): not true; MyBool==MyBool yields UntypedBool.
+	t := fn.Pkg.typeOf(e)
+
+	var short Value // value of the short-circuit path
+	switch e.Op {
+	case token.LAND:
+		b.cond(fn, e.X, rhs, done)
+		short = NewConst(exact.MakeBool(false), t)
+
+	case token.LOR:
+		b.cond(fn, e.X, done, rhs)
+		short = NewConst(exact.MakeBool(true), t)
+	}
+
+	// Is rhs unreachable?
+	if rhs.Preds == nil {
+		// Simplify false&&y to false, true||y to true.
+		fn.currentBlock = done
+		return short
+	}
+
+	// Is done unreachable?
+	if done.Preds == nil {
+		// Simplify true&&y (or false||y) to y.
+		fn.currentBlock = rhs
+		return b.expr(fn, e.Y)
+	}
+
+	// All edges from e.X to done carry the short-circuit value.
+	var edges []Value
+	for _ = range done.Preds {
+		edges = append(edges, short)
+	}
+
+	// The edge from e.Y to done carries the value of e.Y.
+	fn.currentBlock = rhs
+	edges = append(edges, b.expr(fn, e.Y))
+	emitJump(fn, done)
+	fn.currentBlock = done
+
+	phi := &Phi{Edges: edges, Comment: e.Op.String()}
+	phi.pos = e.OpPos
+	phi.typ = t
+	return done.emit(phi)
+}
+
+// exprN lowers a multi-result expression e to SSA form, emitting code
+// to fn and returning a single Value whose type is a *types.Tuple.
+// The caller must access the components via Extract.
+//
+// Multi-result expressions include CallExprs in a multi-value
+// assignment or return statement, and "value,ok" uses of
+// TypeAssertExpr, IndexExpr (when X is a map), and UnaryExpr (when Op
+// is token.ARROW).
+//
+func (b *builder) exprN(fn *Function, e ast.Expr) Value {
+	typ := fn.Pkg.typeOf(e).(*types.Tuple)
+	switch e := e.(type) {
+	case *ast.ParenExpr:
+		return b.exprN(fn, e.X)
+
+	case *ast.CallExpr:
+		// Currently, no built-in function nor type conversion
+		// has multiple results, so we can avoid some of the
+		// cases for single-valued CallExpr.
+		var c Call
+		b.setCall(fn, e, &c.Call)
+		c.typ = typ
+		return fn.emit(&c)
+
+	case *ast.IndexExpr:
+		mapt := fn.Pkg.typeOf(e.X).Underlying().(*types.Map)
+		lookup := &Lookup{
+			X:       b.expr(fn, e.X),
+			Index:   emitConv(fn, b.expr(fn, e.Index), mapt.Key()),
+			CommaOk: true,
+		}
+		lookup.setType(typ)
+		lookup.setPos(e.Lbrack)
+		return fn.emit(lookup)
+
+	case *ast.TypeAssertExpr:
+		return emitTypeTest(fn, b.expr(fn, e.X), typ.At(0).Type(), e.Lparen)
+
+	case *ast.UnaryExpr: // must be receive <-
+		unop := &UnOp{
+			Op:      token.ARROW,
+			X:       b.expr(fn, e.X),
+			CommaOk: true,
+		}
+		unop.setType(typ)
+		unop.setPos(e.OpPos)
+		return fn.emit(unop)
+	}
+	panic(fmt.Sprintf("exprN(%T) in %s", e, fn))
+}
+
+// builtin emits to fn SSA instructions to implement a call to the
+// built-in function obj with the specified arguments
+// and return type.  It returns the value defined by the result.
+//
+// The result is nil if no special handling was required; in this case
+// the caller should treat this like an ordinary library function
+// call.
+//
+func (b *builder) builtin(fn *Function, obj *types.Builtin, args []ast.Expr, typ types.Type, pos token.Pos) Value {
+	switch obj.Name() {
+	case "make":
+		switch typ.Underlying().(type) {
+		case *types.Slice:
+			n := b.expr(fn, args[1])
+			m := n
+			if len(args) == 3 {
+				m = b.expr(fn, args[2])
+			}
+			if m, ok := m.(*Const); ok {
+				// treat make([]T, n, m) as new([m]T)[:n]
+				cap, _ := exact.Int64Val(m.Value)
+				at := types.NewArray(typ.Underlying().(*types.Slice).Elem(), cap)
+				alloc := emitNew(fn, at, pos)
+				alloc.Comment = "makeslice"
+				v := &Slice{
+					X:    alloc,
+					High: n,
+				}
+				v.setPos(pos)
+				v.setType(typ)
+				return fn.emit(v)
+			}
+			v := &MakeSlice{
+				Len: n,
+				Cap: m,
+			}
+			v.setPos(pos)
+			v.setType(typ)
+			return fn.emit(v)
+
+		case *types.Map:
+			var res Value
+			if len(args) == 2 {
+				res = b.expr(fn, args[1])
+			}
+			v := &MakeMap{Reserve: res}
+			v.setPos(pos)
+			v.setType(typ)
+			return fn.emit(v)
+
+		case *types.Chan:
+			var sz Value = vZero
+			if len(args) == 2 {
+				sz = b.expr(fn, args[1])
+			}
+			v := &MakeChan{Size: sz}
+			v.setPos(pos)
+			v.setType(typ)
+			return fn.emit(v)
+		}
+
+	case "new":
+		alloc := emitNew(fn, deref(typ), pos)
+		alloc.Comment = "new"
+		return alloc
+
+	case "len", "cap":
+		// Special case: len or cap of an array or *array is
+		// based on the type, not the value which may be nil.
+		// We must still evaluate the value, though.  (If it
+		// was side-effect free, the whole call would have
+		// been constant-folded.)
+		t := deref(fn.Pkg.typeOf(args[0])).Underlying()
+		if at, ok := t.(*types.Array); ok {
+			b.expr(fn, args[0]) // for effects only
+			return intConst(at.Len())
+		}
+		// Otherwise treat as normal.
+
+	case "panic":
+		fn.emit(&Panic{
+			X:   emitConv(fn, b.expr(fn, args[0]), tEface),
+			pos: pos,
+		})
+		fn.currentBlock = fn.newBasicBlock("unreachable")
+		return vTrue // any non-nil Value will do
+	}
+	return nil // treat all others as a regular function call
+}
+
+// addr lowers a single-result addressable expression e to SSA form,
+// emitting code to fn and returning the location (an lvalue) defined
+// by the expression.
+//
+// If escaping is true, addr marks the base variable of the
+// addressable expression e as being a potentially escaping pointer
+// value.  For example, in this code:
+//
+//   a := A{
+//     b: [1]B{B{c: 1}}
+//   }
+//   return &a.b[0].c
+//
+// the application of & causes a.b[0].c to have its address taken,
+// which means that ultimately the local variable a must be
+// heap-allocated.  This is a simple but very conservative escape
+// analysis.
+//
+// Operations forming potentially escaping pointers include:
+// - &x, including when implicit in method call or composite literals.
+// - a[:] iff a is an array (not *array)
+// - references to variables in lexically enclosing functions.
+//
+func (b *builder) addr(fn *Function, e ast.Expr, escaping bool) lvalue {
+	switch e := e.(type) {
+	case *ast.Ident:
+		if isBlankIdent(e) {
+			return blank{}
+		}
+		obj := fn.Pkg.objectOf(e)
+		v := fn.Prog.packageLevelValue(obj) // var (address)
+		if v == nil {
+			v = fn.lookup(obj, escaping)
+		}
+		return &address{addr: v, pos: e.Pos(), expr: e}
+
+	case *ast.CompositeLit:
+		t := deref(fn.Pkg.typeOf(e))
+		var v *Alloc
+		if escaping {
+			v = emitNew(fn, t, e.Lbrace)
+		} else {
+			v = fn.addLocal(t, e.Lbrace)
+		}
+		v.Comment = "complit"
+		var sb storebuf
+		b.compLit(fn, v, e, true, &sb)
+		sb.emit(fn)
+		return &address{addr: v, pos: e.Lbrace, expr: e}
+
+	case *ast.ParenExpr:
+		return b.addr(fn, e.X, escaping)
+
+	case *ast.SelectorExpr:
+		sel, ok := fn.Pkg.info.Selections[e]
+		if !ok {
+			// qualified identifier
+			return b.addr(fn, e.Sel, escaping)
+		}
+		if sel.Kind() != types.FieldVal {
+			panic(sel)
+		}
+		wantAddr := true
+		v := b.receiver(fn, e.X, wantAddr, escaping, sel)
+		last := len(sel.Index()) - 1
+		return &address{
+			addr: emitFieldSelection(fn, v, sel.Index()[last], true, e.Sel),
+			pos:  e.Sel.Pos(),
+			expr: e.Sel,
+		}
+
+	case *ast.IndexExpr:
+		var x Value
+		var et types.Type
+		switch t := fn.Pkg.typeOf(e.X).Underlying().(type) {
+		case *types.Array:
+			x = b.addr(fn, e.X, escaping).address(fn)
+			et = types.NewPointer(t.Elem())
+		case *types.Pointer: // *array
+			x = b.expr(fn, e.X)
+			et = types.NewPointer(t.Elem().Underlying().(*types.Array).Elem())
+		case *types.Slice:
+			x = b.expr(fn, e.X)
+			et = types.NewPointer(t.Elem())
+		case *types.Map:
+			return &element{
+				m:   b.expr(fn, e.X),
+				k:   emitConv(fn, b.expr(fn, e.Index), t.Key()),
+				t:   t.Elem(),
+				pos: e.Lbrack,
+			}
+		default:
+			panic("unexpected container type in IndexExpr: " + t.String())
+		}
+		v := &IndexAddr{
+			X:     x,
+			Index: emitConv(fn, b.expr(fn, e.Index), tInt),
+		}
+		v.setPos(e.Lbrack)
+		v.setType(et)
+		return &address{addr: fn.emit(v), pos: e.Lbrack, expr: e}
+
+	case *ast.StarExpr:
+		return &address{addr: b.expr(fn, e.X), pos: e.Star, expr: e}
+	}
+
+	panic(fmt.Sprintf("unexpected address expression: %T", e))
+}
+
+type store struct {
+	lhs lvalue
+	rhs Value
+}
+
+type storebuf struct{ stores []store }
+
+func (sb *storebuf) store(lhs lvalue, rhs Value) {
+	sb.stores = append(sb.stores, store{lhs, rhs})
+}
+
+func (sb *storebuf) emit(fn *Function) {
+	for _, s := range sb.stores {
+		s.lhs.store(fn, s.rhs)
+	}
+}
+
+// assign emits to fn code to initialize the lvalue loc with the value
+// of expression e.  If isZero is true, assign assumes that loc holds
+// the zero value for its type.
+//
+// This is equivalent to loc.store(fn, b.expr(fn, e)), but may generate
+// better code in some cases, e.g., for composite literals in an
+// addressable location.
+//
+// If sb is not nil, assign generates code to evaluate expression e, but
+// not to update loc.  Instead, the necessary stores are appended to the
+// storebuf sb so that they can be executed later.  This allows correct
+// in-place update of existing variables when the RHS is a composite
+// literal that may reference parts of the LHS.
+//
+func (b *builder) assign(fn *Function, loc lvalue, e ast.Expr, isZero bool, sb *storebuf) {
+	// Can we initialize it in place?
+	if e, ok := unparen(e).(*ast.CompositeLit); ok {
+		// A CompositeLit never evaluates to a pointer,
+		// so if the type of the location is a pointer,
+		// an &-operation is implied.
+		if _, ok := loc.(blank); !ok { // avoid calling blank.typ()
+			if isPointer(loc.typ()) {
+				ptr := b.addr(fn, e, true).address(fn)
+				// copy address
+				if sb != nil {
+					sb.store(loc, ptr)
+				} else {
+					loc.store(fn, ptr)
+				}
+				return
+			}
+		}
+
+		if _, ok := loc.(*address); ok {
+			if isInterface(loc.typ()) {
+				// e.g. var x interface{} = T{...}
+				// Can't in-place initialize an interface value.
+				// Fall back to copying.
+			} else {
+				// x = T{...} or x := T{...}
+				addr := loc.address(fn)
+				if sb != nil {
+					b.compLit(fn, addr, e, isZero, sb)
+				} else {
+					var sb storebuf
+					b.compLit(fn, addr, e, isZero, &sb)
+					sb.emit(fn)
+				}
+
+				// Subtle: emit debug ref for aggregate types only;
+				// slice and map are handled by store ops in compLit.
+				switch loc.typ().Underlying().(type) {
+				case *types.Struct, *types.Array:
+					emitDebugRef(fn, e, addr, true)
+				}
+
+				return
+			}
+		}
+	}
+
+	// simple case: just copy
+	rhs := b.expr(fn, e)
+	if sb != nil {
+		sb.store(loc, rhs)
+	} else {
+		loc.store(fn, rhs)
+	}
+}
+
+// expr lowers a single-result expression e to SSA form, emitting code
+// to fn and returning the Value defined by the expression.
+//
+func (b *builder) expr(fn *Function, e ast.Expr) Value {
+	e = unparen(e)
+
+	tv := fn.Pkg.info.Types[e]
+
+	// Is expression a constant?
+	if tv.Value != nil {
+		return NewConst(tv.Value, tv.Type)
+	}
+
+	var v Value
+	if tv.Addressable() {
+		// Prefer pointer arithmetic ({Index,Field}Addr) followed
+		// by Load over subelement extraction (e.g. Index, Field),
+		// to avoid large copies.
+		v = b.addr(fn, e, false).load(fn)
+	} else {
+		v = b.expr0(fn, e, tv)
+	}
+	if fn.debugInfo() {
+		emitDebugRef(fn, e, v, false)
+	}
+	return v
+}
+
+func (b *builder) expr0(fn *Function, e ast.Expr, tv types.TypeAndValue) Value {
+	switch e := e.(type) {
+	case *ast.BasicLit:
+		panic("non-constant BasicLit") // unreachable
+
+	case *ast.FuncLit:
+		fn2 := &Function{
+			name:      fmt.Sprintf("%s$%d", fn.Name(), 1+len(fn.AnonFuncs)),
+			Signature: fn.Pkg.typeOf(e.Type).Underlying().(*types.Signature),
+			pos:       e.Type.Func,
+			parent:    fn,
+			Pkg:       fn.Pkg,
+			Prog:      fn.Prog,
+			syntax:    e,
+		}
+		fn.AnonFuncs = append(fn.AnonFuncs, fn2)
+		b.buildFunction(fn2)
+		if fn2.FreeVars == nil {
+			return fn2
+		}
+		v := &MakeClosure{Fn: fn2}
+		v.setType(tv.Type)
+		for _, fv := range fn2.FreeVars {
+			v.Bindings = append(v.Bindings, fv.outer)
+			fv.outer = nil
+		}
+		return fn.emit(v)
+
+	case *ast.TypeAssertExpr: // single-result form only
+		return emitTypeAssert(fn, b.expr(fn, e.X), tv.Type, e.Lparen)
+
+	case *ast.CallExpr:
+		if fn.Pkg.info.Types[e.Fun].IsType() {
+			// Explicit type conversion, e.g. string(x) or big.Int(x)
+			x := b.expr(fn, e.Args[0])
+			y := emitConv(fn, x, tv.Type)
+			if y != x {
+				switch y := y.(type) {
+				case *Convert:
+					y.pos = e.Lparen
+				case *ChangeType:
+					y.pos = e.Lparen
+				case *MakeInterface:
+					y.pos = e.Lparen
+				}
+			}
+			return y
+		}
+		// Call to "intrinsic" built-ins, e.g. new, make, panic.
+		if id, ok := unparen(e.Fun).(*ast.Ident); ok {
+			if obj, ok := fn.Pkg.info.Uses[id].(*types.Builtin); ok {
+				if v := b.builtin(fn, obj, e.Args, tv.Type, e.Lparen); v != nil {
+					return v
+				}
+			}
+		}
+		// Regular function call.
+		var v Call
+		b.setCall(fn, e, &v.Call)
+		v.setType(tv.Type)
+		return fn.emit(&v)
+
+	case *ast.UnaryExpr:
+		switch e.Op {
+		case token.AND: // &X --- potentially escaping.
+			addr := b.addr(fn, e.X, true)
+			if _, ok := unparen(e.X).(*ast.StarExpr); ok {
+				// &*p must panic if p is nil (http://golang.org/s/go12nil).
+				// For simplicity, we'll just (suboptimally) rely
+				// on the side effects of a load.
+				// TODO(adonovan): emit dedicated nilcheck.
+				addr.load(fn)
+			}
+			return addr.address(fn)
+		case token.ADD:
+			return b.expr(fn, e.X)
+		case token.NOT, token.ARROW, token.SUB, token.XOR: // ! <- - ^
+			v := &UnOp{
+				Op: e.Op,
+				X:  b.expr(fn, e.X),
+			}
+			v.setPos(e.OpPos)
+			v.setType(tv.Type)
+			return fn.emit(v)
+		default:
+			panic(e.Op)
+		}
+
+	case *ast.BinaryExpr:
+		switch e.Op {
+		case token.LAND, token.LOR:
+			return b.logicalBinop(fn, e)
+		case token.SHL, token.SHR:
+			fallthrough
+		case token.ADD, token.SUB, token.MUL, token.QUO, token.REM, token.AND, token.OR, token.XOR, token.AND_NOT:
+			return emitArith(fn, e.Op, b.expr(fn, e.X), b.expr(fn, e.Y), tv.Type, e.OpPos)
+
+		case token.EQL, token.NEQ, token.GTR, token.LSS, token.LEQ, token.GEQ:
+			cmp := emitCompare(fn, e.Op, b.expr(fn, e.X), b.expr(fn, e.Y), e.OpPos)
+			// The type of x==y may be UntypedBool.
+			return emitConv(fn, cmp, DefaultType(tv.Type))
+		default:
+			panic("illegal op in BinaryExpr: " + e.Op.String())
+		}
+
+	case *ast.SliceExpr:
+		var low, high, max Value
+		var x Value
+		switch fn.Pkg.typeOf(e.X).Underlying().(type) {
+		case *types.Array:
+			// Potentially escaping.
+			x = b.addr(fn, e.X, true).address(fn)
+		case *types.Basic, *types.Slice, *types.Pointer: // *array
+			x = b.expr(fn, e.X)
+		default:
+			panic("unreachable")
+		}
+		if e.High != nil {
+			high = b.expr(fn, e.High)
+		}
+		if e.Low != nil {
+			low = b.expr(fn, e.Low)
+		}
+		if e.Slice3 {
+			max = b.expr(fn, e.Max)
+		}
+		v := &Slice{
+			X:    x,
+			Low:  low,
+			High: high,
+			Max:  max,
+		}
+		v.setPos(e.Lbrack)
+		v.setType(tv.Type)
+		return fn.emit(v)
+
+	case *ast.Ident:
+		obj := fn.Pkg.info.Uses[e]
+		// Universal built-in or nil?
+		switch obj := obj.(type) {
+		case *types.Builtin:
+			return &Builtin{name: obj.Name(), sig: tv.Type.(*types.Signature)}
+		case *types.Nil:
+			return nilConst(tv.Type)
+		}
+		// Package-level func or var?
+		if v := fn.Prog.packageLevelValue(obj); v != nil {
+			if _, ok := obj.(*types.Var); ok {
+				return emitLoad(fn, v) // var (address)
+			}
+			return v // (func)
+		}
+		// Local var.
+		return emitLoad(fn, fn.lookup(obj, false)) // var (address)
+
+	case *ast.SelectorExpr:
+		sel, ok := fn.Pkg.info.Selections[e]
+		if !ok {
+			// qualified identifier
+			return b.expr(fn, e.Sel)
+		}
+		switch sel.Kind() {
+		case types.MethodExpr:
+			// (*T).f or T.f, the method f from the method-set of type T.
+			// The result is a "thunk".
+			return emitConv(fn, makeThunk(fn.Prog, sel), tv.Type)
+
+		case types.MethodVal:
+			// e.f where e is an expression and f is a method.
+			// The result is a "bound".
+			obj := sel.Obj().(*types.Func)
+			rt := recvType(obj)
+			wantAddr := isPointer(rt)
+			escaping := true
+			v := b.receiver(fn, e.X, wantAddr, escaping, sel)
+			if isInterface(rt) {
+				// If v has interface type I,
+				// we must emit a check that v is non-nil.
+				// We use: typeassert v.(I).
+				emitTypeAssert(fn, v, rt, token.NoPos)
+			}
+			c := &MakeClosure{
+				Fn:       makeBound(fn.Prog, obj),
+				Bindings: []Value{v},
+			}
+			c.setPos(e.Sel.Pos())
+			c.setType(tv.Type)
+			return fn.emit(c)
+
+		case types.FieldVal:
+			indices := sel.Index()
+			last := len(indices) - 1
+			v := b.expr(fn, e.X)
+			v = emitImplicitSelections(fn, v, indices[:last])
+			v = emitFieldSelection(fn, v, indices[last], false, e.Sel)
+			return v
+		}
+
+		panic("unexpected expression-relative selector")
+
+	case *ast.IndexExpr:
+		switch t := fn.Pkg.typeOf(e.X).Underlying().(type) {
+		case *types.Array:
+			// Non-addressable array (in a register).
+			v := &Index{
+				X:     b.expr(fn, e.X),
+				Index: emitConv(fn, b.expr(fn, e.Index), tInt),
+			}
+			v.setPos(e.Lbrack)
+			v.setType(t.Elem())
+			return fn.emit(v)
+
+		case *types.Map:
+			// Maps are not addressable.
+			mapt := fn.Pkg.typeOf(e.X).Underlying().(*types.Map)
+			v := &Lookup{
+				X:     b.expr(fn, e.X),
+				Index: emitConv(fn, b.expr(fn, e.Index), mapt.Key()),
+			}
+			v.setPos(e.Lbrack)
+			v.setType(mapt.Elem())
+			return fn.emit(v)
+
+		case *types.Basic: // => string
+			// Strings are not addressable.
+			v := &Lookup{
+				X:     b.expr(fn, e.X),
+				Index: b.expr(fn, e.Index),
+			}
+			v.setPos(e.Lbrack)
+			v.setType(tByte)
+			return fn.emit(v)
+
+		case *types.Slice, *types.Pointer: // *array
+			// Addressable slice/array; use IndexAddr and Load.
+			return b.addr(fn, e, false).load(fn)
+
+		default:
+			panic("unexpected container type in IndexExpr: " + t.String())
+		}
+
+	case *ast.CompositeLit, *ast.StarExpr:
+		// Addressable types (lvalues)
+		return b.addr(fn, e, false).load(fn)
+	}
+
+	panic(fmt.Sprintf("unexpected expr: %T", e))
+}
+
+// stmtList emits to fn code for all statements in list.
+func (b *builder) stmtList(fn *Function, list []ast.Stmt) {
+	for _, s := range list {
+		b.stmt(fn, s)
+	}
+}
+
+// receiver emits to fn code for expression e in the "receiver"
+// position of selection e.f (where f may be a field or a method) and
+// returns the effective receiver after applying the implicit field
+// selections of sel.
+//
+// wantAddr requests that the result is an an address.  If
+// !sel.Indirect(), this may require that e be built in addr() mode; it
+// must thus be addressable.
+//
+// escaping is defined as per builder.addr().
+//
+func (b *builder) receiver(fn *Function, e ast.Expr, wantAddr, escaping bool, sel *types.Selection) Value {
+	var v Value
+	if wantAddr && !sel.Indirect() && !isPointer(fn.Pkg.typeOf(e)) {
+		v = b.addr(fn, e, escaping).address(fn)
+	} else {
+		v = b.expr(fn, e)
+	}
+
+	last := len(sel.Index()) - 1
+	v = emitImplicitSelections(fn, v, sel.Index()[:last])
+	if !wantAddr && isPointer(v.Type()) {
+		v = emitLoad(fn, v)
+	}
+	return v
+}
+
+// setCallFunc populates the function parts of a CallCommon structure
+// (Func, Method, Recv, Args[0]) based on the kind of invocation
+// occurring in e.
+//
+func (b *builder) setCallFunc(fn *Function, e *ast.CallExpr, c *CallCommon) {
+	c.pos = e.Lparen
+
+	// Is this a method call?
+	if selector, ok := unparen(e.Fun).(*ast.SelectorExpr); ok {
+		sel, ok := fn.Pkg.info.Selections[selector]
+		if ok && sel.Kind() == types.MethodVal {
+			obj := sel.Obj().(*types.Func)
+			recv := recvType(obj)
+			wantAddr := isPointer(recv)
+			escaping := true
+			v := b.receiver(fn, selector.X, wantAddr, escaping, sel)
+			if isInterface(recv) {
+				// Invoke-mode call.
+				c.Value = v
+				c.Method = obj
+			} else {
+				// "Call"-mode call.
+				c.Value = fn.Prog.declaredFunc(obj)
+				c.Args = append(c.Args, v)
+			}
+			return
+		}
+
+		// sel.Kind()==MethodExpr indicates T.f() or (*T).f():
+		// a statically dispatched call to the method f in the
+		// method-set of T or *T.  T may be an interface.
+		//
+		// e.Fun would evaluate to a concrete method, interface
+		// wrapper function, or promotion wrapper.
+		//
+		// For now, we evaluate it in the usual way.
+		//
+		// TODO(adonovan): opt: inline expr() here, to make the
+		// call static and to avoid generation of wrappers.
+		// It's somewhat tricky as it may consume the first
+		// actual parameter if the call is "invoke" mode.
+		//
+		// Examples:
+		//  type T struct{}; func (T) f() {}   // "call" mode
+		//  type T interface { f() }           // "invoke" mode
+		//
+		//  type S struct{ T }
+		//
+		//  var s S
+		//  S.f(s)
+		//  (*S).f(&s)
+		//
+		// Suggested approach:
+		// - consume the first actual parameter expression
+		//   and build it with b.expr().
+		// - apply implicit field selections.
+		// - use MethodVal logic to populate fields of c.
+	}
+
+	// Evaluate the function operand in the usual way.
+	c.Value = b.expr(fn, e.Fun)
+}
+
+// emitCallArgs emits to f code for the actual parameters of call e to
+// a (possibly built-in) function of effective type sig.
+// The argument values are appended to args, which is then returned.
+//
+func (b *builder) emitCallArgs(fn *Function, sig *types.Signature, e *ast.CallExpr, args []Value) []Value {
+	// f(x, y, z...): pass slice z straight through.
+	if e.Ellipsis != 0 {
+		for i, arg := range e.Args {
+			v := emitConv(fn, b.expr(fn, arg), sig.Params().At(i).Type())
+			args = append(args, v)
+		}
+		return args
+	}
+
+	offset := len(args) // 1 if call has receiver, 0 otherwise
+
+	// Evaluate actual parameter expressions.
+	//
+	// If this is a chained call of the form f(g()) where g has
+	// multiple return values (MRV), they are flattened out into
+	// args; a suffix of them may end up in a varargs slice.
+	for _, arg := range e.Args {
+		v := b.expr(fn, arg)
+		if ttuple, ok := v.Type().(*types.Tuple); ok { // MRV chain
+			for i, n := 0, ttuple.Len(); i < n; i++ {
+				args = append(args, emitExtract(fn, v, i))
+			}
+		} else {
+			args = append(args, v)
+		}
+	}
+
+	// Actual->formal assignability conversions for normal parameters.
+	np := sig.Params().Len() // number of normal parameters
+	if sig.Variadic() {
+		np--
+	}
+	for i := 0; i < np; i++ {
+		args[offset+i] = emitConv(fn, args[offset+i], sig.Params().At(i).Type())
+	}
+
+	// Actual->formal assignability conversions for variadic parameter,
+	// and construction of slice.
+	if sig.Variadic() {
+		varargs := args[offset+np:]
+		st := sig.Params().At(np).Type().(*types.Slice)
+		vt := st.Elem()
+		if len(varargs) == 0 {
+			args = append(args, nilConst(st))
+		} else {
+			// Replace a suffix of args with a slice containing it.
+			at := types.NewArray(vt, int64(len(varargs)))
+			a := emitNew(fn, at, token.NoPos)
+			a.setPos(e.Rparen)
+			a.Comment = "varargs"
+			for i, arg := range varargs {
+				iaddr := &IndexAddr{
+					X:     a,
+					Index: intConst(int64(i)),
+				}
+				iaddr.setType(types.NewPointer(vt))
+				fn.emit(iaddr)
+				emitStore(fn, iaddr, arg, arg.Pos())
+			}
+			s := &Slice{X: a}
+			s.setType(st)
+			args[offset+np] = fn.emit(s)
+			args = args[:offset+np+1]
+		}
+	}
+	return args
+}
+
+// setCall emits to fn code to evaluate all the parameters of a function
+// call e, and populates *c with those values.
+//
+func (b *builder) setCall(fn *Function, e *ast.CallExpr, c *CallCommon) {
+	// First deal with the f(...) part and optional receiver.
+	b.setCallFunc(fn, e, c)
+
+	// Then append the other actual parameters.
+	sig, _ := fn.Pkg.typeOf(e.Fun).Underlying().(*types.Signature)
+	if sig == nil {
+		panic(fmt.Sprintf("no signature for call of %s", e.Fun))
+	}
+	c.Args = b.emitCallArgs(fn, sig, e, c.Args)
+}
+
+// assignOp emits to fn code to perform loc += incr or loc -= incr.
+func (b *builder) assignOp(fn *Function, loc lvalue, incr Value, op token.Token) {
+	oldv := loc.load(fn)
+	loc.store(fn, emitArith(fn, op, oldv, emitConv(fn, incr, oldv.Type()), loc.typ(), token.NoPos))
+}
+
+// localValueSpec emits to fn code to define all of the vars in the
+// function-local ValueSpec, spec.
+//
+func (b *builder) localValueSpec(fn *Function, spec *ast.ValueSpec) {
+	switch {
+	case len(spec.Values) == len(spec.Names):
+		// e.g. var x, y = 0, 1
+		// 1:1 assignment
+		for i, id := range spec.Names {
+			if !isBlankIdent(id) {
+				fn.addLocalForIdent(id)
+			}
+			lval := b.addr(fn, id, false) // non-escaping
+			b.assign(fn, lval, spec.Values[i], true, nil)
+		}
+
+	case len(spec.Values) == 0:
+		// e.g. var x, y int
+		// Locals are implicitly zero-initialized.
+		for _, id := range spec.Names {
+			if !isBlankIdent(id) {
+				lhs := fn.addLocalForIdent(id)
+				if fn.debugInfo() {
+					emitDebugRef(fn, id, lhs, true)
+				}
+			}
+		}
+
+	default:
+		// e.g. var x, y = pos()
+		tuple := b.exprN(fn, spec.Values[0])
+		for i, id := range spec.Names {
+			if !isBlankIdent(id) {
+				fn.addLocalForIdent(id)
+				lhs := b.addr(fn, id, false) // non-escaping
+				lhs.store(fn, emitExtract(fn, tuple, i))
+			}
+		}
+	}
+}
+
+// assignStmt emits code to fn for a parallel assignment of rhss to lhss.
+// isDef is true if this is a short variable declaration (:=).
+//
+// Note the similarity with localValueSpec.
+//
+func (b *builder) assignStmt(fn *Function, lhss, rhss []ast.Expr, isDef bool) {
+	// Side effects of all LHSs and RHSs must occur in left-to-right order.
+	lvals := make([]lvalue, len(lhss))
+	isZero := make([]bool, len(lhss))
+	for i, lhs := range lhss {
+		var lval lvalue = blank{}
+		if !isBlankIdent(lhs) {
+			if isDef {
+				if obj := fn.Pkg.info.Defs[lhs.(*ast.Ident)]; obj != nil {
+					fn.addNamedLocal(obj)
+					isZero[i] = true
+				}
+			}
+			lval = b.addr(fn, lhs, false) // non-escaping
+		}
+		lvals[i] = lval
+	}
+	if len(lhss) == len(rhss) {
+		// Simple assignment:   x     = f()        (!isDef)
+		// Parallel assignment: x, y  = f(), g()   (!isDef)
+		// or short var decl:   x, y := f(), g()   (isDef)
+		//
+		// In all cases, the RHSs may refer to the LHSs,
+		// so we need a storebuf.
+		var sb storebuf
+		for i := range rhss {
+			b.assign(fn, lvals[i], rhss[i], isZero[i], &sb)
+		}
+		sb.emit(fn)
+	} else {
+		// e.g. x, y = pos()
+		tuple := b.exprN(fn, rhss[0])
+		for i, lval := range lvals {
+			lval.store(fn, emitExtract(fn, tuple, i))
+		}
+	}
+}
+
+// arrayLen returns the length of the array whose composite literal elements are elts.
+func (b *builder) arrayLen(fn *Function, elts []ast.Expr) int64 {
+	var max int64 = -1
+	var i int64 = -1
+	for _, e := range elts {
+		if kv, ok := e.(*ast.KeyValueExpr); ok {
+			i = b.expr(fn, kv.Key).(*Const).Int64()
+		} else {
+			i++
+		}
+		if i > max {
+			max = i
+		}
+	}
+	return max + 1
+}
+
+// compLit emits to fn code to initialize a composite literal e at
+// address addr with type typ.
+//
+// Nested composite literals are recursively initialized in place
+// where possible. If isZero is true, compLit assumes that addr
+// holds the zero value for typ.
+//
+// Because the elements of a composite literal may refer to the
+// variables being updated, as in the second line below,
+//	x := T{a: 1}
+//	x = T{a: x.a}
+// all the reads must occur before all the writes.  Thus all stores to
+// loc are emitted to the storebuf sb for later execution.
+//
+// A CompositeLit may have pointer type only in the recursive (nested)
+// case when the type name is implicit.  e.g. in []*T{{}}, the inner
+// literal has type *T behaves like &T{}.
+// In that case, addr must hold a T, not a *T.
+//
+func (b *builder) compLit(fn *Function, addr Value, e *ast.CompositeLit, isZero bool, sb *storebuf) {
+	typ := deref(fn.Pkg.typeOf(e))
+	switch t := typ.Underlying().(type) {
+	case *types.Struct:
+		if !isZero && len(e.Elts) != t.NumFields() {
+			// memclear
+			sb.store(&address{addr, e.Lbrace, nil},
+				zeroValue(fn, deref(addr.Type())))
+			isZero = true
+		}
+		for i, e := range e.Elts {
+			fieldIndex := i
+			pos := e.Pos()
+			if kv, ok := e.(*ast.KeyValueExpr); ok {
+				fname := kv.Key.(*ast.Ident).Name
+				for i, n := 0, t.NumFields(); i < n; i++ {
+					sf := t.Field(i)
+					if sf.Name() == fname {
+						fieldIndex = i
+						pos = kv.Colon
+						e = kv.Value
+						break
+					}
+				}
+			}
+			sf := t.Field(fieldIndex)
+			faddr := &FieldAddr{
+				X:     addr,
+				Field: fieldIndex,
+			}
+			faddr.setType(types.NewPointer(sf.Type()))
+			fn.emit(faddr)
+			b.assign(fn, &address{addr: faddr, pos: pos, expr: e}, e, isZero, sb)
+		}
+
+	case *types.Array, *types.Slice:
+		var at *types.Array
+		var array Value
+		switch t := t.(type) {
+		case *types.Slice:
+			at = types.NewArray(t.Elem(), b.arrayLen(fn, e.Elts))
+			alloc := emitNew(fn, at, e.Lbrace)
+			alloc.Comment = "slicelit"
+			array = alloc
+		case *types.Array:
+			at = t
+			array = addr
+
+			if !isZero && int64(len(e.Elts)) != at.Len() {
+				// memclear
+				sb.store(&address{array, e.Lbrace, nil},
+					zeroValue(fn, deref(array.Type())))
+			}
+		}
+
+		var idx *Const
+		for _, e := range e.Elts {
+			pos := e.Pos()
+			if kv, ok := e.(*ast.KeyValueExpr); ok {
+				idx = b.expr(fn, kv.Key).(*Const)
+				pos = kv.Colon
+				e = kv.Value
+			} else {
+				var idxval int64
+				if idx != nil {
+					idxval = idx.Int64() + 1
+				}
+				idx = intConst(idxval)
+			}
+			iaddr := &IndexAddr{
+				X:     array,
+				Index: idx,
+			}
+			iaddr.setType(types.NewPointer(at.Elem()))
+			fn.emit(iaddr)
+			if t != at { // slice
+				// backing array is unaliased => storebuf not needed.
+				b.assign(fn, &address{addr: iaddr, pos: pos, expr: e}, e, true, nil)
+			} else {
+				b.assign(fn, &address{addr: iaddr, pos: pos, expr: e}, e, true, sb)
+			}
+		}
+
+		if t != at { // slice
+			s := &Slice{X: array}
+			s.setPos(e.Lbrace)
+			s.setType(typ)
+			sb.store(&address{addr: addr, pos: e.Lbrace, expr: e}, fn.emit(s))
+		}
+
+	case *types.Map:
+		m := &MakeMap{Reserve: intConst(int64(len(e.Elts)))}
+		m.setPos(e.Lbrace)
+		m.setType(typ)
+		fn.emit(m)
+		for _, e := range e.Elts {
+			e := e.(*ast.KeyValueExpr)
+			loc := element{
+				m:   m,
+				k:   emitConv(fn, b.expr(fn, e.Key), t.Key()),
+				t:   t.Elem(),
+				pos: e.Colon,
+			}
+
+			// We call assign() only because it takes care
+			// of any &-operation required in the recursive
+			// case, e.g.,
+			// map[int]*struct{}{0: {}} implies &struct{}{}.
+			// In-place update is of course impossible,
+			// and no storebuf is needed.
+			b.assign(fn, &loc, e.Value, true, nil)
+		}
+		sb.store(&address{addr: addr, pos: e.Lbrace, expr: e}, m)
+
+	default:
+		panic("unexpected CompositeLit type: " + t.String())
+	}
+}
+
+// switchStmt emits to fn code for the switch statement s, optionally
+// labelled by label.
+//
+func (b *builder) switchStmt(fn *Function, s *ast.SwitchStmt, label *lblock) {
+	// We treat SwitchStmt like a sequential if-else chain.
+	// Multiway dispatch can be recovered later by ssautil.Switches()
+	// to those cases that are free of side effects.
+	if s.Init != nil {
+		b.stmt(fn, s.Init)
+	}
+	var tag Value = vTrue
+	if s.Tag != nil {
+		tag = b.expr(fn, s.Tag)
+	}
+	done := fn.newBasicBlock("switch.done")
+	if label != nil {
+		label._break = done
+	}
+	// We pull the default case (if present) down to the end.
+	// But each fallthrough label must point to the next
+	// body block in source order, so we preallocate a
+	// body block (fallthru) for the next case.
+	// Unfortunately this makes for a confusing block order.
+	var dfltBody *[]ast.Stmt
+	var dfltFallthrough *BasicBlock
+	var fallthru, dfltBlock *BasicBlock
+	ncases := len(s.Body.List)
+	for i, clause := range s.Body.List {
+		body := fallthru
+		if body == nil {
+			body = fn.newBasicBlock("switch.body") // first case only
+		}
+
+		// Preallocate body block for the next case.
+		fallthru = done
+		if i+1 < ncases {
+			fallthru = fn.newBasicBlock("switch.body")
+		}
+
+		cc := clause.(*ast.CaseClause)
+		if cc.List == nil {
+			// Default case.
+			dfltBody = &cc.Body
+			dfltFallthrough = fallthru
+			dfltBlock = body
+			continue
+		}
+
+		var nextCond *BasicBlock
+		for _, cond := range cc.List {
+			nextCond = fn.newBasicBlock("switch.next")
+			// TODO(adonovan): opt: when tag==vTrue, we'd
+			// get better code if we use b.cond(cond)
+			// instead of BinOp(EQL, tag, b.expr(cond))
+			// followed by If.  Don't forget conversions
+			// though.
+			cond := emitCompare(fn, token.EQL, tag, b.expr(fn, cond), token.NoPos)
+			emitIf(fn, cond, body, nextCond)
+			fn.currentBlock = nextCond
+		}
+		fn.currentBlock = body
+		fn.targets = &targets{
+			tail:         fn.targets,
+			_break:       done,
+			_fallthrough: fallthru,
+		}
+		b.stmtList(fn, cc.Body)
+		fn.targets = fn.targets.tail
+		emitJump(fn, done)
+		fn.currentBlock = nextCond
+	}
+	if dfltBlock != nil {
+		emitJump(fn, dfltBlock)
+		fn.currentBlock = dfltBlock
+		fn.targets = &targets{
+			tail:         fn.targets,
+			_break:       done,
+			_fallthrough: dfltFallthrough,
+		}
+		b.stmtList(fn, *dfltBody)
+		fn.targets = fn.targets.tail
+	}
+	emitJump(fn, done)
+	fn.currentBlock = done
+}
+
+// typeSwitchStmt emits to fn code for the type switch statement s, optionally
+// labelled by label.
+//
+func (b *builder) typeSwitchStmt(fn *Function, s *ast.TypeSwitchStmt, label *lblock) {
+	// We treat TypeSwitchStmt like a sequential if-else chain.
+	// Multiway dispatch can be recovered later by ssautil.Switches().
+
+	// Typeswitch lowering:
+	//
+	// var x X
+	// switch y := x.(type) {
+	// case T1, T2: S1                  // >1 	(y := x)
+	// case nil:    SN                  // nil 	(y := x)
+	// default:     SD                  // 0 types 	(y := x)
+	// case T3:     S3                  // 1 type 	(y := x.(T3))
+	// }
+	//
+	//      ...s.Init...
+	// 	x := eval x
+	// .caseT1:
+	// 	t1, ok1 := typeswitch,ok x <T1>
+	// 	if ok1 then goto S1 else goto .caseT2
+	// .caseT2:
+	// 	t2, ok2 := typeswitch,ok x <T2>
+	// 	if ok2 then goto S1 else goto .caseNil
+	// .S1:
+	//      y := x
+	// 	...S1...
+	// 	goto done
+	// .caseNil:
+	// 	if t2, ok2 := typeswitch,ok x <T2>
+	// 	if x == nil then goto SN else goto .caseT3
+	// .SN:
+	//      y := x
+	// 	...SN...
+	// 	goto done
+	// .caseT3:
+	// 	t3, ok3 := typeswitch,ok x <T3>
+	// 	if ok3 then goto S3 else goto default
+	// .S3:
+	//      y := t3
+	// 	...S3...
+	// 	goto done
+	// .default:
+	//      y := x
+	// 	...SD...
+	// 	goto done
+	// .done:
+
+	if s.Init != nil {
+		b.stmt(fn, s.Init)
+	}
+
+	var x Value
+	switch ass := s.Assign.(type) {
+	case *ast.ExprStmt: // x.(type)
+		x = b.expr(fn, unparen(ass.X).(*ast.TypeAssertExpr).X)
+	case *ast.AssignStmt: // y := x.(type)
+		x = b.expr(fn, unparen(ass.Rhs[0]).(*ast.TypeAssertExpr).X)
+	}
+
+	done := fn.newBasicBlock("typeswitch.done")
+	if label != nil {
+		label._break = done
+	}
+	var default_ *ast.CaseClause
+	for _, clause := range s.Body.List {
+		cc := clause.(*ast.CaseClause)
+		if cc.List == nil {
+			default_ = cc
+			continue
+		}
+		body := fn.newBasicBlock("typeswitch.body")
+		var next *BasicBlock
+		var casetype types.Type
+		var ti Value // ti, ok := typeassert,ok x <Ti>
+		for _, cond := range cc.List {
+			next = fn.newBasicBlock("typeswitch.next")
+			casetype = fn.Pkg.typeOf(cond)
+			var condv Value
+			if casetype == tUntypedNil {
+				condv = emitCompare(fn, token.EQL, x, nilConst(x.Type()), token.NoPos)
+				ti = x
+			} else {
+				yok := emitTypeTest(fn, x, casetype, cc.Case)
+				ti = emitExtract(fn, yok, 0)
+				condv = emitExtract(fn, yok, 1)
+			}
+			emitIf(fn, condv, body, next)
+			fn.currentBlock = next
+		}
+		if len(cc.List) != 1 {
+			ti = x
+		}
+		fn.currentBlock = body
+		b.typeCaseBody(fn, cc, ti, done)
+		fn.currentBlock = next
+	}
+	if default_ != nil {
+		b.typeCaseBody(fn, default_, x, done)
+	} else {
+		emitJump(fn, done)
+	}
+	fn.currentBlock = done
+}
+
+func (b *builder) typeCaseBody(fn *Function, cc *ast.CaseClause, x Value, done *BasicBlock) {
+	if obj := fn.Pkg.info.Implicits[cc]; obj != nil {
+		// In a switch y := x.(type), each case clause
+		// implicitly declares a distinct object y.
+		// In a single-type case, y has that type.
+		// In multi-type cases, 'case nil' and default,
+		// y has the same type as the interface operand.
+		emitStore(fn, fn.addNamedLocal(obj), x, obj.Pos())
+	}
+	fn.targets = &targets{
+		tail:   fn.targets,
+		_break: done,
+	}
+	b.stmtList(fn, cc.Body)
+	fn.targets = fn.targets.tail
+	emitJump(fn, done)
+}
+
+// selectStmt emits to fn code for the select statement s, optionally
+// labelled by label.
+//
+func (b *builder) selectStmt(fn *Function, s *ast.SelectStmt, label *lblock) {
+	// A blocking select of a single case degenerates to a
+	// simple send or receive.
+	// TODO(adonovan): opt: is this optimization worth its weight?
+	if len(s.Body.List) == 1 {
+		clause := s.Body.List[0].(*ast.CommClause)
+		if clause.Comm != nil {
+			b.stmt(fn, clause.Comm)
+			done := fn.newBasicBlock("select.done")
+			if label != nil {
+				label._break = done
+			}
+			fn.targets = &targets{
+				tail:   fn.targets,
+				_break: done,
+			}
+			b.stmtList(fn, clause.Body)
+			fn.targets = fn.targets.tail
+			emitJump(fn, done)
+			fn.currentBlock = done
+			return
+		}
+	}
+
+	// First evaluate all channels in all cases, and find
+	// the directions of each state.
+	var states []*SelectState
+	blocking := true
+	debugInfo := fn.debugInfo()
+	for _, clause := range s.Body.List {
+		var st *SelectState
+		switch comm := clause.(*ast.CommClause).Comm.(type) {
+		case nil: // default case
+			blocking = false
+			continue
+
+		case *ast.SendStmt: // ch<- i
+			ch := b.expr(fn, comm.Chan)
+			st = &SelectState{
+				Dir:  types.SendOnly,
+				Chan: ch,
+				Send: emitConv(fn, b.expr(fn, comm.Value),
+					ch.Type().Underlying().(*types.Chan).Elem()),
+				Pos: comm.Arrow,
+			}
+			if debugInfo {
+				st.DebugNode = comm
+			}
+
+		case *ast.AssignStmt: // x := <-ch
+			recv := unparen(comm.Rhs[0]).(*ast.UnaryExpr)
+			st = &SelectState{
+				Dir:  types.RecvOnly,
+				Chan: b.expr(fn, recv.X),
+				Pos:  recv.OpPos,
+			}
+			if debugInfo {
+				st.DebugNode = recv
+			}
+
+		case *ast.ExprStmt: // <-ch
+			recv := unparen(comm.X).(*ast.UnaryExpr)
+			st = &SelectState{
+				Dir:  types.RecvOnly,
+				Chan: b.expr(fn, recv.X),
+				Pos:  recv.OpPos,
+			}
+			if debugInfo {
+				st.DebugNode = recv
+			}
+		}
+		states = append(states, st)
+	}
+
+	// We dispatch on the (fair) result of Select using a
+	// sequential if-else chain, in effect:
+	//
+	// idx, recvOk, r0...r_n-1 := select(...)
+	// if idx == 0 {  // receive on channel 0  (first receive => r0)
+	//     x, ok := r0, recvOk
+	//     ...state0...
+	// } else if v == 1 {   // send on channel 1
+	//     ...state1...
+	// } else {
+	//     ...default...
+	// }
+	sel := &Select{
+		States:   states,
+		Blocking: blocking,
+	}
+	sel.setPos(s.Select)
+	var vars []*types.Var
+	vars = append(vars, varIndex, varOk)
+	for _, st := range states {
+		if st.Dir == types.RecvOnly {
+			tElem := st.Chan.Type().Underlying().(*types.Chan).Elem()
+			vars = append(vars, anonVar(tElem))
+		}
+	}
+	sel.setType(types.NewTuple(vars...))
+
+	fn.emit(sel)
+	idx := emitExtract(fn, sel, 0)
+
+	done := fn.newBasicBlock("select.done")
+	if label != nil {
+		label._break = done
+	}
+
+	var defaultBody *[]ast.Stmt
+	state := 0
+	r := 2 // index in 'sel' tuple of value; increments if st.Dir==RECV
+	for _, cc := range s.Body.List {
+		clause := cc.(*ast.CommClause)
+		if clause.Comm == nil {
+			defaultBody = &clause.Body
+			continue
+		}
+		body := fn.newBasicBlock("select.body")
+		next := fn.newBasicBlock("select.next")
+		emitIf(fn, emitCompare(fn, token.EQL, idx, intConst(int64(state)), token.NoPos), body, next)
+		fn.currentBlock = body
+		fn.targets = &targets{
+			tail:   fn.targets,
+			_break: done,
+		}
+		switch comm := clause.Comm.(type) {
+		case *ast.ExprStmt: // <-ch
+			if debugInfo {
+				v := emitExtract(fn, sel, r)
+				emitDebugRef(fn, states[state].DebugNode.(ast.Expr), v, false)
+			}
+			r++
+
+		case *ast.AssignStmt: // x := <-states[state].Chan
+			if comm.Tok == token.DEFINE {
+				fn.addLocalForIdent(comm.Lhs[0].(*ast.Ident))
+			}
+			x := b.addr(fn, comm.Lhs[0], false) // non-escaping
+			v := emitExtract(fn, sel, r)
+			if debugInfo {
+				emitDebugRef(fn, states[state].DebugNode.(ast.Expr), v, false)
+			}
+			x.store(fn, v)
+
+			if len(comm.Lhs) == 2 { // x, ok := ...
+				if comm.Tok == token.DEFINE {
+					fn.addLocalForIdent(comm.Lhs[1].(*ast.Ident))
+				}
+				ok := b.addr(fn, comm.Lhs[1], false) // non-escaping
+				ok.store(fn, emitExtract(fn, sel, 1))
+			}
+			r++
+		}
+		b.stmtList(fn, clause.Body)
+		fn.targets = fn.targets.tail
+		emitJump(fn, done)
+		fn.currentBlock = next
+		state++
+	}
+	if defaultBody != nil {
+		fn.targets = &targets{
+			tail:   fn.targets,
+			_break: done,
+		}
+		b.stmtList(fn, *defaultBody)
+		fn.targets = fn.targets.tail
+	} else {
+		// A blocking select must match some case.
+		// (This should really be a runtime.errorString, not a string.)
+		fn.emit(&Panic{
+			X: emitConv(fn, stringConst("blocking select matched no case"), tEface),
+		})
+		fn.currentBlock = fn.newBasicBlock("unreachable")
+	}
+	emitJump(fn, done)
+	fn.currentBlock = done
+}
+
+// forStmt emits to fn code for the for statement s, optionally
+// labelled by label.
+//
+func (b *builder) forStmt(fn *Function, s *ast.ForStmt, label *lblock) {
+	//	...init...
+	//      jump loop
+	// loop:
+	//      if cond goto body else done
+	// body:
+	//      ...body...
+	//      jump post
+	// post:				 (target of continue)
+	//      ...post...
+	//      jump loop
+	// done:                                 (target of break)
+	if s.Init != nil {
+		b.stmt(fn, s.Init)
+	}
+	body := fn.newBasicBlock("for.body")
+	done := fn.newBasicBlock("for.done") // target of 'break'
+	loop := body                         // target of back-edge
+	if s.Cond != nil {
+		loop = fn.newBasicBlock("for.loop")
+	}
+	cont := loop // target of 'continue'
+	if s.Post != nil {
+		cont = fn.newBasicBlock("for.post")
+	}
+	if label != nil {
+		label._break = done
+		label._continue = cont
+	}
+	emitJump(fn, loop)
+	fn.currentBlock = loop
+	if loop != body {
+		b.cond(fn, s.Cond, body, done)
+		fn.currentBlock = body
+	}
+	fn.targets = &targets{
+		tail:      fn.targets,
+		_break:    done,
+		_continue: cont,
+	}
+	b.stmt(fn, s.Body)
+	fn.targets = fn.targets.tail
+	emitJump(fn, cont)
+
+	if s.Post != nil {
+		fn.currentBlock = cont
+		b.stmt(fn, s.Post)
+		emitJump(fn, loop) // back-edge
+	}
+	fn.currentBlock = done
+}
+
+// rangeIndexed emits to fn the header for an integer-indexed loop
+// over array, *array or slice value x.
+// The v result is defined only if tv is non-nil.
+// forPos is the position of the "for" token.
+//
+func (b *builder) rangeIndexed(fn *Function, x Value, tv types.Type, pos token.Pos) (k, v Value, loop, done *BasicBlock) {
+	//
+	//      length = len(x)
+	//      index = -1
+	// loop:                                   (target of continue)
+	//      index++
+	// 	if index < length goto body else done
+	// body:
+	//      k = index
+	//      v = x[index]
+	//      ...body...
+	// 	jump loop
+	// done:                                   (target of break)
+
+	// Determine number of iterations.
+	var length Value
+	if arr, ok := deref(x.Type()).Underlying().(*types.Array); ok {
+		// For array or *array, the number of iterations is
+		// known statically thanks to the type.  We avoid a
+		// data dependence upon x, permitting later dead-code
+		// elimination if x is pure, static unrolling, etc.
+		// Ranging over a nil *array may have >0 iterations.
+		// We still generate code for x, in case it has effects.
+		length = intConst(arr.Len())
+	} else {
+		// length = len(x).
+		var c Call
+		c.Call.Value = makeLen(x.Type())
+		c.Call.Args = []Value{x}
+		c.setType(tInt)
+		length = fn.emit(&c)
+	}
+
+	index := fn.addLocal(tInt, token.NoPos)
+	emitStore(fn, index, intConst(-1), pos)
+
+	loop = fn.newBasicBlock("rangeindex.loop")
+	emitJump(fn, loop)
+	fn.currentBlock = loop
+
+	incr := &BinOp{
+		Op: token.ADD,
+		X:  emitLoad(fn, index),
+		Y:  vOne,
+	}
+	incr.setType(tInt)
+	emitStore(fn, index, fn.emit(incr), pos)
+
+	body := fn.newBasicBlock("rangeindex.body")
+	done = fn.newBasicBlock("rangeindex.done")
+	emitIf(fn, emitCompare(fn, token.LSS, incr, length, token.NoPos), body, done)
+	fn.currentBlock = body
+
+	k = emitLoad(fn, index)
+	if tv != nil {
+		switch t := x.Type().Underlying().(type) {
+		case *types.Array:
+			instr := &Index{
+				X:     x,
+				Index: k,
+			}
+			instr.setType(t.Elem())
+			v = fn.emit(instr)
+
+		case *types.Pointer: // *array
+			instr := &IndexAddr{
+				X:     x,
+				Index: k,
+			}
+			instr.setType(types.NewPointer(t.Elem().Underlying().(*types.Array).Elem()))
+			v = emitLoad(fn, fn.emit(instr))
+
+		case *types.Slice:
+			instr := &IndexAddr{
+				X:     x,
+				Index: k,
+			}
+			instr.setType(types.NewPointer(t.Elem()))
+			v = emitLoad(fn, fn.emit(instr))
+
+		default:
+			panic("rangeIndexed x:" + t.String())
+		}
+	}
+	return
+}
+
+// rangeIter emits to fn the header for a loop using
+// Range/Next/Extract to iterate over map or string value x.
+// tk and tv are the types of the key/value results k and v, or nil
+// if the respective component is not wanted.
+//
+func (b *builder) rangeIter(fn *Function, x Value, tk, tv types.Type, pos token.Pos) (k, v Value, loop, done *BasicBlock) {
+	//
+	//	it = range x
+	// loop:                                   (target of continue)
+	//	okv = next it                      (ok, key, value)
+	//  	ok = extract okv #0
+	// 	if ok goto body else done
+	// body:
+	// 	k = extract okv #1
+	// 	v = extract okv #2
+	//      ...body...
+	// 	jump loop
+	// done:                                   (target of break)
+	//
+
+	if tk == nil {
+		tk = tInvalid
+	}
+	if tv == nil {
+		tv = tInvalid
+	}
+
+	rng := &Range{X: x}
+	rng.setPos(pos)
+	rng.setType(tRangeIter)
+	it := fn.emit(rng)
+
+	loop = fn.newBasicBlock("rangeiter.loop")
+	emitJump(fn, loop)
+	fn.currentBlock = loop
+
+	_, isString := x.Type().Underlying().(*types.Basic)
+
+	okv := &Next{
+		Iter:     it,
+		IsString: isString,
+	}
+	okv.setType(types.NewTuple(
+		varOk,
+		newVar("k", tk),
+		newVar("v", tv),
+	))
+	fn.emit(okv)
+
+	body := fn.newBasicBlock("rangeiter.body")
+	done = fn.newBasicBlock("rangeiter.done")
+	emitIf(fn, emitExtract(fn, okv, 0), body, done)
+	fn.currentBlock = body
+
+	if tk != tInvalid {
+		k = emitExtract(fn, okv, 1)
+	}
+	if tv != tInvalid {
+		v = emitExtract(fn, okv, 2)
+	}
+	return
+}
+
+// rangeChan emits to fn the header for a loop that receives from
+// channel x until it fails.
+// tk is the channel's element type, or nil if the k result is
+// not wanted
+// pos is the position of the '=' or ':=' token.
+//
+func (b *builder) rangeChan(fn *Function, x Value, tk types.Type, pos token.Pos) (k Value, loop, done *BasicBlock) {
+	//
+	// loop:                                   (target of continue)
+	//      ko = <-x                           (key, ok)
+	//      ok = extract ko #1
+	//      if ok goto body else done
+	// body:
+	//      k = extract ko #0
+	//      ...
+	//      goto loop
+	// done:                                   (target of break)
+
+	loop = fn.newBasicBlock("rangechan.loop")
+	emitJump(fn, loop)
+	fn.currentBlock = loop
+	recv := &UnOp{
+		Op:      token.ARROW,
+		X:       x,
+		CommaOk: true,
+	}
+	recv.setPos(pos)
+	recv.setType(types.NewTuple(
+		newVar("k", x.Type().Underlying().(*types.Chan).Elem()),
+		varOk,
+	))
+	ko := fn.emit(recv)
+	body := fn.newBasicBlock("rangechan.body")
+	done = fn.newBasicBlock("rangechan.done")
+	emitIf(fn, emitExtract(fn, ko, 1), body, done)
+	fn.currentBlock = body
+	if tk != nil {
+		k = emitExtract(fn, ko, 0)
+	}
+	return
+}
+
+// rangeStmt emits to fn code for the range statement s, optionally
+// labelled by label.
+//
+func (b *builder) rangeStmt(fn *Function, s *ast.RangeStmt, label *lblock) {
+	var tk, tv types.Type
+	if s.Key != nil && !isBlankIdent(s.Key) {
+		tk = fn.Pkg.typeOf(s.Key)
+	}
+	if s.Value != nil && !isBlankIdent(s.Value) {
+		tv = fn.Pkg.typeOf(s.Value)
+	}
+
+	// If iteration variables are defined (:=), this
+	// occurs once outside the loop.
+	//
+	// Unlike a short variable declaration, a RangeStmt
+	// using := never redeclares an existing variable; it
+	// always creates a new one.
+	if s.Tok == token.DEFINE {
+		if tk != nil {
+			fn.addLocalForIdent(s.Key.(*ast.Ident))
+		}
+		if tv != nil {
+			fn.addLocalForIdent(s.Value.(*ast.Ident))
+		}
+	}
+
+	x := b.expr(fn, s.X)
+
+	var k, v Value
+	var loop, done *BasicBlock
+	switch rt := x.Type().Underlying().(type) {
+	case *types.Slice, *types.Array, *types.Pointer: // *array
+		k, v, loop, done = b.rangeIndexed(fn, x, tv, s.For)
+
+	case *types.Chan:
+		k, loop, done = b.rangeChan(fn, x, tk, s.For)
+
+	case *types.Map, *types.Basic: // string
+		k, v, loop, done = b.rangeIter(fn, x, tk, tv, s.For)
+
+	default:
+		panic("Cannot range over: " + rt.String())
+	}
+
+	// Evaluate both LHS expressions before we update either.
+	var kl, vl lvalue
+	if tk != nil {
+		kl = b.addr(fn, s.Key, false) // non-escaping
+	}
+	if tv != nil {
+		vl = b.addr(fn, s.Value, false) // non-escaping
+	}
+	if tk != nil {
+		kl.store(fn, k)
+	}
+	if tv != nil {
+		vl.store(fn, v)
+	}
+
+	if label != nil {
+		label._break = done
+		label._continue = loop
+	}
+
+	fn.targets = &targets{
+		tail:      fn.targets,
+		_break:    done,
+		_continue: loop,
+	}
+	b.stmt(fn, s.Body)
+	fn.targets = fn.targets.tail
+	emitJump(fn, loop) // back-edge
+	fn.currentBlock = done
+}
+
+// stmt lowers statement s to SSA form, emitting code to fn.
+func (b *builder) stmt(fn *Function, _s ast.Stmt) {
+	// The label of the current statement.  If non-nil, its _goto
+	// target is always set; its _break and _continue are set only
+	// within the body of switch/typeswitch/select/for/range.
+	// It is effectively an additional default-nil parameter of stmt().
+	var label *lblock
+start:
+	switch s := _s.(type) {
+	case *ast.EmptyStmt:
+		// ignore.  (Usually removed by gofmt.)
+
+	case *ast.DeclStmt: // Con, Var or Typ
+		d := s.Decl.(*ast.GenDecl)
+		if d.Tok == token.VAR {
+			for _, spec := range d.Specs {
+				if vs, ok := spec.(*ast.ValueSpec); ok {
+					b.localValueSpec(fn, vs)
+				}
+			}
+		}
+
+	case *ast.LabeledStmt:
+		label = fn.labelledBlock(s.Label)
+		emitJump(fn, label._goto)
+		fn.currentBlock = label._goto
+		_s = s.Stmt
+		goto start // effectively: tailcall stmt(fn, s.Stmt, label)
+
+	case *ast.ExprStmt:
+		b.expr(fn, s.X)
+
+	case *ast.SendStmt:
+		fn.emit(&Send{
+			Chan: b.expr(fn, s.Chan),
+			X: emitConv(fn, b.expr(fn, s.Value),
+				fn.Pkg.typeOf(s.Chan).Underlying().(*types.Chan).Elem()),
+			pos: s.Arrow,
+		})
+
+	case *ast.IncDecStmt:
+		op := token.ADD
+		if s.Tok == token.DEC {
+			op = token.SUB
+		}
+		loc := b.addr(fn, s.X, false)
+		b.assignOp(fn, loc, NewConst(exact.MakeInt64(1), loc.typ()), op)
+
+	case *ast.AssignStmt:
+		switch s.Tok {
+		case token.ASSIGN, token.DEFINE:
+			b.assignStmt(fn, s.Lhs, s.Rhs, s.Tok == token.DEFINE)
+
+		default: // +=, etc.
+			op := s.Tok + token.ADD - token.ADD_ASSIGN
+			b.assignOp(fn, b.addr(fn, s.Lhs[0], false), b.expr(fn, s.Rhs[0]), op)
+		}
+
+	case *ast.GoStmt:
+		// The "intrinsics" new/make/len/cap are forbidden here.
+		// panic is treated like an ordinary function call.
+		v := Go{pos: s.Go}
+		b.setCall(fn, s.Call, &v.Call)
+		fn.emit(&v)
+
+	case *ast.DeferStmt:
+		// The "intrinsics" new/make/len/cap are forbidden here.
+		// panic is treated like an ordinary function call.
+		v := Defer{pos: s.Defer}
+		b.setCall(fn, s.Call, &v.Call)
+		fn.emit(&v)
+
+		// A deferred call can cause recovery from panic,
+		// and control resumes at the Recover block.
+		createRecoverBlock(fn)
+
+	case *ast.ReturnStmt:
+		var results []Value
+		if len(s.Results) == 1 && fn.Signature.Results().Len() > 1 {
+			// Return of one expression in a multi-valued function.
+			tuple := b.exprN(fn, s.Results[0])
+			ttuple := tuple.Type().(*types.Tuple)
+			for i, n := 0, ttuple.Len(); i < n; i++ {
+				results = append(results,
+					emitConv(fn, emitExtract(fn, tuple, i),
+						fn.Signature.Results().At(i).Type()))
+			}
+		} else {
+			// 1:1 return, or no-arg return in non-void function.
+			for i, r := range s.Results {
+				v := emitConv(fn, b.expr(fn, r), fn.Signature.Results().At(i).Type())
+				results = append(results, v)
+			}
+		}
+		if fn.namedResults != nil {
+			// Function has named result parameters (NRPs).
+			// Perform parallel assignment of return operands to NRPs.
+			for i, r := range results {
+				emitStore(fn, fn.namedResults[i], r, s.Return)
+			}
+		}
+		// Run function calls deferred in this
+		// function when explicitly returning from it.
+		fn.emit(new(RunDefers))
+		if fn.namedResults != nil {
+			// Reload NRPs to form the result tuple.
+			results = results[:0]
+			for _, r := range fn.namedResults {
+				results = append(results, emitLoad(fn, r))
+			}
+		}
+		fn.emit(&Return{Results: results, pos: s.Return})
+		fn.currentBlock = fn.newBasicBlock("unreachable")
+
+	case *ast.BranchStmt:
+		var block *BasicBlock
+		switch s.Tok {
+		case token.BREAK:
+			if s.Label != nil {
+				block = fn.labelledBlock(s.Label)._break
+			} else {
+				for t := fn.targets; t != nil && block == nil; t = t.tail {
+					block = t._break
+				}
+			}
+
+		case token.CONTINUE:
+			if s.Label != nil {
+				block = fn.labelledBlock(s.Label)._continue
+			} else {
+				for t := fn.targets; t != nil && block == nil; t = t.tail {
+					block = t._continue
+				}
+			}
+
+		case token.FALLTHROUGH:
+			for t := fn.targets; t != nil && block == nil; t = t.tail {
+				block = t._fallthrough
+			}
+
+		case token.GOTO:
+			block = fn.labelledBlock(s.Label)._goto
+		}
+		emitJump(fn, block)
+		fn.currentBlock = fn.newBasicBlock("unreachable")
+
+	case *ast.BlockStmt:
+		b.stmtList(fn, s.List)
+
+	case *ast.IfStmt:
+		if s.Init != nil {
+			b.stmt(fn, s.Init)
+		}
+		then := fn.newBasicBlock("if.then")
+		done := fn.newBasicBlock("if.done")
+		els := done
+		if s.Else != nil {
+			els = fn.newBasicBlock("if.else")
+		}
+		b.cond(fn, s.Cond, then, els)
+		fn.currentBlock = then
+		b.stmt(fn, s.Body)
+		emitJump(fn, done)
+
+		if s.Else != nil {
+			fn.currentBlock = els
+			b.stmt(fn, s.Else)
+			emitJump(fn, done)
+		}
+
+		fn.currentBlock = done
+
+	case *ast.SwitchStmt:
+		b.switchStmt(fn, s, label)
+
+	case *ast.TypeSwitchStmt:
+		b.typeSwitchStmt(fn, s, label)
+
+	case *ast.SelectStmt:
+		b.selectStmt(fn, s, label)
+
+	case *ast.ForStmt:
+		b.forStmt(fn, s, label)
+
+	case *ast.RangeStmt:
+		b.rangeStmt(fn, s, label)
+
+	default:
+		panic(fmt.Sprintf("unexpected statement kind: %T", s))
+	}
+}
+
+// buildFunction builds SSA code for the body of function fn.  Idempotent.
+func (b *builder) buildFunction(fn *Function) {
+	if fn.Blocks != nil {
+		return // building already started
+	}
+
+	var recvField *ast.FieldList
+	var body *ast.BlockStmt
+	var functype *ast.FuncType
+	switch n := fn.syntax.(type) {
+	case nil:
+		return // not a Go source function.  (Synthetic, or from object file.)
+	case *ast.FuncDecl:
+		functype = n.Type
+		recvField = n.Recv
+		body = n.Body
+	case *ast.FuncLit:
+		functype = n.Type
+		body = n.Body
+	default:
+		panic(n)
+	}
+
+	if body == nil {
+		// External function.
+		if fn.Params == nil {
+			// This condition ensures we add a non-empty
+			// params list once only, but we may attempt
+			// the degenerate empty case repeatedly.
+			// TODO(adonovan): opt: don't do that.
+
+			// We set Function.Params even though there is no body
+			// code to reference them.  This simplifies clients.
+			if recv := fn.Signature.Recv(); recv != nil {
+				fn.addParamObj(recv)
+			}
+			params := fn.Signature.Params()
+			for i, n := 0, params.Len(); i < n; i++ {
+				fn.addParamObj(params.At(i))
+			}
+		}
+		return
+	}
+	if fn.Prog.mode&LogSource != 0 {
+		defer logStack("build function %s @ %s", fn, fn.Prog.Fset.Position(fn.pos))()
+	}
+	fn.startBody()
+	fn.createSyntacticParams(recvField, functype)
+	b.stmt(fn, body)
+	if cb := fn.currentBlock; cb != nil && (cb == fn.Blocks[0] || cb == fn.Recover || cb.Preds != nil) {
+		// Control fell off the end of the function's body block.
+		//
+		// Block optimizations eliminate the current block, if
+		// unreachable.  It is a builder invariant that
+		// if this no-arg return is ill-typed for
+		// fn.Signature.Results, this block must be
+		// unreachable.  The sanity checker checks this.
+		fn.emit(new(RunDefers))
+		fn.emit(new(Return))
+	}
+	fn.finishBody()
+}
+
+// buildFuncDecl builds SSA code for the function or method declared
+// by decl in package pkg.
+//
+func (b *builder) buildFuncDecl(pkg *Package, decl *ast.FuncDecl) {
+	id := decl.Name
+	if isBlankIdent(id) {
+		return // discard
+	}
+	fn := pkg.values[pkg.info.Defs[id]].(*Function)
+	if decl.Recv == nil && id.Name == "init" {
+		var v Call
+		v.Call.Value = fn
+		v.setType(types.NewTuple())
+		pkg.init.emit(&v)
+	}
+	b.buildFunction(fn)
+}
+
+// BuildAll calls Package.Build() for each package in prog.
+// Building occurs in parallel unless the BuildSerially mode flag was set.
+//
+// BuildAll is intended for whole-program analysis; a typical compiler
+// need only build a single package.
+//
+// BuildAll is idempotent and thread-safe.
+//
+// TODO(adonovan): rename to Build.
+//
+func (prog *Program) BuildAll() {
+	var wg sync.WaitGroup
+	for _, p := range prog.packages {
+		if prog.mode&BuildSerially != 0 {
+			p.Build()
+		} else {
+			wg.Add(1)
+			go func(p *Package) {
+				p.Build()
+				wg.Done()
+			}(p)
+		}
+	}
+	wg.Wait()
+}
+
+// Build builds SSA code for all functions and vars in package p.
+//
+// Precondition: CreatePackage must have been called for all of p's
+// direct imports (and hence its direct imports must have been
+// error-free).
+//
+// Build is idempotent and thread-safe.
+//
+func (p *Package) Build() {
+	if !atomic.CompareAndSwapInt32(&p.started, 0, 1) {
+		return // already started
+	}
+	if p.info == nil {
+		return // synthetic package, e.g. "testmain"
+	}
+	if p.files == nil {
+		p.info = nil
+		return // package loaded from export data
+	}
+
+	// Ensure we have runtime type info for all exported members.
+	// TODO(adonovan): ideally belongs in memberFromObject, but
+	// that would require package creation in topological order.
+	for name, mem := range p.Members {
+		if ast.IsExported(name) {
+			p.Prog.needMethodsOf(mem.Type())
+		}
+	}
+	if p.Prog.mode&LogSource != 0 {
+		defer logStack("build %s", p)()
+	}
+	init := p.init
+	init.startBody()
+
+	var done *BasicBlock
+
+	if p.Prog.mode&BareInits == 0 {
+		// Make init() skip if package is already initialized.
+		initguard := p.Var("init$guard")
+		doinit := init.newBasicBlock("init.start")
+		done = init.newBasicBlock("init.done")
+		emitIf(init, emitLoad(init, initguard), done, doinit)
+		init.currentBlock = doinit
+		emitStore(init, initguard, vTrue, token.NoPos)
+
+		// Call the init() function of each package we import.
+		for _, pkg := range p.Object.Imports() {
+			prereq := p.Prog.packages[pkg]
+			if prereq == nil {
+				panic(fmt.Sprintf("Package(%q).Build(): unsatisfied import: Program.CreatePackage(%q) was not called", p.Object.Path(), pkg.Path()))
+			}
+			var v Call
+			v.Call.Value = prereq.init
+			v.Call.pos = init.pos
+			v.setType(types.NewTuple())
+			init.emit(&v)
+		}
+	}
+
+	var b builder
+
+	// Initialize package-level vars in correct order.
+	for _, varinit := range p.info.InitOrder {
+		if init.Prog.mode&LogSource != 0 {
+			fmt.Fprintf(os.Stderr, "build global initializer %v @ %s\n",
+				varinit.Lhs, p.Prog.Fset.Position(varinit.Rhs.Pos()))
+		}
+		if len(varinit.Lhs) == 1 {
+			// 1:1 initialization: var x, y = a(), b()
+			var lval lvalue
+			if v := varinit.Lhs[0]; v.Name() != "_" {
+				lval = &address{addr: p.values[v].(*Global), pos: v.Pos()}
+			} else {
+				lval = blank{}
+			}
+			b.assign(init, lval, varinit.Rhs, true, nil)
+		} else {
+			// n:1 initialization: var x, y :=  f()
+			tuple := b.exprN(init, varinit.Rhs)
+			for i, v := range varinit.Lhs {
+				if v.Name() == "_" {
+					continue
+				}
+				emitStore(init, p.values[v].(*Global), emitExtract(init, tuple, i), v.Pos())
+			}
+		}
+	}
+
+	// Build all package-level functions, init functions
+	// and methods, including unreachable/blank ones.
+	// We build them in source order, but it's not significant.
+	for _, file := range p.files {
+		for _, decl := range file.Decls {
+			if decl, ok := decl.(*ast.FuncDecl); ok {
+				b.buildFuncDecl(p, decl)
+			}
+		}
+	}
+
+	// Finish up init().
+	if p.Prog.mode&BareInits == 0 {
+		emitJump(init, done)
+		init.currentBlock = done
+	}
+	init.emit(new(Return))
+	init.finishBody()
+
+	p.info = nil // We no longer need ASTs or go/types deductions.
+
+	if p.Prog.mode&SanityCheckFunctions != 0 {
+		sanityCheckPackage(p)
+	}
+}
+
+// Like ObjectOf, but panics instead of returning nil.
+// Only valid during p's create and build phases.
+func (p *Package) objectOf(id *ast.Ident) types.Object {
+	if o := p.info.ObjectOf(id); o != nil {
+		return o
+	}
+	panic(fmt.Sprintf("no types.Object for ast.Ident %s @ %s",
+		id.Name, p.Prog.Fset.Position(id.Pos())))
+}
+
+// Like TypeOf, but panics instead of returning nil.
+// Only valid during p's create and build phases.
+func (p *Package) typeOf(e ast.Expr) types.Type {
+	if T := p.info.TypeOf(e); T != nil {
+		return T
+	}
+	panic(fmt.Sprintf("no type for %T @ %s",
+		e, p.Prog.Fset.Position(e.Pos())))
+}
diff --git a/go/ssa/builder_test.go b/go/ssa/builder_test.go
new file mode 100644
index 0000000..e7ac838
--- /dev/null
+++ b/go/ssa/builder_test.go
@@ -0,0 +1,419 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssa_test
+
+import (
+	"bytes"
+	"go/ast"
+	"go/parser"
+	"go/token"
+	"reflect"
+	"sort"
+	"strings"
+	"testing"
+
+	"golang.org/x/tools/go/loader"
+	"golang.org/x/tools/go/ssa"
+	"golang.org/x/tools/go/ssa/ssautil"
+	"golang.org/x/tools/go/types"
+
+	_ "golang.org/x/tools/go/gcimporter"
+)
+
+func isEmpty(f *ssa.Function) bool { return f.Blocks == nil }
+
+// Tests that programs partially loaded from gc object files contain
+// functions with no code for the external portions, but are otherwise ok.
+func TestBuildPackage(t *testing.T) {
+	input := `
+package main
+
+import (
+	"bytes"
+	"io"
+	"testing"
+)
+
+func main() {
+        var t testing.T
+	t.Parallel()    // static call to external declared method
+        t.Fail()        // static call to promoted external declared method
+        testing.Short() // static call to external package-level function
+
+        var w io.Writer = new(bytes.Buffer)
+        w.Write(nil)    // interface invoke of external declared method
+}
+`
+
+	// Parse the file.
+	fset := token.NewFileSet()
+	f, err := parser.ParseFile(fset, "input.go", input, 0)
+	if err != nil {
+		t.Error(err)
+		return
+	}
+
+	// Build an SSA program from the parsed file.
+	// Load its dependencies from gc binary export data.
+	mainPkg, _, err := ssautil.BuildPackage(new(types.Config), fset,
+		types.NewPackage("main", ""), []*ast.File{f}, ssa.SanityCheckFunctions)
+	if err != nil {
+		t.Error(err)
+		return
+	}
+
+	// The main package, its direct and indirect dependencies are loaded.
+	deps := []string{
+		// directly imported dependencies:
+		"bytes", "io", "testing",
+		// indirect dependencies (partial list):
+		"errors", "fmt", "os", "runtime",
+	}
+
+	prog := mainPkg.Prog
+	all := prog.AllPackages()
+	if len(all) <= len(deps) {
+		t.Errorf("unexpected set of loaded packages: %q", all)
+	}
+	for _, path := range deps {
+		pkg := prog.ImportedPackage(path)
+		if pkg == nil {
+			t.Errorf("package not loaded: %q", path)
+			continue
+		}
+
+		// External packages should have no function bodies (except for wrappers).
+		isExt := pkg != mainPkg
+
+		// init()
+		if isExt && !isEmpty(pkg.Func("init")) {
+			t.Errorf("external package %s has non-empty init", pkg)
+		} else if !isExt && isEmpty(pkg.Func("init")) {
+			t.Errorf("main package %s has empty init", pkg)
+		}
+
+		for _, mem := range pkg.Members {
+			switch mem := mem.(type) {
+			case *ssa.Function:
+				// Functions at package level.
+				if isExt && !isEmpty(mem) {
+					t.Errorf("external function %s is non-empty", mem)
+				} else if !isExt && isEmpty(mem) {
+					t.Errorf("function %s is empty", mem)
+				}
+
+			case *ssa.Type:
+				// Methods of named types T.
+				// (In this test, all exported methods belong to *T not T.)
+				if !isExt {
+					t.Fatalf("unexpected name type in main package: %s", mem)
+				}
+				mset := prog.MethodSets.MethodSet(types.NewPointer(mem.Type()))
+				for i, n := 0, mset.Len(); i < n; i++ {
+					m := prog.Method(mset.At(i))
+					// For external types, only synthetic wrappers have code.
+					expExt := !strings.Contains(m.Synthetic, "wrapper")
+					if expExt && !isEmpty(m) {
+						t.Errorf("external method %s is non-empty: %s",
+							m, m.Synthetic)
+					} else if !expExt && isEmpty(m) {
+						t.Errorf("method function %s is empty: %s",
+							m, m.Synthetic)
+					}
+				}
+			}
+		}
+	}
+
+	expectedCallee := []string{
+		"(*testing.T).Parallel",
+		"(*testing.common).Fail",
+		"testing.Short",
+		"N/A",
+	}
+	callNum := 0
+	for _, b := range mainPkg.Func("main").Blocks {
+		for _, instr := range b.Instrs {
+			switch instr := instr.(type) {
+			case ssa.CallInstruction:
+				call := instr.Common()
+				if want := expectedCallee[callNum]; want != "N/A" {
+					got := call.StaticCallee().String()
+					if want != got {
+						t.Errorf("call #%d from main.main: got callee %s, want %s",
+							callNum, got, want)
+					}
+				}
+				callNum++
+			}
+		}
+	}
+	if callNum != 4 {
+		t.Errorf("in main.main: got %d calls, want %d", callNum, 4)
+	}
+}
+
+// TestRuntimeTypes tests that (*Program).RuntimeTypes() includes all necessary types.
+func TestRuntimeTypes(t *testing.T) {
+	tests := []struct {
+		input string
+		want  []string
+	}{
+		// An exported package-level type is needed.
+		{`package A; type T struct{}; func (T) f() {}`,
+			[]string{"*p.T", "p.T"},
+		},
+		// An unexported package-level type is not needed.
+		{`package B; type t struct{}; func (t) f() {}`,
+			nil,
+		},
+		// Subcomponents of type of exported package-level var are needed.
+		{`package C; import "bytes"; var V struct {*bytes.Buffer}`,
+			[]string{"*bytes.Buffer", "*struct{*bytes.Buffer}", "struct{*bytes.Buffer}"},
+		},
+		// Subcomponents of type of unexported package-level var are not needed.
+		{`package D; import "bytes"; var v struct {*bytes.Buffer}`,
+			nil,
+		},
+		// Subcomponents of type of exported package-level function are needed.
+		{`package E; import "bytes"; func F(struct {*bytes.Buffer}) {}`,
+			[]string{"*bytes.Buffer", "struct{*bytes.Buffer}"},
+		},
+		// Subcomponents of type of unexported package-level function are not needed.
+		{`package F; import "bytes"; func f(struct {*bytes.Buffer}) {}`,
+			nil,
+		},
+		// Subcomponents of type of exported method of uninstantiated unexported type are not needed.
+		{`package G; import "bytes"; type x struct{}; func (x) G(struct {*bytes.Buffer}) {}; var v x`,
+			nil,
+		},
+		// ...unless used by MakeInterface.
+		{`package G2; import "bytes"; type x struct{}; func (x) G(struct {*bytes.Buffer}) {}; var v interface{} = x{}`,
+			[]string{"*bytes.Buffer", "*p.x", "p.x", "struct{*bytes.Buffer}"},
+		},
+		// Subcomponents of type of unexported method are not needed.
+		{`package I; import "bytes"; type X struct{}; func (X) G(struct {*bytes.Buffer}) {}`,
+			[]string{"*bytes.Buffer", "*p.X", "p.X", "struct{*bytes.Buffer}"},
+		},
+		// Local types aren't needed.
+		{`package J; import "bytes"; func f() { type T struct {*bytes.Buffer}; var t T; _ = t }`,
+			nil,
+		},
+		// ...unless used by MakeInterface.
+		{`package K; import "bytes"; func f() { type T struct {*bytes.Buffer}; _ = interface{}(T{}) }`,
+			[]string{"*bytes.Buffer", "*p.T", "p.T"},
+		},
+		// Types used as operand of MakeInterface are needed.
+		{`package L; import "bytes"; func f() { _ = interface{}(struct{*bytes.Buffer}{}) }`,
+			[]string{"*bytes.Buffer", "struct{*bytes.Buffer}"},
+		},
+		// MakeInterface is optimized away when storing to a blank.
+		{`package M; import "bytes"; var _ interface{} = struct{*bytes.Buffer}{}`,
+			nil,
+		},
+	}
+	for _, test := range tests {
+		// Parse the file.
+		fset := token.NewFileSet()
+		f, err := parser.ParseFile(fset, "input.go", test.input, 0)
+		if err != nil {
+			t.Errorf("test %q: %s", test.input[:15], err)
+			continue
+		}
+
+		// Create a single-file main package.
+		// Load dependencies from gc binary export data.
+		ssapkg, _, err := ssautil.BuildPackage(new(types.Config), fset,
+			types.NewPackage("p", ""), []*ast.File{f}, ssa.SanityCheckFunctions)
+		if err != nil {
+			t.Errorf("test %q: %s", test.input[:15], err)
+			continue
+		}
+
+		var typstrs []string
+		for _, T := range ssapkg.Prog.RuntimeTypes() {
+			typstrs = append(typstrs, T.String())
+		}
+		sort.Strings(typstrs)
+
+		if !reflect.DeepEqual(typstrs, test.want) {
+			t.Errorf("test 'package %s': got %q, want %q",
+				f.Name.Name, typstrs, test.want)
+		}
+	}
+}
+
+// TestInit tests that synthesized init functions are correctly formed.
+// Bare init functions omit calls to dependent init functions and the use of
+// an init guard. They are useful in cases where the client uses a different
+// calling convention for init functions, or cases where it is easier for a
+// client to analyze bare init functions. Both of these aspects are used by
+// the llgo compiler for simpler integration with gccgo's runtime library,
+// and to simplify the analysis whereby it deduces which stores to globals
+// can be lowered to global initializers.
+func TestInit(t *testing.T) {
+	tests := []struct {
+		mode        ssa.BuilderMode
+		input, want string
+	}{
+		{0, `package A; import _ "errors"; var i int = 42`,
+			`# Name: A.init
+# Package: A
+# Synthetic: package initializer
+func init():
+0:                                                                entry P:0 S:2
+	t0 = *init$guard                                                   bool
+	if t0 goto 2 else 1
+1:                                                           init.start P:1 S:1
+	*init$guard = true:bool
+	t1 = errors.init()                                                   ()
+	*i = 42:int
+	jump 2
+2:                                                            init.done P:2 S:0
+	return
+
+`},
+		{ssa.BareInits, `package B; import _ "errors"; var i int = 42`,
+			`# Name: B.init
+# Package: B
+# Synthetic: package initializer
+func init():
+0:                                                                entry P:0 S:0
+	*i = 42:int
+	return
+
+`},
+	}
+	for _, test := range tests {
+		// Create a single-file main package.
+		var conf loader.Config
+		f, err := conf.ParseFile("<input>", test.input)
+		if err != nil {
+			t.Errorf("test %q: %s", test.input[:15], err)
+			continue
+		}
+		conf.CreateFromFiles(f.Name.Name, f)
+
+		lprog, err := conf.Load()
+		if err != nil {
+			t.Errorf("test 'package %s': Load: %s", f.Name.Name, err)
+			continue
+		}
+		prog := ssautil.CreateProgram(lprog, test.mode)
+		mainPkg := prog.Package(lprog.Created[0].Pkg)
+		prog.BuildAll()
+		initFunc := mainPkg.Func("init")
+		if initFunc == nil {
+			t.Errorf("test 'package %s': no init function", f.Name.Name)
+			continue
+		}
+
+		var initbuf bytes.Buffer
+		_, err = initFunc.WriteTo(&initbuf)
+		if err != nil {
+			t.Errorf("test 'package %s': WriteTo: %s", f.Name.Name, err)
+			continue
+		}
+
+		if initbuf.String() != test.want {
+			t.Errorf("test 'package %s': got %s, want %s", f.Name.Name, initbuf.String(), test.want)
+		}
+	}
+}
+
+// TestSyntheticFuncs checks that the expected synthetic functions are
+// created, reachable, and not duplicated.
+func TestSyntheticFuncs(t *testing.T) {
+	const input = `package P
+type T int
+func (T) f() int
+func (*T) g() int
+var (
+	// thunks
+	a = T.f
+	b = T.f
+	c = (struct{T}).f
+	d = (struct{T}).f
+	e = (*T).g
+	f = (*T).g
+	g = (struct{*T}).g
+	h = (struct{*T}).g
+
+	// bounds
+	i = T(0).f
+	j = T(0).f
+	k = new(T).g
+	l = new(T).g
+
+	// wrappers
+	m interface{} = struct{T}{}
+	n interface{} = struct{T}{}
+	o interface{} = struct{*T}{}
+	p interface{} = struct{*T}{}
+	q interface{} = new(struct{T})
+	r interface{} = new(struct{T})
+	s interface{} = new(struct{*T})
+	t interface{} = new(struct{*T})
+)
+`
+	// Parse
+	var conf loader.Config
+	f, err := conf.ParseFile("<input>", input)
+	if err != nil {
+		t.Fatalf("parse: %v", err)
+	}
+	conf.CreateFromFiles(f.Name.Name, f)
+
+	// Load
+	lprog, err := conf.Load()
+	if err != nil {
+		t.Fatalf("Load: %v", err)
+	}
+
+	// Create and build SSA
+	prog := ssautil.CreateProgram(lprog, 0)
+	prog.BuildAll()
+
+	// Enumerate reachable synthetic functions
+	want := map[string]string{
+		"(*P.T).g$bound": "bound method wrapper for func (*P.T).g() int",
+		"(P.T).f$bound":  "bound method wrapper for func (P.T).f() int",
+
+		"(*P.T).g$thunk":         "thunk for func (*P.T).g() int",
+		"(P.T).f$thunk":          "thunk for func (P.T).f() int",
+		"(struct{*P.T}).g$thunk": "thunk for func (*P.T).g() int",
+		"(struct{P.T}).f$thunk":  "thunk for func (P.T).f() int",
+
+		"(*P.T).f":          "wrapper for func (P.T).f() int",
+		"(*struct{*P.T}).f": "wrapper for func (P.T).f() int",
+		"(*struct{*P.T}).g": "wrapper for func (*P.T).g() int",
+		"(*struct{P.T}).f":  "wrapper for func (P.T).f() int",
+		"(*struct{P.T}).g":  "wrapper for func (*P.T).g() int",
+		"(struct{*P.T}).f":  "wrapper for func (P.T).f() int",
+		"(struct{*P.T}).g":  "wrapper for func (*P.T).g() int",
+		"(struct{P.T}).f":   "wrapper for func (P.T).f() int",
+
+		"P.init": "package initializer",
+	}
+	for fn := range ssautil.AllFunctions(prog) {
+		if fn.Synthetic == "" {
+			continue
+		}
+		name := fn.String()
+		wantDescr, ok := want[name]
+		if !ok {
+			t.Errorf("got unexpected/duplicate func: %q: %q", name, fn.Synthetic)
+			continue
+		}
+		delete(want, name)
+
+		if wantDescr != fn.Synthetic {
+			t.Errorf("(%s).Synthetic = %q, want %q", name, fn.Synthetic, wantDescr)
+		}
+	}
+	for fn, descr := range want {
+		t.Errorf("want func: %q: %q", fn, descr)
+	}
+}
diff --git a/go/ssa/const.go b/go/ssa/const.go
new file mode 100644
index 0000000..304096e
--- /dev/null
+++ b/go/ssa/const.go
@@ -0,0 +1,168 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssa
+
+// This file defines the Const SSA value type.
+
+import (
+	"fmt"
+	"go/token"
+	"strconv"
+
+	"golang.org/x/tools/go/exact"
+	"golang.org/x/tools/go/types"
+)
+
+// NewConst returns a new constant of the specified value and type.
+// val must be valid according to the specification of Const.Value.
+//
+func NewConst(val exact.Value, typ types.Type) *Const {
+	return &Const{typ, val}
+}
+
+// intConst returns an 'int' constant that evaluates to i.
+// (i is an int64 in case the host is narrower than the target.)
+func intConst(i int64) *Const {
+	return NewConst(exact.MakeInt64(i), tInt)
+}
+
+// nilConst returns a nil constant of the specified type, which may
+// be any reference type, including interfaces.
+//
+func nilConst(typ types.Type) *Const {
+	return NewConst(nil, typ)
+}
+
+// stringConst returns a 'string' constant that evaluates to s.
+func stringConst(s string) *Const {
+	return NewConst(exact.MakeString(s), tString)
+}
+
+// zeroConst returns a new "zero" constant of the specified type,
+// which must not be an array or struct type: the zero values of
+// aggregates are well-defined but cannot be represented by Const.
+//
+func zeroConst(t types.Type) *Const {
+	switch t := t.(type) {
+	case *types.Basic:
+		switch {
+		case t.Info()&types.IsBoolean != 0:
+			return NewConst(exact.MakeBool(false), t)
+		case t.Info()&types.IsNumeric != 0:
+			return NewConst(exact.MakeInt64(0), t)
+		case t.Info()&types.IsString != 0:
+			return NewConst(exact.MakeString(""), t)
+		case t.Kind() == types.UnsafePointer:
+			fallthrough
+		case t.Kind() == types.UntypedNil:
+			return nilConst(t)
+		default:
+			panic(fmt.Sprint("zeroConst for unexpected type:", t))
+		}
+	case *types.Pointer, *types.Slice, *types.Interface, *types.Chan, *types.Map, *types.Signature:
+		return nilConst(t)
+	case *types.Named:
+		return NewConst(zeroConst(t.Underlying()).Value, t)
+	case *types.Array, *types.Struct, *types.Tuple:
+		panic(fmt.Sprint("zeroConst applied to aggregate:", t))
+	}
+	panic(fmt.Sprint("zeroConst: unexpected ", t))
+}
+
+func (c *Const) RelString(from *types.Package) string {
+	var s string
+	if c.Value == nil {
+		s = "nil"
+	} else if c.Value.Kind() == exact.String {
+		s = exact.StringVal(c.Value)
+		const max = 20
+		// TODO(adonovan): don't cut a rune in half.
+		if len(s) > max {
+			s = s[:max-3] + "..." // abbreviate
+		}
+		s = strconv.Quote(s)
+	} else {
+		s = c.Value.String()
+	}
+	return s + ":" + relType(c.Type(), from)
+}
+
+func (c *Const) Name() string {
+	return c.RelString(nil)
+}
+
+func (c *Const) String() string {
+	return c.Name()
+}
+
+func (c *Const) Type() types.Type {
+	return c.typ
+}
+
+func (c *Const) Referrers() *[]Instruction {
+	return nil
+}
+
+func (c *Const) Parent() *Function { return nil }
+
+func (c *Const) Pos() token.Pos {
+	return token.NoPos
+}
+
+// IsNil returns true if this constant represents a typed or untyped nil value.
+func (c *Const) IsNil() bool {
+	return c.Value == nil
+}
+
+// Int64 returns the numeric value of this constant truncated to fit
+// a signed 64-bit integer.
+//
+func (c *Const) Int64() int64 {
+	switch x := c.Value; x.Kind() {
+	case exact.Int:
+		if i, ok := exact.Int64Val(x); ok {
+			return i
+		}
+		return 0
+	case exact.Float:
+		f, _ := exact.Float64Val(x)
+		return int64(f)
+	}
+	panic(fmt.Sprintf("unexpected constant value: %T", c.Value))
+}
+
+// Uint64 returns the numeric value of this constant truncated to fit
+// an unsigned 64-bit integer.
+//
+func (c *Const) Uint64() uint64 {
+	switch x := c.Value; x.Kind() {
+	case exact.Int:
+		if u, ok := exact.Uint64Val(x); ok {
+			return u
+		}
+		return 0
+	case exact.Float:
+		f, _ := exact.Float64Val(x)
+		return uint64(f)
+	}
+	panic(fmt.Sprintf("unexpected constant value: %T", c.Value))
+}
+
+// Float64 returns the numeric value of this constant truncated to fit
+// a float64.
+//
+func (c *Const) Float64() float64 {
+	f, _ := exact.Float64Val(c.Value)
+	return f
+}
+
+// Complex128 returns the complex value of this constant truncated to
+// fit a complex128.
+//
+func (c *Const) Complex128() complex128 {
+	re, _ := exact.Float64Val(exact.Real(c.Value))
+	im, _ := exact.Float64Val(exact.Imag(c.Value))
+	return complex(re, im)
+}
diff --git a/go/ssa/create.go b/go/ssa/create.go
new file mode 100644
index 0000000..88226ae
--- /dev/null
+++ b/go/ssa/create.go
@@ -0,0 +1,257 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssa
+
+// This file implements the CREATE phase of SSA construction.
+// See builder.go for explanation.
+
+import (
+	"fmt"
+	"go/ast"
+	"go/token"
+	"os"
+	"sync"
+
+	"golang.org/x/tools/go/types"
+	"golang.org/x/tools/go/types/typeutil"
+)
+
+// NewProgram returns a new SSA Program.
+//
+// mode controls diagnostics and checking during SSA construction.
+//
+func NewProgram(fset *token.FileSet, mode BuilderMode) *Program {
+	prog := &Program{
+		Fset:     fset,
+		imported: make(map[string]*Package),
+		packages: make(map[*types.Package]*Package),
+		thunks:   make(map[selectionKey]*Function),
+		bounds:   make(map[*types.Func]*Function),
+		mode:     mode,
+	}
+
+	h := typeutil.MakeHasher() // protected by methodsMu, in effect
+	prog.methodSets.SetHasher(h)
+	prog.canon.SetHasher(h)
+
+	return prog
+}
+
+// memberFromObject populates package pkg with a member for the
+// typechecker object obj.
+//
+// For objects from Go source code, syntax is the associated syntax
+// tree (for funcs and vars only); it will be used during the build
+// phase.
+//
+func memberFromObject(pkg *Package, obj types.Object, syntax ast.Node) {
+	name := obj.Name()
+	switch obj := obj.(type) {
+	case *types.TypeName:
+		pkg.Members[name] = &Type{
+			object: obj,
+			pkg:    pkg,
+		}
+
+	case *types.Const:
+		c := &NamedConst{
+			object: obj,
+			Value:  NewConst(obj.Val(), obj.Type()),
+			pkg:    pkg,
+		}
+		pkg.values[obj] = c.Value
+		pkg.Members[name] = c
+
+	case *types.Var:
+		g := &Global{
+			Pkg:    pkg,
+			name:   name,
+			object: obj,
+			typ:    types.NewPointer(obj.Type()), // address
+			pos:    obj.Pos(),
+		}
+		pkg.values[obj] = g
+		pkg.Members[name] = g
+
+	case *types.Func:
+		sig := obj.Type().(*types.Signature)
+		if sig.Recv() == nil && name == "init" {
+			pkg.ninit++
+			name = fmt.Sprintf("init#%d", pkg.ninit)
+		}
+		fn := &Function{
+			name:      name,
+			object:    obj,
+			Signature: sig,
+			syntax:    syntax,
+			pos:       obj.Pos(),
+			Pkg:       pkg,
+			Prog:      pkg.Prog,
+		}
+		if syntax == nil {
+			fn.Synthetic = "loaded from gc object file"
+		}
+
+		pkg.values[obj] = fn
+		if sig.Recv() == nil {
+			pkg.Members[name] = fn // package-level function
+		}
+
+	default: // (incl. *types.Package)
+		panic("unexpected Object type: " + obj.String())
+	}
+}
+
+// membersFromDecl populates package pkg with members for each
+// typechecker object (var, func, const or type) associated with the
+// specified decl.
+//
+func membersFromDecl(pkg *Package, decl ast.Decl) {
+	switch decl := decl.(type) {
+	case *ast.GenDecl: // import, const, type or var
+		switch decl.Tok {
+		case token.CONST:
+			for _, spec := range decl.Specs {
+				for _, id := range spec.(*ast.ValueSpec).Names {
+					if !isBlankIdent(id) {
+						memberFromObject(pkg, pkg.info.Defs[id], nil)
+					}
+				}
+			}
+
+		case token.VAR:
+			for _, spec := range decl.Specs {
+				for _, id := range spec.(*ast.ValueSpec).Names {
+					if !isBlankIdent(id) {
+						memberFromObject(pkg, pkg.info.Defs[id], spec)
+					}
+				}
+			}
+
+		case token.TYPE:
+			for _, spec := range decl.Specs {
+				id := spec.(*ast.TypeSpec).Name
+				if !isBlankIdent(id) {
+					memberFromObject(pkg, pkg.info.Defs[id], nil)
+				}
+			}
+		}
+
+	case *ast.FuncDecl:
+		id := decl.Name
+		if !isBlankIdent(id) {
+			memberFromObject(pkg, pkg.info.Defs[id], decl)
+		}
+	}
+}
+
+// CreatePackage constructs and returns an SSA Package from the
+// specified type-checked, error-free file ASTs, and populates its
+// Members mapping.
+//
+// importable determines whether this package should be returned by a
+// subsequent call to ImportedPackage(pkg.Path()).
+//
+// The real work of building SSA form for each function is not done
+// until a subsequent call to Package.Build().
+//
+func (prog *Program) CreatePackage(pkg *types.Package, files []*ast.File, info *types.Info, importable bool) *Package {
+	p := &Package{
+		Prog:    prog,
+		Members: make(map[string]Member),
+		values:  make(map[types.Object]Value),
+		Object:  pkg,
+		info:    info,  // transient (CREATE and BUILD phases)
+		files:   files, // transient (CREATE and BUILD phases)
+	}
+
+	// Add init() function.
+	p.init = &Function{
+		name:      "init",
+		Signature: new(types.Signature),
+		Synthetic: "package initializer",
+		Pkg:       p,
+		Prog:      prog,
+	}
+	p.Members[p.init.name] = p.init
+
+	// CREATE phase.
+	// Allocate all package members: vars, funcs, consts and types.
+	if len(files) > 0 {
+		// Go source package.
+		for _, file := range files {
+			for _, decl := range file.Decls {
+				membersFromDecl(p, decl)
+			}
+		}
+	} else {
+		// GC-compiled binary package.
+		// No code.
+		// No position information.
+		scope := p.Object.Scope()
+		for _, name := range scope.Names() {
+			obj := scope.Lookup(name)
+			memberFromObject(p, obj, nil)
+			if obj, ok := obj.(*types.TypeName); ok {
+				named := obj.Type().(*types.Named)
+				for i, n := 0, named.NumMethods(); i < n; i++ {
+					memberFromObject(p, named.Method(i), nil)
+				}
+			}
+		}
+	}
+
+	if prog.mode&BareInits == 0 {
+		// Add initializer guard variable.
+		initguard := &Global{
+			Pkg:  p,
+			name: "init$guard",
+			typ:  types.NewPointer(tBool),
+		}
+		p.Members[initguard.Name()] = initguard
+	}
+
+	if prog.mode&GlobalDebug != 0 {
+		p.SetDebugMode(true)
+	}
+
+	if prog.mode&PrintPackages != 0 {
+		printMu.Lock()
+		p.WriteTo(os.Stdout)
+		printMu.Unlock()
+	}
+
+	if importable {
+		prog.imported[p.Object.Path()] = p
+	}
+	prog.packages[p.Object] = p
+
+	return p
+}
+
+// printMu serializes printing of Packages/Functions to stdout.
+var printMu sync.Mutex
+
+// AllPackages returns a new slice containing all packages in the
+// program prog in unspecified order.
+//
+func (prog *Program) AllPackages() []*Package {
+	pkgs := make([]*Package, 0, len(prog.packages))
+	for _, pkg := range prog.packages {
+		pkgs = append(pkgs, pkg)
+	}
+	return pkgs
+}
+
+// ImportedPackage returns the importable SSA Package whose import
+// path is path, or nil if no such SSA package has been created.
+//
+// Not all packages are importable.  For example, no import
+// declaration can resolve to the x_test package created by 'go test'
+// or the ad-hoc main package created 'go build foo.go'.
+//
+func (prog *Program) ImportedPackage(path string) *Package {
+	return prog.imported[path]
+}
diff --git a/go/ssa/doc.go b/go/ssa/doc.go
new file mode 100644
index 0000000..2aa04f4
--- /dev/null
+++ b/go/ssa/doc.go
@@ -0,0 +1,123 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package ssa defines a representation of the elements of Go programs
+// (packages, types, functions, variables and constants) using a
+// static single-assignment (SSA) form intermediate representation
+// (IR) for the bodies of functions.
+//
+// THIS INTERFACE IS EXPERIMENTAL AND IS LIKELY TO CHANGE.
+//
+// For an introduction to SSA form, see
+// http://en.wikipedia.org/wiki/Static_single_assignment_form.
+// This page provides a broader reading list:
+// http://www.dcs.gla.ac.uk/~jsinger/ssa.html.
+//
+// The level of abstraction of the SSA form is intentionally close to
+// the source language to facilitate construction of source analysis
+// tools.  It is not intended for machine code generation.
+//
+// All looping, branching and switching constructs are replaced with
+// unstructured control flow.  Higher-level control flow constructs
+// such as multi-way branch can be reconstructed as needed; see
+// ssautil.Switches() for an example.
+//
+// To construct an SSA-form program, call ssautil.CreateProgram on a
+// loader.Program, a set of type-checked packages created from
+// parsed Go source files.  The resulting ssa.Program contains all the
+// packages and their members, but SSA code is not created for
+// function bodies until a subsequent call to (*Package).Build.
+//
+// The builder initially builds a naive SSA form in which all local
+// variables are addresses of stack locations with explicit loads and
+// stores.  Registerisation of eligible locals and φ-node insertion
+// using dominance and dataflow are then performed as a second pass
+// called "lifting" to improve the accuracy and performance of
+// subsequent analyses; this pass can be skipped by setting the
+// NaiveForm builder flag.
+//
+// The primary interfaces of this package are:
+//
+//    - Member: a named member of a Go package.
+//    - Value: an expression that yields a value.
+//    - Instruction: a statement that consumes values and performs computation.
+//    - Node: a Value or Instruction (emphasizing its membership in the SSA value graph)
+//
+// A computation that yields a result implements both the Value and
+// Instruction interfaces.  The following table shows for each
+// concrete type which of these interfaces it implements.
+//
+//                      Value?          Instruction?    Member?
+//   *Alloc             ✔               ✔
+//   *BinOp             ✔               ✔
+//   *Builtin           ✔
+//   *Call              ✔               ✔
+//   *ChangeInterface   ✔               ✔
+//   *ChangeType        ✔               ✔
+//   *Const             ✔
+//   *Convert           ✔               ✔
+//   *DebugRef                          ✔
+//   *Defer                             ✔
+//   *Extract           ✔               ✔
+//   *Field             ✔               ✔
+//   *FieldAddr         ✔               ✔
+//   *FreeVar           ✔
+//   *Function          ✔                               ✔ (func)
+//   *Global            ✔                               ✔ (var)
+//   *Go                                ✔
+//   *If                                ✔
+//   *Index             ✔               ✔
+//   *IndexAddr         ✔               ✔
+//   *Jump                              ✔
+//   *Lookup            ✔               ✔
+//   *MakeChan          ✔               ✔
+//   *MakeClosure       ✔               ✔
+//   *MakeInterface     ✔               ✔
+//   *MakeMap           ✔               ✔
+//   *MakeSlice         ✔               ✔
+//   *MapUpdate                         ✔
+//   *NamedConst                                        ✔ (const)
+//   *Next              ✔               ✔
+//   *Panic                             ✔
+//   *Parameter         ✔
+//   *Phi               ✔               ✔
+//   *Range             ✔               ✔
+//   *Return                            ✔
+//   *RunDefers                         ✔
+//   *Select            ✔               ✔
+//   *Send                              ✔
+//   *Slice             ✔               ✔
+//   *Store                             ✔
+//   *Type                                              ✔ (type)
+//   *TypeAssert        ✔               ✔
+//   *UnOp              ✔               ✔
+//
+// Other key types in this package include: Program, Package, Function
+// and BasicBlock.
+//
+// The program representation constructed by this package is fully
+// resolved internally, i.e. it does not rely on the names of Values,
+// Packages, Functions, Types or BasicBlocks for the correct
+// interpretation of the program.  Only the identities of objects and
+// the topology of the SSA and type graphs are semantically
+// significant.  (There is one exception: Ids, used to identify field
+// and method names, contain strings.)  Avoidance of name-based
+// operations simplifies the implementation of subsequent passes and
+// can make them very efficient.  Many objects are nonetheless named
+// to aid in debugging, but it is not essential that the names be
+// either accurate or unambiguous.  The public API exposes a number of
+// name-based maps for client convenience.
+//
+// The ssa/ssautil package provides various utilities that depend only
+// on the public API of this package.
+//
+// TODO(adonovan): Consider the exceptional control-flow implications
+// of defer and recover().
+//
+// TODO(adonovan): write a how-to document for all the various cases
+// of trying to determine corresponding elements across the four
+// domains of source locations, ast.Nodes, types.Objects,
+// ssa.Values/Instructions.
+//
+package ssa // import "golang.org/x/tools/go/ssa"
diff --git a/go/ssa/dom.go b/go/ssa/dom.go
new file mode 100644
index 0000000..12ef430
--- /dev/null
+++ b/go/ssa/dom.go
@@ -0,0 +1,341 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssa
+
+// This file defines algorithms related to dominance.
+
+// Dominator tree construction ----------------------------------------
+//
+// We use the algorithm described in Lengauer & Tarjan. 1979.  A fast
+// algorithm for finding dominators in a flowgraph.
+// http://doi.acm.org/10.1145/357062.357071
+//
+// We also apply the optimizations to SLT described in Georgiadis et
+// al, Finding Dominators in Practice, JGAA 2006,
+// http://jgaa.info/accepted/2006/GeorgiadisTarjanWerneck2006.10.1.pdf
+// to avoid the need for buckets of size > 1.
+
+import (
+	"bytes"
+	"fmt"
+	"math/big"
+	"os"
+	"sort"
+)
+
+// Idom returns the block that immediately dominates b:
+// its parent in the dominator tree, if any.
+// Neither the entry node (b.Index==0) nor recover node
+// (b==b.Parent().Recover()) have a parent.
+//
+func (b *BasicBlock) Idom() *BasicBlock { return b.dom.idom }
+
+// Dominees returns the list of blocks that b immediately dominates:
+// its children in the dominator tree.
+//
+func (b *BasicBlock) Dominees() []*BasicBlock { return b.dom.children }
+
+// Dominates reports whether b dominates c.
+func (b *BasicBlock) Dominates(c *BasicBlock) bool {
+	return b.dom.pre <= c.dom.pre && c.dom.post <= b.dom.post
+}
+
+type byDomPreorder []*BasicBlock
+
+func (a byDomPreorder) Len() int           { return len(a) }
+func (a byDomPreorder) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
+func (a byDomPreorder) Less(i, j int) bool { return a[i].dom.pre < a[j].dom.pre }
+
+// DomPreorder returns a new slice containing the blocks of f in
+// dominator tree preorder.
+//
+func (f *Function) DomPreorder() []*BasicBlock {
+	n := len(f.Blocks)
+	order := make(byDomPreorder, n, n)
+	copy(order, f.Blocks)
+	sort.Sort(order)
+	return order
+}
+
+// domInfo contains a BasicBlock's dominance information.
+type domInfo struct {
+	idom      *BasicBlock   // immediate dominator (parent in domtree)
+	children  []*BasicBlock // nodes immediately dominated by this one
+	pre, post int32         // pre- and post-order numbering within domtree
+}
+
+// ltState holds the working state for Lengauer-Tarjan algorithm
+// (during which domInfo.pre is repurposed for CFG DFS preorder number).
+type ltState struct {
+	// Each slice is indexed by b.Index.
+	sdom     []*BasicBlock // b's semidominator
+	parent   []*BasicBlock // b's parent in DFS traversal of CFG
+	ancestor []*BasicBlock // b's ancestor with least sdom
+}
+
+// dfs implements the depth-first search part of the LT algorithm.
+func (lt *ltState) dfs(v *BasicBlock, i int32, preorder []*BasicBlock) int32 {
+	preorder[i] = v
+	v.dom.pre = i // For now: DFS preorder of spanning tree of CFG
+	i++
+	lt.sdom[v.Index] = v
+	lt.link(nil, v)
+	for _, w := range v.Succs {
+		if lt.sdom[w.Index] == nil {
+			lt.parent[w.Index] = v
+			i = lt.dfs(w, i, preorder)
+		}
+	}
+	return i
+}
+
+// eval implements the EVAL part of the LT algorithm.
+func (lt *ltState) eval(v *BasicBlock) *BasicBlock {
+	// TODO(adonovan): opt: do path compression per simple LT.
+	u := v
+	for ; lt.ancestor[v.Index] != nil; v = lt.ancestor[v.Index] {
+		if lt.sdom[v.Index].dom.pre < lt.sdom[u.Index].dom.pre {
+			u = v
+		}
+	}
+	return u
+}
+
+// link implements the LINK part of the LT algorithm.
+func (lt *ltState) link(v, w *BasicBlock) {
+	lt.ancestor[w.Index] = v
+}
+
+// buildDomTree computes the dominator tree of f using the LT algorithm.
+// Precondition: all blocks are reachable (e.g. optimizeBlocks has been run).
+//
+func buildDomTree(f *Function) {
+	// The step numbers refer to the original LT paper; the
+	// reordering is due to Georgiadis.
+
+	// Clear any previous domInfo.
+	for _, b := range f.Blocks {
+		b.dom = domInfo{}
+	}
+
+	n := len(f.Blocks)
+	// Allocate space for 5 contiguous [n]*BasicBlock arrays:
+	// sdom, parent, ancestor, preorder, buckets.
+	space := make([]*BasicBlock, 5*n, 5*n)
+	lt := ltState{
+		sdom:     space[0:n],
+		parent:   space[n : 2*n],
+		ancestor: space[2*n : 3*n],
+	}
+
+	// Step 1.  Number vertices by depth-first preorder.
+	preorder := space[3*n : 4*n]
+	root := f.Blocks[0]
+	prenum := lt.dfs(root, 0, preorder)
+	recover := f.Recover
+	if recover != nil {
+		lt.dfs(recover, prenum, preorder)
+	}
+
+	buckets := space[4*n : 5*n]
+	copy(buckets, preorder)
+
+	// In reverse preorder...
+	for i := int32(n) - 1; i > 0; i-- {
+		w := preorder[i]
+
+		// Step 3. Implicitly define the immediate dominator of each node.
+		for v := buckets[i]; v != w; v = buckets[v.dom.pre] {
+			u := lt.eval(v)
+			if lt.sdom[u.Index].dom.pre < i {
+				v.dom.idom = u
+			} else {
+				v.dom.idom = w
+			}
+		}
+
+		// Step 2. Compute the semidominators of all nodes.
+		lt.sdom[w.Index] = lt.parent[w.Index]
+		for _, v := range w.Preds {
+			u := lt.eval(v)
+			if lt.sdom[u.Index].dom.pre < lt.sdom[w.Index].dom.pre {
+				lt.sdom[w.Index] = lt.sdom[u.Index]
+			}
+		}
+
+		lt.link(lt.parent[w.Index], w)
+
+		if lt.parent[w.Index] == lt.sdom[w.Index] {
+			w.dom.idom = lt.parent[w.Index]
+		} else {
+			buckets[i] = buckets[lt.sdom[w.Index].dom.pre]
+			buckets[lt.sdom[w.Index].dom.pre] = w
+		}
+	}
+
+	// The final 'Step 3' is now outside the loop.
+	for v := buckets[0]; v != root; v = buckets[v.dom.pre] {
+		v.dom.idom = root
+	}
+
+	// Step 4. Explicitly define the immediate dominator of each
+	// node, in preorder.
+	for _, w := range preorder[1:] {
+		if w == root || w == recover {
+			w.dom.idom = nil
+		} else {
+			if w.dom.idom != lt.sdom[w.Index] {
+				w.dom.idom = w.dom.idom.dom.idom
+			}
+			// Calculate Children relation as inverse of Idom.
+			w.dom.idom.dom.children = append(w.dom.idom.dom.children, w)
+		}
+	}
+
+	pre, post := numberDomTree(root, 0, 0)
+	if recover != nil {
+		numberDomTree(recover, pre, post)
+	}
+
+	// printDomTreeDot(os.Stderr, f)        // debugging
+	// printDomTreeText(os.Stderr, root, 0) // debugging
+
+	if f.Prog.mode&SanityCheckFunctions != 0 {
+		sanityCheckDomTree(f)
+	}
+}
+
+// numberDomTree sets the pre- and post-order numbers of a depth-first
+// traversal of the dominator tree rooted at v.  These are used to
+// answer dominance queries in constant time.
+//
+func numberDomTree(v *BasicBlock, pre, post int32) (int32, int32) {
+	v.dom.pre = pre
+	pre++
+	for _, child := range v.dom.children {
+		pre, post = numberDomTree(child, pre, post)
+	}
+	v.dom.post = post
+	post++
+	return pre, post
+}
+
+// Testing utilities ----------------------------------------
+
+// sanityCheckDomTree checks the correctness of the dominator tree
+// computed by the LT algorithm by comparing against the dominance
+// relation computed by a naive Kildall-style forward dataflow
+// analysis (Algorithm 10.16 from the "Dragon" book).
+//
+func sanityCheckDomTree(f *Function) {
+	n := len(f.Blocks)
+
+	// D[i] is the set of blocks that dominate f.Blocks[i],
+	// represented as a bit-set of block indices.
+	D := make([]big.Int, n)
+
+	one := big.NewInt(1)
+
+	// all is the set of all blocks; constant.
+	var all big.Int
+	all.Set(one).Lsh(&all, uint(n)).Sub(&all, one)
+
+	// Initialization.
+	for i, b := range f.Blocks {
+		if i == 0 || b == f.Recover {
+			// A root is dominated only by itself.
+			D[i].SetBit(&D[0], 0, 1)
+		} else {
+			// All other blocks are (initially) dominated
+			// by every block.
+			D[i].Set(&all)
+		}
+	}
+
+	// Iteration until fixed point.
+	for changed := true; changed; {
+		changed = false
+		for i, b := range f.Blocks {
+			if i == 0 || b == f.Recover {
+				continue
+			}
+			// Compute intersection across predecessors.
+			var x big.Int
+			x.Set(&all)
+			for _, pred := range b.Preds {
+				x.And(&x, &D[pred.Index])
+			}
+			x.SetBit(&x, i, 1) // a block always dominates itself.
+			if D[i].Cmp(&x) != 0 {
+				D[i].Set(&x)
+				changed = true
+			}
+		}
+	}
+
+	// Check the entire relation.  O(n^2).
+	// The Recover block (if any) must be treated specially so we skip it.
+	ok := true
+	for i := 0; i < n; i++ {
+		for j := 0; j < n; j++ {
+			b, c := f.Blocks[i], f.Blocks[j]
+			if c == f.Recover {
+				continue
+			}
+			actual := b.Dominates(c)
+			expected := D[j].Bit(i) == 1
+			if actual != expected {
+				fmt.Fprintf(os.Stderr, "dominates(%s, %s)==%t, want %t\n", b, c, actual, expected)
+				ok = false
+			}
+		}
+	}
+
+	preorder := f.DomPreorder()
+	for _, b := range f.Blocks {
+		if got := preorder[b.dom.pre]; got != b {
+			fmt.Fprintf(os.Stderr, "preorder[%d]==%s, want %s\n", b.dom.pre, got, b)
+			ok = false
+		}
+	}
+
+	if !ok {
+		panic("sanityCheckDomTree failed for " + f.String())
+	}
+
+}
+
+// Printing functions ----------------------------------------
+
+// printDomTree prints the dominator tree as text, using indentation.
+func printDomTreeText(buf *bytes.Buffer, v *BasicBlock, indent int) {
+	fmt.Fprintf(buf, "%*s%s\n", 4*indent, "", v)
+	for _, child := range v.dom.children {
+		printDomTreeText(buf, child, indent+1)
+	}
+}
+
+// printDomTreeDot prints the dominator tree of f in AT&T GraphViz
+// (.dot) format.
+func printDomTreeDot(buf *bytes.Buffer, f *Function) {
+	fmt.Fprintln(buf, "//", f)
+	fmt.Fprintln(buf, "digraph domtree {")
+	for i, b := range f.Blocks {
+		v := b.dom
+		fmt.Fprintf(buf, "\tn%d [label=\"%s (%d, %d)\",shape=\"rectangle\"];\n", v.pre, b, v.pre, v.post)
+		// TODO(adonovan): improve appearance of edges
+		// belonging to both dominator tree and CFG.
+
+		// Dominator tree edge.
+		if i != 0 {
+			fmt.Fprintf(buf, "\tn%d -> n%d [style=\"solid\",weight=100];\n", v.idom.dom.pre, v.pre)
+		}
+		// CFG edges.
+		for _, pred := range b.Preds {
+			fmt.Fprintf(buf, "\tn%d -> n%d [style=\"dotted\",weight=0];\n", pred.dom.pre, v.pre)
+		}
+	}
+	fmt.Fprintln(buf, "}")
+}
diff --git a/go/ssa/emit.go b/go/ssa/emit.go
new file mode 100644
index 0000000..fa9646b
--- /dev/null
+++ b/go/ssa/emit.go
@@ -0,0 +1,469 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssa
+
+// Helpers for emitting SSA instructions.
+
+import (
+	"fmt"
+	"go/ast"
+	"go/token"
+
+	"golang.org/x/tools/go/types"
+)
+
+// emitNew emits to f a new (heap Alloc) instruction allocating an
+// object of type typ.  pos is the optional source location.
+//
+func emitNew(f *Function, typ types.Type, pos token.Pos) *Alloc {
+	v := &Alloc{Heap: true}
+	v.setType(types.NewPointer(typ))
+	v.setPos(pos)
+	f.emit(v)
+	return v
+}
+
+// emitLoad emits to f an instruction to load the address addr into a
+// new temporary, and returns the value so defined.
+//
+func emitLoad(f *Function, addr Value) *UnOp {
+	v := &UnOp{Op: token.MUL, X: addr}
+	v.setType(deref(addr.Type()))
+	f.emit(v)
+	return v
+}
+
+// emitDebugRef emits to f a DebugRef pseudo-instruction associating
+// expression e with value v.
+//
+func emitDebugRef(f *Function, e ast.Expr, v Value, isAddr bool) {
+	if !f.debugInfo() {
+		return // debugging not enabled
+	}
+	if v == nil || e == nil {
+		panic("nil")
+	}
+	var obj types.Object
+	e = unparen(e)
+	if id, ok := e.(*ast.Ident); ok {
+		if isBlankIdent(id) {
+			return
+		}
+		obj = f.Pkg.objectOf(id)
+		switch obj.(type) {
+		case *types.Nil, *types.Const, *types.Builtin:
+			return
+		}
+	}
+	f.emit(&DebugRef{
+		X:      v,
+		Expr:   e,
+		IsAddr: isAddr,
+		object: obj,
+	})
+}
+
+// emitArith emits to f code to compute the binary operation op(x, y)
+// where op is an eager shift, logical or arithmetic operation.
+// (Use emitCompare() for comparisons and Builder.logicalBinop() for
+// non-eager operations.)
+//
+func emitArith(f *Function, op token.Token, x, y Value, t types.Type, pos token.Pos) Value {
+	switch op {
+	case token.SHL, token.SHR:
+		x = emitConv(f, x, t)
+		// y may be signed or an 'untyped' constant.
+		// TODO(adonovan): whence signed values?
+		if b, ok := y.Type().Underlying().(*types.Basic); ok && b.Info()&types.IsUnsigned == 0 {
+			y = emitConv(f, y, types.Typ[types.Uint64])
+		}
+
+	case token.ADD, token.SUB, token.MUL, token.QUO, token.REM, token.AND, token.OR, token.XOR, token.AND_NOT:
+		x = emitConv(f, x, t)
+		y = emitConv(f, y, t)
+
+	default:
+		panic("illegal op in emitArith: " + op.String())
+
+	}
+	v := &BinOp{
+		Op: op,
+		X:  x,
+		Y:  y,
+	}
+	v.setPos(pos)
+	v.setType(t)
+	return f.emit(v)
+}
+
+// emitCompare emits to f code compute the boolean result of
+// comparison comparison 'x op y'.
+//
+func emitCompare(f *Function, op token.Token, x, y Value, pos token.Pos) Value {
+	xt := x.Type().Underlying()
+	yt := y.Type().Underlying()
+
+	// Special case to optimise a tagless SwitchStmt so that
+	// these are equivalent
+	//   switch { case e: ...}
+	//   switch true { case e: ... }
+	//   if e==true { ... }
+	// even in the case when e's type is an interface.
+	// TODO(adonovan): opt: generalise to x==true, false!=y, etc.
+	if x == vTrue && op == token.EQL {
+		if yt, ok := yt.(*types.Basic); ok && yt.Info()&types.IsBoolean != 0 {
+			return y
+		}
+	}
+
+	if types.Identical(xt, yt) {
+		// no conversion necessary
+	} else if _, ok := xt.(*types.Interface); ok {
+		y = emitConv(f, y, x.Type())
+	} else if _, ok := yt.(*types.Interface); ok {
+		x = emitConv(f, x, y.Type())
+	} else if _, ok := x.(*Const); ok {
+		x = emitConv(f, x, y.Type())
+	} else if _, ok := y.(*Const); ok {
+		y = emitConv(f, y, x.Type())
+	} else {
+		// other cases, e.g. channels.  No-op.
+	}
+
+	v := &BinOp{
+		Op: op,
+		X:  x,
+		Y:  y,
+	}
+	v.setPos(pos)
+	v.setType(tBool)
+	return f.emit(v)
+}
+
+// isValuePreserving returns true if a conversion from ut_src to
+// ut_dst is value-preserving, i.e. just a change of type.
+// Precondition: neither argument is a named type.
+//
+func isValuePreserving(ut_src, ut_dst types.Type) bool {
+	// Identical underlying types?
+	if types.Identical(ut_dst, ut_src) {
+		return true
+	}
+
+	switch ut_dst.(type) {
+	case *types.Chan:
+		// Conversion between channel types?
+		_, ok := ut_src.(*types.Chan)
+		return ok
+
+	case *types.Pointer:
+		// Conversion between pointers with identical base types?
+		_, ok := ut_src.(*types.Pointer)
+		return ok
+	}
+	return false
+}
+
+// emitConv emits to f code to convert Value val to exactly type typ,
+// and returns the converted value.  Implicit conversions are required
+// by language assignability rules in assignments, parameter passing,
+// etc.  Conversions cannot fail dynamically.
+//
+func emitConv(f *Function, val Value, typ types.Type) Value {
+	t_src := val.Type()
+
+	// Identical types?  Conversion is a no-op.
+	if types.Identical(t_src, typ) {
+		return val
+	}
+
+	ut_dst := typ.Underlying()
+	ut_src := t_src.Underlying()
+
+	// Just a change of type, but not value or representation?
+	if isValuePreserving(ut_src, ut_dst) {
+		c := &ChangeType{X: val}
+		c.setType(typ)
+		return f.emit(c)
+	}
+
+	// Conversion to, or construction of a value of, an interface type?
+	if _, ok := ut_dst.(*types.Interface); ok {
+		// Assignment from one interface type to another?
+		if _, ok := ut_src.(*types.Interface); ok {
+			c := &ChangeInterface{X: val}
+			c.setType(typ)
+			return f.emit(c)
+		}
+
+		// Untyped nil constant?  Return interface-typed nil constant.
+		if ut_src == tUntypedNil {
+			return nilConst(typ)
+		}
+
+		// Convert (non-nil) "untyped" literals to their default type.
+		if t, ok := ut_src.(*types.Basic); ok && t.Info()&types.IsUntyped != 0 {
+			val = emitConv(f, val, DefaultType(ut_src))
+		}
+
+		f.Pkg.Prog.needMethodsOf(val.Type())
+		mi := &MakeInterface{X: val}
+		mi.setType(typ)
+		return f.emit(mi)
+	}
+
+	// Conversion of a compile-time constant value?
+	if c, ok := val.(*Const); ok {
+		if _, ok := ut_dst.(*types.Basic); ok || c.IsNil() {
+			// Conversion of a compile-time constant to
+			// another constant type results in a new
+			// constant of the destination type and
+			// (initially) the same abstract value.
+			// We don't truncate the value yet.
+			return NewConst(c.Value, typ)
+		}
+
+		// We're converting from constant to non-constant type,
+		// e.g. string -> []byte/[]rune.
+	}
+
+	// A representation-changing conversion?
+	// At least one of {ut_src,ut_dst} must be *Basic.
+	// (The other may be []byte or []rune.)
+	_, ok1 := ut_src.(*types.Basic)
+	_, ok2 := ut_dst.(*types.Basic)
+	if ok1 || ok2 {
+		c := &Convert{X: val}
+		c.setType(typ)
+		return f.emit(c)
+	}
+
+	panic(fmt.Sprintf("in %s: cannot convert %s (%s) to %s", f, val, val.Type(), typ))
+}
+
+// emitStore emits to f an instruction to store value val at location
+// addr, applying implicit conversions as required by assignability rules.
+//
+func emitStore(f *Function, addr, val Value, pos token.Pos) *Store {
+	s := &Store{
+		Addr: addr,
+		Val:  emitConv(f, val, deref(addr.Type())),
+		pos:  pos,
+	}
+	f.emit(s)
+	return s
+}
+
+// emitJump emits to f a jump to target, and updates the control-flow graph.
+// Postcondition: f.currentBlock is nil.
+//
+func emitJump(f *Function, target *BasicBlock) {
+	b := f.currentBlock
+	b.emit(new(Jump))
+	addEdge(b, target)
+	f.currentBlock = nil
+}
+
+// emitIf emits to f a conditional jump to tblock or fblock based on
+// cond, and updates the control-flow graph.
+// Postcondition: f.currentBlock is nil.
+//
+func emitIf(f *Function, cond Value, tblock, fblock *BasicBlock) {
+	b := f.currentBlock
+	b.emit(&If{Cond: cond})
+	addEdge(b, tblock)
+	addEdge(b, fblock)
+	f.currentBlock = nil
+}
+
+// emitExtract emits to f an instruction to extract the index'th
+// component of tuple.  It returns the extracted value.
+//
+func emitExtract(f *Function, tuple Value, index int) Value {
+	e := &Extract{Tuple: tuple, Index: index}
+	e.setType(tuple.Type().(*types.Tuple).At(index).Type())
+	return f.emit(e)
+}
+
+// emitTypeAssert emits to f a type assertion value := x.(t) and
+// returns the value.  x.Type() must be an interface.
+//
+func emitTypeAssert(f *Function, x Value, t types.Type, pos token.Pos) Value {
+	a := &TypeAssert{X: x, AssertedType: t}
+	a.setPos(pos)
+	a.setType(t)
+	return f.emit(a)
+}
+
+// emitTypeTest emits to f a type test value,ok := x.(t) and returns
+// a (value, ok) tuple.  x.Type() must be an interface.
+//
+func emitTypeTest(f *Function, x Value, t types.Type, pos token.Pos) Value {
+	a := &TypeAssert{
+		X:            x,
+		AssertedType: t,
+		CommaOk:      true,
+	}
+	a.setPos(pos)
+	a.setType(types.NewTuple(
+		newVar("value", t),
+		varOk,
+	))
+	return f.emit(a)
+}
+
+// emitTailCall emits to f a function call in tail position.  The
+// caller is responsible for all fields of 'call' except its type.
+// Intended for wrapper methods.
+// Precondition: f does/will not use deferred procedure calls.
+// Postcondition: f.currentBlock is nil.
+//
+func emitTailCall(f *Function, call *Call) {
+	tresults := f.Signature.Results()
+	nr := tresults.Len()
+	if nr == 1 {
+		call.typ = tresults.At(0).Type()
+	} else {
+		call.typ = tresults
+	}
+	tuple := f.emit(call)
+	var ret Return
+	switch nr {
+	case 0:
+		// no-op
+	case 1:
+		ret.Results = []Value{tuple}
+	default:
+		for i := 0; i < nr; i++ {
+			v := emitExtract(f, tuple, i)
+			// TODO(adonovan): in principle, this is required:
+			//   v = emitConv(f, o.Type, f.Signature.Results[i].Type)
+			// but in practice emitTailCall is only used when
+			// the types exactly match.
+			ret.Results = append(ret.Results, v)
+		}
+	}
+	f.emit(&ret)
+	f.currentBlock = nil
+}
+
+// emitImplicitSelections emits to f code to apply the sequence of
+// implicit field selections specified by indices to base value v, and
+// returns the selected value.
+//
+// If v is the address of a struct, the result will be the address of
+// a field; if it is the value of a struct, the result will be the
+// value of a field.
+//
+func emitImplicitSelections(f *Function, v Value, indices []int) Value {
+	for _, index := range indices {
+		fld := deref(v.Type()).Underlying().(*types.Struct).Field(index)
+
+		if isPointer(v.Type()) {
+			instr := &FieldAddr{
+				X:     v,
+				Field: index,
+			}
+			instr.setType(types.NewPointer(fld.Type()))
+			v = f.emit(instr)
+			// Load the field's value iff indirectly embedded.
+			if isPointer(fld.Type()) {
+				v = emitLoad(f, v)
+			}
+		} else {
+			instr := &Field{
+				X:     v,
+				Field: index,
+			}
+			instr.setType(fld.Type())
+			v = f.emit(instr)
+		}
+	}
+	return v
+}
+
+// emitFieldSelection emits to f code to select the index'th field of v.
+//
+// If wantAddr, the input must be a pointer-to-struct and the result
+// will be the field's address; otherwise the result will be the
+// field's value.
+// Ident id is used for position and debug info.
+//
+func emitFieldSelection(f *Function, v Value, index int, wantAddr bool, id *ast.Ident) Value {
+	fld := deref(v.Type()).Underlying().(*types.Struct).Field(index)
+	if isPointer(v.Type()) {
+		instr := &FieldAddr{
+			X:     v,
+			Field: index,
+		}
+		instr.setPos(id.Pos())
+		instr.setType(types.NewPointer(fld.Type()))
+		v = f.emit(instr)
+		// Load the field's value iff we don't want its address.
+		if !wantAddr {
+			v = emitLoad(f, v)
+		}
+	} else {
+		instr := &Field{
+			X:     v,
+			Field: index,
+		}
+		instr.setPos(id.Pos())
+		instr.setType(fld.Type())
+		v = f.emit(instr)
+	}
+	emitDebugRef(f, id, v, wantAddr)
+	return v
+}
+
+// zeroValue emits to f code to produce a zero value of type t,
+// and returns it.
+//
+func zeroValue(f *Function, t types.Type) Value {
+	switch t.Underlying().(type) {
+	case *types.Struct, *types.Array:
+		return emitLoad(f, f.addLocal(t, token.NoPos))
+	default:
+		return zeroConst(t)
+	}
+}
+
+// createRecoverBlock emits to f a block of code to return after a
+// recovered panic, and sets f.Recover to it.
+//
+// If f's result parameters are named, the code loads and returns
+// their current values, otherwise it returns the zero values of their
+// type.
+//
+// Idempotent.
+//
+func createRecoverBlock(f *Function) {
+	if f.Recover != nil {
+		return // already created
+	}
+	saved := f.currentBlock
+
+	f.Recover = f.newBasicBlock("recover")
+	f.currentBlock = f.Recover
+
+	var results []Value
+	if f.namedResults != nil {
+		// Reload NRPs to form value tuple.
+		for _, r := range f.namedResults {
+			results = append(results, emitLoad(f, r))
+		}
+	} else {
+		R := f.Signature.Results()
+		for i, n := 0, R.Len(); i < n; i++ {
+			T := R.At(i).Type()
+
+			// Return zero value of each result type.
+			results = append(results, zeroValue(f, T))
+		}
+	}
+	f.emit(&Return{Results: results})
+
+	f.currentBlock = saved
+}
diff --git a/go/ssa/example_test.go b/go/ssa/example_test.go
new file mode 100644
index 0000000..3e095b8
--- /dev/null
+++ b/go/ssa/example_test.go
@@ -0,0 +1,138 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssa_test
+
+import (
+	"fmt"
+	"os"
+
+	"go/ast"
+	"go/parser"
+	"go/token"
+
+	"golang.org/x/tools/go/loader"
+	"golang.org/x/tools/go/ssa"
+	"golang.org/x/tools/go/ssa/ssautil"
+	"golang.org/x/tools/go/types"
+)
+
+const hello = `
+package main
+
+import "fmt"
+
+const message = "Hello, World!"
+
+func main() {
+	fmt.Println(message)
+}
+`
+
+// This program demonstrates how to run the SSA builder on a single
+// package of one or more already-parsed files.  Its dependencies are
+// loaded from compiler export data.  This is what you'd typically use
+// for a compiler; it does not depend on golang.org/x/tools/go/loader.
+//
+// It shows the printed representation of packages, functions, and
+// instructions.  Within the function listing, the name of each
+// BasicBlock such as ".0.entry" is printed left-aligned, followed by
+// the block's Instructions.
+//
+// For each instruction that defines an SSA virtual register
+// (i.e. implements Value), the type of that value is shown in the
+// right column.
+//
+// Build and run the ssadump.go program if you want a standalone tool
+// with similar functionality. It is located at
+// golang.org/x/tools/cmd/ssadump.
+//
+func ExampleBuildPackage() {
+	// Parse the source files.
+	fset := token.NewFileSet()
+	f, err := parser.ParseFile(fset, "hello.go", hello, parser.ParseComments)
+	if err != nil {
+		fmt.Print(err) // parse error
+		return
+	}
+	files := []*ast.File{f}
+
+	// Create the type-checker's package.
+	pkg := types.NewPackage("hello", "")
+
+	// Type-check the package, load dependencies.
+	// Create and build the SSA program.
+	hello, _, err := ssautil.BuildPackage(
+		new(types.Config), fset, pkg, files, ssa.SanityCheckFunctions)
+	if err != nil {
+		fmt.Print(err) // type error in some package
+		return
+	}
+
+	// Print out the package.
+	hello.WriteTo(os.Stdout)
+
+	// Print out the package-level functions.
+	hello.Func("init").WriteTo(os.Stdout)
+	hello.Func("main").WriteTo(os.Stdout)
+
+	// Output:
+	//
+	// package hello:
+	//   func  init       func()
+	//   var   init$guard bool
+	//   func  main       func()
+	//   const message    message = "Hello, World!":untyped string
+	//
+	// # Name: hello.init
+	// # Package: hello
+	// # Synthetic: package initializer
+	// func init():
+	// 0:                                                                entry P:0 S:2
+	// 	t0 = *init$guard                                                   bool
+	// 	if t0 goto 2 else 1
+	// 1:                                                           init.start P:1 S:1
+	// 	*init$guard = true:bool
+	// 	t1 = fmt.init()                                                      ()
+	// 	jump 2
+	// 2:                                                            init.done P:2 S:0
+	// 	return
+	//
+	// # Name: hello.main
+	// # Package: hello
+	// # Location: hello.go:8:6
+	// func main():
+	// 0:                                                                entry P:0 S:0
+	// 	t0 = new [1]interface{} (varargs)                       *[1]interface{}
+	// 	t1 = &t0[0:int]                                            *interface{}
+	// 	t2 = make interface{} <- string ("Hello, World!":string)    interface{}
+	// 	*t1 = t2
+	// 	t3 = slice t0[:]                                          []interface{}
+	// 	t4 = fmt.Println(t3...)                              (n int, err error)
+	// 	return
+}
+
+// This program shows how to load a main package (cmd/nm) and all its
+// dependencies from source, using the loader, and then build SSA code
+// for the entire program.  This is what you'd typically use for a
+// whole-program analysis.
+//
+func ExampleLoadProgram() {
+	// Load cmd/nm and its dependencies.
+	var conf loader.Config
+	conf.Import("cmd/nm")
+	lprog, err := conf.Load()
+	if err != nil {
+		fmt.Print(err) // type error in some package
+		return
+	}
+
+	// Create SSA-form program representation.
+	prog := ssautil.CreateProgram(lprog, ssa.SanityCheckFunctions)
+
+	// Build SSA code for the entire cmd/nm program.
+	prog.BuildAll()
+
+	// Output:
+}
diff --git a/go/ssa/func.go b/go/ssa/func.go
new file mode 100644
index 0000000..a9c0f75
--- /dev/null
+++ b/go/ssa/func.go
@@ -0,0 +1,690 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssa
+
+// This file implements the Function and BasicBlock types.
+
+import (
+	"bytes"
+	"fmt"
+	"go/ast"
+	"go/token"
+	"io"
+	"os"
+	"strings"
+
+	"golang.org/x/tools/go/types"
+)
+
+// addEdge adds a control-flow graph edge from from to to.
+func addEdge(from, to *BasicBlock) {
+	from.Succs = append(from.Succs, to)
+	to.Preds = append(to.Preds, from)
+}
+
+// Parent returns the function that contains block b.
+func (b *BasicBlock) Parent() *Function { return b.parent }
+
+// String returns a human-readable label of this block.
+// It is not guaranteed unique within the function.
+//
+func (b *BasicBlock) String() string {
+	return fmt.Sprintf("%d", b.Index)
+}
+
+// emit appends an instruction to the current basic block.
+// If the instruction defines a Value, it is returned.
+//
+func (b *BasicBlock) emit(i Instruction) Value {
+	i.setBlock(b)
+	b.Instrs = append(b.Instrs, i)
+	v, _ := i.(Value)
+	return v
+}
+
+// predIndex returns the i such that b.Preds[i] == c or panics if
+// there is none.
+func (b *BasicBlock) predIndex(c *BasicBlock) int {
+	for i, pred := range b.Preds {
+		if pred == c {
+			return i
+		}
+	}
+	panic(fmt.Sprintf("no edge %s -> %s", c, b))
+}
+
+// hasPhi returns true if b.Instrs contains φ-nodes.
+func (b *BasicBlock) hasPhi() bool {
+	_, ok := b.Instrs[0].(*Phi)
+	return ok
+}
+
+// phis returns the prefix of b.Instrs containing all the block's φ-nodes.
+func (b *BasicBlock) phis() []Instruction {
+	for i, instr := range b.Instrs {
+		if _, ok := instr.(*Phi); !ok {
+			return b.Instrs[:i]
+		}
+	}
+	return nil // unreachable in well-formed blocks
+}
+
+// replacePred replaces all occurrences of p in b's predecessor list with q.
+// Ordinarily there should be at most one.
+//
+func (b *BasicBlock) replacePred(p, q *BasicBlock) {
+	for i, pred := range b.Preds {
+		if pred == p {
+			b.Preds[i] = q
+		}
+	}
+}
+
+// replaceSucc replaces all occurrences of p in b's successor list with q.
+// Ordinarily there should be at most one.
+//
+func (b *BasicBlock) replaceSucc(p, q *BasicBlock) {
+	for i, succ := range b.Succs {
+		if succ == p {
+			b.Succs[i] = q
+		}
+	}
+}
+
+// removePred removes all occurrences of p in b's
+// predecessor list and φ-nodes.
+// Ordinarily there should be at most one.
+//
+func (b *BasicBlock) removePred(p *BasicBlock) {
+	phis := b.phis()
+
+	// We must preserve edge order for φ-nodes.
+	j := 0
+	for i, pred := range b.Preds {
+		if pred != p {
+			b.Preds[j] = b.Preds[i]
+			// Strike out φ-edge too.
+			for _, instr := range phis {
+				phi := instr.(*Phi)
+				phi.Edges[j] = phi.Edges[i]
+			}
+			j++
+		}
+	}
+	// Nil out b.Preds[j:] and φ-edges[j:] to aid GC.
+	for i := j; i < len(b.Preds); i++ {
+		b.Preds[i] = nil
+		for _, instr := range phis {
+			instr.(*Phi).Edges[i] = nil
+		}
+	}
+	b.Preds = b.Preds[:j]
+	for _, instr := range phis {
+		phi := instr.(*Phi)
+		phi.Edges = phi.Edges[:j]
+	}
+}
+
+// Destinations associated with unlabelled for/switch/select stmts.
+// We push/pop one of these as we enter/leave each construct and for
+// each BranchStmt we scan for the innermost target of the right type.
+//
+type targets struct {
+	tail         *targets // rest of stack
+	_break       *BasicBlock
+	_continue    *BasicBlock
+	_fallthrough *BasicBlock
+}
+
+// Destinations associated with a labelled block.
+// We populate these as labels are encountered in forward gotos or
+// labelled statements.
+//
+type lblock struct {
+	_goto     *BasicBlock
+	_break    *BasicBlock
+	_continue *BasicBlock
+}
+
+// labelledBlock returns the branch target associated with the
+// specified label, creating it if needed.
+//
+func (f *Function) labelledBlock(label *ast.Ident) *lblock {
+	lb := f.lblocks[label.Obj]
+	if lb == nil {
+		lb = &lblock{_goto: f.newBasicBlock(label.Name)}
+		if f.lblocks == nil {
+			f.lblocks = make(map[*ast.Object]*lblock)
+		}
+		f.lblocks[label.Obj] = lb
+	}
+	return lb
+}
+
+// addParam adds a (non-escaping) parameter to f.Params of the
+// specified name, type and source position.
+//
+func (f *Function) addParam(name string, typ types.Type, pos token.Pos) *Parameter {
+	v := &Parameter{
+		name:   name,
+		typ:    typ,
+		pos:    pos,
+		parent: f,
+	}
+	f.Params = append(f.Params, v)
+	return v
+}
+
+func (f *Function) addParamObj(obj types.Object) *Parameter {
+	name := obj.Name()
+	if name == "" {
+		name = fmt.Sprintf("arg%d", len(f.Params))
+	}
+	param := f.addParam(name, obj.Type(), obj.Pos())
+	param.object = obj
+	return param
+}
+
+// addSpilledParam declares a parameter that is pre-spilled to the
+// stack; the function body will load/store the spilled location.
+// Subsequent lifting will eliminate spills where possible.
+//
+func (f *Function) addSpilledParam(obj types.Object) {
+	param := f.addParamObj(obj)
+	spill := &Alloc{Comment: obj.Name()}
+	spill.setType(types.NewPointer(obj.Type()))
+	spill.setPos(obj.Pos())
+	f.objects[obj] = spill
+	f.Locals = append(f.Locals, spill)
+	f.emit(spill)
+	f.emit(&Store{Addr: spill, Val: param})
+}
+
+// startBody initializes the function prior to generating SSA code for its body.
+// Precondition: f.Type() already set.
+//
+func (f *Function) startBody() {
+	f.currentBlock = f.newBasicBlock("entry")
+	f.objects = make(map[types.Object]Value) // needed for some synthetics, e.g. init
+}
+
+// createSyntacticParams populates f.Params and generates code (spills
+// and named result locals) for all the parameters declared in the
+// syntax.  In addition it populates the f.objects mapping.
+//
+// Preconditions:
+// f.startBody() was called.
+// Postcondition:
+// len(f.Params) == len(f.Signature.Params) + (f.Signature.Recv() ? 1 : 0)
+//
+func (f *Function) createSyntacticParams(recv *ast.FieldList, functype *ast.FuncType) {
+	// Receiver (at most one inner iteration).
+	if recv != nil {
+		for _, field := range recv.List {
+			for _, n := range field.Names {
+				f.addSpilledParam(f.Pkg.info.Defs[n])
+			}
+			// Anonymous receiver?  No need to spill.
+			if field.Names == nil {
+				f.addParamObj(f.Signature.Recv())
+			}
+		}
+	}
+
+	// Parameters.
+	if functype.Params != nil {
+		n := len(f.Params) // 1 if has recv, 0 otherwise
+		for _, field := range functype.Params.List {
+			for _, n := range field.Names {
+				f.addSpilledParam(f.Pkg.info.Defs[n])
+			}
+			// Anonymous parameter?  No need to spill.
+			if field.Names == nil {
+				f.addParamObj(f.Signature.Params().At(len(f.Params) - n))
+			}
+		}
+	}
+
+	// Named results.
+	if functype.Results != nil {
+		for _, field := range functype.Results.List {
+			// Implicit "var" decl of locals for named results.
+			for _, n := range field.Names {
+				f.namedResults = append(f.namedResults, f.addLocalForIdent(n))
+			}
+		}
+	}
+}
+
+// numberRegisters assigns numbers to all SSA registers
+// (value-defining Instructions) in f, to aid debugging.
+// (Non-Instruction Values are named at construction.)
+//
+func numberRegisters(f *Function) {
+	v := 0
+	for _, b := range f.Blocks {
+		for _, instr := range b.Instrs {
+			switch instr.(type) {
+			case Value:
+				instr.(interface {
+					setNum(int)
+				}).setNum(v)
+				v++
+			}
+		}
+	}
+}
+
+// buildReferrers populates the def/use information in all non-nil
+// Value.Referrers slice.
+// Precondition: all such slices are initially empty.
+func buildReferrers(f *Function) {
+	var rands []*Value
+	for _, b := range f.Blocks {
+		for _, instr := range b.Instrs {
+			rands = instr.Operands(rands[:0]) // recycle storage
+			for _, rand := range rands {
+				if r := *rand; r != nil {
+					if ref := r.Referrers(); ref != nil {
+						*ref = append(*ref, instr)
+					}
+				}
+			}
+		}
+	}
+}
+
+// finishBody() finalizes the function after SSA code generation of its body.
+func (f *Function) finishBody() {
+	f.objects = nil
+	f.currentBlock = nil
+	f.lblocks = nil
+
+	// Don't pin the AST in memory (except in debug mode).
+	if n := f.syntax; n != nil && !f.debugInfo() {
+		f.syntax = extentNode{n.Pos(), n.End()}
+	}
+
+	// Remove from f.Locals any Allocs that escape to the heap.
+	j := 0
+	for _, l := range f.Locals {
+		if !l.Heap {
+			f.Locals[j] = l
+			j++
+		}
+	}
+	// Nil out f.Locals[j:] to aid GC.
+	for i := j; i < len(f.Locals); i++ {
+		f.Locals[i] = nil
+	}
+	f.Locals = f.Locals[:j]
+
+	optimizeBlocks(f)
+
+	buildReferrers(f)
+
+	buildDomTree(f)
+
+	if f.Prog.mode&NaiveForm == 0 {
+		// For debugging pre-state of lifting pass:
+		// numberRegisters(f)
+		// f.WriteTo(os.Stderr)
+		lift(f)
+	}
+
+	f.namedResults = nil // (used by lifting)
+
+	numberRegisters(f)
+
+	if f.Prog.mode&PrintFunctions != 0 {
+		printMu.Lock()
+		f.WriteTo(os.Stdout)
+		printMu.Unlock()
+	}
+
+	if f.Prog.mode&SanityCheckFunctions != 0 {
+		mustSanityCheck(f, nil)
+	}
+}
+
+// removeNilBlocks eliminates nils from f.Blocks and updates each
+// BasicBlock.Index.  Use this after any pass that may delete blocks.
+//
+func (f *Function) removeNilBlocks() {
+	j := 0
+	for _, b := range f.Blocks {
+		if b != nil {
+			b.Index = j
+			f.Blocks[j] = b
+			j++
+		}
+	}
+	// Nil out f.Blocks[j:] to aid GC.
+	for i := j; i < len(f.Blocks); i++ {
+		f.Blocks[i] = nil
+	}
+	f.Blocks = f.Blocks[:j]
+}
+
+// SetDebugMode sets the debug mode for package pkg.  If true, all its
+// functions will include full debug info.  This greatly increases the
+// size of the instruction stream, and causes Functions to depend upon
+// the ASTs, potentially keeping them live in memory for longer.
+//
+func (pkg *Package) SetDebugMode(debug bool) {
+	// TODO(adonovan): do we want ast.File granularity?
+	pkg.debug = debug
+}
+
+// debugInfo reports whether debug info is wanted for this function.
+func (f *Function) debugInfo() bool {
+	return f.Pkg != nil && f.Pkg.debug
+}
+
+// addNamedLocal creates a local variable, adds it to function f and
+// returns it.  Its name and type are taken from obj.  Subsequent
+// calls to f.lookup(obj) will return the same local.
+//
+func (f *Function) addNamedLocal(obj types.Object) *Alloc {
+	l := f.addLocal(obj.Type(), obj.Pos())
+	l.Comment = obj.Name()
+	f.objects[obj] = l
+	return l
+}
+
+func (f *Function) addLocalForIdent(id *ast.Ident) *Alloc {
+	return f.addNamedLocal(f.Pkg.info.Defs[id])
+}
+
+// addLocal creates an anonymous local variable of type typ, adds it
+// to function f and returns it.  pos is the optional source location.
+//
+func (f *Function) addLocal(typ types.Type, pos token.Pos) *Alloc {
+	v := &Alloc{}
+	v.setType(types.NewPointer(typ))
+	v.setPos(pos)
+	f.Locals = append(f.Locals, v)
+	f.emit(v)
+	return v
+}
+
+// lookup returns the address of the named variable identified by obj
+// that is local to function f or one of its enclosing functions.
+// If escaping, the reference comes from a potentially escaping pointer
+// expression and the referent must be heap-allocated.
+//
+func (f *Function) lookup(obj types.Object, escaping bool) Value {
+	if v, ok := f.objects[obj]; ok {
+		if alloc, ok := v.(*Alloc); ok && escaping {
+			alloc.Heap = true
+		}
+		return v // function-local var (address)
+	}
+
+	// Definition must be in an enclosing function;
+	// plumb it through intervening closures.
+	if f.parent == nil {
+		panic("no ssa.Value for " + obj.String())
+	}
+	outer := f.parent.lookup(obj, true) // escaping
+	v := &FreeVar{
+		name:   obj.Name(),
+		typ:    outer.Type(),
+		pos:    outer.Pos(),
+		outer:  outer,
+		parent: f,
+	}
+	f.objects[obj] = v
+	f.FreeVars = append(f.FreeVars, v)
+	return v
+}
+
+// emit emits the specified instruction to function f.
+func (f *Function) emit(instr Instruction) Value {
+	return f.currentBlock.emit(instr)
+}
+
+// RelString returns the full name of this function, qualified by
+// package name, receiver type, etc.
+//
+// The specific formatting rules are not guaranteed and may change.
+//
+// Examples:
+//      "math.IsNaN"                  // a package-level function
+//      "(*bytes.Buffer).Bytes"       // a declared method or a wrapper
+//      "(*bytes.Buffer).Bytes$thunk" // thunk (func wrapping method; receiver is param 0)
+//      "(*bytes.Buffer).Bytes$bound" // bound (func wrapping method; receiver supplied by closure)
+//      "main.main$1"                 // an anonymous function in main
+//      "main.init#1"                 // a declared init function
+//      "main.init"                   // the synthesized package initializer
+//
+// When these functions are referred to from within the same package
+// (i.e. from == f.Pkg.Object), they are rendered without the package path.
+// For example: "IsNaN", "(*Buffer).Bytes", etc.
+//
+// All non-synthetic functions have distinct package-qualified names.
+// (But two methods may have the same name "(T).f" if one is a synthetic
+// wrapper promoting a non-exported method "f" from another package; in
+// that case, the strings are equal but the identifiers "f" are distinct.)
+//
+func (f *Function) RelString(from *types.Package) string {
+	// Anonymous?
+	if f.parent != nil {
+		// An anonymous function's Name() looks like "parentName$1",
+		// but its String() should include the type/package/etc.
+		parent := f.parent.RelString(from)
+		for i, anon := range f.parent.AnonFuncs {
+			if anon == f {
+				return fmt.Sprintf("%s$%d", parent, 1+i)
+			}
+		}
+
+		return f.name // should never happen
+	}
+
+	// Method (declared or wrapper)?
+	if recv := f.Signature.Recv(); recv != nil {
+		return f.relMethod(from, recv.Type())
+	}
+
+	// Thunk?
+	if f.method != nil {
+		return f.relMethod(from, f.method.Recv())
+	}
+
+	// Bound?
+	if len(f.FreeVars) == 1 && strings.HasSuffix(f.name, "$bound") {
+		return f.relMethod(from, f.FreeVars[0].Type())
+	}
+
+	// Package-level function?
+	// Prefix with package name for cross-package references only.
+	if p := f.pkgobj(); p != nil && p != from {
+		return fmt.Sprintf("%s.%s", p.Path(), f.name)
+	}
+
+	// Unknown.
+	return f.name
+}
+
+func (f *Function) relMethod(from *types.Package, recv types.Type) string {
+	return fmt.Sprintf("(%s).%s", relType(recv, from), f.name)
+}
+
+// writeSignature writes to buf the signature sig in declaration syntax.
+func writeSignature(buf *bytes.Buffer, from *types.Package, name string, sig *types.Signature, params []*Parameter) {
+	buf.WriteString("func ")
+	if recv := sig.Recv(); recv != nil {
+		buf.WriteString("(")
+		if n := params[0].Name(); n != "" {
+			buf.WriteString(n)
+			buf.WriteString(" ")
+		}
+		types.WriteType(buf, params[0].Type(), types.RelativeTo(from))
+		buf.WriteString(") ")
+	}
+	buf.WriteString(name)
+	types.WriteSignature(buf, sig, types.RelativeTo(from))
+}
+
+func (f *Function) pkgobj() *types.Package {
+	if f.Pkg != nil {
+		return f.Pkg.Object
+	}
+	return nil
+}
+
+var _ io.WriterTo = (*Function)(nil) // *Function implements io.Writer
+
+func (f *Function) WriteTo(w io.Writer) (int64, error) {
+	var buf bytes.Buffer
+	WriteFunction(&buf, f)
+	n, err := w.Write(buf.Bytes())
+	return int64(n), err
+}
+
+// WriteFunction writes to buf a human-readable "disassembly" of f.
+func WriteFunction(buf *bytes.Buffer, f *Function) {
+	fmt.Fprintf(buf, "# Name: %s\n", f.String())
+	if f.Pkg != nil {
+		fmt.Fprintf(buf, "# Package: %s\n", f.Pkg.Object.Path())
+	}
+	if syn := f.Synthetic; syn != "" {
+		fmt.Fprintln(buf, "# Synthetic:", syn)
+	}
+	if pos := f.Pos(); pos.IsValid() {
+		fmt.Fprintf(buf, "# Location: %s\n", f.Prog.Fset.Position(pos))
+	}
+
+	if f.parent != nil {
+		fmt.Fprintf(buf, "# Parent: %s\n", f.parent.Name())
+	}
+
+	if f.Recover != nil {
+		fmt.Fprintf(buf, "# Recover: %s\n", f.Recover)
+	}
+
+	from := f.pkgobj()
+
+	if f.FreeVars != nil {
+		buf.WriteString("# Free variables:\n")
+		for i, fv := range f.FreeVars {
+			fmt.Fprintf(buf, "# % 3d:\t%s %s\n", i, fv.Name(), relType(fv.Type(), from))
+		}
+	}
+
+	if len(f.Locals) > 0 {
+		buf.WriteString("# Locals:\n")
+		for i, l := range f.Locals {
+			fmt.Fprintf(buf, "# % 3d:\t%s %s\n", i, l.Name(), relType(deref(l.Type()), from))
+		}
+	}
+	writeSignature(buf, from, f.Name(), f.Signature, f.Params)
+	buf.WriteString(":\n")
+
+	if f.Blocks == nil {
+		buf.WriteString("\t(external)\n")
+	}
+
+	// NB. column calculations are confused by non-ASCII
+	// characters and assume 8-space tabs.
+	const punchcard = 80 // for old time's sake.
+	const tabwidth = 8
+	for _, b := range f.Blocks {
+		if b == nil {
+			// Corrupt CFG.
+			fmt.Fprintf(buf, ".nil:\n")
+			continue
+		}
+		n, _ := fmt.Fprintf(buf, "%d:", b.Index)
+		bmsg := fmt.Sprintf("%s P:%d S:%d", b.Comment, len(b.Preds), len(b.Succs))
+		fmt.Fprintf(buf, "%*s%s\n", punchcard-1-n-len(bmsg), "", bmsg)
+
+		if false { // CFG debugging
+			fmt.Fprintf(buf, "\t# CFG: %s --> %s --> %s\n", b.Preds, b, b.Succs)
+		}
+		for _, instr := range b.Instrs {
+			buf.WriteString("\t")
+			switch v := instr.(type) {
+			case Value:
+				l := punchcard - tabwidth
+				// Left-align the instruction.
+				if name := v.Name(); name != "" {
+					n, _ := fmt.Fprintf(buf, "%s = ", name)
+					l -= n
+				}
+				n, _ := buf.WriteString(instr.String())
+				l -= n
+				// Right-align the type if there's space.
+				if t := v.Type(); t != nil {
+					buf.WriteByte(' ')
+					ts := relType(t, from)
+					l -= len(ts) + len("  ") // (spaces before and after type)
+					if l > 0 {
+						fmt.Fprintf(buf, "%*s", l, "")
+					}
+					buf.WriteString(ts)
+				}
+			case nil:
+				// Be robust against bad transforms.
+				buf.WriteString("<deleted>")
+			default:
+				buf.WriteString(instr.String())
+			}
+			buf.WriteString("\n")
+		}
+	}
+	fmt.Fprintf(buf, "\n")
+}
+
+// newBasicBlock adds to f a new basic block and returns it.  It does
+// not automatically become the current block for subsequent calls to emit.
+// comment is an optional string for more readable debugging output.
+//
+func (f *Function) newBasicBlock(comment string) *BasicBlock {
+	b := &BasicBlock{
+		Index:   len(f.Blocks),
+		Comment: comment,
+		parent:  f,
+	}
+	b.Succs = b.succs2[:0]
+	f.Blocks = append(f.Blocks, b)
+	return b
+}
+
+// NewFunction returns a new synthetic Function instance belonging to
+// prog, with its name and signature fields set as specified.
+//
+// The caller is responsible for initializing the remaining fields of
+// the function object, e.g. Pkg, Params, Blocks.
+//
+// It is practically impossible for clients to construct well-formed
+// SSA functions/packages/programs directly, so we assume this is the
+// job of the Builder alone.  NewFunction exists to provide clients a
+// little flexibility.  For example, analysis tools may wish to
+// construct fake Functions for the root of the callgraph, a fake
+// "reflect" package, etc.
+//
+// TODO(adonovan): think harder about the API here.
+//
+func (prog *Program) NewFunction(name string, sig *types.Signature, provenance string) *Function {
+	return &Function{Prog: prog, name: name, Signature: sig, Synthetic: provenance}
+}
+
+type extentNode [2]token.Pos
+
+func (n extentNode) Pos() token.Pos { return n[0] }
+func (n extentNode) End() token.Pos { return n[1] }
+
+// Syntax returns an ast.Node whose Pos/End methods provide the
+// lexical extent of the function if it was defined by Go source code
+// (f.Synthetic==""), or nil otherwise.
+//
+// If f was built with debug information (see Package.SetDebugRef),
+// the result is the *ast.FuncDecl or *ast.FuncLit that declared the
+// function.  Otherwise, it is an opaque Node providing only position
+// information; this avoids pinning the AST in memory.
+//
+func (f *Function) Syntax() ast.Node { return f.syntax }
diff --git a/go/ssa/interp/external.go b/go/ssa/interp/external.go
new file mode 100644
index 0000000..eb0757f
--- /dev/null
+++ b/go/ssa/interp/external.go
@@ -0,0 +1,493 @@
+// Copyright 2013 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package interp
+
+// Emulated functions that we cannot interpret because they are
+// external or because they use "unsafe" or "reflect" operations.
+
+import (
+	"math"
+	"os"
+	"runtime"
+	"syscall"
+	"time"
+	"unsafe"
+
+	"golang.org/x/tools/go/ssa"
+	"golang.org/x/tools/go/types"
+)
+
+type externalFn func(fr *frame, args []value) value
+
+// TODO(adonovan): fix: reflect.Value abstracts an lvalue or an
+// rvalue; Set() causes mutations that can be observed via aliases.
+// We have not captured that correctly here.
+
+// Key strings are from Function.String().
+var externals map[string]externalFn
+
+func init() {
+	// That little dot ۰ is an Arabic zero numeral (U+06F0), categories [Nd].
+	externals = map[string]externalFn{
+		"(*sync.Pool).Get":                 ext۰sync۰Pool۰Get,
+		"(*sync.Pool).Put":                 ext۰sync۰Pool۰Put,
+		"(reflect.Value).Bool":             ext۰reflect۰Value۰Bool,
+		"(reflect.Value).CanAddr":          ext۰reflect۰Value۰CanAddr,
+		"(reflect.Value).CanInterface":     ext۰reflect۰Value۰CanInterface,
+		"(reflect.Value).Elem":             ext۰reflect۰Value۰Elem,
+		"(reflect.Value).Field":            ext۰reflect۰Value۰Field,
+		"(reflect.Value).Float":            ext۰reflect۰Value۰Float,
+		"(reflect.Value).Index":            ext۰reflect۰Value۰Index,
+		"(reflect.Value).Int":              ext۰reflect۰Value۰Int,
+		"(reflect.Value).Interface":        ext۰reflect۰Value۰Interface,
+		"(reflect.Value).IsNil":            ext۰reflect۰Value۰IsNil,
+		"(reflect.Value).IsValid":          ext۰reflect۰Value۰IsValid,
+		"(reflect.Value).Kind":             ext۰reflect۰Value۰Kind,
+		"(reflect.Value).Len":              ext۰reflect۰Value۰Len,
+		"(reflect.Value).MapIndex":         ext۰reflect۰Value۰MapIndex,
+		"(reflect.Value).MapKeys":          ext۰reflect۰Value۰MapKeys,
+		"(reflect.Value).NumField":         ext۰reflect۰Value۰NumField,
+		"(reflect.Value).NumMethod":        ext۰reflect۰Value۰NumMethod,
+		"(reflect.Value).Pointer":          ext۰reflect۰Value۰Pointer,
+		"(reflect.Value).Set":              ext۰reflect۰Value۰Set,
+		"(reflect.Value).String":           ext۰reflect۰Value۰String,
+		"(reflect.Value).Type":             ext۰reflect۰Value۰Type,
+		"(reflect.Value).Uint":             ext۰reflect۰Value۰Uint,
+		"(reflect.error).Error":            ext۰reflect۰error۰Error,
+		"(reflect.rtype).Bits":             ext۰reflect۰rtype۰Bits,
+		"(reflect.rtype).Elem":             ext۰reflect۰rtype۰Elem,
+		"(reflect.rtype).Field":            ext۰reflect۰rtype۰Field,
+		"(reflect.rtype).In":               ext۰reflect۰rtype۰In,
+		"(reflect.rtype).Kind":             ext۰reflect۰rtype۰Kind,
+		"(reflect.rtype).NumField":         ext۰reflect۰rtype۰NumField,
+		"(reflect.rtype).NumIn":            ext۰reflect۰rtype۰NumIn,
+		"(reflect.rtype).NumMethod":        ext۰reflect۰rtype۰NumMethod,
+		"(reflect.rtype).NumOut":           ext۰reflect۰rtype۰NumOut,
+		"(reflect.rtype).Out":              ext۰reflect۰rtype۰Out,
+		"(reflect.rtype).Size":             ext۰reflect۰rtype۰Size,
+		"(reflect.rtype).String":           ext۰reflect۰rtype۰String,
+		"bytes.Equal":                      ext۰bytes۰Equal,
+		"bytes.IndexByte":                  ext۰bytes۰IndexByte,
+		"hash/crc32.haveSSE42":             ext۰crc32۰haveSSE42,
+		"math.Abs":                         ext۰math۰Abs,
+		"math.Exp":                         ext۰math۰Exp,
+		"math.Float32bits":                 ext۰math۰Float32bits,
+		"math.Float32frombits":             ext۰math۰Float32frombits,
+		"math.Float64bits":                 ext۰math۰Float64bits,
+		"math.Float64frombits":             ext۰math۰Float64frombits,
+		"math.Ldexp":                       ext۰math۰Ldexp,
+		"math.Log":                         ext۰math۰Log,
+		"math.Min":                         ext۰math۰Min,
+		"os.runtime_args":                  ext۰os۰runtime_args,
+		"os.runtime_beforeExit":            ext۰os۰runtime_beforeExit,
+		"reflect.New":                      ext۰reflect۰New,
+		"reflect.SliceOf":                  ext۰reflect۰SliceOf,
+		"reflect.TypeOf":                   ext۰reflect۰TypeOf,
+		"reflect.ValueOf":                  ext۰reflect۰ValueOf,
+		"reflect.Zero":                     ext۰reflect۰Zero,
+		"reflect.init":                     ext۰reflect۰Init,
+		"reflect.valueInterface":           ext۰reflect۰valueInterface,
+		"runtime.Breakpoint":               ext۰runtime۰Breakpoint,
+		"runtime.Caller":                   ext۰runtime۰Caller,
+		"runtime.Callers":                  ext۰runtime۰Callers,
+		"runtime.FuncForPC":                ext۰runtime۰FuncForPC,
+		"runtime.GC":                       ext۰runtime۰GC,
+		"runtime.GOMAXPROCS":               ext۰runtime۰GOMAXPROCS,
+		"runtime.Goexit":                   ext۰runtime۰Goexit,
+		"runtime.Gosched":                  ext۰runtime۰Gosched,
+		"runtime.init":                     ext۰runtime۰init,
+		"runtime.NumCPU":                   ext۰runtime۰NumCPU,
+		"runtime.ReadMemStats":             ext۰runtime۰ReadMemStats,
+		"runtime.SetFinalizer":             ext۰runtime۰SetFinalizer,
+		"(*runtime.Func).Entry":            ext۰runtime۰Func۰Entry,
+		"(*runtime.Func).FileLine":         ext۰runtime۰Func۰FileLine,
+		"(*runtime.Func).Name":             ext۰runtime۰Func۰Name,
+		"runtime.environ":                  ext۰runtime۰environ,
+		"runtime.getgoroot":                ext۰runtime۰getgoroot,
+		"strings.IndexByte":                ext۰strings۰IndexByte,
+		"sync.runtime_Semacquire":          ext۰sync۰runtime_Semacquire,
+		"sync.runtime_Semrelease":          ext۰sync۰runtime_Semrelease,
+		"sync.runtime_Syncsemcheck":        ext۰sync۰runtime_Syncsemcheck,
+		"sync.runtime_registerPoolCleanup": ext۰sync۰runtime_registerPoolCleanup,
+		"sync/atomic.AddInt32":             ext۰atomic۰AddInt32,
+		"sync/atomic.AddUint32":            ext۰atomic۰AddUint32,
+		"sync/atomic.AddUint64":            ext۰atomic۰AddUint64,
+		"sync/atomic.CompareAndSwapInt32":  ext۰atomic۰CompareAndSwapInt32,
+		"sync/atomic.LoadInt32":            ext۰atomic۰LoadInt32,
+		"sync/atomic.LoadUint32":           ext۰atomic۰LoadUint32,
+		"sync/atomic.StoreInt32":           ext۰atomic۰StoreInt32,
+		"sync/atomic.StoreUint32":          ext۰atomic۰StoreUint32,
+		"syscall.Close":                    ext۰syscall۰Close,
+		"syscall.Exit":                     ext۰syscall۰Exit,
+		"syscall.Fstat":                    ext۰syscall۰Fstat,
+		"syscall.Getpid":                   ext۰syscall۰Getpid,
+		"syscall.Getwd":                    ext۰syscall۰Getwd,
+		"syscall.Kill":                     ext۰syscall۰Kill,
+		"syscall.Lstat":                    ext۰syscall۰Lstat,
+		"syscall.Open":                     ext۰syscall۰Open,
+		"syscall.ParseDirent":              ext۰syscall۰ParseDirent,
+		"syscall.RawSyscall":               ext۰syscall۰RawSyscall,
+		"syscall.Read":                     ext۰syscall۰Read,
+		"syscall.ReadDirent":               ext۰syscall۰ReadDirent,
+		"syscall.Stat":                     ext۰syscall۰Stat,
+		"syscall.Write":                    ext۰syscall۰Write,
+		"syscall.runtime_envs":             ext۰runtime۰environ,
+		"time.Sleep":                       ext۰time۰Sleep,
+		"time.now":                         ext۰time۰now,
+	}
+}
+
+// wrapError returns an interpreted 'error' interface value for err.
+func wrapError(err error) value {
+	if err == nil {
+		return iface{}
+	}
+	return iface{t: errorType, v: err.Error()}
+}
+
+func ext۰sync۰Pool۰Get(fr *frame, args []value) value {
+	Pool := fr.i.prog.ImportedPackage("sync").Type("Pool").Object()
+	_, newIndex, _ := types.LookupFieldOrMethod(Pool.Type(), false, Pool.Pkg(), "New")
+
+	if New := (*args[0].(*value)).(structure)[newIndex[0]]; New != nil {
+		return call(fr.i, fr, 0, New, nil)
+	}
+	return nil
+}
+
+func ext۰sync۰Pool۰Put(fr *frame, args []value) value {
+	return nil
+}
+
+func ext۰bytes۰Equal(fr *frame, args []value) value {
+	// func Equal(a, b []byte) bool
+	a := args[0].([]value)
+	b := args[1].([]value)
+	if len(a) != len(b) {
+		return false
+	}
+	for i := range a {
+		if a[i] != b[i] {
+			return false
+		}
+	}
+	return true
+}
+
+func ext۰bytes۰IndexByte(fr *frame, args []value) value {
+	// func IndexByte(s []byte, c byte) int
+	s := args[0].([]value)
+	c := args[1].(byte)
+	for i, b := range s {
+		if b.(byte) == c {
+			return i
+		}
+	}
+	return -1
+}
+
+func ext۰crc32۰haveSSE42(fr *frame, args []value) value {
+	return false
+}
+
+func ext۰math۰Float64frombits(fr *frame, args []value) value {
+	return math.Float64frombits(args[0].(uint64))
+}
+
+func ext۰math۰Float64bits(fr *frame, args []value) value {
+	return math.Float64bits(args[0].(float64))
+}
+
+func ext۰math۰Float32frombits(fr *frame, args []value) value {
+	return math.Float32frombits(args[0].(uint32))
+}
+
+func ext۰math۰Abs(fr *frame, args []value) value {
+	return math.Abs(args[0].(float64))
+}
+
+func ext۰math۰Exp(fr *frame, args []value) value {
+	return math.Exp(args[0].(float64))
+}
+
+func ext۰math۰Float32bits(fr *frame, args []value) value {
+	return math.Float32bits(args[0].(float32))
+}
+
+func ext۰math۰Min(fr *frame, args []value) value {
+	return math.Min(args[0].(float64), args[1].(float64))
+}
+
+func ext۰math۰Ldexp(fr *frame, args []value) value {
+	return math.Ldexp(args[0].(float64), args[1].(int))
+}
+
+func ext۰math۰Log(fr *frame, args []value) value {
+	return math.Log(args[0].(float64))
+}
+
+func ext۰os۰runtime_args(fr *frame, args []value) value {
+	return fr.i.osArgs
+}
+
+func ext۰os۰runtime_beforeExit(fr *frame, args []value) value {
+	return nil
+}
+
+func ext۰runtime۰Breakpoint(fr *frame, args []value) value {
+	runtime.Breakpoint()
+	return nil
+}
+
+func ext۰runtime۰Caller(fr *frame, args []value) value {
+	// func Caller(skip int) (pc uintptr, file string, line int, ok bool)
+	skip := 1 + args[0].(int)
+	for i := 0; i < skip; i++ {
+		if fr != nil {
+			fr = fr.caller
+		}
+	}
+	var pc uintptr
+	var file string
+	var line int
+	var ok bool
+	if fr != nil {
+		fn := fr.fn
+		// TODO(adonovan): use pc/posn of current instruction, not start of fn.
+		pc = uintptr(unsafe.Pointer(fn))
+		posn := fn.Prog.Fset.Position(fn.Pos())
+		file = posn.Filename
+		line = posn.Line
+		ok = true
+	}
+	return tuple{pc, file, line, ok}
+}
+
+func ext۰runtime۰Callers(fr *frame, args []value) value {
+	// Callers(skip int, pc []uintptr) int
+	skip := args[0].(int)
+	pc := args[1].([]value)
+	for i := 0; i < skip; i++ {
+		if fr != nil {
+			fr = fr.caller
+		}
+	}
+	i := 0
+	for fr != nil {
+		pc[i] = uintptr(unsafe.Pointer(fr.fn))
+		i++
+		fr = fr.caller
+	}
+	return i
+}
+
+func ext۰runtime۰FuncForPC(fr *frame, args []value) value {
+	// FuncForPC(pc uintptr) *Func
+	pc := args[0].(uintptr)
+	var fn *ssa.Function
+	if pc != 0 {
+		fn = (*ssa.Function)(unsafe.Pointer(pc)) // indeed unsafe!
+	}
+	var Func value
+	Func = structure{fn} // a runtime.Func
+	return &Func
+}
+
+func ext۰runtime۰environ(fr *frame, args []value) value {
+	// This function also implements syscall.runtime_envs.
+	return environ
+}
+
+func ext۰runtime۰getgoroot(fr *frame, args []value) value {
+	return os.Getenv("GOROOT")
+}
+
+func ext۰strings۰IndexByte(fr *frame, args []value) value {
+	// func IndexByte(s string, c byte) int
+	s := args[0].(string)
+	c := args[1].(byte)
+	for i := 0; i < len(s); i++ {
+		if s[i] == c {
+			return i
+		}
+	}
+	return -1
+}
+
+func ext۰sync۰runtime_Syncsemcheck(fr *frame, args []value) value {
+	// TODO(adonovan): fix: implement.
+	return nil
+}
+
+func ext۰sync۰runtime_registerPoolCleanup(fr *frame, args []value) value {
+	return nil
+}
+
+func ext۰sync۰runtime_Semacquire(fr *frame, args []value) value {
+	// TODO(adonovan): fix: implement.
+	return nil
+}
+
+func ext۰sync۰runtime_Semrelease(fr *frame, args []value) value {
+	// TODO(adonovan): fix: implement.
+	return nil
+}
+
+func ext۰runtime۰GOMAXPROCS(fr *frame, args []value) value {
+	// Ignore args[0]; don't let the interpreted program
+	// set the interpreter's GOMAXPROCS!
+	return runtime.GOMAXPROCS(0)
+}
+
+func ext۰runtime۰Goexit(fr *frame, args []value) value {
+	// TODO(adonovan): don't kill the interpreter's main goroutine.
+	runtime.Goexit()
+	return nil
+}
+
+func ext۰runtime۰GC(fr *frame, args []value) value {
+	runtime.GC()
+	return nil
+}
+
+func ext۰runtime۰Gosched(fr *frame, args []value) value {
+	runtime.Gosched()
+	return nil
+}
+
+func ext۰runtime۰init(fr *frame, args []value) value {
+	return nil
+}
+
+func ext۰runtime۰NumCPU(fr *frame, args []value) value {
+	return runtime.NumCPU()
+}
+
+func ext۰runtime۰ReadMemStats(fr *frame, args []value) value {
+	// TODO(adonovan): populate args[0].(Struct)
+	return nil
+}
+
+func ext۰atomic۰LoadUint32(fr *frame, args []value) value {
+	// TODO(adonovan): fix: not atomic!
+	return (*args[0].(*value)).(uint32)
+}
+
+func ext۰atomic۰StoreUint32(fr *frame, args []value) value {
+	// TODO(adonovan): fix: not atomic!
+	*args[0].(*value) = args[1].(uint32)
+	return nil
+}
+
+func ext۰atomic۰LoadInt32(fr *frame, args []value) value {
+	// TODO(adonovan): fix: not atomic!
+	return (*args[0].(*value)).(int32)
+}
+
+func ext۰atomic۰StoreInt32(fr *frame, args []value) value {
+	// TODO(adonovan): fix: not atomic!
+	*args[0].(*value) = args[1].(int32)
+	return nil
+}
+
+func ext۰atomic۰CompareAndSwapInt32(fr *frame, args []value) value {
+	// TODO(adonovan): fix: not atomic!
+	p := args[0].(*value)
+	if (*p).(int32) == args[1].(int32) {
+		*p = args[2].(int32)
+		return true
+	}
+	return false
+}
+
+func ext۰atomic۰AddInt32(fr *frame, args []value) value {
+	// TODO(adonovan): fix: not atomic!
+	p := args[0].(*value)
+	newv := (*p).(int32) + args[1].(int32)
+	*p = newv
+	return newv
+}
+
+func ext۰atomic۰AddUint32(fr *frame, args []value) value {
+	// TODO(adonovan): fix: not atomic!
+	p := args[0].(*value)
+	newv := (*p).(uint32) + args[1].(uint32)
+	*p = newv
+	return newv
+}
+
+func ext۰atomic۰AddUint64(fr *frame, args []value) value {
+	// TODO(adonovan): fix: not atomic!
+	p := args[0].(*value)
+	newv := (*p).(uint64) + args[1].(uint64)
+	*p = newv
+	return newv
+}
+
+func ext۰runtime۰SetFinalizer(fr *frame, args []value) value {
+	return nil // ignore
+}
+
+// Pretend: type runtime.Func struct { entry *ssa.Function }
+
+func ext۰runtime۰Func۰FileLine(fr *frame, args []value) value {
+	// func (*runtime.Func) FileLine(uintptr) (string, int)
+	f, _ := (*args[0].(*value)).(structure)[0].(*ssa.Function)
+	pc := args[1].(uintptr)
+	_ = pc
+	if f != nil {
+		// TODO(adonovan): use position of current instruction, not fn.
+		posn := f.Prog.Fset.Position(f.Pos())
+		return tuple{posn.Filename, posn.Line}
+	}
+	return tuple{"", 0}
+}
+
+func ext۰runtime۰Func۰Name(fr *frame, args []value) value {
+	// func (*runtime.Func) Name() string
+	f, _ := (*args[0].(*value)).(structure)[0].(*ssa.Function)
+	if f != nil {
+		return f.String()
+	}
+	return ""
+}
+
+func ext۰runtime۰Func۰Entry(fr *frame, args []value) value {
+	// func (*runtime.Func) Entry() uintptr
+	f, _ := (*args[0].(*value)).(structure)[0].(*ssa.Function)
+	return uintptr(unsafe.Pointer(f))
+}
+
+func ext۰time۰now(fr *frame, args []value) value {
+	nano := time.Now().UnixNano()
+	return tuple{int64(nano / 1e9), int32(nano % 1e9)}
+}
+
+func ext۰time۰Sleep(fr *frame, args []value) value {
+	time.Sleep(time.Duration(args[0].(int64)))
+	return nil
+}
+
+func ext۰syscall۰Exit(fr *frame, args []value) value {
+	panic(exitPanic(args[0].(int)))
+}
+
+func ext۰syscall۰Getwd(fr *frame, args []value) value {
+	s, err := syscall.Getwd()
+	return tuple{s, wrapError(err)}
+}
+
+func ext۰syscall۰Getpid(fr *frame, args []value) value {
+	return syscall.Getpid()
+}
+
+func valueToBytes(v value) []byte {
+	in := v.([]value)
+	b := make([]byte, len(in))
+	for i := range in {
+		b[i] = in[i].(byte)
+	}
+	return b
+}
diff --git a/go/ssa/interp/external_darwin.go b/go/ssa/interp/external_darwin.go
new file mode 100644
index 0000000..4974ad6
--- /dev/null
+++ b/go/ssa/interp/external_darwin.go
@@ -0,0 +1,18 @@
+// Copyright 2014 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build darwin
+
+package interp
+
+import "syscall"
+
+func init() {
+	externals["syscall.Sysctl"] = ext۰syscall۰Sysctl
+}
+
+func ext۰syscall۰Sysctl(fr *frame, args []value) value {
+	r, err := syscall.Sysctl(args[0].(string))
+	return tuple{r, wrapError(err)}
+}
diff --git a/go/ssa/interp/external_freebsd.go b/go/ssa/interp/external_freebsd.go
new file mode 100644
index 0000000..5203303
--- /dev/null
+++ b/go/ssa/interp/external_freebsd.go
@@ -0,0 +1,24 @@
+// Copyright 2014 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build freebsd
+
+package interp
+
+import "syscall"
+
+func init() {
+	externals["syscall.Sysctl"] = ext۰syscall۰Sysctl
+	externals["syscall.SysctlUint32"] = ext۰syscall۰SysctlUint32
+}
+
+func ext۰syscall۰Sysctl(fr *frame, args []value) value {
+	r, err := syscall.Sysctl(args[0].(string))
+	return tuple{r, wrapError(err)}
+}
+
+func ext۰syscall۰SysctlUint32(fr *frame, args []value) value {
+	r, err := syscall.SysctlUint32(args[0].(string))
+	return tuple{r, wrapError(err)}
+}
diff --git a/go/ssa/interp/external_plan9.go b/go/ssa/interp/external_plan9.go
new file mode 100644
index 0000000..05d02d5
--- /dev/null
+++ b/go/ssa/interp/external_plan9.go
@@ -0,0 +1,47 @@
+// Copyright 2013 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package interp
+
+import "syscall"
+
+func ext۰syscall۰Close(fr *frame, args []value) value {
+	panic("syscall.Close not yet implemented")
+}
+func ext۰syscall۰Fstat(fr *frame, args []value) value {
+	panic("syscall.Fstat not yet implemented")
+}
+func ext۰syscall۰Kill(fr *frame, args []value) value {
+	panic("syscall.Kill not yet implemented")
+}
+func ext۰syscall۰Lstat(fr *frame, args []value) value {
+	panic("syscall.Lstat not yet implemented")
+}
+func ext۰syscall۰Open(fr *frame, args []value) value {
+	panic("syscall.Open not yet implemented")
+}
+func ext۰syscall۰ParseDirent(fr *frame, args []value) value {
+	panic("syscall.ParseDirent not yet implemented")
+}
+func ext۰syscall۰Read(fr *frame, args []value) value {
+	panic("syscall.Read not yet implemented")
+}
+func ext۰syscall۰ReadDirent(fr *frame, args []value) value {
+	panic("syscall.ReadDirent not yet implemented")
+}
+func ext۰syscall۰Stat(fr *frame, args []value) value {
+	panic("syscall.Stat not yet implemented")
+}
+func ext۰syscall۰Write(fr *frame, args []value) value {
+	// func Write(fd int, p []byte) (n int, err error)
+	n, err := write(args[0].(int), valueToBytes(args[1]))
+	return tuple{n, wrapError(err)}
+}
+func ext۰syscall۰RawSyscall(fr *frame, args []value) value {
+	return tuple{^uintptr(0), uintptr(0), uintptr(0)}
+}
+
+func syswrite(fd int, b []byte) (int, error) {
+	return syscall.Write(fd, b)
+}
diff --git a/go/ssa/interp/external_unix.go b/go/ssa/interp/external_unix.go
new file mode 100644
index 0000000..c482eab
--- /dev/null
+++ b/go/ssa/interp/external_unix.go
@@ -0,0 +1,132 @@
+// Copyright 2013 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !windows,!plan9
+
+package interp
+
+import "syscall"
+
+func fillStat(st *syscall.Stat_t, stat structure) {
+	stat[0] = st.Dev
+	stat[1] = st.Ino
+	stat[2] = st.Nlink
+	stat[3] = st.Mode
+	stat[4] = st.Uid
+	stat[5] = st.Gid
+
+	stat[7] = st.Rdev
+	stat[8] = st.Size
+	stat[9] = st.Blksize
+	stat[10] = st.Blocks
+	// TODO(adonovan): fix: copy Timespecs.
+	// stat[11] = st.Atim
+	// stat[12] = st.Mtim
+	// stat[13] = st.Ctim
+}
+
+func ext۰syscall۰Close(fr *frame, args []value) value {
+	// func Close(fd int) (err error)
+	return wrapError(syscall.Close(args[0].(int)))
+}
+
+func ext۰syscall۰Fstat(fr *frame, args []value) value {
+	// func Fstat(fd int, stat *Stat_t) (err error)
+	fd := args[0].(int)
+	stat := (*args[1].(*value)).(structure)
+
+	var st syscall.Stat_t
+	err := syscall.Fstat(fd, &st)
+	fillStat(&st, stat)
+	return wrapError(err)
+}
+
+func ext۰syscall۰ReadDirent(fr *frame, args []value) value {
+	// func ReadDirent(fd int, buf []byte) (n int, err error)
+	fd := args[0].(int)
+	p := args[1].([]value)
+	b := make([]byte, len(p))
+	n, err := syscall.ReadDirent(fd, b)
+	for i := 0; i < n; i++ {
+		p[i] = b[i]
+	}
+	return tuple{n, wrapError(err)}
+}
+
+func ext۰syscall۰Kill(fr *frame, args []value) value {
+	// func Kill(pid int, sig Signal) (err error)
+	return wrapError(syscall.Kill(args[0].(int), syscall.Signal(args[1].(int))))
+}
+
+func ext۰syscall۰Lstat(fr *frame, args []value) value {
+	// func Lstat(name string, stat *Stat_t) (err error)
+	name := args[0].(string)
+	stat := (*args[1].(*value)).(structure)
+
+	var st syscall.Stat_t
+	err := syscall.Lstat(name, &st)
+	fillStat(&st, stat)
+	return wrapError(err)
+}
+
+func ext۰syscall۰Open(fr *frame, args []value) value {
+	// func Open(path string, mode int, perm uint32) (fd int, err error) {
+	path := args[0].(string)
+	mode := args[1].(int)
+	perm := args[2].(uint32)
+	fd, err := syscall.Open(path, mode, perm)
+	return tuple{fd, wrapError(err)}
+}
+
+func ext۰syscall۰ParseDirent(fr *frame, args []value) value {
+	// func ParseDirent(buf []byte, max int, names []string) (consumed int, count int, newnames []string)
+	max := args[1].(int)
+	var names []string
+	for _, iname := range args[2].([]value) {
+		names = append(names, iname.(string))
+	}
+	consumed, count, newnames := syscall.ParseDirent(valueToBytes(args[0]), max, names)
+	var inewnames []value
+	for _, newname := range newnames {
+		inewnames = append(inewnames, newname)
+	}
+	return tuple{consumed, count, inewnames}
+}
+
+func ext۰syscall۰Read(fr *frame, args []value) value {
+	// func Read(fd int, p []byte) (n int, err error)
+	fd := args[0].(int)
+	p := args[1].([]value)
+	b := make([]byte, len(p))
+	n, err := syscall.Read(fd, b)
+	for i := 0; i < n; i++ {
+		p[i] = b[i]
+	}
+	return tuple{n, wrapError(err)}
+}
+
+func ext۰syscall۰Stat(fr *frame, args []value) value {
+	// func Stat(name string, stat *Stat_t) (err error)
+	name := args[0].(string)
+	stat := (*args[1].(*value)).(structure)
+
+	var st syscall.Stat_t
+	err := syscall.Stat(name, &st)
+	fillStat(&st, stat)
+	return wrapError(err)
+}
+
+func ext۰syscall۰Write(fr *frame, args []value) value {
+	// func Write(fd int, p []byte) (n int, err error)
+	n, err := write(args[0].(int), valueToBytes(args[1]))
+	return tuple{n, wrapError(err)}
+}
+
+func ext۰syscall۰RawSyscall(fr *frame, args []value) value {
+	return tuple{uintptr(0), uintptr(0), uintptr(syscall.ENOSYS)}
+}
+
+func syswrite(fd int, b []byte) (int, error) {
+	return syscall.Write(fd, b)
+}
diff --git a/go/ssa/interp/external_windows.go b/go/ssa/interp/external_windows.go
new file mode 100644
index 0000000..ef28a37
--- /dev/null
+++ b/go/ssa/interp/external_windows.go
@@ -0,0 +1,44 @@
+// Copyright 2013 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package interp
+
+import "syscall"
+
+func ext۰syscall۰Close(fr *frame, args []value) value {
+	panic("syscall.Close not yet implemented")
+}
+func ext۰syscall۰Fstat(fr *frame, args []value) value {
+	panic("syscall.Fstat not yet implemented")
+}
+func ext۰syscall۰Kill(fr *frame, args []value) value {
+	panic("syscall.Kill not yet implemented")
+}
+func ext۰syscall۰Lstat(fr *frame, args []value) value {
+	panic("syscall.Lstat not yet implemented")
+}
+func ext۰syscall۰Open(fr *frame, args []value) value {
+	panic("syscall.Open not yet implemented")
+}
+func ext۰syscall۰ParseDirent(fr *frame, args []value) value {
+	panic("syscall.ParseDirent not yet implemented")
+}
+func ext۰syscall۰Read(fr *frame, args []value) value {
+	panic("syscall.Read not yet implemented")
+}
+func ext۰syscall۰ReadDirent(fr *frame, args []value) value {
+	panic("syscall.ReadDirent not yet implemented")
+}
+func ext۰syscall۰Stat(fr *frame, args []value) value {
+	panic("syscall.Stat not yet implemented")
+}
+func ext۰syscall۰Write(fr *frame, args []value) value {
+	panic("syscall.Write not yet implemented")
+}
+func ext۰syscall۰RawSyscall(fr *frame, args []value) value {
+	return tuple{uintptr(0), uintptr(0), uintptr(syscall.ENOSYS)}
+}
+func syswrite(fd int, b []byte) (int, error) {
+	panic("syswrite not yet implemented")
+}
diff --git a/go/ssa/interp/interp.go b/go/ssa/interp/interp.go
new file mode 100644
index 0000000..afe4939
--- /dev/null
+++ b/go/ssa/interp/interp.go
@@ -0,0 +1,750 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package ssa/interp defines an interpreter for the SSA
+// representation of Go programs.
+//
+// This interpreter is provided as an adjunct for testing the SSA
+// construction algorithm.  Its purpose is to provide a minimal
+// metacircular implementation of the dynamic semantics of each SSA
+// instruction.  It is not, and will never be, a production-quality Go
+// interpreter.
+//
+// The following is a partial list of Go features that are currently
+// unsupported or incomplete in the interpreter.
+//
+// * Unsafe operations, including all uses of unsafe.Pointer, are
+// impossible to support given the "boxed" value representation we
+// have chosen.
+//
+// * The reflect package is only partially implemented.
+//
+// * "sync/atomic" operations are not currently atomic due to the
+// "boxed" value representation: it is not possible to read, modify
+// and write an interface value atomically.  As a consequence, Mutexes
+// are currently broken.  TODO(adonovan): provide a metacircular
+// implementation of Mutex avoiding the broken atomic primitives.
+//
+// * recover is only partially implemented.  Also, the interpreter
+// makes no attempt to distinguish target panics from interpreter
+// crashes.
+//
+// * map iteration is asymptotically inefficient.
+//
+// * the sizes of the int, uint and uintptr types in the target
+// program are assumed to be the same as those of the interpreter
+// itself.
+//
+// * all values occupy space, even those of types defined by the spec
+// to have zero size, e.g. struct{}.  This can cause asymptotic
+// performance degradation.
+//
+// * os.Exit is implemented using panic, causing deferred functions to
+// run.
+package interp // import "golang.org/x/tools/go/ssa/interp"
+
+import (
+	"fmt"
+	"go/token"
+	"os"
+	"reflect"
+	"runtime"
+
+	"golang.org/x/tools/go/ssa"
+	"golang.org/x/tools/go/types"
+)
+
+type continuation int
+
+const (
+	kNext continuation = iota
+	kReturn
+	kJump
+)
+
+// Mode is a bitmask of options affecting the interpreter.
+type Mode uint
+
+const (
+	DisableRecover Mode = 1 << iota // Disable recover() in target programs; show interpreter crash instead.
+	EnableTracing                   // Print a trace of all instructions as they are interpreted.
+)
+
+type methodSet map[string]*ssa.Function
+
+// State shared between all interpreted goroutines.
+type interpreter struct {
+	osArgs             []value              // the value of os.Args
+	prog               *ssa.Program         // the SSA program
+	globals            map[ssa.Value]*value // addresses of global variables (immutable)
+	mode               Mode                 // interpreter options
+	reflectPackage     *ssa.Package         // the fake reflect package
+	errorMethods       methodSet            // the method set of reflect.error, which implements the error interface.
+	rtypeMethods       methodSet            // the method set of rtype, which implements the reflect.Type interface.
+	runtimeErrorString types.Type           // the runtime.errorString type
+	sizes              types.Sizes          // the effective type-sizing function
+}
+
+type deferred struct {
+	fn    value
+	args  []value
+	instr *ssa.Defer
+	tail  *deferred
+}
+
+type frame struct {
+	i                *interpreter
+	caller           *frame
+	fn               *ssa.Function
+	block, prevBlock *ssa.BasicBlock
+	env              map[ssa.Value]value // dynamic values of SSA variables
+	locals           []value
+	defers           *deferred
+	result           value
+	panicking        bool
+	panic            interface{}
+}
+
+func (fr *frame) get(key ssa.Value) value {
+	switch key := key.(type) {
+	case nil:
+		// Hack; simplifies handling of optional attributes
+		// such as ssa.Slice.{Low,High}.
+		return nil
+	case *ssa.Function, *ssa.Builtin:
+		return key
+	case *ssa.Const:
+		return constValue(key)
+	case *ssa.Global:
+		if r, ok := fr.i.globals[key]; ok {
+			return r
+		}
+	}
+	if r, ok := fr.env[key]; ok {
+		return r
+	}
+	panic(fmt.Sprintf("get: no value for %T: %v", key, key.Name()))
+}
+
+// runDefer runs a deferred call d.
+// It always returns normally, but may set or clear fr.panic.
+//
+func (fr *frame) runDefer(d *deferred) {
+	if fr.i.mode&EnableTracing != 0 {
+		fmt.Fprintf(os.Stderr, "%s: invoking deferred function call\n",
+			fr.i.prog.Fset.Position(d.instr.Pos()))
+	}
+	var ok bool
+	defer func() {
+		if !ok {
+			// Deferred call created a new state of panic.
+			fr.panicking = true
+			fr.panic = recover()
+		}
+	}()
+	call(fr.i, fr, d.instr.Pos(), d.fn, d.args)
+	ok = true
+}
+
+// runDefers executes fr's deferred function calls in LIFO order.
+//
+// On entry, fr.panicking indicates a state of panic; if
+// true, fr.panic contains the panic value.
+//
+// On completion, if a deferred call started a panic, or if no
+// deferred call recovered from a previous state of panic, then
+// runDefers itself panics after the last deferred call has run.
+//
+// If there was no initial state of panic, or it was recovered from,
+// runDefers returns normally.
+//
+func (fr *frame) runDefers() {
+	for d := fr.defers; d != nil; d = d.tail {
+		fr.runDefer(d)
+	}
+	fr.defers = nil
+	if fr.panicking {
+		panic(fr.panic) // new panic, or still panicking
+	}
+}
+
+// lookupMethod returns the method set for type typ, which may be one
+// of the interpreter's fake types.
+func lookupMethod(i *interpreter, typ types.Type, meth *types.Func) *ssa.Function {
+	switch typ {
+	case rtypeType:
+		return i.rtypeMethods[meth.Id()]
+	case errorType:
+		return i.errorMethods[meth.Id()]
+	}
+	return i.prog.LookupMethod(typ, meth.Pkg(), meth.Name())
+}
+
+// visitInstr interprets a single ssa.Instruction within the activation
+// record frame.  It returns a continuation value indicating where to
+// read the next instruction from.
+func visitInstr(fr *frame, instr ssa.Instruction) continuation {
+	switch instr := instr.(type) {
+	case *ssa.DebugRef:
+		// no-op
+
+	case *ssa.UnOp:
+		fr.env[instr] = unop(instr, fr.get(instr.X))
+
+	case *ssa.BinOp:
+		fr.env[instr] = binop(instr.Op, instr.X.Type(), fr.get(instr.X), fr.get(instr.Y))
+
+	case *ssa.Call:
+		fn, args := prepareCall(fr, &instr.Call)
+		fr.env[instr] = call(fr.i, fr, instr.Pos(), fn, args)
+
+	case *ssa.ChangeInterface:
+		fr.env[instr] = fr.get(instr.X)
+
+	case *ssa.ChangeType:
+		fr.env[instr] = fr.get(instr.X) // (can't fail)
+
+	case *ssa.Convert:
+		fr.env[instr] = conv(instr.Type(), instr.X.Type(), fr.get(instr.X))
+
+	case *ssa.MakeInterface:
+		fr.env[instr] = iface{t: instr.X.Type(), v: fr.get(instr.X)}
+
+	case *ssa.Extract:
+		fr.env[instr] = fr.get(instr.Tuple).(tuple)[instr.Index]
+
+	case *ssa.Slice:
+		fr.env[instr] = slice(fr.get(instr.X), fr.get(instr.Low), fr.get(instr.High), fr.get(instr.Max))
+
+	case *ssa.Return:
+		switch len(instr.Results) {
+		case 0:
+		case 1:
+			fr.result = fr.get(instr.Results[0])
+		default:
+			var res []value
+			for _, r := range instr.Results {
+				res = append(res, fr.get(r))
+			}
+			fr.result = tuple(res)
+		}
+		fr.block = nil
+		return kReturn
+
+	case *ssa.RunDefers:
+		fr.runDefers()
+
+	case *ssa.Panic:
+		panic(targetPanic{fr.get(instr.X)})
+
+	case *ssa.Send:
+		fr.get(instr.Chan).(chan value) <- fr.get(instr.X)
+
+	case *ssa.Store:
+		store(deref(instr.Addr.Type()), fr.get(instr.Addr).(*value), fr.get(instr.Val))
+
+	case *ssa.If:
+		succ := 1
+		if fr.get(instr.Cond).(bool) {
+			succ = 0
+		}
+		fr.prevBlock, fr.block = fr.block, fr.block.Succs[succ]
+		return kJump
+
+	case *ssa.Jump:
+		fr.prevBlock, fr.block = fr.block, fr.block.Succs[0]
+		return kJump
+
+	case *ssa.Defer:
+		fn, args := prepareCall(fr, &instr.Call)
+		fr.defers = &deferred{
+			fn:    fn,
+			args:  args,
+			instr: instr,
+			tail:  fr.defers,
+		}
+
+	case *ssa.Go:
+		fn, args := prepareCall(fr, &instr.Call)
+		go call(fr.i, nil, instr.Pos(), fn, args)
+
+	case *ssa.MakeChan:
+		fr.env[instr] = make(chan value, asInt(fr.get(instr.Size)))
+
+	case *ssa.Alloc:
+		var addr *value
+		if instr.Heap {
+			// new
+			addr = new(value)
+			fr.env[instr] = addr
+		} else {
+			// local
+			addr = fr.env[instr].(*value)
+		}
+		*addr = zero(deref(instr.Type()))
+
+	case *ssa.MakeSlice:
+		slice := make([]value, asInt(fr.get(instr.Cap)))
+		tElt := instr.Type().Underlying().(*types.Slice).Elem()
+		for i := range slice {
+			slice[i] = zero(tElt)
+		}
+		fr.env[instr] = slice[:asInt(fr.get(instr.Len))]
+
+	case *ssa.MakeMap:
+		reserve := 0
+		if instr.Reserve != nil {
+			reserve = asInt(fr.get(instr.Reserve))
+		}
+		fr.env[instr] = makeMap(instr.Type().Underlying().(*types.Map).Key(), reserve)
+
+	case *ssa.Range:
+		fr.env[instr] = rangeIter(fr.get(instr.X), instr.X.Type())
+
+	case *ssa.Next:
+		fr.env[instr] = fr.get(instr.Iter).(iter).next()
+
+	case *ssa.FieldAddr:
+		x := fr.get(instr.X)
+		// FIXME wrong!  &global.f must not change if we do *global = zero!
+		fr.env[instr] = &(*x.(*value)).(structure)[instr.Field]
+
+	case *ssa.Field:
+		fr.env[instr] = fr.get(instr.X).(structure)[instr.Field]
+
+	case *ssa.IndexAddr:
+		x := fr.get(instr.X)
+		idx := fr.get(instr.Index)
+		switch x := x.(type) {
+		case []value:
+			fr.env[instr] = &x[asInt(idx)]
+		case *value: // *array
+			fr.env[instr] = &(*x).(array)[asInt(idx)]
+		default:
+			panic(fmt.Sprintf("unexpected x type in IndexAddr: %T", x))
+		}
+
+	case *ssa.Index:
+		fr.env[instr] = fr.get(instr.X).(array)[asInt(fr.get(instr.Index))]
+
+	case *ssa.Lookup:
+		fr.env[instr] = lookup(instr, fr.get(instr.X), fr.get(instr.Index))
+
+	case *ssa.MapUpdate:
+		m := fr.get(instr.Map)
+		key := fr.get(instr.Key)
+		v := fr.get(instr.Value)
+		switch m := m.(type) {
+		case map[value]value:
+			m[key] = v
+		case *hashmap:
+			m.insert(key.(hashable), v)
+		default:
+			panic(fmt.Sprintf("illegal map type: %T", m))
+		}
+
+	case *ssa.TypeAssert:
+		fr.env[instr] = typeAssert(fr.i, instr, fr.get(instr.X).(iface))
+
+	case *ssa.MakeClosure:
+		var bindings []value
+		for _, binding := range instr.Bindings {
+			bindings = append(bindings, fr.get(binding))
+		}
+		fr.env[instr] = &closure{instr.Fn.(*ssa.Function), bindings}
+
+	case *ssa.Phi:
+		for i, pred := range instr.Block().Preds {
+			if fr.prevBlock == pred {
+				fr.env[instr] = fr.get(instr.Edges[i])
+				break
+			}
+		}
+
+	case *ssa.Select:
+		var cases []reflect.SelectCase
+		if !instr.Blocking {
+			cases = append(cases, reflect.SelectCase{
+				Dir: reflect.SelectDefault,
+			})
+		}
+		for _, state := range instr.States {
+			var dir reflect.SelectDir
+			if state.Dir == types.RecvOnly {
+				dir = reflect.SelectRecv
+			} else {
+				dir = reflect.SelectSend
+			}
+			var send reflect.Value
+			if state.Send != nil {
+				send = reflect.ValueOf(fr.get(state.Send))
+			}
+			cases = append(cases, reflect.SelectCase{
+				Dir:  dir,
+				Chan: reflect.ValueOf(fr.get(state.Chan)),
+				Send: send,
+			})
+		}
+		chosen, recv, recvOk := reflect.Select(cases)
+		if !instr.Blocking {
+			chosen-- // default case should have index -1.
+		}
+		r := tuple{chosen, recvOk}
+		for i, st := range instr.States {
+			if st.Dir == types.RecvOnly {
+				var v value
+				if i == chosen && recvOk {
+					// No need to copy since send makes an unaliased copy.
+					v = recv.Interface().(value)
+				} else {
+					v = zero(st.Chan.Type().Underlying().(*types.Chan).Elem())
+				}
+				r = append(r, v)
+			}
+		}
+		fr.env[instr] = r
+
+	default:
+		panic(fmt.Sprintf("unexpected instruction: %T", instr))
+	}
+
+	// if val, ok := instr.(ssa.Value); ok {
+	// 	fmt.Println(toString(fr.env[val])) // debugging
+	// }
+
+	return kNext
+}
+
+// prepareCall determines the function value and argument values for a
+// function call in a Call, Go or Defer instruction, performing
+// interface method lookup if needed.
+//
+func prepareCall(fr *frame, call *ssa.CallCommon) (fn value, args []value) {
+	v := fr.get(call.Value)
+	if call.Method == nil {
+		// Function call.
+		fn = v
+	} else {
+		// Interface method invocation.
+		recv := v.(iface)
+		if recv.t == nil {
+			panic("method invoked on nil interface")
+		}
+		if f := lookupMethod(fr.i, recv.t, call.Method); f == nil {
+			// Unreachable in well-typed programs.
+			panic(fmt.Sprintf("method set for dynamic type %v does not contain %s", recv.t, call.Method))
+		} else {
+			fn = f
+		}
+		args = append(args, recv.v)
+	}
+	for _, arg := range call.Args {
+		args = append(args, fr.get(arg))
+	}
+	return
+}
+
+// call interprets a call to a function (function, builtin or closure)
+// fn with arguments args, returning its result.
+// callpos is the position of the callsite.
+//
+func call(i *interpreter, caller *frame, callpos token.Pos, fn value, args []value) value {
+	switch fn := fn.(type) {
+	case *ssa.Function:
+		if fn == nil {
+			panic("call of nil function") // nil of func type
+		}
+		return callSSA(i, caller, callpos, fn, args, nil)
+	case *closure:
+		return callSSA(i, caller, callpos, fn.Fn, args, fn.Env)
+	case *ssa.Builtin:
+		return callBuiltin(caller, callpos, fn, args)
+	}
+	panic(fmt.Sprintf("cannot call %T", fn))
+}
+
+func loc(fset *token.FileSet, pos token.Pos) string {
+	if pos == token.NoPos {
+		return ""
+	}
+	return " at " + fset.Position(pos).String()
+}
+
+// callSSA interprets a call to function fn with arguments args,
+// and lexical environment env, returning its result.
+// callpos is the position of the callsite.
+//
+func callSSA(i *interpreter, caller *frame, callpos token.Pos, fn *ssa.Function, args []value, env []value) value {
+	if i.mode&EnableTracing != 0 {
+		fset := fn.Prog.Fset
+		// TODO(adonovan): fix: loc() lies for external functions.
+		fmt.Fprintf(os.Stderr, "Entering %s%s.\n", fn, loc(fset, fn.Pos()))
+		suffix := ""
+		if caller != nil {
+			suffix = ", resuming " + caller.fn.String() + loc(fset, callpos)
+		}
+		defer fmt.Fprintf(os.Stderr, "Leaving %s%s.\n", fn, suffix)
+	}
+	fr := &frame{
+		i:      i,
+		caller: caller, // for panic/recover
+		fn:     fn,
+	}
+	if fn.Parent() == nil {
+		name := fn.String()
+		if ext := externals[name]; ext != nil {
+			if i.mode&EnableTracing != 0 {
+				fmt.Fprintln(os.Stderr, "\t(external)")
+			}
+			return ext(fr, args)
+		}
+		if fn.Blocks == nil {
+			panic("no code for function: " + name)
+		}
+	}
+	fr.env = make(map[ssa.Value]value)
+	fr.block = fn.Blocks[0]
+	fr.locals = make([]value, len(fn.Locals))
+	for i, l := range fn.Locals {
+		fr.locals[i] = zero(deref(l.Type()))
+		fr.env[l] = &fr.locals[i]
+	}
+	for i, p := range fn.Params {
+		fr.env[p] = args[i]
+	}
+	for i, fv := range fn.FreeVars {
+		fr.env[fv] = env[i]
+	}
+	for fr.block != nil {
+		runFrame(fr)
+	}
+	// Destroy the locals to avoid accidental use after return.
+	for i := range fn.Locals {
+		fr.locals[i] = bad{}
+	}
+	return fr.result
+}
+
+// runFrame executes SSA instructions starting at fr.block and
+// continuing until a return, a panic, or a recovered panic.
+//
+// After a panic, runFrame panics.
+//
+// After a normal return, fr.result contains the result of the call
+// and fr.block is nil.
+//
+// A recovered panic in a function without named return parameters
+// (NRPs) becomes a normal return of the zero value of the function's
+// result type.
+//
+// After a recovered panic in a function with NRPs, fr.result is
+// undefined and fr.block contains the block at which to resume
+// control.
+//
+func runFrame(fr *frame) {
+	defer func() {
+		if fr.block == nil {
+			return // normal return
+		}
+		if fr.i.mode&DisableRecover != 0 {
+			return // let interpreter crash
+		}
+		fr.panicking = true
+		fr.panic = recover()
+		if fr.i.mode&EnableTracing != 0 {
+			fmt.Fprintf(os.Stderr, "Panicking: %T %v.\n", fr.panic, fr.panic)
+		}
+		fr.runDefers()
+		fr.block = fr.fn.Recover
+	}()
+
+	for {
+		if fr.i.mode&EnableTracing != 0 {
+			fmt.Fprintf(os.Stderr, ".%s:\n", fr.block)
+		}
+	block:
+		for _, instr := range fr.block.Instrs {
+			if fr.i.mode&EnableTracing != 0 {
+				if v, ok := instr.(ssa.Value); ok {
+					fmt.Fprintln(os.Stderr, "\t", v.Name(), "=", instr)
+				} else {
+					fmt.Fprintln(os.Stderr, "\t", instr)
+				}
+			}
+			switch visitInstr(fr, instr) {
+			case kReturn:
+				return
+			case kNext:
+				// no-op
+			case kJump:
+				break block
+			}
+		}
+	}
+}
+
+// doRecover implements the recover() built-in.
+func doRecover(caller *frame) value {
+	// recover() must be exactly one level beneath the deferred
+	// function (two levels beneath the panicking function) to
+	// have any effect.  Thus we ignore both "defer recover()" and
+	// "defer f() -> g() -> recover()".
+	if caller.i.mode&DisableRecover == 0 &&
+		caller != nil && !caller.panicking &&
+		caller.caller != nil && caller.caller.panicking {
+		caller.caller.panicking = false
+		p := caller.caller.panic
+		caller.caller.panic = nil
+		switch p := p.(type) {
+		case targetPanic:
+			// The target program explicitly called panic().
+			return p.v
+		case runtime.Error:
+			// The interpreter encountered a runtime error.
+			return iface{caller.i.runtimeErrorString, p.Error()}
+		case string:
+			// The interpreter explicitly called panic().
+			return iface{caller.i.runtimeErrorString, p}
+		default:
+			panic(fmt.Sprintf("unexpected panic type %T in target call to recover()", p))
+		}
+	}
+	return iface{}
+}
+
+// setGlobal sets the value of a system-initialized global variable.
+func setGlobal(i *interpreter, pkg *ssa.Package, name string, v value) {
+	if g, ok := i.globals[pkg.Var(name)]; ok {
+		*g = v
+		return
+	}
+	panic("no global variable: " + pkg.Object.Path() + "." + name)
+}
+
+var environ []value
+
+func init() {
+	for _, s := range os.Environ() {
+		environ = append(environ, s)
+	}
+	environ = append(environ, "GOSSAINTERP=1")
+	environ = append(environ, "GOARCH="+runtime.GOARCH)
+}
+
+// deleteBodies delete the bodies of all standalone functions except the
+// specified ones.  A missing intrinsic leads to a clear runtime error.
+func deleteBodies(pkg *ssa.Package, except ...string) {
+	keep := make(map[string]bool)
+	for _, e := range except {
+		keep[e] = true
+	}
+	for _, mem := range pkg.Members {
+		if fn, ok := mem.(*ssa.Function); ok && !keep[fn.Name()] {
+			fn.Blocks = nil
+		}
+	}
+}
+
+// Interpret interprets the Go program whose main package is mainpkg.
+// mode specifies various interpreter options.  filename and args are
+// the initial values of os.Args for the target program.  sizes is the
+// effective type-sizing function for this program.
+//
+// Interpret returns the exit code of the program: 2 for panic (like
+// gc does), or the argument to os.Exit for normal termination.
+//
+// The SSA program must include the "runtime" package.
+//
+func Interpret(mainpkg *ssa.Package, mode Mode, sizes types.Sizes, filename string, args []string) (exitCode int) {
+	i := &interpreter{
+		prog:    mainpkg.Prog,
+		globals: make(map[ssa.Value]*value),
+		mode:    mode,
+		sizes:   sizes,
+	}
+	runtimePkg := i.prog.ImportedPackage("runtime")
+	if runtimePkg == nil {
+		panic("ssa.Program doesn't include runtime package")
+	}
+	i.runtimeErrorString = runtimePkg.Type("errorString").Object().Type()
+
+	initReflect(i)
+
+	i.osArgs = append(i.osArgs, filename)
+	for _, arg := range args {
+		i.osArgs = append(i.osArgs, arg)
+	}
+
+	for _, pkg := range i.prog.AllPackages() {
+		// Initialize global storage.
+		for _, m := range pkg.Members {
+			switch v := m.(type) {
+			case *ssa.Global:
+				cell := zero(deref(v.Type()))
+				i.globals[v] = &cell
+			}
+		}
+
+		// Ad-hoc initialization for magic system variables.
+		switch pkg.Object.Path() {
+		case "syscall":
+			setGlobal(i, pkg, "envs", environ)
+
+		case "reflect":
+			deleteBodies(pkg, "DeepEqual", "deepValueEqual")
+
+		case "runtime":
+			sz := sizes.Sizeof(pkg.Object.Scope().Lookup("MemStats").Type())
+			setGlobal(i, pkg, "sizeof_C_MStats", uintptr(sz))
+			deleteBodies(pkg, "GOROOT", "gogetenv")
+		}
+	}
+
+	// Top-level error handler.
+	exitCode = 2
+	defer func() {
+		if exitCode != 2 || i.mode&DisableRecover != 0 {
+			return
+		}
+		switch p := recover().(type) {
+		case exitPanic:
+			exitCode = int(p)
+			return
+		case targetPanic:
+			fmt.Fprintln(os.Stderr, "panic:", toString(p.v))
+		case runtime.Error:
+			fmt.Fprintln(os.Stderr, "panic:", p.Error())
+		case string:
+			fmt.Fprintln(os.Stderr, "panic:", p)
+		default:
+			fmt.Fprintf(os.Stderr, "panic: unexpected type: %T: %v\n", p, p)
+		}
+
+		// TODO(adonovan): dump panicking interpreter goroutine?
+		// buf := make([]byte, 0x10000)
+		// runtime.Stack(buf, false)
+		// fmt.Fprintln(os.Stderr, string(buf))
+		// (Or dump panicking target goroutine?)
+	}()
+
+	// Run!
+	call(i, nil, token.NoPos, mainpkg.Func("init"), nil)
+	if mainFn := mainpkg.Func("main"); mainFn != nil {
+		call(i, nil, token.NoPos, mainFn, nil)
+		exitCode = 0
+	} else {
+		fmt.Fprintln(os.Stderr, "No main function.")
+		exitCode = 1
+	}
+	return
+}
+
+// deref returns a pointer's element type; otherwise it returns typ.
+// TODO(adonovan): Import from ssa?
+func deref(typ types.Type) types.Type {
+	if p, ok := typ.Underlying().(*types.Pointer); ok {
+		return p.Elem()
+	}
+	return typ
+}
diff --git a/go/ssa/interp/interp_test.go b/go/ssa/interp/interp_test.go
new file mode 100644
index 0000000..f36c23e
--- /dev/null
+++ b/go/ssa/interp/interp_test.go
@@ -0,0 +1,366 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !android,!windows,!plan9
+
+package interp_test
+
+import (
+	"bytes"
+	"fmt"
+	"go/build"
+	"os"
+	"path/filepath"
+	"strings"
+	"testing"
+	"time"
+
+	"golang.org/x/tools/go/loader"
+	"golang.org/x/tools/go/ssa"
+	"golang.org/x/tools/go/ssa/interp"
+	"golang.org/x/tools/go/ssa/ssautil"
+	"golang.org/x/tools/go/types"
+)
+
+// Each line contains a space-separated list of $GOROOT/test/
+// filenames comprising the main package of a program.
+// They are ordered quickest-first, roughly.
+//
+// TODO(adonovan): integrate into the $GOROOT/test driver scripts,
+// golden file checking, etc.
+var gorootTestTests = []string{
+	"235.go",
+	"alias1.go",
+	"chancap.go",
+	"func5.go",
+	"func6.go",
+	"func7.go",
+	"func8.go",
+	"helloworld.go",
+	"varinit.go",
+	"escape3.go",
+	"initcomma.go",
+	"cmp.go",
+	"compos.go",
+	"turing.go",
+	"indirect.go",
+	"complit.go",
+	"for.go",
+	"struct0.go",
+	"intcvt.go",
+	"printbig.go",
+	"deferprint.go",
+	"escape.go",
+	"range.go",
+	"const4.go",
+	"float_lit.go",
+	"bigalg.go",
+	"decl.go",
+	"if.go",
+	"named.go",
+	"bigmap.go",
+	"func.go",
+	"reorder2.go",
+	"closure.go",
+	"gc.go",
+	"simassign.go",
+	"iota.go",
+	"nilptr2.go",
+	"goprint.go", // doesn't actually assert anything (cmpout)
+	"utf.go",
+	"method.go",
+	"char_lit.go",
+	"env.go",
+	"int_lit.go",
+	"string_lit.go",
+	"defer.go",
+	"typeswitch.go",
+	"stringrange.go",
+	"reorder.go",
+	"method3.go",
+	"literal.go",
+	"nul1.go", // doesn't actually assert anything (errorcheckoutput)
+	"zerodivide.go",
+	"convert.go",
+	"convT2X.go",
+	"switch.go",
+	"initialize.go",
+	"ddd.go",
+	"blank.go", // partly disabled
+	"map.go",
+	"closedchan.go",
+	"divide.go",
+	"rename.go",
+	"const3.go",
+	"nil.go",
+	"recover.go", // reflection parts disabled
+	"recover1.go",
+	"recover2.go",
+	"recover3.go",
+	"typeswitch1.go",
+	"floatcmp.go",
+	"crlf.go", // doesn't actually assert anything (runoutput)
+	// Slow tests follow.
+	"bom.go", // ~1.7s
+	"gc1.go", // ~1.7s
+	"cmplxdivide.go cmplxdivide1.go", // ~2.4s
+
+	// Working, but not worth enabling:
+	// "append.go",    // works, but slow (15s).
+	// "gc2.go",       // works, but slow, and cheats on the memory check.
+	// "sigchld.go",   // works, but only on POSIX.
+	// "peano.go",     // works only up to n=9, and slow even then.
+	// "stack.go",     // works, but too slow (~30s) by default.
+	// "solitaire.go", // works, but too slow (~30s).
+	// "const.go",     // works but for but one bug: constant folder doesn't consider representations.
+	// "init1.go",     // too slow (80s) and not that interesting. Cheats on ReadMemStats check too.
+	// "rotate.go rotate0.go", // emits source for a test
+	// "rotate.go rotate1.go", // emits source for a test
+	// "rotate.go rotate2.go", // emits source for a test
+	// "rotate.go rotate3.go", // emits source for a test
+	// "64bit.go",             // emits source for a test
+	// "run.go",               // test driver, not a test.
+
+	// Broken.  TODO(adonovan): fix.
+	// copy.go         // very slow; but with N=4 quickly crashes, slice index out of range.
+	// nilptr.go       // interp: V > uintptr not implemented. Slow test, lots of mem
+	// args.go         // works, but requires specific os.Args from the driver.
+	// index.go        // a template, not a real test.
+	// mallocfin.go    // SetFinalizer not implemented.
+
+	// TODO(adonovan): add tests from $GOROOT/test/* subtrees:
+	// bench chan bugs fixedbugs interface ken.
+}
+
+// These are files in go.tools/go/ssa/interp/testdata/.
+var testdataTests = []string{
+	"boundmeth.go",
+	"complit.go",
+	"coverage.go",
+	"defer.go",
+	"fieldprom.go",
+	"ifaceconv.go",
+	"ifaceprom.go",
+	"initorder.go",
+	"methprom.go",
+	"mrvchain.go",
+	"range.go",
+	"recover.go",
+	"reflect.go",
+	"static.go",
+	"callstack.go",
+}
+
+// These are files and packages in $GOROOT/src/.
+var gorootSrcTests = []string{
+	"encoding/ascii85",
+	"encoding/hex",
+	// "encoding/pem", // TODO(adonovan): implement (reflect.Value).SetString
+	// "testing",      // TODO(adonovan): implement runtime.Goexit correctly
+	"unicode",
+
+	// Too slow:
+	// "container/ring",
+	// "hash/adler32",
+
+	// TODO(adonovan): packages with Examples require os.Pipe (unimplemented):
+	// "hash/crc32",
+	// "unicode/utf8",
+	// "log",
+	// "path",
+	// "flag",
+	// "encoding/csv"
+	// "text/scanner"
+}
+
+type successPredicate func(exitcode int, output string) error
+
+func run(t *testing.T, dir, input string, success successPredicate) bool {
+	fmt.Printf("Input: %s\n", input)
+
+	start := time.Now()
+
+	var inputs []string
+	for _, i := range strings.Split(input, " ") {
+		if strings.HasSuffix(i, ".go") {
+			i = dir + i
+		}
+		inputs = append(inputs, i)
+	}
+
+	var conf loader.Config
+	if _, err := conf.FromArgs(inputs, true); err != nil {
+		t.Errorf("FromArgs(%s) failed: %s", inputs, err)
+		return false
+	}
+
+	conf.Import("runtime")
+
+	// Print a helpful hint if we don't make it to the end.
+	var hint string
+	defer func() {
+		if hint != "" {
+			fmt.Println("FAIL")
+			fmt.Println(hint)
+		} else {
+			fmt.Println("PASS")
+		}
+
+		interp.CapturedOutput = nil
+	}()
+
+	hint = fmt.Sprintf("To dump SSA representation, run:\n%% go build golang.org/x/tools/cmd/ssadump && ./ssadump -build=CFP %s\n", input)
+
+	iprog, err := conf.Load()
+	if err != nil {
+		t.Errorf("conf.Load(%s) failed: %s", inputs, err)
+		return false
+	}
+
+	prog := ssautil.CreateProgram(iprog, ssa.SanityCheckFunctions)
+	prog.BuildAll()
+
+	var mainPkg *ssa.Package
+	var initialPkgs []*ssa.Package
+	for _, info := range iprog.InitialPackages() {
+		if info.Pkg.Path() == "runtime" {
+			continue // not an initial package
+		}
+		p := prog.Package(info.Pkg)
+		initialPkgs = append(initialPkgs, p)
+		if mainPkg == nil && p.Func("main") != nil {
+			mainPkg = p
+		}
+	}
+	if mainPkg == nil {
+		testmainPkg := prog.CreateTestMainPackage(initialPkgs...)
+		if testmainPkg == nil {
+			t.Errorf("CreateTestMainPackage(%s) returned nil", mainPkg)
+			return false
+		}
+		if testmainPkg.Func("main") == nil {
+			t.Errorf("synthetic testmain package has no main")
+			return false
+		}
+		mainPkg = testmainPkg
+	}
+
+	var out bytes.Buffer
+	interp.CapturedOutput = &out
+
+	hint = fmt.Sprintf("To trace execution, run:\n%% go build golang.org/x/tools/cmd/ssadump && ./ssadump -build=C -run --interp=T %s\n", input)
+	exitCode := interp.Interpret(mainPkg, 0, &types.StdSizes{8, 8}, inputs[0], []string{})
+
+	// The definition of success varies with each file.
+	if err := success(exitCode, out.String()); err != nil {
+		t.Errorf("interp.Interpret(%s) failed: %s", inputs, err)
+		return false
+	}
+
+	hint = "" // call off the hounds
+
+	if false {
+		fmt.Println(input, time.Since(start)) // test profiling
+	}
+
+	return true
+}
+
+const slash = string(os.PathSeparator)
+
+func printFailures(failures []string) {
+	if failures != nil {
+		fmt.Println("The following tests failed:")
+		for _, f := range failures {
+			fmt.Printf("\t%s\n", f)
+		}
+	}
+}
+
+func success(exitcode int, output string) error {
+	if exitcode != 0 {
+		return fmt.Errorf("exit code was %d", exitcode)
+	}
+	if strings.Contains(output, "BUG") {
+		return fmt.Errorf("exited zero but output contained 'BUG'")
+	}
+	return nil
+}
+
+// TestTestdataFiles runs the interpreter on testdata/*.go.
+func TestTestdataFiles(t *testing.T) {
+	var failures []string
+	start := time.Now()
+	for _, input := range testdataTests {
+		if testing.Short() && time.Since(start) > 30*time.Second {
+			printFailures(failures)
+			t.Skipf("timeout - aborting test")
+		}
+		if !run(t, "testdata"+slash, input, success) {
+			failures = append(failures, input)
+		}
+	}
+	printFailures(failures)
+}
+
+// TestGorootTest runs the interpreter on $GOROOT/test/*.go.
+func TestGorootTest(t *testing.T) {
+	if testing.Short() {
+		t.Skip() // too slow (~30s)
+	}
+
+	var failures []string
+
+	for _, input := range gorootTestTests {
+		if !run(t, filepath.Join(build.Default.GOROOT, "test")+slash, input, success) {
+			failures = append(failures, input)
+		}
+	}
+	for _, input := range gorootSrcTests {
+		if !run(t, filepath.Join(build.Default.GOROOT, "src")+slash, input, success) {
+			failures = append(failures, input)
+		}
+	}
+	printFailures(failures)
+}
+
+// TestTestmainPackage runs the interpreter on a synthetic "testmain" package.
+func TestTestmainPackage(t *testing.T) {
+	if testing.Short() {
+		t.Skip() // too slow on some platforms
+	}
+
+	success := func(exitcode int, output string) error {
+		if exitcode == 0 {
+			return fmt.Errorf("unexpected success")
+		}
+		if !strings.Contains(output, "FAIL: TestFoo") {
+			return fmt.Errorf("missing failure log for TestFoo")
+		}
+		if !strings.Contains(output, "FAIL: TestBar") {
+			return fmt.Errorf("missing failure log for TestBar")
+		}
+		// TODO(adonovan): test benchmarks too
+		return nil
+	}
+	run(t, "testdata"+slash, "a_test.go", success)
+}
+
+// CreateTestMainPackage should return nil if there were no tests.
+func TestNullTestmainPackage(t *testing.T) {
+	var conf loader.Config
+	conf.CreateFromFilenames("", "testdata/b_test.go")
+	iprog, err := conf.Load()
+	if err != nil {
+		t.Fatalf("CreatePackages failed: %s", err)
+	}
+	prog := ssautil.CreateProgram(iprog, ssa.SanityCheckFunctions)
+	mainPkg := prog.Package(iprog.Created[0].Pkg)
+	if mainPkg.Func("main") != nil {
+		t.Fatalf("unexpected main function")
+	}
+	if prog.CreateTestMainPackage(mainPkg) != nil {
+		t.Fatalf("CreateTestMainPackage returned non-nil")
+	}
+}
diff --git a/go/ssa/interp/map.go b/go/ssa/interp/map.go
new file mode 100644
index 0000000..5dbaf0a
--- /dev/null
+++ b/go/ssa/interp/map.go
@@ -0,0 +1,113 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package interp
+
+// Custom hashtable atop map.
+// For use when the key's equivalence relation is not consistent with ==.
+
+// The Go specification doesn't address the atomicity of map operations.
+// The FAQ states that an implementation is permitted to crash on
+// concurrent map access.
+
+import (
+	"golang.org/x/tools/go/types"
+)
+
+type hashable interface {
+	hash(t types.Type) int
+	eq(t types.Type, x interface{}) bool
+}
+
+type entry struct {
+	key   hashable
+	value value
+	next  *entry
+}
+
+// A hashtable atop the built-in map.  Since each bucket contains
+// exactly one hash value, there's no need to perform hash-equality
+// tests when walking the linked list.  Rehashing is done by the
+// underlying map.
+type hashmap struct {
+	keyType types.Type
+	table   map[int]*entry
+	length  int // number of entries in map
+}
+
+// makeMap returns an empty initialized map of key type kt,
+// preallocating space for reserve elements.
+func makeMap(kt types.Type, reserve int) value {
+	if usesBuiltinMap(kt) {
+		return make(map[value]value, reserve)
+	}
+	return &hashmap{keyType: kt, table: make(map[int]*entry, reserve)}
+}
+
+// delete removes the association for key k, if any.
+func (m *hashmap) delete(k hashable) {
+	if m != nil {
+		hash := k.hash(m.keyType)
+		head := m.table[hash]
+		if head != nil {
+			if k.eq(m.keyType, head.key) {
+				m.table[hash] = head.next
+				m.length--
+				return
+			}
+			prev := head
+			for e := head.next; e != nil; e = e.next {
+				if k.eq(m.keyType, e.key) {
+					prev.next = e.next
+					m.length--
+					return
+				}
+				prev = e
+			}
+		}
+	}
+}
+
+// lookup returns the value associated with key k, if present, or
+// value(nil) otherwise.
+func (m *hashmap) lookup(k hashable) value {
+	if m != nil {
+		hash := k.hash(m.keyType)
+		for e := m.table[hash]; e != nil; e = e.next {
+			if k.eq(m.keyType, e.key) {
+				return e.value
+			}
+		}
+	}
+	return nil
+}
+
+// insert updates the map to associate key k with value v.  If there
+// was already an association for an eq() (though not necessarily ==)
+// k, the previous key remains in the map and its associated value is
+// updated.
+func (m *hashmap) insert(k hashable, v value) {
+	hash := k.hash(m.keyType)
+	head := m.table[hash]
+	for e := head; e != nil; e = e.next {
+		if k.eq(m.keyType, e.key) {
+			e.value = v
+			return
+		}
+	}
+	m.table[hash] = &entry{
+		key:   k,
+		value: v,
+		next:  head,
+	}
+	m.length++
+}
+
+// len returns the number of key/value associations in the map.
+func (m *hashmap) len() int {
+	if m != nil {
+		return m.length
+	}
+	return 0
+}
diff --git a/go/ssa/interp/ops.go b/go/ssa/interp/ops.go
new file mode 100644
index 0000000..de89904
--- /dev/null
+++ b/go/ssa/interp/ops.go
@@ -0,0 +1,1394 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package interp
+
+import (
+	"bytes"
+	"fmt"
+	"go/token"
+	"strings"
+	"sync"
+	"unsafe"
+
+	"golang.org/x/tools/go/exact"
+	"golang.org/x/tools/go/ssa"
+	"golang.org/x/tools/go/types"
+)
+
+// If the target program panics, the interpreter panics with this type.
+type targetPanic struct {
+	v value
+}
+
+func (p targetPanic) String() string {
+	return toString(p.v)
+}
+
+// If the target program calls exit, the interpreter panics with this type.
+type exitPanic int
+
+// constValue returns the value of the constant with the
+// dynamic type tag appropriate for c.Type().
+func constValue(c *ssa.Const) value {
+	if c.IsNil() {
+		return zero(c.Type()) // typed nil
+	}
+
+	if t, ok := c.Type().Underlying().(*types.Basic); ok {
+		// TODO(adonovan): eliminate untyped constants from SSA form.
+		switch t.Kind() {
+		case types.Bool, types.UntypedBool:
+			return exact.BoolVal(c.Value)
+		case types.Int, types.UntypedInt:
+			// Assume sizeof(int) is same on host and target.
+			return int(c.Int64())
+		case types.Int8:
+			return int8(c.Int64())
+		case types.Int16:
+			return int16(c.Int64())
+		case types.Int32, types.UntypedRune:
+			return int32(c.Int64())
+		case types.Int64:
+			return c.Int64()
+		case types.Uint:
+			// Assume sizeof(uint) is same on host and target.
+			return uint(c.Uint64())
+		case types.Uint8:
+			return uint8(c.Uint64())
+		case types.Uint16:
+			return uint16(c.Uint64())
+		case types.Uint32:
+			return uint32(c.Uint64())
+		case types.Uint64:
+			return c.Uint64()
+		case types.Uintptr:
+			// Assume sizeof(uintptr) is same on host and target.
+			return uintptr(c.Uint64())
+		case types.Float32:
+			return float32(c.Float64())
+		case types.Float64, types.UntypedFloat:
+			return c.Float64()
+		case types.Complex64:
+			return complex64(c.Complex128())
+		case types.Complex128, types.UntypedComplex:
+			return c.Complex128()
+		case types.String, types.UntypedString:
+			if c.Value.Kind() == exact.String {
+				return exact.StringVal(c.Value)
+			}
+			return string(rune(c.Int64()))
+		}
+	}
+
+	panic(fmt.Sprintf("constValue: %s", c))
+}
+
+// asInt converts x, which must be an integer, to an int suitable for
+// use as a slice or array index or operand to make().
+func asInt(x value) int {
+	switch x := x.(type) {
+	case int:
+		return x
+	case int8:
+		return int(x)
+	case int16:
+		return int(x)
+	case int32:
+		return int(x)
+	case int64:
+		return int(x)
+	case uint:
+		return int(x)
+	case uint8:
+		return int(x)
+	case uint16:
+		return int(x)
+	case uint32:
+		return int(x)
+	case uint64:
+		return int(x)
+	case uintptr:
+		return int(x)
+	}
+	panic(fmt.Sprintf("cannot convert %T to int", x))
+}
+
+// asUint64 converts x, which must be an unsigned integer, to a uint64
+// suitable for use as a bitwise shift count.
+func asUint64(x value) uint64 {
+	switch x := x.(type) {
+	case uint:
+		return uint64(x)
+	case uint8:
+		return uint64(x)
+	case uint16:
+		return uint64(x)
+	case uint32:
+		return uint64(x)
+	case uint64:
+		return x
+	case uintptr:
+		return uint64(x)
+	}
+	panic(fmt.Sprintf("cannot convert %T to uint64", x))
+}
+
+// zero returns a new "zero" value of the specified type.
+func zero(t types.Type) value {
+	switch t := t.(type) {
+	case *types.Basic:
+		if t.Kind() == types.UntypedNil {
+			panic("untyped nil has no zero value")
+		}
+		if t.Info()&types.IsUntyped != 0 {
+			// TODO(adonovan): make it an invariant that
+			// this is unreachable.  Currently some
+			// constants have 'untyped' types when they
+			// should be defaulted by the typechecker.
+			t = ssa.DefaultType(t).(*types.Basic)
+		}
+		switch t.Kind() {
+		case types.Bool:
+			return false
+		case types.Int:
+			return int(0)
+		case types.Int8:
+			return int8(0)
+		case types.Int16:
+			return int16(0)
+		case types.Int32:
+			return int32(0)
+		case types.Int64:
+			return int64(0)
+		case types.Uint:
+			return uint(0)
+		case types.Uint8:
+			return uint8(0)
+		case types.Uint16:
+			return uint16(0)
+		case types.Uint32:
+			return uint32(0)
+		case types.Uint64:
+			return uint64(0)
+		case types.Uintptr:
+			return uintptr(0)
+		case types.Float32:
+			return float32(0)
+		case types.Float64:
+			return float64(0)
+		case types.Complex64:
+			return complex64(0)
+		case types.Complex128:
+			return complex128(0)
+		case types.String:
+			return ""
+		case types.UnsafePointer:
+			return unsafe.Pointer(nil)
+		default:
+			panic(fmt.Sprint("zero for unexpected type:", t))
+		}
+	case *types.Pointer:
+		return (*value)(nil)
+	case *types.Array:
+		a := make(array, t.Len())
+		for i := range a {
+			a[i] = zero(t.Elem())
+		}
+		return a
+	case *types.Named:
+		return zero(t.Underlying())
+	case *types.Interface:
+		return iface{} // nil type, methodset and value
+	case *types.Slice:
+		return []value(nil)
+	case *types.Struct:
+		s := make(structure, t.NumFields())
+		for i := range s {
+			s[i] = zero(t.Field(i).Type())
+		}
+		return s
+	case *types.Tuple:
+		if t.Len() == 1 {
+			return zero(t.At(0).Type())
+		}
+		s := make(tuple, t.Len())
+		for i := range s {
+			s[i] = zero(t.At(i).Type())
+		}
+		return s
+	case *types.Chan:
+		return chan value(nil)
+	case *types.Map:
+		if usesBuiltinMap(t.Key()) {
+			return map[value]value(nil)
+		}
+		return (*hashmap)(nil)
+	case *types.Signature:
+		return (*ssa.Function)(nil)
+	}
+	panic(fmt.Sprint("zero: unexpected ", t))
+}
+
+// slice returns x[lo:hi:max].  Any of lo, hi and max may be nil.
+func slice(x, lo, hi, max value) value {
+	var Len, Cap int
+	switch x := x.(type) {
+	case string:
+		Len = len(x)
+	case []value:
+		Len = len(x)
+		Cap = cap(x)
+	case *value: // *array
+		a := (*x).(array)
+		Len = len(a)
+		Cap = cap(a)
+	}
+
+	l := 0
+	if lo != nil {
+		l = asInt(lo)
+	}
+
+	h := Len
+	if hi != nil {
+		h = asInt(hi)
+	}
+
+	m := Cap
+	if max != nil {
+		m = asInt(max)
+	}
+
+	switch x := x.(type) {
+	case string:
+		return x[l:h]
+	case []value:
+		return x[l:h:m]
+	case *value: // *array
+		a := (*x).(array)
+		return []value(a)[l:h:m]
+	}
+	panic(fmt.Sprintf("slice: unexpected X type: %T", x))
+}
+
+// lookup returns x[idx] where x is a map or string.
+func lookup(instr *ssa.Lookup, x, idx value) value {
+	switch x := x.(type) { // map or string
+	case map[value]value, *hashmap:
+		var v value
+		var ok bool
+		switch x := x.(type) {
+		case map[value]value:
+			v, ok = x[idx]
+		case *hashmap:
+			v = x.lookup(idx.(hashable))
+			ok = v != nil
+		}
+		if !ok {
+			v = zero(instr.X.Type().Underlying().(*types.Map).Elem())
+		}
+		if instr.CommaOk {
+			v = tuple{v, ok}
+		}
+		return v
+	case string:
+		return x[asInt(idx)]
+	}
+	panic(fmt.Sprintf("unexpected x type in Lookup: %T", x))
+}
+
+// binop implements all arithmetic and logical binary operators for
+// numeric datatypes and strings.  Both operands must have identical
+// dynamic type.
+//
+func binop(op token.Token, t types.Type, x, y value) value {
+	switch op {
+	case token.ADD:
+		switch x.(type) {
+		case int:
+			return x.(int) + y.(int)
+		case int8:
+			return x.(int8) + y.(int8)
+		case int16:
+			return x.(int16) + y.(int16)
+		case int32:
+			return x.(int32) + y.(int32)
+		case int64:
+			return x.(int64) + y.(int64)
+		case uint:
+			return x.(uint) + y.(uint)
+		case uint8:
+			return x.(uint8) + y.(uint8)
+		case uint16:
+			return x.(uint16) + y.(uint16)
+		case uint32:
+			return x.(uint32) + y.(uint32)
+		case uint64:
+			return x.(uint64) + y.(uint64)
+		case uintptr:
+			return x.(uintptr) + y.(uintptr)
+		case float32:
+			return x.(float32) + y.(float32)
+		case float64:
+			return x.(float64) + y.(float64)
+		case complex64:
+			return x.(complex64) + y.(complex64)
+		case complex128:
+			return x.(complex128) + y.(complex128)
+		case string:
+			return x.(string) + y.(string)
+		}
+
+	case token.SUB:
+		switch x.(type) {
+		case int:
+			return x.(int) - y.(int)
+		case int8:
+			return x.(int8) - y.(int8)
+		case int16:
+			return x.(int16) - y.(int16)
+		case int32:
+			return x.(int32) - y.(int32)
+		case int64:
+			return x.(int64) - y.(int64)
+		case uint:
+			return x.(uint) - y.(uint)
+		case uint8:
+			return x.(uint8) - y.(uint8)
+		case uint16:
+			return x.(uint16) - y.(uint16)
+		case uint32:
+			return x.(uint32) - y.(uint32)
+		case uint64:
+			return x.(uint64) - y.(uint64)
+		case uintptr:
+			return x.(uintptr) - y.(uintptr)
+		case float32:
+			return x.(float32) - y.(float32)
+		case float64:
+			return x.(float64) - y.(float64)
+		case complex64:
+			return x.(complex64) - y.(complex64)
+		case complex128:
+			return x.(complex128) - y.(complex128)
+		}
+
+	case token.MUL:
+		switch x.(type) {
+		case int:
+			return x.(int) * y.(int)
+		case int8:
+			return x.(int8) * y.(int8)
+		case int16:
+			return x.(int16) * y.(int16)
+		case int32:
+			return x.(int32) * y.(int32)
+		case int64:
+			return x.(int64) * y.(int64)
+		case uint:
+			return x.(uint) * y.(uint)
+		case uint8:
+			return x.(uint8) * y.(uint8)
+		case uint16:
+			return x.(uint16) * y.(uint16)
+		case uint32:
+			return x.(uint32) * y.(uint32)
+		case uint64:
+			return x.(uint64) * y.(uint64)
+		case uintptr:
+			return x.(uintptr) * y.(uintptr)
+		case float32:
+			return x.(float32) * y.(float32)
+		case float64:
+			return x.(float64) * y.(float64)
+		case complex64:
+			return x.(complex64) * y.(complex64)
+		case complex128:
+			return x.(complex128) * y.(complex128)
+		}
+
+	case token.QUO:
+		switch x.(type) {
+		case int:
+			return x.(int) / y.(int)
+		case int8:
+			return x.(int8) / y.(int8)
+		case int16:
+			return x.(int16) / y.(int16)
+		case int32:
+			return x.(int32) / y.(int32)
+		case int64:
+			return x.(int64) / y.(int64)
+		case uint:
+			return x.(uint) / y.(uint)
+		case uint8:
+			return x.(uint8) / y.(uint8)
+		case uint16:
+			return x.(uint16) / y.(uint16)
+		case uint32:
+			return x.(uint32) / y.(uint32)
+		case uint64:
+			return x.(uint64) / y.(uint64)
+		case uintptr:
+			return x.(uintptr) / y.(uintptr)
+		case float32:
+			return x.(float32) / y.(float32)
+		case float64:
+			return x.(float64) / y.(float64)
+		case complex64:
+			return x.(complex64) / y.(complex64)
+		case complex128:
+			return x.(complex128) / y.(complex128)
+		}
+
+	case token.REM:
+		switch x.(type) {
+		case int:
+			return x.(int) % y.(int)
+		case int8:
+			return x.(int8) % y.(int8)
+		case int16:
+			return x.(int16) % y.(int16)
+		case int32:
+			return x.(int32) % y.(int32)
+		case int64:
+			return x.(int64) % y.(int64)
+		case uint:
+			return x.(uint) % y.(uint)
+		case uint8:
+			return x.(uint8) % y.(uint8)
+		case uint16:
+			return x.(uint16) % y.(uint16)
+		case uint32:
+			return x.(uint32) % y.(uint32)
+		case uint64:
+			return x.(uint64) % y.(uint64)
+		case uintptr:
+			return x.(uintptr) % y.(uintptr)
+		}
+
+	case token.AND:
+		switch x.(type) {
+		case int:
+			return x.(int) & y.(int)
+		case int8:
+			return x.(int8) & y.(int8)
+		case int16:
+			return x.(int16) & y.(int16)
+		case int32:
+			return x.(int32) & y.(int32)
+		case int64:
+			return x.(int64) & y.(int64)
+		case uint:
+			return x.(uint) & y.(uint)
+		case uint8:
+			return x.(uint8) & y.(uint8)
+		case uint16:
+			return x.(uint16) & y.(uint16)
+		case uint32:
+			return x.(uint32) & y.(uint32)
+		case uint64:
+			return x.(uint64) & y.(uint64)
+		case uintptr:
+			return x.(uintptr) & y.(uintptr)
+		}
+
+	case token.OR:
+		switch x.(type) {
+		case int:
+			return x.(int) | y.(int)
+		case int8:
+			return x.(int8) | y.(int8)
+		case int16:
+			return x.(int16) | y.(int16)
+		case int32:
+			return x.(int32) | y.(int32)
+		case int64:
+			return x.(int64) | y.(int64)
+		case uint:
+			return x.(uint) | y.(uint)
+		case uint8:
+			return x.(uint8) | y.(uint8)
+		case uint16:
+			return x.(uint16) | y.(uint16)
+		case uint32:
+			return x.(uint32) | y.(uint32)
+		case uint64:
+			return x.(uint64) | y.(uint64)
+		case uintptr:
+			return x.(uintptr) | y.(uintptr)
+		}
+
+	case token.XOR:
+		switch x.(type) {
+		case int:
+			return x.(int) ^ y.(int)
+		case int8:
+			return x.(int8) ^ y.(int8)
+		case int16:
+			return x.(int16) ^ y.(int16)
+		case int32:
+			return x.(int32) ^ y.(int32)
+		case int64:
+			return x.(int64) ^ y.(int64)
+		case uint:
+			return x.(uint) ^ y.(uint)
+		case uint8:
+			return x.(uint8) ^ y.(uint8)
+		case uint16:
+			return x.(uint16) ^ y.(uint16)
+		case uint32:
+			return x.(uint32) ^ y.(uint32)
+		case uint64:
+			return x.(uint64) ^ y.(uint64)
+		case uintptr:
+			return x.(uintptr) ^ y.(uintptr)
+		}
+
+	case token.AND_NOT:
+		switch x.(type) {
+		case int:
+			return x.(int) &^ y.(int)
+		case int8:
+			return x.(int8) &^ y.(int8)
+		case int16:
+			return x.(int16) &^ y.(int16)
+		case int32:
+			return x.(int32) &^ y.(int32)
+		case int64:
+			return x.(int64) &^ y.(int64)
+		case uint:
+			return x.(uint) &^ y.(uint)
+		case uint8:
+			return x.(uint8) &^ y.(uint8)
+		case uint16:
+			return x.(uint16) &^ y.(uint16)
+		case uint32:
+			return x.(uint32) &^ y.(uint32)
+		case uint64:
+			return x.(uint64) &^ y.(uint64)
+		case uintptr:
+			return x.(uintptr) &^ y.(uintptr)
+		}
+
+	case token.SHL:
+		y := asUint64(y)
+		switch x.(type) {
+		case int:
+			return x.(int) << y
+		case int8:
+			return x.(int8) << y
+		case int16:
+			return x.(int16) << y
+		case int32:
+			return x.(int32) << y
+		case int64:
+			return x.(int64) << y
+		case uint:
+			return x.(uint) << y
+		case uint8:
+			return x.(uint8) << y
+		case uint16:
+			return x.(uint16) << y
+		case uint32:
+			return x.(uint32) << y
+		case uint64:
+			return x.(uint64) << y
+		case uintptr:
+			return x.(uintptr) << y
+		}
+
+	case token.SHR:
+		y := asUint64(y)
+		switch x.(type) {
+		case int:
+			return x.(int) >> y
+		case int8:
+			return x.(int8) >> y
+		case int16:
+			return x.(int16) >> y
+		case int32:
+			return x.(int32) >> y
+		case int64:
+			return x.(int64) >> y
+		case uint:
+			return x.(uint) >> y
+		case uint8:
+			return x.(uint8) >> y
+		case uint16:
+			return x.(uint16) >> y
+		case uint32:
+			return x.(uint32) >> y
+		case uint64:
+			return x.(uint64) >> y
+		case uintptr:
+			return x.(uintptr) >> y
+		}
+
+	case token.LSS:
+		switch x.(type) {
+		case int:
+			return x.(int) < y.(int)
+		case int8:
+			return x.(int8) < y.(int8)
+		case int16:
+			return x.(int16) < y.(int16)
+		case int32:
+			return x.(int32) < y.(int32)
+		case int64:
+			return x.(int64) < y.(int64)
+		case uint:
+			return x.(uint) < y.(uint)
+		case uint8:
+			return x.(uint8) < y.(uint8)
+		case uint16:
+			return x.(uint16) < y.(uint16)
+		case uint32:
+			return x.(uint32) < y.(uint32)
+		case uint64:
+			return x.(uint64) < y.(uint64)
+		case uintptr:
+			return x.(uintptr) < y.(uintptr)
+		case float32:
+			return x.(float32) < y.(float32)
+		case float64:
+			return x.(float64) < y.(float64)
+		case string:
+			return x.(string) < y.(string)
+		}
+
+	case token.LEQ:
+		switch x.(type) {
+		case int:
+			return x.(int) <= y.(int)
+		case int8:
+			return x.(int8) <= y.(int8)
+		case int16:
+			return x.(int16) <= y.(int16)
+		case int32:
+			return x.(int32) <= y.(int32)
+		case int64:
+			return x.(int64) <= y.(int64)
+		case uint:
+			return x.(uint) <= y.(uint)
+		case uint8:
+			return x.(uint8) <= y.(uint8)
+		case uint16:
+			return x.(uint16) <= y.(uint16)
+		case uint32:
+			return x.(uint32) <= y.(uint32)
+		case uint64:
+			return x.(uint64) <= y.(uint64)
+		case uintptr:
+			return x.(uintptr) <= y.(uintptr)
+		case float32:
+			return x.(float32) <= y.(float32)
+		case float64:
+			return x.(float64) <= y.(float64)
+		case string:
+			return x.(string) <= y.(string)
+		}
+
+	case token.EQL:
+		return eqnil(t, x, y)
+
+	case token.NEQ:
+		return !eqnil(t, x, y)
+
+	case token.GTR:
+		switch x.(type) {
+		case int:
+			return x.(int) > y.(int)
+		case int8:
+			return x.(int8) > y.(int8)
+		case int16:
+			return x.(int16) > y.(int16)
+		case int32:
+			return x.(int32) > y.(int32)
+		case int64:
+			return x.(int64) > y.(int64)
+		case uint:
+			return x.(uint) > y.(uint)
+		case uint8:
+			return x.(uint8) > y.(uint8)
+		case uint16:
+			return x.(uint16) > y.(uint16)
+		case uint32:
+			return x.(uint32) > y.(uint32)
+		case uint64:
+			return x.(uint64) > y.(uint64)
+		case uintptr:
+			return x.(uintptr) > y.(uintptr)
+		case float32:
+			return x.(float32) > y.(float32)
+		case float64:
+			return x.(float64) > y.(float64)
+		case string:
+			return x.(string) > y.(string)
+		}
+
+	case token.GEQ:
+		switch x.(type) {
+		case int:
+			return x.(int) >= y.(int)
+		case int8:
+			return x.(int8) >= y.(int8)
+		case int16:
+			return x.(int16) >= y.(int16)
+		case int32:
+			return x.(int32) >= y.(int32)
+		case int64:
+			return x.(int64) >= y.(int64)
+		case uint:
+			return x.(uint) >= y.(uint)
+		case uint8:
+			return x.(uint8) >= y.(uint8)
+		case uint16:
+			return x.(uint16) >= y.(uint16)
+		case uint32:
+			return x.(uint32) >= y.(uint32)
+		case uint64:
+			return x.(uint64) >= y.(uint64)
+		case uintptr:
+			return x.(uintptr) >= y.(uintptr)
+		case float32:
+			return x.(float32) >= y.(float32)
+		case float64:
+			return x.(float64) >= y.(float64)
+		case string:
+			return x.(string) >= y.(string)
+		}
+	}
+	panic(fmt.Sprintf("invalid binary op: %T %s %T", x, op, y))
+}
+
+// eqnil returns the comparison x == y using the equivalence relation
+// appropriate for type t.
+// If t is a reference type, at most one of x or y may be a nil value
+// of that type.
+//
+func eqnil(t types.Type, x, y value) bool {
+	switch t.Underlying().(type) {
+	case *types.Map, *types.Signature, *types.Slice:
+		// Since these types don't support comparison,
+		// one of the operands must be a literal nil.
+		switch x := x.(type) {
+		case *hashmap:
+			return (x != nil) == (y.(*hashmap) != nil)
+		case map[value]value:
+			return (x != nil) == (y.(map[value]value) != nil)
+		case *ssa.Function:
+			switch y := y.(type) {
+			case *ssa.Function:
+				return (x != nil) == (y != nil)
+			case *closure:
+				return true
+			}
+		case *closure:
+			return (x != nil) == (y.(*ssa.Function) != nil)
+		case []value:
+			return (x != nil) == (y.([]value) != nil)
+		}
+		panic(fmt.Sprintf("eqnil(%s): illegal dynamic type: %T", t, x))
+	}
+
+	return equals(t, x, y)
+}
+
+func unop(instr *ssa.UnOp, x value) value {
+	switch instr.Op {
+	case token.ARROW: // receive
+		v, ok := <-x.(chan value)
+		if !ok {
+			v = zero(instr.X.Type().Underlying().(*types.Chan).Elem())
+		}
+		if instr.CommaOk {
+			v = tuple{v, ok}
+		}
+		return v
+	case token.SUB:
+		switch x := x.(type) {
+		case int:
+			return -x
+		case int8:
+			return -x
+		case int16:
+			return -x
+		case int32:
+			return -x
+		case int64:
+			return -x
+		case uint:
+			return -x
+		case uint8:
+			return -x
+		case uint16:
+			return -x
+		case uint32:
+			return -x
+		case uint64:
+			return -x
+		case uintptr:
+			return -x
+		case float32:
+			return -x
+		case float64:
+			return -x
+		case complex64:
+			return -x
+		case complex128:
+			return -x
+		}
+	case token.MUL:
+		return load(deref(instr.X.Type()), x.(*value))
+	case token.NOT:
+		return !x.(bool)
+	case token.XOR:
+		switch x := x.(type) {
+		case int:
+			return ^x
+		case int8:
+			return ^x
+		case int16:
+			return ^x
+		case int32:
+			return ^x
+		case int64:
+			return ^x
+		case uint:
+			return ^x
+		case uint8:
+			return ^x
+		case uint16:
+			return ^x
+		case uint32:
+			return ^x
+		case uint64:
+			return ^x
+		case uintptr:
+			return ^x
+		}
+	}
+	panic(fmt.Sprintf("invalid unary op %s %T", instr.Op, x))
+}
+
+// typeAssert checks whether dynamic type of itf is instr.AssertedType.
+// It returns the extracted value on success, and panics on failure,
+// unless instr.CommaOk, in which case it always returns a "value,ok" tuple.
+//
+func typeAssert(i *interpreter, instr *ssa.TypeAssert, itf iface) value {
+	var v value
+	err := ""
+	if itf.t == nil {
+		err = fmt.Sprintf("interface conversion: interface is nil, not %s", instr.AssertedType)
+
+	} else if idst, ok := instr.AssertedType.Underlying().(*types.Interface); ok {
+		v = itf
+		err = checkInterface(i, idst, itf)
+
+	} else if types.Identical(itf.t, instr.AssertedType) {
+		v = itf.v // extract value
+
+	} else {
+		err = fmt.Sprintf("interface conversion: interface is %s, not %s", itf.t, instr.AssertedType)
+	}
+
+	if err != "" {
+		if !instr.CommaOk {
+			panic(err)
+		}
+		return tuple{zero(instr.AssertedType), false}
+	}
+	if instr.CommaOk {
+		return tuple{v, true}
+	}
+	return v
+}
+
+// If CapturedOutput is non-nil, all writes by the interpreted program
+// to file descriptors 1 and 2 will also be written to CapturedOutput.
+//
+// (The $GOROOT/test system requires that the test be considered a
+// failure if "BUG" appears in the combined stdout/stderr output, even
+// if it exits zero.  This is a global variable shared by all
+// interpreters in the same process.)
+//
+var CapturedOutput *bytes.Buffer
+var capturedOutputMu sync.Mutex
+
+// write writes bytes b to the target program's file descriptor fd.
+// The print/println built-ins and the write() system call funnel
+// through here so they can be captured by the test driver.
+func write(fd int, b []byte) (int, error) {
+	// TODO(adonovan): fix: on Windows, std{out,err} are not 1, 2.
+	if CapturedOutput != nil && (fd == 1 || fd == 2) {
+		capturedOutputMu.Lock()
+		CapturedOutput.Write(b) // ignore errors
+		capturedOutputMu.Unlock()
+	}
+	return syswrite(fd, b)
+}
+
+// callBuiltin interprets a call to builtin fn with arguments args,
+// returning its result.
+func callBuiltin(caller *frame, callpos token.Pos, fn *ssa.Builtin, args []value) value {
+	switch fn.Name() {
+	case "append":
+		if len(args) == 1 {
+			return args[0]
+		}
+		if s, ok := args[1].(string); ok {
+			// append([]byte, ...string) []byte
+			arg0 := args[0].([]value)
+			for i := 0; i < len(s); i++ {
+				arg0 = append(arg0, s[i])
+			}
+			return arg0
+		}
+		// append([]T, ...[]T) []T
+		return append(args[0].([]value), args[1].([]value)...)
+
+	case "copy": // copy([]T, []T) int or copy([]byte, string) int
+		src := args[1]
+		if _, ok := src.(string); ok {
+			params := fn.Type().(*types.Signature).Params()
+			src = conv(params.At(0).Type(), params.At(1).Type(), src)
+		}
+		return copy(args[0].([]value), src.([]value))
+
+	case "close": // close(chan T)
+		close(args[0].(chan value))
+		return nil
+
+	case "delete": // delete(map[K]value, K)
+		switch m := args[0].(type) {
+		case map[value]value:
+			delete(m, args[1])
+		case *hashmap:
+			m.delete(args[1].(hashable))
+		default:
+			panic(fmt.Sprintf("illegal map type: %T", m))
+		}
+		return nil
+
+	case "print", "println": // print(any, ...)
+		ln := fn.Name() == "println"
+		var buf bytes.Buffer
+		for i, arg := range args {
+			if i > 0 && ln {
+				buf.WriteRune(' ')
+			}
+			buf.WriteString(toString(arg))
+		}
+		if ln {
+			buf.WriteRune('\n')
+		}
+		write(1, buf.Bytes())
+		return nil
+
+	case "len":
+		switch x := args[0].(type) {
+		case string:
+			return len(x)
+		case array:
+			return len(x)
+		case *value:
+			return len((*x).(array))
+		case []value:
+			return len(x)
+		case map[value]value:
+			return len(x)
+		case *hashmap:
+			return x.len()
+		case chan value:
+			return len(x)
+		default:
+			panic(fmt.Sprintf("len: illegal operand: %T", x))
+		}
+
+	case "cap":
+		switch x := args[0].(type) {
+		case array:
+			return cap(x)
+		case *value:
+			return cap((*x).(array))
+		case []value:
+			return cap(x)
+		case chan value:
+			return cap(x)
+		default:
+			panic(fmt.Sprintf("cap: illegal operand: %T", x))
+		}
+
+	case "real":
+		switch c := args[0].(type) {
+		case complex64:
+			return real(c)
+		case complex128:
+			return real(c)
+		default:
+			panic(fmt.Sprintf("real: illegal operand: %T", c))
+		}
+
+	case "imag":
+		switch c := args[0].(type) {
+		case complex64:
+			return imag(c)
+		case complex128:
+			return imag(c)
+		default:
+			panic(fmt.Sprintf("imag: illegal operand: %T", c))
+		}
+
+	case "complex":
+		switch f := args[0].(type) {
+		case float32:
+			return complex(f, args[1].(float32))
+		case float64:
+			return complex(f, args[1].(float64))
+		default:
+			panic(fmt.Sprintf("complex: illegal operand: %T", f))
+		}
+
+	case "panic":
+		// ssa.Panic handles most cases; this is only for "go
+		// panic" or "defer panic".
+		panic(targetPanic{args[0]})
+
+	case "recover":
+		return doRecover(caller)
+
+	case "ssa:wrapnilchk":
+		recv := args[0]
+		if recv.(*value) == nil {
+			recvType := args[1]
+			methodName := args[2]
+			panic(fmt.Sprintf("value method (%s).%s called using nil *%s pointer",
+				recvType, methodName, recvType))
+		}
+		return recv
+	}
+
+	panic("unknown built-in: " + fn.Name())
+}
+
+func rangeIter(x value, t types.Type) iter {
+	switch x := x.(type) {
+	case map[value]value:
+		// TODO(adonovan): fix: leaks goroutines and channels
+		// on each incomplete map iteration.  We need to open
+		// up an iteration interface using the
+		// reflect.(Value).MapKeys machinery.
+		it := make(mapIter)
+		go func() {
+			for k, v := range x {
+				it <- [2]value{k, v}
+			}
+			close(it)
+		}()
+		return it
+	case *hashmap:
+		// TODO(adonovan): fix: leaks goroutines and channels
+		// on each incomplete map iteration.  We need to open
+		// up an iteration interface using the
+		// reflect.(Value).MapKeys machinery.
+		it := make(mapIter)
+		go func() {
+			for _, e := range x.table {
+				for e != nil {
+					it <- [2]value{e.key, e.value}
+					e = e.next
+				}
+			}
+			close(it)
+		}()
+		return it
+	case string:
+		return &stringIter{Reader: strings.NewReader(x)}
+	}
+	panic(fmt.Sprintf("cannot range over %T", x))
+}
+
+// widen widens a basic typed value x to the widest type of its
+// category, one of:
+//   bool, int64, uint64, float64, complex128, string.
+// This is inefficient but reduces the size of the cross-product of
+// cases we have to consider.
+//
+func widen(x value) value {
+	switch y := x.(type) {
+	case bool, int64, uint64, float64, complex128, string, unsafe.Pointer:
+		return x
+	case int:
+		return int64(y)
+	case int8:
+		return int64(y)
+	case int16:
+		return int64(y)
+	case int32:
+		return int64(y)
+	case uint:
+		return uint64(y)
+	case uint8:
+		return uint64(y)
+	case uint16:
+		return uint64(y)
+	case uint32:
+		return uint64(y)
+	case uintptr:
+		return uint64(y)
+	case float32:
+		return float64(y)
+	case complex64:
+		return complex128(y)
+	}
+	panic(fmt.Sprintf("cannot widen %T", x))
+}
+
+// conv converts the value x of type t_src to type t_dst and returns
+// the result.
+// Possible cases are described with the ssa.Convert operator.
+//
+func conv(t_dst, t_src types.Type, x value) value {
+	ut_src := t_src.Underlying()
+	ut_dst := t_dst.Underlying()
+
+	// Destination type is not an "untyped" type.
+	if b, ok := ut_dst.(*types.Basic); ok && b.Info()&types.IsUntyped != 0 {
+		panic("oops: conversion to 'untyped' type: " + b.String())
+	}
+
+	// Nor is it an interface type.
+	if _, ok := ut_dst.(*types.Interface); ok {
+		if _, ok := ut_src.(*types.Interface); ok {
+			panic("oops: Convert should be ChangeInterface")
+		} else {
+			panic("oops: Convert should be MakeInterface")
+		}
+	}
+
+	// Remaining conversions:
+	//    + untyped string/number/bool constant to a specific
+	//      representation.
+	//    + conversions between non-complex numeric types.
+	//    + conversions between complex numeric types.
+	//    + integer/[]byte/[]rune -> string.
+	//    + string -> []byte/[]rune.
+	//
+	// All are treated the same: first we extract the value to the
+	// widest representation (int64, uint64, float64, complex128,
+	// or string), then we convert it to the desired type.
+
+	switch ut_src := ut_src.(type) {
+	case *types.Pointer:
+		switch ut_dst := ut_dst.(type) {
+		case *types.Basic:
+			// *value to unsafe.Pointer?
+			if ut_dst.Kind() == types.UnsafePointer {
+				return unsafe.Pointer(x.(*value))
+			}
+		}
+
+	case *types.Slice:
+		// []byte or []rune -> string
+		// TODO(adonovan): fix: type B byte; conv([]B -> string).
+		switch ut_src.Elem().(*types.Basic).Kind() {
+		case types.Byte:
+			x := x.([]value)
+			b := make([]byte, 0, len(x))
+			for i := range x {
+				b = append(b, x[i].(byte))
+			}
+			return string(b)
+
+		case types.Rune:
+			x := x.([]value)
+			r := make([]rune, 0, len(x))
+			for i := range x {
+				r = append(r, x[i].(rune))
+			}
+			return string(r)
+		}
+
+	case *types.Basic:
+		x = widen(x)
+
+		// integer -> string?
+		// TODO(adonovan): fix: test integer -> named alias of string.
+		if ut_src.Info()&types.IsInteger != 0 {
+			if ut_dst, ok := ut_dst.(*types.Basic); ok && ut_dst.Kind() == types.String {
+				return string(asInt(x))
+			}
+		}
+
+		// string -> []rune, []byte or string?
+		if s, ok := x.(string); ok {
+			switch ut_dst := ut_dst.(type) {
+			case *types.Slice:
+				var res []value
+				// TODO(adonovan): fix: test named alias of rune, byte.
+				switch ut_dst.Elem().(*types.Basic).Kind() {
+				case types.Rune:
+					for _, r := range []rune(s) {
+						res = append(res, r)
+					}
+					return res
+				case types.Byte:
+					for _, b := range []byte(s) {
+						res = append(res, b)
+					}
+					return res
+				}
+			case *types.Basic:
+				if ut_dst.Kind() == types.String {
+					return x.(string)
+				}
+			}
+			break // fail: no other conversions for string
+		}
+
+		// unsafe.Pointer -> *value
+		if ut_src.Kind() == types.UnsafePointer {
+			// TODO(adonovan): this is wrong and cannot
+			// really be fixed with the current design.
+			//
+			// return (*value)(x.(unsafe.Pointer))
+			// creates a new pointer of a different
+			// type but the underlying interface value
+			// knows its "true" type and so cannot be
+			// meaningfully used through the new pointer.
+			//
+			// To make this work, the interpreter needs to
+			// simulate the memory layout of a real
+			// compiled implementation.
+			//
+			// To at least preserve type-safety, we'll
+			// just return the zero value of the
+			// destination type.
+			return zero(t_dst)
+		}
+
+		// Conversions between complex numeric types?
+		if ut_src.Info()&types.IsComplex != 0 {
+			switch ut_dst.(*types.Basic).Kind() {
+			case types.Complex64:
+				return complex64(x.(complex128))
+			case types.Complex128:
+				return x.(complex128)
+			}
+			break // fail: no other conversions for complex
+		}
+
+		// Conversions between non-complex numeric types?
+		if ut_src.Info()&types.IsNumeric != 0 {
+			kind := ut_dst.(*types.Basic).Kind()
+			switch x := x.(type) {
+			case int64: // signed integer -> numeric?
+				switch kind {
+				case types.Int:
+					return int(x)
+				case types.Int8:
+					return int8(x)
+				case types.Int16:
+					return int16(x)
+				case types.Int32:
+					return int32(x)
+				case types.Int64:
+					return int64(x)
+				case types.Uint:
+					return uint(x)
+				case types.Uint8:
+					return uint8(x)
+				case types.Uint16:
+					return uint16(x)
+				case types.Uint32:
+					return uint32(x)
+				case types.Uint64:
+					return uint64(x)
+				case types.Uintptr:
+					return uintptr(x)
+				case types.Float32:
+					return float32(x)
+				case types.Float64:
+					return float64(x)
+				}
+
+			case uint64: // unsigned integer -> numeric?
+				switch kind {
+				case types.Int:
+					return int(x)
+				case types.Int8:
+					return int8(x)
+				case types.Int16:
+					return int16(x)
+				case types.Int32:
+					return int32(x)
+				case types.Int64:
+					return int64(x)
+				case types.Uint:
+					return uint(x)
+				case types.Uint8:
+					return uint8(x)
+				case types.Uint16:
+					return uint16(x)
+				case types.Uint32:
+					return uint32(x)
+				case types.Uint64:
+					return uint64(x)
+				case types.Uintptr:
+					return uintptr(x)
+				case types.Float32:
+					return float32(x)
+				case types.Float64:
+					return float64(x)
+				}
+
+			case float64: // floating point -> numeric?
+				switch kind {
+				case types.Int:
+					return int(x)
+				case types.Int8:
+					return int8(x)
+				case types.Int16:
+					return int16(x)
+				case types.Int32:
+					return int32(x)
+				case types.Int64:
+					return int64(x)
+				case types.Uint:
+					return uint(x)
+				case types.Uint8:
+					return uint8(x)
+				case types.Uint16:
+					return uint16(x)
+				case types.Uint32:
+					return uint32(x)
+				case types.Uint64:
+					return uint64(x)
+				case types.Uintptr:
+					return uintptr(x)
+				case types.Float32:
+					return float32(x)
+				case types.Float64:
+					return float64(x)
+				}
+			}
+		}
+	}
+
+	panic(fmt.Sprintf("unsupported conversion: %s  -> %s, dynamic type %T", t_src, t_dst, x))
+}
+
+// checkInterface checks that the method set of x implements the
+// interface itype.
+// On success it returns "", on failure, an error message.
+//
+func checkInterface(i *interpreter, itype *types.Interface, x iface) string {
+	if meth, _ := types.MissingMethod(x.t, itype, true); meth != nil {
+		return fmt.Sprintf("interface conversion: %v is not %v: missing method %s",
+			x.t, itype, meth.Name())
+	}
+	return "" // ok
+}
diff --git a/go/ssa/interp/reflect.go b/go/ssa/interp/reflect.go
new file mode 100644
index 0000000..468771b
--- /dev/null
+++ b/go/ssa/interp/reflect.go
@@ -0,0 +1,574 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package interp
+
+// Emulated "reflect" package.
+//
+// We completely replace the built-in "reflect" package.
+// The only thing clients can depend upon are that reflect.Type is an
+// interface and reflect.Value is an (opaque) struct.
+
+import (
+	"fmt"
+	"go/token"
+	"reflect"
+	"unsafe"
+
+	"golang.org/x/tools/go/ssa"
+	"golang.org/x/tools/go/types"
+)
+
+type opaqueType struct {
+	types.Type
+	name string
+}
+
+func (t *opaqueType) String() string { return t.name }
+
+// A bogus "reflect" type-checker package.  Shared across interpreters.
+var reflectTypesPackage = types.NewPackage("reflect", "reflect")
+
+// rtype is the concrete type the interpreter uses to implement the
+// reflect.Type interface.
+//
+// type rtype <opaque>
+var rtypeType = makeNamedType("rtype", &opaqueType{nil, "rtype"})
+
+// error is an (interpreted) named type whose underlying type is string.
+// The interpreter uses it for all implementations of the built-in error
+// interface that it creates.
+// We put it in the "reflect" package for expedience.
+//
+// type error string
+var errorType = makeNamedType("error", &opaqueType{nil, "error"})
+
+func makeNamedType(name string, underlying types.Type) *types.Named {
+	obj := types.NewTypeName(token.NoPos, reflectTypesPackage, name, nil)
+	return types.NewNamed(obj, underlying, nil)
+}
+
+func makeReflectValue(t types.Type, v value) value {
+	return structure{rtype{t}, v}
+}
+
+// Given a reflect.Value, returns its rtype.
+func rV2T(v value) rtype {
+	return v.(structure)[0].(rtype)
+}
+
+// Given a reflect.Value, returns the underlying interpreter value.
+func rV2V(v value) value {
+	return v.(structure)[1]
+}
+
+// makeReflectType boxes up an rtype in a reflect.Type interface.
+func makeReflectType(rt rtype) value {
+	return iface{rtypeType, rt}
+}
+
+func ext۰reflect۰Init(fr *frame, args []value) value {
+	// Signature: func()
+	return nil
+}
+
+func ext۰reflect۰rtype۰Bits(fr *frame, args []value) value {
+	// Signature: func (t reflect.rtype) int
+	rt := args[0].(rtype).t
+	basic, ok := rt.Underlying().(*types.Basic)
+	if !ok {
+		panic(fmt.Sprintf("reflect.Type.Bits(%T): non-basic type", rt))
+	}
+	return int(fr.i.sizes.Sizeof(basic)) * 8
+}
+
+func ext۰reflect۰rtype۰Elem(fr *frame, args []value) value {
+	// Signature: func (t reflect.rtype) reflect.Type
+	return makeReflectType(rtype{args[0].(rtype).t.Underlying().(interface {
+		Elem() types.Type
+	}).Elem()})
+}
+
+func ext۰reflect۰rtype۰Field(fr *frame, args []value) value {
+	// Signature: func (t reflect.rtype, i int) reflect.StructField
+	st := args[0].(rtype).t.Underlying().(*types.Struct)
+	i := args[1].(int)
+	f := st.Field(i)
+	return structure{
+		f.Name(),
+		f.Pkg().Path(),
+		makeReflectType(rtype{f.Type()}),
+		st.Tag(i),
+		0,         // TODO(adonovan): offset
+		[]value{}, // TODO(adonovan): indices
+		f.Anonymous(),
+	}
+}
+
+func ext۰reflect۰rtype۰In(fr *frame, args []value) value {
+	// Signature: func (t reflect.rtype, i int) int
+	i := args[1].(int)
+	return makeReflectType(rtype{args[0].(rtype).t.(*types.Signature).Params().At(i).Type()})
+}
+
+func ext۰reflect۰rtype۰Kind(fr *frame, args []value) value {
+	// Signature: func (t reflect.rtype) uint
+	return uint(reflectKind(args[0].(rtype).t))
+}
+
+func ext۰reflect۰rtype۰NumField(fr *frame, args []value) value {
+	// Signature: func (t reflect.rtype) int
+	return args[0].(rtype).t.Underlying().(*types.Struct).NumFields()
+}
+
+func ext۰reflect۰rtype۰NumIn(fr *frame, args []value) value {
+	// Signature: func (t reflect.rtype) int
+	return args[0].(rtype).t.(*types.Signature).Params().Len()
+}
+
+func ext۰reflect۰rtype۰NumMethod(fr *frame, args []value) value {
+	// Signature: func (t reflect.rtype) int
+	return fr.i.prog.MethodSets.MethodSet(args[0].(rtype).t).Len()
+}
+
+func ext۰reflect۰rtype۰NumOut(fr *frame, args []value) value {
+	// Signature: func (t reflect.rtype) int
+	return args[0].(rtype).t.(*types.Signature).Results().Len()
+}
+
+func ext۰reflect۰rtype۰Out(fr *frame, args []value) value {
+	// Signature: func (t reflect.rtype, i int) int
+	i := args[1].(int)
+	return makeReflectType(rtype{args[0].(rtype).t.(*types.Signature).Results().At(i).Type()})
+}
+
+func ext۰reflect۰rtype۰Size(fr *frame, args []value) value {
+	// Signature: func (t reflect.rtype) uintptr
+	return uintptr(fr.i.sizes.Sizeof(args[0].(rtype).t))
+}
+
+func ext۰reflect۰rtype۰String(fr *frame, args []value) value {
+	// Signature: func (t reflect.rtype) string
+	return args[0].(rtype).t.String()
+}
+
+func ext۰reflect۰New(fr *frame, args []value) value {
+	// Signature: func (t reflect.Type) reflect.Value
+	t := args[0].(iface).v.(rtype).t
+	alloc := zero(t)
+	return makeReflectValue(types.NewPointer(t), &alloc)
+}
+
+func ext۰reflect۰SliceOf(fr *frame, args []value) value {
+	// Signature: func (t reflect.rtype) Type
+	return makeReflectType(rtype{types.NewSlice(args[0].(iface).v.(rtype).t)})
+}
+
+func ext۰reflect۰TypeOf(fr *frame, args []value) value {
+	// Signature: func (t reflect.rtype) Type
+	return makeReflectType(rtype{args[0].(iface).t})
+}
+
+func ext۰reflect۰ValueOf(fr *frame, args []value) value {
+	// Signature: func (interface{}) reflect.Value
+	itf := args[0].(iface)
+	return makeReflectValue(itf.t, itf.v)
+}
+
+func ext۰reflect۰Zero(fr *frame, args []value) value {
+	// Signature: func (t reflect.Type) reflect.Value
+	t := args[0].(iface).v.(rtype).t
+	return makeReflectValue(t, zero(t))
+}
+
+func reflectKind(t types.Type) reflect.Kind {
+	switch t := t.(type) {
+	case *types.Named:
+		return reflectKind(t.Underlying())
+	case *types.Basic:
+		switch t.Kind() {
+		case types.Bool:
+			return reflect.Bool
+		case types.Int:
+			return reflect.Int
+		case types.Int8:
+			return reflect.Int8
+		case types.Int16:
+			return reflect.Int16
+		case types.Int32:
+			return reflect.Int32
+		case types.Int64:
+			return reflect.Int64
+		case types.Uint:
+			return reflect.Uint
+		case types.Uint8:
+			return reflect.Uint8
+		case types.Uint16:
+			return reflect.Uint16
+		case types.Uint32:
+			return reflect.Uint32
+		case types.Uint64:
+			return reflect.Uint64
+		case types.Uintptr:
+			return reflect.Uintptr
+		case types.Float32:
+			return reflect.Float32
+		case types.Float64:
+			return reflect.Float64
+		case types.Complex64:
+			return reflect.Complex64
+		case types.Complex128:
+			return reflect.Complex128
+		case types.String:
+			return reflect.String
+		case types.UnsafePointer:
+			return reflect.UnsafePointer
+		}
+	case *types.Array:
+		return reflect.Array
+	case *types.Chan:
+		return reflect.Chan
+	case *types.Signature:
+		return reflect.Func
+	case *types.Interface:
+		return reflect.Interface
+	case *types.Map:
+		return reflect.Map
+	case *types.Pointer:
+		return reflect.Ptr
+	case *types.Slice:
+		return reflect.Slice
+	case *types.Struct:
+		return reflect.Struct
+	}
+	panic(fmt.Sprint("unexpected type: ", t))
+}
+
+func ext۰reflect۰Value۰Kind(fr *frame, args []value) value {
+	// Signature: func (reflect.Value) uint
+	return uint(reflectKind(rV2T(args[0]).t))
+}
+
+func ext۰reflect۰Value۰String(fr *frame, args []value) value {
+	// Signature: func (reflect.Value) string
+	return toString(rV2V(args[0]))
+}
+
+func ext۰reflect۰Value۰Type(fr *frame, args []value) value {
+	// Signature: func (reflect.Value) reflect.Type
+	return makeReflectType(rV2T(args[0]))
+}
+
+func ext۰reflect۰Value۰Uint(fr *frame, args []value) value {
+	// Signature: func (reflect.Value) uint64
+	switch v := rV2V(args[0]).(type) {
+	case uint:
+		return uint64(v)
+	case uint8:
+		return uint64(v)
+	case uint16:
+		return uint64(v)
+	case uint32:
+		return uint64(v)
+	case uint64:
+		return uint64(v)
+	case uintptr:
+		return uint64(v)
+	}
+	panic("reflect.Value.Uint")
+}
+
+func ext۰reflect۰Value۰Len(fr *frame, args []value) value {
+	// Signature: func (reflect.Value) int
+	switch v := rV2V(args[0]).(type) {
+	case string:
+		return len(v)
+	case array:
+		return len(v)
+	case chan value:
+		return cap(v)
+	case []value:
+		return len(v)
+	case *hashmap:
+		return v.len()
+	case map[value]value:
+		return len(v)
+	default:
+		panic(fmt.Sprintf("reflect.(Value).Len(%v)", v))
+	}
+}
+
+func ext۰reflect۰Value۰MapIndex(fr *frame, args []value) value {
+	// Signature: func (reflect.Value) Value
+	tValue := rV2T(args[0]).t.Underlying().(*types.Map).Key()
+	k := rV2V(args[1])
+	switch m := rV2V(args[0]).(type) {
+	case map[value]value:
+		if v, ok := m[k]; ok {
+			return makeReflectValue(tValue, v)
+		}
+
+	case *hashmap:
+		if v := m.lookup(k.(hashable)); v != nil {
+			return makeReflectValue(tValue, v)
+		}
+
+	default:
+		panic(fmt.Sprintf("(reflect.Value).MapIndex(%T, %T)", m, k))
+	}
+	return makeReflectValue(nil, nil)
+}
+
+func ext۰reflect۰Value۰MapKeys(fr *frame, args []value) value {
+	// Signature: func (reflect.Value) []Value
+	var keys []value
+	tKey := rV2T(args[0]).t.Underlying().(*types.Map).Key()
+	switch v := rV2V(args[0]).(type) {
+	case map[value]value:
+		for k := range v {
+			keys = append(keys, makeReflectValue(tKey, k))
+		}
+
+	case *hashmap:
+		for _, e := range v.table {
+			for ; e != nil; e = e.next {
+				keys = append(keys, makeReflectValue(tKey, e.key))
+			}
+		}
+
+	default:
+		panic(fmt.Sprintf("(reflect.Value).MapKeys(%T)", v))
+	}
+	return keys
+}
+
+func ext۰reflect۰Value۰NumField(fr *frame, args []value) value {
+	// Signature: func (reflect.Value) int
+	return len(rV2V(args[0]).(structure))
+}
+
+func ext۰reflect۰Value۰NumMethod(fr *frame, args []value) value {
+	// Signature: func (reflect.Value) int
+	return fr.i.prog.MethodSets.MethodSet(rV2T(args[0]).t).Len()
+}
+
+func ext۰reflect۰Value۰Pointer(fr *frame, args []value) value {
+	// Signature: func (v reflect.Value) uintptr
+	switch v := rV2V(args[0]).(type) {
+	case *value:
+		return uintptr(unsafe.Pointer(v))
+	case chan value:
+		return reflect.ValueOf(v).Pointer()
+	case []value:
+		return reflect.ValueOf(v).Pointer()
+	case *hashmap:
+		return reflect.ValueOf(v.table).Pointer()
+	case map[value]value:
+		return reflect.ValueOf(v).Pointer()
+	case *ssa.Function:
+		return uintptr(unsafe.Pointer(v))
+	case *closure:
+		return uintptr(unsafe.Pointer(v))
+	default:
+		panic(fmt.Sprintf("reflect.(Value).Pointer(%T)", v))
+	}
+}
+
+func ext۰reflect۰Value۰Index(fr *frame, args []value) value {
+	// Signature: func (v reflect.Value, i int) Value
+	i := args[1].(int)
+	t := rV2T(args[0]).t.Underlying()
+	switch v := rV2V(args[0]).(type) {
+	case array:
+		return makeReflectValue(t.(*types.Array).Elem(), v[i])
+	case []value:
+		return makeReflectValue(t.(*types.Slice).Elem(), v[i])
+	default:
+		panic(fmt.Sprintf("reflect.(Value).Index(%T)", v))
+	}
+}
+
+func ext۰reflect۰Value۰Bool(fr *frame, args []value) value {
+	// Signature: func (reflect.Value) bool
+	return rV2V(args[0]).(bool)
+}
+
+func ext۰reflect۰Value۰CanAddr(fr *frame, args []value) value {
+	// Signature: func (v reflect.Value) bool
+	// Always false for our representation.
+	return false
+}
+
+func ext۰reflect۰Value۰CanInterface(fr *frame, args []value) value {
+	// Signature: func (v reflect.Value) bool
+	// Always true for our representation.
+	return true
+}
+
+func ext۰reflect۰Value۰Elem(fr *frame, args []value) value {
+	// Signature: func (v reflect.Value) reflect.Value
+	switch x := rV2V(args[0]).(type) {
+	case iface:
+		return makeReflectValue(x.t, x.v)
+	case *value:
+		return makeReflectValue(rV2T(args[0]).t.Underlying().(*types.Pointer).Elem(), *x)
+	default:
+		panic(fmt.Sprintf("reflect.(Value).Elem(%T)", x))
+	}
+}
+
+func ext۰reflect۰Value۰Field(fr *frame, args []value) value {
+	// Signature: func (v reflect.Value, i int) reflect.Value
+	v := args[0]
+	i := args[1].(int)
+	return makeReflectValue(rV2T(v).t.Underlying().(*types.Struct).Field(i).Type(), rV2V(v).(structure)[i])
+}
+
+func ext۰reflect۰Value۰Float(fr *frame, args []value) value {
+	// Signature: func (reflect.Value) float64
+	switch v := rV2V(args[0]).(type) {
+	case float32:
+		return float64(v)
+	case float64:
+		return float64(v)
+	}
+	panic("reflect.Value.Float")
+}
+
+func ext۰reflect۰Value۰Interface(fr *frame, args []value) value {
+	// Signature: func (v reflect.Value) interface{}
+	return ext۰reflect۰valueInterface(fr, args)
+}
+
+func ext۰reflect۰Value۰Int(fr *frame, args []value) value {
+	// Signature: func (reflect.Value) int64
+	switch x := rV2V(args[0]).(type) {
+	case int:
+		return int64(x)
+	case int8:
+		return int64(x)
+	case int16:
+		return int64(x)
+	case int32:
+		return int64(x)
+	case int64:
+		return x
+	default:
+		panic(fmt.Sprintf("reflect.(Value).Int(%T)", x))
+	}
+}
+
+func ext۰reflect۰Value۰IsNil(fr *frame, args []value) value {
+	// Signature: func (reflect.Value) bool
+	switch x := rV2V(args[0]).(type) {
+	case *value:
+		return x == nil
+	case chan value:
+		return x == nil
+	case map[value]value:
+		return x == nil
+	case *hashmap:
+		return x == nil
+	case iface:
+		return x.t == nil
+	case []value:
+		return x == nil
+	case *ssa.Function:
+		return x == nil
+	case *ssa.Builtin:
+		return x == nil
+	case *closure:
+		return x == nil
+	default:
+		panic(fmt.Sprintf("reflect.(Value).IsNil(%T)", x))
+	}
+}
+
+func ext۰reflect۰Value۰IsValid(fr *frame, args []value) value {
+	// Signature: func (reflect.Value) bool
+	return rV2V(args[0]) != nil
+}
+
+func ext۰reflect۰Value۰Set(fr *frame, args []value) value {
+	// TODO(adonovan): implement.
+	return nil
+}
+
+func ext۰reflect۰valueInterface(fr *frame, args []value) value {
+	// Signature: func (v reflect.Value, safe bool) interface{}
+	v := args[0].(structure)
+	return iface{rV2T(v).t, rV2V(v)}
+}
+
+func ext۰reflect۰error۰Error(fr *frame, args []value) value {
+	return args[0]
+}
+
+// newMethod creates a new method of the specified name, package and receiver type.
+func newMethod(pkg *ssa.Package, recvType types.Type, name string) *ssa.Function {
+	// TODO(adonovan): fix: hack: currently the only part of Signature
+	// that is needed is the "pointerness" of Recv.Type, and for
+	// now, we'll set it to always be false since we're only
+	// concerned with rtype.  Encapsulate this better.
+	sig := types.NewSignature(types.NewVar(token.NoPos, nil, "recv", recvType), nil, nil, false)
+	fn := pkg.Prog.NewFunction(name, sig, "fake reflect method")
+	fn.Pkg = pkg
+	return fn
+}
+
+func initReflect(i *interpreter) {
+	i.reflectPackage = &ssa.Package{
+		Prog:    i.prog,
+		Object:  reflectTypesPackage,
+		Members: make(map[string]ssa.Member),
+	}
+
+	// Clobber the type-checker's notion of reflect.Value's
+	// underlying type so that it more closely matches the fake one
+	// (at least in the number of fields---we lie about the type of
+	// the rtype field).
+	//
+	// We must ensure that calls to (ssa.Value).Type() return the
+	// fake type so that correct "shape" is used when allocating
+	// variables, making zero values, loading, and storing.
+	//
+	// TODO(adonovan): obviously this is a hack.  We need a cleaner
+	// way to fake the reflect package (almost---DeepEqual is fine).
+	// One approach would be not to even load its source code, but
+	// provide fake source files.  This would guarantee that no bad
+	// information leaks into other packages.
+	if r := i.prog.ImportedPackage("reflect"); r != nil {
+		rV := r.Object.Scope().Lookup("Value").Type().(*types.Named)
+
+		// delete bodies of the old methods
+		mset := i.prog.MethodSets.MethodSet(rV)
+		for j := 0; j < mset.Len(); j++ {
+			i.prog.Method(mset.At(j)).Blocks = nil
+		}
+
+		tEface := types.NewInterface(nil, nil).Complete()
+		rV.SetUnderlying(types.NewStruct([]*types.Var{
+			types.NewField(token.NoPos, r.Object, "t", tEface, false), // a lie
+			types.NewField(token.NoPos, r.Object, "v", tEface, false),
+		}, nil))
+	}
+
+	i.rtypeMethods = methodSet{
+		"Bits":      newMethod(i.reflectPackage, rtypeType, "Bits"),
+		"Elem":      newMethod(i.reflectPackage, rtypeType, "Elem"),
+		"Field":     newMethod(i.reflectPackage, rtypeType, "Field"),
+		"In":        newMethod(i.reflectPackage, rtypeType, "In"),
+		"Kind":      newMethod(i.reflectPackage, rtypeType, "Kind"),
+		"NumField":  newMethod(i.reflectPackage, rtypeType, "NumField"),
+		"NumIn":     newMethod(i.reflectPackage, rtypeType, "NumIn"),
+		"NumMethod": newMethod(i.reflectPackage, rtypeType, "NumMethod"),
+		"NumOut":    newMethod(i.reflectPackage, rtypeType, "NumOut"),
+		"Out":       newMethod(i.reflectPackage, rtypeType, "Out"),
+		"Size":      newMethod(i.reflectPackage, rtypeType, "Size"),
+		"String":    newMethod(i.reflectPackage, rtypeType, "String"),
+	}
+	i.errorMethods = methodSet{
+		"Error": newMethod(i.reflectPackage, errorType, "Error"),
+	}
+}
diff --git a/go/ssa/interp/testdata/a_test.go b/go/ssa/interp/testdata/a_test.go
new file mode 100644
index 0000000..844ec5c
--- /dev/null
+++ b/go/ssa/interp/testdata/a_test.go
@@ -0,0 +1,17 @@
+package a
+
+import "testing"
+
+func TestFoo(t *testing.T) {
+	t.Error("foo")
+}
+
+func TestBar(t *testing.T) {
+	t.Error("bar")
+}
+
+func BenchmarkWiz(b *testing.B) {
+	b.Error("wiz")
+}
+
+// Don't test Examples since that testing package needs pipe(2) for that.
diff --git a/go/ssa/interp/testdata/b_test.go b/go/ssa/interp/testdata/b_test.go
new file mode 100644
index 0000000..4a30e96
--- /dev/null
+++ b/go/ssa/interp/testdata/b_test.go
@@ -0,0 +1,11 @@
+package b
+
+import "testing"
+
+func NotATest(t *testing.T) {
+	t.Error("foo")
+}
+
+func NotABenchmark(b *testing.B) {
+	b.Error("wiz")
+}
diff --git a/go/ssa/interp/testdata/boundmeth.go b/go/ssa/interp/testdata/boundmeth.go
new file mode 100644
index 0000000..255cc60
--- /dev/null
+++ b/go/ssa/interp/testdata/boundmeth.go
@@ -0,0 +1,144 @@
+// Tests of bound method closures.
+
+package main
+
+import "fmt"
+
+func assert(b bool) {
+	if !b {
+		panic("oops")
+	}
+}
+
+type I int
+
+func (i I) add(x int) int {
+	return int(i) + x
+}
+
+func valueReceiver() {
+	var three I = 3
+	assert(three.add(5) == 8)
+	var add3 func(int) int = three.add
+	assert(add3(5) == 8)
+}
+
+type S struct{ x int }
+
+func (s *S) incr() {
+	s.x++
+}
+
+func (s *S) get() int {
+	return s.x
+}
+
+func pointerReceiver() {
+	ps := new(S)
+	incr := ps.incr
+	get := ps.get
+	assert(get() == 0)
+	incr()
+	incr()
+	incr()
+	assert(get() == 3)
+}
+
+func addressibleValuePointerReceiver() {
+	var s S
+	incr := s.incr
+	get := s.get
+	assert(get() == 0)
+	incr()
+	incr()
+	incr()
+	assert(get() == 3)
+}
+
+type S2 struct {
+	S
+}
+
+func promotedReceiver() {
+	var s2 S2
+	incr := s2.incr
+	get := s2.get
+	assert(get() == 0)
+	incr()
+	incr()
+	incr()
+	assert(get() == 3)
+}
+
+func anonStruct() {
+	var s struct{ S }
+	incr := s.incr
+	get := s.get
+	assert(get() == 0)
+	incr()
+	incr()
+	incr()
+	assert(get() == 3)
+}
+
+func typeCheck() {
+	var i interface{}
+	i = (*S).incr
+	_ = i.(func(*S)) // type assertion: receiver type prepended to params
+
+	var s S
+	i = s.incr
+	_ = i.(func()) // type assertion: receiver type disappears
+}
+
+type errString string
+
+func (err errString) Error() string {
+	return string(err)
+}
+
+// Regression test for a builder crash.
+func regress1(x error) func() string {
+	return x.Error
+}
+
+// Regression test for b/7269:
+// taking the value of an interface method performs a nil check.
+func nilInterfaceMethodValue() {
+	err := fmt.Errorf("ok")
+	f := err.Error
+	if got := f(); got != "ok" {
+		panic(got)
+	}
+
+	err = nil
+	if got := f(); got != "ok" {
+		panic(got)
+	}
+
+	defer func() {
+		r := fmt.Sprint(recover())
+		// runtime panic string varies across toolchains
+		if r != "runtime error: interface conversion: interface is nil, not error" &&
+			r != "runtime error: invalid memory address or nil pointer dereference" {
+			panic("want runtime panic from nil interface method value, got " + r)
+		}
+	}()
+	f = err.Error // runtime panic: err is nil
+	panic("unreachable")
+}
+
+func main() {
+	valueReceiver()
+	pointerReceiver()
+	addressibleValuePointerReceiver()
+	promotedReceiver()
+	anonStruct()
+	typeCheck()
+
+	if e := regress1(errString("hi"))(); e != "hi" {
+		panic(e)
+	}
+
+	nilInterfaceMethodValue()
+}
diff --git a/go/ssa/interp/testdata/callstack.go b/go/ssa/interp/testdata/callstack.go
new file mode 100644
index 0000000..56f3b28
--- /dev/null
+++ b/go/ssa/interp/testdata/callstack.go
@@ -0,0 +1,52 @@
+package main
+
+import (
+	"fmt"
+	"path"
+	"runtime"
+	"strings"
+)
+
+var stack string
+
+func f() {
+	pc := make([]uintptr, 6)
+	pc = pc[:runtime.Callers(1, pc)]
+	for _, f := range pc {
+		Func := runtime.FuncForPC(f)
+		name := Func.Name()
+		if strings.Contains(name, "$") || strings.Contains(name, ".func") {
+			name = "func" // anon funcs vary across toolchains
+		}
+		file, line := Func.FileLine(0)
+		stack += fmt.Sprintf("%s at %s:%d\n", name, path.Base(file), line)
+	}
+}
+
+func g() { f() }
+func h() { g() }
+func i() { func() { h() }() }
+
+// Hack: the 'func' and the call to Caller are on the same line,
+// to paper over differences between toolchains.
+// (The interpreter's location info isn't yet complete.)
+func runtimeCaller0() (uintptr, string, int, bool) { return runtime.Caller(0) }
+
+func main() {
+	i()
+	if stack != `main.f at callstack.go:12
+main.g at callstack.go:26
+main.h at callstack.go:27
+func at callstack.go:28
+main.i at callstack.go:28
+main.main at callstack.go:35
+` {
+		panic("unexpected stack: " + stack)
+	}
+
+	pc, file, line, _ := runtimeCaller0()
+	got := fmt.Sprintf("%s @ %s:%d", runtime.FuncForPC(pc).Name(), path.Base(file), line)
+	if got != "main.runtimeCaller0 @ callstack.go:33" {
+		panic("runtime.Caller: " + got)
+	}
+}
diff --git a/go/ssa/interp/testdata/complit.go b/go/ssa/interp/testdata/complit.go
new file mode 100644
index 0000000..02f9916
--- /dev/null
+++ b/go/ssa/interp/testdata/complit.go
@@ -0,0 +1,168 @@
+package main
+
+// Tests of composite literals.
+
+import "fmt"
+
+// Map literals.
+func init() {
+	type M map[int]int
+	m1 := []*M{{1: 1}, &M{2: 2}}
+	want := "map[1:1] map[2:2]"
+	if got := fmt.Sprint(*m1[0], *m1[1]); got != want {
+		panic(got)
+	}
+	m2 := []M{{1: 1}, M{2: 2}}
+	if got := fmt.Sprint(m2[0], m2[1]); got != want {
+		panic(got)
+	}
+}
+
+// Nonliteral keys in composite literal.
+func init() {
+	const zero int = 1
+	var v = []int{1 + zero: 42}
+	if x := fmt.Sprint(v); x != "[0 0 42]" {
+		panic(x)
+	}
+}
+
+// Test for in-place initialization.
+func init() {
+	// struct
+	type S struct {
+		a, b int
+	}
+	s := S{1, 2}
+	s = S{b: 3}
+	if s.a != 0 {
+		panic("s.a != 0")
+	}
+	if s.b != 3 {
+		panic("s.b != 3")
+	}
+	s = S{}
+	if s.a != 0 {
+		panic("s.a != 0")
+	}
+	if s.b != 0 {
+		panic("s.b != 0")
+	}
+
+	// array
+	type A [4]int
+	a := A{2, 4, 6, 8}
+	a = A{1: 6, 2: 4}
+	if a[0] != 0 {
+		panic("a[0] != 0")
+	}
+	if a[1] != 6 {
+		panic("a[1] != 6")
+	}
+	if a[2] != 4 {
+		panic("a[2] != 4")
+	}
+	if a[3] != 0 {
+		panic("a[3] != 0")
+	}
+	a = A{}
+	if a[0] != 0 {
+		panic("a[0] != 0")
+	}
+	if a[1] != 0 {
+		panic("a[1] != 0")
+	}
+	if a[2] != 0 {
+		panic("a[2] != 0")
+	}
+	if a[3] != 0 {
+		panic("a[3] != 0")
+	}
+}
+
+// Regression test for https://github.com/golang/go/issues/10127:
+// composite literal clobbers destination before reading from it.
+func init() {
+	// map
+	{
+		type M map[string]int
+		m := M{"x": 1, "y": 2}
+		m = M{"x": m["y"], "y": m["x"]}
+		if m["x"] != 2 || m["y"] != 1 {
+			panic(fmt.Sprint(m))
+		}
+
+		n := M{"x": 3}
+		m, n = M{"x": n["x"]}, M{"x": m["x"]} // parallel assignment
+		if got := fmt.Sprint(m["x"], n["x"]); got != "3 2" {
+			panic(got)
+		}
+	}
+
+	// struct
+	{
+		type T struct{ x, y, z int }
+		t := T{x: 1, y: 2, z: 3}
+
+		t = T{x: t.y, y: t.z, z: t.x} // all fields
+		if got := fmt.Sprint(t); got != "{2 3 1}" {
+			panic(got)
+		}
+
+		t = T{x: t.y, y: t.z + 3} // not all fields
+		if got := fmt.Sprint(t); got != "{3 4 0}" {
+			panic(got)
+		}
+
+		u := T{x: 5, y: 6, z: 7}
+		t, u = T{x: u.x}, T{x: t.x} // parallel assignment
+		if got := fmt.Sprint(t, u); got != "{5 0 0} {3 0 0}" {
+			panic(got)
+		}
+	}
+
+	// array
+	{
+		a := [3]int{0: 1, 1: 2, 2: 3}
+
+		a = [3]int{0: a[1], 1: a[2], 2: a[0]} //  all elements
+		if got := fmt.Sprint(a); got != "[2 3 1]" {
+			panic(got)
+		}
+
+		a = [3]int{0: a[1], 1: a[2] + 3} //  not all elements
+		if got := fmt.Sprint(a); got != "[3 4 0]" {
+			panic(got)
+		}
+
+		b := [3]int{0: 5, 1: 6, 2: 7}
+		a, b = [3]int{0: b[0]}, [3]int{0: a[0]} // parallel assignment
+		if got := fmt.Sprint(a, b); got != "[5 0 0] [3 0 0]" {
+			panic(got)
+		}
+	}
+
+	// slice
+	{
+		s := []int{0: 1, 1: 2, 2: 3}
+
+		s = []int{0: s[1], 1: s[2], 2: s[0]} //  all elements
+		if got := fmt.Sprint(s); got != "[2 3 1]" {
+			panic(got)
+		}
+
+		s = []int{0: s[1], 1: s[2] + 3} //  not all elements
+		if got := fmt.Sprint(s); got != "[3 4]" {
+			panic(got)
+		}
+
+		t := []int{0: 5, 1: 6, 2: 7}
+		s, t = []int{0: t[0]}, []int{0: s[0]} // parallel assignment
+		if got := fmt.Sprint(s, t); got != "[5] [3]" {
+			panic(got)
+		}
+	}
+}
+
+func main() {
+}
diff --git a/go/ssa/interp/testdata/coverage.go b/go/ssa/interp/testdata/coverage.go
new file mode 100644
index 0000000..0bc0586
--- /dev/null
+++ b/go/ssa/interp/testdata/coverage.go
@@ -0,0 +1,534 @@
+// This interpreter test is designed to run very quickly yet provide
+// some coverage of a broad selection of constructs.
+//
+// Validate this file with 'go run' after editing.
+// TODO(adonovan): break this into small files organized by theme.
+
+package main
+
+import (
+	"fmt"
+	"reflect"
+)
+
+func init() {
+	// Call of variadic function with (implicit) empty slice.
+	if x := fmt.Sprint(); x != "" {
+		panic(x)
+	}
+}
+
+type empty interface{}
+
+type I interface {
+	f() int
+}
+
+type T struct{ z int }
+
+func (t T) f() int { return t.z }
+
+func use(interface{}) {}
+
+var counter = 2
+
+// Test initialization, including init blocks containing 'return'.
+// Assertion is in main.
+func init() {
+	counter *= 3
+	return
+	counter *= 3
+}
+
+func init() {
+	counter *= 5
+	return
+	counter *= 5
+}
+
+// Recursion.
+func fib(x int) int {
+	if x < 2 {
+		return x
+	}
+	return fib(x-1) + fib(x-2)
+}
+
+func fibgen(ch chan int) {
+	for x := 0; x < 10; x++ {
+		ch <- fib(x)
+	}
+	close(ch)
+}
+
+// Goroutines and channels.
+func init() {
+	ch := make(chan int)
+	go fibgen(ch)
+	var fibs []int
+	for v := range ch {
+		fibs = append(fibs, v)
+		if len(fibs) == 10 {
+			break
+		}
+	}
+	if x := fmt.Sprint(fibs); x != "[0 1 1 2 3 5 8 13 21 34]" {
+		panic(x)
+	}
+}
+
+// Test of aliasing.
+func init() {
+	type S struct {
+		a, b string
+	}
+
+	s1 := []string{"foo", "bar"}
+	s2 := s1 // creates an alias
+	s2[0] = "wiz"
+	if x := fmt.Sprint(s1, s2); x != "[wiz bar] [wiz bar]" {
+		panic(x)
+	}
+
+	pa1 := &[2]string{"foo", "bar"}
+	pa2 := pa1 // creates an alias
+	pa2[0] = "wiz"
+	if x := fmt.Sprint(*pa1, *pa2); x != "[wiz bar] [wiz bar]" {
+		panic(x)
+	}
+
+	a1 := [2]string{"foo", "bar"}
+	a2 := a1 // creates a copy
+	a2[0] = "wiz"
+	if x := fmt.Sprint(a1, a2); x != "[foo bar] [wiz bar]" {
+		panic(x)
+	}
+
+	t1 := S{"foo", "bar"}
+	t2 := t1 // copy
+	t2.a = "wiz"
+	if x := fmt.Sprint(t1, t2); x != "{foo bar} {wiz bar}" {
+		panic(x)
+	}
+}
+
+func main() {
+	print() // legal
+
+	if counter != 2*3*5 {
+		panic(counter)
+	}
+
+	// Test builtins (e.g. complex) preserve named argument types.
+	type N complex128
+	var n N
+	n = complex(1.0, 2.0)
+	if n != complex(1.0, 2.0) {
+		panic(n)
+	}
+	if x := reflect.TypeOf(n).String(); x != "main.N" {
+		panic(x)
+	}
+	if real(n) != 1.0 || imag(n) != 2.0 {
+		panic(n)
+	}
+
+	// Channel + select.
+	ch := make(chan int, 1)
+	select {
+	case ch <- 1:
+		// ok
+	default:
+		panic("couldn't send")
+	}
+	if <-ch != 1 {
+		panic("couldn't receive")
+	}
+	// A "receive" select-case that doesn't declare its vars.  (regression test)
+	anint := 0
+	ok := false
+	select {
+	case anint, ok = <-ch:
+	case anint = <-ch:
+	default:
+	}
+	_ = anint
+	_ = ok
+
+	// Anon structs with methods.
+	anon := struct{ T }{T: T{z: 1}}
+	if x := anon.f(); x != 1 {
+		panic(x)
+	}
+	var i I = anon
+	if x := i.f(); x != 1 {
+		panic(x)
+	}
+	// NB. precise output of reflect.Type.String is undefined.
+	if x := reflect.TypeOf(i).String(); x != "struct { main.T }" && x != "struct{main.T}" {
+		panic(x)
+	}
+
+	// fmt.
+	const message = "Hello, World!"
+	if fmt.Sprintf("%s, %s!", "Hello", "World") != message {
+		panic("oops")
+	}
+
+	// Type assertion.
+	type S struct {
+		f int
+	}
+	var e empty = S{f: 42}
+	switch v := e.(type) {
+	case S:
+		if v.f != 42 {
+			panic(v.f)
+		}
+	default:
+		panic(reflect.TypeOf(v))
+	}
+	if i, ok := e.(I); ok {
+		panic(i)
+	}
+
+	// Switch.
+	var x int
+	switch x {
+	case 1:
+		panic(x)
+		fallthrough
+	case 2, 3:
+		panic(x)
+	default:
+		// ok
+	}
+	// empty switch
+	switch {
+	}
+	// empty switch
+	switch {
+	default:
+	}
+	// empty switch
+	switch {
+	default:
+		fallthrough
+	case false:
+	}
+
+	// string -> []rune conversion.
+	use([]rune("foo"))
+
+	// Calls of form x.f().
+	type S2 struct {
+		f func() int
+	}
+	S2{f: func() int { return 1 }}.f() // field is a func value
+	T{}.f()                            // method call
+	i.f()                              // interface method invocation
+	(interface {
+		f() int
+	}(T{})).f() // anon interface method invocation
+
+	// Map lookup.
+	if v, ok := map[string]string{}["foo5"]; v != "" || ok {
+		panic("oops")
+	}
+
+	// Regression test: implicit address-taken struct literal
+	// inside literal map element.
+	_ = map[int]*struct{}{0: {}}
+}
+
+type mybool bool
+
+func (mybool) f() {}
+
+func init() {
+	type mybool bool
+	var b mybool
+	var i interface{} = b || b // result preserves types of operands
+	_ = i.(mybool)
+
+	i = false && b // result preserves type of "typed" operand
+	_ = i.(mybool)
+
+	i = b || true // result preserves type of "typed" operand
+	_ = i.(mybool)
+}
+
+func init() {
+	var x, y int
+	var b mybool = x == y // x==y is an untyped bool
+	b.f()
+}
+
+// Simple closures.
+func init() {
+	b := 3
+	f := func(a int) int {
+		return a + b
+	}
+	b++
+	if x := f(1); x != 5 { // 1+4 == 5
+		panic(x)
+	}
+	b++
+	if x := f(2); x != 7 { // 2+5 == 7
+		panic(x)
+	}
+	if b := f(1) < 16 || f(2) < 17; !b {
+		panic("oops")
+	}
+}
+
+// Shifts.
+func init() {
+	var i int64 = 1
+	var u uint64 = 1 << 32
+	if x := i << uint32(u); x != 1 {
+		panic(x)
+	}
+	if x := i << uint64(u); x != 0 {
+		panic(x)
+	}
+}
+
+// Implicit conversion of delete() key operand.
+func init() {
+	type I interface{}
+	m := make(map[I]bool)
+	m[1] = true
+	m[I(2)] = true
+	if len(m) != 2 {
+		panic(m)
+	}
+	delete(m, I(1))
+	delete(m, 2)
+	if len(m) != 0 {
+		panic(m)
+	}
+}
+
+// An I->I conversion always succeeds.
+func init() {
+	var x I
+	if I(x) != I(nil) {
+		panic("I->I conversion failed")
+	}
+}
+
+// An I->I type-assert fails iff the value is nil.
+func init() {
+	defer func() {
+		r := fmt.Sprint(recover())
+		// Exact error varies by toolchain.
+		if r != "runtime error: interface conversion: interface is nil, not main.I" &&
+			r != "interface conversion: interface is nil, not main.I" {
+			panic("I->I type assertion succeeded for nil value")
+		}
+	}()
+	var x I
+	_ = x.(I)
+}
+
+//////////////////////////////////////////////////////////////////////
+// Variadic bridge methods and interface thunks.
+
+type VT int
+
+var vcount = 0
+
+func (VT) f(x int, y ...string) {
+	vcount++
+	if x != 1 {
+		panic(x)
+	}
+	if len(y) != 2 || y[0] != "foo" || y[1] != "bar" {
+		panic(y)
+	}
+}
+
+type VS struct {
+	VT
+}
+
+type VI interface {
+	f(x int, y ...string)
+}
+
+func init() {
+	foobar := []string{"foo", "bar"}
+	var s VS
+	s.f(1, "foo", "bar")
+	s.f(1, foobar...)
+	if vcount != 2 {
+		panic("s.f not called twice")
+	}
+
+	fn := VI.f
+	fn(s, 1, "foo", "bar")
+	fn(s, 1, foobar...)
+	if vcount != 4 {
+		panic("I.f not called twice")
+	}
+}
+
+// Multiple labels on same statement.
+func multipleLabels() {
+	var trace []int
+	i := 0
+one:
+two:
+	for ; i < 3; i++ {
+		trace = append(trace, i)
+		switch i {
+		case 0:
+			continue two
+		case 1:
+			i++
+			goto one
+		case 2:
+			break two
+		}
+	}
+	if x := fmt.Sprint(trace); x != "[0 1 2]" {
+		panic(x)
+	}
+}
+
+func init() {
+	multipleLabels()
+}
+
+func init() {
+	// Struct equivalence ignores blank fields.
+	type s struct{ x, _, z int }
+	s1 := s{x: 1, z: 3}
+	s2 := s{x: 1, z: 3}
+	if s1 != s2 {
+		panic("not equal")
+	}
+}
+
+func init() {
+	// A slice var can be compared to const []T nil.
+	var i interface{} = []string{"foo"}
+	var j interface{} = []string(nil)
+	if i.([]string) == nil {
+		panic("expected i non-nil")
+	}
+	if j.([]string) != nil {
+		panic("expected j nil")
+	}
+	// But two slices cannot be compared, even if one is nil.
+	defer func() {
+		r := fmt.Sprint(recover())
+		if r != "runtime error: comparing uncomparable type []string" {
+			panic("want panic from slice comparison, got " + r)
+		}
+	}()
+	_ = i == j // interface comparison recurses on types
+}
+
+func init() {
+	// Regression test for SSA renaming bug.
+	var ints []int
+	for _ = range "foo" {
+		var x int
+		x++
+		ints = append(ints, x)
+	}
+	if fmt.Sprint(ints) != "[1 1 1]" {
+		panic(ints)
+	}
+}
+
+// Regression test for issue 6949:
+// []byte("foo") is not a constant since it allocates memory.
+func init() {
+	var r string
+	for i, b := range "ABC" {
+		x := []byte("abc")
+		x[i] = byte(b)
+		r += string(x)
+	}
+	if r != "AbcaBcabC" {
+		panic(r)
+	}
+}
+
+// Test of 3-operand x[lo:hi:max] slice.
+func init() {
+	s := []int{0, 1, 2, 3}
+	lenCapLoHi := func(x []int) [4]int { return [4]int{len(x), cap(x), x[0], x[len(x)-1]} }
+	if got := lenCapLoHi(s[1:3]); got != [4]int{2, 3, 1, 2} {
+		panic(got)
+	}
+	if got := lenCapLoHi(s[1:3:3]); got != [4]int{2, 2, 1, 2} {
+		panic(got)
+	}
+	max := 3
+	if "a"[0] == 'a' {
+		max = 2 // max is non-constant, even in SSA form
+	}
+	if got := lenCapLoHi(s[1:2:max]); got != [4]int{1, 1, 1, 1} {
+		panic(got)
+	}
+}
+
+var one = 1 // not a constant
+
+// Test makeslice.
+func init() {
+	check := func(s []string, wantLen, wantCap int) {
+		if len(s) != wantLen {
+			panic(len(s))
+		}
+		if cap(s) != wantCap {
+			panic(cap(s))
+		}
+	}
+	//                                       SSA form:
+	check(make([]string, 10), 10, 10)     // new([10]string)[:10]
+	check(make([]string, one), 1, 1)      // make([]string, one, one)
+	check(make([]string, 0, 10), 0, 10)   // new([10]string)[:0]
+	check(make([]string, 0, one), 0, 1)   // make([]string, 0, one)
+	check(make([]string, one, 10), 1, 10) // new([10]string)[:one]
+	check(make([]string, one, one), 1, 1) // make([]string, one, one)
+}
+
+// Test that a nice error is issued by indirection wrappers.
+func init() {
+	var ptr *T
+	var i I = ptr
+
+	defer func() {
+		r := fmt.Sprint(recover())
+		// Exact error varies by toolchain:
+		if r != "runtime error: value method (main.T).f called using nil *main.T pointer" &&
+			r != "value method main.T.f called using nil *T pointer" {
+			panic("want panic from call with nil receiver, got " + r)
+		}
+	}()
+	i.f()
+	panic("unreachable")
+}
+
+// Regression test for a subtle bug in which copying values would causes
+// subcomponents of aggregate variables to change address, breaking
+// aliases.
+func init() {
+	type T struct{ f int }
+	var x T
+	p := &x.f
+	x = T{}
+	*p = 1
+	if x.f != 1 {
+		panic("lost store")
+	}
+	if p != &x.f {
+		panic("unstable address")
+	}
+}
diff --git a/go/ssa/interp/testdata/defer.go b/go/ssa/interp/testdata/defer.go
new file mode 100644
index 0000000..f5bae6c
--- /dev/null
+++ b/go/ssa/interp/testdata/defer.go
@@ -0,0 +1,53 @@
+package main
+
+// Tests of defer.  (Deferred recover() belongs is recover.go.)
+
+import "fmt"
+
+func deferMutatesResults(noArgReturn bool) (a, b int) {
+	defer func() {
+		if a != 1 || b != 2 {
+			panic(fmt.Sprint(a, b))
+		}
+		a, b = 3, 4
+	}()
+	if noArgReturn {
+		a, b = 1, 2
+		return
+	}
+	return 1, 2
+}
+
+func init() {
+	a, b := deferMutatesResults(true)
+	if a != 3 || b != 4 {
+		panic(fmt.Sprint(a, b))
+	}
+	a, b = deferMutatesResults(false)
+	if a != 3 || b != 4 {
+		panic(fmt.Sprint(a, b))
+	}
+}
+
+// We concatenate init blocks to make a single function, but we must
+// run defers at the end of each block, not the combined function.
+var deferCount = 0
+
+func init() {
+	deferCount = 1
+	defer func() {
+		deferCount++
+	}()
+	// defer runs HERE
+}
+
+func init() {
+	// Strictly speaking the spec says deferCount may be 0 or 2
+	// since the relative order of init blocks is unspecified.
+	if deferCount != 2 {
+		panic(deferCount) // defer call has not run!
+	}
+}
+
+func main() {
+}
diff --git a/go/ssa/interp/testdata/fieldprom.go b/go/ssa/interp/testdata/fieldprom.go
new file mode 100644
index 0000000..fc276dd
--- /dev/null
+++ b/go/ssa/interp/testdata/fieldprom.go
@@ -0,0 +1,114 @@
+package main
+
+// Tests of field promotion logic.
+
+type A struct {
+	x int
+	y *int
+}
+
+type B struct {
+	p int
+	q *int
+}
+
+type C struct {
+	A
+	*B
+}
+
+type D struct {
+	a int
+	C
+}
+
+func assert(cond bool) {
+	if !cond {
+		panic("failed")
+	}
+}
+
+func f1(c C) {
+	assert(c.x == c.A.x)
+	assert(c.y == c.A.y)
+	assert(&c.x == &c.A.x)
+	assert(&c.y == &c.A.y)
+
+	assert(c.p == c.B.p)
+	assert(c.q == c.B.q)
+	assert(&c.p == &c.B.p)
+	assert(&c.q == &c.B.q)
+
+	c.x = 1
+	*c.y = 1
+	c.p = 1
+	*c.q = 1
+}
+
+func f2(c *C) {
+	assert(c.x == c.A.x)
+	assert(c.y == c.A.y)
+	assert(&c.x == &c.A.x)
+	assert(&c.y == &c.A.y)
+
+	assert(c.p == c.B.p)
+	assert(c.q == c.B.q)
+	assert(&c.p == &c.B.p)
+	assert(&c.q == &c.B.q)
+
+	c.x = 1
+	*c.y = 1
+	c.p = 1
+	*c.q = 1
+}
+
+func f3(d D) {
+	assert(d.x == d.C.A.x)
+	assert(d.y == d.C.A.y)
+	assert(&d.x == &d.C.A.x)
+	assert(&d.y == &d.C.A.y)
+
+	assert(d.p == d.C.B.p)
+	assert(d.q == d.C.B.q)
+	assert(&d.p == &d.C.B.p)
+	assert(&d.q == &d.C.B.q)
+
+	d.x = 1
+	*d.y = 1
+	d.p = 1
+	*d.q = 1
+}
+
+func f4(d *D) {
+	assert(d.x == d.C.A.x)
+	assert(d.y == d.C.A.y)
+	assert(&d.x == &d.C.A.x)
+	assert(&d.y == &d.C.A.y)
+
+	assert(d.p == d.C.B.p)
+	assert(d.q == d.C.B.q)
+	assert(&d.p == &d.C.B.p)
+	assert(&d.q == &d.C.B.q)
+
+	d.x = 1
+	*d.y = 1
+	d.p = 1
+	*d.q = 1
+}
+
+func main() {
+	y := 123
+	c := C{
+		A{x: 42, y: &y},
+		&B{p: 42, q: &y},
+	}
+
+	assert(&c.x == &c.A.x)
+
+	f1(c)
+	f2(&c)
+
+	d := D{C: c}
+	f3(d)
+	f4(&d)
+}
diff --git a/go/ssa/interp/testdata/ifaceconv.go b/go/ssa/interp/testdata/ifaceconv.go
new file mode 100644
index 0000000..96fc105
--- /dev/null
+++ b/go/ssa/interp/testdata/ifaceconv.go
@@ -0,0 +1,83 @@
+package main
+
+// Tests of interface conversions and type assertions.
+
+type I0 interface {
+}
+type I1 interface {
+	f()
+}
+type I2 interface {
+	f()
+	g()
+}
+
+type C0 struct{}
+type C1 struct{}
+
+func (C1) f() {}
+
+type C2 struct{}
+
+func (C2) f() {}
+func (C2) g() {}
+
+func main() {
+	var i0 I0
+	var i1 I1
+	var i2 I2
+
+	// Nil always causes a type assertion to fail, even to the
+	// same type.
+	if _, ok := i0.(I0); ok {
+		panic("nil i0.(I0) succeeded")
+	}
+	if _, ok := i1.(I1); ok {
+		panic("nil i1.(I1) succeeded")
+	}
+	if _, ok := i2.(I2); ok {
+		panic("nil i2.(I2) succeeded")
+	}
+
+	// Conversions can't fail, even with nil.
+	_ = I0(i0)
+
+	_ = I0(i1)
+	_ = I1(i1)
+
+	_ = I0(i2)
+	_ = I1(i2)
+	_ = I2(i2)
+
+	// Non-nil type assertions pass or fail based on the concrete type.
+	i1 = C1{}
+	if _, ok := i1.(I0); !ok {
+		panic("C1 i1.(I0) failed")
+	}
+	if _, ok := i1.(I1); !ok {
+		panic("C1 i1.(I1) failed")
+	}
+	if _, ok := i1.(I2); ok {
+		panic("C1 i1.(I2) succeeded")
+	}
+
+	i1 = C2{}
+	if _, ok := i1.(I0); !ok {
+		panic("C2 i1.(I0) failed")
+	}
+	if _, ok := i1.(I1); !ok {
+		panic("C2 i1.(I1) failed")
+	}
+	if _, ok := i1.(I2); !ok {
+		panic("C2 i1.(I2) failed")
+	}
+
+	// Conversions can't fail.
+	i1 = C1{}
+	if I0(i1) == nil {
+		panic("C1 I0(i1) was nil")
+	}
+	if I1(i1) == nil {
+		panic("C1 I1(i1) was nil")
+	}
+}
diff --git a/go/ssa/interp/testdata/ifaceprom.go b/go/ssa/interp/testdata/ifaceprom.go
new file mode 100644
index 0000000..414dc73
--- /dev/null
+++ b/go/ssa/interp/testdata/ifaceprom.go
@@ -0,0 +1,58 @@
+package main
+
+// Test of promotion of methods of an interface embedded within a
+// struct.  In particular, this test exercises that the correct
+// method is called.
+
+type I interface {
+	one() int
+	two() string
+}
+
+type S struct {
+	I
+}
+
+type impl struct{}
+
+func (impl) one() int {
+	return 1
+}
+
+func (impl) two() string {
+	return "two"
+}
+
+func main() {
+	var s S
+	s.I = impl{}
+	if one := s.I.one(); one != 1 {
+		panic(one)
+	}
+	if one := s.one(); one != 1 {
+		panic(one)
+	}
+	closOne := s.I.one
+	if one := closOne(); one != 1 {
+		panic(one)
+	}
+	closOne = s.one
+	if one := closOne(); one != 1 {
+		panic(one)
+	}
+
+	if two := s.I.two(); two != "two" {
+		panic(two)
+	}
+	if two := s.two(); two != "two" {
+		panic(two)
+	}
+	closTwo := s.I.two
+	if two := closTwo(); two != "two" {
+		panic(two)
+	}
+	closTwo = s.two
+	if two := closTwo(); two != "two" {
+		panic(two)
+	}
+}
diff --git a/go/ssa/interp/testdata/initorder.go b/go/ssa/interp/testdata/initorder.go
new file mode 100644
index 0000000..0f26bed
--- /dev/null
+++ b/go/ssa/interp/testdata/initorder.go
@@ -0,0 +1,67 @@
+package main
+
+import "fmt"
+
+// Test of initialization order of package-level vars.
+
+var counter int
+
+func next() int {
+	c := counter
+	counter++
+	return c
+}
+
+func next2() (x int, y int) {
+	x = next()
+	y = next()
+	return
+}
+
+func makeOrder() int {
+	_, _, _, _ = f, b, d, e
+	return 0
+}
+
+func main() {
+	// Initialization constraints:
+	// - {f,b,c/d,e} < order  (ref graph traversal)
+	// - order < {a}          (lexical order)
+	// - b < c/d < e < f      (lexical order)
+	// Solution: a b c/d e f
+	abcdef := [6]int{a, b, c, d, e, f}
+	if abcdef != [6]int{0, 1, 2, 3, 4, 5} {
+		panic(abcdef)
+	}
+}
+
+var order = makeOrder()
+
+var a, b = next(), next()
+var c, d = next2()
+var e, f = next(), next()
+
+// ------------------------------------------------------------------------
+
+var order2 []string
+
+func create(x int, name string) int {
+	order2 = append(order2, name)
+	return x
+}
+
+var C = create(B+1, "C")
+var A, B = create(1, "A"), create(2, "B")
+
+// Initialization order of package-level value specs.
+func init() {
+	x := fmt.Sprint(order2)
+	// Result varies by toolchain.  This is a spec bug.
+	if x != "[B C A]" && // gc
+		x != "[A B C]" { // go/types
+		panic(x)
+	}
+	if C != 3 {
+		panic(c)
+	}
+}
diff --git a/go/ssa/interp/testdata/methprom.go b/go/ssa/interp/testdata/methprom.go
new file mode 100644
index 0000000..e8e384c
--- /dev/null
+++ b/go/ssa/interp/testdata/methprom.go
@@ -0,0 +1,93 @@
+package main
+
+// Tests of method promotion logic.
+
+type A struct{ magic int }
+
+func (a A) x() {
+	if a.magic != 1 {
+		panic(a.magic)
+	}
+}
+func (a *A) y() *A {
+	return a
+}
+
+type B struct{ magic int }
+
+func (b B) p() {
+	if b.magic != 2 {
+		panic(b.magic)
+	}
+}
+func (b *B) q() {
+	if b != theC.B {
+		panic("oops")
+	}
+}
+
+type I interface {
+	f()
+}
+
+type impl struct{ magic int }
+
+func (i impl) f() {
+	if i.magic != 3 {
+		panic("oops")
+	}
+}
+
+type C struct {
+	A
+	*B
+	I
+}
+
+func assert(cond bool) {
+	if !cond {
+		panic("failed")
+	}
+}
+
+var theC = C{
+	A: A{1},
+	B: &B{2},
+	I: impl{3},
+}
+
+func addr() *C {
+	return &theC
+}
+
+func value() C {
+	return theC
+}
+
+func main() {
+	// address
+	addr().x()
+	if addr().y() != &theC.A {
+		panic("oops")
+	}
+	addr().p()
+	addr().q()
+	addr().f()
+
+	// addressable value
+	var c C = value()
+	c.x()
+	if c.y() != &c.A {
+		panic("oops")
+	}
+	c.p()
+	c.q()
+	c.f()
+
+	// non-addressable value
+	value().x()
+	// value().y() // not in method set
+	value().p()
+	value().q()
+	value().f()
+}
diff --git a/go/ssa/interp/testdata/mrvchain.go b/go/ssa/interp/testdata/mrvchain.go
new file mode 100644
index 0000000..70dfd02
--- /dev/null
+++ b/go/ssa/interp/testdata/mrvchain.go
@@ -0,0 +1,75 @@
+// Tests of call chaining f(g()) when g has multiple return values (MRVs).
+// See https://code.google.com/p/go/issues/detail?id=4573.
+
+package main
+
+func assert(actual, expected int) {
+	if actual != expected {
+		panic(actual)
+	}
+}
+
+func g() (int, int) {
+	return 5, 7
+}
+
+func g2() (float64, float64) {
+	return 5, 7
+}
+
+func f1v(x int, v ...int) {
+	assert(x, 5)
+	assert(v[0], 7)
+}
+
+func f2(x, y int) {
+	assert(x, 5)
+	assert(y, 7)
+}
+
+func f2v(x, y int, v ...int) {
+	assert(x, 5)
+	assert(y, 7)
+	assert(len(v), 0)
+}
+
+func complexArgs() (float64, float64) {
+	return 5, 7
+}
+
+func appendArgs() ([]string, string) {
+	return []string{"foo"}, "bar"
+}
+
+func h() (i interface{}, ok bool) {
+	m := map[int]string{1: "hi"}
+	i, ok = m[1] // string->interface{} conversion within multi-valued expression
+	return
+}
+
+func h2() (i interface{}, ok bool) {
+	ch := make(chan string, 1)
+	ch <- "hi"
+	i, ok = <-ch // string->interface{} conversion within multi-valued expression
+	return
+}
+
+func main() {
+	f1v(g())
+	f2(g())
+	f2v(g())
+	if c := complex(complexArgs()); c != 5+7i {
+		panic(c)
+	}
+	if s := append(appendArgs()); len(s) != 2 || s[0] != "foo" || s[1] != "bar" {
+		panic(s)
+	}
+	i, ok := h()
+	if !ok || i.(string) != "hi" {
+		panic(i)
+	}
+	i, ok = h2()
+	if !ok || i.(string) != "hi" {
+		panic(i)
+	}
+}
diff --git a/go/ssa/interp/testdata/range.go b/go/ssa/interp/testdata/range.go
new file mode 100644
index 0000000..da8a421
--- /dev/null
+++ b/go/ssa/interp/testdata/range.go
@@ -0,0 +1,55 @@
+package main
+
+// Tests of range loops.
+
+import "fmt"
+
+// Range over string.
+func init() {
+	if x := len("Hello, 世界"); x != 13 { // bytes
+		panic(x)
+	}
+	var indices []int
+	var runes []rune
+	for i, r := range "Hello, 世界" {
+		runes = append(runes, r)
+		indices = append(indices, i)
+	}
+	if x := fmt.Sprint(runes); x != "[72 101 108 108 111 44 32 19990 30028]" {
+		panic(x)
+	}
+	if x := fmt.Sprint(indices); x != "[0 1 2 3 4 5 6 7 10]" {
+		panic(x)
+	}
+	s := ""
+	for _, r := range runes {
+		s = fmt.Sprintf("%s%c", s, r)
+	}
+	if s != "Hello, 世界" {
+		panic(s)
+	}
+
+	var x int
+	for range "Hello, 世界" {
+		x++
+	}
+	if x != len(indices) {
+		panic(x)
+	}
+}
+
+// Regression test for range of pointer to named array type.
+func init() {
+	type intarr [3]int
+	ia := intarr{1, 2, 3}
+	var count int
+	for _, x := range &ia {
+		count += x
+	}
+	if count != 6 {
+		panic(count)
+	}
+}
+
+func main() {
+}
diff --git a/go/ssa/interp/testdata/recover.go b/go/ssa/interp/testdata/recover.go
new file mode 100644
index 0000000..b560052
--- /dev/null
+++ b/go/ssa/interp/testdata/recover.go
@@ -0,0 +1,34 @@
+package main
+
+// Tests of panic/recover.
+
+import "fmt"
+
+func fortyTwo() (r int) {
+	r = 42
+	// The next two statements simulate a 'return' statement.
+	defer func() { recover() }()
+	panic(nil)
+}
+
+func zero() int {
+	defer func() { recover() }()
+	panic(1)
+}
+
+func zeroEmpty() (int, string) {
+	defer func() { recover() }()
+	panic(1)
+}
+
+func main() {
+	if r := fortyTwo(); r != 42 {
+		panic(r)
+	}
+	if r := zero(); r != 0 {
+		panic(r)
+	}
+	if r, s := zeroEmpty(); r != 0 || s != "" {
+		panic(fmt.Sprint(r, s))
+	}
+}
diff --git a/go/ssa/interp/testdata/reflect.go b/go/ssa/interp/testdata/reflect.go
new file mode 100644
index 0000000..6aa9a67
--- /dev/null
+++ b/go/ssa/interp/testdata/reflect.go
@@ -0,0 +1,11 @@
+package main
+
+import "reflect"
+
+func main() {
+	// Regression test for issue 9462.
+	got := reflect.SliceOf(reflect.TypeOf(byte(0))).String()
+	if got != "[]uint8" && got != "[]byte" { // result varies by toolchain
+		println("BUG: " + got)
+	}
+}
diff --git a/go/ssa/interp/testdata/static.go b/go/ssa/interp/testdata/static.go
new file mode 100644
index 0000000..b115513
--- /dev/null
+++ b/go/ssa/interp/testdata/static.go
@@ -0,0 +1,58 @@
+package main
+
+// Static tests of SSA builder (via the sanity checker).
+// Dynamic semantics are not exercised.
+
+func init() {
+	// Regression test for issue 6806.
+	ch := make(chan int)
+	select {
+	case n, _ := <-ch:
+		_ = n
+	default:
+		// The default case disables the simplification of
+		// select to a simple receive statement.
+	}
+
+	// value,ok-form receive where TypeOf(ok) is a named boolean.
+	type mybool bool
+	var x int
+	var y mybool
+	select {
+	case x, y = <-ch:
+	default:
+		// The default case disables the simplification of
+		// select to a simple receive statement.
+	}
+	_ = x
+	_ = y
+}
+
+var a int
+
+// Regression test for issue 7840 (covered by SSA sanity checker).
+func bug7840() bool {
+	// This creates a single-predecessor block with a φ-node.
+	return false && a == 0 && a == 0
+}
+
+// A blocking select (sans "default:") cannot fall through.
+// Regression test for issue 7022.
+func bug7022() int {
+	var c1, c2 chan int
+	select {
+	case <-c1:
+		return 123
+	case <-c2:
+		return 456
+	}
+}
+
+// Parens should not prevent intrinsic treatment of built-ins.
+// (Regression test for a crash.)
+func init() {
+	_ = (new)(int)
+	_ = (make)([]int, 0)
+}
+
+func main() {}
diff --git a/go/ssa/interp/value.go b/go/ssa/interp/value.go
new file mode 100644
index 0000000..2ab0c04
--- /dev/null
+++ b/go/ssa/interp/value.go
@@ -0,0 +1,497 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package interp
+
+// Values
+//
+// All interpreter values are "boxed" in the empty interface, value.
+// The range of possible dynamic types within value are:
+//
+// - bool
+// - numbers (all built-in int/float/complex types are distinguished)
+// - string
+// - map[value]value --- maps for which  usesBuiltinMap(keyType)
+//   *hashmap        --- maps for which !usesBuiltinMap(keyType)
+// - chan value
+// - []value --- slices
+// - iface --- interfaces.
+// - structure --- structs.  Fields are ordered and accessed by numeric indices.
+// - array --- arrays.
+// - *value --- pointers.  Careful: *value is a distinct type from *array etc.
+// - *ssa.Function \
+//   *ssa.Builtin   } --- functions.  A nil 'func' is always of type *ssa.Function.
+//   *closure      /
+// - tuple --- as returned by Return, Next, "value,ok" modes, etc.
+// - iter --- iterators from 'range' over map or string.
+// - bad --- a poison pill for locals that have gone out of scope.
+// - rtype -- the interpreter's concrete implementation of reflect.Type
+//
+// Note that nil is not on this list.
+//
+// Pay close attention to whether or not the dynamic type is a pointer.
+// The compiler cannot help you since value is an empty interface.
+
+import (
+	"bytes"
+	"fmt"
+	"io"
+	"reflect"
+	"strings"
+	"sync"
+	"unsafe"
+
+	"golang.org/x/tools/go/ssa"
+	"golang.org/x/tools/go/types"
+	"golang.org/x/tools/go/types/typeutil"
+)
+
+type value interface{}
+
+type tuple []value
+
+type array []value
+
+type iface struct {
+	t types.Type // never an "untyped" type
+	v value
+}
+
+type structure []value
+
+// For map, array, *array, slice, string or channel.
+type iter interface {
+	// next returns a Tuple (key, value, ok).
+	// key and value are unaliased, e.g. copies of the sequence element.
+	next() tuple
+}
+
+type closure struct {
+	Fn  *ssa.Function
+	Env []value
+}
+
+type bad struct{}
+
+type rtype struct {
+	t types.Type
+}
+
+// Hash functions and equivalence relation:
+
+// hashString computes the FNV hash of s.
+func hashString(s string) int {
+	var h uint32
+	for i := 0; i < len(s); i++ {
+		h ^= uint32(s[i])
+		h *= 16777619
+	}
+	return int(h)
+}
+
+var (
+	mu     sync.Mutex
+	hasher = typeutil.MakeHasher()
+)
+
+// hashType returns a hash for t such that
+// types.Identical(x, y) => hashType(x) == hashType(y).
+func hashType(t types.Type) int {
+	mu.Lock()
+	h := int(hasher.Hash(t))
+	mu.Unlock()
+	return h
+}
+
+// usesBuiltinMap returns true if the built-in hash function and
+// equivalence relation for type t are consistent with those of the
+// interpreter's representation of type t.  Such types are: all basic
+// types (bool, numbers, string), pointers and channels.
+//
+// usesBuiltinMap returns false for types that require a custom map
+// implementation: interfaces, arrays and structs.
+//
+// Panic ensues if t is an invalid map key type: function, map or slice.
+func usesBuiltinMap(t types.Type) bool {
+	switch t := t.(type) {
+	case *types.Basic, *types.Chan, *types.Pointer:
+		return true
+	case *types.Named:
+		return usesBuiltinMap(t.Underlying())
+	case *types.Interface, *types.Array, *types.Struct:
+		return false
+	}
+	panic(fmt.Sprintf("invalid map key type: %T", t))
+}
+
+func (x array) eq(t types.Type, _y interface{}) bool {
+	y := _y.(array)
+	tElt := t.Underlying().(*types.Array).Elem()
+	for i, xi := range x {
+		if !equals(tElt, xi, y[i]) {
+			return false
+		}
+	}
+	return true
+}
+
+func (x array) hash(t types.Type) int {
+	h := 0
+	tElt := t.Underlying().(*types.Array).Elem()
+	for _, xi := range x {
+		h += hash(tElt, xi)
+	}
+	return h
+}
+
+func (x structure) eq(t types.Type, _y interface{}) bool {
+	y := _y.(structure)
+	tStruct := t.Underlying().(*types.Struct)
+	for i, n := 0, tStruct.NumFields(); i < n; i++ {
+		if f := tStruct.Field(i); !f.Anonymous() {
+			if !equals(f.Type(), x[i], y[i]) {
+				return false
+			}
+		}
+	}
+	return true
+}
+
+func (x structure) hash(t types.Type) int {
+	tStruct := t.Underlying().(*types.Struct)
+	h := 0
+	for i, n := 0, tStruct.NumFields(); i < n; i++ {
+		if f := tStruct.Field(i); !f.Anonymous() {
+			h += hash(f.Type(), x[i])
+		}
+	}
+	return h
+}
+
+// nil-tolerant variant of types.Identical.
+func sameType(x, y types.Type) bool {
+	if x == nil {
+		return y == nil
+	}
+	return y != nil && types.Identical(x, y)
+}
+
+func (x iface) eq(t types.Type, _y interface{}) bool {
+	y := _y.(iface)
+	return sameType(x.t, y.t) && (x.t == nil || equals(x.t, x.v, y.v))
+}
+
+func (x iface) hash(_ types.Type) int {
+	return hashType(x.t)*8581 + hash(x.t, x.v)
+}
+
+func (x rtype) hash(_ types.Type) int {
+	return hashType(x.t)
+}
+
+func (x rtype) eq(_ types.Type, y interface{}) bool {
+	return types.Identical(x.t, y.(rtype).t)
+}
+
+// equals returns true iff x and y are equal according to Go's
+// linguistic equivalence relation for type t.
+// In a well-typed program, the dynamic types of x and y are
+// guaranteed equal.
+func equals(t types.Type, x, y value) bool {
+	switch x := x.(type) {
+	case bool:
+		return x == y.(bool)
+	case int:
+		return x == y.(int)
+	case int8:
+		return x == y.(int8)
+	case int16:
+		return x == y.(int16)
+	case int32:
+		return x == y.(int32)
+	case int64:
+		return x == y.(int64)
+	case uint:
+		return x == y.(uint)
+	case uint8:
+		return x == y.(uint8)
+	case uint16:
+		return x == y.(uint16)
+	case uint32:
+		return x == y.(uint32)
+	case uint64:
+		return x == y.(uint64)
+	case uintptr:
+		return x == y.(uintptr)
+	case float32:
+		return x == y.(float32)
+	case float64:
+		return x == y.(float64)
+	case complex64:
+		return x == y.(complex64)
+	case complex128:
+		return x == y.(complex128)
+	case string:
+		return x == y.(string)
+	case *value:
+		return x == y.(*value)
+	case chan value:
+		return x == y.(chan value)
+	case structure:
+		return x.eq(t, y)
+	case array:
+		return x.eq(t, y)
+	case iface:
+		return x.eq(t, y)
+	case rtype:
+		return x.eq(t, y)
+	}
+
+	// Since map, func and slice don't support comparison, this
+	// case is only reachable if one of x or y is literally nil
+	// (handled in eqnil) or via interface{} values.
+	panic(fmt.Sprintf("comparing uncomparable type %s", t))
+}
+
+// Returns an integer hash of x such that equals(x, y) => hash(x) == hash(y).
+func hash(t types.Type, x value) int {
+	switch x := x.(type) {
+	case bool:
+		if x {
+			return 1
+		}
+		return 0
+	case int:
+		return x
+	case int8:
+		return int(x)
+	case int16:
+		return int(x)
+	case int32:
+		return int(x)
+	case int64:
+		return int(x)
+	case uint:
+		return int(x)
+	case uint8:
+		return int(x)
+	case uint16:
+		return int(x)
+	case uint32:
+		return int(x)
+	case uint64:
+		return int(x)
+	case uintptr:
+		return int(x)
+	case float32:
+		return int(x)
+	case float64:
+		return int(x)
+	case complex64:
+		return int(real(x))
+	case complex128:
+		return int(real(x))
+	case string:
+		return hashString(x)
+	case *value:
+		return int(uintptr(unsafe.Pointer(x)))
+	case chan value:
+		return int(uintptr(reflect.ValueOf(x).Pointer()))
+	case structure:
+		return x.hash(t)
+	case array:
+		return x.hash(t)
+	case iface:
+		return x.hash(t)
+	case rtype:
+		return x.hash(t)
+	}
+	panic(fmt.Sprintf("%T is unhashable", x))
+}
+
+// reflect.Value struct values don't have a fixed shape, since the
+// payload can be a scalar or an aggregate depending on the instance.
+// So store (and load) can't simply use recursion over the shape of the
+// rhs value, or the lhs, to copy the value; we need the static type
+// information.  (We can't make reflect.Value a new basic data type
+// because its "structness" is exposed to Go programs.)
+
+// load returns the value of type T in *addr.
+func load(T types.Type, addr *value) value {
+	switch T := T.Underlying().(type) {
+	case *types.Struct:
+		v := (*addr).(structure)
+		a := make(structure, len(v))
+		for i := range a {
+			a[i] = load(T.Field(i).Type(), &v[i])
+		}
+		return a
+	case *types.Array:
+		v := (*addr).(array)
+		a := make(array, len(v))
+		for i := range a {
+			a[i] = load(T.Elem(), &v[i])
+		}
+		return a
+	default:
+		return *addr
+	}
+}
+
+// store stores value v of type T into *addr.
+func store(T types.Type, addr *value, v value) {
+	switch T := T.Underlying().(type) {
+	case *types.Struct:
+		lhs := (*addr).(structure)
+		rhs := v.(structure)
+		for i := range lhs {
+			store(T.Field(i).Type(), &lhs[i], rhs[i])
+		}
+	case *types.Array:
+		lhs := (*addr).(array)
+		rhs := v.(array)
+		for i := range lhs {
+			store(T.Elem(), &lhs[i], rhs[i])
+		}
+	default:
+		*addr = v
+	}
+}
+
+// Prints in the style of built-in println.
+// (More or less; in gc println is actually a compiler intrinsic and
+// can distinguish println(1) from println(interface{}(1)).)
+func writeValue(buf *bytes.Buffer, v value) {
+	switch v := v.(type) {
+	case nil, bool, int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, uintptr, float32, float64, complex64, complex128, string:
+		fmt.Fprintf(buf, "%v", v)
+
+	case map[value]value:
+		buf.WriteString("map[")
+		sep := ""
+		for k, e := range v {
+			buf.WriteString(sep)
+			sep = " "
+			writeValue(buf, k)
+			buf.WriteString(":")
+			writeValue(buf, e)
+		}
+		buf.WriteString("]")
+
+	case *hashmap:
+		buf.WriteString("map[")
+		sep := " "
+		for _, e := range v.table {
+			for e != nil {
+				buf.WriteString(sep)
+				sep = " "
+				writeValue(buf, e.key)
+				buf.WriteString(":")
+				writeValue(buf, e.value)
+				e = e.next
+			}
+		}
+		buf.WriteString("]")
+
+	case chan value:
+		fmt.Fprintf(buf, "%v", v) // (an address)
+
+	case *value:
+		if v == nil {
+			buf.WriteString("<nil>")
+		} else {
+			fmt.Fprintf(buf, "%p", v)
+		}
+
+	case iface:
+		fmt.Fprintf(buf, "(%s, ", v.t)
+		writeValue(buf, v.v)
+		buf.WriteString(")")
+
+	case structure:
+		buf.WriteString("{")
+		for i, e := range v {
+			if i > 0 {
+				buf.WriteString(" ")
+			}
+			writeValue(buf, e)
+		}
+		buf.WriteString("}")
+
+	case array:
+		buf.WriteString("[")
+		for i, e := range v {
+			if i > 0 {
+				buf.WriteString(" ")
+			}
+			writeValue(buf, e)
+		}
+		buf.WriteString("]")
+
+	case []value:
+		buf.WriteString("[")
+		for i, e := range v {
+			if i > 0 {
+				buf.WriteString(" ")
+			}
+			writeValue(buf, e)
+		}
+		buf.WriteString("]")
+
+	case *ssa.Function, *ssa.Builtin, *closure:
+		fmt.Fprintf(buf, "%p", v) // (an address)
+
+	case rtype:
+		buf.WriteString(v.t.String())
+
+	case tuple:
+		// Unreachable in well-formed Go programs
+		buf.WriteString("(")
+		for i, e := range v {
+			if i > 0 {
+				buf.WriteString(", ")
+			}
+			writeValue(buf, e)
+		}
+		buf.WriteString(")")
+
+	default:
+		fmt.Fprintf(buf, "<%T>", v)
+	}
+}
+
+// Implements printing of Go values in the style of built-in println.
+func toString(v value) string {
+	var b bytes.Buffer
+	writeValue(&b, v)
+	return b.String()
+}
+
+// ------------------------------------------------------------------------
+// Iterators
+
+type stringIter struct {
+	*strings.Reader
+	i int
+}
+
+func (it *stringIter) next() tuple {
+	okv := make(tuple, 3)
+	ch, n, err := it.ReadRune()
+	ok := err != io.EOF
+	okv[0] = ok
+	if ok {
+		okv[1] = it.i
+		okv[2] = ch
+	}
+	it.i += n
+	return okv
+}
+
+type mapIter chan [2]value
+
+func (it mapIter) next() tuple {
+	kv, ok := <-it
+	return tuple{ok, kv[0], kv[1]}
+}
diff --git a/go/ssa/lift.go b/go/ssa/lift.go
new file mode 100644
index 0000000..3771f61
--- /dev/null
+++ b/go/ssa/lift.go
@@ -0,0 +1,599 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssa
+
+// This file defines the lifting pass which tries to "lift" Alloc
+// cells (new/local variables) into SSA registers, replacing loads
+// with the dominating stored value, eliminating loads and stores, and
+// inserting φ-nodes as needed.
+
+// Cited papers and resources:
+//
+// Ron Cytron et al. 1991. Efficiently computing SSA form...
+// http://doi.acm.org/10.1145/115372.115320
+//
+// Cooper, Harvey, Kennedy.  2001.  A Simple, Fast Dominance Algorithm.
+// Software Practice and Experience 2001, 4:1-10.
+// http://www.hipersoft.rice.edu/grads/publications/dom14.pdf
+//
+// Daniel Berlin, llvmdev mailing list, 2012.
+// http://lists.cs.uiuc.edu/pipermail/llvmdev/2012-January/046638.html
+// (Be sure to expand the whole thread.)
+
+// TODO(adonovan): opt: there are many optimizations worth evaluating, and
+// the conventional wisdom for SSA construction is that a simple
+// algorithm well engineered often beats those of better asymptotic
+// complexity on all but the most egregious inputs.
+//
+// Danny Berlin suggests that the Cooper et al. algorithm for
+// computing the dominance frontier is superior to Cytron et al.
+// Furthermore he recommends that rather than computing the DF for the
+// whole function then renaming all alloc cells, it may be cheaper to
+// compute the DF for each alloc cell separately and throw it away.
+//
+// Consider exploiting liveness information to avoid creating dead
+// φ-nodes which we then immediately remove.
+//
+// Integrate lifting with scalar replacement of aggregates (SRA) since
+// the two are synergistic.
+//
+// Also see many other "TODO: opt" suggestions in the code.
+
+import (
+	"fmt"
+	"go/token"
+	"math/big"
+	"os"
+
+	"golang.org/x/tools/go/types"
+)
+
+// If true, perform sanity checking and show diagnostic information at
+// each step of lifting.  Very verbose.
+const debugLifting = false
+
+// domFrontier maps each block to the set of blocks in its dominance
+// frontier.  The outer slice is conceptually a map keyed by
+// Block.Index.  The inner slice is conceptually a set, possibly
+// containing duplicates.
+//
+// TODO(adonovan): opt: measure impact of dups; consider a packed bit
+// representation, e.g. big.Int, and bitwise parallel operations for
+// the union step in the Children loop.
+//
+// domFrontier's methods mutate the slice's elements but not its
+// length, so their receivers needn't be pointers.
+//
+type domFrontier [][]*BasicBlock
+
+func (df domFrontier) add(u, v *BasicBlock) {
+	p := &df[u.Index]
+	*p = append(*p, v)
+}
+
+// build builds the dominance frontier df for the dominator (sub)tree
+// rooted at u, using the Cytron et al. algorithm.
+//
+// TODO(adonovan): opt: consider Berlin approach, computing pruned SSA
+// by pruning the entire IDF computation, rather than merely pruning
+// the DF -> IDF step.
+func (df domFrontier) build(u *BasicBlock) {
+	// Encounter each node u in postorder of dom tree.
+	for _, child := range u.dom.children {
+		df.build(child)
+	}
+	for _, vb := range u.Succs {
+		if v := vb.dom; v.idom != u {
+			df.add(u, vb)
+		}
+	}
+	for _, w := range u.dom.children {
+		for _, vb := range df[w.Index] {
+			// TODO(adonovan): opt: use word-parallel bitwise union.
+			if v := vb.dom; v.idom != u {
+				df.add(u, vb)
+			}
+		}
+	}
+}
+
+func buildDomFrontier(fn *Function) domFrontier {
+	df := make(domFrontier, len(fn.Blocks))
+	df.build(fn.Blocks[0])
+	if fn.Recover != nil {
+		df.build(fn.Recover)
+	}
+	return df
+}
+
+func removeInstr(refs []Instruction, instr Instruction) []Instruction {
+	i := 0
+	for _, ref := range refs {
+		if ref == instr {
+			continue
+		}
+		refs[i] = ref
+		i++
+	}
+	for j := i; j != len(refs); j++ {
+		refs[j] = nil // aid GC
+	}
+	return refs[:i]
+}
+
+// lift attempts to replace local and new Allocs accessed only with
+// load/store by SSA registers, inserting φ-nodes where necessary.
+// The result is a program in classical pruned SSA form.
+//
+// Preconditions:
+// - fn has no dead blocks (blockopt has run).
+// - Def/use info (Operands and Referrers) is up-to-date.
+// - The dominator tree is up-to-date.
+//
+func lift(fn *Function) {
+	// TODO(adonovan): opt: lots of little optimizations may be
+	// worthwhile here, especially if they cause us to avoid
+	// buildDomFrontier.  For example:
+	//
+	// - Alloc never loaded?  Eliminate.
+	// - Alloc never stored?  Replace all loads with a zero constant.
+	// - Alloc stored once?  Replace loads with dominating store;
+	//   don't forget that an Alloc is itself an effective store
+	//   of zero.
+	// - Alloc used only within a single block?
+	//   Use degenerate algorithm avoiding φ-nodes.
+	// - Consider synergy with scalar replacement of aggregates (SRA).
+	//   e.g. *(&x.f) where x is an Alloc.
+	//   Perhaps we'd get better results if we generated this as x.f
+	//   i.e. Field(x, .f) instead of Load(FieldIndex(x, .f)).
+	//   Unclear.
+	//
+	// But we will start with the simplest correct code.
+	df := buildDomFrontier(fn)
+
+	if debugLifting {
+		title := false
+		for i, blocks := range df {
+			if blocks != nil {
+				if !title {
+					fmt.Fprintf(os.Stderr, "Dominance frontier of %s:\n", fn)
+					title = true
+				}
+				fmt.Fprintf(os.Stderr, "\t%s: %s\n", fn.Blocks[i], blocks)
+			}
+		}
+	}
+
+	newPhis := make(newPhiMap)
+
+	// During this pass we will replace some BasicBlock.Instrs
+	// (allocs, loads and stores) with nil, keeping a count in
+	// BasicBlock.gaps.  At the end we will reset Instrs to the
+	// concatenation of all non-dead newPhis and non-nil Instrs
+	// for the block, reusing the original array if space permits.
+
+	// While we're here, we also eliminate 'rundefers'
+	// instructions in functions that contain no 'defer'
+	// instructions.
+	usesDefer := false
+
+	// Determine which allocs we can lift and number them densely.
+	// The renaming phase uses this numbering for compact maps.
+	numAllocs := 0
+	for _, b := range fn.Blocks {
+		b.gaps = 0
+		b.rundefers = 0
+		for _, instr := range b.Instrs {
+			switch instr := instr.(type) {
+			case *Alloc:
+				index := -1
+				if liftAlloc(df, instr, newPhis) {
+					index = numAllocs
+					numAllocs++
+				}
+				instr.index = index
+			case *Defer:
+				usesDefer = true
+			case *RunDefers:
+				b.rundefers++
+			}
+		}
+	}
+
+	// renaming maps an alloc (keyed by index) to its replacement
+	// value.  Initially the renaming contains nil, signifying the
+	// zero constant of the appropriate type; we construct the
+	// Const lazily at most once on each path through the domtree.
+	// TODO(adonovan): opt: cache per-function not per subtree.
+	renaming := make([]Value, numAllocs)
+
+	// Renaming.
+	rename(fn.Blocks[0], renaming, newPhis)
+
+	// Eliminate dead new phis, then prepend the live ones to each block.
+	for _, b := range fn.Blocks {
+
+		// Compress the newPhis slice to eliminate unused phis.
+		// TODO(adonovan): opt: compute liveness to avoid
+		// placing phis in blocks for which the alloc cell is
+		// not live.
+		nps := newPhis[b]
+		j := 0
+		for _, np := range nps {
+			if !phiIsLive(np.phi) {
+				// discard it, first removing it from referrers
+				for _, newval := range np.phi.Edges {
+					if refs := newval.Referrers(); refs != nil {
+						*refs = removeInstr(*refs, np.phi)
+					}
+				}
+				continue
+			}
+			nps[j] = np
+			j++
+		}
+		nps = nps[:j]
+
+		rundefersToKill := b.rundefers
+		if usesDefer {
+			rundefersToKill = 0
+		}
+
+		if j+b.gaps+rundefersToKill == 0 {
+			continue // fast path: no new phis or gaps
+		}
+
+		// Compact nps + non-nil Instrs into a new slice.
+		// TODO(adonovan): opt: compact in situ if there is
+		// sufficient space or slack in the slice.
+		dst := make([]Instruction, len(b.Instrs)+j-b.gaps-rundefersToKill)
+		for i, np := range nps {
+			dst[i] = np.phi
+		}
+		for _, instr := range b.Instrs {
+			if instr == nil {
+				continue
+			}
+			if !usesDefer {
+				if _, ok := instr.(*RunDefers); ok {
+					continue
+				}
+			}
+			dst[j] = instr
+			j++
+		}
+		for i, np := range nps {
+			dst[i] = np.phi
+		}
+		b.Instrs = dst
+	}
+
+	// Remove any fn.Locals that were lifted.
+	j := 0
+	for _, l := range fn.Locals {
+		if l.index < 0 {
+			fn.Locals[j] = l
+			j++
+		}
+	}
+	// Nil out fn.Locals[j:] to aid GC.
+	for i := j; i < len(fn.Locals); i++ {
+		fn.Locals[i] = nil
+	}
+	fn.Locals = fn.Locals[:j]
+}
+
+func phiIsLive(phi *Phi) bool {
+	for _, instr := range *phi.Referrers() {
+		if instr == phi {
+			continue // self-refs don't count
+		}
+		if _, ok := instr.(*DebugRef); ok {
+			continue // debug refs don't count
+		}
+		return true
+	}
+	return false
+}
+
+type blockSet struct{ big.Int } // (inherit methods from Int)
+
+// add adds b to the set and returns true if the set changed.
+func (s *blockSet) add(b *BasicBlock) bool {
+	i := b.Index
+	if s.Bit(i) != 0 {
+		return false
+	}
+	s.SetBit(&s.Int, i, 1)
+	return true
+}
+
+// take removes an arbitrary element from a set s and
+// returns its index, or returns -1 if empty.
+func (s *blockSet) take() int {
+	l := s.BitLen()
+	for i := 0; i < l; i++ {
+		if s.Bit(i) == 1 {
+			s.SetBit(&s.Int, i, 0)
+			return i
+		}
+	}
+	return -1
+}
+
+// newPhi is a pair of a newly introduced φ-node and the lifted Alloc
+// it replaces.
+type newPhi struct {
+	phi   *Phi
+	alloc *Alloc
+}
+
+// newPhiMap records for each basic block, the set of newPhis that
+// must be prepended to the block.
+type newPhiMap map[*BasicBlock][]newPhi
+
+// liftAlloc determines whether alloc can be lifted into registers,
+// and if so, it populates newPhis with all the φ-nodes it may require
+// and returns true.
+//
+func liftAlloc(df domFrontier, alloc *Alloc, newPhis newPhiMap) bool {
+	// Don't lift aggregates into registers, because we don't have
+	// a way to express their zero-constants.
+	switch deref(alloc.Type()).Underlying().(type) {
+	case *types.Array, *types.Struct:
+		return false
+	}
+
+	// Don't lift named return values in functions that defer
+	// calls that may recover from panic.
+	if fn := alloc.Parent(); fn.Recover != nil {
+		for _, nr := range fn.namedResults {
+			if nr == alloc {
+				return false
+			}
+		}
+	}
+
+	// Compute defblocks, the set of blocks containing a
+	// definition of the alloc cell.
+	var defblocks blockSet
+	for _, instr := range *alloc.Referrers() {
+		// Bail out if we discover the alloc is not liftable;
+		// the only operations permitted to use the alloc are
+		// loads/stores into the cell, and DebugRef.
+		switch instr := instr.(type) {
+		case *Store:
+			if instr.Val == alloc {
+				return false // address used as value
+			}
+			if instr.Addr != alloc {
+				panic("Alloc.Referrers is inconsistent")
+			}
+			defblocks.add(instr.Block())
+		case *UnOp:
+			if instr.Op != token.MUL {
+				return false // not a load
+			}
+			if instr.X != alloc {
+				panic("Alloc.Referrers is inconsistent")
+			}
+		case *DebugRef:
+			// ok
+		default:
+			return false // some other instruction
+		}
+	}
+	// The Alloc itself counts as a (zero) definition of the cell.
+	defblocks.add(alloc.Block())
+
+	if debugLifting {
+		fmt.Fprintln(os.Stderr, "\tlifting ", alloc, alloc.Name())
+	}
+
+	fn := alloc.Parent()
+
+	// Φ-insertion.
+	//
+	// What follows is the body of the main loop of the insert-φ
+	// function described by Cytron et al, but instead of using
+	// counter tricks, we just reset the 'hasAlready' and 'work'
+	// sets each iteration.  These are bitmaps so it's pretty cheap.
+	//
+	// TODO(adonovan): opt: recycle slice storage for W,
+	// hasAlready, defBlocks across liftAlloc calls.
+	var hasAlready blockSet
+
+	// Initialize W and work to defblocks.
+	var work blockSet = defblocks // blocks seen
+	var W blockSet                // blocks to do
+	W.Set(&defblocks.Int)
+
+	// Traverse iterated dominance frontier, inserting φ-nodes.
+	for i := W.take(); i != -1; i = W.take() {
+		u := fn.Blocks[i]
+		for _, v := range df[u.Index] {
+			if hasAlready.add(v) {
+				// Create φ-node.
+				// It will be prepended to v.Instrs later, if needed.
+				phi := &Phi{
+					Edges:   make([]Value, len(v.Preds)),
+					Comment: alloc.Comment,
+				}
+				phi.pos = alloc.Pos()
+				phi.setType(deref(alloc.Type()))
+				phi.block = v
+				if debugLifting {
+					fmt.Fprintf(os.Stderr, "\tplace %s = %s at block %s\n", phi.Name(), phi, v)
+				}
+				newPhis[v] = append(newPhis[v], newPhi{phi, alloc})
+
+				if work.add(v) {
+					W.add(v)
+				}
+			}
+		}
+	}
+
+	return true
+}
+
+// replaceAll replaces all intraprocedural uses of x with y,
+// updating x.Referrers and y.Referrers.
+// Precondition: x.Referrers() != nil, i.e. x must be local to some function.
+//
+func replaceAll(x, y Value) {
+	var rands []*Value
+	pxrefs := x.Referrers()
+	pyrefs := y.Referrers()
+	for _, instr := range *pxrefs {
+		rands = instr.Operands(rands[:0]) // recycle storage
+		for _, rand := range rands {
+			if *rand != nil {
+				if *rand == x {
+					*rand = y
+				}
+			}
+		}
+		if pyrefs != nil {
+			*pyrefs = append(*pyrefs, instr) // dups ok
+		}
+	}
+	*pxrefs = nil // x is now unreferenced
+}
+
+// renamed returns the value to which alloc is being renamed,
+// constructing it lazily if it's the implicit zero initialization.
+//
+func renamed(renaming []Value, alloc *Alloc) Value {
+	v := renaming[alloc.index]
+	if v == nil {
+		v = zeroConst(deref(alloc.Type()))
+		renaming[alloc.index] = v
+	}
+	return v
+}
+
+// rename implements the (Cytron et al) SSA renaming algorithm, a
+// preorder traversal of the dominator tree replacing all loads of
+// Alloc cells with the value stored to that cell by the dominating
+// store instruction.  For lifting, we need only consider loads,
+// stores and φ-nodes.
+//
+// renaming is a map from *Alloc (keyed by index number) to its
+// dominating stored value; newPhis[x] is the set of new φ-nodes to be
+// prepended to block x.
+//
+func rename(u *BasicBlock, renaming []Value, newPhis newPhiMap) {
+	// Each φ-node becomes the new name for its associated Alloc.
+	for _, np := range newPhis[u] {
+		phi := np.phi
+		alloc := np.alloc
+		renaming[alloc.index] = phi
+	}
+
+	// Rename loads and stores of allocs.
+	for i, instr := range u.Instrs {
+		switch instr := instr.(type) {
+		case *Alloc:
+			if instr.index >= 0 { // store of zero to Alloc cell
+				// Replace dominated loads by the zero value.
+				renaming[instr.index] = nil
+				if debugLifting {
+					fmt.Fprintf(os.Stderr, "\tkill alloc %s\n", instr)
+				}
+				// Delete the Alloc.
+				u.Instrs[i] = nil
+				u.gaps++
+			}
+
+		case *Store:
+			if alloc, ok := instr.Addr.(*Alloc); ok && alloc.index >= 0 { // store to Alloc cell
+				// Replace dominated loads by the stored value.
+				renaming[alloc.index] = instr.Val
+				if debugLifting {
+					fmt.Fprintf(os.Stderr, "\tkill store %s; new value: %s\n",
+						instr, instr.Val.Name())
+				}
+				// Remove the store from the referrer list of the stored value.
+				if refs := instr.Val.Referrers(); refs != nil {
+					*refs = removeInstr(*refs, instr)
+				}
+				// Delete the Store.
+				u.Instrs[i] = nil
+				u.gaps++
+			}
+
+		case *UnOp:
+			if instr.Op == token.MUL {
+				if alloc, ok := instr.X.(*Alloc); ok && alloc.index >= 0 { // load of Alloc cell
+					newval := renamed(renaming, alloc)
+					if debugLifting {
+						fmt.Fprintf(os.Stderr, "\tupdate load %s = %s with %s\n",
+							instr.Name(), instr, newval.Name())
+					}
+					// Replace all references to
+					// the loaded value by the
+					// dominating stored value.
+					replaceAll(instr, newval)
+					// Delete the Load.
+					u.Instrs[i] = nil
+					u.gaps++
+				}
+			}
+
+		case *DebugRef:
+			if alloc, ok := instr.X.(*Alloc); ok && alloc.index >= 0 { // ref of Alloc cell
+				if instr.IsAddr {
+					instr.X = renamed(renaming, alloc)
+					instr.IsAddr = false
+
+					// Add DebugRef to instr.X's referrers.
+					if refs := instr.X.Referrers(); refs != nil {
+						*refs = append(*refs, instr)
+					}
+				} else {
+					// A source expression denotes the address
+					// of an Alloc that was optimized away.
+					instr.X = nil
+
+					// Delete the DebugRef.
+					u.Instrs[i] = nil
+					u.gaps++
+				}
+			}
+		}
+	}
+
+	// For each φ-node in a CFG successor, rename the edge.
+	for _, v := range u.Succs {
+		phis := newPhis[v]
+		if len(phis) == 0 {
+			continue
+		}
+		i := v.predIndex(u)
+		for _, np := range phis {
+			phi := np.phi
+			alloc := np.alloc
+			newval := renamed(renaming, alloc)
+			if debugLifting {
+				fmt.Fprintf(os.Stderr, "\tsetphi %s edge %s -> %s (#%d) (alloc=%s) := %s\n",
+					phi.Name(), u, v, i, alloc.Name(), newval.Name())
+			}
+			phi.Edges[i] = newval
+			if prefs := newval.Referrers(); prefs != nil {
+				*prefs = append(*prefs, phi)
+			}
+		}
+	}
+
+	// Continue depth-first recursion over domtree, pushing a
+	// fresh copy of the renaming map for each subtree.
+	for _, v := range u.dom.children {
+		// TODO(adonovan): opt: avoid copy on final iteration; use destructive update.
+		r := make([]Value, len(renaming))
+		copy(r, renaming)
+		rename(v, r, newPhis)
+	}
+}
diff --git a/go/ssa/lvalue.go b/go/ssa/lvalue.go
new file mode 100644
index 0000000..4284b1c
--- /dev/null
+++ b/go/ssa/lvalue.go
@@ -0,0 +1,121 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssa
+
+// lvalues are the union of addressable expressions and map-index
+// expressions.
+
+import (
+	"go/ast"
+	"go/token"
+
+	"golang.org/x/tools/go/types"
+)
+
+// An lvalue represents an assignable location that may appear on the
+// left-hand side of an assignment.  This is a generalization of a
+// pointer to permit updates to elements of maps.
+//
+type lvalue interface {
+	store(fn *Function, v Value) // stores v into the location
+	load(fn *Function) Value     // loads the contents of the location
+	address(fn *Function) Value  // address of the location
+	typ() types.Type             // returns the type of the location
+}
+
+// An address is an lvalue represented by a true pointer.
+type address struct {
+	addr Value
+	pos  token.Pos // source position
+	expr ast.Expr  // source syntax of the value (not address) [debug mode]
+}
+
+func (a *address) load(fn *Function) Value {
+	load := emitLoad(fn, a.addr)
+	load.pos = a.pos
+	return load
+}
+
+func (a *address) store(fn *Function, v Value) {
+	store := emitStore(fn, a.addr, v, a.pos)
+	if a.expr != nil {
+		// store.Val is v, converted for assignability.
+		emitDebugRef(fn, a.expr, store.Val, false)
+	}
+}
+
+func (a *address) address(fn *Function) Value {
+	if a.expr != nil {
+		emitDebugRef(fn, a.expr, a.addr, true)
+	}
+	return a.addr
+}
+
+func (a *address) typ() types.Type {
+	return deref(a.addr.Type())
+}
+
+// An element is an lvalue represented by m[k], the location of an
+// element of a map or string.  These locations are not addressable
+// since pointers cannot be formed from them, but they do support
+// load(), and in the case of maps, store().
+//
+type element struct {
+	m, k Value      // map or string
+	t    types.Type // map element type or string byte type
+	pos  token.Pos  // source position of colon ({k:v}) or lbrack (m[k]=v)
+}
+
+func (e *element) load(fn *Function) Value {
+	l := &Lookup{
+		X:     e.m,
+		Index: e.k,
+	}
+	l.setPos(e.pos)
+	l.setType(e.t)
+	return fn.emit(l)
+}
+
+func (e *element) store(fn *Function, v Value) {
+	up := &MapUpdate{
+		Map:   e.m,
+		Key:   e.k,
+		Value: emitConv(fn, v, e.t),
+	}
+	up.pos = e.pos
+	fn.emit(up)
+}
+
+func (e *element) address(fn *Function) Value {
+	panic("map/string elements are not addressable")
+}
+
+func (e *element) typ() types.Type {
+	return e.t
+}
+
+// A blank is a dummy variable whose name is "_".
+// It is not reified: loads are illegal and stores are ignored.
+//
+type blank struct{}
+
+func (bl blank) load(fn *Function) Value {
+	panic("blank.load is illegal")
+}
+
+func (bl blank) store(fn *Function, v Value) {
+	// no-op
+}
+
+func (bl blank) address(fn *Function) Value {
+	panic("blank var is not addressable")
+}
+
+func (bl blank) typ() types.Type {
+	// This should be the type of the blank Ident; the typechecker
+	// doesn't provide this yet, but fortunately, we don't need it
+	// yet either.
+	panic("blank.typ is unimplemented")
+}
diff --git a/go/ssa/methods.go b/go/ssa/methods.go
new file mode 100644
index 0000000..12534de
--- /dev/null
+++ b/go/ssa/methods.go
@@ -0,0 +1,243 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssa
+
+// This file defines utilities for population of method sets.
+
+import (
+	"fmt"
+
+	"golang.org/x/tools/go/types"
+)
+
+// Method returns the Function implementing method sel, building
+// wrapper methods on demand.  It returns nil if sel denotes an
+// abstract (interface) method.
+//
+// Precondition: sel.Kind() == MethodVal.
+//
+// TODO(adonovan): rename this to MethodValue because of the
+// precondition, and for consistency with functions in source.go.
+//
+// Thread-safe.
+//
+// EXCLUSIVE_LOCKS_ACQUIRED(prog.methodsMu)
+//
+func (prog *Program) Method(sel *types.Selection) *Function {
+	if sel.Kind() != types.MethodVal {
+		panic(fmt.Sprintf("Method(%s) kind != MethodVal", sel))
+	}
+	T := sel.Recv()
+	if isInterface(T) {
+		return nil // abstract method
+	}
+	if prog.mode&LogSource != 0 {
+		defer logStack("Method %s %v", T, sel)()
+	}
+
+	prog.methodsMu.Lock()
+	defer prog.methodsMu.Unlock()
+
+	return prog.addMethod(prog.createMethodSet(T), sel)
+}
+
+// LookupMethod returns the implementation of the method of type T
+// identified by (pkg, name).  It returns nil if the method exists but
+// is abstract, and panics if T has no such method.
+//
+func (prog *Program) LookupMethod(T types.Type, pkg *types.Package, name string) *Function {
+	sel := prog.MethodSets.MethodSet(T).Lookup(pkg, name)
+	if sel == nil {
+		panic(fmt.Sprintf("%s has no method %s", T, types.Id(pkg, name)))
+	}
+	return prog.Method(sel)
+}
+
+// methodSet contains the (concrete) methods of a non-interface type.
+type methodSet struct {
+	mapping  map[string]*Function // populated lazily
+	complete bool                 // mapping contains all methods
+}
+
+// Precondition: !isInterface(T).
+// EXCLUSIVE_LOCKS_REQUIRED(prog.methodsMu)
+func (prog *Program) createMethodSet(T types.Type) *methodSet {
+	mset, ok := prog.methodSets.At(T).(*methodSet)
+	if !ok {
+		mset = &methodSet{mapping: make(map[string]*Function)}
+		prog.methodSets.Set(T, mset)
+	}
+	return mset
+}
+
+// EXCLUSIVE_LOCKS_REQUIRED(prog.methodsMu)
+func (prog *Program) addMethod(mset *methodSet, sel *types.Selection) *Function {
+	if sel.Kind() == types.MethodExpr {
+		panic(sel)
+	}
+	id := sel.Obj().Id()
+	fn := mset.mapping[id]
+	if fn == nil {
+		obj := sel.Obj().(*types.Func)
+
+		needsPromotion := len(sel.Index()) > 1
+		needsIndirection := !isPointer(recvType(obj)) && isPointer(sel.Recv())
+		if needsPromotion || needsIndirection {
+			fn = makeWrapper(prog, sel)
+		} else {
+			fn = prog.declaredFunc(obj)
+		}
+		if fn.Signature.Recv() == nil {
+			panic(fn) // missing receiver
+		}
+		mset.mapping[id] = fn
+	}
+	return fn
+}
+
+// RuntimeTypes returns a new unordered slice containing all
+// concrete types in the program for which a complete (non-empty)
+// method set is required at run-time.
+//
+// Thread-safe.
+//
+// EXCLUSIVE_LOCKS_ACQUIRED(prog.methodsMu)
+//
+func (prog *Program) RuntimeTypes() []types.Type {
+	prog.methodsMu.Lock()
+	defer prog.methodsMu.Unlock()
+
+	var res []types.Type
+	prog.methodSets.Iterate(func(T types.Type, v interface{}) {
+		if v.(*methodSet).complete {
+			res = append(res, T)
+		}
+	})
+	return res
+}
+
+// declaredFunc returns the concrete function/method denoted by obj.
+// Panic ensues if there is none.
+//
+func (prog *Program) declaredFunc(obj *types.Func) *Function {
+	if v := prog.packageLevelValue(obj); v != nil {
+		return v.(*Function)
+	}
+	panic("no concrete method: " + obj.String())
+}
+
+// needMethodsOf ensures that runtime type information (including the
+// complete method set) is available for the specified type T and all
+// its subcomponents.
+//
+// needMethodsOf must be called for at least every type that is an
+// operand of some MakeInterface instruction, and for the type of
+// every exported package member.
+//
+// Precondition: T is not a method signature (*Signature with Recv()!=nil).
+//
+// Thread-safe.  (Called via emitConv from multiple builder goroutines.)
+//
+// TODO(adonovan): make this faster.  It accounts for 20% of SSA build time.
+//
+// EXCLUSIVE_LOCKS_ACQUIRED(prog.methodsMu)
+//
+func (prog *Program) needMethodsOf(T types.Type) {
+	prog.methodsMu.Lock()
+	prog.needMethods(T, false)
+	prog.methodsMu.Unlock()
+}
+
+// Precondition: T is not a method signature (*Signature with Recv()!=nil).
+// Recursive case: skip => don't create methods for T.
+//
+// EXCLUSIVE_LOCKS_REQUIRED(prog.methodsMu)
+//
+func (prog *Program) needMethods(T types.Type, skip bool) {
+	// Each package maintains its own set of types it has visited.
+	if prevSkip, ok := prog.runtimeTypes.At(T).(bool); ok {
+		// needMethods(T) was previously called
+		if !prevSkip || skip {
+			return // already seen, with same or false 'skip' value
+		}
+	}
+	prog.runtimeTypes.Set(T, skip)
+
+	tmset := prog.MethodSets.MethodSet(T)
+
+	if !skip && !isInterface(T) && tmset.Len() > 0 {
+		// Create methods of T.
+		mset := prog.createMethodSet(T)
+		if !mset.complete {
+			mset.complete = true
+			n := tmset.Len()
+			for i := 0; i < n; i++ {
+				prog.addMethod(mset, tmset.At(i))
+			}
+		}
+	}
+
+	// Recursion over signatures of each method.
+	for i := 0; i < tmset.Len(); i++ {
+		sig := tmset.At(i).Type().(*types.Signature)
+		prog.needMethods(sig.Params(), false)
+		prog.needMethods(sig.Results(), false)
+	}
+
+	switch t := T.(type) {
+	case *types.Basic:
+		// nop
+
+	case *types.Interface:
+		// nop---handled by recursion over method set.
+
+	case *types.Pointer:
+		prog.needMethods(t.Elem(), false)
+
+	case *types.Slice:
+		prog.needMethods(t.Elem(), false)
+
+	case *types.Chan:
+		prog.needMethods(t.Elem(), false)
+
+	case *types.Map:
+		prog.needMethods(t.Key(), false)
+		prog.needMethods(t.Elem(), false)
+
+	case *types.Signature:
+		if t.Recv() != nil {
+			panic(fmt.Sprintf("Signature %s has Recv %s", t, t.Recv()))
+		}
+		prog.needMethods(t.Params(), false)
+		prog.needMethods(t.Results(), false)
+
+	case *types.Named:
+		// A pointer-to-named type can be derived from a named
+		// type via reflection.  It may have methods too.
+		prog.needMethods(types.NewPointer(T), false)
+
+		// Consider 'type T struct{S}' where S has methods.
+		// Reflection provides no way to get from T to struct{S},
+		// only to S, so the method set of struct{S} is unwanted,
+		// so set 'skip' flag during recursion.
+		prog.needMethods(t.Underlying(), true)
+
+	case *types.Array:
+		prog.needMethods(t.Elem(), false)
+
+	case *types.Struct:
+		for i, n := 0, t.NumFields(); i < n; i++ {
+			prog.needMethods(t.Field(i).Type(), false)
+		}
+
+	case *types.Tuple:
+		for i, n := 0, t.Len(); i < n; i++ {
+			prog.needMethods(t.At(i).Type(), false)
+		}
+
+	default:
+		panic(T)
+	}
+}
diff --git a/go/ssa/mode.go b/go/ssa/mode.go
new file mode 100644
index 0000000..bbd613a
--- /dev/null
+++ b/go/ssa/mode.go
@@ -0,0 +1,107 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssa
+
+// This file defines the BuilderMode type and its command-line flag.
+
+import (
+	"bytes"
+	"flag"
+	"fmt"
+)
+
+// BuilderMode is a bitmask of options for diagnostics and checking.
+type BuilderMode uint
+
+const (
+	PrintPackages        BuilderMode = 1 << iota // Print package inventory to stdout
+	PrintFunctions                               // Print function SSA code to stdout
+	LogSource                                    // Log source locations as SSA builder progresses
+	SanityCheckFunctions                         // Perform sanity checking of function bodies
+	NaiveForm                                    // Build naïve SSA form: don't replace local loads/stores with registers
+	BuildSerially                                // Build packages serially, not in parallel.
+	GlobalDebug                                  // Enable debug info for all packages
+	BareInits                                    // Build init functions without guards or calls to dependent inits
+)
+
+const modeFlagUsage = `Options controlling the SSA builder.
+The value is a sequence of zero or more of these letters:
+C	perform sanity [C]hecking of the SSA form.
+D	include [D]ebug info for every function.
+P	print [P]ackage inventory.
+F	print [F]unction SSA code.
+S	log [S]ource locations as SSA builder progresses.
+L	build distinct packages seria[L]ly instead of in parallel.
+N	build [N]aive SSA form: don't replace local loads/stores with registers.
+I	build bare [I]nit functions: no init guards or calls to dependent inits.
+`
+
+// BuilderModeFlag creates a new command line flag of type BuilderMode,
+// adds it to the specified flag set, and returns it.
+//
+// Example:
+// 	var ssabuild = BuilderModeFlag(flag.CommandLine, "ssabuild", 0)
+//
+func BuilderModeFlag(set *flag.FlagSet, name string, value BuilderMode) *BuilderMode {
+	set.Var((*builderModeValue)(&value), name, modeFlagUsage)
+	return &value
+}
+
+type builderModeValue BuilderMode // satisfies flag.Value and flag.Getter.
+
+func (v *builderModeValue) Set(s string) error {
+	var mode BuilderMode
+	for _, c := range s {
+		switch c {
+		case 'D':
+			mode |= GlobalDebug
+		case 'P':
+			mode |= PrintPackages
+		case 'F':
+			mode |= PrintFunctions
+		case 'S':
+			mode |= LogSource | BuildSerially
+		case 'C':
+			mode |= SanityCheckFunctions
+		case 'N':
+			mode |= NaiveForm
+		case 'L':
+			mode |= BuildSerially
+		default:
+			return fmt.Errorf("unknown BuilderMode option: %q", c)
+		}
+	}
+	*v = builderModeValue(mode)
+	return nil
+}
+
+func (v *builderModeValue) Get() interface{} { return BuilderMode(*v) }
+
+func (v *builderModeValue) String() string {
+	mode := BuilderMode(*v)
+	var buf bytes.Buffer
+	if mode&GlobalDebug != 0 {
+		buf.WriteByte('D')
+	}
+	if mode&PrintPackages != 0 {
+		buf.WriteByte('P')
+	}
+	if mode&PrintFunctions != 0 {
+		buf.WriteByte('F')
+	}
+	if mode&LogSource != 0 {
+		buf.WriteByte('S')
+	}
+	if mode&SanityCheckFunctions != 0 {
+		buf.WriteByte('C')
+	}
+	if mode&NaiveForm != 0 {
+		buf.WriteByte('N')
+	}
+	if mode&BuildSerially != 0 {
+		buf.WriteByte('L')
+	}
+	return buf.String()
+}
diff --git a/go/ssa/print.go b/go/ssa/print.go
new file mode 100644
index 0000000..88c31f6
--- /dev/null
+++ b/go/ssa/print.go
@@ -0,0 +1,427 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssa
+
+// This file implements the String() methods for all Value and
+// Instruction types.
+
+import (
+	"bytes"
+	"fmt"
+	"io"
+	"reflect"
+	"sort"
+
+	"golang.org/x/tools/go/types"
+	"golang.org/x/tools/go/types/typeutil"
+)
+
+// relName returns the name of v relative to i.
+// In most cases, this is identical to v.Name(), but references to
+// Functions (including methods) and Globals use RelString and
+// all types are displayed with relType, so that only cross-package
+// references are package-qualified.
+//
+func relName(v Value, i Instruction) string {
+	var from *types.Package
+	if i != nil {
+		from = i.Parent().pkgobj()
+	}
+	switch v := v.(type) {
+	case Member: // *Function or *Global
+		return v.RelString(from)
+	case *Const:
+		return v.RelString(from)
+	}
+	return v.Name()
+}
+
+func relType(t types.Type, from *types.Package) string {
+	return types.TypeString(t, types.RelativeTo(from))
+}
+
+func relString(m Member, from *types.Package) string {
+	// NB: not all globals have an Object (e.g. init$guard),
+	// so use Package().Object not Object.Package().
+	if obj := m.Package().Object; obj != nil && obj != from {
+		return fmt.Sprintf("%s.%s", obj.Path(), m.Name())
+	}
+	return m.Name()
+}
+
+// Value.String()
+//
+// This method is provided only for debugging.
+// It never appears in disassembly, which uses Value.Name().
+
+func (v *Parameter) String() string {
+	from := v.Parent().pkgobj()
+	return fmt.Sprintf("parameter %s : %s", v.Name(), relType(v.Type(), from))
+}
+
+func (v *FreeVar) String() string {
+	from := v.Parent().pkgobj()
+	return fmt.Sprintf("freevar %s : %s", v.Name(), relType(v.Type(), from))
+}
+
+func (v *Builtin) String() string {
+	return fmt.Sprintf("builtin %s", v.Name())
+}
+
+// Instruction.String()
+
+func (v *Alloc) String() string {
+	op := "local"
+	if v.Heap {
+		op = "new"
+	}
+	from := v.Parent().pkgobj()
+	return fmt.Sprintf("%s %s (%s)", op, relType(deref(v.Type()), from), v.Comment)
+}
+
+func (v *Phi) String() string {
+	var b bytes.Buffer
+	b.WriteString("phi [")
+	for i, edge := range v.Edges {
+		if i > 0 {
+			b.WriteString(", ")
+		}
+		// Be robust against malformed CFG.
+		block := -1
+		if v.block != nil && i < len(v.block.Preds) {
+			block = v.block.Preds[i].Index
+		}
+		fmt.Fprintf(&b, "%d: ", block)
+		edgeVal := "<nil>" // be robust
+		if edge != nil {
+			edgeVal = relName(edge, v)
+		}
+		b.WriteString(edgeVal)
+	}
+	b.WriteString("]")
+	if v.Comment != "" {
+		b.WriteString(" #")
+		b.WriteString(v.Comment)
+	}
+	return b.String()
+}
+
+func printCall(v *CallCommon, prefix string, instr Instruction) string {
+	var b bytes.Buffer
+	b.WriteString(prefix)
+	if !v.IsInvoke() {
+		b.WriteString(relName(v.Value, instr))
+	} else {
+		fmt.Fprintf(&b, "invoke %s.%s", relName(v.Value, instr), v.Method.Name())
+	}
+	b.WriteString("(")
+	for i, arg := range v.Args {
+		if i > 0 {
+			b.WriteString(", ")
+		}
+		b.WriteString(relName(arg, instr))
+	}
+	if v.Signature().Variadic() {
+		b.WriteString("...")
+	}
+	b.WriteString(")")
+	return b.String()
+}
+
+func (c *CallCommon) String() string {
+	return printCall(c, "", nil)
+}
+
+func (v *Call) String() string {
+	return printCall(&v.Call, "", v)
+}
+
+func (v *BinOp) String() string {
+	return fmt.Sprintf("%s %s %s", relName(v.X, v), v.Op.String(), relName(v.Y, v))
+}
+
+func (v *UnOp) String() string {
+	return fmt.Sprintf("%s%s%s", v.Op, relName(v.X, v), commaOk(v.CommaOk))
+}
+
+func printConv(prefix string, v, x Value) string {
+	from := v.Parent().pkgobj()
+	return fmt.Sprintf("%s %s <- %s (%s)",
+		prefix,
+		relType(v.Type(), from),
+		relType(x.Type(), from),
+		relName(x, v.(Instruction)))
+}
+
+func (v *ChangeType) String() string      { return printConv("changetype", v, v.X) }
+func (v *Convert) String() string         { return printConv("convert", v, v.X) }
+func (v *ChangeInterface) String() string { return printConv("change interface", v, v.X) }
+func (v *MakeInterface) String() string   { return printConv("make", v, v.X) }
+
+func (v *MakeClosure) String() string {
+	var b bytes.Buffer
+	fmt.Fprintf(&b, "make closure %s", relName(v.Fn, v))
+	if v.Bindings != nil {
+		b.WriteString(" [")
+		for i, c := range v.Bindings {
+			if i > 0 {
+				b.WriteString(", ")
+			}
+			b.WriteString(relName(c, v))
+		}
+		b.WriteString("]")
+	}
+	return b.String()
+}
+
+func (v *MakeSlice) String() string {
+	from := v.Parent().pkgobj()
+	return fmt.Sprintf("make %s %s %s",
+		relType(v.Type(), from),
+		relName(v.Len, v),
+		relName(v.Cap, v))
+}
+
+func (v *Slice) String() string {
+	var b bytes.Buffer
+	b.WriteString("slice ")
+	b.WriteString(relName(v.X, v))
+	b.WriteString("[")
+	if v.Low != nil {
+		b.WriteString(relName(v.Low, v))
+	}
+	b.WriteString(":")
+	if v.High != nil {
+		b.WriteString(relName(v.High, v))
+	}
+	if v.Max != nil {
+		b.WriteString(":")
+		b.WriteString(relName(v.Max, v))
+	}
+	b.WriteString("]")
+	return b.String()
+}
+
+func (v *MakeMap) String() string {
+	res := ""
+	if v.Reserve != nil {
+		res = relName(v.Reserve, v)
+	}
+	from := v.Parent().pkgobj()
+	return fmt.Sprintf("make %s %s", relType(v.Type(), from), res)
+}
+
+func (v *MakeChan) String() string {
+	from := v.Parent().pkgobj()
+	return fmt.Sprintf("make %s %s", relType(v.Type(), from), relName(v.Size, v))
+}
+
+func (v *FieldAddr) String() string {
+	st := deref(v.X.Type()).Underlying().(*types.Struct)
+	// Be robust against a bad index.
+	name := "?"
+	if 0 <= v.Field && v.Field < st.NumFields() {
+		name = st.Field(v.Field).Name()
+	}
+	return fmt.Sprintf("&%s.%s [#%d]", relName(v.X, v), name, v.Field)
+}
+
+func (v *Field) String() string {
+	st := v.X.Type().Underlying().(*types.Struct)
+	// Be robust against a bad index.
+	name := "?"
+	if 0 <= v.Field && v.Field < st.NumFields() {
+		name = st.Field(v.Field).Name()
+	}
+	return fmt.Sprintf("%s.%s [#%d]", relName(v.X, v), name, v.Field)
+}
+
+func (v *IndexAddr) String() string {
+	return fmt.Sprintf("&%s[%s]", relName(v.X, v), relName(v.Index, v))
+}
+
+func (v *Index) String() string {
+	return fmt.Sprintf("%s[%s]", relName(v.X, v), relName(v.Index, v))
+}
+
+func (v *Lookup) String() string {
+	return fmt.Sprintf("%s[%s]%s", relName(v.X, v), relName(v.Index, v), commaOk(v.CommaOk))
+}
+
+func (v *Range) String() string {
+	return "range " + relName(v.X, v)
+}
+
+func (v *Next) String() string {
+	return "next " + relName(v.Iter, v)
+}
+
+func (v *TypeAssert) String() string {
+	from := v.Parent().pkgobj()
+	return fmt.Sprintf("typeassert%s %s.(%s)", commaOk(v.CommaOk), relName(v.X, v), relType(v.AssertedType, from))
+}
+
+func (v *Extract) String() string {
+	return fmt.Sprintf("extract %s #%d", relName(v.Tuple, v), v.Index)
+}
+
+func (s *Jump) String() string {
+	// Be robust against malformed CFG.
+	block := -1
+	if s.block != nil && len(s.block.Succs) == 1 {
+		block = s.block.Succs[0].Index
+	}
+	return fmt.Sprintf("jump %d", block)
+}
+
+func (s *If) String() string {
+	// Be robust against malformed CFG.
+	tblock, fblock := -1, -1
+	if s.block != nil && len(s.block.Succs) == 2 {
+		tblock = s.block.Succs[0].Index
+		fblock = s.block.Succs[1].Index
+	}
+	return fmt.Sprintf("if %s goto %d else %d", relName(s.Cond, s), tblock, fblock)
+}
+
+func (s *Go) String() string {
+	return printCall(&s.Call, "go ", s)
+}
+
+func (s *Panic) String() string {
+	return "panic " + relName(s.X, s)
+}
+
+func (s *Return) String() string {
+	var b bytes.Buffer
+	b.WriteString("return")
+	for i, r := range s.Results {
+		if i == 0 {
+			b.WriteString(" ")
+		} else {
+			b.WriteString(", ")
+		}
+		b.WriteString(relName(r, s))
+	}
+	return b.String()
+}
+
+func (*RunDefers) String() string {
+	return "rundefers"
+}
+
+func (s *Send) String() string {
+	return fmt.Sprintf("send %s <- %s", relName(s.Chan, s), relName(s.X, s))
+}
+
+func (s *Defer) String() string {
+	return printCall(&s.Call, "defer ", s)
+}
+
+func (s *Select) String() string {
+	var b bytes.Buffer
+	for i, st := range s.States {
+		if i > 0 {
+			b.WriteString(", ")
+		}
+		if st.Dir == types.RecvOnly {
+			b.WriteString("<-")
+			b.WriteString(relName(st.Chan, s))
+		} else {
+			b.WriteString(relName(st.Chan, s))
+			b.WriteString("<-")
+			b.WriteString(relName(st.Send, s))
+		}
+	}
+	non := ""
+	if !s.Blocking {
+		non = "non"
+	}
+	return fmt.Sprintf("select %sblocking [%s]", non, b.String())
+}
+
+func (s *Store) String() string {
+	return fmt.Sprintf("*%s = %s", relName(s.Addr, s), relName(s.Val, s))
+}
+
+func (s *MapUpdate) String() string {
+	return fmt.Sprintf("%s[%s] = %s", relName(s.Map, s), relName(s.Key, s), relName(s.Value, s))
+}
+
+func (s *DebugRef) String() string {
+	p := s.Parent().Prog.Fset.Position(s.Pos())
+	var descr interface{}
+	if s.object != nil {
+		descr = s.object // e.g. "var x int"
+	} else {
+		descr = reflect.TypeOf(s.Expr) // e.g. "*ast.CallExpr"
+	}
+	var addr string
+	if s.IsAddr {
+		addr = "address of "
+	}
+	return fmt.Sprintf("; %s%s @ %d:%d is %s", addr, descr, p.Line, p.Column, s.X.Name())
+}
+
+func (p *Package) String() string {
+	return "package " + p.Object.Path()
+}
+
+var _ io.WriterTo = (*Package)(nil) // *Package implements io.Writer
+
+func (p *Package) WriteTo(w io.Writer) (int64, error) {
+	var buf bytes.Buffer
+	WritePackage(&buf, p)
+	n, err := w.Write(buf.Bytes())
+	return int64(n), err
+}
+
+// WritePackage writes to buf a human-readable summary of p.
+func WritePackage(buf *bytes.Buffer, p *Package) {
+	fmt.Fprintf(buf, "%s:\n", p)
+
+	var names []string
+	maxname := 0
+	for name := range p.Members {
+		if l := len(name); l > maxname {
+			maxname = l
+		}
+		names = append(names, name)
+	}
+
+	from := p.Object
+	sort.Strings(names)
+	for _, name := range names {
+		switch mem := p.Members[name].(type) {
+		case *NamedConst:
+			fmt.Fprintf(buf, "  const %-*s %s = %s\n",
+				maxname, name, mem.Name(), mem.Value.RelString(from))
+
+		case *Function:
+			fmt.Fprintf(buf, "  func  %-*s %s\n",
+				maxname, name, relType(mem.Type(), from))
+
+		case *Type:
+			fmt.Fprintf(buf, "  type  %-*s %s\n",
+				maxname, name, relType(mem.Type().Underlying(), from))
+			for _, meth := range typeutil.IntuitiveMethodSet(mem.Type(), &p.Prog.MethodSets) {
+				fmt.Fprintf(buf, "    %s\n", types.SelectionString(meth, types.RelativeTo(from)))
+			}
+
+		case *Global:
+			fmt.Fprintf(buf, "  var   %-*s %s\n",
+				maxname, name, relType(mem.Type().(*types.Pointer).Elem(), from))
+		}
+	}
+
+	fmt.Fprintf(buf, "\n")
+}
+
+func commaOk(x bool) string {
+	if x {
+		return ",ok"
+	}
+	return ""
+}
diff --git a/go/ssa/sanity.go b/go/ssa/sanity.go
new file mode 100644
index 0000000..b0593d0
--- /dev/null
+++ b/go/ssa/sanity.go
@@ -0,0 +1,520 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssa
+
+// An optional pass for sanity-checking invariants of the SSA representation.
+// Currently it checks CFG invariants but little at the instruction level.
+
+import (
+	"fmt"
+	"io"
+	"os"
+	"strings"
+
+	"golang.org/x/tools/go/types"
+)
+
+type sanity struct {
+	reporter io.Writer
+	fn       *Function
+	block    *BasicBlock
+	instrs   map[Instruction]struct{}
+	insane   bool
+}
+
+// sanityCheck performs integrity checking of the SSA representation
+// of the function fn and returns true if it was valid.  Diagnostics
+// are written to reporter if non-nil, os.Stderr otherwise.  Some
+// diagnostics are only warnings and do not imply a negative result.
+//
+// Sanity-checking is intended to facilitate the debugging of code
+// transformation passes.
+//
+func sanityCheck(fn *Function, reporter io.Writer) bool {
+	if reporter == nil {
+		reporter = os.Stderr
+	}
+	return (&sanity{reporter: reporter}).checkFunction(fn)
+}
+
+// mustSanityCheck is like sanityCheck but panics instead of returning
+// a negative result.
+//
+func mustSanityCheck(fn *Function, reporter io.Writer) {
+	if !sanityCheck(fn, reporter) {
+		fn.WriteTo(os.Stderr)
+		panic("SanityCheck failed")
+	}
+}
+
+func (s *sanity) diagnostic(prefix, format string, args ...interface{}) {
+	fmt.Fprintf(s.reporter, "%s: function %s", prefix, s.fn)
+	if s.block != nil {
+		fmt.Fprintf(s.reporter, ", block %s", s.block)
+	}
+	io.WriteString(s.reporter, ": ")
+	fmt.Fprintf(s.reporter, format, args...)
+	io.WriteString(s.reporter, "\n")
+}
+
+func (s *sanity) errorf(format string, args ...interface{}) {
+	s.insane = true
+	s.diagnostic("Error", format, args...)
+}
+
+func (s *sanity) warnf(format string, args ...interface{}) {
+	s.diagnostic("Warning", format, args...)
+}
+
+// findDuplicate returns an arbitrary basic block that appeared more
+// than once in blocks, or nil if all were unique.
+func findDuplicate(blocks []*BasicBlock) *BasicBlock {
+	if len(blocks) < 2 {
+		return nil
+	}
+	if blocks[0] == blocks[1] {
+		return blocks[0]
+	}
+	// Slow path:
+	m := make(map[*BasicBlock]bool)
+	for _, b := range blocks {
+		if m[b] {
+			return b
+		}
+		m[b] = true
+	}
+	return nil
+}
+
+func (s *sanity) checkInstr(idx int, instr Instruction) {
+	switch instr := instr.(type) {
+	case *If, *Jump, *Return, *Panic:
+		s.errorf("control flow instruction not at end of block")
+	case *Phi:
+		if idx == 0 {
+			// It suffices to apply this check to just the first phi node.
+			if dup := findDuplicate(s.block.Preds); dup != nil {
+				s.errorf("phi node in block with duplicate predecessor %s", dup)
+			}
+		} else {
+			prev := s.block.Instrs[idx-1]
+			if _, ok := prev.(*Phi); !ok {
+				s.errorf("Phi instruction follows a non-Phi: %T", prev)
+			}
+		}
+		if ne, np := len(instr.Edges), len(s.block.Preds); ne != np {
+			s.errorf("phi node has %d edges but %d predecessors", ne, np)
+
+		} else {
+			for i, e := range instr.Edges {
+				if e == nil {
+					s.errorf("phi node '%s' has no value for edge #%d from %s", instr.Comment, i, s.block.Preds[i])
+				}
+			}
+		}
+
+	case *Alloc:
+		if !instr.Heap {
+			found := false
+			for _, l := range s.fn.Locals {
+				if l == instr {
+					found = true
+					break
+				}
+			}
+			if !found {
+				s.errorf("local alloc %s = %s does not appear in Function.Locals", instr.Name(), instr)
+			}
+		}
+
+	case *BinOp:
+	case *Call:
+	case *ChangeInterface:
+	case *ChangeType:
+	case *Convert:
+		if _, ok := instr.X.Type().Underlying().(*types.Basic); !ok {
+			if _, ok := instr.Type().Underlying().(*types.Basic); !ok {
+				s.errorf("convert %s -> %s: at least one type must be basic", instr.X.Type(), instr.Type())
+			}
+		}
+
+	case *Defer:
+	case *Extract:
+	case *Field:
+	case *FieldAddr:
+	case *Go:
+	case *Index:
+	case *IndexAddr:
+	case *Lookup:
+	case *MakeChan:
+	case *MakeClosure:
+		numFree := len(instr.Fn.(*Function).FreeVars)
+		numBind := len(instr.Bindings)
+		if numFree != numBind {
+			s.errorf("MakeClosure has %d Bindings for function %s with %d free vars",
+				numBind, instr.Fn, numFree)
+
+		}
+		if recv := instr.Type().(*types.Signature).Recv(); recv != nil {
+			s.errorf("MakeClosure's type includes receiver %s", recv.Type())
+		}
+
+	case *MakeInterface:
+	case *MakeMap:
+	case *MakeSlice:
+	case *MapUpdate:
+	case *Next:
+	case *Range:
+	case *RunDefers:
+	case *Select:
+	case *Send:
+	case *Slice:
+	case *Store:
+	case *TypeAssert:
+	case *UnOp:
+	case *DebugRef:
+		// TODO(adonovan): implement checks.
+	default:
+		panic(fmt.Sprintf("Unknown instruction type: %T", instr))
+	}
+
+	if call, ok := instr.(CallInstruction); ok {
+		if call.Common().Signature() == nil {
+			s.errorf("nil signature: %s", call)
+		}
+	}
+
+	// Check that value-defining instructions have valid types
+	// and a valid referrer list.
+	if v, ok := instr.(Value); ok {
+		t := v.Type()
+		if t == nil {
+			s.errorf("no type: %s = %s", v.Name(), v)
+		} else if t == tRangeIter {
+			// not a proper type; ignore.
+		} else if b, ok := t.Underlying().(*types.Basic); ok && b.Info()&types.IsUntyped != 0 {
+			s.errorf("instruction has 'untyped' result: %s = %s : %s", v.Name(), v, t)
+		}
+		s.checkReferrerList(v)
+	}
+
+	// Untyped constants are legal as instruction Operands(),
+	// for example:
+	//   _ = "foo"[0]
+	// or:
+	//   if wordsize==64 {...}
+
+	// All other non-Instruction Values can be found via their
+	// enclosing Function or Package.
+}
+
+func (s *sanity) checkFinalInstr(idx int, instr Instruction) {
+	switch instr := instr.(type) {
+	case *If:
+		if nsuccs := len(s.block.Succs); nsuccs != 2 {
+			s.errorf("If-terminated block has %d successors; expected 2", nsuccs)
+			return
+		}
+		if s.block.Succs[0] == s.block.Succs[1] {
+			s.errorf("If-instruction has same True, False target blocks: %s", s.block.Succs[0])
+			return
+		}
+
+	case *Jump:
+		if nsuccs := len(s.block.Succs); nsuccs != 1 {
+			s.errorf("Jump-terminated block has %d successors; expected 1", nsuccs)
+			return
+		}
+
+	case *Return:
+		if nsuccs := len(s.block.Succs); nsuccs != 0 {
+			s.errorf("Return-terminated block has %d successors; expected none", nsuccs)
+			return
+		}
+		if na, nf := len(instr.Results), s.fn.Signature.Results().Len(); nf != na {
+			s.errorf("%d-ary return in %d-ary function", na, nf)
+		}
+
+	case *Panic:
+		if nsuccs := len(s.block.Succs); nsuccs != 0 {
+			s.errorf("Panic-terminated block has %d successors; expected none", nsuccs)
+			return
+		}
+
+	default:
+		s.errorf("non-control flow instruction at end of block")
+	}
+}
+
+func (s *sanity) checkBlock(b *BasicBlock, index int) {
+	s.block = b
+
+	if b.Index != index {
+		s.errorf("block has incorrect Index %d", b.Index)
+	}
+	if b.parent != s.fn {
+		s.errorf("block has incorrect parent %s", b.parent)
+	}
+
+	// Check all blocks are reachable.
+	// (The entry block is always implicitly reachable,
+	// as is the Recover block, if any.)
+	if (index > 0 && b != b.parent.Recover) && len(b.Preds) == 0 {
+		s.warnf("unreachable block")
+		if b.Instrs == nil {
+			// Since this block is about to be pruned,
+			// tolerating transient problems in it
+			// simplifies other optimizations.
+			return
+		}
+	}
+
+	// Check predecessor and successor relations are dual,
+	// and that all blocks in CFG belong to same function.
+	for _, a := range b.Preds {
+		found := false
+		for _, bb := range a.Succs {
+			if bb == b {
+				found = true
+				break
+			}
+		}
+		if !found {
+			s.errorf("expected successor edge in predecessor %s; found only: %s", a, a.Succs)
+		}
+		if a.parent != s.fn {
+			s.errorf("predecessor %s belongs to different function %s", a, a.parent)
+		}
+	}
+	for _, c := range b.Succs {
+		found := false
+		for _, bb := range c.Preds {
+			if bb == b {
+				found = true
+				break
+			}
+		}
+		if !found {
+			s.errorf("expected predecessor edge in successor %s; found only: %s", c, c.Preds)
+		}
+		if c.parent != s.fn {
+			s.errorf("successor %s belongs to different function %s", c, c.parent)
+		}
+	}
+
+	// Check each instruction is sane.
+	n := len(b.Instrs)
+	if n == 0 {
+		s.errorf("basic block contains no instructions")
+	}
+	var rands [10]*Value // reuse storage
+	for j, instr := range b.Instrs {
+		if instr == nil {
+			s.errorf("nil instruction at index %d", j)
+			continue
+		}
+		if b2 := instr.Block(); b2 == nil {
+			s.errorf("nil Block() for instruction at index %d", j)
+			continue
+		} else if b2 != b {
+			s.errorf("wrong Block() (%s) for instruction at index %d ", b2, j)
+			continue
+		}
+		if j < n-1 {
+			s.checkInstr(j, instr)
+		} else {
+			s.checkFinalInstr(j, instr)
+		}
+
+		// Check Instruction.Operands.
+	operands:
+		for i, op := range instr.Operands(rands[:0]) {
+			if op == nil {
+				s.errorf("nil operand pointer %d of %s", i, instr)
+				continue
+			}
+			val := *op
+			if val == nil {
+				continue // a nil operand is ok
+			}
+
+			// Check that "untyped" types only appear on constant operands.
+			if _, ok := (*op).(*Const); !ok {
+				if basic, ok := (*op).Type().(*types.Basic); ok {
+					if basic.Info()&types.IsUntyped != 0 {
+						s.errorf("operand #%d of %s is untyped: %s", i, instr, basic)
+					}
+				}
+			}
+
+			// Check that Operands that are also Instructions belong to same function.
+			// TODO(adonovan): also check their block dominates block b.
+			if val, ok := val.(Instruction); ok {
+				if val.Parent() != s.fn {
+					s.errorf("operand %d of %s is an instruction (%s) from function %s", i, instr, val, val.Parent())
+				}
+			}
+
+			// Check that each function-local operand of
+			// instr refers back to instr.  (NB: quadratic)
+			switch val := val.(type) {
+			case *Const, *Global, *Builtin:
+				continue // not local
+			case *Function:
+				if val.parent == nil {
+					continue // only anon functions are local
+				}
+			}
+
+			// TODO(adonovan): check val.Parent() != nil <=> val.Referrers() is defined.
+
+			if refs := val.Referrers(); refs != nil {
+				for _, ref := range *refs {
+					if ref == instr {
+						continue operands
+					}
+				}
+				s.errorf("operand %d of %s (%s) does not refer to us", i, instr, val)
+			} else {
+				s.errorf("operand %d of %s (%s) has no referrers", i, instr, val)
+			}
+		}
+	}
+}
+
+func (s *sanity) checkReferrerList(v Value) {
+	refs := v.Referrers()
+	if refs == nil {
+		s.errorf("%s has missing referrer list", v.Name())
+		return
+	}
+	for i, ref := range *refs {
+		if _, ok := s.instrs[ref]; !ok {
+			s.errorf("%s.Referrers()[%d] = %s is not an instruction belonging to this function", v.Name(), i, ref)
+		}
+	}
+}
+
+func (s *sanity) checkFunction(fn *Function) bool {
+	// TODO(adonovan): check Function invariants:
+	// - check params match signature
+	// - check transient fields are nil
+	// - warn if any fn.Locals do not appear among block instructions.
+	s.fn = fn
+	if fn.Prog == nil {
+		s.errorf("nil Prog")
+	}
+
+	fn.String()               // must not crash
+	fn.RelString(fn.pkgobj()) // must not crash
+
+	// All functions have a package, except delegates (which are
+	// shared across packages, or duplicated as weak symbols in a
+	// separate-compilation model), and error.Error.
+	if fn.Pkg == nil {
+		if strings.HasPrefix(fn.Synthetic, "wrapper ") ||
+			strings.HasPrefix(fn.Synthetic, "bound ") ||
+			strings.HasPrefix(fn.Synthetic, "thunk ") ||
+			strings.HasSuffix(fn.name, "Error") {
+			// ok
+		} else {
+			s.errorf("nil Pkg")
+		}
+	}
+	if src, syn := fn.Synthetic == "", fn.Syntax() != nil; src != syn {
+		s.errorf("got fromSource=%t, hasSyntax=%t; want same values", src, syn)
+	}
+	for i, l := range fn.Locals {
+		if l.Parent() != fn {
+			s.errorf("Local %s at index %d has wrong parent", l.Name(), i)
+		}
+		if l.Heap {
+			s.errorf("Local %s at index %d has Heap flag set", l.Name(), i)
+		}
+	}
+	// Build the set of valid referrers.
+	s.instrs = make(map[Instruction]struct{})
+	for _, b := range fn.Blocks {
+		for _, instr := range b.Instrs {
+			s.instrs[instr] = struct{}{}
+		}
+	}
+	for i, p := range fn.Params {
+		if p.Parent() != fn {
+			s.errorf("Param %s at index %d has wrong parent", p.Name(), i)
+		}
+		s.checkReferrerList(p)
+	}
+	for i, fv := range fn.FreeVars {
+		if fv.Parent() != fn {
+			s.errorf("FreeVar %s at index %d has wrong parent", fv.Name(), i)
+		}
+		s.checkReferrerList(fv)
+	}
+
+	if fn.Blocks != nil && len(fn.Blocks) == 0 {
+		// Function _had_ blocks (so it's not external) but
+		// they were "optimized" away, even the entry block.
+		s.errorf("Blocks slice is non-nil but empty")
+	}
+	for i, b := range fn.Blocks {
+		if b == nil {
+			s.warnf("nil *BasicBlock at f.Blocks[%d]", i)
+			continue
+		}
+		s.checkBlock(b, i)
+	}
+	if fn.Recover != nil && fn.Blocks[fn.Recover.Index] != fn.Recover {
+		s.errorf("Recover block is not in Blocks slice")
+	}
+
+	s.block = nil
+	for i, anon := range fn.AnonFuncs {
+		if anon.Parent() != fn {
+			s.errorf("AnonFuncs[%d]=%s but %s.Parent()=%s", i, anon, anon, anon.Parent())
+		}
+	}
+	s.fn = nil
+	return !s.insane
+}
+
+// sanityCheckPackage checks invariants of packages upon creation.
+// It does not require that the package is built.
+// Unlike sanityCheck (for functions), it just panics at the first error.
+func sanityCheckPackage(pkg *Package) {
+	if pkg.Object == nil {
+		panic(fmt.Sprintf("Package %s has no Object", pkg))
+	}
+	pkg.String() // must not crash
+
+	for name, mem := range pkg.Members {
+		if name != mem.Name() {
+			panic(fmt.Sprintf("%s: %T.Name() = %s, want %s",
+				pkg.Object.Path(), mem, mem.Name(), name))
+		}
+		obj := mem.Object()
+		if obj == nil {
+			// This check is sound because fields
+			// {Global,Function}.object have type
+			// types.Object.  (If they were declared as
+			// *types.{Var,Func}, we'd have a non-empty
+			// interface containing a nil pointer.)
+
+			continue // not all members have typechecker objects
+		}
+		if obj.Name() != name {
+			if obj.Name() == "init" && strings.HasPrefix(mem.Name(), "init#") {
+				// Ok.  The name of a declared init function varies between
+				// its types.Func ("init") and its ssa.Function ("init#%d").
+			} else {
+				panic(fmt.Sprintf("%s: %T.Object().Name() = %s, want %s",
+					pkg.Object.Path(), mem, obj.Name(), name))
+			}
+		}
+		if obj.Pos() != mem.Pos() {
+			panic(fmt.Sprintf("%s Pos=%d obj.Pos=%d", mem, mem.Pos(), obj.Pos()))
+		}
+	}
+}
diff --git a/go/ssa/source.go b/go/ssa/source.go
new file mode 100644
index 0000000..84e6f1d
--- /dev/null
+++ b/go/ssa/source.go
@@ -0,0 +1,294 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssa
+
+// This file defines utilities for working with source positions
+// or source-level named entities ("objects").
+
+// TODO(adonovan): test that {Value,Instruction}.Pos() positions match
+// the originating syntax, as specified.
+
+import (
+	"go/ast"
+	"go/token"
+
+	"golang.org/x/tools/go/types"
+)
+
+// EnclosingFunction returns the function that contains the syntax
+// node denoted by path.
+//
+// Syntax associated with package-level variable specifications is
+// enclosed by the package's init() function.
+//
+// Returns nil if not found; reasons might include:
+//    - the node is not enclosed by any function.
+//    - the node is within an anonymous function (FuncLit) and
+//      its SSA function has not been created yet
+//      (pkg.Build() has not yet been called).
+//
+func EnclosingFunction(pkg *Package, path []ast.Node) *Function {
+	// Start with package-level function...
+	fn := findEnclosingPackageLevelFunction(pkg, path)
+	if fn == nil {
+		return nil // not in any function
+	}
+
+	// ...then walk down the nested anonymous functions.
+	n := len(path)
+outer:
+	for i := range path {
+		if lit, ok := path[n-1-i].(*ast.FuncLit); ok {
+			for _, anon := range fn.AnonFuncs {
+				if anon.Pos() == lit.Type.Func {
+					fn = anon
+					continue outer
+				}
+			}
+			// SSA function not found:
+			// - package not yet built, or maybe
+			// - builder skipped FuncLit in dead block
+			//   (in principle; but currently the Builder
+			//   generates even dead FuncLits).
+			return nil
+		}
+	}
+	return fn
+}
+
+// HasEnclosingFunction returns true if the AST node denoted by path
+// is contained within the declaration of some function or
+// package-level variable.
+//
+// Unlike EnclosingFunction, the behaviour of this function does not
+// depend on whether SSA code for pkg has been built, so it can be
+// used to quickly reject check inputs that will cause
+// EnclosingFunction to fail, prior to SSA building.
+//
+func HasEnclosingFunction(pkg *Package, path []ast.Node) bool {
+	return findEnclosingPackageLevelFunction(pkg, path) != nil
+}
+
+// findEnclosingPackageLevelFunction returns the Function
+// corresponding to the package-level function enclosing path.
+//
+func findEnclosingPackageLevelFunction(pkg *Package, path []ast.Node) *Function {
+	if n := len(path); n >= 2 { // [... {Gen,Func}Decl File]
+		switch decl := path[n-2].(type) {
+		case *ast.GenDecl:
+			if decl.Tok == token.VAR && n >= 3 {
+				// Package-level 'var' initializer.
+				return pkg.init
+			}
+
+		case *ast.FuncDecl:
+			if decl.Recv == nil && decl.Name.Name == "init" {
+				// Explicit init() function.
+				for _, b := range pkg.init.Blocks {
+					for _, instr := range b.Instrs {
+						if instr, ok := instr.(*Call); ok {
+							if callee, ok := instr.Call.Value.(*Function); ok && callee.Pkg == pkg && callee.Pos() == decl.Name.NamePos {
+								return callee
+							}
+						}
+					}
+				}
+				// Hack: return non-nil when SSA is not yet
+				// built so that HasEnclosingFunction works.
+				return pkg.init
+			}
+			// Declared function/method.
+			return findNamedFunc(pkg, decl.Name.NamePos)
+		}
+	}
+	return nil // not in any function
+}
+
+// findNamedFunc returns the named function whose FuncDecl.Ident is at
+// position pos.
+//
+func findNamedFunc(pkg *Package, pos token.Pos) *Function {
+	// Look at all package members and method sets of named types.
+	// Not very efficient.
+	for _, mem := range pkg.Members {
+		switch mem := mem.(type) {
+		case *Function:
+			if mem.Pos() == pos {
+				return mem
+			}
+		case *Type:
+			mset := pkg.Prog.MethodSets.MethodSet(types.NewPointer(mem.Type()))
+			for i, n := 0, mset.Len(); i < n; i++ {
+				// Don't call Program.Method: avoid creating wrappers.
+				obj := mset.At(i).Obj().(*types.Func)
+				if obj.Pos() == pos {
+					return pkg.values[obj].(*Function)
+				}
+			}
+		}
+	}
+	return nil
+}
+
+// ValueForExpr returns the SSA Value that corresponds to non-constant
+// expression e.
+//
+// It returns nil if no value was found, e.g.
+//    - the expression is not lexically contained within f;
+//    - f was not built with debug information; or
+//    - e is a constant expression.  (For efficiency, no debug
+//      information is stored for constants. Use
+//      go/types.Info.Types[e].Value instead.)
+//    - e is a reference to nil or a built-in function.
+//    - the value was optimised away.
+//
+// If e is an addressable expression used in an lvalue context,
+// value is the address denoted by e, and isAddr is true.
+//
+// The types of e (or &e, if isAddr) and the result are equal
+// (modulo "untyped" bools resulting from comparisons).
+//
+// (Tip: to find the ssa.Value given a source position, use
+// importer.PathEnclosingInterval to locate the ast.Node, then
+// EnclosingFunction to locate the Function, then ValueForExpr to find
+// the ssa.Value.)
+//
+func (f *Function) ValueForExpr(e ast.Expr) (value Value, isAddr bool) {
+	if f.debugInfo() { // (opt)
+		e = unparen(e)
+		for _, b := range f.Blocks {
+			for _, instr := range b.Instrs {
+				if ref, ok := instr.(*DebugRef); ok {
+					if ref.Expr == e {
+						return ref.X, ref.IsAddr
+					}
+				}
+			}
+		}
+	}
+	return
+}
+
+// --- Lookup functions for source-level named entities (types.Objects) ---
+
+// Package returns the SSA Package corresponding to the specified
+// type-checker package object.
+// It returns nil if no such SSA package has been created.
+//
+func (prog *Program) Package(obj *types.Package) *Package {
+	return prog.packages[obj]
+}
+
+// packageLevelValue returns the package-level value corresponding to
+// the specified named object, which may be a package-level const
+// (*Const), var (*Global) or func (*Function) of some package in
+// prog.  It returns nil if the object is not found.
+//
+func (prog *Program) packageLevelValue(obj types.Object) Value {
+	if pkg, ok := prog.packages[obj.Pkg()]; ok {
+		return pkg.values[obj]
+	}
+	return nil
+}
+
+// FuncValue returns the concrete Function denoted by the source-level
+// named function obj, or nil if obj denotes an interface method.
+//
+// TODO(adonovan): check the invariant that obj.Type() matches the
+// result's Signature, both in the params/results and in the receiver.
+//
+func (prog *Program) FuncValue(obj *types.Func) *Function {
+	fn, _ := prog.packageLevelValue(obj).(*Function)
+	return fn
+}
+
+// ConstValue returns the SSA Value denoted by the source-level named
+// constant obj.
+//
+func (prog *Program) ConstValue(obj *types.Const) *Const {
+	// TODO(adonovan): opt: share (don't reallocate)
+	// Consts for const objects and constant ast.Exprs.
+
+	// Universal constant? {true,false,nil}
+	if obj.Parent() == types.Universe {
+		return NewConst(obj.Val(), obj.Type())
+	}
+	// Package-level named constant?
+	if v := prog.packageLevelValue(obj); v != nil {
+		return v.(*Const)
+	}
+	return NewConst(obj.Val(), obj.Type())
+}
+
+// VarValue returns the SSA Value that corresponds to a specific
+// identifier denoting the source-level named variable obj.
+//
+// VarValue returns nil if a local variable was not found, perhaps
+// because its package was not built, the debug information was not
+// requested during SSA construction, or the value was optimized away.
+//
+// ref is the path to an ast.Ident (e.g. from PathEnclosingInterval),
+// and that ident must resolve to obj.
+//
+// pkg is the package enclosing the reference.  (A reference to a var
+// always occurs within a function, so we need to know where to find it.)
+//
+// If the identifier is a field selector and its base expression is
+// non-addressable, then VarValue returns the value of that field.
+// For example:
+//    func f() struct {x int}
+//    f().x  // VarValue(x) returns a *Field instruction of type int
+//
+// All other identifiers denote addressable locations (variables).
+// For them, VarValue may return either the variable's address or its
+// value, even when the expression is evaluated only for its value; the
+// situation is reported by isAddr, the second component of the result.
+//
+// If !isAddr, the returned value is the one associated with the
+// specific identifier.  For example,
+//       var x int    // VarValue(x) returns Const 0 here
+//       x = 1        // VarValue(x) returns Const 1 here
+//
+// It is not specified whether the value or the address is returned in
+// any particular case, as it may depend upon optimizations performed
+// during SSA code generation, such as registerization, constant
+// folding, avoidance of materialization of subexpressions, etc.
+//
+func (prog *Program) VarValue(obj *types.Var, pkg *Package, ref []ast.Node) (value Value, isAddr bool) {
+	// All references to a var are local to some function, possibly init.
+	fn := EnclosingFunction(pkg, ref)
+	if fn == nil {
+		return // e.g. def of struct field; SSA not built?
+	}
+
+	id := ref[0].(*ast.Ident)
+
+	// Defining ident of a parameter?
+	if id.Pos() == obj.Pos() {
+		for _, param := range fn.Params {
+			if param.Object() == obj {
+				return param, false
+			}
+		}
+	}
+
+	// Other ident?
+	for _, b := range fn.Blocks {
+		for _, instr := range b.Instrs {
+			if dr, ok := instr.(*DebugRef); ok {
+				if dr.Pos() == id.Pos() {
+					return dr.X, dr.IsAddr
+				}
+			}
+		}
+	}
+
+	// Defining ident of package-level var?
+	if v := prog.packageLevelValue(obj); v != nil {
+		return v.(*Global), true
+	}
+
+	return // e.g. debug info not requested, or var optimized away
+}
diff --git a/go/ssa/source_test.go b/go/ssa/source_test.go
new file mode 100644
index 0000000..75669c1
--- /dev/null
+++ b/go/ssa/source_test.go
@@ -0,0 +1,393 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssa_test
+
+// This file defines tests of source-level debugging utilities.
+
+import (
+	"fmt"
+	"go/ast"
+	"go/parser"
+	"go/token"
+	"os"
+	"regexp"
+	"runtime"
+	"strings"
+	"testing"
+
+	"golang.org/x/tools/go/ast/astutil"
+	"golang.org/x/tools/go/exact"
+	"golang.org/x/tools/go/loader"
+	"golang.org/x/tools/go/ssa"
+	"golang.org/x/tools/go/ssa/ssautil"
+	"golang.org/x/tools/go/types"
+)
+
+func TestObjValueLookup(t *testing.T) {
+	if runtime.GOOS == "android" {
+		t.Skipf("no testdata directory on %s", runtime.GOOS)
+	}
+
+	conf := loader.Config{ParserMode: parser.ParseComments}
+	f, err := conf.ParseFile("testdata/objlookup.go", nil)
+	if err != nil {
+		t.Error(err)
+		return
+	}
+	conf.CreateFromFiles("main", f)
+
+	// Maps each var Ident (represented "name:linenum") to the
+	// kind of ssa.Value we expect (represented "Constant", "&Alloc").
+	expectations := make(map[string]string)
+
+	// Find all annotations of form x::BinOp, &y::Alloc, etc.
+	re := regexp.MustCompile(`(\b|&)?(\w*)::(\w*)\b`)
+	for _, c := range f.Comments {
+		text := c.Text()
+		pos := conf.Fset.Position(c.Pos())
+		for _, m := range re.FindAllStringSubmatch(text, -1) {
+			key := fmt.Sprintf("%s:%d", m[2], pos.Line)
+			value := m[1] + m[3]
+			expectations[key] = value
+		}
+	}
+
+	iprog, err := conf.Load()
+	if err != nil {
+		t.Error(err)
+		return
+	}
+
+	prog := ssautil.CreateProgram(iprog, 0 /*|ssa.PrintFunctions*/)
+	mainInfo := iprog.Created[0]
+	mainPkg := prog.Package(mainInfo.Pkg)
+	mainPkg.SetDebugMode(true)
+	mainPkg.Build()
+
+	var varIds []*ast.Ident
+	var varObjs []*types.Var
+	for id, obj := range mainInfo.Defs {
+		// Check invariants for func and const objects.
+		switch obj := obj.(type) {
+		case *types.Func:
+			checkFuncValue(t, prog, obj)
+
+		case *types.Const:
+			checkConstValue(t, prog, obj)
+
+		case *types.Var:
+			if id.Name == "_" {
+				continue
+			}
+			varIds = append(varIds, id)
+			varObjs = append(varObjs, obj)
+		}
+	}
+	for id, obj := range mainInfo.Uses {
+		if obj, ok := obj.(*types.Var); ok {
+			varIds = append(varIds, id)
+			varObjs = append(varObjs, obj)
+		}
+	}
+
+	// Check invariants for var objects.
+	// The result varies based on the specific Ident.
+	for i, id := range varIds {
+		obj := varObjs[i]
+		ref, _ := astutil.PathEnclosingInterval(f, id.Pos(), id.Pos())
+		pos := prog.Fset.Position(id.Pos())
+		exp := expectations[fmt.Sprintf("%s:%d", id.Name, pos.Line)]
+		if exp == "" {
+			t.Errorf("%s: no expectation for var ident %s ", pos, id.Name)
+			continue
+		}
+		wantAddr := false
+		if exp[0] == '&' {
+			wantAddr = true
+			exp = exp[1:]
+		}
+		checkVarValue(t, prog, mainPkg, ref, obj, exp, wantAddr)
+	}
+}
+
+func checkFuncValue(t *testing.T, prog *ssa.Program, obj *types.Func) {
+	fn := prog.FuncValue(obj)
+	// fmt.Printf("FuncValue(%s) = %s\n", obj, fn) // debugging
+	if fn == nil {
+		if obj.Name() != "interfaceMethod" {
+			t.Errorf("FuncValue(%s) == nil", obj)
+		}
+		return
+	}
+	if fnobj := fn.Object(); fnobj != obj {
+		t.Errorf("FuncValue(%s).Object() == %s; value was %s",
+			obj, fnobj, fn.Name())
+		return
+	}
+	if !types.Identical(fn.Type(), obj.Type()) {
+		t.Errorf("FuncValue(%s).Type() == %s", obj, fn.Type())
+		return
+	}
+}
+
+func checkConstValue(t *testing.T, prog *ssa.Program, obj *types.Const) {
+	c := prog.ConstValue(obj)
+	// fmt.Printf("ConstValue(%s) = %s\n", obj, c) // debugging
+	if c == nil {
+		t.Errorf("ConstValue(%s) == nil", obj)
+		return
+	}
+	if !types.Identical(c.Type(), obj.Type()) {
+		t.Errorf("ConstValue(%s).Type() == %s", obj, c.Type())
+		return
+	}
+	if obj.Name() != "nil" {
+		if !exact.Compare(c.Value, token.EQL, obj.Val()) {
+			t.Errorf("ConstValue(%s).Value (%s) != %s",
+				obj, c.Value, obj.Val())
+			return
+		}
+	}
+}
+
+func checkVarValue(t *testing.T, prog *ssa.Program, pkg *ssa.Package, ref []ast.Node, obj *types.Var, expKind string, wantAddr bool) {
+	// The prefix of all assertions messages.
+	prefix := fmt.Sprintf("VarValue(%s @ L%d)",
+		obj, prog.Fset.Position(ref[0].Pos()).Line)
+
+	v, gotAddr := prog.VarValue(obj, pkg, ref)
+
+	// Kind is the concrete type of the ssa Value.
+	gotKind := "nil"
+	if v != nil {
+		gotKind = fmt.Sprintf("%T", v)[len("*ssa."):]
+	}
+
+	// fmt.Printf("%s = %v (kind %q; expect %q) wantAddr=%t gotAddr=%t\n", prefix, v, gotKind, expKind, wantAddr, gotAddr) // debugging
+
+	// Check the kinds match.
+	// "nil" indicates expected failure (e.g. optimized away).
+	if expKind != gotKind {
+		t.Errorf("%s concrete type == %s, want %s", prefix, gotKind, expKind)
+	}
+
+	// Check the types match.
+	// If wantAddr, the expected type is the object's address.
+	if v != nil {
+		expType := obj.Type()
+		if wantAddr {
+			expType = types.NewPointer(expType)
+			if !gotAddr {
+				t.Errorf("%s: got value, want address", prefix)
+			}
+		} else if gotAddr {
+			t.Errorf("%s: got address, want value", prefix)
+		}
+		if !types.Identical(v.Type(), expType) {
+			t.Errorf("%s.Type() == %s, want %s", prefix, v.Type(), expType)
+		}
+	}
+}
+
+// Ensure that, in debug mode, we can determine the ssa.Value
+// corresponding to every ast.Expr.
+func TestValueForExpr(t *testing.T) {
+	if runtime.GOOS == "android" {
+		t.Skipf("no testdata dir on %s", runtime.GOOS)
+	}
+
+	conf := loader.Config{ParserMode: parser.ParseComments}
+	f, err := conf.ParseFile("testdata/valueforexpr.go", nil)
+	if err != nil {
+		t.Error(err)
+		return
+	}
+	conf.CreateFromFiles("main", f)
+
+	iprog, err := conf.Load()
+	if err != nil {
+		t.Error(err)
+		return
+	}
+
+	mainInfo := iprog.Created[0]
+
+	prog := ssautil.CreateProgram(iprog, 0)
+	mainPkg := prog.Package(mainInfo.Pkg)
+	mainPkg.SetDebugMode(true)
+	mainPkg.Build()
+
+	if false {
+		// debugging
+		for _, mem := range mainPkg.Members {
+			if fn, ok := mem.(*ssa.Function); ok {
+				fn.WriteTo(os.Stderr)
+			}
+		}
+	}
+
+	// Find the actual AST node for each canonical position.
+	parenExprByPos := make(map[token.Pos]*ast.ParenExpr)
+	ast.Inspect(f, func(n ast.Node) bool {
+		if n != nil {
+			if e, ok := n.(*ast.ParenExpr); ok {
+				parenExprByPos[e.Pos()] = e
+			}
+		}
+		return true
+	})
+
+	// Find all annotations of form /*@kind*/.
+	for _, c := range f.Comments {
+		text := strings.TrimSpace(c.Text())
+		if text == "" || text[0] != '@' {
+			continue
+		}
+		text = text[1:]
+		pos := c.End() + 1
+		position := prog.Fset.Position(pos)
+		var e ast.Expr
+		if target := parenExprByPos[pos]; target == nil {
+			t.Errorf("%s: annotation doesn't precede ParenExpr: %q", position, text)
+			continue
+		} else {
+			e = target.X
+		}
+
+		path, _ := astutil.PathEnclosingInterval(f, pos, pos)
+		if path == nil {
+			t.Errorf("%s: can't find AST path from root to comment: %s", position, text)
+			continue
+		}
+
+		fn := ssa.EnclosingFunction(mainPkg, path)
+		if fn == nil {
+			t.Errorf("%s: can't find enclosing function", position)
+			continue
+		}
+
+		v, gotAddr := fn.ValueForExpr(e) // (may be nil)
+		got := strings.TrimPrefix(fmt.Sprintf("%T", v), "*ssa.")
+		if want := text; got != want {
+			t.Errorf("%s: got value %q, want %q", position, got, want)
+		}
+		if v != nil {
+			T := v.Type()
+			if gotAddr {
+				T = T.Underlying().(*types.Pointer).Elem() // deref
+			}
+			if !types.Identical(T, mainInfo.TypeOf(e)) {
+				t.Errorf("%s: got type %s, want %s", position, mainInfo.TypeOf(e), T)
+			}
+		}
+	}
+}
+
+// findInterval parses input and returns the [start, end) positions of
+// the first occurrence of substr in input.  f==nil indicates failure;
+// an error has already been reported in that case.
+//
+func findInterval(t *testing.T, fset *token.FileSet, input, substr string) (f *ast.File, start, end token.Pos) {
+	f, err := parser.ParseFile(fset, "<input>", input, 0)
+	if err != nil {
+		t.Errorf("parse error: %s", err)
+		return
+	}
+
+	i := strings.Index(input, substr)
+	if i < 0 {
+		t.Errorf("%q is not a substring of input", substr)
+		f = nil
+		return
+	}
+
+	filePos := fset.File(f.Package)
+	return f, filePos.Pos(i), filePos.Pos(i + len(substr))
+}
+
+func TestEnclosingFunction(t *testing.T) {
+	tests := []struct {
+		input  string // the input file
+		substr string // first occurrence of this string denotes interval
+		fn     string // name of expected containing function
+	}{
+		// We use distinctive numbers as syntactic landmarks.
+
+		// Ordinary function:
+		{`package main
+		  func f() { println(1003) }`,
+			"100", "main.f"},
+		// Methods:
+		{`package main
+                  type T int
+		  func (t T) f() { println(200) }`,
+			"200", "(main.T).f"},
+		// Function literal:
+		{`package main
+		  func f() { println(func() { print(300) }) }`,
+			"300", "main.f$1"},
+		// Doubly nested
+		{`package main
+		  func f() { println(func() { print(func() { print(350) })})}`,
+			"350", "main.f$1$1"},
+		// Implicit init for package-level var initializer.
+		{"package main; var a = 400", "400", "main.init"},
+		// No code for constants:
+		{"package main; const a = 500", "500", "(none)"},
+		// Explicit init()
+		{"package main; func init() { println(600) }", "600", "main.init#1"},
+		// Multiple explicit init functions:
+		{`package main
+		  func init() { println("foo") }
+		  func init() { println(800) }`,
+			"800", "main.init#2"},
+		// init() containing FuncLit.
+		{`package main
+		  func init() { println(func(){print(900)}) }`,
+			"900", "main.init#1$1"},
+	}
+	for _, test := range tests {
+		conf := loader.Config{Fset: token.NewFileSet()}
+		f, start, end := findInterval(t, conf.Fset, test.input, test.substr)
+		if f == nil {
+			continue
+		}
+		path, exact := astutil.PathEnclosingInterval(f, start, end)
+		if !exact {
+			t.Errorf("EnclosingFunction(%q) not exact", test.substr)
+			continue
+		}
+
+		conf.CreateFromFiles("main", f)
+
+		iprog, err := conf.Load()
+		if err != nil {
+			t.Error(err)
+			continue
+		}
+		prog := ssautil.CreateProgram(iprog, 0)
+		pkg := prog.Package(iprog.Created[0].Pkg)
+		pkg.Build()
+
+		name := "(none)"
+		fn := ssa.EnclosingFunction(pkg, path)
+		if fn != nil {
+			name = fn.String()
+		}
+
+		if name != test.fn {
+			t.Errorf("EnclosingFunction(%q in %q) got %s, want %s",
+				test.substr, test.input, name, test.fn)
+			continue
+		}
+
+		// While we're here: test HasEnclosingFunction.
+		if has := ssa.HasEnclosingFunction(pkg, path); has != (fn != nil) {
+			t.Errorf("HasEnclosingFunction(%q in %q) got %v, want %v",
+				test.substr, test.input, has, fn != nil)
+			continue
+		}
+	}
+}
diff --git a/go/ssa/ssa.go b/go/ssa/ssa.go
new file mode 100644
index 0000000..f4c64bb
--- /dev/null
+++ b/go/ssa/ssa.go
@@ -0,0 +1,1700 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssa
+
+// This package defines a high-level intermediate representation for
+// Go programs using static single-assignment (SSA) form.
+
+import (
+	"fmt"
+	"go/ast"
+	"go/token"
+	"sync"
+
+	"golang.org/x/tools/go/exact"
+	"golang.org/x/tools/go/types"
+	"golang.org/x/tools/go/types/typeutil"
+)
+
+// A Program is a partial or complete Go program converted to SSA form.
+type Program struct {
+	Fset       *token.FileSet              // position information for the files of this Program
+	imported   map[string]*Package         // all importable Packages, keyed by import path
+	packages   map[*types.Package]*Package // all loaded Packages, keyed by object
+	mode       BuilderMode                 // set of mode bits for SSA construction
+	MethodSets typeutil.MethodSetCache     // cache of type-checker's method-sets
+
+	methodsMu    sync.Mutex                 // guards the following maps:
+	methodSets   typeutil.Map               // maps type to its concrete methodSet
+	runtimeTypes typeutil.Map               // types for which rtypes are needed
+	canon        typeutil.Map               // type canonicalization map
+	bounds       map[*types.Func]*Function  // bounds for curried x.Method closures
+	thunks       map[selectionKey]*Function // thunks for T.Method expressions
+}
+
+// A Package is a single analyzed Go package containing Members for
+// all package-level functions, variables, constants and types it
+// declares.  These may be accessed directly via Members, or via the
+// type-specific accessor methods Func, Type, Var and Const.
+//
+// Members also contains entries for "init" (the synthetic package
+// initializer) and "init#%d", the nth declared init function,
+// and unspecified other things too.
+//
+type Package struct {
+	Prog    *Program               // the owning program
+	Object  *types.Package         // the type checker's package object for this package
+	Members map[string]Member      // all package members keyed by name (incl. init and init#%d)
+	values  map[types.Object]Value // package members (incl. types and methods), keyed by object
+	init    *Function              // Func("init"); the package's init function
+	debug   bool                   // include full debug info in this package
+
+	// The following fields are set transiently, then cleared
+	// after building.
+	started int32       // atomically tested and set at start of build phase
+	ninit   int32       // number of init functions
+	info    *types.Info // package type information
+	files   []*ast.File // package ASTs
+}
+
+// A Member is a member of a Go package, implemented by *NamedConst,
+// *Global, *Function, or *Type; they are created by package-level
+// const, var, func and type declarations respectively.
+//
+type Member interface {
+	Name() string                    // declared name of the package member
+	String() string                  // package-qualified name of the package member
+	RelString(*types.Package) string // like String, but relative refs are unqualified
+	Object() types.Object            // typechecker's object for this member, if any
+	Pos() token.Pos                  // position of member's declaration, if known
+	Type() types.Type                // type of the package member
+	Token() token.Token              // token.{VAR,FUNC,CONST,TYPE}
+	Package() *Package               // the containing package
+}
+
+// A Type is a Member of a Package representing a package-level named type.
+//
+// Type() returns a *types.Named.
+//
+type Type struct {
+	object *types.TypeName
+	pkg    *Package
+}
+
+// A NamedConst is a Member of a Package representing a package-level
+// named constant.
+//
+// Pos() returns the position of the declaring ast.ValueSpec.Names[*]
+// identifier.
+//
+// NB: a NamedConst is not a Value; it contains a constant Value, which
+// it augments with the name and position of its 'const' declaration.
+//
+type NamedConst struct {
+	object *types.Const
+	Value  *Const
+	pos    token.Pos
+	pkg    *Package
+}
+
+// A Value is an SSA value that can be referenced by an instruction.
+type Value interface {
+	// Name returns the name of this value, and determines how
+	// this Value appears when used as an operand of an
+	// Instruction.
+	//
+	// This is the same as the source name for Parameters,
+	// Builtins, Functions, FreeVars, Globals.
+	// For constants, it is a representation of the constant's value
+	// and type.  For all other Values this is the name of the
+	// virtual register defined by the instruction.
+	//
+	// The name of an SSA Value is not semantically significant,
+	// and may not even be unique within a function.
+	Name() string
+
+	// If this value is an Instruction, String returns its
+	// disassembled form; otherwise it returns unspecified
+	// human-readable information about the Value, such as its
+	// kind, name and type.
+	String() string
+
+	// Type returns the type of this value.  Many instructions
+	// (e.g. IndexAddr) change their behaviour depending on the
+	// types of their operands.
+	Type() types.Type
+
+	// Parent returns the function to which this Value belongs.
+	// It returns nil for named Functions, Builtin, Const and Global.
+	Parent() *Function
+
+	// Referrers returns the list of instructions that have this
+	// value as one of their operands; it may contain duplicates
+	// if an instruction has a repeated operand.
+	//
+	// Referrers actually returns a pointer through which the
+	// caller may perform mutations to the object's state.
+	//
+	// Referrers is currently only defined if Parent()!=nil,
+	// i.e. for the function-local values FreeVar, Parameter,
+	// Functions (iff anonymous) and all value-defining instructions.
+	// It returns nil for named Functions, Builtin, Const and Global.
+	//
+	// Instruction.Operands contains the inverse of this relation.
+	Referrers() *[]Instruction
+
+	// Pos returns the location of the AST token most closely
+	// associated with the operation that gave rise to this value,
+	// or token.NoPos if it was not explicit in the source.
+	//
+	// For each ast.Node type, a particular token is designated as
+	// the closest location for the expression, e.g. the Lparen
+	// for an *ast.CallExpr.  This permits a compact but
+	// approximate mapping from Values to source positions for use
+	// in diagnostic messages, for example.
+	//
+	// (Do not use this position to determine which Value
+	// corresponds to an ast.Expr; use Function.ValueForExpr
+	// instead.  NB: it requires that the function was built with
+	// debug information.)
+	Pos() token.Pos
+}
+
+// An Instruction is an SSA instruction that computes a new Value or
+// has some effect.
+//
+// An Instruction that defines a value (e.g. BinOp) also implements
+// the Value interface; an Instruction that only has an effect (e.g. Store)
+// does not.
+//
+type Instruction interface {
+	// String returns the disassembled form of this value.
+	//
+	// Examples of Instructions that are Values:
+	//       "x + y"     (BinOp)
+	//       "len([])"   (Call)
+	// Note that the name of the Value is not printed.
+	//
+	// Examples of Instructions that are not Values:
+	//       "return x"  (Return)
+	//       "*y = x"    (Store)
+	//
+	// (The separation Value.Name() from Value.String() is useful
+	// for some analyses which distinguish the operation from the
+	// value it defines, e.g., 'y = local int' is both an allocation
+	// of memory 'local int' and a definition of a pointer y.)
+	String() string
+
+	// Parent returns the function to which this instruction
+	// belongs.
+	Parent() *Function
+
+	// Block returns the basic block to which this instruction
+	// belongs.
+	Block() *BasicBlock
+
+	// setBlock sets the basic block to which this instruction belongs.
+	setBlock(*BasicBlock)
+
+	// Operands returns the operands of this instruction: the
+	// set of Values it references.
+	//
+	// Specifically, it appends their addresses to rands, a
+	// user-provided slice, and returns the resulting slice,
+	// permitting avoidance of memory allocation.
+	//
+	// The operands are appended in undefined order, but the order
+	// is consistent for a given Instruction; the addresses are
+	// always non-nil but may point to a nil Value.  Clients may
+	// store through the pointers, e.g. to effect a value
+	// renaming.
+	//
+	// Value.Referrers is a subset of the inverse of this
+	// relation.  (Referrers are not tracked for all types of
+	// Values.)
+	Operands(rands []*Value) []*Value
+
+	// Pos returns the location of the AST token most closely
+	// associated with the operation that gave rise to this
+	// instruction, or token.NoPos if it was not explicit in the
+	// source.
+	//
+	// For each ast.Node type, a particular token is designated as
+	// the closest location for the expression, e.g. the Go token
+	// for an *ast.GoStmt.  This permits a compact but approximate
+	// mapping from Instructions to source positions for use in
+	// diagnostic messages, for example.
+	//
+	// (Do not use this position to determine which Instruction
+	// corresponds to an ast.Expr; see the notes for Value.Pos.
+	// This position may be used to determine which non-Value
+	// Instruction corresponds to some ast.Stmts, but not all: If
+	// and Jump instructions have no Pos(), for example.)
+	Pos() token.Pos
+}
+
+// A Node is a node in the SSA value graph.  Every concrete type that
+// implements Node is also either a Value, an Instruction, or both.
+//
+// Node contains the methods common to Value and Instruction, plus the
+// Operands and Referrers methods generalized to return nil for
+// non-Instructions and non-Values, respectively.
+//
+// Node is provided to simplify SSA graph algorithms.  Clients should
+// use the more specific and informative Value or Instruction
+// interfaces where appropriate.
+//
+type Node interface {
+	// Common methods:
+	String() string
+	Pos() token.Pos
+	Parent() *Function
+
+	// Partial methods:
+	Operands(rands []*Value) []*Value // nil for non-Instructions
+	Referrers() *[]Instruction        // nil for non-Values
+}
+
+// Function represents the parameters, results, and code of a function
+// or method.
+//
+// If Blocks is nil, this indicates an external function for which no
+// Go source code is available.  In this case, FreeVars and Locals
+// are nil too.  Clients performing whole-program analysis must
+// handle external functions specially.
+//
+// Blocks contains the function's control-flow graph (CFG).
+// Blocks[0] is the function entry point; block order is not otherwise
+// semantically significant, though it may affect the readability of
+// the disassembly.
+// To iterate over the blocks in dominance order, use DomPreorder().
+//
+// Recover is an optional second entry point to which control resumes
+// after a recovered panic.  The Recover block may contain only a return
+// statement, preceded by a load of the function's named return
+// parameters, if any.
+//
+// A nested function (Parent()!=nil) that refers to one or more
+// lexically enclosing local variables ("free variables") has FreeVars.
+// Such functions cannot be called directly but require a
+// value created by MakeClosure which, via its Bindings, supplies
+// values for these parameters.
+//
+// If the function is a method (Signature.Recv() != nil) then the first
+// element of Params is the receiver parameter.
+//
+// A Go package may declare many functions called "init".
+// For each one, Object().Name() returns "init" but Name() returns
+// "init#1", etc, in declaration order.
+//
+// Pos() returns the declaring ast.FuncLit.Type.Func or the position
+// of the ast.FuncDecl.Name, if the function was explicit in the
+// source.  Synthetic wrappers, for which Synthetic != "", may share
+// the same position as the function they wrap.
+// Syntax.Pos() always returns the position of the declaring "func" token.
+//
+// Type() returns the function's Signature.
+//
+type Function struct {
+	name      string
+	object    types.Object     // a declared *types.Func or one of its wrappers
+	method    *types.Selection // info about provenance of synthetic methods
+	Signature *types.Signature
+	pos       token.Pos
+
+	Synthetic string        // provenance of synthetic function; "" for true source functions
+	syntax    ast.Node      // *ast.Func{Decl,Lit}; replaced with simple ast.Node after build, unless debug mode
+	parent    *Function     // enclosing function if anon; nil if global
+	Pkg       *Package      // enclosing package; nil for shared funcs (wrappers and error.Error)
+	Prog      *Program      // enclosing program
+	Params    []*Parameter  // function parameters; for methods, includes receiver
+	FreeVars  []*FreeVar    // free variables whose values must be supplied by closure
+	Locals    []*Alloc      // local variables of this function
+	Blocks    []*BasicBlock // basic blocks of the function; nil => external
+	Recover   *BasicBlock   // optional; control transfers here after recovered panic
+	AnonFuncs []*Function   // anonymous functions directly beneath this one
+	referrers []Instruction // referring instructions (iff Parent() != nil)
+
+	// The following fields are set transiently during building,
+	// then cleared.
+	currentBlock *BasicBlock             // where to emit code
+	objects      map[types.Object]Value  // addresses of local variables
+	namedResults []*Alloc                // tuple of named results
+	targets      *targets                // linked stack of branch targets
+	lblocks      map[*ast.Object]*lblock // labelled blocks
+}
+
+// BasicBlock represents an SSA basic block.
+//
+// The final element of Instrs is always an explicit transfer of
+// control (If, Jump, Return, or Panic).
+//
+// A block may contain no Instructions only if it is unreachable,
+// i.e., Preds is nil.  Empty blocks are typically pruned.
+//
+// BasicBlocks and their Preds/Succs relation form a (possibly cyclic)
+// graph independent of the SSA Value graph: the control-flow graph or
+// CFG.  It is illegal for multiple edges to exist between the same
+// pair of blocks.
+//
+// Each BasicBlock is also a node in the dominator tree of the CFG.
+// The tree may be navigated using Idom()/Dominees() and queried using
+// Dominates().
+//
+// The order of Preds and Succs is significant (to Phi and If
+// instructions, respectively).
+//
+type BasicBlock struct {
+	Index        int            // index of this block within Parent().Blocks
+	Comment      string         // optional label; no semantic significance
+	parent       *Function      // parent function
+	Instrs       []Instruction  // instructions in order
+	Preds, Succs []*BasicBlock  // predecessors and successors
+	succs2       [2]*BasicBlock // initial space for Succs
+	dom          domInfo        // dominator tree info
+	gaps         int            // number of nil Instrs (transient)
+	rundefers    int            // number of rundefers (transient)
+}
+
+// Pure values ----------------------------------------
+
+// A FreeVar represents a free variable of the function to which it
+// belongs.
+//
+// FreeVars are used to implement anonymous functions, whose free
+// variables are lexically captured in a closure formed by
+// MakeClosure.  The value of such a free var is an Alloc or another
+// FreeVar and is considered a potentially escaping heap address, with
+// pointer type.
+//
+// FreeVars are also used to implement bound method closures.  Such a
+// free var represents the receiver value and may be of any type that
+// has concrete methods.
+//
+// Pos() returns the position of the value that was captured, which
+// belongs to an enclosing function.
+//
+type FreeVar struct {
+	name      string
+	typ       types.Type
+	pos       token.Pos
+	parent    *Function
+	referrers []Instruction
+
+	// Transiently needed during building.
+	outer Value // the Value captured from the enclosing context.
+}
+
+// A Parameter represents an input parameter of a function.
+//
+type Parameter struct {
+	name      string
+	object    types.Object // a *types.Var; nil for non-source locals
+	typ       types.Type
+	pos       token.Pos
+	parent    *Function
+	referrers []Instruction
+}
+
+// A Const represents the value of a constant expression.
+//
+// The underlying type of a constant may be any boolean, numeric, or
+// string type.  In addition, a Const may represent the nil value of
+// any reference type---interface, map, channel, pointer, slice, or
+// function---but not "untyped nil".
+//
+// All source-level constant expressions are represented by a Const
+// of the same type and value.
+//
+// Value holds the exact value of the constant, independent of its
+// Type(), using the same representation as package go/exact uses for
+// constants, or nil for a typed nil value.
+//
+// Pos() returns token.NoPos.
+//
+// Example printed form:
+// 	42:int
+//	"hello":untyped string
+//	3+4i:MyComplex
+//
+type Const struct {
+	typ   types.Type
+	Value exact.Value
+}
+
+// A Global is a named Value holding the address of a package-level
+// variable.
+//
+// Pos() returns the position of the ast.ValueSpec.Names[*]
+// identifier.
+//
+type Global struct {
+	name   string
+	object types.Object // a *types.Var; may be nil for synthetics e.g. init$guard
+	typ    types.Type
+	pos    token.Pos
+
+	Pkg *Package
+}
+
+// A Builtin represents a specific use of a built-in function, e.g. len.
+//
+// Builtins are immutable values.  Builtins do not have addresses.
+// Builtins can only appear in CallCommon.Func.
+//
+// Name() indicates the function: one of the built-in functions from the
+// Go spec (excluding "make" and "new") or one of these ssa-defined
+// intrinsics:
+//
+//   // wrapnilchk returns ptr if non-nil, panics otherwise.
+//   // (For use in indirection wrappers.)
+//   func ssa:wrapnilchk(ptr *T, recvType, methodName string) *T
+//
+// Object() returns a *types.Builtin for built-ins defined by the spec,
+// nil for others.
+//
+// Type() returns a *types.Signature representing the effective
+// signature of the built-in for this call.
+//
+type Builtin struct {
+	name string
+	sig  *types.Signature
+}
+
+// Value-defining instructions  ----------------------------------------
+
+// The Alloc instruction reserves space for a variable of the given type,
+// zero-initializes it, and yields its address.
+//
+// Alloc values are always addresses, and have pointer types, so the
+// type of the allocated variable is actually
+// Type().Underlying().(*types.Pointer).Elem().
+//
+// If Heap is false, Alloc allocates space in the function's
+// activation record (frame); we refer to an Alloc(Heap=false) as a
+// "local" alloc.  Each local Alloc returns the same address each time
+// it is executed within the same activation; the space is
+// re-initialized to zero.
+//
+// If Heap is true, Alloc allocates space in the heap; we
+// refer to an Alloc(Heap=true) as a "new" alloc.  Each new Alloc
+// returns a different address each time it is executed.
+//
+// When Alloc is applied to a channel, map or slice type, it returns
+// the address of an uninitialized (nil) reference of that kind; store
+// the result of MakeSlice, MakeMap or MakeChan in that location to
+// instantiate these types.
+//
+// Pos() returns the ast.CompositeLit.Lbrace for a composite literal,
+// or the ast.CallExpr.Rparen for a call to new() or for a call that
+// allocates a varargs slice.
+//
+// Example printed form:
+// 	t0 = local int
+// 	t1 = new int
+//
+type Alloc struct {
+	register
+	Comment string
+	Heap    bool
+	index   int // dense numbering; for lifting
+}
+
+// The Phi instruction represents an SSA φ-node, which combines values
+// that differ across incoming control-flow edges and yields a new
+// value.  Within a block, all φ-nodes must appear before all non-φ
+// nodes.
+//
+// Pos() returns the position of the && or || for short-circuit
+// control-flow joins, or that of the *Alloc for φ-nodes inserted
+// during SSA renaming.
+//
+// Example printed form:
+// 	t2 = phi [0: t0, 1: t1]
+//
+type Phi struct {
+	register
+	Comment string  // a hint as to its purpose
+	Edges   []Value // Edges[i] is value for Block().Preds[i]
+}
+
+// The Call instruction represents a function or method call.
+//
+// The Call instruction yields the function result if there is exactly
+// one.  Otherwise it returns a tuple, the components of which are
+// accessed via Extract.
+//
+// See CallCommon for generic function call documentation.
+//
+// Pos() returns the ast.CallExpr.Lparen, if explicit in the source.
+//
+// Example printed form:
+// 	t2 = println(t0, t1)
+// 	t4 = t3()
+// 	t7 = invoke t5.Println(...t6)
+//
+type Call struct {
+	register
+	Call CallCommon
+}
+
+// The BinOp instruction yields the result of binary operation X Op Y.
+//
+// Pos() returns the ast.BinaryExpr.OpPos, if explicit in the source.
+//
+// Example printed form:
+// 	t1 = t0 + 1:int
+//
+type BinOp struct {
+	register
+	// One of:
+	// ADD SUB MUL QUO REM          + - * / %
+	// AND OR XOR SHL SHR AND_NOT   & | ^ << >> &~
+	// EQL LSS GTR NEQ LEQ GEQ      == != < <= < >=
+	Op   token.Token
+	X, Y Value
+}
+
+// The UnOp instruction yields the result of Op X.
+// ARROW is channel receive.
+// MUL is pointer indirection (load).
+// XOR is bitwise complement.
+// SUB is negation.
+// NOT is logical negation.
+//
+// If CommaOk and Op=ARROW, the result is a 2-tuple of the value above
+// and a boolean indicating the success of the receive.  The
+// components of the tuple are accessed using Extract.
+//
+// Pos() returns the ast.UnaryExpr.OpPos, if explicit in the source.
+// For receive operations (ARROW) implicit in ranging over a channel,
+// Pos() returns the ast.RangeStmt.For.
+// For implicit memory loads (STAR), Pos() returns the position of the
+// most closely associated source-level construct; the details are not
+// specified.
+//
+// Example printed form:
+// 	t0 = *x
+// 	t2 = <-t1,ok
+//
+type UnOp struct {
+	register
+	Op      token.Token // One of: NOT SUB ARROW MUL XOR ! - <- * ^
+	X       Value
+	CommaOk bool
+}
+
+// The ChangeType instruction applies to X a value-preserving type
+// change to Type().
+//
+// Type changes are permitted:
+//    - between a named type and its underlying type.
+//    - between two named types of the same underlying type.
+//    - between (possibly named) pointers to identical base types.
+//    - from a bidirectional channel to a read- or write-channel,
+//      optionally adding/removing a name.
+//
+// This operation cannot fail dynamically.
+//
+// Pos() returns the ast.CallExpr.Lparen, if the instruction arose
+// from an explicit conversion in the source.
+//
+// Example printed form:
+// 	t1 = changetype *int <- IntPtr (t0)
+//
+type ChangeType struct {
+	register
+	X Value
+}
+
+// The Convert instruction yields the conversion of value X to type
+// Type().  One or both of those types is basic (but possibly named).
+//
+// A conversion may change the value and representation of its operand.
+// Conversions are permitted:
+//    - between real numeric types.
+//    - between complex numeric types.
+//    - between string and []byte or []rune.
+//    - between pointers and unsafe.Pointer.
+//    - between unsafe.Pointer and uintptr.
+//    - from (Unicode) integer to (UTF-8) string.
+// A conversion may imply a type name change also.
+//
+// This operation cannot fail dynamically.
+//
+// Conversions of untyped string/number/bool constants to a specific
+// representation are eliminated during SSA construction.
+//
+// Pos() returns the ast.CallExpr.Lparen, if the instruction arose
+// from an explicit conversion in the source.
+//
+// Example printed form:
+// 	t1 = convert []byte <- string (t0)
+//
+type Convert struct {
+	register
+	X Value
+}
+
+// ChangeInterface constructs a value of one interface type from a
+// value of another interface type known to be assignable to it.
+// This operation cannot fail.
+//
+// Pos() returns the ast.CallExpr.Lparen if the instruction arose from
+// an explicit T(e) conversion; the ast.TypeAssertExpr.Lparen if the
+// instruction arose from an explicit e.(T) operation; or token.NoPos
+// otherwise.
+//
+// Example printed form:
+// 	t1 = change interface interface{} <- I (t0)
+//
+type ChangeInterface struct {
+	register
+	X Value
+}
+
+// MakeInterface constructs an instance of an interface type from a
+// value of a concrete type.
+//
+// Use Program.MethodSets.MethodSet(X.Type()) to find the method-set
+// of X, and Program.Method(m) to find the implementation of a method.
+//
+// To construct the zero value of an interface type T, use:
+// 	NewConst(exact.MakeNil(), T, pos)
+//
+// Pos() returns the ast.CallExpr.Lparen, if the instruction arose
+// from an explicit conversion in the source.
+//
+// Example printed form:
+// 	t1 = make interface{} <- int (42:int)
+// 	t2 = make Stringer <- t0
+//
+type MakeInterface struct {
+	register
+	X Value
+}
+
+// The MakeClosure instruction yields a closure value whose code is
+// Fn and whose free variables' values are supplied by Bindings.
+//
+// Type() returns a (possibly named) *types.Signature.
+//
+// Pos() returns the ast.FuncLit.Type.Func for a function literal
+// closure or the ast.SelectorExpr.Sel for a bound method closure.
+//
+// Example printed form:
+// 	t0 = make closure anon@1.2 [x y z]
+// 	t1 = make closure bound$(main.I).add [i]
+//
+type MakeClosure struct {
+	register
+	Fn       Value   // always a *Function
+	Bindings []Value // values for each free variable in Fn.FreeVars
+}
+
+// The MakeMap instruction creates a new hash-table-based map object
+// and yields a value of kind map.
+//
+// Type() returns a (possibly named) *types.Map.
+//
+// Pos() returns the ast.CallExpr.Lparen, if created by make(map), or
+// the ast.CompositeLit.Lbrack if created by a literal.
+//
+// Example printed form:
+// 	t1 = make map[string]int t0
+// 	t1 = make StringIntMap t0
+//
+type MakeMap struct {
+	register
+	Reserve Value // initial space reservation; nil => default
+}
+
+// The MakeChan instruction creates a new channel object and yields a
+// value of kind chan.
+//
+// Type() returns a (possibly named) *types.Chan.
+//
+// Pos() returns the ast.CallExpr.Lparen for the make(chan) that
+// created it.
+//
+// Example printed form:
+// 	t0 = make chan int 0
+// 	t0 = make IntChan 0
+//
+type MakeChan struct {
+	register
+	Size Value // int; size of buffer; zero => synchronous.
+}
+
+// The MakeSlice instruction yields a slice of length Len backed by a
+// newly allocated array of length Cap.
+//
+// Both Len and Cap must be non-nil Values of integer type.
+//
+// (Alloc(types.Array) followed by Slice will not suffice because
+// Alloc can only create arrays of constant length.)
+//
+// Type() returns a (possibly named) *types.Slice.
+//
+// Pos() returns the ast.CallExpr.Lparen for the make([]T) that
+// created it.
+//
+// Example printed form:
+// 	t1 = make []string 1:int t0
+// 	t1 = make StringSlice 1:int t0
+//
+type MakeSlice struct {
+	register
+	Len Value
+	Cap Value
+}
+
+// The Slice instruction yields a slice of an existing string, slice
+// or *array X between optional integer bounds Low and High.
+//
+// Dynamically, this instruction panics if X evaluates to a nil *array
+// pointer.
+//
+// Type() returns string if the type of X was string, otherwise a
+// *types.Slice with the same element type as X.
+//
+// Pos() returns the ast.SliceExpr.Lbrack if created by a x[:] slice
+// operation, the ast.CompositeLit.Lbrace if created by a literal, or
+// NoPos if not explicit in the source (e.g. a variadic argument slice).
+//
+// Example printed form:
+// 	t1 = slice t0[1:]
+//
+type Slice struct {
+	register
+	X              Value // slice, string, or *array
+	Low, High, Max Value // each may be nil
+}
+
+// The FieldAddr instruction yields the address of Field of *struct X.
+//
+// The field is identified by its index within the field list of the
+// struct type of X.
+//
+// Dynamically, this instruction panics if X evaluates to a nil
+// pointer.
+//
+// Type() returns a (possibly named) *types.Pointer.
+//
+// Pos() returns the position of the ast.SelectorExpr.Sel for the
+// field, if explicit in the source.
+//
+// Example printed form:
+// 	t1 = &t0.name [#1]
+//
+type FieldAddr struct {
+	register
+	X     Value // *struct
+	Field int   // index into X.Type().Deref().(*types.Struct).Fields
+}
+
+// The Field instruction yields the Field of struct X.
+//
+// The field is identified by its index within the field list of the
+// struct type of X; by using numeric indices we avoid ambiguity of
+// package-local identifiers and permit compact representations.
+//
+// Pos() returns the position of the ast.SelectorExpr.Sel for the
+// field, if explicit in the source.
+//
+// Example printed form:
+// 	t1 = t0.name [#1]
+//
+type Field struct {
+	register
+	X     Value // struct
+	Field int   // index into X.Type().(*types.Struct).Fields
+}
+
+// The IndexAddr instruction yields the address of the element at
+// index Index of collection X.  Index is an integer expression.
+//
+// The elements of maps and strings are not addressable; use Lookup or
+// MapUpdate instead.
+//
+// Dynamically, this instruction panics if X evaluates to a nil *array
+// pointer.
+//
+// Type() returns a (possibly named) *types.Pointer.
+//
+// Pos() returns the ast.IndexExpr.Lbrack for the index operation, if
+// explicit in the source.
+//
+// Example printed form:
+// 	t2 = &t0[t1]
+//
+type IndexAddr struct {
+	register
+	X     Value // slice or *array,
+	Index Value // numeric index
+}
+
+// The Index instruction yields element Index of array X.
+//
+// Pos() returns the ast.IndexExpr.Lbrack for the index operation, if
+// explicit in the source.
+//
+// Example printed form:
+// 	t2 = t0[t1]
+//
+type Index struct {
+	register
+	X     Value // array
+	Index Value // integer index
+}
+
+// The Lookup instruction yields element Index of collection X, a map
+// or string.  Index is an integer expression if X is a string or the
+// appropriate key type if X is a map.
+//
+// If CommaOk, the result is a 2-tuple of the value above and a
+// boolean indicating the result of a map membership test for the key.
+// The components of the tuple are accessed using Extract.
+//
+// Pos() returns the ast.IndexExpr.Lbrack, if explicit in the source.
+//
+// Example printed form:
+// 	t2 = t0[t1]
+// 	t5 = t3[t4],ok
+//
+type Lookup struct {
+	register
+	X       Value // string or map
+	Index   Value // numeric or key-typed index
+	CommaOk bool  // return a value,ok pair
+}
+
+// SelectState is a helper for Select.
+// It represents one goal state and its corresponding communication.
+//
+type SelectState struct {
+	Dir       types.ChanDir // direction of case (SendOnly or RecvOnly)
+	Chan      Value         // channel to use (for send or receive)
+	Send      Value         // value to send (for send)
+	Pos       token.Pos     // position of token.ARROW
+	DebugNode ast.Node      // ast.SendStmt or ast.UnaryExpr(<-) [debug mode]
+}
+
+// The Select instruction tests whether (or blocks until) one
+// of the specified sent or received states is entered.
+//
+// Let n be the number of States for which Dir==RECV and T_i (0<=i<n)
+// be the element type of each such state's Chan.
+// Select returns an n+2-tuple
+//    (index int, recvOk bool, r_0 T_0, ... r_n-1 T_n-1)
+// The tuple's components, described below, must be accessed via the
+// Extract instruction.
+//
+// If Blocking, select waits until exactly one state holds, i.e. a
+// channel becomes ready for the designated operation of sending or
+// receiving; select chooses one among the ready states
+// pseudorandomly, performs the send or receive operation, and sets
+// 'index' to the index of the chosen channel.
+//
+// If !Blocking, select doesn't block if no states hold; instead it
+// returns immediately with index equal to -1.
+//
+// If the chosen channel was used for a receive, the r_i component is
+// set to the received value, where i is the index of that state among
+// all n receive states; otherwise r_i has the zero value of type T_i.
+// Note that the receive index i is not the same as the state
+// index index.
+//
+// The second component of the triple, recvOk, is a boolean whose value
+// is true iff the selected operation was a receive and the receive
+// successfully yielded a value.
+//
+// Pos() returns the ast.SelectStmt.Select.
+//
+// Example printed form:
+// 	t3 = select nonblocking [<-t0, t1<-t2]
+// 	t4 = select blocking []
+//
+type Select struct {
+	register
+	States   []*SelectState
+	Blocking bool
+}
+
+// The Range instruction yields an iterator over the domain and range
+// of X, which must be a string or map.
+//
+// Elements are accessed via Next.
+//
+// Type() returns an opaque and degenerate "rangeIter" type.
+//
+// Pos() returns the ast.RangeStmt.For.
+//
+// Example printed form:
+// 	t0 = range "hello":string
+//
+type Range struct {
+	register
+	X Value // string or map
+}
+
+// The Next instruction reads and advances the (map or string)
+// iterator Iter and returns a 3-tuple value (ok, k, v).  If the
+// iterator is not exhausted, ok is true and k and v are the next
+// elements of the domain and range, respectively.  Otherwise ok is
+// false and k and v are undefined.
+//
+// Components of the tuple are accessed using Extract.
+//
+// The IsString field distinguishes iterators over strings from those
+// over maps, as the Type() alone is insufficient: consider
+// map[int]rune.
+//
+// Type() returns a *types.Tuple for the triple (ok, k, v).
+// The types of k and/or v may be types.Invalid.
+//
+// Example printed form:
+// 	t1 = next t0
+//
+type Next struct {
+	register
+	Iter     Value
+	IsString bool // true => string iterator; false => map iterator.
+}
+
+// The TypeAssert instruction tests whether interface value X has type
+// AssertedType.
+//
+// If !CommaOk, on success it returns v, the result of the conversion
+// (defined below); on failure it panics.
+//
+// If CommaOk: on success it returns a pair (v, true) where v is the
+// result of the conversion; on failure it returns (z, false) where z
+// is AssertedType's zero value.  The components of the pair must be
+// accessed using the Extract instruction.
+//
+// If AssertedType is a concrete type, TypeAssert checks whether the
+// dynamic type in interface X is equal to it, and if so, the result
+// of the conversion is a copy of the value in the interface.
+//
+// If AssertedType is an interface, TypeAssert checks whether the
+// dynamic type of the interface is assignable to it, and if so, the
+// result of the conversion is a copy of the interface value X.
+// If AssertedType is a superinterface of X.Type(), the operation will
+// fail iff the operand is nil.  (Contrast with ChangeInterface, which
+// performs no nil-check.)
+//
+// Type() reflects the actual type of the result, possibly a
+// 2-types.Tuple; AssertedType is the asserted type.
+//
+// Pos() returns the ast.CallExpr.Lparen if the instruction arose from
+// an explicit T(e) conversion; the ast.TypeAssertExpr.Lparen if the
+// instruction arose from an explicit e.(T) operation; or the
+// ast.CaseClause.Case if the instruction arose from a case of a
+// type-switch statement.
+//
+// Example printed form:
+// 	t1 = typeassert t0.(int)
+// 	t3 = typeassert,ok t2.(T)
+//
+type TypeAssert struct {
+	register
+	X            Value
+	AssertedType types.Type
+	CommaOk      bool
+}
+
+// The Extract instruction yields component Index of Tuple.
+//
+// This is used to access the results of instructions with multiple
+// return values, such as Call, TypeAssert, Next, UnOp(ARROW) and
+// IndexExpr(Map).
+//
+// Example printed form:
+// 	t1 = extract t0 #1
+//
+type Extract struct {
+	register
+	Tuple Value
+	Index int
+}
+
+// Instructions executed for effect.  They do not yield a value. --------------------
+
+// The Jump instruction transfers control to the sole successor of its
+// owning block.
+//
+// A Jump must be the last instruction of its containing BasicBlock.
+//
+// Pos() returns NoPos.
+//
+// Example printed form:
+// 	jump done
+//
+type Jump struct {
+	anInstruction
+}
+
+// The If instruction transfers control to one of the two successors
+// of its owning block, depending on the boolean Cond: the first if
+// true, the second if false.
+//
+// An If instruction must be the last instruction of its containing
+// BasicBlock.
+//
+// Pos() returns NoPos.
+//
+// Example printed form:
+// 	if t0 goto done else body
+//
+type If struct {
+	anInstruction
+	Cond Value
+}
+
+// The Return instruction returns values and control back to the calling
+// function.
+//
+// len(Results) is always equal to the number of results in the
+// function's signature.
+//
+// If len(Results) > 1, Return returns a tuple value with the specified
+// components which the caller must access using Extract instructions.
+//
+// There is no instruction to return a ready-made tuple like those
+// returned by a "value,ok"-mode TypeAssert, Lookup or UnOp(ARROW) or
+// a tail-call to a function with multiple result parameters.
+//
+// Return must be the last instruction of its containing BasicBlock.
+// Such a block has no successors.
+//
+// Pos() returns the ast.ReturnStmt.Return, if explicit in the source.
+//
+// Example printed form:
+// 	return
+// 	return nil:I, 2:int
+//
+type Return struct {
+	anInstruction
+	Results []Value
+	pos     token.Pos
+}
+
+// The RunDefers instruction pops and invokes the entire stack of
+// procedure calls pushed by Defer instructions in this function.
+//
+// It is legal to encounter multiple 'rundefers' instructions in a
+// single control-flow path through a function; this is useful in
+// the combined init() function, for example.
+//
+// Pos() returns NoPos.
+//
+// Example printed form:
+//	rundefers
+//
+type RunDefers struct {
+	anInstruction
+}
+
+// The Panic instruction initiates a panic with value X.
+//
+// A Panic instruction must be the last instruction of its containing
+// BasicBlock, which must have no successors.
+//
+// NB: 'go panic(x)' and 'defer panic(x)' do not use this instruction;
+// they are treated as calls to a built-in function.
+//
+// Pos() returns the ast.CallExpr.Lparen if this panic was explicit
+// in the source.
+//
+// Example printed form:
+// 	panic t0
+//
+type Panic struct {
+	anInstruction
+	X   Value // an interface{}
+	pos token.Pos
+}
+
+// The Go instruction creates a new goroutine and calls the specified
+// function within it.
+//
+// See CallCommon for generic function call documentation.
+//
+// Pos() returns the ast.GoStmt.Go.
+//
+// Example printed form:
+// 	go println(t0, t1)
+// 	go t3()
+// 	go invoke t5.Println(...t6)
+//
+type Go struct {
+	anInstruction
+	Call CallCommon
+	pos  token.Pos
+}
+
+// The Defer instruction pushes the specified call onto a stack of
+// functions to be called by a RunDefers instruction or by a panic.
+//
+// See CallCommon for generic function call documentation.
+//
+// Pos() returns the ast.DeferStmt.Defer.
+//
+// Example printed form:
+// 	defer println(t0, t1)
+// 	defer t3()
+// 	defer invoke t5.Println(...t6)
+//
+type Defer struct {
+	anInstruction
+	Call CallCommon
+	pos  token.Pos
+}
+
+// The Send instruction sends X on channel Chan.
+//
+// Pos() returns the ast.SendStmt.Arrow, if explicit in the source.
+//
+// Example printed form:
+// 	send t0 <- t1
+//
+type Send struct {
+	anInstruction
+	Chan, X Value
+	pos     token.Pos
+}
+
+// The Store instruction stores Val at address Addr.
+// Stores can be of arbitrary types.
+//
+// Pos() returns the position of the source-level construct most closely
+// associated with the memory store operation.
+// Since implicit memory stores are numerous and varied and depend upon
+// implementation choices, the details are not specified.
+//
+// Example printed form:
+// 	*x = y
+//
+type Store struct {
+	anInstruction
+	Addr Value
+	Val  Value
+	pos  token.Pos
+}
+
+// The MapUpdate instruction updates the association of Map[Key] to
+// Value.
+//
+// Pos() returns the ast.KeyValueExpr.Colon or ast.IndexExpr.Lbrack,
+// if explicit in the source.
+//
+// Example printed form:
+//	t0[t1] = t2
+//
+type MapUpdate struct {
+	anInstruction
+	Map   Value
+	Key   Value
+	Value Value
+	pos   token.Pos
+}
+
+// A DebugRef instruction maps a source-level expression Expr to the
+// SSA value X that represents the value (!IsAddr) or address (IsAddr)
+// of that expression.
+//
+// DebugRef is a pseudo-instruction: it has no dynamic effect.
+//
+// Pos() returns Expr.Pos(), the start position of the source-level
+// expression.  This is not the same as the "designated" token as
+// documented at Value.Pos(). e.g. CallExpr.Pos() does not return the
+// position of the ("designated") Lparen token.
+//
+// If Expr is an *ast.Ident denoting a var or func, Object() returns
+// the object; though this information can be obtained from the type
+// checker, including it here greatly facilitates debugging.
+// For non-Ident expressions, Object() returns nil.
+//
+// DebugRefs are generated only for functions built with debugging
+// enabled; see Package.SetDebugMode() and the GlobalDebug builder
+// mode flag.
+//
+// DebugRefs are not emitted for ast.Idents referring to constants or
+// predeclared identifiers, since they are trivial and numerous.
+// Nor are they emitted for ast.ParenExprs.
+//
+// (By representing these as instructions, rather than out-of-band,
+// consistency is maintained during transformation passes by the
+// ordinary SSA renaming machinery.)
+//
+// Example printed form:
+//      ; *ast.CallExpr @ 102:9 is t5
+//      ; var x float64 @ 109:72 is x
+//      ; address of *ast.CompositeLit @ 216:10 is t0
+//
+type DebugRef struct {
+	anInstruction
+	Expr   ast.Expr     // the referring expression (never *ast.ParenExpr)
+	object types.Object // the identity of the source var/func
+	IsAddr bool         // Expr is addressable and X is the address it denotes
+	X      Value        // the value or address of Expr
+}
+
+// Embeddable mix-ins and helpers for common parts of other structs. -----------
+
+// register is a mix-in embedded by all SSA values that are also
+// instructions, i.e. virtual registers, and provides a uniform
+// implementation of most of the Value interface: Value.Name() is a
+// numbered register (e.g. "t0"); the other methods are field accessors.
+//
+// Temporary names are automatically assigned to each register on
+// completion of building a function in SSA form.
+//
+// Clients must not assume that the 'id' value (and the Name() derived
+// from it) is unique within a function.  As always in this API,
+// semantics are determined only by identity; names exist only to
+// facilitate debugging.
+//
+type register struct {
+	anInstruction
+	num       int        // "name" of virtual register, e.g. "t0".  Not guaranteed unique.
+	typ       types.Type // type of virtual register
+	pos       token.Pos  // position of source expression, or NoPos
+	referrers []Instruction
+}
+
+// anInstruction is a mix-in embedded by all Instructions.
+// It provides the implementations of the Block and setBlock methods.
+type anInstruction struct {
+	block *BasicBlock // the basic block of this instruction
+}
+
+// CallCommon is contained by Go, Defer and Call to hold the
+// common parts of a function or method call.
+//
+// Each CallCommon exists in one of two modes, function call and
+// interface method invocation, or "call" and "invoke" for short.
+//
+// 1. "call" mode: when Method is nil (!IsInvoke), a CallCommon
+// represents an ordinary function call of the value in Value,
+// which may be a *Builtin, a *Function or any other value of kind
+// 'func'.
+//
+// Value may be one of:
+//    (a) a *Function, indicating a statically dispatched call
+//        to a package-level function, an anonymous function, or
+//        a method of a named type.
+//    (b) a *MakeClosure, indicating an immediately applied
+//        function literal with free variables.
+//    (c) a *Builtin, indicating a statically dispatched call
+//        to a built-in function.
+//    (d) any other value, indicating a dynamically dispatched
+//        function call.
+// StaticCallee returns the identity of the callee in cases
+// (a) and (b), nil otherwise.
+//
+// Args contains the arguments to the call.  If Value is a method,
+// Args[0] contains the receiver parameter.
+//
+// Example printed form:
+// 	t2 = println(t0, t1)
+// 	go t3()
+//	defer t5(...t6)
+//
+// 2. "invoke" mode: when Method is non-nil (IsInvoke), a CallCommon
+// represents a dynamically dispatched call to an interface method.
+// In this mode, Value is the interface value and Method is the
+// interface's abstract method.  Note: an abstract method may be
+// shared by multiple interfaces due to embedding; Value.Type()
+// provides the specific interface used for this call.
+//
+// Value is implicitly supplied to the concrete method implementation
+// as the receiver parameter; in other words, Args[0] holds not the
+// receiver but the first true argument.
+//
+// Example printed form:
+// 	t1 = invoke t0.String()
+// 	go invoke t3.Run(t2)
+// 	defer invoke t4.Handle(...t5)
+//
+// For all calls to variadic functions (Signature().Variadic()),
+// the last element of Args is a slice.
+//
+type CallCommon struct {
+	Value  Value       // receiver (invoke mode) or func value (call mode)
+	Method *types.Func // abstract method (invoke mode)
+	Args   []Value     // actual parameters (in static method call, includes receiver)
+	pos    token.Pos   // position of CallExpr.Lparen, iff explicit in source
+}
+
+// IsInvoke returns true if this call has "invoke" (not "call") mode.
+func (c *CallCommon) IsInvoke() bool {
+	return c.Method != nil
+}
+
+func (c *CallCommon) Pos() token.Pos { return c.pos }
+
+// Signature returns the signature of the called function.
+//
+// For an "invoke"-mode call, the signature of the interface method is
+// returned.
+//
+// In either "call" or "invoke" mode, if the callee is a method, its
+// receiver is represented by sig.Recv, not sig.Params().At(0).
+//
+func (c *CallCommon) Signature() *types.Signature {
+	if c.Method != nil {
+		return c.Method.Type().(*types.Signature)
+	}
+	return c.Value.Type().Underlying().(*types.Signature)
+}
+
+// StaticCallee returns the callee if this is a trivially static
+// "call"-mode call to a function.
+func (c *CallCommon) StaticCallee() *Function {
+	switch fn := c.Value.(type) {
+	case *Function:
+		return fn
+	case *MakeClosure:
+		return fn.Fn.(*Function)
+	}
+	return nil
+}
+
+// Description returns a description of the mode of this call suitable
+// for a user interface, e.g., "static method call".
+func (c *CallCommon) Description() string {
+	switch fn := c.Value.(type) {
+	case *Builtin:
+		return "built-in function call"
+	case *MakeClosure:
+		return "static function closure call"
+	case *Function:
+		if fn.Signature.Recv() != nil {
+			return "static method call"
+		}
+		return "static function call"
+	}
+	if c.IsInvoke() {
+		return "dynamic method call" // ("invoke" mode)
+	}
+	return "dynamic function call"
+}
+
+// The CallInstruction interface, implemented by *Go, *Defer and *Call,
+// exposes the common parts of function-calling instructions,
+// yet provides a way back to the Value defined by *Call alone.
+//
+type CallInstruction interface {
+	Instruction
+	Common() *CallCommon // returns the common parts of the call
+	Value() *Call        // returns the result value of the call (*Call) or nil (*Go, *Defer)
+}
+
+func (s *Call) Common() *CallCommon  { return &s.Call }
+func (s *Defer) Common() *CallCommon { return &s.Call }
+func (s *Go) Common() *CallCommon    { return &s.Call }
+
+func (s *Call) Value() *Call  { return s }
+func (s *Defer) Value() *Call { return nil }
+func (s *Go) Value() *Call    { return nil }
+
+func (v *Builtin) Type() types.Type        { return v.sig }
+func (v *Builtin) Name() string            { return v.name }
+func (*Builtin) Referrers() *[]Instruction { return nil }
+func (v *Builtin) Pos() token.Pos          { return token.NoPos }
+func (v *Builtin) Object() types.Object    { return types.Universe.Lookup(v.name) }
+func (v *Builtin) Parent() *Function       { return nil }
+
+func (v *FreeVar) Type() types.Type          { return v.typ }
+func (v *FreeVar) Name() string              { return v.name }
+func (v *FreeVar) Referrers() *[]Instruction { return &v.referrers }
+func (v *FreeVar) Pos() token.Pos            { return v.pos }
+func (v *FreeVar) Parent() *Function         { return v.parent }
+
+func (v *Global) Type() types.Type                     { return v.typ }
+func (v *Global) Name() string                         { return v.name }
+func (v *Global) Parent() *Function                    { return nil }
+func (v *Global) Pos() token.Pos                       { return v.pos }
+func (v *Global) Referrers() *[]Instruction            { return nil }
+func (v *Global) Token() token.Token                   { return token.VAR }
+func (v *Global) Object() types.Object                 { return v.object }
+func (v *Global) String() string                       { return v.RelString(nil) }
+func (v *Global) Package() *Package                    { return v.Pkg }
+func (v *Global) RelString(from *types.Package) string { return relString(v, from) }
+
+func (v *Function) Name() string         { return v.name }
+func (v *Function) Type() types.Type     { return v.Signature }
+func (v *Function) Pos() token.Pos       { return v.pos }
+func (v *Function) Token() token.Token   { return token.FUNC }
+func (v *Function) Object() types.Object { return v.object }
+func (v *Function) String() string       { return v.RelString(nil) }
+func (v *Function) Package() *Package    { return v.Pkg }
+func (v *Function) Parent() *Function    { return v.parent }
+func (v *Function) Referrers() *[]Instruction {
+	if v.parent != nil {
+		return &v.referrers
+	}
+	return nil
+}
+
+func (v *Parameter) Type() types.Type          { return v.typ }
+func (v *Parameter) Name() string              { return v.name }
+func (v *Parameter) Object() types.Object      { return v.object }
+func (v *Parameter) Referrers() *[]Instruction { return &v.referrers }
+func (v *Parameter) Pos() token.Pos            { return v.pos }
+func (v *Parameter) Parent() *Function         { return v.parent }
+
+func (v *Alloc) Type() types.Type          { return v.typ }
+func (v *Alloc) Referrers() *[]Instruction { return &v.referrers }
+func (v *Alloc) Pos() token.Pos            { return v.pos }
+
+func (v *register) Type() types.Type          { return v.typ }
+func (v *register) setType(typ types.Type)    { v.typ = typ }
+func (v *register) Name() string              { return fmt.Sprintf("t%d", v.num) }
+func (v *register) setNum(num int)            { v.num = num }
+func (v *register) Referrers() *[]Instruction { return &v.referrers }
+func (v *register) Pos() token.Pos            { return v.pos }
+func (v *register) setPos(pos token.Pos)      { v.pos = pos }
+
+func (v *anInstruction) Parent() *Function          { return v.block.parent }
+func (v *anInstruction) Block() *BasicBlock         { return v.block }
+func (v *anInstruction) setBlock(block *BasicBlock) { v.block = block }
+func (v *anInstruction) Referrers() *[]Instruction  { return nil }
+
+func (t *Type) Name() string                         { return t.object.Name() }
+func (t *Type) Pos() token.Pos                       { return t.object.Pos() }
+func (t *Type) Type() types.Type                     { return t.object.Type() }
+func (t *Type) Token() token.Token                   { return token.TYPE }
+func (t *Type) Object() types.Object                 { return t.object }
+func (t *Type) String() string                       { return t.RelString(nil) }
+func (t *Type) Package() *Package                    { return t.pkg }
+func (t *Type) RelString(from *types.Package) string { return relString(t, from) }
+
+func (c *NamedConst) Name() string                         { return c.object.Name() }
+func (c *NamedConst) Pos() token.Pos                       { return c.object.Pos() }
+func (c *NamedConst) String() string                       { return c.RelString(nil) }
+func (c *NamedConst) Type() types.Type                     { return c.object.Type() }
+func (c *NamedConst) Token() token.Token                   { return token.CONST }
+func (c *NamedConst) Object() types.Object                 { return c.object }
+func (c *NamedConst) Package() *Package                    { return c.pkg }
+func (c *NamedConst) RelString(from *types.Package) string { return relString(c, from) }
+
+// Func returns the package-level function of the specified name,
+// or nil if not found.
+//
+func (p *Package) Func(name string) (f *Function) {
+	f, _ = p.Members[name].(*Function)
+	return
+}
+
+// Var returns the package-level variable of the specified name,
+// or nil if not found.
+//
+func (p *Package) Var(name string) (g *Global) {
+	g, _ = p.Members[name].(*Global)
+	return
+}
+
+// Const returns the package-level constant of the specified name,
+// or nil if not found.
+//
+func (p *Package) Const(name string) (c *NamedConst) {
+	c, _ = p.Members[name].(*NamedConst)
+	return
+}
+
+// Type returns the package-level type of the specified name,
+// or nil if not found.
+//
+func (p *Package) Type(name string) (t *Type) {
+	t, _ = p.Members[name].(*Type)
+	return
+}
+
+func (v *Call) Pos() token.Pos      { return v.Call.pos }
+func (s *Defer) Pos() token.Pos     { return s.pos }
+func (s *Go) Pos() token.Pos        { return s.pos }
+func (s *MapUpdate) Pos() token.Pos { return s.pos }
+func (s *Panic) Pos() token.Pos     { return s.pos }
+func (s *Return) Pos() token.Pos    { return s.pos }
+func (s *Send) Pos() token.Pos      { return s.pos }
+func (s *Store) Pos() token.Pos     { return s.pos }
+func (s *If) Pos() token.Pos        { return token.NoPos }
+func (s *Jump) Pos() token.Pos      { return token.NoPos }
+func (s *RunDefers) Pos() token.Pos { return token.NoPos }
+func (s *DebugRef) Pos() token.Pos  { return s.Expr.Pos() }
+
+// Operands.
+
+func (v *Alloc) Operands(rands []*Value) []*Value {
+	return rands
+}
+
+func (v *BinOp) Operands(rands []*Value) []*Value {
+	return append(rands, &v.X, &v.Y)
+}
+
+func (c *CallCommon) Operands(rands []*Value) []*Value {
+	rands = append(rands, &c.Value)
+	for i := range c.Args {
+		rands = append(rands, &c.Args[i])
+	}
+	return rands
+}
+
+func (s *Go) Operands(rands []*Value) []*Value {
+	return s.Call.Operands(rands)
+}
+
+func (s *Call) Operands(rands []*Value) []*Value {
+	return s.Call.Operands(rands)
+}
+
+func (s *Defer) Operands(rands []*Value) []*Value {
+	return s.Call.Operands(rands)
+}
+
+func (v *ChangeInterface) Operands(rands []*Value) []*Value {
+	return append(rands, &v.X)
+}
+
+func (v *ChangeType) Operands(rands []*Value) []*Value {
+	return append(rands, &v.X)
+}
+
+func (v *Convert) Operands(rands []*Value) []*Value {
+	return append(rands, &v.X)
+}
+
+func (s *DebugRef) Operands(rands []*Value) []*Value {
+	return append(rands, &s.X)
+}
+
+func (v *Extract) Operands(rands []*Value) []*Value {
+	return append(rands, &v.Tuple)
+}
+
+func (v *Field) Operands(rands []*Value) []*Value {
+	return append(rands, &v.X)
+}
+
+func (v *FieldAddr) Operands(rands []*Value) []*Value {
+	return append(rands, &v.X)
+}
+
+func (s *If) Operands(rands []*Value) []*Value {
+	return append(rands, &s.Cond)
+}
+
+func (v *Index) Operands(rands []*Value) []*Value {
+	return append(rands, &v.X, &v.Index)
+}
+
+func (v *IndexAddr) Operands(rands []*Value) []*Value {
+	return append(rands, &v.X, &v.Index)
+}
+
+func (*Jump) Operands(rands []*Value) []*Value {
+	return rands
+}
+
+func (v *Lookup) Operands(rands []*Value) []*Value {
+	return append(rands, &v.X, &v.Index)
+}
+
+func (v *MakeChan) Operands(rands []*Value) []*Value {
+	return append(rands, &v.Size)
+}
+
+func (v *MakeClosure) Operands(rands []*Value) []*Value {
+	rands = append(rands, &v.Fn)
+	for i := range v.Bindings {
+		rands = append(rands, &v.Bindings[i])
+	}
+	return rands
+}
+
+func (v *MakeInterface) Operands(rands []*Value) []*Value {
+	return append(rands, &v.X)
+}
+
+func (v *MakeMap) Operands(rands []*Value) []*Value {
+	return append(rands, &v.Reserve)
+}
+
+func (v *MakeSlice) Operands(rands []*Value) []*Value {
+	return append(rands, &v.Len, &v.Cap)
+}
+
+func (v *MapUpdate) Operands(rands []*Value) []*Value {
+	return append(rands, &v.Map, &v.Key, &v.Value)
+}
+
+func (v *Next) Operands(rands []*Value) []*Value {
+	return append(rands, &v.Iter)
+}
+
+func (s *Panic) Operands(rands []*Value) []*Value {
+	return append(rands, &s.X)
+}
+
+func (v *Phi) Operands(rands []*Value) []*Value {
+	for i := range v.Edges {
+		rands = append(rands, &v.Edges[i])
+	}
+	return rands
+}
+
+func (v *Range) Operands(rands []*Value) []*Value {
+	return append(rands, &v.X)
+}
+
+func (s *Return) Operands(rands []*Value) []*Value {
+	for i := range s.Results {
+		rands = append(rands, &s.Results[i])
+	}
+	return rands
+}
+
+func (*RunDefers) Operands(rands []*Value) []*Value {
+	return rands
+}
+
+func (v *Select) Operands(rands []*Value) []*Value {
+	for i := range v.States {
+		rands = append(rands, &v.States[i].Chan, &v.States[i].Send)
+	}
+	return rands
+}
+
+func (s *Send) Operands(rands []*Value) []*Value {
+	return append(rands, &s.Chan, &s.X)
+}
+
+func (v *Slice) Operands(rands []*Value) []*Value {
+	return append(rands, &v.X, &v.Low, &v.High, &v.Max)
+}
+
+func (s *Store) Operands(rands []*Value) []*Value {
+	return append(rands, &s.Addr, &s.Val)
+}
+
+func (v *TypeAssert) Operands(rands []*Value) []*Value {
+	return append(rands, &v.X)
+}
+
+func (v *UnOp) Operands(rands []*Value) []*Value {
+	return append(rands, &v.X)
+}
+
+// Non-Instruction Values:
+func (v *Builtin) Operands(rands []*Value) []*Value   { return rands }
+func (v *FreeVar) Operands(rands []*Value) []*Value   { return rands }
+func (v *Const) Operands(rands []*Value) []*Value     { return rands }
+func (v *Function) Operands(rands []*Value) []*Value  { return rands }
+func (v *Global) Operands(rands []*Value) []*Value    { return rands }
+func (v *Parameter) Operands(rands []*Value) []*Value { return rands }
diff --git a/go/ssa/ssautil/load.go b/go/ssa/ssautil/load.go
new file mode 100644
index 0000000..c2b8ce1
--- /dev/null
+++ b/go/ssa/ssautil/load.go
@@ -0,0 +1,95 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssautil
+
+// This file defines utility functions for constructing programs in SSA form.
+
+import (
+	"go/ast"
+	"go/token"
+
+	"golang.org/x/tools/go/loader"
+	"golang.org/x/tools/go/ssa"
+	"golang.org/x/tools/go/types"
+)
+
+// CreateProgram returns a new program in SSA form, given a program
+// loaded from source.  An SSA package is created for each transitively
+// error-free package of lprog.
+//
+// Code for bodies of functions is not built until BuildAll() is called
+// on the result.
+//
+// mode controls diagnostics and checking during SSA construction.
+//
+func CreateProgram(lprog *loader.Program, mode ssa.BuilderMode) *ssa.Program {
+	prog := ssa.NewProgram(lprog.Fset, mode)
+
+	for _, info := range lprog.AllPackages {
+		if info.TransitivelyErrorFree {
+			prog.CreatePackage(info.Pkg, info.Files, &info.Info, info.Importable)
+		}
+	}
+
+	return prog
+}
+
+// BuildPackage builds an SSA program with IR for a single package.
+//
+// It populates pkg by type-checking the specified file ASTs.  All
+// dependencies are loaded using the importer specified by tc, which
+// typically loads compiler export data; SSA code cannot be built for
+// those packages.  BuildPackage then constructs an ssa.Program with all
+// dependency packages created, and builds and returns the SSA package
+// corresponding to pkg.
+//
+// The caller must have set pkg.Path() to the import path.
+//
+// The operation fails if there were any type-checking or import errors.
+//
+// See ../ssa/example_test.go for an example.
+//
+func BuildPackage(tc *types.Config, fset *token.FileSet, pkg *types.Package, files []*ast.File, mode ssa.BuilderMode) (*ssa.Package, *types.Info, error) {
+	if fset == nil {
+		panic("no token.FileSet")
+	}
+	if pkg.Path() == "" {
+		panic("package has no import path")
+	}
+
+	info := &types.Info{
+		Types:      make(map[ast.Expr]types.TypeAndValue),
+		Defs:       make(map[*ast.Ident]types.Object),
+		Uses:       make(map[*ast.Ident]types.Object),
+		Implicits:  make(map[ast.Node]types.Object),
+		Scopes:     make(map[ast.Node]*types.Scope),
+		Selections: make(map[*ast.SelectorExpr]*types.Selection),
+	}
+	if err := types.NewChecker(tc, fset, pkg, info).Files(files); err != nil {
+		return nil, nil, err
+	}
+
+	prog := ssa.NewProgram(fset, mode)
+
+	// Create SSA packages for all imports.
+	// Order is not significant.
+	created := make(map[*types.Package]bool)
+	var createAll func(pkgs []*types.Package)
+	createAll = func(pkgs []*types.Package) {
+		for _, p := range pkgs {
+			if !created[p] {
+				created[p] = true
+				prog.CreatePackage(p, nil, nil, true)
+				createAll(p.Imports())
+			}
+		}
+	}
+	createAll(pkg.Imports())
+
+	// Create and build the primary package.
+	ssapkg := prog.CreatePackage(pkg, files, info, false)
+	ssapkg.Build()
+	return ssapkg, info, nil
+}
diff --git a/go/ssa/ssautil/load_test.go b/go/ssa/ssautil/load_test.go
new file mode 100644
index 0000000..458d2dc
--- /dev/null
+++ b/go/ssa/ssautil/load_test.go
@@ -0,0 +1,65 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssautil_test
+
+import (
+	"go/ast"
+	"go/parser"
+	"go/token"
+	"os"
+	"testing"
+
+	"golang.org/x/tools/go/ssa/ssautil"
+	"golang.org/x/tools/go/types"
+
+	_ "golang.org/x/tools/go/gcimporter"
+)
+
+const hello = `package main
+
+import "fmt"
+
+func main() {
+	fmt.Println("Hello, world")
+}
+`
+
+func TestBuildPackage(t *testing.T) {
+	// There is a more substantial test of BuildPackage and the
+	// SSA program it builds in ../ssa/builder_test.go.
+
+	fset := token.NewFileSet()
+	f, err := parser.ParseFile(fset, "hello.go", hello, 0)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	pkg := types.NewPackage("hello", "")
+	ssapkg, _, err := ssautil.BuildPackage(new(types.Config), fset, pkg, []*ast.File{f}, 0)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if pkg.Name() != "main" {
+		t.Errorf("pkg.Name() = %s, want main", pkg.Name())
+	}
+	if ssapkg.Func("main") == nil {
+		ssapkg.WriteTo(os.Stderr)
+		t.Errorf("ssapkg has no main function")
+	}
+}
+
+func TestBuildPackage_MissingImport(t *testing.T) {
+	fset := token.NewFileSet()
+	f, err := parser.ParseFile(fset, "bad.go", `package bad; import "missing"`, 0)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	pkg := types.NewPackage("bad", "")
+	ssapkg, _, err := ssautil.BuildPackage(new(types.Config), fset, pkg, []*ast.File{f}, 0)
+	if err == nil || ssapkg != nil {
+		t.Fatal("BuildPackage succeeded unexpectedly")
+	}
+}
diff --git a/go/ssa/ssautil/switch.go b/go/ssa/ssautil/switch.go
new file mode 100644
index 0000000..70fff9c
--- /dev/null
+++ b/go/ssa/ssautil/switch.go
@@ -0,0 +1,234 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssautil
+
+// This file implements discovery of switch and type-switch constructs
+// from low-level control flow.
+//
+// Many techniques exist for compiling a high-level switch with
+// constant cases to efficient machine code.  The optimal choice will
+// depend on the data type, the specific case values, the code in the
+// body of each case, and the hardware.
+// Some examples:
+// - a lookup table (for a switch that maps constants to constants)
+// - a computed goto
+// - a binary tree
+// - a perfect hash
+// - a two-level switch (to partition constant strings by their first byte).
+
+import (
+	"bytes"
+	"fmt"
+	"go/token"
+
+	"golang.org/x/tools/go/ssa"
+	"golang.org/x/tools/go/types"
+)
+
+// A ConstCase represents a single constant comparison.
+// It is part of a Switch.
+type ConstCase struct {
+	Block *ssa.BasicBlock // block performing the comparison
+	Body  *ssa.BasicBlock // body of the case
+	Value *ssa.Const      // case comparand
+}
+
+// A TypeCase represents a single type assertion.
+// It is part of a Switch.
+type TypeCase struct {
+	Block   *ssa.BasicBlock // block performing the type assert
+	Body    *ssa.BasicBlock // body of the case
+	Type    types.Type      // case type
+	Binding ssa.Value       // value bound by this case
+}
+
+// A Switch is a logical high-level control flow operation
+// (a multiway branch) discovered by analysis of a CFG containing
+// only if/else chains.  It is not part of the ssa.Instruction set.
+//
+// One of ConstCases and TypeCases has length >= 2;
+// the other is nil.
+//
+// In a value switch, the list of cases may contain duplicate constants.
+// A type switch may contain duplicate types, or types assignable
+// to an interface type also in the list.
+// TODO(adonovan): eliminate such duplicates.
+//
+type Switch struct {
+	Start      *ssa.BasicBlock // block containing start of if/else chain
+	X          ssa.Value       // the switch operand
+	ConstCases []ConstCase     // ordered list of constant comparisons
+	TypeCases  []TypeCase      // ordered list of type assertions
+	Default    *ssa.BasicBlock // successor if all comparisons fail
+}
+
+func (sw *Switch) String() string {
+	// We represent each block by the String() of its
+	// first Instruction, e.g. "print(42:int)".
+	var buf bytes.Buffer
+	if sw.ConstCases != nil {
+		fmt.Fprintf(&buf, "switch %s {\n", sw.X.Name())
+		for _, c := range sw.ConstCases {
+			fmt.Fprintf(&buf, "case %s: %s\n", c.Value, c.Body.Instrs[0])
+		}
+	} else {
+		fmt.Fprintf(&buf, "switch %s.(type) {\n", sw.X.Name())
+		for _, c := range sw.TypeCases {
+			fmt.Fprintf(&buf, "case %s %s: %s\n",
+				c.Binding.Name(), c.Type, c.Body.Instrs[0])
+		}
+	}
+	if sw.Default != nil {
+		fmt.Fprintf(&buf, "default: %s\n", sw.Default.Instrs[0])
+	}
+	fmt.Fprintf(&buf, "}")
+	return buf.String()
+}
+
+// Switches examines the control-flow graph of fn and returns the
+// set of inferred value and type switches.  A value switch tests an
+// ssa.Value for equality against two or more compile-time constant
+// values.  Switches involving link-time constants (addresses) are
+// ignored.  A type switch type-asserts an ssa.Value against two or
+// more types.
+//
+// The switches are returned in dominance order.
+//
+// The resulting switches do not necessarily correspond to uses of the
+// 'switch' keyword in the source: for example, a single source-level
+// switch statement with non-constant cases may result in zero, one or
+// many Switches, one per plural sequence of constant cases.
+// Switches may even be inferred from if/else- or goto-based control flow.
+// (In general, the control flow constructs of the source program
+// cannot be faithfully reproduced from the SSA representation.)
+//
+func Switches(fn *ssa.Function) []Switch {
+	// Traverse the CFG in dominance order, so we don't
+	// enter an if/else-chain in the middle.
+	var switches []Switch
+	seen := make(map[*ssa.BasicBlock]bool) // TODO(adonovan): opt: use ssa.blockSet
+	for _, b := range fn.DomPreorder() {
+		if x, k := isComparisonBlock(b); x != nil {
+			// Block b starts a switch.
+			sw := Switch{Start: b, X: x}
+			valueSwitch(&sw, k, seen)
+			if len(sw.ConstCases) > 1 {
+				switches = append(switches, sw)
+			}
+		}
+
+		if y, x, T := isTypeAssertBlock(b); y != nil {
+			// Block b starts a type switch.
+			sw := Switch{Start: b, X: x}
+			typeSwitch(&sw, y, T, seen)
+			if len(sw.TypeCases) > 1 {
+				switches = append(switches, sw)
+			}
+		}
+	}
+	return switches
+}
+
+func valueSwitch(sw *Switch, k *ssa.Const, seen map[*ssa.BasicBlock]bool) {
+	b := sw.Start
+	x := sw.X
+	for x == sw.X {
+		if seen[b] {
+			break
+		}
+		seen[b] = true
+
+		sw.ConstCases = append(sw.ConstCases, ConstCase{
+			Block: b,
+			Body:  b.Succs[0],
+			Value: k,
+		})
+		b = b.Succs[1]
+		if len(b.Instrs) > 2 {
+			// Block b contains not just 'if x == k',
+			// so it may have side effects that
+			// make it unsafe to elide.
+			break
+		}
+		if len(b.Preds) != 1 {
+			// Block b has multiple predecessors,
+			// so it cannot be treated as a case.
+			break
+		}
+		x, k = isComparisonBlock(b)
+	}
+	sw.Default = b
+}
+
+func typeSwitch(sw *Switch, y ssa.Value, T types.Type, seen map[*ssa.BasicBlock]bool) {
+	b := sw.Start
+	x := sw.X
+	for x == sw.X {
+		if seen[b] {
+			break
+		}
+		seen[b] = true
+
+		sw.TypeCases = append(sw.TypeCases, TypeCase{
+			Block:   b,
+			Body:    b.Succs[0],
+			Type:    T,
+			Binding: y,
+		})
+		b = b.Succs[1]
+		if len(b.Instrs) > 4 {
+			// Block b contains not just
+			//  {TypeAssert; Extract #0; Extract #1; If}
+			// so it may have side effects that
+			// make it unsafe to elide.
+			break
+		}
+		if len(b.Preds) != 1 {
+			// Block b has multiple predecessors,
+			// so it cannot be treated as a case.
+			break
+		}
+		y, x, T = isTypeAssertBlock(b)
+	}
+	sw.Default = b
+}
+
+// isComparisonBlock returns the operands (v, k) if a block ends with
+// a comparison v==k, where k is a compile-time constant.
+//
+func isComparisonBlock(b *ssa.BasicBlock) (v ssa.Value, k *ssa.Const) {
+	if n := len(b.Instrs); n >= 2 {
+		if i, ok := b.Instrs[n-1].(*ssa.If); ok {
+			if binop, ok := i.Cond.(*ssa.BinOp); ok && binop.Block() == b && binop.Op == token.EQL {
+				if k, ok := binop.Y.(*ssa.Const); ok {
+					return binop.X, k
+				}
+				if k, ok := binop.X.(*ssa.Const); ok {
+					return binop.Y, k
+				}
+			}
+		}
+	}
+	return
+}
+
+// isTypeAssertBlock returns the operands (y, x, T) if a block ends with
+// a type assertion "if y, ok := x.(T); ok {".
+//
+func isTypeAssertBlock(b *ssa.BasicBlock) (y, x ssa.Value, T types.Type) {
+	if n := len(b.Instrs); n >= 4 {
+		if i, ok := b.Instrs[n-1].(*ssa.If); ok {
+			if ext1, ok := i.Cond.(*ssa.Extract); ok && ext1.Block() == b && ext1.Index == 1 {
+				if ta, ok := ext1.Tuple.(*ssa.TypeAssert); ok && ta.Block() == b {
+					// hack: relies upon instruction ordering.
+					if ext0, ok := b.Instrs[n-3].(*ssa.Extract); ok {
+						return ext0, ta.X, ta.AssertedType
+					}
+				}
+			}
+		}
+	}
+	return
+}
diff --git a/go/ssa/ssautil/switch_test.go b/go/ssa/ssautil/switch_test.go
new file mode 100644
index 0000000..a47dbef
--- /dev/null
+++ b/go/ssa/ssautil/switch_test.go
@@ -0,0 +1,74 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// No testdata on Android.
+
+// +build !android
+
+package ssautil_test
+
+import (
+	"go/parser"
+	"strings"
+	"testing"
+
+	"golang.org/x/tools/go/loader"
+	"golang.org/x/tools/go/ssa"
+	"golang.org/x/tools/go/ssa/ssautil"
+)
+
+func TestSwitches(t *testing.T) {
+	conf := loader.Config{ParserMode: parser.ParseComments}
+	f, err := conf.ParseFile("testdata/switches.go", nil)
+	if err != nil {
+		t.Error(err)
+		return
+	}
+
+	conf.CreateFromFiles("main", f)
+	iprog, err := conf.Load()
+	if err != nil {
+		t.Error(err)
+		return
+	}
+
+	prog := ssautil.CreateProgram(iprog, 0)
+	mainPkg := prog.Package(iprog.Created[0].Pkg)
+	mainPkg.Build()
+
+	for _, mem := range mainPkg.Members {
+		if fn, ok := mem.(*ssa.Function); ok {
+			if fn.Synthetic != "" {
+				continue // e.g. init()
+			}
+			// Each (multi-line) "switch" comment within
+			// this function must match the printed form
+			// of a ConstSwitch.
+			var wantSwitches []string
+			for _, c := range f.Comments {
+				if fn.Syntax().Pos() <= c.Pos() && c.Pos() < fn.Syntax().End() {
+					text := strings.TrimSpace(c.Text())
+					if strings.HasPrefix(text, "switch ") {
+						wantSwitches = append(wantSwitches, text)
+					}
+				}
+			}
+
+			switches := ssautil.Switches(fn)
+			if len(switches) != len(wantSwitches) {
+				t.Errorf("in %s, found %d switches, want %d", fn, len(switches), len(wantSwitches))
+			}
+			for i, sw := range switches {
+				got := sw.String()
+				if i >= len(wantSwitches) {
+					continue
+				}
+				want := wantSwitches[i]
+				if got != want {
+					t.Errorf("in %s, found switch %d: got <<%s>>, want <<%s>>", fn, i, got, want)
+				}
+			}
+		}
+	}
+}
diff --git a/go/ssa/ssautil/testdata/switches.go b/go/ssa/ssautil/testdata/switches.go
new file mode 100644
index 0000000..8ab4c11
--- /dev/null
+++ b/go/ssa/ssautil/testdata/switches.go
@@ -0,0 +1,357 @@
+// +build ignore
+
+package main
+
+// This file is the input to TestSwitches in switch_test.go.
+// Each multiway conditional with constant or type cases (Switch)
+// discovered by Switches is printed, and compared with the
+// comments.
+//
+// The body of each case is printed as the value of its first
+// instruction.
+
+// -------- Value switches --------
+
+func SimpleSwitch(x, y int) {
+	// switch x {
+	// case 1:int: print(1:int)
+	// case 2:int: print(23:int)
+	// case 3:int: print(23:int)
+	// case 4:int: print(3:int)
+	// default: x == y
+	// }
+	switch x {
+	case 1:
+		print(1)
+	case 2, 3:
+		print(23)
+		fallthrough
+	case 4:
+		print(3)
+	default:
+		print(4)
+	case y:
+		print(5)
+	}
+	print(6)
+}
+
+func four() int { return 4 }
+
+// A non-constant case makes a switch "impure", but its pure
+// cases form two separate switches.
+func SwitchWithNonConstantCase(x int) {
+	// switch x {
+	// case 1:int: print(1:int)
+	// case 2:int: print(23:int)
+	// case 3:int: print(23:int)
+	// default: four()
+	// }
+
+	// switch x {
+	// case 5:int: print(5:int)
+	// case 6:int: print(6:int)
+	// default: print("done":string)
+	// }
+	switch x {
+	case 1:
+		print(1)
+	case 2, 3:
+		print(23)
+	case four():
+		print(3)
+	case 5:
+		print(5)
+	case 6:
+		print(6)
+	}
+	print("done")
+}
+
+// Switches may be found even where the source
+// program doesn't have a switch statement.
+
+func ImplicitSwitches(x, y int) {
+	// switch x {
+	// case 1:int: print(12:int)
+	// case 2:int: print(12:int)
+	// default: x < 5:int
+	// }
+	if x == 1 || 2 == x || x < 5 {
+		print(12)
+	}
+
+	// switch x {
+	// case 3:int: print(34:int)
+	// case 4:int: print(34:int)
+	// default: x == y
+	// }
+	if x == 3 || 4 == x || x == y {
+		print(34)
+	}
+
+	// Not a switch: no consistent variable.
+	if x == 5 || y == 6 {
+		print(56)
+	}
+
+	// Not a switch: only one constant comparison.
+	if x == 7 || x == y {
+		print(78)
+	}
+}
+
+func IfElseBasedSwitch(x int) {
+	// switch x {
+	// case 1:int: print(1:int)
+	// case 2:int: print(2:int)
+	// default: print("else":string)
+	// }
+	if x == 1 {
+		print(1)
+	} else if x == 2 {
+		print(2)
+	} else {
+		print("else")
+	}
+}
+
+func GotoBasedSwitch(x int) {
+	// switch x {
+	// case 1:int: print(1:int)
+	// case 2:int: print(2:int)
+	// default: print("else":string)
+	// }
+	if x == 1 {
+		goto L1
+	}
+	if x == 2 {
+		goto L2
+	}
+	print("else")
+L1:
+	print(1)
+	goto end
+L2:
+	print(2)
+end:
+}
+
+func SwitchInAForLoop(x int) {
+	// switch x {
+	// case 1:int: print(1:int)
+	// case 2:int: print(2:int)
+	// default: print("head":string)
+	// }
+loop:
+	for {
+		print("head")
+		switch x {
+		case 1:
+			print(1)
+			break loop
+		case 2:
+			print(2)
+			break loop
+		}
+	}
+}
+
+// This case is a switch in a for-loop, both constructed using goto.
+// As before, the default case points back to the block containing the
+// switch, but that's ok.
+func SwitchInAForLoopUsingGoto(x int) {
+	// switch x {
+	// case 1:int: print(1:int)
+	// case 2:int: print(2:int)
+	// default: print("head":string)
+	// }
+loop:
+	print("head")
+	if x == 1 {
+		goto L1
+	}
+	if x == 2 {
+		goto L2
+	}
+	goto loop
+L1:
+	print(1)
+	goto end
+L2:
+	print(2)
+end:
+}
+
+func UnstructuredSwitchInAForLoop(x int) {
+	// switch x {
+	// case 1:int: print(1:int)
+	// case 2:int: x == 1:int
+	// default: print("end":string)
+	// }
+	for {
+		if x == 1 {
+			print(1)
+			return
+		}
+		if x == 2 {
+			continue
+		}
+		break
+	}
+	print("end")
+}
+
+func CaseWithMultiplePreds(x int) {
+	for {
+		if x == 1 {
+			print(1)
+			return
+		}
+	loop:
+		// This block has multiple predecessors,
+		// so can't be treated as a switch case.
+		if x == 2 {
+			goto loop
+		}
+		break
+	}
+	print("end")
+}
+
+func DuplicateConstantsAreNotEliminated(x int) {
+	// switch x {
+	// case 1:int: print(1:int)
+	// case 1:int: print("1a":string)
+	// case 2:int: print(2:int)
+	// default: return
+	// }
+	if x == 1 {
+		print(1)
+	} else if x == 1 { // duplicate => unreachable
+		print("1a")
+	} else if x == 2 {
+		print(2)
+	}
+}
+
+// Interface values (created by comparisons) are not constants,
+// so ConstSwitch.X is never of interface type.
+func MakeInterfaceIsNotAConstant(x interface{}) {
+	if x == "foo" {
+		print("foo")
+	} else if x == 1 {
+		print(1)
+	}
+}
+
+func ZeroInitializedVarsAreConstants(x int) {
+	// switch x {
+	// case 0:int: print(1:int)
+	// case 2:int: print(2:int)
+	// default: print("end":string)
+	// }
+	var zero int // SSA construction replaces zero with 0
+	if x == zero {
+		print(1)
+	} else if x == 2 {
+		print(2)
+	}
+	print("end")
+}
+
+// -------- Select --------
+
+// NB, potentially fragile reliance on register number.
+func SelectDesugarsToSwitch(ch chan int) {
+	// switch t1 {
+	// case 0:int: extract t0 #2
+	// case 1:int: println(0:int)
+	// case 2:int: println(1:int)
+	// default: println("default":string)
+	// }
+	select {
+	case x := <-ch:
+		println(x)
+	case <-ch:
+		println(0)
+	case ch <- 1:
+		println(1)
+	default:
+		println("default")
+	}
+}
+
+// NB, potentially fragile reliance on register number.
+func NonblockingSelectDefaultCasePanics(ch chan int) {
+	// switch t1 {
+	// case 0:int: extract t0 #2
+	// case 1:int: println(0:int)
+	// case 2:int: println(1:int)
+	// default: make interface{} <- string ("blocking select m...":string)
+	// }
+	select {
+	case x := <-ch:
+		println(x)
+	case <-ch:
+		println(0)
+	case ch <- 1:
+		println(1)
+	}
+}
+
+// -------- Type switches --------
+
+// NB, reliance on fragile register numbering.
+func SimpleTypeSwitch(x interface{}) {
+	// switch x.(type) {
+	// case t3 int: println(x)
+	// case t7 bool: println(x)
+	// case t10 string: println(t10)
+	// default: println(x)
+	// }
+	switch y := x.(type) {
+	case nil:
+		println(y)
+	case int, bool:
+		println(y)
+	case string:
+		println(y)
+	default:
+		println(y)
+	}
+}
+
+// NB, potentially fragile reliance on register number.
+func DuplicateTypesAreNotEliminated(x interface{}) {
+	// switch x.(type) {
+	// case t1 string: println(1:int)
+	// case t5 interface{}: println(t5)
+	// case t9 int: println(3:int)
+	// default: return
+	// }
+	switch y := x.(type) {
+	case string:
+		println(1)
+	case interface{}:
+		println(y)
+	case int:
+		println(3) // unreachable!
+	}
+}
+
+// NB, potentially fragile reliance on register number.
+func AdHocTypeSwitch(x interface{}) {
+	// switch x.(type) {
+	// case t1 int: println(t1)
+	// case t5 string: println(t5)
+	// default: print("default":string)
+	// }
+	if i, ok := x.(int); ok {
+		println(i)
+	} else if s, ok := x.(string); ok {
+		println(s)
+	} else {
+		print("default")
+	}
+}
diff --git a/go/ssa/ssautil/visit.go b/go/ssa/ssautil/visit.go
new file mode 100644
index 0000000..30843c3
--- /dev/null
+++ b/go/ssa/ssautil/visit.go
@@ -0,0 +1,66 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssautil // import "golang.org/x/tools/go/ssa/ssautil"
+
+import "golang.org/x/tools/go/ssa"
+
+// This file defines utilities for visiting the SSA representation of
+// a Program.
+//
+// TODO(adonovan): test coverage.
+
+// AllFunctions finds and returns the set of functions potentially
+// needed by program prog, as determined by a simple linker-style
+// reachability algorithm starting from the members and method-sets of
+// each package.  The result may include anonymous functions and
+// synthetic wrappers.
+//
+// Precondition: all packages are built.
+//
+func AllFunctions(prog *ssa.Program) map[*ssa.Function]bool {
+	visit := visitor{
+		prog: prog,
+		seen: make(map[*ssa.Function]bool),
+	}
+	visit.program()
+	return visit.seen
+}
+
+type visitor struct {
+	prog *ssa.Program
+	seen map[*ssa.Function]bool
+}
+
+func (visit *visitor) program() {
+	for _, pkg := range visit.prog.AllPackages() {
+		for _, mem := range pkg.Members {
+			if fn, ok := mem.(*ssa.Function); ok {
+				visit.function(fn)
+			}
+		}
+	}
+	for _, T := range visit.prog.RuntimeTypes() {
+		mset := visit.prog.MethodSets.MethodSet(T)
+		for i, n := 0, mset.Len(); i < n; i++ {
+			visit.function(visit.prog.Method(mset.At(i)))
+		}
+	}
+}
+
+func (visit *visitor) function(fn *ssa.Function) {
+	if !visit.seen[fn] {
+		visit.seen[fn] = true
+		var buf [10]*ssa.Value // avoid alloc in common case
+		for _, b := range fn.Blocks {
+			for _, instr := range b.Instrs {
+				for _, op := range instr.Operands(buf[:0]) {
+					if fn, ok := (*op).(*ssa.Function); ok {
+						visit.function(fn)
+					}
+				}
+			}
+		}
+	}
+}
diff --git a/go/ssa/stdlib_test.go b/go/ssa/stdlib_test.go
new file mode 100644
index 0000000..d339d07
--- /dev/null
+++ b/go/ssa/stdlib_test.go
@@ -0,0 +1,134 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Incomplete source tree on Android.
+
+// +build !android
+
+package ssa_test
+
+// This file runs the SSA builder in sanity-checking mode on all
+// packages beneath $GOROOT and prints some summary information.
+//
+// Run with "go test -cpu=8 to" set GOMAXPROCS.
+
+import (
+	"go/ast"
+	"go/build"
+	"go/token"
+	"runtime"
+	"testing"
+	"time"
+
+	"golang.org/x/tools/go/buildutil"
+	"golang.org/x/tools/go/loader"
+	"golang.org/x/tools/go/ssa"
+	"golang.org/x/tools/go/ssa/ssautil"
+)
+
+func bytesAllocated() uint64 {
+	runtime.GC()
+	var stats runtime.MemStats
+	runtime.ReadMemStats(&stats)
+	return stats.Alloc
+}
+
+func TestStdlib(t *testing.T) {
+	// Load, parse and type-check the program.
+	t0 := time.Now()
+	alloc0 := bytesAllocated()
+
+	// Load, parse and type-check the program.
+	ctxt := build.Default // copy
+	ctxt.GOPATH = ""      // disable GOPATH
+	conf := loader.Config{Build: &ctxt}
+	if _, err := conf.FromArgs(buildutil.AllPackages(conf.Build), true); err != nil {
+		t.Errorf("FromArgs failed: %v", err)
+		return
+	}
+
+	iprog, err := conf.Load()
+	if err != nil {
+		t.Fatalf("Load failed: %v", err)
+	}
+
+	t1 := time.Now()
+	alloc1 := bytesAllocated()
+
+	// Create SSA packages.
+	var mode ssa.BuilderMode
+	// Comment out these lines during benchmarking.  Approx SSA build costs are noted.
+	mode |= ssa.SanityCheckFunctions // + 2% space, + 4% time
+	mode |= ssa.GlobalDebug          // +30% space, +18% time
+	prog := ssautil.CreateProgram(iprog, mode)
+
+	t2 := time.Now()
+
+	// Build SSA.
+	prog.BuildAll()
+
+	t3 := time.Now()
+	alloc3 := bytesAllocated()
+
+	numPkgs := len(prog.AllPackages())
+	if want := 140; numPkgs < want {
+		t.Errorf("Loaded only %d packages, want at least %d", numPkgs, want)
+	}
+
+	// Keep iprog reachable until after we've measured memory usage.
+	if len(iprog.AllPackages) == 0 {
+		print() // unreachable
+	}
+
+	allFuncs := ssautil.AllFunctions(prog)
+
+	// Check that all non-synthetic functions have distinct names.
+	// Synthetic wrappers for exported methods should be distinct too,
+	// except for unexported ones (explained at (*Function).RelString).
+	byName := make(map[string]*ssa.Function)
+	for fn := range allFuncs {
+		if fn.Synthetic == "" || ast.IsExported(fn.Name()) {
+			str := fn.String()
+			prev := byName[str]
+			byName[str] = fn
+			if prev != nil {
+				t.Errorf("%s: duplicate function named %s",
+					prog.Fset.Position(fn.Pos()), str)
+				t.Errorf("%s:   (previously defined here)",
+					prog.Fset.Position(prev.Pos()))
+			}
+		}
+	}
+
+	// Dump some statistics.
+	var numInstrs int
+	for fn := range allFuncs {
+		for _, b := range fn.Blocks {
+			numInstrs += len(b.Instrs)
+		}
+	}
+
+	// determine line count
+	var lineCount int
+	prog.Fset.Iterate(func(f *token.File) bool {
+		lineCount += f.LineCount()
+		return true
+	})
+
+	// NB: when benchmarking, don't forget to clear the debug +
+	// sanity builder flags for better performance.
+
+	t.Log("GOMAXPROCS:           ", runtime.GOMAXPROCS(0))
+	t.Log("#Source lines:        ", lineCount)
+	t.Log("Load/parse/typecheck: ", t1.Sub(t0))
+	t.Log("SSA create:           ", t2.Sub(t1))
+	t.Log("SSA build:            ", t3.Sub(t2))
+
+	// SSA stats:
+	t.Log("#Packages:            ", numPkgs)
+	t.Log("#Functions:           ", len(allFuncs))
+	t.Log("#Instructions:        ", numInstrs)
+	t.Log("#MB AST+types:        ", int64(alloc1-alloc0)/1e6)
+	t.Log("#MB SSA:              ", int64(alloc3-alloc1)/1e6)
+}
diff --git a/go/ssa/testdata/objlookup.go b/go/ssa/testdata/objlookup.go
new file mode 100644
index 0000000..1aaa417
--- /dev/null
+++ b/go/ssa/testdata/objlookup.go
@@ -0,0 +1,160 @@
+//+build ignore
+
+package main
+
+// This file is the input to TestObjValueLookup in source_test.go,
+// which ensures that each occurrence of an ident defining or
+// referring to a func, var or const object can be mapped to its
+// corresponding SSA Value.
+//
+// For every reference to a var object, we use annotations in comments
+// to denote both the expected SSA Value kind, and whether to expect
+// its value (x) or its address (&x).
+//
+// For const and func objects, the results don't vary by reference and
+// are always values not addresses, so no annotations are needed.  The
+// declaration is enough.
+
+import "fmt"
+import "os"
+
+type J int
+
+func (*J) method() {}
+
+const globalConst = 0
+
+var globalVar int // &globalVar::Global
+
+func globalFunc() {}
+
+type I interface {
+	interfaceMethod()
+}
+
+type S struct {
+	x int // x::nil
+}
+
+func main() {
+	print(globalVar) // globalVar::UnOp
+	globalVar = 1    // globalVar::Const
+
+	var v0 int = 1 // v0::Const (simple local value spec)
+	if v0 > 0 {    // v0::Const
+		v0 = 2 // v0::Const
+	}
+	print(v0) // v0::Phi
+
+	// v1 is captured and thus implicitly address-taken.
+	var v1 int = 1         // v1::Const
+	v1 = 2                 // v1::Const
+	fmt.Println(v1)        // v1::UnOp (load)
+	f := func(param int) { // f::MakeClosure param::Parameter
+		if y := 1; y > 0 { // y::Const
+			print(v1, param) // v1::UnOp (load) param::Parameter
+		}
+		param = 2      // param::Const
+		println(param) // param::Const
+	}
+
+	f(0) // f::MakeClosure
+
+	var v2 int // v2::Const (implicitly zero-initialized local value spec)
+	print(v2)  // v2::Const
+
+	m := make(map[string]int) // m::MakeMap
+
+	// Local value spec with multi-valued RHS:
+	var v3, v4 = m[""] // v3::Extract v4::Extract m::MakeMap
+	print(v3)          // v3::Extract
+	print(v4)          // v4::Extract
+
+	v3++    // v3::BinOp (assign with op)
+	v3 += 2 // v3::BinOp (assign with op)
+
+	v5, v6 := false, "" // v5::Const v6::Const (defining assignment)
+	print(v5)           // v5::Const
+	print(v6)           // v6::Const
+
+	var v7 S    // &v7::Alloc
+	v7.x = 1    // &v7::Alloc &x::FieldAddr
+	print(v7.x) // &v7::Alloc &x::FieldAddr
+
+	var v8 [1]int // &v8::Alloc
+	v8[0] = 0     // &v8::Alloc
+	print(v8[:])  // &v8::Alloc
+	_ = v8[0]     // &v8::Alloc
+	_ = v8[:][0]  // &v8::Alloc
+	v8ptr := &v8  // v8ptr::Alloc &v8::Alloc
+	_ = v8ptr[0]  // v8ptr::Alloc
+	_ = *v8ptr    // v8ptr::Alloc
+
+	v8a := make([]int, 1) // v8a::Slice
+	v8a[0] = 0            // v8a::Slice
+	print(v8a[:])         // v8a::Slice
+
+	v9 := S{} // &v9::Alloc
+
+	v10 := &v9 // v10::Alloc &v9::Alloc
+	_ = v10    // v10::Alloc
+
+	var v11 *J = nil // v11::Const
+	v11.method()     // v11::Const
+
+	var v12 J    // &v12::Alloc
+	v12.method() // &v12::Alloc (implicitly address-taken)
+
+	// NB, in the following, 'method' resolves to the *types.Func
+	// of (*J).method, so it doesn't help us locate the specific
+	// ssa.Values here: a bound-method closure and a promotion
+	// wrapper.
+	_ = v11.method            // v11::Const
+	_ = (*struct{ J }).method // J::nil
+
+	// These vars are not optimised away.
+	if false {
+		v13 := 0     // v13::Const
+		println(v13) // v13::Const
+	}
+
+	switch x := 1; x { // x::Const
+	case v0: // v0::Phi
+	}
+
+	for k, v := range m { // k::Extract v::Extract m::MakeMap
+		_ = k // k::Extract
+		v++   // v::BinOp
+	}
+
+	if y := 0; y > 1 { // y::Const y::Const
+	}
+
+	var i interface{}      // i::Const (nil interface)
+	i = 1                  // i::MakeInterface
+	switch i := i.(type) { // i::MakeInterface i::MakeInterface
+	case int:
+		println(i) // i::Extract
+	}
+
+	ch := make(chan int) // ch::MakeChan
+	select {
+	case x := <-ch: // x::UnOp (receive) ch::MakeChan
+		_ = x // x::UnOp
+	}
+
+	// .Op is an inter-package FieldVal-selection.
+	var err os.PathError // &err::Alloc
+	_ = err.Op           // &err::Alloc &Op::FieldAddr
+	_ = &err.Op          // &err::Alloc &Op::FieldAddr
+
+	// Exercise corner-cases of lvalues vs rvalues.
+	// (Guessing IsAddr from the 'pointerness' won't cut it here.)
+	type N *N
+	var n N    // n::Const
+	n1 := n    // n1::Const n::Const
+	n2 := &n1  // n2::Alloc &n1::Alloc
+	n3 := *n2  // n3::UnOp n2::Alloc
+	n4 := **n3 // n4::UnOp n3::UnOp
+	_ = n4     // n4::UnOp
+}
diff --git a/go/ssa/testdata/valueforexpr.go b/go/ssa/testdata/valueforexpr.go
new file mode 100644
index 0000000..028c153
--- /dev/null
+++ b/go/ssa/testdata/valueforexpr.go
@@ -0,0 +1,148 @@
+//+build ignore
+
+package main
+
+// This file is the input to TestValueForExpr in source_test.go, which
+// ensures that each expression e immediately following a /*@kind*/(x)
+// annotation, when passed to Function.ValueForExpr(e), returns a
+// non-nil Value of the same type as e and of kind 'kind'.
+
+func f(spilled, unspilled int) {
+	_ = /*@UnOp*/ (spilled)
+	_ = /*@Parameter*/ (unspilled)
+	_ = /*@<nil>*/ (1 + 2) // (constant)
+	i := 0
+	/*@Call*/ (print( /*@BinOp*/ (i + 1)))
+	ch := /*@MakeChan*/ (make(chan int))
+	/*@UnOp*/ (<-ch)
+	x := /*@UnOp*/ (<-ch)
+	_ = x
+	select {
+	case /*@Extract*/ (<-ch):
+	case x := /*@Extract*/ (<-ch):
+		_ = x
+	}
+	defer /*@Function*/ (func() {
+	})()
+	go /*@Function*/ (func() {
+	})()
+	y := 0
+	if true && /*@BinOp*/ (bool(y > 0)) {
+		y = 1
+	}
+	_ = /*@Phi*/ (y)
+	map1 := /*@MakeMap*/ (make(map[string]string))
+	_ = map1
+	_ = /*@Slice*/ (make([]int, 0))
+	_ = /*@MakeClosure*/ (func() { print(spilled) })
+
+	sl := []int{}
+	_ = /*@Slice*/ (sl[:0])
+
+	_ = /*@<nil>*/ (new(int)) // optimized away
+	tmp := /*@Alloc*/ (new(int))
+	_ = tmp
+	var iface interface{}
+	_ = /*@TypeAssert*/ (iface.(int))
+	_ = /*@UnOp*/ (sl[0])
+	_ = /*@IndexAddr*/ (&sl[0])
+	_ = /*@Index*/ ([2]int{}[0])
+	var p *int
+	_ = /*@UnOp*/ (*p)
+
+	_ = /*@UnOp*/ (global)
+	/*@UnOp*/ (global)[""] = ""
+	/*@Global*/ (global) = map[string]string{}
+
+	var local t
+	/*UnOp*/ (local.x) = 1
+
+	// Exercise corner-cases of lvalues vs rvalues.
+	type N *N
+	var n N
+	/*@UnOp*/ (n) = /*@UnOp*/ (n)
+	/*@ChangeType*/ (n) = /*@Alloc*/ (&n)
+	/*@UnOp*/ (n) = /*@UnOp*/ (*n)
+	/*@UnOp*/ (n) = /*@UnOp*/ (**n)
+}
+
+func complit() {
+	// Composite literals.
+	// We get different results for
+	// - composite literal as value (e.g. operand to print)
+	// - composite literal initializer for addressable value
+	// - composite literal value assigned to blank var
+
+	// 1. Slices
+	print( /*@Slice*/ ([]int{}))
+	print( /*@Alloc*/ (&[]int{}))
+	print(& /*@Slice*/ ([]int{}))
+
+	sl1 := /*@Slice*/ ([]int{})
+	sl2 := /*@Alloc*/ (&[]int{})
+	sl3 := & /*@Slice*/ ([]int{})
+	_, _, _ = sl1, sl2, sl3
+
+	_ = /*@Slice*/ ([]int{})
+	_ = /*@<nil>*/ (& /*@Slice*/ ([]int{})) // & optimized away
+	_ = & /*@Slice*/ ([]int{})
+
+	// 2. Arrays
+	print( /*@UnOp*/ ([1]int{}))
+	print( /*@Alloc*/ (&[1]int{}))
+	print(& /*@Alloc*/ ([1]int{}))
+
+	arr1 := /*@Alloc*/ ([1]int{})
+	arr2 := /*@Alloc*/ (&[1]int{})
+	arr3 := & /*@Alloc*/ ([1]int{})
+	_, _, _ = arr1, arr2, arr3
+
+	_ = /*@UnOp*/ ([1]int{})
+	_ = /*@Alloc*/ (& /*@Alloc*/ ([1]int{}))
+	_ = & /*@Alloc*/ ([1]int{})
+
+	// 3. Maps
+	type M map[int]int
+	print( /*@MakeMap*/ (M{}))
+	print( /*@Alloc*/ (&M{}))
+	print(& /*@MakeMap*/ (M{}))
+
+	m1 := /*@MakeMap*/ (M{})
+	m2 := /*@Alloc*/ (&M{})
+	m3 := & /*@MakeMap*/ (M{})
+	_, _, _ = m1, m2, m3
+
+	_ = /*@MakeMap*/ (M{})
+	_ = /*@<nil>*/ (& /*@MakeMap*/ (M{})) // & optimized away
+	_ = & /*@MakeMap*/ (M{})
+
+	// 4. Structs
+	print( /*@UnOp*/ (struct{}{}))
+	print( /*@Alloc*/ (&struct{}{}))
+	print(& /*@Alloc*/ (struct{}{}))
+
+	s1 := /*@Alloc*/ (struct{}{})
+	s2 := /*@Alloc*/ (&struct{}{})
+	s3 := & /*@Alloc*/ (struct{}{})
+	_, _, _ = s1, s2, s3
+
+	_ = /*@UnOp*/ (struct{}{})
+	_ = /*@Alloc*/ (& /*@Alloc*/ (struct{}{}))
+	_ = & /*@Alloc*/ (struct{}{})
+}
+
+type t struct{ x int }
+
+// Ensure we can locate methods of named types.
+func (t) f(param int) {
+	_ = /*@Parameter*/ (param)
+}
+
+// Ensure we can locate init functions.
+func init() {
+	m := /*@MakeMap*/ (make(map[string]string))
+	_ = m
+}
+
+// Ensure we can locate variables in initializer expressions.
+var global = /*@MakeMap*/ (make(map[string]string))
diff --git a/go/ssa/testmain.go b/go/ssa/testmain.go
new file mode 100644
index 0000000..a7b1242
--- /dev/null
+++ b/go/ssa/testmain.go
@@ -0,0 +1,296 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssa
+
+// CreateTestMainPackage synthesizes a main package that runs all the
+// tests of the supplied packages.
+// It is closely coupled to $GOROOT/src/cmd/go/test.go and $GOROOT/src/testing.
+
+import (
+	"go/ast"
+	"go/token"
+	"os"
+	"sort"
+	"strings"
+
+	"golang.org/x/tools/go/exact"
+	"golang.org/x/tools/go/types"
+)
+
+// FindTests returns the list of packages that define at least one Test,
+// Example or Benchmark function (as defined by "go test"), and the
+// lists of all such functions.
+//
+func FindTests(pkgs []*Package) (testpkgs []*Package, tests, benchmarks, examples []*Function) {
+	if len(pkgs) == 0 {
+		return
+	}
+	prog := pkgs[0].Prog
+
+	// The first two of these may be nil: if the program doesn't import "testing",
+	// it can't contain any tests, but it may yet contain Examples.
+	var testSig *types.Signature                              // func(*testing.T)
+	var benchmarkSig *types.Signature                         // func(*testing.B)
+	var exampleSig = types.NewSignature(nil, nil, nil, false) // func()
+
+	// Obtain the types from the parameters of testing.Main().
+	if testingPkg := prog.ImportedPackage("testing"); testingPkg != nil {
+		params := testingPkg.Func("Main").Signature.Params()
+		testSig = funcField(params.At(1).Type())
+		benchmarkSig = funcField(params.At(2).Type())
+	}
+
+	seen := make(map[*Package]bool)
+	for _, pkg := range pkgs {
+		if pkg.Prog != prog {
+			panic("wrong Program")
+		}
+
+		// TODO(adonovan): use a stable order, e.g. lexical.
+		for _, mem := range pkg.Members {
+			if f, ok := mem.(*Function); ok &&
+				ast.IsExported(f.Name()) &&
+				strings.HasSuffix(prog.Fset.Position(f.Pos()).Filename, "_test.go") {
+
+				switch {
+				case testSig != nil && isTestSig(f, "Test", testSig):
+					tests = append(tests, f)
+				case benchmarkSig != nil && isTestSig(f, "Benchmark", benchmarkSig):
+					benchmarks = append(benchmarks, f)
+				case isTestSig(f, "Example", exampleSig):
+					examples = append(examples, f)
+				default:
+					continue
+				}
+
+				if !seen[pkg] {
+					seen[pkg] = true
+					testpkgs = append(testpkgs, pkg)
+				}
+			}
+		}
+	}
+	return
+}
+
+// Like isTest, but checks the signature too.
+func isTestSig(f *Function, prefix string, sig *types.Signature) bool {
+	return isTest(f.Name(), prefix) && types.Identical(f.Signature, sig)
+}
+
+// If non-nil, testMainStartBodyHook is called immediately after
+// startBody for main.init and main.main, making it easy for users to
+// add custom imports and initialization steps for proprietary build
+// systems that don't exactly follow 'go test' conventions.
+var testMainStartBodyHook func(*Function)
+
+// CreateTestMainPackage creates and returns a synthetic "main"
+// package that runs all the tests of the supplied packages, similar
+// to the one that would be created by the 'go test' tool.
+//
+// It returns nil if the program contains no tests.
+//
+func (prog *Program) CreateTestMainPackage(pkgs ...*Package) *Package {
+	pkgs, tests, benchmarks, examples := FindTests(pkgs)
+	if len(pkgs) == 0 {
+		return nil
+	}
+
+	testmain := &Package{
+		Prog:    prog,
+		Members: make(map[string]Member),
+		values:  make(map[types.Object]Value),
+		Object:  types.NewPackage("test$main", "main"),
+	}
+
+	// Build package's init function.
+	init := &Function{
+		name:      "init",
+		Signature: new(types.Signature),
+		Synthetic: "package initializer",
+		Pkg:       testmain,
+		Prog:      prog,
+	}
+	init.startBody()
+
+	if testMainStartBodyHook != nil {
+		testMainStartBodyHook(init)
+	}
+
+	// Initialize packages to test.
+	var pkgpaths []string
+	for _, pkg := range pkgs {
+		var v Call
+		v.Call.Value = pkg.init
+		v.setType(types.NewTuple())
+		init.emit(&v)
+
+		pkgpaths = append(pkgpaths, pkg.Object.Path())
+	}
+	sort.Strings(pkgpaths)
+	init.emit(new(Return))
+	init.finishBody()
+	testmain.init = init
+	testmain.Object.MarkComplete()
+	testmain.Members[init.name] = init
+
+	// For debugging convenience, define an unexported const
+	// that enumerates the packages.
+	packagesConst := types.NewConst(token.NoPos, testmain.Object, "packages", tString,
+		exact.MakeString(strings.Join(pkgpaths, " ")))
+	memberFromObject(testmain, packagesConst, nil)
+
+	// Create main *types.Func and *ssa.Function
+	mainFunc := types.NewFunc(token.NoPos, testmain.Object, "main", new(types.Signature))
+	memberFromObject(testmain, mainFunc, nil)
+	main := testmain.Func("main")
+	main.Synthetic = "test main function"
+
+	main.startBody()
+
+	if testMainStartBodyHook != nil {
+		testMainStartBodyHook(main)
+	}
+
+	if testingPkg := prog.ImportedPackage("testing"); testingPkg != nil {
+		testingMain := testingPkg.Func("Main")
+		testingMainParams := testingMain.Signature.Params()
+
+		// The generated code is as if compiled from this:
+		//
+		// func main() {
+		//      match      := func(_, _ string) (bool, error) { return true, nil }
+		//      tests      := []testing.InternalTest{{"TestFoo", TestFoo}, ...}
+		//      benchmarks := []testing.InternalBenchmark{...}
+		//      examples   := []testing.InternalExample{...}
+		// 	testing.Main(match, tests, benchmarks, examples)
+		// }
+
+		matcher := &Function{
+			name:      "matcher",
+			Signature: testingMainParams.At(0).Type().(*types.Signature),
+			Synthetic: "test matcher predicate",
+			parent:    main,
+			Pkg:       testmain,
+			Prog:      prog,
+		}
+		main.AnonFuncs = append(main.AnonFuncs, matcher)
+		matcher.startBody()
+		matcher.emit(&Return{Results: []Value{vTrue, nilConst(types.Universe.Lookup("error").Type())}})
+		matcher.finishBody()
+
+		// Emit call: testing.Main(matcher, tests, benchmarks, examples).
+		var c Call
+		c.Call.Value = testingMain
+		c.Call.Args = []Value{
+			matcher,
+			testMainSlice(main, tests, testingMainParams.At(1).Type()),
+			testMainSlice(main, benchmarks, testingMainParams.At(2).Type()),
+			testMainSlice(main, examples, testingMainParams.At(3).Type()),
+		}
+		emitTailCall(main, &c)
+	} else {
+		// The program does not import "testing", but FindTests
+		// returned non-nil, which must mean there were Examples
+		// but no Tests or Benchmarks.
+		// We'll simply call them from testmain.main; this will
+		// ensure they don't panic, but will not check any
+		// "Output:" comments.
+		for _, eg := range examples {
+			var c Call
+			c.Call.Value = eg
+			c.setType(types.NewTuple())
+			main.emit(&c)
+		}
+		main.emit(&Return{})
+		main.currentBlock = nil
+	}
+
+	main.finishBody()
+
+	testmain.Members["main"] = main
+
+	if prog.mode&PrintPackages != 0 {
+		printMu.Lock()
+		testmain.WriteTo(os.Stdout)
+		printMu.Unlock()
+	}
+
+	if prog.mode&SanityCheckFunctions != 0 {
+		sanityCheckPackage(testmain)
+	}
+
+	prog.packages[testmain.Object] = testmain
+
+	return testmain
+}
+
+// testMainSlice emits to fn code to construct a slice of type slice
+// (one of []testing.Internal{Test,Benchmark,Example}) for all
+// functions in testfuncs.  It returns the slice value.
+//
+func testMainSlice(fn *Function, testfuncs []*Function, slice types.Type) Value {
+	if testfuncs == nil {
+		return nilConst(slice)
+	}
+
+	tElem := slice.(*types.Slice).Elem()
+	tPtrString := types.NewPointer(tString)
+	tPtrElem := types.NewPointer(tElem)
+	tPtrFunc := types.NewPointer(funcField(slice))
+
+	// Emit: array = new [n]testing.InternalTest
+	tArray := types.NewArray(tElem, int64(len(testfuncs)))
+	array := emitNew(fn, tArray, token.NoPos)
+	array.Comment = "test main"
+	for i, testfunc := range testfuncs {
+		// Emit: pitem = &array[i]
+		ia := &IndexAddr{X: array, Index: intConst(int64(i))}
+		ia.setType(tPtrElem)
+		pitem := fn.emit(ia)
+
+		// Emit: pname = &pitem.Name
+		fa := &FieldAddr{X: pitem, Field: 0} // .Name
+		fa.setType(tPtrString)
+		pname := fn.emit(fa)
+
+		// Emit: *pname = "testfunc"
+		emitStore(fn, pname, stringConst(testfunc.Name()), token.NoPos)
+
+		// Emit: pfunc = &pitem.F
+		fa = &FieldAddr{X: pitem, Field: 1} // .F
+		fa.setType(tPtrFunc)
+		pfunc := fn.emit(fa)
+
+		// Emit: *pfunc = testfunc
+		emitStore(fn, pfunc, testfunc, token.NoPos)
+	}
+
+	// Emit: slice array[:]
+	sl := &Slice{X: array}
+	sl.setType(slice)
+	return fn.emit(sl)
+}
+
+// Given the type of one of the three slice parameters of testing.Main,
+// returns the function type.
+func funcField(slice types.Type) *types.Signature {
+	return slice.(*types.Slice).Elem().Underlying().(*types.Struct).Field(1).Type().(*types.Signature)
+}
+
+// Plundered from $GOROOT/src/cmd/go/test.go
+
+// isTest tells whether name looks like a test (or benchmark, according to prefix).
+// It is a Test (say) if there is a character after Test that is not a lower-case letter.
+// We don't want TesticularCancer.
+func isTest(name, prefix string) bool {
+	if !strings.HasPrefix(name, prefix) {
+		return false
+	}
+	if len(name) == len(prefix) { // "Test" is ok
+		return true
+	}
+	return ast.IsExported(name[len(prefix):])
+}
diff --git a/go/ssa/testmain_test.go b/go/ssa/testmain_test.go
new file mode 100644
index 0000000..56cb604
--- /dev/null
+++ b/go/ssa/testmain_test.go
@@ -0,0 +1,123 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssa_test
+
+// Tests of FindTests.  CreateTestMainPackage is tested via the interpreter.
+// TODO(adonovan): test the 'pkgs' result from FindTests.
+
+import (
+	"fmt"
+	"sort"
+	"testing"
+
+	"golang.org/x/tools/go/loader"
+	"golang.org/x/tools/go/ssa"
+	"golang.org/x/tools/go/ssa/ssautil"
+)
+
+func create(t *testing.T, content string) []*ssa.Package {
+	var conf loader.Config
+	f, err := conf.ParseFile("foo_test.go", content)
+	if err != nil {
+		t.Fatal(err)
+	}
+	conf.CreateFromFiles("foo", f)
+
+	iprog, err := conf.Load()
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	// We needn't call Build.
+	return ssautil.CreateProgram(iprog, ssa.SanityCheckFunctions).AllPackages()
+}
+
+func TestFindTests(t *testing.T) {
+	test := `
+package foo
+
+import "testing"
+
+type T int
+
+// Tests:
+func Test(t *testing.T) {}
+func TestA(t *testing.T) {}
+func TestB(t *testing.T) {}
+
+// Not tests:
+func testC(t *testing.T) {}
+func TestD() {}
+func testE(t *testing.T) int { return 0 }
+func (T) Test(t *testing.T) {}
+
+// Benchmarks:
+func Benchmark(*testing.B) {}
+func BenchmarkA(b *testing.B) {}
+func BenchmarkB(*testing.B) {}
+
+// Not benchmarks:
+func benchmarkC(t *testing.T) {}
+func BenchmarkD() {}
+func benchmarkE(t *testing.T) int { return 0 }
+func (T) Benchmark(t *testing.T) {}
+
+// Examples:
+func Example() {}
+func ExampleA() {}
+
+// Not examples:
+func exampleC() {}
+func ExampleD(t *testing.T) {}
+func exampleE() int { return 0 }
+func (T) Example() {}
+`
+	pkgs := create(t, test)
+	_, tests, benchmarks, examples := ssa.FindTests(pkgs)
+
+	sort.Sort(funcsByPos(tests))
+	if got, want := fmt.Sprint(tests), "[foo.Test foo.TestA foo.TestB]"; got != want {
+		t.Errorf("FindTests.tests = %s, want %s", got, want)
+	}
+
+	sort.Sort(funcsByPos(benchmarks))
+	if got, want := fmt.Sprint(benchmarks), "[foo.Benchmark foo.BenchmarkA foo.BenchmarkB]"; got != want {
+		t.Errorf("FindTests.benchmarks = %s, want %s", got, want)
+	}
+
+	sort.Sort(funcsByPos(examples))
+	if got, want := fmt.Sprint(examples), "[foo.Example foo.ExampleA]"; got != want {
+		t.Errorf("FindTests examples = %s, want %s", got, want)
+	}
+}
+
+func TestFindTestsTesting(t *testing.T) {
+	test := `
+package foo
+
+// foo does not import "testing", but defines Examples.
+
+func Example() {}
+func ExampleA() {}
+`
+	pkgs := create(t, test)
+	_, tests, benchmarks, examples := ssa.FindTests(pkgs)
+	if len(tests) > 0 {
+		t.Errorf("FindTests.tests = %s, want none", tests)
+	}
+	if len(benchmarks) > 0 {
+		t.Errorf("FindTests.benchmarks = %s, want none", benchmarks)
+	}
+	sort.Sort(funcsByPos(examples))
+	if got, want := fmt.Sprint(examples), "[foo.Example foo.ExampleA]"; got != want {
+		t.Errorf("FindTests examples = %s, want %s", got, want)
+	}
+}
+
+type funcsByPos []*ssa.Function
+
+func (p funcsByPos) Len() int           { return len(p) }
+func (p funcsByPos) Less(i, j int) bool { return p[i].Pos() < p[j].Pos() }
+func (p funcsByPos) Swap(i, j int)      { p[i], p[j] = p[j], p[i] }
diff --git a/go/ssa/util.go b/go/ssa/util.go
new file mode 100644
index 0000000..4f9d43d
--- /dev/null
+++ b/go/ssa/util.go
@@ -0,0 +1,119 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssa
+
+// This file defines a number of miscellaneous utility functions.
+
+import (
+	"fmt"
+	"go/ast"
+	"go/token"
+	"io"
+	"os"
+
+	"golang.org/x/tools/go/ast/astutil"
+	"golang.org/x/tools/go/types"
+)
+
+//// AST utilities
+
+func unparen(e ast.Expr) ast.Expr { return astutil.Unparen(e) }
+
+// isBlankIdent returns true iff e is an Ident with name "_".
+// They have no associated types.Object, and thus no type.
+//
+func isBlankIdent(e ast.Expr) bool {
+	id, ok := e.(*ast.Ident)
+	return ok && id.Name == "_"
+}
+
+//// Type utilities.  Some of these belong in go/types.
+
+// isPointer returns true for types whose underlying type is a pointer.
+func isPointer(typ types.Type) bool {
+	_, ok := typ.Underlying().(*types.Pointer)
+	return ok
+}
+
+func isInterface(T types.Type) bool { return types.IsInterface(T) }
+
+// deref returns a pointer's element type; otherwise it returns typ.
+func deref(typ types.Type) types.Type {
+	if p, ok := typ.Underlying().(*types.Pointer); ok {
+		return p.Elem()
+	}
+	return typ
+}
+
+// recvType returns the receiver type of method obj.
+func recvType(obj *types.Func) types.Type {
+	return obj.Type().(*types.Signature).Recv().Type()
+}
+
+// DefaultType returns the default "typed" type for an "untyped" type;
+// it returns the incoming type for all other types.  The default type
+// for untyped nil is untyped nil.
+//
+// Exported to ssa/interp.
+//
+// TODO(gri): this is a copy of go/types.defaultType; export that function.
+//
+func DefaultType(typ types.Type) types.Type {
+	if t, ok := typ.(*types.Basic); ok {
+		k := t.Kind()
+		switch k {
+		case types.UntypedBool:
+			k = types.Bool
+		case types.UntypedInt:
+			k = types.Int
+		case types.UntypedRune:
+			k = types.Rune
+		case types.UntypedFloat:
+			k = types.Float64
+		case types.UntypedComplex:
+			k = types.Complex128
+		case types.UntypedString:
+			k = types.String
+		}
+		typ = types.Typ[k]
+	}
+	return typ
+}
+
+// logStack prints the formatted "start" message to stderr and
+// returns a closure that prints the corresponding "end" message.
+// Call using 'defer logStack(...)()' to show builder stack on panic.
+// Don't forget trailing parens!
+//
+func logStack(format string, args ...interface{}) func() {
+	msg := fmt.Sprintf(format, args...)
+	io.WriteString(os.Stderr, msg)
+	io.WriteString(os.Stderr, "\n")
+	return func() {
+		io.WriteString(os.Stderr, msg)
+		io.WriteString(os.Stderr, " end\n")
+	}
+}
+
+// newVar creates a 'var' for use in a types.Tuple.
+func newVar(name string, typ types.Type) *types.Var {
+	return types.NewParam(token.NoPos, nil, name, typ)
+}
+
+// anonVar creates an anonymous 'var' for use in a types.Tuple.
+func anonVar(typ types.Type) *types.Var {
+	return newVar("", typ)
+}
+
+var lenResults = types.NewTuple(anonVar(tInt))
+
+// makeLen returns the len builtin specialized to type func(T)int.
+func makeLen(T types.Type) *Builtin {
+	lenParams := types.NewTuple(anonVar(T))
+	return &Builtin{
+		name: "len",
+		sig:  types.NewSignature(nil, lenParams, lenResults, false),
+	}
+}
diff --git a/go/ssa/wrappers.go b/go/ssa/wrappers.go
new file mode 100644
index 0000000..ff1eac5
--- /dev/null
+++ b/go/ssa/wrappers.go
@@ -0,0 +1,294 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssa
+
+// This file defines synthesis of Functions that delegate to declared
+// methods; they come in three kinds:
+//
+// (1) wrappers: methods that wrap declared methods, performing
+//     implicit pointer indirections and embedded field selections.
+//
+// (2) thunks: funcs that wrap declared methods.  Like wrappers,
+//     thunks perform indirections and field selections. The thunk's
+//     first parameter is used as the receiver for the method call.
+//
+// (3) bounds: funcs that wrap declared methods.  The bound's sole
+//     free variable, supplied by a closure, is used as the receiver
+//     for the method call.  No indirections or field selections are
+//     performed since they can be done before the call.
+
+import (
+	"fmt"
+
+	"golang.org/x/tools/go/types"
+)
+
+// -- wrappers -----------------------------------------------------------
+
+// makeWrapper returns a synthetic method that delegates to the
+// declared method denoted by meth.Obj(), first performing any
+// necessary pointer indirections or field selections implied by meth.
+//
+// The resulting method's receiver type is meth.Recv().
+//
+// This function is versatile but quite subtle!  Consider the
+// following axes of variation when making changes:
+//   - optional receiver indirection
+//   - optional implicit field selections
+//   - meth.Obj() may denote a concrete or an interface method
+//   - the result may be a thunk or a wrapper.
+//
+// EXCLUSIVE_LOCKS_REQUIRED(prog.methodsMu)
+//
+func makeWrapper(prog *Program, sel *types.Selection) *Function {
+	obj := sel.Obj().(*types.Func)       // the declared function
+	sig := sel.Type().(*types.Signature) // type of this wrapper
+
+	var recv *types.Var // wrapper's receiver or thunk's params[0]
+	name := obj.Name()
+	var description string
+	var start int // first regular param
+	if sel.Kind() == types.MethodExpr {
+		name += "$thunk"
+		description = "thunk"
+		recv = sig.Params().At(0)
+		start = 1
+	} else {
+		description = "wrapper"
+		recv = sig.Recv()
+	}
+
+	description = fmt.Sprintf("%s for %s", description, sel.Obj())
+	if prog.mode&LogSource != 0 {
+		defer logStack("make %s to (%s)", description, recv.Type())()
+	}
+	fn := &Function{
+		name:      name,
+		method:    sel,
+		object:    obj,
+		Signature: sig,
+		Synthetic: description,
+		Prog:      prog,
+		pos:       obj.Pos(),
+	}
+	fn.startBody()
+	fn.addSpilledParam(recv)
+	createParams(fn, start)
+
+	indices := sel.Index()
+
+	var v Value = fn.Locals[0] // spilled receiver
+	if isPointer(sel.Recv()) {
+		v = emitLoad(fn, v)
+
+		// For simple indirection wrappers, perform an informative nil-check:
+		// "value method (T).f called using nil *T pointer"
+		if len(indices) == 1 && !isPointer(recvType(obj)) {
+			var c Call
+			c.Call.Value = &Builtin{
+				name: "ssa:wrapnilchk",
+				sig: types.NewSignature(nil,
+					types.NewTuple(anonVar(sel.Recv()), anonVar(tString), anonVar(tString)),
+					types.NewTuple(anonVar(sel.Recv())), false),
+			}
+			c.Call.Args = []Value{
+				v,
+				stringConst(deref(sel.Recv()).String()),
+				stringConst(sel.Obj().Name()),
+			}
+			c.setType(v.Type())
+			v = fn.emit(&c)
+		}
+	}
+
+	// Invariant: v is a pointer, either
+	//   value of *A receiver param, or
+	// address of  A spilled receiver.
+
+	// We use pointer arithmetic (FieldAddr possibly followed by
+	// Load) in preference to value extraction (Field possibly
+	// preceded by Load).
+
+	v = emitImplicitSelections(fn, v, indices[:len(indices)-1])
+
+	// Invariant: v is a pointer, either
+	//   value of implicit *C field, or
+	// address of implicit  C field.
+
+	var c Call
+	if r := recvType(obj); !isInterface(r) { // concrete method
+		if !isPointer(r) {
+			v = emitLoad(fn, v)
+		}
+		c.Call.Value = prog.declaredFunc(obj)
+		c.Call.Args = append(c.Call.Args, v)
+	} else {
+		c.Call.Method = obj
+		c.Call.Value = emitLoad(fn, v)
+	}
+	for _, arg := range fn.Params[1:] {
+		c.Call.Args = append(c.Call.Args, arg)
+	}
+	emitTailCall(fn, &c)
+	fn.finishBody()
+	return fn
+}
+
+// createParams creates parameters for wrapper method fn based on its
+// Signature.Params, which do not include the receiver.
+// start is the index of the first regular parameter to use.
+//
+func createParams(fn *Function, start int) {
+	var last *Parameter
+	tparams := fn.Signature.Params()
+	for i, n := start, tparams.Len(); i < n; i++ {
+		last = fn.addParamObj(tparams.At(i))
+	}
+	if fn.Signature.Variadic() {
+		last.typ = types.NewSlice(last.typ)
+	}
+}
+
+// -- bounds -----------------------------------------------------------
+
+// makeBound returns a bound method wrapper (or "bound"), a synthetic
+// function that delegates to a concrete or interface method denoted
+// by obj.  The resulting function has no receiver, but has one free
+// variable which will be used as the method's receiver in the
+// tail-call.
+//
+// Use MakeClosure with such a wrapper to construct a bound method
+// closure.  e.g.:
+//
+//   type T int          or:  type T interface { meth() }
+//   func (t T) meth()
+//   var t T
+//   f := t.meth
+//   f() // calls t.meth()
+//
+// f is a closure of a synthetic wrapper defined as if by:
+//
+//   f := func() { return t.meth() }
+//
+// Unlike makeWrapper, makeBound need perform no indirection or field
+// selections because that can be done before the closure is
+// constructed.
+//
+// EXCLUSIVE_LOCKS_ACQUIRED(meth.Prog.methodsMu)
+//
+func makeBound(prog *Program, obj *types.Func) *Function {
+	prog.methodsMu.Lock()
+	defer prog.methodsMu.Unlock()
+	fn, ok := prog.bounds[obj]
+	if !ok {
+		description := fmt.Sprintf("bound method wrapper for %s", obj)
+		if prog.mode&LogSource != 0 {
+			defer logStack("%s", description)()
+		}
+		fn = &Function{
+			name:      obj.Name() + "$bound",
+			object:    obj,
+			Signature: changeRecv(obj.Type().(*types.Signature), nil), // drop receiver
+			Synthetic: description,
+			Prog:      prog,
+			pos:       obj.Pos(),
+		}
+
+		fv := &FreeVar{name: "recv", typ: recvType(obj), parent: fn}
+		fn.FreeVars = []*FreeVar{fv}
+		fn.startBody()
+		createParams(fn, 0)
+		var c Call
+
+		if !isInterface(recvType(obj)) { // concrete
+			c.Call.Value = prog.declaredFunc(obj)
+			c.Call.Args = []Value{fv}
+		} else {
+			c.Call.Value = fv
+			c.Call.Method = obj
+		}
+		for _, arg := range fn.Params {
+			c.Call.Args = append(c.Call.Args, arg)
+		}
+		emitTailCall(fn, &c)
+		fn.finishBody()
+
+		prog.bounds[obj] = fn
+	}
+	return fn
+}
+
+// -- thunks -----------------------------------------------------------
+
+// makeThunk returns a thunk, a synthetic function that delegates to a
+// concrete or interface method denoted by sel.Obj().  The resulting
+// function has no receiver, but has an additional (first) regular
+// parameter.
+//
+// Precondition: sel.Kind() == types.MethodExpr.
+//
+//   type T int          or:  type T interface { meth() }
+//   func (t T) meth()
+//   f := T.meth
+//   var t T
+//   f(t) // calls t.meth()
+//
+// f is a synthetic wrapper defined as if by:
+//
+//   f := func(t T) { return t.meth() }
+//
+// TODO(adonovan): opt: currently the stub is created even when used
+// directly in a function call: C.f(i, 0).  This is less efficient
+// than inlining the stub.
+//
+// EXCLUSIVE_LOCKS_ACQUIRED(meth.Prog.methodsMu)
+//
+func makeThunk(prog *Program, sel *types.Selection) *Function {
+	if sel.Kind() != types.MethodExpr {
+		panic(sel)
+	}
+
+	key := selectionKey{
+		kind:     sel.Kind(),
+		recv:     sel.Recv(),
+		obj:      sel.Obj(),
+		index:    fmt.Sprint(sel.Index()),
+		indirect: sel.Indirect(),
+	}
+
+	prog.methodsMu.Lock()
+	defer prog.methodsMu.Unlock()
+
+	// Canonicalize key.recv to avoid constructing duplicate thunks.
+	canonRecv, ok := prog.canon.At(key.recv).(types.Type)
+	if !ok {
+		canonRecv = key.recv
+		prog.canon.Set(key.recv, canonRecv)
+	}
+	key.recv = canonRecv
+
+	fn, ok := prog.thunks[key]
+	if !ok {
+		fn = makeWrapper(prog, sel)
+		if fn.Signature.Recv() != nil {
+			panic(fn) // unexpected receiver
+		}
+		prog.thunks[key] = fn
+	}
+	return fn
+}
+
+func changeRecv(s *types.Signature, recv *types.Var) *types.Signature {
+	return types.NewSignature(recv, s.Params(), s.Results(), s.Variadic())
+}
+
+// selectionKey is like types.Selection but a usable map key.
+type selectionKey struct {
+	kind     types.SelectionKind
+	recv     types.Type // canonicalized via Program.canon
+	obj      types.Object
+	index    string
+	indirect bool
+}
diff --git a/go/types/api.go b/go/types/api.go
new file mode 100644
index 0000000..5344a39
--- /dev/null
+++ b/go/types/api.go
@@ -0,0 +1,365 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package types declares the data types and implements
+// the algorithms for type-checking of Go packages.
+// Use Check and Config.Check to invoke the type-checker.
+//
+// Type-checking consists of several interdependent phases:
+//
+// Name resolution maps each identifier (ast.Ident) in the program to the
+// language object (Object) it denotes.
+// Use Info.{Defs,Uses,Implicits} for the results of name resolution.
+//
+// Constant folding computes the exact constant value (exact.Value) for
+// every expression (ast.Expr) that is a compile-time constant.
+// Use Info.Types[expr].Value for the results of constant folding.
+//
+// Type inference computes the type (Type) of every expression (ast.Expr)
+// and checks for compliance with the language specification.
+// Use Info.Types[expr].Type for the results of type inference.
+//
+package types // import "golang.org/x/tools/go/types"
+
+import (
+	"bytes"
+	"fmt"
+	"go/ast"
+	"go/token"
+
+	"golang.org/x/tools/go/exact"
+)
+
+// Check type-checks a package and returns the resulting complete package
+// object, or a nil package and the first error. The package is specified
+// by a list of *ast.Files and corresponding file set, and the import path
+// the package is identified with. The clean path must not be empty or dot (".").
+//
+// For more control over type-checking and results, use Config.Check.
+func Check(path string, fset *token.FileSet, files []*ast.File) (*Package, error) {
+	var conf Config
+	pkg, err := conf.Check(path, fset, files, nil)
+	if err != nil {
+		return nil, err
+	}
+	return pkg, nil
+}
+
+// An Error describes a type-checking error; it implements the error interface.
+// A "soft" error is an error that still permits a valid interpretation of a
+// package (such as "unused variable"); "hard" errors may lead to unpredictable
+// behavior if ignored.
+type Error struct {
+	Fset *token.FileSet // file set for interpretation of Pos
+	Pos  token.Pos      // error position
+	Msg  string         // error message
+	Soft bool           // if set, error is "soft"
+}
+
+// Error returns an error string formatted as follows:
+// filename:line:column: message
+func (err Error) Error() string {
+	return fmt.Sprintf("%s: %s", err.Fset.Position(err.Pos), err.Msg)
+}
+
+// An importer resolves import paths to Packages.
+// The imports map records packages already known,
+// indexed by package path. The type-checker
+// will invoke Import with Config.Packages.
+// An importer must determine the canonical package path and
+// check imports to see if it is already present in the map.
+// If so, the Importer can return the map entry.  Otherwise,
+// the importer must load the package data for the given path
+// into a new *Package, record it in imports map, and return
+// the package.
+// TODO(gri) Need to be clearer about requirements of completeness.
+type Importer func(map[string]*Package, string) (*Package, error)
+
+// A Config specifies the configuration for type checking.
+// The zero value for Config is a ready-to-use default configuration.
+type Config struct {
+	// If IgnoreFuncBodies is set, function bodies are not
+	// type-checked.
+	IgnoreFuncBodies bool
+
+	// If FakeImportC is set, `import "C"` (for packages requiring Cgo)
+	// declares an empty "C" package and errors are omitted for qualified
+	// identifiers referring to package C (which won't find an object).
+	// This feature is intended for the standard library cmd/api tool.
+	//
+	// Caution: Effects may be unpredictable due to follow-up errors.
+	//          Do not use casually!
+	FakeImportC bool
+
+	// Packages is used to look up (and thus canonicalize) packages by
+	// package path. If Packages is nil, it is set to a new empty map.
+	// During type-checking, imported packages are added to the map.
+	Packages map[string]*Package
+
+	// If Error != nil, it is called with each error found
+	// during type checking; err has dynamic type Error.
+	// Secondary errors (for instance, to enumerate all types
+	// involved in an invalid recursive type declaration) have
+	// error strings that start with a '\t' character.
+	// If Error == nil, type-checking stops with the first
+	// error found.
+	Error func(err error)
+
+	// If Import != nil, it is called for each imported package.
+	// Otherwise, DefaultImport is called.
+	Import Importer
+
+	// If Sizes != nil, it provides the sizing functions for package unsafe.
+	// Otherwise &StdSizes{WordSize: 8, MaxAlign: 8} is used instead.
+	Sizes Sizes
+
+	// If DisableUnusedImportCheck is set, packages are not checked
+	// for unused imports.
+	DisableUnusedImportCheck bool
+}
+
+// DefaultImport is the default importer invoked if Config.Import == nil.
+// The declaration:
+//
+//	import _ "golang.org/x/tools/go/gcimporter"
+//
+// in a client of go/types will initialize DefaultImport to gcimporter.Import.
+var DefaultImport Importer
+
+// Info holds result type information for a type-checked package.
+// Only the information for which a map is provided is collected.
+// If the package has type errors, the collected information may
+// be incomplete.
+type Info struct {
+	// Types maps expressions to their types, and for constant
+	// expressions, their values. Invalid expressions are omitted.
+	//
+	// For (possibly parenthesized) identifiers denoting built-in
+	// functions, the recorded signatures are call-site specific:
+	// if the call result is not a constant, the recorded type is
+	// an argument-specific signature. Otherwise, the recorded type
+	// is invalid.
+	//
+	// Identifiers on the lhs of declarations (i.e., the identifiers
+	// which are being declared) are collected in the Defs map.
+	// Identifiers denoting packages are collected in the Uses maps.
+	Types map[ast.Expr]TypeAndValue
+
+	// Defs maps identifiers to the objects they define (including
+	// package names, dots "." of dot-imports, and blank "_" identifiers).
+	// For identifiers that do not denote objects (e.g., the package name
+	// in package clauses, or symbolic variables t in t := x.(type) of
+	// type switch headers), the corresponding objects are nil.
+	//
+	// For an anonymous field, Defs returns the field *Var it defines.
+	//
+	// Invariant: Defs[id] == nil || Defs[id].Pos() == id.Pos()
+	Defs map[*ast.Ident]Object
+
+	// Uses maps identifiers to the objects they denote.
+	//
+	// For an anonymous field, Uses returns the *TypeName it denotes.
+	//
+	// Invariant: Uses[id].Pos() != id.Pos()
+	Uses map[*ast.Ident]Object
+
+	// Implicits maps nodes to their implicitly declared objects, if any.
+	// The following node and object types may appear:
+	//
+	//	node               declared object
+	//
+	//	*ast.ImportSpec    *PkgName for dot-imports and imports without renames
+	//	*ast.CaseClause    type-specific *Var for each type switch case clause (incl. default)
+	//      *ast.Field         anonymous struct field or parameter *Var
+	//
+	Implicits map[ast.Node]Object
+
+	// Selections maps selector expressions (excluding qualified identifiers)
+	// to their corresponding selections.
+	Selections map[*ast.SelectorExpr]*Selection
+
+	// Scopes maps ast.Nodes to the scopes they define. Package scopes are not
+	// associated with a specific node but with all files belonging to a package.
+	// Thus, the package scope can be found in the type-checked Package object.
+	// Scopes nest, with the Universe scope being the outermost scope, enclosing
+	// the package scope, which contains (one or more) files scopes, which enclose
+	// function scopes which in turn enclose statement and function literal scopes.
+	// Note that even though package-level functions are declared in the package
+	// scope, the function scopes are embedded in the file scope of the file
+	// containing the function declaration.
+	//
+	// The following node types may appear in Scopes:
+	//
+	//	*ast.File
+	//	*ast.FuncType
+	//	*ast.BlockStmt
+	//	*ast.IfStmt
+	//	*ast.SwitchStmt
+	//	*ast.TypeSwitchStmt
+	//	*ast.CaseClause
+	//	*ast.CommClause
+	//	*ast.ForStmt
+	//	*ast.RangeStmt
+	//
+	Scopes map[ast.Node]*Scope
+
+	// InitOrder is the list of package-level initializers in the order in which
+	// they must be executed. Initializers referring to variables related by an
+	// initialization dependency appear in topological order, the others appear
+	// in source order. Variables without an initialization expression do not
+	// appear in this list.
+	InitOrder []*Initializer
+}
+
+// TypeOf returns the type of expression e, or nil if not found.
+// Precondition: the Types, Uses and Defs maps are populated.
+//
+func (info *Info) TypeOf(e ast.Expr) Type {
+	if t, ok := info.Types[e]; ok {
+		return t.Type
+	}
+	if id, _ := e.(*ast.Ident); id != nil {
+		if obj := info.ObjectOf(id); obj != nil {
+			return obj.Type()
+		}
+	}
+	return nil
+}
+
+// ObjectOf returns the object denoted by the specified id,
+// or nil if not found.
+//
+// If id is an anonymous struct field, ObjectOf returns the field (*Var)
+// it uses, not the type (*TypeName) it defines.
+//
+// Precondition: the Uses and Defs maps are populated.
+//
+func (info *Info) ObjectOf(id *ast.Ident) Object {
+	if obj, _ := info.Defs[id]; obj != nil {
+		return obj
+	}
+	return info.Uses[id]
+}
+
+// TypeAndValue reports the type and value (for constants)
+// of the corresponding expression.
+type TypeAndValue struct {
+	mode  operandMode
+	Type  Type
+	Value exact.Value
+}
+
+// TODO(gri) Consider eliminating the IsVoid predicate. Instead, report
+// "void" values as regular values but with the empty tuple type.
+
+// IsVoid reports whether the corresponding expression
+// is a function call without results.
+func (tv TypeAndValue) IsVoid() bool {
+	return tv.mode == novalue
+}
+
+// IsType reports whether the corresponding expression specifies a type.
+func (tv TypeAndValue) IsType() bool {
+	return tv.mode == typexpr
+}
+
+// IsBuiltin reports whether the corresponding expression denotes
+// a (possibly parenthesized) built-in function.
+func (tv TypeAndValue) IsBuiltin() bool {
+	return tv.mode == builtin
+}
+
+// IsValue reports whether the corresponding expression is a value.
+// Builtins are not considered values. Constant values have a non-
+// nil Value.
+func (tv TypeAndValue) IsValue() bool {
+	switch tv.mode {
+	case constant, variable, mapindex, value, commaok:
+		return true
+	}
+	return false
+}
+
+// IsNil reports whether the corresponding expression denotes the
+// predeclared value nil.
+func (tv TypeAndValue) IsNil() bool {
+	return tv.mode == value && tv.Type == Typ[UntypedNil]
+}
+
+// Addressable reports whether the corresponding expression
+// is addressable (http://golang.org/ref/spec#Address_operators).
+func (tv TypeAndValue) Addressable() bool {
+	return tv.mode == variable
+}
+
+// Assignable reports whether the corresponding expression
+// is assignable to (provided a value of the right type).
+func (tv TypeAndValue) Assignable() bool {
+	return tv.mode == variable || tv.mode == mapindex
+}
+
+// HasOk reports whether the corresponding expression may be
+// used on the lhs of a comma-ok assignment.
+func (tv TypeAndValue) HasOk() bool {
+	return tv.mode == commaok || tv.mode == mapindex
+}
+
+// An Initializer describes a package-level variable, or a list of variables in case
+// of a multi-valued initialization expression, and the corresponding initialization
+// expression.
+type Initializer struct {
+	Lhs []*Var // var Lhs = Rhs
+	Rhs ast.Expr
+}
+
+func (init *Initializer) String() string {
+	var buf bytes.Buffer
+	for i, lhs := range init.Lhs {
+		if i > 0 {
+			buf.WriteString(", ")
+		}
+		buf.WriteString(lhs.Name())
+	}
+	buf.WriteString(" = ")
+	WriteExpr(&buf, init.Rhs)
+	return buf.String()
+}
+
+// Check type-checks a package and returns the resulting package object,
+// the first error if any, and if info != nil, additional type information.
+// The package is marked as complete if no errors occurred, otherwise it is
+// incomplete. See Config.Error for controlling behavior in the presence of
+// errors.
+//
+// The package is specified by a list of *ast.Files and corresponding
+// file set, and the package path the package is identified with.
+// The clean path must not be empty or dot (".").
+func (conf *Config) Check(path string, fset *token.FileSet, files []*ast.File, info *Info) (*Package, error) {
+	pkg := NewPackage(path, "")
+	return pkg, NewChecker(conf, fset, pkg, info).Files(files)
+}
+
+// AssertableTo reports whether a value of type V can be asserted to have type T.
+func AssertableTo(V *Interface, T Type) bool {
+	m, _ := assertableTo(V, T)
+	return m == nil
+}
+
+// AssignableTo reports whether a value of type V is assignable to a variable of type T.
+func AssignableTo(V, T Type) bool {
+	x := operand{mode: value, typ: V}
+	return x.assignableTo(nil, T) // config not needed for non-constant x
+}
+
+// ConvertibleTo reports whether a value of type V is convertible to a value of type T.
+func ConvertibleTo(V, T Type) bool {
+	x := operand{mode: value, typ: V}
+	return x.convertibleTo(nil, T) // config not needed for non-constant x
+}
+
+// Implements reports whether type V implements interface T.
+func Implements(V Type, T *Interface) bool {
+	f, _ := MissingMethod(V, T, true)
+	return f == nil
+}
diff --git a/go/types/api_test.go b/go/types/api_test.go
new file mode 100644
index 0000000..5a0535f
--- /dev/null
+++ b/go/types/api_test.go
@@ -0,0 +1,1060 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package types_test
+
+import (
+	"bytes"
+	"fmt"
+	"go/ast"
+	"go/parser"
+	"go/token"
+	"reflect"
+	"regexp"
+	"runtime"
+	"strings"
+	"testing"
+
+	_ "golang.org/x/tools/go/gcimporter"
+	. "golang.org/x/tools/go/types"
+)
+
+// skipSpecialPlatforms causes the test to be skipped for platforms where
+// builders (build.golang.org) don't have access to compiled packages for
+// import.
+func skipSpecialPlatforms(t *testing.T) {
+	switch platform := runtime.GOOS + "-" + runtime.GOARCH; platform {
+	case "android-arm",
+		"nacl-amd64p32",
+		"nacl-386",
+		"nacl-arm",
+		"darwin-arm",
+		"darwin-arm64":
+		t.Skipf("no compiled packages available for import on %s", platform)
+	}
+}
+
+func pkgFor(path, source string, info *Info) (*Package, error) {
+	fset := token.NewFileSet()
+	f, err := parser.ParseFile(fset, path, source, 0)
+	if err != nil {
+		return nil, err
+	}
+
+	var conf Config
+	return conf.Check(f.Name.Name, fset, []*ast.File{f}, info)
+}
+
+func mustTypecheck(t *testing.T, path, source string, info *Info) string {
+	pkg, err := pkgFor(path, source, info)
+	if err != nil {
+		name := path
+		if pkg != nil {
+			name = "package " + pkg.Name()
+		}
+		t.Fatalf("%s: didn't type-check (%s)", name, err)
+	}
+	return pkg.Name()
+}
+
+func TestValuesInfo(t *testing.T) {
+	var tests = []struct {
+		src  string
+		expr string // constant expression
+		typ  string // constant type
+		val  string // constant value
+	}{
+		{`package a0; const _ = false`, `false`, `untyped bool`, `false`},
+		{`package a1; const _ = 0`, `0`, `untyped int`, `0`},
+		{`package a2; const _ = 'A'`, `'A'`, `untyped rune`, `65`},
+		{`package a3; const _ = 0.`, `0.`, `untyped float`, `0`},
+		{`package a4; const _ = 0i`, `0i`, `untyped complex`, `0`},
+		{`package a5; const _ = "foo"`, `"foo"`, `untyped string`, `"foo"`},
+
+		{`package b0; var _ = false`, `false`, `bool`, `false`},
+		{`package b1; var _ = 0`, `0`, `int`, `0`},
+		{`package b2; var _ = 'A'`, `'A'`, `rune`, `65`},
+		{`package b3; var _ = 0.`, `0.`, `float64`, `0`},
+		{`package b4; var _ = 0i`, `0i`, `complex128`, `0`},
+		{`package b5; var _ = "foo"`, `"foo"`, `string`, `"foo"`},
+
+		{`package c0a; var _ = bool(false)`, `false`, `bool`, `false`},
+		{`package c0b; var _ = bool(false)`, `bool(false)`, `bool`, `false`},
+		{`package c0c; type T bool; var _ = T(false)`, `T(false)`, `c0c.T`, `false`},
+
+		{`package c1a; var _ = int(0)`, `0`, `int`, `0`},
+		{`package c1b; var _ = int(0)`, `int(0)`, `int`, `0`},
+		{`package c1c; type T int; var _ = T(0)`, `T(0)`, `c1c.T`, `0`},
+
+		{`package c2a; var _ = rune('A')`, `'A'`, `rune`, `65`},
+		{`package c2b; var _ = rune('A')`, `rune('A')`, `rune`, `65`},
+		{`package c2c; type T rune; var _ = T('A')`, `T('A')`, `c2c.T`, `65`},
+
+		{`package c3a; var _ = float32(0.)`, `0.`, `float32`, `0`},
+		{`package c3b; var _ = float32(0.)`, `float32(0.)`, `float32`, `0`},
+		{`package c3c; type T float32; var _ = T(0.)`, `T(0.)`, `c3c.T`, `0`},
+
+		{`package c4a; var _ = complex64(0i)`, `0i`, `complex64`, `0`},
+		{`package c4b; var _ = complex64(0i)`, `complex64(0i)`, `complex64`, `0`},
+		{`package c4c; type T complex64; var _ = T(0i)`, `T(0i)`, `c4c.T`, `0`},
+
+		{`package c5a; var _ = string("foo")`, `"foo"`, `string`, `"foo"`},
+		{`package c5b; var _ = string("foo")`, `string("foo")`, `string`, `"foo"`},
+		{`package c5c; type T string; var _ = T("foo")`, `T("foo")`, `c5c.T`, `"foo"`},
+
+		{`package d0; var _ = []byte("foo")`, `"foo"`, `string`, `"foo"`},
+		{`package d1; var _ = []byte(string("foo"))`, `"foo"`, `string`, `"foo"`},
+		{`package d2; var _ = []byte(string("foo"))`, `string("foo")`, `string`, `"foo"`},
+		{`package d3; type T []byte; var _ = T("foo")`, `"foo"`, `string`, `"foo"`},
+
+		{`package e0; const _ = float32( 1e-200)`, `float32(1e-200)`, `float32`, `0`},
+		{`package e1; const _ = float32(-1e-200)`, `float32(-1e-200)`, `float32`, `0`},
+		{`package e2; const _ = float64( 1e-2000)`, `float64(1e-2000)`, `float64`, `0`},
+		{`package e3; const _ = float64(-1e-2000)`, `float64(-1e-2000)`, `float64`, `0`},
+		{`package e4; const _ = complex64( 1e-200)`, `complex64(1e-200)`, `complex64`, `0`},
+		{`package e5; const _ = complex64(-1e-200)`, `complex64(-1e-200)`, `complex64`, `0`},
+		{`package e6; const _ = complex128( 1e-2000)`, `complex128(1e-2000)`, `complex128`, `0`},
+		{`package e7; const _ = complex128(-1e-2000)`, `complex128(-1e-2000)`, `complex128`, `0`},
+
+		{`package f0 ; var _ float32 =  1e-200`, `1e-200`, `float32`, `0`},
+		{`package f1 ; var _ float32 = -1e-200`, `-1e-200`, `float32`, `0`},
+		{`package f2a; var _ float64 =  1e-2000`, `1e-2000`, `float64`, `0`},
+		{`package f3a; var _ float64 = -1e-2000`, `-1e-2000`, `float64`, `0`},
+		{`package f2b; var _         =  1e-2000`, `1e-2000`, `float64`, `0`},
+		{`package f3b; var _         = -1e-2000`, `-1e-2000`, `float64`, `0`},
+		{`package f4 ; var _ complex64  =  1e-200 `, `1e-200`, `complex64`, `0`},
+		{`package f5 ; var _ complex64  = -1e-200 `, `-1e-200`, `complex64`, `0`},
+		{`package f6a; var _ complex128 =  1e-2000i`, `1e-2000i`, `complex128`, `0`},
+		{`package f7a; var _ complex128 = -1e-2000i`, `-1e-2000i`, `complex128`, `0`},
+		{`package f6b; var _            =  1e-2000i`, `1e-2000i`, `complex128`, `0`},
+		{`package f7b; var _            = -1e-2000i`, `-1e-2000i`, `complex128`, `0`},
+	}
+
+	for _, test := range tests {
+		info := Info{
+			Types: make(map[ast.Expr]TypeAndValue),
+		}
+		name := mustTypecheck(t, "ValuesInfo", test.src, &info)
+
+		// look for constant expression
+		var expr ast.Expr
+		for e := range info.Types {
+			if ExprString(e) == test.expr {
+				expr = e
+				break
+			}
+		}
+		if expr == nil {
+			t.Errorf("package %s: no expression found for %s", name, test.expr)
+			continue
+		}
+		tv := info.Types[expr]
+
+		// check that type is correct
+		if got := tv.Type.String(); got != test.typ {
+			t.Errorf("package %s: got type %s; want %s", name, got, test.typ)
+			continue
+		}
+
+		// check that value is correct
+		if got := tv.Value.String(); got != test.val {
+			t.Errorf("package %s: got value %s; want %s", name, got, test.val)
+		}
+	}
+}
+
+func TestTypesInfo(t *testing.T) {
+	var tests = []struct {
+		src  string
+		expr string // expression
+		typ  string // value type
+	}{
+		// single-valued expressions of untyped constants
+		{`package b0; var x interface{} = false`, `false`, `bool`},
+		{`package b1; var x interface{} = 0`, `0`, `int`},
+		{`package b2; var x interface{} = 0.`, `0.`, `float64`},
+		{`package b3; var x interface{} = 0i`, `0i`, `complex128`},
+		{`package b4; var x interface{} = "foo"`, `"foo"`, `string`},
+
+		// comma-ok expressions
+		{`package p0; var x interface{}; var _, _ = x.(int)`,
+			`x.(int)`,
+			`(int, bool)`,
+		},
+		{`package p1; var x interface{}; func _() { _, _ = x.(int) }`,
+			`x.(int)`,
+			`(int, bool)`,
+		},
+		// TODO(gri): uncomment if we accept issue 8189.
+		// {`package p2; type mybool bool; var m map[string]complex128; var b mybool; func _() { _, b = m["foo"] }`,
+		// 	`m["foo"]`,
+		// 	`(complex128, p2.mybool)`,
+		// },
+		// TODO(gri): remove if we accept issue 8189.
+		{`package p2; var m map[string]complex128; var b bool; func _() { _, b = m["foo"] }`,
+			`m["foo"]`,
+			`(complex128, bool)`,
+		},
+		{`package p3; var c chan string; var _, _ = <-c`,
+			`<-c`,
+			`(string, bool)`,
+		},
+
+		// issue 6796
+		{`package issue6796_a; var x interface{}; var _, _ = (x.(int))`,
+			`x.(int)`,
+			`(int, bool)`,
+		},
+		{`package issue6796_b; var c chan string; var _, _ = (<-c)`,
+			`(<-c)`,
+			`(string, bool)`,
+		},
+		{`package issue6796_c; var c chan string; var _, _ = (<-c)`,
+			`<-c`,
+			`(string, bool)`,
+		},
+		{`package issue6796_d; var c chan string; var _, _ = ((<-c))`,
+			`(<-c)`,
+			`(string, bool)`,
+		},
+		{`package issue6796_e; func f(c chan string) { _, _ = ((<-c)) }`,
+			`(<-c)`,
+			`(string, bool)`,
+		},
+
+		// issue 7060
+		{`package issue7060_a; var ( m map[int]string; x, ok = m[0] )`,
+			`m[0]`,
+			`(string, bool)`,
+		},
+		{`package issue7060_b; var ( m map[int]string; x, ok interface{} = m[0] )`,
+			`m[0]`,
+			`(string, bool)`,
+		},
+		{`package issue7060_c; func f(x interface{}, ok bool, m map[int]string) { x, ok = m[0] }`,
+			`m[0]`,
+			`(string, bool)`,
+		},
+		{`package issue7060_d; var ( ch chan string; x, ok = <-ch )`,
+			`<-ch`,
+			`(string, bool)`,
+		},
+		{`package issue7060_e; var ( ch chan string; x, ok interface{} = <-ch )`,
+			`<-ch`,
+			`(string, bool)`,
+		},
+		{`package issue7060_f; func f(x interface{}, ok bool, ch chan string) { x, ok = <-ch }`,
+			`<-ch`,
+			`(string, bool)`,
+		},
+	}
+
+	for _, test := range tests {
+		info := Info{Types: make(map[ast.Expr]TypeAndValue)}
+		name := mustTypecheck(t, "TypesInfo", test.src, &info)
+
+		// look for expression type
+		var typ Type
+		for e, tv := range info.Types {
+			if ExprString(e) == test.expr {
+				typ = tv.Type
+				break
+			}
+		}
+		if typ == nil {
+			t.Errorf("package %s: no type found for %s", name, test.expr)
+			continue
+		}
+
+		// check that type is correct
+		if got := typ.String(); got != test.typ {
+			t.Errorf("package %s: got %s; want %s", name, got, test.typ)
+		}
+	}
+}
+
+func predString(tv TypeAndValue) string {
+	var buf bytes.Buffer
+	pred := func(b bool, s string) {
+		if b {
+			if buf.Len() > 0 {
+				buf.WriteString(", ")
+			}
+			buf.WriteString(s)
+		}
+	}
+
+	pred(tv.IsVoid(), "void")
+	pred(tv.IsType(), "type")
+	pred(tv.IsBuiltin(), "builtin")
+	pred(tv.IsValue() && tv.Value != nil, "const")
+	pred(tv.IsValue() && tv.Value == nil, "value")
+	pred(tv.IsNil(), "nil")
+	pred(tv.Addressable(), "addressable")
+	pred(tv.Assignable(), "assignable")
+	pred(tv.HasOk(), "hasOk")
+
+	if buf.Len() == 0 {
+		return "invalid"
+	}
+	return buf.String()
+}
+
+func TestPredicatesInfo(t *testing.T) {
+	skipSpecialPlatforms(t)
+
+	var tests = []struct {
+		src  string
+		expr string
+		pred string
+	}{
+		// void
+		{`package n0; func f() { f() }`, `f()`, `void`},
+
+		// types
+		{`package t0; type _ int`, `int`, `type`},
+		{`package t1; type _ []int`, `[]int`, `type`},
+		{`package t2; type _ func()`, `func()`, `type`},
+
+		// built-ins
+		{`package b0; var _ = len("")`, `len`, `builtin`},
+		{`package b1; var _ = (len)("")`, `(len)`, `builtin`},
+
+		// constants
+		{`package c0; var _ = 42`, `42`, `const`},
+		{`package c1; var _ = "foo" + "bar"`, `"foo" + "bar"`, `const`},
+		{`package c2; const (i = 1i; _ = i)`, `i`, `const`},
+
+		// values
+		{`package v0; var (a, b int; _ = a + b)`, `a + b`, `value`},
+		{`package v1; var _ = &[]int{1}`, `([]int literal)`, `value`},
+		{`package v2; var _ = func(){}`, `(func() literal)`, `value`},
+		{`package v4; func f() { _ = f }`, `f`, `value`},
+		{`package v3; var _ *int = nil`, `nil`, `value, nil`},
+		{`package v3; var _ *int = (nil)`, `(nil)`, `value, nil`},
+
+		// addressable (and thus assignable) operands
+		{`package a0; var (x int; _ = x)`, `x`, `value, addressable, assignable`},
+		{`package a1; var (p *int; _ = *p)`, `*p`, `value, addressable, assignable`},
+		{`package a2; var (s []int; _ = s[0])`, `s[0]`, `value, addressable, assignable`},
+		{`package a3; var (s struct{f int}; _ = s.f)`, `s.f`, `value, addressable, assignable`},
+		{`package a4; var (a [10]int; _ = a[0])`, `a[0]`, `value, addressable, assignable`},
+		{`package a5; func _(x int) { _ = x }`, `x`, `value, addressable, assignable`},
+		{`package a6; func _()(x int) { _ = x; return }`, `x`, `value, addressable, assignable`},
+		{`package a7; type T int; func (x T) _() { _ = x }`, `x`, `value, addressable, assignable`},
+		// composite literals are not addressable
+
+		// assignable but not addressable values
+		{`package s0; var (m map[int]int; _ = m[0])`, `m[0]`, `value, assignable, hasOk`},
+		{`package s1; var (m map[int]int; _, _ = m[0])`, `m[0]`, `value, assignable, hasOk`},
+
+		// hasOk expressions
+		{`package k0; var (ch chan int; _ = <-ch)`, `<-ch`, `value, hasOk`},
+		{`package k1; var (ch chan int; _, _ = <-ch)`, `<-ch`, `value, hasOk`},
+
+		// missing entries
+		// - package names are collected in the Uses map
+		// - identifiers being declared are collected in the Defs map
+		{`package m0; import "os"; func _() { _ = os.Stdout }`, `os`, `<missing>`},
+		{`package m1; import p "os"; func _() { _ = p.Stdout }`, `p`, `<missing>`},
+		{`package m2; const c = 0`, `c`, `<missing>`},
+		{`package m3; type T int`, `T`, `<missing>`},
+		{`package m4; var v int`, `v`, `<missing>`},
+		{`package m5; func f() {}`, `f`, `<missing>`},
+		{`package m6; func _(x int) {}`, `x`, `<missing>`},
+		{`package m6; func _()(x int) { return }`, `x`, `<missing>`},
+		{`package m6; type T int; func (x T) _() {}`, `x`, `<missing>`},
+	}
+
+	for _, test := range tests {
+		info := Info{Types: make(map[ast.Expr]TypeAndValue)}
+		name := mustTypecheck(t, "PredicatesInfo", test.src, &info)
+
+		// look for expression predicates
+		got := "<missing>"
+		for e, tv := range info.Types {
+			//println(name, ExprString(e))
+			if ExprString(e) == test.expr {
+				got = predString(tv)
+				break
+			}
+		}
+
+		if got != test.pred {
+			t.Errorf("package %s: got %s; want %s", name, got, test.pred)
+		}
+	}
+}
+
+func TestScopesInfo(t *testing.T) {
+	skipSpecialPlatforms(t)
+
+	var tests = []struct {
+		src    string
+		scopes []string // list of scope descriptors of the form kind:varlist
+	}{
+		{`package p0`, []string{
+			"file:",
+		}},
+		{`package p1; import ( "fmt"; m "math"; _ "os" ); var ( _ = fmt.Println; _ = m.Pi )`, []string{
+			"file:fmt m",
+		}},
+		{`package p2; func _() {}`, []string{
+			"file:", "func:",
+		}},
+		{`package p3; func _(x, y int) {}`, []string{
+			"file:", "func:x y",
+		}},
+		{`package p4; func _(x, y int) { x, z := 1, 2; _ = z }`, []string{
+			"file:", "func:x y z", // redeclaration of x
+		}},
+		{`package p5; func _(x, y int) (u, _ int) { return }`, []string{
+			"file:", "func:u x y",
+		}},
+		{`package p6; func _() { { var x int; _ = x } }`, []string{
+			"file:", "func:", "block:x",
+		}},
+		{`package p7; func _() { if true {} }`, []string{
+			"file:", "func:", "if:", "block:",
+		}},
+		{`package p8; func _() { if x := 0; x < 0 { y := x; _ = y } }`, []string{
+			"file:", "func:", "if:x", "block:y",
+		}},
+		{`package p9; func _() { switch x := 0; x {} }`, []string{
+			"file:", "func:", "switch:x",
+		}},
+		{`package p10; func _() { switch x := 0; x { case 1: y := x; _ = y; default: }}`, []string{
+			"file:", "func:", "switch:x", "case:y", "case:",
+		}},
+		{`package p11; func _(t interface{}) { switch t.(type) {} }`, []string{
+			"file:", "func:t", "type switch:",
+		}},
+		{`package p12; func _(t interface{}) { switch t := t; t.(type) {} }`, []string{
+			"file:", "func:t", "type switch:t",
+		}},
+		{`package p13; func _(t interface{}) { switch x := t.(type) { case int: _ = x } }`, []string{
+			"file:", "func:t", "type switch:", "case:x", // x implicitly declared
+		}},
+		{`package p14; func _() { select{} }`, []string{
+			"file:", "func:",
+		}},
+		{`package p15; func _(c chan int) { select{ case <-c: } }`, []string{
+			"file:", "func:c", "comm:",
+		}},
+		{`package p16; func _(c chan int) { select{ case i := <-c: x := i; _ = x} }`, []string{
+			"file:", "func:c", "comm:i x",
+		}},
+		{`package p17; func _() { for{} }`, []string{
+			"file:", "func:", "for:", "block:",
+		}},
+		{`package p18; func _(n int) { for i := 0; i < n; i++ { _ = i } }`, []string{
+			"file:", "func:n", "for:i", "block:",
+		}},
+		{`package p19; func _(a []int) { for i := range a { _ = i} }`, []string{
+			"file:", "func:a", "range:i", "block:",
+		}},
+		{`package p20; var s int; func _(a []int) { for i, x := range a { s += x; _ = i } }`, []string{
+			"file:", "func:a", "range:i x", "block:",
+		}},
+	}
+
+	for _, test := range tests {
+		info := Info{Scopes: make(map[ast.Node]*Scope)}
+		name := mustTypecheck(t, "ScopesInfo", test.src, &info)
+
+		// number of scopes must match
+		if len(info.Scopes) != len(test.scopes) {
+			t.Errorf("package %s: got %d scopes; want %d", name, len(info.Scopes), len(test.scopes))
+		}
+
+		// scope descriptions must match
+		for node, scope := range info.Scopes {
+			kind := "<unknown node kind>"
+			switch node.(type) {
+			case *ast.File:
+				kind = "file"
+			case *ast.FuncType:
+				kind = "func"
+			case *ast.BlockStmt:
+				kind = "block"
+			case *ast.IfStmt:
+				kind = "if"
+			case *ast.SwitchStmt:
+				kind = "switch"
+			case *ast.TypeSwitchStmt:
+				kind = "type switch"
+			case *ast.CaseClause:
+				kind = "case"
+			case *ast.CommClause:
+				kind = "comm"
+			case *ast.ForStmt:
+				kind = "for"
+			case *ast.RangeStmt:
+				kind = "range"
+			}
+
+			// look for matching scope description
+			desc := kind + ":" + strings.Join(scope.Names(), " ")
+			found := false
+			for _, d := range test.scopes {
+				if desc == d {
+					found = true
+					break
+				}
+			}
+			if !found {
+				t.Errorf("package %s: no matching scope found for %s", name, desc)
+			}
+		}
+	}
+}
+
+func TestInitOrderInfo(t *testing.T) {
+	var tests = []struct {
+		src   string
+		inits []string
+	}{
+		{`package p0; var (x = 1; y = x)`, []string{
+			"x = 1", "y = x",
+		}},
+		{`package p1; var (a = 1; b = 2; c = 3)`, []string{
+			"a = 1", "b = 2", "c = 3",
+		}},
+		{`package p2; var (a, b, c = 1, 2, 3)`, []string{
+			"a = 1", "b = 2", "c = 3",
+		}},
+		{`package p3; var _ = f(); func f() int { return 1 }`, []string{
+			"_ = f()", // blank var
+		}},
+		{`package p4; var (a = 0; x = y; y = z; z = 0)`, []string{
+			"a = 0", "z = 0", "y = z", "x = y",
+		}},
+		{`package p5; var (a, _ = m[0]; m map[int]string)`, []string{
+			"a, _ = m[0]", // blank var
+		}},
+		{`package p6; var a, b = f(); func f() (_, _ int) { return z, z }; var z = 0`, []string{
+			"z = 0", "a, b = f()",
+		}},
+		{`package p7; var (a = func() int { return b }(); b = 1)`, []string{
+			"b = 1", "a = (func() int literal)()",
+		}},
+		{`package p8; var (a, b = func() (_, _ int) { return c, c }(); c = 1)`, []string{
+			"c = 1", "a, b = (func() (_, _ int) literal)()",
+		}},
+		{`package p9; type T struct{}; func (T) m() int { _ = y; return 0 }; var x, y = T.m, 1`, []string{
+			"y = 1", "x = T.m",
+		}},
+		{`package p10; var (d = c + b; a = 0; b = 0; c = 0)`, []string{
+			"a = 0", "b = 0", "c = 0", "d = c + b",
+		}},
+		{`package p11; var (a = e + c; b = d + c; c = 0; d = 0; e = 0)`, []string{
+			"c = 0", "d = 0", "b = d + c", "e = 0", "a = e + c",
+		}},
+		// emit an initializer for n:1 initializations only once (not for each node
+		// on the lhs which may appear in different order in the dependency graph)
+		{`package p12; var (a = x; b = 0; x, y = m[0]; m map[int]int)`, []string{
+			"b = 0", "x, y = m[0]", "a = x",
+		}},
+		// test case from spec section on package initialization
+		{`package p12
+
+		var (
+			a = c + b
+			b = f()
+			c = f()
+			d = 3
+		)
+
+		func f() int {
+			d++
+			return d
+		}`, []string{
+			"d = 3", "b = f()", "c = f()", "a = c + b",
+		}},
+		// test case for issue 7131
+		{`package main
+
+		var counter int
+		func next() int { counter++; return counter }
+
+		var _ = makeOrder()
+		func makeOrder() []int { return []int{f, b, d, e, c, a} }
+
+		var a       = next()
+		var b, c    = next(), next()
+		var d, e, f = next(), next(), next()
+		`, []string{
+			"a = next()", "b = next()", "c = next()", "d = next()", "e = next()", "f = next()", "_ = makeOrder()",
+		}},
+	}
+
+	for _, test := range tests {
+		info := Info{}
+		name := mustTypecheck(t, "InitOrderInfo", test.src, &info)
+
+		// number of initializers must match
+		if len(info.InitOrder) != len(test.inits) {
+			t.Errorf("package %s: got %d initializers; want %d", name, len(info.InitOrder), len(test.inits))
+			continue
+		}
+
+		// initializers must match
+		for i, want := range test.inits {
+			got := info.InitOrder[i].String()
+			if got != want {
+				t.Errorf("package %s, init %d: got %s; want %s", name, i, got, want)
+				continue
+			}
+		}
+	}
+}
+
+func TestMultiFileInitOrder(t *testing.T) {
+	fset := token.NewFileSet()
+	mustParse := func(src string) *ast.File {
+		f, err := parser.ParseFile(fset, "main", src, 0)
+		if err != nil {
+			t.Fatal(err)
+		}
+		return f
+	}
+
+	fileA := mustParse(`package main; var a = 1`)
+	fileB := mustParse(`package main; var b = 2`)
+
+	// The initialization order must not depend on the parse
+	// order of the files, only on the presentation order to
+	// the type-checker.
+	for _, test := range []struct {
+		files []*ast.File
+		want  string
+	}{
+		{[]*ast.File{fileA, fileB}, "[a = 1 b = 2]"},
+		{[]*ast.File{fileB, fileA}, "[b = 2 a = 1]"},
+	} {
+		var info Info
+		if _, err := new(Config).Check("main", fset, test.files, &info); err != nil {
+			t.Fatal(err)
+		}
+		if got := fmt.Sprint(info.InitOrder); got != test.want {
+			t.Fatalf("got %s; want %s", got, test.want)
+		}
+	}
+}
+
+func TestFiles(t *testing.T) {
+	var sources = []string{
+		"package p; type T struct{}; func (T) m1() {}",
+		"package p; func (T) m2() {}; var x interface{ m1(); m2() } = T{}",
+		"package p; func (T) m3() {}; var y interface{ m1(); m2(); m3() } = T{}",
+		"package p",
+	}
+
+	var conf Config
+	fset := token.NewFileSet()
+	pkg := NewPackage("p", "p")
+	var info Info
+	check := NewChecker(&conf, fset, pkg, &info)
+
+	for i, src := range sources {
+		filename := fmt.Sprintf("sources%d", i)
+		f, err := parser.ParseFile(fset, filename, src, 0)
+		if err != nil {
+			t.Fatal(err)
+		}
+		if err := check.Files([]*ast.File{f}); err != nil {
+			t.Error(err)
+		}
+	}
+
+	// check InitOrder is [x y]
+	var vars []string
+	for _, init := range info.InitOrder {
+		for _, v := range init.Lhs {
+			vars = append(vars, v.Name())
+		}
+	}
+	if got, want := fmt.Sprint(vars), "[x y]"; got != want {
+		t.Errorf("InitOrder == %s, want %s", got, want)
+	}
+}
+
+func TestSelection(t *testing.T) {
+	selections := make(map[*ast.SelectorExpr]*Selection)
+
+	fset := token.NewFileSet()
+	conf := Config{
+		Packages: make(map[string]*Package),
+		Import: func(imports map[string]*Package, path string) (*Package, error) {
+			return imports[path], nil
+		},
+	}
+	makePkg := func(path, src string) {
+		f, err := parser.ParseFile(fset, path+".go", src, 0)
+		if err != nil {
+			t.Fatal(err)
+		}
+		pkg, err := conf.Check(path, fset, []*ast.File{f}, &Info{Selections: selections})
+		if err != nil {
+			t.Fatal(err)
+		}
+		conf.Packages[path] = pkg
+	}
+
+	const libSrc = `
+package lib
+type T float64
+const C T = 3
+var V T
+func F() {}
+func (T) M() {}
+`
+	const mainSrc = `
+package main
+import "lib"
+
+type A struct {
+	*B
+	C
+}
+
+type B struct {
+	b int
+}
+
+func (B) f(int)
+
+type C struct {
+	c int
+}
+
+func (C) g()
+func (*C) h()
+
+func main() {
+	// qualified identifiers
+	var _ lib.T
+        _ = lib.C
+        _ = lib.F
+        _ = lib.V
+	_ = lib.T.M
+
+	// fields
+	_ = A{}.B
+	_ = new(A).B
+
+	_ = A{}.C
+	_ = new(A).C
+
+	_ = A{}.b
+	_ = new(A).b
+
+	_ = A{}.c
+	_ = new(A).c
+
+	// methods
+        _ = A{}.f
+        _ = new(A).f
+        _ = A{}.g
+        _ = new(A).g
+        _ = new(A).h
+
+        _ = B{}.f
+        _ = new(B).f
+
+        _ = C{}.g
+        _ = new(C).g
+        _ = new(C).h
+
+	// method expressions
+        _ = A.f
+        _ = (*A).f
+        _ = B.f
+        _ = (*B).f
+}`
+
+	wantOut := map[string][2]string{
+		"lib.T.M": {"method expr (lib.T) M(lib.T)", ".[0]"},
+
+		"A{}.B":    {"field (main.A) B *main.B", ".[0]"},
+		"new(A).B": {"field (*main.A) B *main.B", "->[0]"},
+		"A{}.C":    {"field (main.A) C main.C", ".[1]"},
+		"new(A).C": {"field (*main.A) C main.C", "->[1]"},
+		"A{}.b":    {"field (main.A) b int", "->[0 0]"},
+		"new(A).b": {"field (*main.A) b int", "->[0 0]"},
+		"A{}.c":    {"field (main.A) c int", ".[1 0]"},
+		"new(A).c": {"field (*main.A) c int", "->[1 0]"},
+
+		"A{}.f":    {"method (main.A) f(int)", "->[0 0]"},
+		"new(A).f": {"method (*main.A) f(int)", "->[0 0]"},
+		"A{}.g":    {"method (main.A) g()", ".[1 0]"},
+		"new(A).g": {"method (*main.A) g()", "->[1 0]"},
+		"new(A).h": {"method (*main.A) h()", "->[1 1]"}, // TODO(gri) should this report .[1 1] ?
+		"B{}.f":    {"method (main.B) f(int)", ".[0]"},
+		"new(B).f": {"method (*main.B) f(int)", "->[0]"},
+		"C{}.g":    {"method (main.C) g()", ".[0]"},
+		"new(C).g": {"method (*main.C) g()", "->[0]"},
+		"new(C).h": {"method (*main.C) h()", "->[1]"}, // TODO(gri) should this report .[1] ?
+
+		"A.f":    {"method expr (main.A) f(main.A, int)", "->[0 0]"},
+		"(*A).f": {"method expr (*main.A) f(*main.A, int)", "->[0 0]"},
+		"B.f":    {"method expr (main.B) f(main.B, int)", ".[0]"},
+		"(*B).f": {"method expr (*main.B) f(*main.B, int)", "->[0]"},
+	}
+
+	makePkg("lib", libSrc)
+	makePkg("main", mainSrc)
+
+	for e, sel := range selections {
+		sel.String() // assertion: must not panic
+
+		start := fset.Position(e.Pos()).Offset
+		end := fset.Position(e.End()).Offset
+		syntax := mainSrc[start:end] // (all SelectorExprs are in main, not lib)
+
+		direct := "."
+		if sel.Indirect() {
+			direct = "->"
+		}
+		got := [2]string{
+			sel.String(),
+			fmt.Sprintf("%s%v", direct, sel.Index()),
+		}
+		want := wantOut[syntax]
+		if want != got {
+			t.Errorf("%s: got %q; want %q", syntax, got, want)
+		}
+		delete(wantOut, syntax)
+
+		// We must explicitly assert properties of the
+		// Signature's receiver since it doesn't participate
+		// in Identical() or String().
+		sig, _ := sel.Type().(*Signature)
+		if sel.Kind() == MethodVal {
+			got := sig.Recv().Type()
+			want := sel.Recv()
+			if !Identical(got, want) {
+				t.Errorf("%s: Recv() = %s, want %s", syntax, got, want)
+			}
+		} else if sig != nil && sig.Recv() != nil {
+			t.Errorf("%s: signature has receiver %s", sig, sig.Recv().Type())
+		}
+	}
+	// Assert that all wantOut entries were used exactly once.
+	for syntax := range wantOut {
+		t.Errorf("no ast.Selection found with syntax %q", syntax)
+	}
+}
+
+func TestIssue8518(t *testing.T) {
+	fset := token.NewFileSet()
+	conf := Config{
+		Packages: make(map[string]*Package),
+		Error:    func(err error) { t.Log(err) }, // don't exit after first error
+		Import: func(imports map[string]*Package, path string) (*Package, error) {
+			return imports[path], nil
+		},
+	}
+	makePkg := func(path, src string) {
+		f, err := parser.ParseFile(fset, path, src, 0)
+		if err != nil {
+			t.Fatal(err)
+		}
+		pkg, _ := conf.Check(path, fset, []*ast.File{f}, nil) // errors logged via conf.Error
+		conf.Packages[path] = pkg
+	}
+
+	const libSrc = `
+package a
+import "missing"
+const C1 = foo
+const C2 = missing.C
+`
+
+	const mainSrc = `
+package main
+import "a"
+var _ = a.C1
+var _ = a.C2
+`
+
+	makePkg("a", libSrc)
+	makePkg("main", mainSrc) // don't crash when type-checking this package
+}
+
+func TestLookupFieldOrMethod(t *testing.T) {
+	// Test cases assume a lookup of the form a.f or x.f, where a stands for an
+	// addressable value, and x for a non-addressable value (even though a variable
+	// for ease of test case writing).
+	var tests = []struct {
+		src      string
+		found    bool
+		index    []int
+		indirect bool
+	}{
+		// field lookups
+		{"var x T; type T struct{}", false, nil, false},
+		{"var x T; type T struct{ f int }", true, []int{0}, false},
+		{"var x T; type T struct{ a, b, f, c int }", true, []int{2}, false},
+
+		// method lookups
+		{"var a T; type T struct{}; func (T) f() {}", true, []int{0}, false},
+		{"var a *T; type T struct{}; func (T) f() {}", true, []int{0}, true},
+		{"var a T; type T struct{}; func (*T) f() {}", true, []int{0}, false},
+		{"var a *T; type T struct{}; func (*T) f() {}", true, []int{0}, true}, // TODO(gri) should this report indirect = false?
+
+		// collisions
+		{"type ( E1 struct{ f int }; E2 struct{ f int }; x struct{ E1; *E2 })", false, []int{1, 0}, false},
+		{"type ( E1 struct{ f int }; E2 struct{}; x struct{ E1; *E2 }); func (E2) f() {}", false, []int{1, 0}, false},
+
+		// outside methodset
+		// (*T).f method exists, but value of type T is not addressable
+		{"var x T; type T struct{}; func (*T) f() {}", false, nil, true},
+	}
+
+	for _, test := range tests {
+		pkg, err := pkgFor("test", "package p;"+test.src, nil)
+		if err != nil {
+			t.Errorf("%s: incorrect test case: %s", test.src, err)
+			continue
+		}
+
+		obj := pkg.Scope().Lookup("a")
+		if obj == nil {
+			if obj = pkg.Scope().Lookup("x"); obj == nil {
+				t.Errorf("%s: incorrect test case - no object a or x", test.src)
+				continue
+			}
+		}
+
+		f, index, indirect := LookupFieldOrMethod(obj.Type(), obj.Name() == "a", pkg, "f")
+		if (f != nil) != test.found {
+			if f == nil {
+				t.Errorf("%s: got no object; want one", test.src)
+			} else {
+				t.Errorf("%s: got object = %v; want none", test.src, f)
+			}
+		}
+		if !sameSlice(index, test.index) {
+			t.Errorf("%s: got index = %v; want %v", test.src, index, test.index)
+		}
+		if indirect != test.indirect {
+			t.Errorf("%s: got indirect = %v; want %v", test.src, indirect, test.indirect)
+		}
+	}
+}
+
+func sameSlice(a, b []int) bool {
+	if len(a) != len(b) {
+		return false
+	}
+	for i, x := range a {
+		if x != b[i] {
+			return false
+		}
+	}
+	return true
+}
+
+// TestScopeLookupParent ensures that (*Scope).LookupParent returns
+// the correct result at various positions with the source.
+func TestScopeLookupParent(t *testing.T) {
+	fset := token.NewFileSet()
+	conf := Config{
+		Packages: make(map[string]*Package),
+		Import: func(imports map[string]*Package, path string) (*Package, error) {
+			return imports[path], nil
+		},
+	}
+	mustParse := func(src string) *ast.File {
+		f, err := parser.ParseFile(fset, "dummy.go", src, parser.ParseComments)
+		if err != nil {
+			t.Fatal(err)
+		}
+		return f
+	}
+	var info Info
+	makePkg := func(path string, files ...*ast.File) {
+		conf.Packages[path], _ = conf.Check(path, fset, files, &info)
+	}
+
+	makePkg("lib", mustParse("package lib; var X int"))
+	// Each /*name=kind:line*/ comment makes the test look up the
+	// name at that point and checks that it resolves to a decl of
+	// the specified kind and line number.  "undef" means undefined.
+	mainSrc := `
+package main
+import "lib"
+var Y = lib.X
+func f() {
+	print(Y) /*Y=var:4*/
+	z /*z=undef*/ := /*z=undef*/ 1 /*z=var:7*/
+	print(z)
+	/*f=func:5*/ /*lib=pkgname:3*/
+	type /*T=undef*/ T /*T=typename:10*/ *T
+}
+`
+	info.Uses = make(map[*ast.Ident]Object)
+	f := mustParse(mainSrc)
+	makePkg("main", f)
+	mainScope := conf.Packages["main"].Scope()
+	rx := regexp.MustCompile(`^/\*(\w*)=([\w:]*)\*/$`)
+	for _, group := range f.Comments {
+		for _, comment := range group.List {
+			// Parse the assertion in the comment.
+			m := rx.FindStringSubmatch(comment.Text)
+			if m == nil {
+				t.Errorf("%s: bad comment: %s",
+					fset.Position(comment.Pos()), comment.Text)
+				continue
+			}
+			name, want := m[1], m[2]
+
+			// Look up the name in the innermost enclosing scope.
+			inner := mainScope.Innermost(comment.Pos())
+			if inner == nil {
+				t.Errorf("%s: at %s: can't find innermost scope",
+					fset.Position(comment.Pos()), comment.Text)
+				continue
+			}
+			got := "undef"
+			if _, obj := inner.LookupParent(name, comment.Pos()); obj != nil {
+				kind := strings.ToLower(strings.TrimPrefix(reflect.TypeOf(obj).String(), "*types."))
+				got = fmt.Sprintf("%s:%d", kind, fset.Position(obj.Pos()).Line)
+			}
+			if got != want {
+				t.Errorf("%s: at %s: %s resolved to %s, want %s",
+					fset.Position(comment.Pos()), comment.Text, name, got, want)
+			}
+		}
+	}
+
+	// Check that for each referring identifier,
+	// a lookup of its name on the innermost
+	// enclosing scope returns the correct object.
+
+	for id, wantObj := range info.Uses {
+		inner := mainScope.Innermost(id.Pos())
+		if inner == nil {
+			t.Errorf("%s: can't find innermost scope enclosing %q",
+				fset.Position(id.Pos()), id.Name)
+			continue
+		}
+
+		// Exclude selectors and qualified identifiers---lexical
+		// refs only.  (Ideally, we'd see if the AST parent is a
+		// SelectorExpr, but that requires PathEnclosingInterval
+		// from golang.org/x/tools/go/ast/astutil.)
+		if id.Name == "X" {
+			continue
+		}
+
+		_, gotObj := inner.LookupParent(id.Name, id.Pos())
+		if gotObj != wantObj {
+			t.Errorf("%s: got %v, want %v",
+				fset.Position(id.Pos()), gotObj, wantObj)
+			continue
+		}
+	}
+}
diff --git a/go/types/assignments.go b/go/types/assignments.go
new file mode 100644
index 0000000..93b842e
--- /dev/null
+++ b/go/types/assignments.go
@@ -0,0 +1,328 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file implements initialization and assignment checks.
+
+package types
+
+import (
+	"go/ast"
+	"go/token"
+)
+
+// assignment reports whether x can be assigned to a variable of type T,
+// if necessary by attempting to convert untyped values to the appropriate
+// type. If x.mode == invalid upon return, then assignment has already
+// issued an error message and the caller doesn't have to report another.
+// Use T == nil to indicate assignment to an untyped blank identifier.
+//
+// TODO(gri) Should find a better way to handle in-band errors.
+//
+func (check *Checker) assignment(x *operand, T Type) bool {
+	switch x.mode {
+	case invalid:
+		return true // error reported before
+	case constant, variable, mapindex, value, commaok:
+		// ok
+	default:
+		unreachable()
+	}
+
+	// x must be a single value
+	// (tuple types are never named - no need for underlying type)
+	if t, _ := x.typ.(*Tuple); t != nil {
+		assert(t.Len() > 1)
+		check.errorf(x.pos(), "%d-valued expression %s used as single value", t.Len(), x)
+		x.mode = invalid
+		return false
+	}
+
+	if isUntyped(x.typ) {
+		target := T
+		// spec: "If an untyped constant is assigned to a variable of interface
+		// type or the blank identifier, the constant is first converted to type
+		// bool, rune, int, float64, complex128 or string respectively, depending
+		// on whether the value is a boolean, rune, integer, floating-point, complex,
+		// or string constant."
+		if T == nil || IsInterface(T) {
+			if T == nil && x.typ == Typ[UntypedNil] {
+				check.errorf(x.pos(), "use of untyped nil")
+				x.mode = invalid
+				return false
+			}
+			target = defaultType(x.typ)
+		}
+		check.convertUntyped(x, target)
+		if x.mode == invalid {
+			return false
+		}
+	}
+
+	// spec: "If a left-hand side is the blank identifier, any typed or
+	// non-constant value except for the predeclared identifier nil may
+	// be assigned to it."
+	return T == nil || x.assignableTo(check.conf, T)
+}
+
+func (check *Checker) initConst(lhs *Const, x *operand) {
+	if x.mode == invalid || x.typ == Typ[Invalid] || lhs.typ == Typ[Invalid] {
+		if lhs.typ == nil {
+			lhs.typ = Typ[Invalid]
+		}
+		return
+	}
+
+	// rhs must be a constant
+	if x.mode != constant {
+		check.errorf(x.pos(), "%s is not constant", x)
+		if lhs.typ == nil {
+			lhs.typ = Typ[Invalid]
+		}
+		return
+	}
+	assert(isConstType(x.typ))
+
+	// If the lhs doesn't have a type yet, use the type of x.
+	if lhs.typ == nil {
+		lhs.typ = x.typ
+	}
+
+	if !check.assignment(x, lhs.typ) {
+		if x.mode != invalid {
+			check.errorf(x.pos(), "cannot define constant %s (type %s) as %s", lhs.Name(), lhs.typ, x)
+		}
+		return
+	}
+
+	lhs.val = x.val
+}
+
+// If result is set, lhs is a function result parameter and x is a return result.
+func (check *Checker) initVar(lhs *Var, x *operand, result bool) Type {
+	if x.mode == invalid || x.typ == Typ[Invalid] || lhs.typ == Typ[Invalid] {
+		if lhs.typ == nil {
+			lhs.typ = Typ[Invalid]
+		}
+		return nil
+	}
+
+	// If the lhs doesn't have a type yet, use the type of x.
+	if lhs.typ == nil {
+		typ := x.typ
+		if isUntyped(typ) {
+			// convert untyped types to default types
+			if typ == Typ[UntypedNil] {
+				check.errorf(x.pos(), "use of untyped nil")
+				lhs.typ = Typ[Invalid]
+				return nil
+			}
+			typ = defaultType(typ)
+		}
+		lhs.typ = typ
+	}
+
+	if !check.assignment(x, lhs.typ) {
+		if x.mode != invalid {
+			if result {
+				// don't refer to lhs.name because it may be an anonymous result parameter
+				check.errorf(x.pos(), "cannot return %s as value of type %s", x, lhs.typ)
+			} else {
+				check.errorf(x.pos(), "cannot initialize %s with %s", lhs, x)
+			}
+		}
+		return nil
+	}
+
+	return x.typ
+}
+
+func (check *Checker) assignVar(lhs ast.Expr, x *operand) Type {
+	if x.mode == invalid || x.typ == Typ[Invalid] {
+		return nil
+	}
+
+	// Determine if the lhs is a (possibly parenthesized) identifier.
+	ident, _ := unparen(lhs).(*ast.Ident)
+
+	// Don't evaluate lhs if it is the blank identifier.
+	if ident != nil && ident.Name == "_" {
+		check.recordDef(ident, nil)
+		if !check.assignment(x, nil) {
+			assert(x.mode == invalid)
+			x.typ = nil
+		}
+		return x.typ
+	}
+
+	// If the lhs is an identifier denoting a variable v, this assignment
+	// is not a 'use' of v. Remember current value of v.used and restore
+	// after evaluating the lhs via check.expr.
+	var v *Var
+	var v_used bool
+	if ident != nil {
+		if _, obj := check.scope.LookupParent(ident.Name, token.NoPos); obj != nil {
+			v, _ = obj.(*Var)
+			if v != nil {
+				v_used = v.used
+			}
+		}
+	}
+
+	var z operand
+	check.expr(&z, lhs)
+	if v != nil {
+		v.used = v_used // restore v.used
+	}
+
+	if z.mode == invalid || z.typ == Typ[Invalid] {
+		return nil
+	}
+
+	// spec: "Each left-hand side operand must be addressable, a map index
+	// expression, or the blank identifier. Operands may be parenthesized."
+	switch z.mode {
+	case invalid:
+		return nil
+	case variable, mapindex:
+		// ok
+	default:
+		check.errorf(z.pos(), "cannot assign to %s", &z)
+		return nil
+	}
+
+	if !check.assignment(x, z.typ) {
+		if x.mode != invalid {
+			check.errorf(x.pos(), "cannot assign %s to %s", x, &z)
+		}
+		return nil
+	}
+
+	return x.typ
+}
+
+// If returnPos is valid, initVars is called to type-check the assignment of
+// return expressions, and returnPos is the position of the return statement.
+func (check *Checker) initVars(lhs []*Var, rhs []ast.Expr, returnPos token.Pos) {
+	l := len(lhs)
+	get, r, commaOk := unpack(func(x *operand, i int) { check.expr(x, rhs[i]) }, len(rhs), l == 2 && !returnPos.IsValid())
+	if get == nil || l != r {
+		// invalidate lhs and use rhs
+		for _, obj := range lhs {
+			if obj.typ == nil {
+				obj.typ = Typ[Invalid]
+			}
+		}
+		if get == nil {
+			return // error reported by unpack
+		}
+		check.useGetter(get, r)
+		if returnPos.IsValid() {
+			check.errorf(returnPos, "wrong number of return values (want %d, got %d)", l, r)
+			return
+		}
+		check.errorf(rhs[0].Pos(), "assignment count mismatch (%d vs %d)", l, r)
+		return
+	}
+
+	var x operand
+	if commaOk {
+		var a [2]Type
+		for i := range a {
+			get(&x, i)
+			a[i] = check.initVar(lhs[i], &x, returnPos.IsValid())
+		}
+		check.recordCommaOkTypes(rhs[0], a)
+		return
+	}
+
+	for i, lhs := range lhs {
+		get(&x, i)
+		check.initVar(lhs, &x, returnPos.IsValid())
+	}
+}
+
+func (check *Checker) assignVars(lhs, rhs []ast.Expr) {
+	l := len(lhs)
+	get, r, commaOk := unpack(func(x *operand, i int) { check.expr(x, rhs[i]) }, len(rhs), l == 2)
+	if get == nil {
+		return // error reported by unpack
+	}
+	if l != r {
+		check.useGetter(get, r)
+		check.errorf(rhs[0].Pos(), "assignment count mismatch (%d vs %d)", l, r)
+		return
+	}
+
+	var x operand
+	if commaOk {
+		var a [2]Type
+		for i := range a {
+			get(&x, i)
+			a[i] = check.assignVar(lhs[i], &x)
+		}
+		check.recordCommaOkTypes(rhs[0], a)
+		return
+	}
+
+	for i, lhs := range lhs {
+		get(&x, i)
+		check.assignVar(lhs, &x)
+	}
+}
+
+func (check *Checker) shortVarDecl(pos token.Pos, lhs, rhs []ast.Expr) {
+	scope := check.scope
+
+	// collect lhs variables
+	var newVars []*Var
+	var lhsVars = make([]*Var, len(lhs))
+	for i, lhs := range lhs {
+		var obj *Var
+		if ident, _ := lhs.(*ast.Ident); ident != nil {
+			// Use the correct obj if the ident is redeclared. The
+			// variable's scope starts after the declaration; so we
+			// must use Scope.Lookup here and call Scope.Insert
+			// (via check.declare) later.
+			name := ident.Name
+			if alt := scope.Lookup(name); alt != nil {
+				// redeclared object must be a variable
+				if alt, _ := alt.(*Var); alt != nil {
+					obj = alt
+				} else {
+					check.errorf(lhs.Pos(), "cannot assign to %s", lhs)
+				}
+				check.recordUse(ident, alt)
+			} else {
+				// declare new variable, possibly a blank (_) variable
+				obj = NewVar(ident.Pos(), check.pkg, name, nil)
+				if name != "_" {
+					newVars = append(newVars, obj)
+				}
+				check.recordDef(ident, obj)
+			}
+		} else {
+			check.errorf(lhs.Pos(), "cannot declare %s", lhs)
+		}
+		if obj == nil {
+			obj = NewVar(lhs.Pos(), check.pkg, "_", nil) // dummy variable
+		}
+		lhsVars[i] = obj
+	}
+
+	check.initVars(lhsVars, rhs, token.NoPos)
+
+	// declare new variables
+	if len(newVars) > 0 {
+		// spec: "The scope of a constant or variable identifier declared inside
+		// a function begins at the end of the ConstSpec or VarSpec (ShortVarDecl
+		// for short variable declarations) and ends at the end of the innermost
+		// containing block."
+		scopePos := rhs[len(rhs)-1].End()
+		for _, obj := range newVars {
+			check.declare(scope, nil, obj, scopePos) // recordObject already called
+		}
+	} else {
+		check.softErrorf(pos, "no new variables on left side of :=")
+	}
+}
diff --git a/go/types/builtins.go b/go/types/builtins.go
new file mode 100644
index 0000000..f45f930
--- /dev/null
+++ b/go/types/builtins.go
@@ -0,0 +1,628 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file implements typechecking of builtin function calls.
+
+package types
+
+import (
+	"go/ast"
+	"go/token"
+
+	"golang.org/x/tools/go/exact"
+)
+
+// builtin type-checks a call to the built-in specified by id and
+// returns true if the call is valid, with *x holding the result;
+// but x.expr is not set. If the call is invalid, the result is
+// false, and *x is undefined.
+//
+func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ bool) {
+	// append is the only built-in that permits the use of ... for the last argument
+	bin := predeclaredFuncs[id]
+	if call.Ellipsis.IsValid() && id != _Append {
+		check.invalidOp(call.Ellipsis, "invalid use of ... with built-in %s", bin.name)
+		check.use(call.Args...)
+		return
+	}
+
+	// For len(x) and cap(x) we need to know if x contains any function calls or
+	// receive operations. Save/restore current setting and set hasCallOrRecv to
+	// false for the evaluation of x so that we can check it afterwards.
+	// Note: We must do this _before_ calling unpack because unpack evaluates the
+	//       first argument before we even call arg(x, 0)!
+	if id == _Len || id == _Cap {
+		defer func(b bool) {
+			check.hasCallOrRecv = b
+		}(check.hasCallOrRecv)
+		check.hasCallOrRecv = false
+	}
+
+	// determine actual arguments
+	var arg getter
+	nargs := len(call.Args)
+	switch id {
+	default:
+		// make argument getter
+		arg, nargs, _ = unpack(func(x *operand, i int) { check.expr(x, call.Args[i]) }, nargs, false)
+		if arg == nil {
+			return
+		}
+		// evaluate first argument, if present
+		if nargs > 0 {
+			arg(x, 0)
+			if x.mode == invalid {
+				return
+			}
+		}
+	case _Make, _New, _Offsetof, _Trace:
+		// arguments require special handling
+	}
+
+	// check argument count
+	{
+		msg := ""
+		if nargs < bin.nargs {
+			msg = "not enough"
+		} else if !bin.variadic && nargs > bin.nargs {
+			msg = "too many"
+		}
+		if msg != "" {
+			check.invalidOp(call.Rparen, "%s arguments for %s (expected %d, found %d)", msg, call, bin.nargs, nargs)
+			return
+		}
+	}
+
+	switch id {
+	case _Append:
+		// append(s S, x ...T) S, where T is the element type of S
+		// spec: "The variadic function append appends zero or more values x to s of type
+		// S, which must be a slice type, and returns the resulting slice, also of type S.
+		// The values x are passed to a parameter of type ...T where T is the element type
+		// of S and the respective parameter passing rules apply."
+		S := x.typ
+		var T Type
+		if s, _ := S.Underlying().(*Slice); s != nil {
+			T = s.elem
+		} else {
+			check.invalidArg(x.pos(), "%s is not a slice", x)
+			return
+		}
+
+		// remember arguments that have been evaluated already
+		alist := []operand{*x}
+
+		// spec: "As a special case, append also accepts a first argument assignable
+		// to type []byte with a second argument of string type followed by ... .
+		// This form appends the bytes of the string.
+		if nargs == 2 && call.Ellipsis.IsValid() && x.assignableTo(check.conf, NewSlice(universeByte)) {
+			arg(x, 1)
+			if x.mode == invalid {
+				return
+			}
+			if isString(x.typ) {
+				if check.Types != nil {
+					sig := makeSig(S, S, x.typ)
+					sig.variadic = true
+					check.recordBuiltinType(call.Fun, sig)
+				}
+				x.mode = value
+				x.typ = S
+				break
+			}
+			alist = append(alist, *x)
+			// fallthrough
+		}
+
+		// check general case by creating custom signature
+		sig := makeSig(S, S, NewSlice(T)) // []T required for variadic signature
+		sig.variadic = true
+		check.arguments(x, call, sig, func(x *operand, i int) {
+			// only evaluate arguments that have not been evaluated before
+			if i < len(alist) {
+				*x = alist[i]
+				return
+			}
+			arg(x, i)
+		}, nargs)
+		// ok to continue even if check.arguments reported errors
+
+		x.mode = value
+		x.typ = S
+		if check.Types != nil {
+			check.recordBuiltinType(call.Fun, sig)
+		}
+
+	case _Cap, _Len:
+		// cap(x)
+		// len(x)
+		mode := invalid
+		var typ Type
+		var val exact.Value
+		switch typ = implicitArrayDeref(x.typ.Underlying()); t := typ.(type) {
+		case *Basic:
+			if isString(t) && id == _Len {
+				if x.mode == constant {
+					mode = constant
+					val = exact.MakeInt64(int64(len(exact.StringVal(x.val))))
+				} else {
+					mode = value
+				}
+			}
+
+		case *Array:
+			mode = value
+			// spec: "The expressions len(s) and cap(s) are constants
+			// if the type of s is an array or pointer to an array and
+			// the expression s does not contain channel receives or
+			// function calls; in this case s is not evaluated."
+			if !check.hasCallOrRecv {
+				mode = constant
+				val = exact.MakeInt64(t.len)
+			}
+
+		case *Slice, *Chan:
+			mode = value
+
+		case *Map:
+			if id == _Len {
+				mode = value
+			}
+		}
+
+		if mode == invalid {
+			check.invalidArg(x.pos(), "%s for %s", x, bin.name)
+			return
+		}
+
+		x.mode = mode
+		x.typ = Typ[Int]
+		x.val = val
+		if check.Types != nil && mode != constant {
+			check.recordBuiltinType(call.Fun, makeSig(x.typ, typ))
+		}
+
+	case _Close:
+		// close(c)
+		c, _ := x.typ.Underlying().(*Chan)
+		if c == nil {
+			check.invalidArg(x.pos(), "%s is not a channel", x)
+			return
+		}
+		if c.dir == RecvOnly {
+			check.invalidArg(x.pos(), "%s must not be a receive-only channel", x)
+			return
+		}
+
+		x.mode = novalue
+		if check.Types != nil {
+			check.recordBuiltinType(call.Fun, makeSig(nil, c))
+		}
+
+	case _Complex:
+		// complex(x, y realT) complexT
+		if !check.complexArg(x) {
+			return
+		}
+
+		var y operand
+		arg(&y, 1)
+		if y.mode == invalid {
+			return
+		}
+		if !check.complexArg(&y) {
+			return
+		}
+
+		check.convertUntyped(x, y.typ)
+		if x.mode == invalid {
+			return
+		}
+		check.convertUntyped(&y, x.typ)
+		if y.mode == invalid {
+			return
+		}
+
+		if !Identical(x.typ, y.typ) {
+			check.invalidArg(x.pos(), "mismatched types %s and %s", x.typ, y.typ)
+			return
+		}
+
+		if x.mode == constant && y.mode == constant {
+			x.val = exact.BinaryOp(x.val, token.ADD, exact.MakeImag(y.val))
+		} else {
+			x.mode = value
+		}
+
+		realT := x.typ
+		complexT := Typ[Invalid]
+		switch realT.Underlying().(*Basic).kind {
+		case Float32:
+			complexT = Typ[Complex64]
+		case Float64:
+			complexT = Typ[Complex128]
+		case UntypedInt, UntypedRune, UntypedFloat:
+			if x.mode == constant {
+				realT = defaultType(realT).(*Basic)
+				complexT = Typ[UntypedComplex]
+			} else {
+				// untyped but not constant; probably because one
+				// operand is a non-constant shift of untyped lhs
+				realT = Typ[Float64]
+				complexT = Typ[Complex128]
+			}
+		default:
+			check.invalidArg(x.pos(), "float32 or float64 arguments expected")
+			return
+		}
+
+		x.typ = complexT
+		if check.Types != nil && x.mode != constant {
+			check.recordBuiltinType(call.Fun, makeSig(complexT, realT, realT))
+		}
+
+		if x.mode != constant {
+			// The arguments have now their final types, which at run-
+			// time will be materialized. Update the expression trees.
+			// If the current types are untyped, the materialized type
+			// is the respective default type.
+			// (If the result is constant, the arguments are never
+			// materialized and there is nothing to do.)
+			check.updateExprType(x.expr, realT, true)
+			check.updateExprType(y.expr, realT, true)
+		}
+
+	case _Copy:
+		// copy(x, y []T) int
+		var dst Type
+		if t, _ := x.typ.Underlying().(*Slice); t != nil {
+			dst = t.elem
+		}
+
+		var y operand
+		arg(&y, 1)
+		if y.mode == invalid {
+			return
+		}
+		var src Type
+		switch t := y.typ.Underlying().(type) {
+		case *Basic:
+			if isString(y.typ) {
+				src = universeByte
+			}
+		case *Slice:
+			src = t.elem
+		}
+
+		if dst == nil || src == nil {
+			check.invalidArg(x.pos(), "copy expects slice arguments; found %s and %s", x, &y)
+			return
+		}
+
+		if !Identical(dst, src) {
+			check.invalidArg(x.pos(), "arguments to copy %s and %s have different element types %s and %s", x, &y, dst, src)
+			return
+		}
+
+		if check.Types != nil {
+			check.recordBuiltinType(call.Fun, makeSig(Typ[Int], x.typ, y.typ))
+		}
+		x.mode = value
+		x.typ = Typ[Int]
+
+	case _Delete:
+		// delete(m, k)
+		m, _ := x.typ.Underlying().(*Map)
+		if m == nil {
+			check.invalidArg(x.pos(), "%s is not a map", x)
+			return
+		}
+		arg(x, 1) // k
+		if x.mode == invalid {
+			return
+		}
+
+		if !x.assignableTo(check.conf, m.key) {
+			check.invalidArg(x.pos(), "%s is not assignable to %s", x, m.key)
+			return
+		}
+
+		x.mode = novalue
+		if check.Types != nil {
+			check.recordBuiltinType(call.Fun, makeSig(nil, m, m.key))
+		}
+
+	case _Imag, _Real:
+		// imag(complexT) realT
+		// real(complexT) realT
+		if !isComplex(x.typ) {
+			check.invalidArg(x.pos(), "%s must be a complex number", x)
+			return
+		}
+		if x.mode == constant {
+			if id == _Real {
+				x.val = exact.Real(x.val)
+			} else {
+				x.val = exact.Imag(x.val)
+			}
+		} else {
+			x.mode = value
+		}
+		var k BasicKind
+		switch x.typ.Underlying().(*Basic).kind {
+		case Complex64:
+			k = Float32
+		case Complex128:
+			k = Float64
+		case UntypedComplex:
+			k = UntypedFloat
+		default:
+			unreachable()
+		}
+
+		if check.Types != nil && x.mode != constant {
+			check.recordBuiltinType(call.Fun, makeSig(Typ[k], x.typ))
+		}
+		x.typ = Typ[k]
+
+	case _Make:
+		// make(T, n)
+		// make(T, n, m)
+		// (no argument evaluated yet)
+		arg0 := call.Args[0]
+		T := check.typ(arg0)
+		if T == Typ[Invalid] {
+			return
+		}
+
+		var min int // minimum number of arguments
+		switch T.Underlying().(type) {
+		case *Slice:
+			min = 2
+		case *Map, *Chan:
+			min = 1
+		default:
+			check.invalidArg(arg0.Pos(), "cannot make %s; type must be slice, map, or channel", arg0)
+			return
+		}
+		if nargs < min || min+1 < nargs {
+			check.errorf(call.Pos(), "%s expects %d or %d arguments; found %d", call, min, min+1, nargs)
+			return
+		}
+		var sizes []int64 // constant integer arguments, if any
+		for _, arg := range call.Args[1:] {
+			if s, ok := check.index(arg, -1); ok && s >= 0 {
+				sizes = append(sizes, s)
+			}
+		}
+		if len(sizes) == 2 && sizes[0] > sizes[1] {
+			check.invalidArg(call.Args[1].Pos(), "length and capacity swapped")
+			// safe to continue
+		}
+		x.mode = value
+		x.typ = T
+		if check.Types != nil {
+			params := [...]Type{T, Typ[Int], Typ[Int]}
+			check.recordBuiltinType(call.Fun, makeSig(x.typ, params[:1+len(sizes)]...))
+		}
+
+	case _New:
+		// new(T)
+		// (no argument evaluated yet)
+		T := check.typ(call.Args[0])
+		if T == Typ[Invalid] {
+			return
+		}
+
+		x.mode = value
+		x.typ = &Pointer{base: T}
+		if check.Types != nil {
+			check.recordBuiltinType(call.Fun, makeSig(x.typ, T))
+		}
+
+	case _Panic:
+		// panic(x)
+		T := new(Interface)
+		if !check.assignment(x, T) {
+			assert(x.mode == invalid)
+			return
+		}
+
+		x.mode = novalue
+		if check.Types != nil {
+			check.recordBuiltinType(call.Fun, makeSig(nil, T))
+		}
+
+	case _Print, _Println:
+		// print(x, y, ...)
+		// println(x, y, ...)
+		var params []Type
+		if nargs > 0 {
+			params = make([]Type, nargs)
+			for i := 0; i < nargs; i++ {
+				if i > 0 {
+					arg(x, i) // first argument already evaluated
+				}
+				if !check.assignment(x, nil) {
+					assert(x.mode == invalid)
+					return
+				}
+				params[i] = x.typ
+			}
+		}
+
+		x.mode = novalue
+		if check.Types != nil {
+			check.recordBuiltinType(call.Fun, makeSig(nil, params...))
+		}
+
+	case _Recover:
+		// recover() interface{}
+		x.mode = value
+		x.typ = new(Interface)
+		if check.Types != nil {
+			check.recordBuiltinType(call.Fun, makeSig(x.typ))
+		}
+
+	case _Alignof:
+		// unsafe.Alignof(x T) uintptr
+		if !check.assignment(x, nil) {
+			assert(x.mode == invalid)
+			return
+		}
+
+		x.mode = constant
+		x.val = exact.MakeInt64(check.conf.alignof(x.typ))
+		x.typ = Typ[Uintptr]
+		// result is constant - no need to record signature
+
+	case _Offsetof:
+		// unsafe.Offsetof(x T) uintptr, where x must be a selector
+		// (no argument evaluated yet)
+		arg0 := call.Args[0]
+		selx, _ := unparen(arg0).(*ast.SelectorExpr)
+		if selx == nil {
+			check.invalidArg(arg0.Pos(), "%s is not a selector expression", arg0)
+			check.use(arg0)
+			return
+		}
+
+		check.expr(x, selx.X)
+		if x.mode == invalid {
+			return
+		}
+
+		base := derefStructPtr(x.typ)
+		sel := selx.Sel.Name
+		obj, index, indirect := LookupFieldOrMethod(base, false, check.pkg, sel)
+		switch obj.(type) {
+		case nil:
+			check.invalidArg(x.pos(), "%s has no single field %s", base, sel)
+			return
+		case *Func:
+			// TODO(gri) Using derefStructPtr may result in methods being found
+			// that don't actually exist. An error either way, but the error
+			// message is confusing. See: http://play.golang.org/p/al75v23kUy ,
+			// but go/types reports: "invalid argument: x.m is a method value".
+			check.invalidArg(arg0.Pos(), "%s is a method value", arg0)
+			return
+		}
+		if indirect {
+			check.invalidArg(x.pos(), "field %s is embedded via a pointer in %s", sel, base)
+			return
+		}
+
+		// TODO(gri) Should we pass x.typ instead of base (and indirect report if derefStructPtr indirected)?
+		check.recordSelection(selx, FieldVal, base, obj, index, false)
+
+		offs := check.conf.offsetof(base, index)
+		x.mode = constant
+		x.val = exact.MakeInt64(offs)
+		x.typ = Typ[Uintptr]
+		// result is constant - no need to record signature
+
+	case _Sizeof:
+		// unsafe.Sizeof(x T) uintptr
+		if !check.assignment(x, nil) {
+			assert(x.mode == invalid)
+			return
+		}
+
+		x.mode = constant
+		x.val = exact.MakeInt64(check.conf.sizeof(x.typ))
+		x.typ = Typ[Uintptr]
+		// result is constant - no need to record signature
+
+	case _Assert:
+		// assert(pred) causes a typechecker error if pred is false.
+		// The result of assert is the value of pred if there is no error.
+		// Note: assert is only available in self-test mode.
+		if x.mode != constant || !isBoolean(x.typ) {
+			check.invalidArg(x.pos(), "%s is not a boolean constant", x)
+			return
+		}
+		if x.val.Kind() != exact.Bool {
+			check.errorf(x.pos(), "internal error: value of %s should be a boolean constant", x)
+			return
+		}
+		if !exact.BoolVal(x.val) {
+			check.errorf(call.Pos(), "%s failed", call)
+			// compile-time assertion failure - safe to continue
+		}
+		// result is constant - no need to record signature
+
+	case _Trace:
+		// trace(x, y, z, ...) dumps the positions, expressions, and
+		// values of its arguments. The result of trace is the value
+		// of the first argument.
+		// Note: trace is only available in self-test mode.
+		// (no argument evaluated yet)
+		if nargs == 0 {
+			check.dump("%s: trace() without arguments", call.Pos())
+			x.mode = novalue
+			break
+		}
+		var t operand
+		x1 := x
+		for _, arg := range call.Args {
+			check.rawExpr(x1, arg, nil) // permit trace for types, e.g.: new(trace(T))
+			check.dump("%s: %s", x1.pos(), x1)
+			x1 = &t // use incoming x only for first argument
+		}
+		// trace is only available in test mode - no need to record signature
+
+	default:
+		unreachable()
+	}
+
+	return true
+}
+
+// makeSig makes a signature for the given argument and result types.
+// Default types are used for untyped arguments, and res may be nil.
+func makeSig(res Type, args ...Type) *Signature {
+	list := make([]*Var, len(args))
+	for i, param := range args {
+		list[i] = NewVar(token.NoPos, nil, "", defaultType(param))
+	}
+	params := NewTuple(list...)
+	var result *Tuple
+	if res != nil {
+		assert(!isUntyped(res))
+		result = NewTuple(NewVar(token.NoPos, nil, "", res))
+	}
+	return &Signature{params: params, results: result}
+}
+
+// implicitArrayDeref returns A if typ is of the form *A and A is an array;
+// otherwise it returns typ.
+//
+func implicitArrayDeref(typ Type) Type {
+	if p, ok := typ.(*Pointer); ok {
+		if a, ok := p.base.Underlying().(*Array); ok {
+			return a
+		}
+	}
+	return typ
+}
+
+// unparen returns e with any enclosing parentheses stripped.
+func unparen(e ast.Expr) ast.Expr {
+	for {
+		p, ok := e.(*ast.ParenExpr)
+		if !ok {
+			return e
+		}
+		e = p.X
+	}
+}
+
+func (check *Checker) complexArg(x *operand) bool {
+	t, _ := x.typ.Underlying().(*Basic)
+	if t != nil && (t.info&IsFloat != 0 || t.kind == UntypedInt || t.kind == UntypedRune) {
+		return true
+	}
+	check.invalidArg(x.pos(), "%s must be a float32, float64, or an untyped non-complex numeric constant", x)
+	return false
+}
diff --git a/go/types/builtins_test.go b/go/types/builtins_test.go
new file mode 100644
index 0000000..e785799
--- /dev/null
+++ b/go/types/builtins_test.go
@@ -0,0 +1,204 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package types_test
+
+import (
+	"fmt"
+	"go/ast"
+	"go/parser"
+	"testing"
+
+	_ "golang.org/x/tools/go/gcimporter"
+	. "golang.org/x/tools/go/types"
+)
+
+var builtinCalls = []struct {
+	name, src, sig string
+}{
+	{"append", `var s []int; _ = append(s)`, `func([]int, ...int) []int`},
+	{"append", `var s []int; _ = append(s, 0)`, `func([]int, ...int) []int`},
+	{"append", `var s []int; _ = (append)(s, 0)`, `func([]int, ...int) []int`},
+	{"append", `var s []byte; _ = ((append))(s, 0)`, `func([]byte, ...byte) []byte`},
+	{"append", `var s []byte; _ = append(s, "foo"...)`, `func([]byte, string...) []byte`},
+	{"append", `type T []byte; var s T; var str string; _ = append(s, str...)`, `func(p.T, string...) p.T`},
+	{"append", `type T []byte; type U string; var s T; var str U; _ = append(s, str...)`, `func(p.T, p.U...) p.T`},
+
+	{"cap", `var s [10]int; _ = cap(s)`, `invalid type`},  // constant
+	{"cap", `var s [10]int; _ = cap(&s)`, `invalid type`}, // constant
+	{"cap", `var s []int64; _ = cap(s)`, `func([]int64) int`},
+	{"cap", `var c chan<-bool; _ = cap(c)`, `func(chan<- bool) int`},
+
+	{"len", `_ = len("foo")`, `invalid type`}, // constant
+	{"len", `var s string; _ = len(s)`, `func(string) int`},
+	{"len", `var s [10]int; _ = len(s)`, `invalid type`},  // constant
+	{"len", `var s [10]int; _ = len(&s)`, `invalid type`}, // constant
+	{"len", `var s []int64; _ = len(s)`, `func([]int64) int`},
+	{"len", `var c chan<-bool; _ = len(c)`, `func(chan<- bool) int`},
+	{"len", `var m map[string]float32; _ = len(m)`, `func(map[string]float32) int`},
+
+	{"close", `var c chan int; close(c)`, `func(chan int)`},
+	{"close", `var c chan<- chan string; close(c)`, `func(chan<- chan string)`},
+
+	{"complex", `_ = complex(1, 0)`, `invalid type`}, // constant
+	{"complex", `var re float32; _ = complex(re, 1.0)`, `func(float32, float32) complex64`},
+	{"complex", `var im float64; _ = complex(1, im)`, `func(float64, float64) complex128`},
+	{"complex", `type F32 float32; var re, im F32; _ = complex(re, im)`, `func(p.F32, p.F32) complex64`},
+	{"complex", `type F64 float64; var re, im F64; _ = complex(re, im)`, `func(p.F64, p.F64) complex128`},
+
+	{"copy", `var src, dst []byte; copy(dst, src)`, `func([]byte, []byte) int`},
+	{"copy", `type T [][]int; var src, dst T; _ = copy(dst, src)`, `func(p.T, p.T) int`},
+	{"copy", `var src string; var dst []byte; copy(dst, src)`, `func([]byte, string) int`},
+	{"copy", `type T string; type U []byte; var src T; var dst U; copy(dst, src)`, `func(p.U, p.T) int`},
+	{"copy", `var dst []byte; copy(dst, "hello")`, `func([]byte, string) int`},
+
+	{"delete", `var m map[string]bool; delete(m, "foo")`, `func(map[string]bool, string)`},
+	{"delete", `type (K string; V int); var m map[K]V; delete(m, "foo")`, `func(map[p.K]p.V, p.K)`},
+
+	{"imag", `_ = imag(1i)`, `invalid type`}, // constant
+	{"imag", `var c complex64; _ = imag(c)`, `func(complex64) float32`},
+	{"imag", `var c complex128; _ = imag(c)`, `func(complex128) float64`},
+	{"imag", `type C64 complex64; var c C64; _ = imag(c)`, `func(p.C64) float32`},
+	{"imag", `type C128 complex128; var c C128; _ = imag(c)`, `func(p.C128) float64`},
+
+	{"real", `_ = real(1i)`, `invalid type`}, // constant
+	{"real", `var c complex64; _ = real(c)`, `func(complex64) float32`},
+	{"real", `var c complex128; _ = real(c)`, `func(complex128) float64`},
+	{"real", `type C64 complex64; var c C64; _ = real(c)`, `func(p.C64) float32`},
+	{"real", `type C128 complex128; var c C128; _ = real(c)`, `func(p.C128) float64`},
+
+	{"make", `_ = make([]int, 10)`, `func([]int, int) []int`},
+	{"make", `type T []byte; _ = make(T, 10, 20)`, `func(p.T, int, int) p.T`},
+
+	{"new", `_ = new(int)`, `func(int) *int`},
+	{"new", `type T struct{}; _ = new(T)`, `func(p.T) *p.T`},
+
+	{"panic", `panic(0)`, `func(interface{})`},
+	{"panic", `panic("foo")`, `func(interface{})`},
+
+	{"print", `print()`, `func()`},
+	{"print", `print(0)`, `func(int)`},
+	{"print", `print(1, 2.0, "foo", true)`, `func(int, float64, string, bool)`},
+
+	{"println", `println()`, `func()`},
+	{"println", `println(0)`, `func(int)`},
+	{"println", `println(1, 2.0, "foo", true)`, `func(int, float64, string, bool)`},
+
+	{"recover", `recover()`, `func() interface{}`},
+	{"recover", `_ = recover()`, `func() interface{}`},
+
+	{"Alignof", `_ = unsafe.Alignof(0)`, `invalid type`},                 // constant
+	{"Alignof", `var x struct{}; _ = unsafe.Alignof(x)`, `invalid type`}, // constant
+
+	{"Offsetof", `var x struct{f bool}; _ = unsafe.Offsetof(x.f)`, `invalid type`},           // constant
+	{"Offsetof", `var x struct{_ int; f bool}; _ = unsafe.Offsetof((&x).f)`, `invalid type`}, // constant
+
+	{"Sizeof", `_ = unsafe.Sizeof(0)`, `invalid type`},                 // constant
+	{"Sizeof", `var x struct{}; _ = unsafe.Sizeof(x)`, `invalid type`}, // constant
+
+	{"assert", `assert(true)`, `invalid type`},                                    // constant
+	{"assert", `type B bool; const pred B = 1 < 2; assert(pred)`, `invalid type`}, // constant
+
+	// no tests for trace since it produces output as a side-effect
+}
+
+func TestBuiltinSignatures(t *testing.T) {
+	DefPredeclaredTestFuncs()
+
+	seen := map[string]bool{"trace": true} // no test for trace built-in; add it manually
+	for _, call := range builtinCalls {
+		testBuiltinSignature(t, call.name, call.src, call.sig)
+		seen[call.name] = true
+	}
+
+	// make sure we didn't miss one
+	for _, name := range Universe.Names() {
+		if _, ok := Universe.Lookup(name).(*Builtin); ok && !seen[name] {
+			t.Errorf("missing test for %s", name)
+		}
+	}
+	for _, name := range Unsafe.Scope().Names() {
+		if _, ok := Unsafe.Scope().Lookup(name).(*Builtin); ok && !seen[name] {
+			t.Errorf("missing test for unsafe.%s", name)
+		}
+	}
+}
+
+func testBuiltinSignature(t *testing.T, name, src0, want string) {
+	src := fmt.Sprintf(`package p; import "unsafe"; type _ unsafe.Pointer /* use unsafe */; func _() { %s }`, src0)
+	f, err := parser.ParseFile(fset, "", src, 0)
+	if err != nil {
+		t.Errorf("%s: %s", src0, err)
+		return
+	}
+
+	var conf Config
+	uses := make(map[*ast.Ident]Object)
+	types := make(map[ast.Expr]TypeAndValue)
+	_, err = conf.Check(f.Name.Name, fset, []*ast.File{f}, &Info{Uses: uses, Types: types})
+	if err != nil {
+		t.Errorf("%s: %s", src0, err)
+		return
+	}
+
+	// find called function
+	n := 0
+	var fun ast.Expr
+	for x := range types {
+		if call, _ := x.(*ast.CallExpr); call != nil {
+			fun = call.Fun
+			n++
+		}
+	}
+	if n != 1 {
+		t.Errorf("%s: got %d CallExprs; want 1", src0, n)
+		return
+	}
+
+	// check recorded types for fun and descendents (may be parenthesized)
+	for {
+		// the recorded type for the built-in must match the wanted signature
+		typ := types[fun].Type
+		if typ == nil {
+			t.Errorf("%s: no type recorded for %s", src0, ExprString(fun))
+			return
+		}
+		if got := typ.String(); got != want {
+			t.Errorf("%s: got type %s; want %s", src0, got, want)
+			return
+		}
+
+		// called function must be a (possibly parenthesized, qualified)
+		// identifier denoting the expected built-in
+		switch p := fun.(type) {
+		case *ast.Ident:
+			obj := uses[p]
+			if obj == nil {
+				t.Errorf("%s: no object found for %s", src0, p)
+				return
+			}
+			bin, _ := obj.(*Builtin)
+			if bin == nil {
+				t.Errorf("%s: %s does not denote a built-in", src0, p)
+				return
+			}
+			if bin.Name() != name {
+				t.Errorf("%s: got built-in %s; want %s", src0, bin.Name(), name)
+				return
+			}
+			return // we're done
+
+		case *ast.ParenExpr:
+			fun = p.X // unpack
+
+		case *ast.SelectorExpr:
+			// built-in from package unsafe - ignore details
+			return // we're done
+
+		default:
+			t.Errorf("%s: invalid function call", src0)
+			return
+		}
+	}
+}
diff --git a/go/types/call.go b/go/types/call.go
new file mode 100644
index 0000000..1e94212
--- /dev/null
+++ b/go/types/call.go
@@ -0,0 +1,441 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file implements typechecking of call and selector expressions.
+
+package types
+
+import (
+	"go/ast"
+	"go/token"
+)
+
+func (check *Checker) call(x *operand, e *ast.CallExpr) exprKind {
+	check.exprOrType(x, e.Fun)
+
+	switch x.mode {
+	case invalid:
+		check.use(e.Args...)
+		x.mode = invalid
+		x.expr = e
+		return statement
+
+	case typexpr:
+		// conversion
+		T := x.typ
+		x.mode = invalid
+		switch n := len(e.Args); n {
+		case 0:
+			check.errorf(e.Rparen, "missing argument in conversion to %s", T)
+		case 1:
+			check.expr(x, e.Args[0])
+			if x.mode != invalid {
+				check.conversion(x, T)
+			}
+		default:
+			check.errorf(e.Args[n-1].Pos(), "too many arguments in conversion to %s", T)
+		}
+		x.expr = e
+		return conversion
+
+	case builtin:
+		id := x.id
+		if !check.builtin(x, e, id) {
+			x.mode = invalid
+		}
+		x.expr = e
+		// a non-constant result implies a function call
+		if x.mode != invalid && x.mode != constant {
+			check.hasCallOrRecv = true
+		}
+		return predeclaredFuncs[id].kind
+
+	default:
+		// function/method call
+		sig, _ := x.typ.Underlying().(*Signature)
+		if sig == nil {
+			check.invalidOp(x.pos(), "cannot call non-function %s", x)
+			x.mode = invalid
+			x.expr = e
+			return statement
+		}
+
+		arg, n, _ := unpack(func(x *operand, i int) { check.expr(x, e.Args[i]) }, len(e.Args), false)
+		if arg == nil {
+			x.mode = invalid
+			x.expr = e
+			return statement
+		}
+
+		check.arguments(x, e, sig, arg, n)
+
+		// determine result
+		switch sig.results.Len() {
+		case 0:
+			x.mode = novalue
+		case 1:
+			x.mode = value
+			x.typ = sig.results.vars[0].typ // unpack tuple
+		default:
+			x.mode = value
+			x.typ = sig.results
+		}
+		x.expr = e
+		check.hasCallOrRecv = true
+
+		return statement
+	}
+}
+
+// use type-checks each argument.
+// Useful to make sure expressions are evaluated
+// (and variables are "used") in the presence of other errors.
+func (check *Checker) use(arg ...ast.Expr) {
+	var x operand
+	for _, e := range arg {
+		check.rawExpr(&x, e, nil)
+	}
+}
+
+// useGetter is like use, but takes a getter instead of a list of expressions.
+// It should be called instead of use if a getter is present to avoid repeated
+// evaluation of the first argument (since the getter was likely obtained via
+// unpack, which may have evaluated the first argument already).
+func (check *Checker) useGetter(get getter, n int) {
+	var x operand
+	for i := 0; i < n; i++ {
+		get(&x, i)
+	}
+}
+
+// A getter sets x as the i'th operand, where 0 <= i < n and n is the total
+// number of operands (context-specific, and maintained elsewhere). A getter
+// type-checks the i'th operand; the details of the actual check are getter-
+// specific.
+type getter func(x *operand, i int)
+
+// unpack takes a getter get and a number of operands n. If n == 1, unpack
+// calls the incoming getter for the first operand. If that operand is
+// invalid, unpack returns (nil, 0, false). Otherwise, if that operand is a
+// function call, or a comma-ok expression and allowCommaOk is set, the result
+// is a new getter and operand count providing access to the function results,
+// or comma-ok values, respectively. The third result value reports if it
+// is indeed the comma-ok case. In all other cases, the incoming getter and
+// operand count are returned unchanged, and the third result value is false.
+//
+// In other words, if there's exactly one operand that - after type-checking
+// by calling get - stands for multiple operands, the resulting getter provides
+// access to those operands instead.
+//
+// If the returned getter is called at most once for a given operand index i
+// (including i == 0), that operand is guaranteed to cause only one call of
+// the incoming getter with that i.
+//
+func unpack(get getter, n int, allowCommaOk bool) (getter, int, bool) {
+	if n == 1 {
+		// possibly result of an n-valued function call or comma,ok value
+		var x0 operand
+		get(&x0, 0)
+		if x0.mode == invalid {
+			return nil, 0, false
+		}
+
+		if t, ok := x0.typ.(*Tuple); ok {
+			// result of an n-valued function call
+			return func(x *operand, i int) {
+				x.mode = value
+				x.expr = x0.expr
+				x.typ = t.At(i).typ
+			}, t.Len(), false
+		}
+
+		if x0.mode == mapindex || x0.mode == commaok {
+			// comma-ok value
+			if allowCommaOk {
+				a := [2]Type{x0.typ, Typ[UntypedBool]}
+				return func(x *operand, i int) {
+					x.mode = value
+					x.expr = x0.expr
+					x.typ = a[i]
+				}, 2, true
+			}
+			x0.mode = value
+		}
+
+		// single value
+		return func(x *operand, i int) {
+			if i != 0 {
+				unreachable()
+			}
+			*x = x0
+		}, 1, false
+	}
+
+	// zero or multiple values
+	return get, n, false
+}
+
+// arguments checks argument passing for the call with the given signature.
+// The arg function provides the operand for the i'th argument.
+func (check *Checker) arguments(x *operand, call *ast.CallExpr, sig *Signature, arg getter, n int) {
+	if call.Ellipsis.IsValid() {
+		// last argument is of the form x...
+		if len(call.Args) == 1 && n > 1 {
+			// f()... is not permitted if f() is multi-valued
+			check.errorf(call.Ellipsis, "cannot use ... with %d-valued expression %s", n, call.Args[0])
+			check.useGetter(arg, n)
+			return
+		}
+		if !sig.variadic {
+			check.errorf(call.Ellipsis, "cannot use ... in call to non-variadic %s", call.Fun)
+			check.useGetter(arg, n)
+			return
+		}
+	}
+
+	// evaluate arguments
+	for i := 0; i < n; i++ {
+		arg(x, i)
+		if x.mode != invalid {
+			var ellipsis token.Pos
+			if i == n-1 && call.Ellipsis.IsValid() {
+				ellipsis = call.Ellipsis
+			}
+			check.argument(sig, i, x, ellipsis)
+		}
+	}
+
+	// check argument count
+	if sig.variadic {
+		// a variadic function accepts an "empty"
+		// last argument: count one extra
+		n++
+	}
+	if n < sig.params.Len() {
+		check.errorf(call.Rparen, "too few arguments in call to %s", call.Fun)
+		// ok to continue
+	}
+}
+
+// argument checks passing of argument x to the i'th parameter of the given signature.
+// If ellipsis is valid, the argument is followed by ... at that position in the call.
+func (check *Checker) argument(sig *Signature, i int, x *operand, ellipsis token.Pos) {
+	n := sig.params.Len()
+
+	// determine parameter type
+	var typ Type
+	switch {
+	case i < n:
+		typ = sig.params.vars[i].typ
+	case sig.variadic:
+		typ = sig.params.vars[n-1].typ
+		if debug {
+			if _, ok := typ.(*Slice); !ok {
+				check.dump("%s: expected unnamed slice type, got %s", sig.params.vars[n-1].Pos(), typ)
+			}
+		}
+	default:
+		check.errorf(x.pos(), "too many arguments")
+		return
+	}
+
+	if ellipsis.IsValid() {
+		// argument is of the form x...
+		if i != n-1 {
+			check.errorf(ellipsis, "can only use ... with matching parameter")
+			return
+		}
+		switch t := x.typ.Underlying().(type) {
+		case *Slice:
+			// ok
+		case *Tuple:
+			check.errorf(ellipsis, "cannot use ... with %d-valued expression %s", t.Len(), x)
+			return
+		default:
+			check.errorf(x.pos(), "cannot use %s as parameter of type %s", x, typ)
+			return
+		}
+	} else if sig.variadic && i >= n-1 {
+		// use the variadic parameter slice's element type
+		typ = typ.(*Slice).elem
+	}
+
+	if !check.assignment(x, typ) && x.mode != invalid {
+		check.errorf(x.pos(), "cannot pass argument %s to parameter of type %s", x, typ)
+	}
+}
+
+func (check *Checker) selector(x *operand, e *ast.SelectorExpr) {
+	// these must be declared before the "goto Error" statements
+	var (
+		obj      Object
+		index    []int
+		indirect bool
+	)
+
+	sel := e.Sel.Name
+	// If the identifier refers to a package, handle everything here
+	// so we don't need a "package" mode for operands: package names
+	// can only appear in qualified identifiers which are mapped to
+	// selector expressions.
+	if ident, ok := e.X.(*ast.Ident); ok {
+		_, obj := check.scope.LookupParent(ident.Name, check.pos)
+		if pkg, _ := obj.(*PkgName); pkg != nil {
+			assert(pkg.pkg == check.pkg)
+			check.recordUse(ident, pkg)
+			pkg.used = true
+			exp := pkg.imported.scope.Lookup(sel)
+			if exp == nil {
+				if !pkg.imported.fake {
+					check.errorf(e.Pos(), "%s not declared by package %s", sel, ident)
+				}
+				goto Error
+			}
+			if !exp.Exported() {
+				check.errorf(e.Pos(), "%s not exported by package %s", sel, ident)
+				// ok to continue
+			}
+			check.recordUse(e.Sel, exp)
+			// Simplified version of the code for *ast.Idents:
+			// - imported objects are always fully initialized
+			switch exp := exp.(type) {
+			case *Const:
+				assert(exp.Val() != nil)
+				x.mode = constant
+				x.typ = exp.typ
+				x.val = exp.val
+			case *TypeName:
+				x.mode = typexpr
+				x.typ = exp.typ
+			case *Var:
+				x.mode = variable
+				x.typ = exp.typ
+			case *Func:
+				x.mode = value
+				x.typ = exp.typ
+			case *Builtin:
+				x.mode = builtin
+				x.typ = exp.typ
+				x.id = exp.id
+			default:
+				unreachable()
+			}
+			x.expr = e
+			return
+		}
+	}
+
+	check.exprOrType(x, e.X)
+	if x.mode == invalid {
+		goto Error
+	}
+
+	obj, index, indirect = LookupFieldOrMethod(x.typ, x.mode == variable, check.pkg, sel)
+	if obj == nil {
+		switch {
+		case index != nil:
+			// TODO(gri) should provide actual type where the conflict happens
+			check.invalidOp(e.Pos(), "ambiguous selector %s", sel)
+		case indirect:
+			check.invalidOp(e.Pos(), "%s is not in method set of %s", sel, x.typ)
+		default:
+			check.invalidOp(e.Pos(), "%s has no field or method %s", x, sel)
+		}
+		goto Error
+	}
+
+	if x.mode == typexpr {
+		// method expression
+		m, _ := obj.(*Func)
+		if m == nil {
+			check.invalidOp(e.Pos(), "%s has no method %s", x, sel)
+			goto Error
+		}
+
+		check.recordSelection(e, MethodExpr, x.typ, m, index, indirect)
+
+		// the receiver type becomes the type of the first function
+		// argument of the method expression's function type
+		var params []*Var
+		sig := m.typ.(*Signature)
+		if sig.params != nil {
+			params = sig.params.vars
+		}
+		x.mode = value
+		x.typ = &Signature{
+			params:   NewTuple(append([]*Var{NewVar(token.NoPos, check.pkg, "", x.typ)}, params...)...),
+			results:  sig.results,
+			variadic: sig.variadic,
+		}
+
+		check.addDeclDep(m)
+
+	} else {
+		// regular selector
+		switch obj := obj.(type) {
+		case *Var:
+			check.recordSelection(e, FieldVal, x.typ, obj, index, indirect)
+			if x.mode == variable || indirect {
+				x.mode = variable
+			} else {
+				x.mode = value
+			}
+			x.typ = obj.typ
+
+		case *Func:
+			// TODO(gri) If we needed to take into account the receiver's
+			// addressability, should we report the type &(x.typ) instead?
+			check.recordSelection(e, MethodVal, x.typ, obj, index, indirect)
+
+			if debug {
+				// Verify that LookupFieldOrMethod and MethodSet.Lookup agree.
+				typ := x.typ
+				if x.mode == variable {
+					// If typ is not an (unnamed) pointer or an interface,
+					// use *typ instead, because the method set of *typ
+					// includes the methods of typ.
+					// Variables are addressable, so we can always take their
+					// address.
+					if _, ok := typ.(*Pointer); !ok && !IsInterface(typ) {
+						typ = &Pointer{base: typ}
+					}
+				}
+				// If we created a synthetic pointer type above, we will throw
+				// away the method set computed here after use.
+				// TODO(gri) Method set computation should probably always compute
+				// both, the value and the pointer receiver method set and represent
+				// them in a single structure.
+				// TODO(gri) Consider also using a method set cache for the lifetime
+				// of checker once we rely on MethodSet lookup instead of individual
+				// lookup.
+				mset := NewMethodSet(typ)
+				if m := mset.Lookup(check.pkg, sel); m == nil || m.obj != obj {
+					check.dump("%s: (%s).%v -> %s", e.Pos(), typ, obj.name, m)
+					check.dump("%s\n", mset)
+					panic("method sets and lookup don't agree")
+				}
+			}
+
+			x.mode = value
+
+			// remove receiver
+			sig := *obj.typ.(*Signature)
+			sig.recv = nil
+			x.typ = &sig
+
+			check.addDeclDep(obj)
+
+		default:
+			unreachable()
+		}
+	}
+
+	// everything went well
+	x.expr = e
+	return
+
+Error:
+	x.mode = invalid
+	x.expr = e
+}
diff --git a/go/types/check.go b/go/types/check.go
new file mode 100644
index 0000000..964d2bd
--- /dev/null
+++ b/go/types/check.go
@@ -0,0 +1,364 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file implements the Check function, which drives type-checking.
+
+package types
+
+import (
+	"go/ast"
+	"go/token"
+
+	"golang.org/x/tools/go/exact"
+)
+
+// debugging/development support
+const (
+	debug = false // leave on during development
+	trace = false // turn on for detailed type resolution traces
+)
+
+// If Strict is set, the type-checker enforces additional
+// rules not specified by the Go 1 spec, but which will
+// catch guaranteed run-time errors if the respective
+// code is executed. In other words, programs passing in
+// Strict mode are Go 1 compliant, but not all Go 1 programs
+// will pass in Strict mode. The additional rules are:
+//
+// - A type assertion x.(T) where T is an interface type
+//   is invalid if any (statically known) method that exists
+//   for both x and T have different signatures.
+//
+const strict = false
+
+// exprInfo stores information about an untyped expression.
+type exprInfo struct {
+	isLhs bool // expression is lhs operand of a shift with delayed type-check
+	mode  operandMode
+	typ   *Basic
+	val   exact.Value // constant value; or nil (if not a constant)
+}
+
+// funcInfo stores the information required for type-checking a function.
+type funcInfo struct {
+	name string    // for debugging/tracing only
+	decl *declInfo // for cycle detection
+	sig  *Signature
+	body *ast.BlockStmt
+}
+
+// A context represents the context within which an object is type-checked.
+type context struct {
+	decl          *declInfo   // package-level declaration whose init expression/function body is checked
+	scope         *Scope      // top-most scope for lookups
+	iota          exact.Value // value of iota in a constant declaration; nil otherwise
+	sig           *Signature  // function signature if inside a function; nil otherwise
+	hasLabel      bool        // set if a function makes use of labels (only ~1% of functions); unused outside functions
+	hasCallOrRecv bool        // set if an expression contains a function call or channel receive operation
+}
+
+// A Checker maintains the state of the type checker.
+// It must be created with NewChecker.
+type Checker struct {
+	// package information
+	// (initialized by NewChecker, valid for the life-time of checker)
+	conf *Config
+	fset *token.FileSet
+	pkg  *Package
+	*Info
+	objMap map[Object]*declInfo // maps package-level object to declaration info
+
+	// information collected during type-checking of a set of package files
+	// (initialized by Files, valid only for the duration of check.Files;
+	// maps and lists are allocated on demand)
+	files            []*ast.File                       // package files
+	unusedDotImports map[*Scope]map[*Package]token.Pos // positions of unused dot-imported packages for each file scope
+
+	firstErr error                 // first error encountered
+	methods  map[string][]*Func    // maps type names to associated methods
+	untyped  map[ast.Expr]exprInfo // map of expressions without final type
+	funcs    []funcInfo            // list of functions to type-check
+	delayed  []func()              // delayed checks requiring fully setup types
+
+	// context within which the current object is type-checked
+	// (valid only for the duration of type-checking a specific object)
+	context
+	pos token.Pos // if valid, identifiers are looked up as if at position pos (used by Eval)
+
+	// debugging
+	indent int // indentation for tracing
+}
+
+// addUnusedImport adds the position of a dot-imported package
+// pkg to the map of dot imports for the given file scope.
+func (check *Checker) addUnusedDotImport(scope *Scope, pkg *Package, pos token.Pos) {
+	mm := check.unusedDotImports
+	if mm == nil {
+		mm = make(map[*Scope]map[*Package]token.Pos)
+		check.unusedDotImports = mm
+	}
+	m := mm[scope]
+	if m == nil {
+		m = make(map[*Package]token.Pos)
+		mm[scope] = m
+	}
+	m[pkg] = pos
+}
+
+// addDeclDep adds the dependency edge (check.decl -> to) if check.decl exists
+func (check *Checker) addDeclDep(to Object) {
+	from := check.decl
+	if from == nil {
+		return // not in a package-level init expression
+	}
+	if _, found := check.objMap[to]; !found {
+		return // to is not a package-level object
+	}
+	from.addDep(to)
+}
+
+func (check *Checker) assocMethod(tname string, meth *Func) {
+	m := check.methods
+	if m == nil {
+		m = make(map[string][]*Func)
+		check.methods = m
+	}
+	m[tname] = append(m[tname], meth)
+}
+
+func (check *Checker) rememberUntyped(e ast.Expr, lhs bool, mode operandMode, typ *Basic, val exact.Value) {
+	m := check.untyped
+	if m == nil {
+		m = make(map[ast.Expr]exprInfo)
+		check.untyped = m
+	}
+	m[e] = exprInfo{lhs, mode, typ, val}
+}
+
+func (check *Checker) later(name string, decl *declInfo, sig *Signature, body *ast.BlockStmt) {
+	check.funcs = append(check.funcs, funcInfo{name, decl, sig, body})
+}
+
+func (check *Checker) delay(f func()) {
+	check.delayed = append(check.delayed, f)
+}
+
+// NewChecker returns a new Checker instance for a given package.
+// Package files may be added incrementally via checker.Files.
+func NewChecker(conf *Config, fset *token.FileSet, pkg *Package, info *Info) *Checker {
+	// make sure we have a configuration
+	if conf == nil {
+		conf = new(Config)
+	}
+
+	// make sure we have a package canonicalization map
+	if conf.Packages == nil {
+		conf.Packages = make(map[string]*Package)
+	}
+
+	// make sure we have an info struct
+	if info == nil {
+		info = new(Info)
+	}
+
+	return &Checker{
+		conf:   conf,
+		fset:   fset,
+		pkg:    pkg,
+		Info:   info,
+		objMap: make(map[Object]*declInfo),
+	}
+}
+
+// initFiles initializes the files-specific portion of checker.
+// The provided files must all belong to the same package.
+func (check *Checker) initFiles(files []*ast.File) {
+	// start with a clean slate (check.Files may be called multiple times)
+	check.files = nil
+	check.unusedDotImports = nil
+
+	check.firstErr = nil
+	check.methods = nil
+	check.untyped = nil
+	check.funcs = nil
+	check.delayed = nil
+
+	// determine package name and collect valid files
+	pkg := check.pkg
+	for _, file := range files {
+		switch name := file.Name.Name; pkg.name {
+		case "":
+			if name != "_" {
+				pkg.name = name
+			} else {
+				check.errorf(file.Name.Pos(), "invalid package name _")
+			}
+			fallthrough
+
+		case name:
+			check.files = append(check.files, file)
+
+		default:
+			check.errorf(file.Package, "package %s; expected %s", name, pkg.name)
+			// ignore this file
+		}
+	}
+}
+
+// A bailout panic is used for early termination.
+type bailout struct{}
+
+func (check *Checker) handleBailout(err *error) {
+	switch p := recover().(type) {
+	case nil, bailout:
+		// normal return or early exit
+		*err = check.firstErr
+	default:
+		// re-panic
+		panic(p)
+	}
+}
+
+// Files checks the provided files as part of the checker's package.
+func (check *Checker) Files(files []*ast.File) (err error) {
+	defer check.handleBailout(&err)
+
+	check.initFiles(files)
+
+	check.collectObjects()
+
+	check.packageObjects(check.resolveOrder())
+
+	check.functionBodies()
+
+	check.initOrder()
+
+	if !check.conf.DisableUnusedImportCheck {
+		check.unusedImports()
+	}
+
+	// perform delayed checks
+	for _, f := range check.delayed {
+		f()
+	}
+
+	check.recordUntyped()
+
+	check.pkg.complete = true
+	return
+}
+
+func (check *Checker) recordUntyped() {
+	if !debug && check.Types == nil {
+		return // nothing to do
+	}
+
+	for x, info := range check.untyped {
+		if debug && isTyped(info.typ) {
+			check.dump("%s: %s (type %s) is typed", x.Pos(), x, info.typ)
+			unreachable()
+		}
+		check.recordTypeAndValue(x, info.mode, info.typ, info.val)
+	}
+}
+
+func (check *Checker) recordTypeAndValue(x ast.Expr, mode operandMode, typ Type, val exact.Value) {
+	assert(x != nil)
+	assert(typ != nil)
+	if mode == invalid {
+		return // omit
+	}
+	assert(typ != nil)
+	if mode == constant {
+		assert(val != nil)
+		assert(typ == Typ[Invalid] || isConstType(typ))
+	}
+	if m := check.Types; m != nil {
+		m[x] = TypeAndValue{mode, typ, val}
+	}
+}
+
+func (check *Checker) recordBuiltinType(f ast.Expr, sig *Signature) {
+	// f must be a (possibly parenthesized) identifier denoting a built-in
+	// (built-ins in package unsafe always produce a constant result and
+	// we don't record their signatures, so we don't see qualified idents
+	// here): record the signature for f and possible children.
+	for {
+		check.recordTypeAndValue(f, builtin, sig, nil)
+		switch p := f.(type) {
+		case *ast.Ident:
+			return // we're done
+		case *ast.ParenExpr:
+			f = p.X
+		default:
+			unreachable()
+		}
+	}
+}
+
+func (check *Checker) recordCommaOkTypes(x ast.Expr, a [2]Type) {
+	assert(x != nil)
+	if a[0] == nil || a[1] == nil {
+		return
+	}
+	assert(isTyped(a[0]) && isTyped(a[1]) && isBoolean(a[1]))
+	if m := check.Types; m != nil {
+		for {
+			tv := m[x]
+			assert(tv.Type != nil) // should have been recorded already
+			pos := x.Pos()
+			tv.Type = NewTuple(
+				NewVar(pos, check.pkg, "", a[0]),
+				NewVar(pos, check.pkg, "", a[1]),
+			)
+			m[x] = tv
+			// if x is a parenthesized expression (p.X), update p.X
+			p, _ := x.(*ast.ParenExpr)
+			if p == nil {
+				break
+			}
+			x = p.X
+		}
+	}
+}
+
+func (check *Checker) recordDef(id *ast.Ident, obj Object) {
+	assert(id != nil)
+	if m := check.Defs; m != nil {
+		m[id] = obj
+	}
+}
+
+func (check *Checker) recordUse(id *ast.Ident, obj Object) {
+	assert(id != nil)
+	assert(obj != nil)
+	if m := check.Uses; m != nil {
+		m[id] = obj
+	}
+}
+
+func (check *Checker) recordImplicit(node ast.Node, obj Object) {
+	assert(node != nil)
+	assert(obj != nil)
+	if m := check.Implicits; m != nil {
+		m[node] = obj
+	}
+}
+
+func (check *Checker) recordSelection(x *ast.SelectorExpr, kind SelectionKind, recv Type, obj Object, index []int, indirect bool) {
+	assert(obj != nil && (recv == nil || len(index) > 0))
+	check.recordUse(x.Sel, obj)
+	// TODO(gri) Should we also call recordTypeAndValue?
+	if m := check.Selections; m != nil {
+		m[x] = &Selection{kind, recv, obj, index, indirect}
+	}
+}
+
+func (check *Checker) recordScope(node ast.Node, scope *Scope) {
+	assert(node != nil)
+	assert(scope != nil)
+	if m := check.Scopes; m != nil {
+		m[node] = scope
+	}
+}
diff --git a/go/types/check_test.go b/go/types/check_test.go
new file mode 100644
index 0000000..fd4dadb
--- /dev/null
+++ b/go/types/check_test.go
@@ -0,0 +1,303 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file implements a typechecker test harness. The packages specified
+// in tests are typechecked. Error messages reported by the typechecker are
+// compared against the error messages expected in the test files.
+//
+// Expected errors are indicated in the test files by putting a comment
+// of the form /* ERROR "rx" */ immediately following an offending token.
+// The harness will verify that an error matching the regular expression
+// rx is reported at that source position. Consecutive comments may be
+// used to indicate multiple errors for the same token position.
+//
+// For instance, the following test file indicates that a "not declared"
+// error should be reported for the undeclared variable x:
+//
+//	package p
+//	func f() {
+//		_ = x /* ERROR "not declared" */ + 1
+//	}
+
+package types_test
+
+import (
+	"flag"
+	"go/ast"
+	"go/parser"
+	"go/scanner"
+	"go/token"
+	"io/ioutil"
+	"regexp"
+	"runtime"
+	"strings"
+	"testing"
+
+	_ "golang.org/x/tools/go/gcimporter"
+	. "golang.org/x/tools/go/types"
+)
+
+var (
+	listErrors = flag.Bool("list", false, "list errors")
+	testFiles  = flag.String("files", "", "space-separated list of test files")
+)
+
+// The test filenames do not end in .go so that they are invisible
+// to gofmt since they contain comments that must not change their
+// positions relative to surrounding tokens.
+
+// Each tests entry is list of files belonging to the same package.
+var tests = []struct {
+	files string      // blank-separated list of file names
+	cond  func() bool // condition under which the test should be run; nil means always
+}{
+	{"testdata/errors.src", nil},
+	{"testdata/importdecl0a.src testdata/importdecl0b.src", nil},
+	{"testdata/importdecl1a.src testdata/importdecl1b.src", nil},
+	{"testdata/cycles.src", nil},
+	{"testdata/cycles1.src", nil},
+	{"testdata/cycles2.src", nil},
+	{"testdata/cycles3.src", nil},
+	{"testdata/cycles4.src", nil},
+	{"testdata/init0.src", nil},
+	{"testdata/init1.src", nil},
+	{"testdata/init2.src", nil},
+	{"testdata/decls0.src", nil},
+	{"testdata/decls1.src", nil},
+	{"testdata/decls2a.src testdata/decls2b.src", nil},
+	{"testdata/decls3.src", nil},
+	{"testdata/const0.src", nil},
+	{"testdata/const1.src", nil},
+	{"testdata/constdecl.src", notGo1_4}, // Go 1.4 parser doesn't report certain errors
+	{"testdata/vardecl.src", notGo1_4},   // Go 1.4 parser doesn't report certain errors
+	{"testdata/expr0.src", nil},
+	{"testdata/expr1.src", nil},
+	{"testdata/expr2.src", nil},
+	{"testdata/expr3.src", notGo1_4}, // Go 1.4 parser doesn't permit omitting key type in map literals
+	{"testdata/methodsets.src", nil},
+	{"testdata/shifts.src", nil},
+	{"testdata/builtins.src", nil},
+	{"testdata/conversions.src", nil},
+	{"testdata/stmt0.src", nil},
+	{"testdata/stmt1.src", nil},
+	{"testdata/gotos.src", nil},
+	{"testdata/labels.src", nil},
+	{"testdata/issues.src", nil},
+	{"testdata/blank.src", nil},
+}
+
+func notGo1_4() bool {
+	return !strings.HasPrefix(runtime.Version(), "go1.4")
+}
+
+var fset = token.NewFileSet()
+
+// Positioned errors are of the form filename:line:column: message .
+var posMsgRx = regexp.MustCompile(`^(.*:[0-9]+:[0-9]+): *(.*)`)
+
+// splitError splits an error's error message into a position string
+// and the actual error message. If there's no position information,
+// pos is the empty string, and msg is the entire error message.
+//
+func splitError(err error) (pos, msg string) {
+	msg = err.Error()
+	if m := posMsgRx.FindStringSubmatch(msg); len(m) == 3 {
+		pos = m[1]
+		msg = m[2]
+	}
+	return
+}
+
+func parseFiles(t *testing.T, filenames string) ([]*ast.File, []error) {
+	var files []*ast.File
+	var errlist []error
+	for _, filename := range strings.Split(filenames, " ") {
+		file, err := parser.ParseFile(fset, filename, nil, parser.AllErrors)
+		if file == nil {
+			t.Fatalf("%s: %s", filename, err)
+		}
+		files = append(files, file)
+		if err != nil {
+			if list, _ := err.(scanner.ErrorList); len(list) > 0 {
+				for _, err := range list {
+					errlist = append(errlist, err)
+				}
+			} else {
+				errlist = append(errlist, err)
+			}
+		}
+	}
+	return files, errlist
+}
+
+// ERROR comments must start with text `ERROR "rx"` or `ERROR rx` where
+// rx is a regular expression that matches the expected error message.
+// Space around "rx" or rx is ignored. Use the form `ERROR HERE "rx"`
+// for error messages that are located immediately after rather than
+// at a token's position.
+//
+var errRx = regexp.MustCompile(`^ *ERROR *(HERE)? *"?([^"]*)"?`)
+
+// errMap collects the regular expressions of ERROR comments found
+// in files and returns them as a map of error positions to error messages.
+//
+func errMap(t *testing.T, testname string, files []*ast.File) map[string][]string {
+	// map of position strings to lists of error message patterns
+	errmap := make(map[string][]string)
+
+	for _, file := range files {
+		filename := fset.Position(file.Package).Filename
+		src, err := ioutil.ReadFile(filename)
+		if err != nil {
+			t.Fatalf("%s: could not read %s", testname, filename)
+		}
+
+		var s scanner.Scanner
+		s.Init(fset.AddFile(filename, -1, len(src)), src, nil, scanner.ScanComments)
+		var prev token.Pos // position of last non-comment, non-semicolon token
+		var here token.Pos // position immediately after the token at position prev
+
+	scanFile:
+		for {
+			pos, tok, lit := s.Scan()
+			switch tok {
+			case token.EOF:
+				break scanFile
+			case token.COMMENT:
+				if lit[1] == '*' {
+					lit = lit[:len(lit)-2] // strip trailing */
+				}
+				if s := errRx.FindStringSubmatch(lit[2:]); len(s) == 3 {
+					pos := prev
+					if s[1] == "HERE" {
+						pos = here
+					}
+					p := fset.Position(pos).String()
+					errmap[p] = append(errmap[p], strings.TrimSpace(s[2]))
+				}
+			case token.SEMICOLON:
+				// ignore automatically inserted semicolon
+				if lit == "\n" {
+					continue scanFile
+				}
+				fallthrough
+			default:
+				prev = pos
+				var l int // token length
+				if tok.IsLiteral() {
+					l = len(lit)
+				} else {
+					l = len(tok.String())
+				}
+				here = prev + token.Pos(l)
+			}
+		}
+	}
+
+	return errmap
+}
+
+func eliminate(t *testing.T, errmap map[string][]string, errlist []error) {
+	for _, err := range errlist {
+		pos, gotMsg := splitError(err)
+		list := errmap[pos]
+		index := -1 // list index of matching message, if any
+		// we expect one of the messages in list to match the error at pos
+		for i, wantRx := range list {
+			rx, err := regexp.Compile(wantRx)
+			if err != nil {
+				t.Errorf("%s: %v", pos, err)
+				continue
+			}
+			if rx.MatchString(gotMsg) {
+				index = i
+				break
+			}
+		}
+		if index >= 0 {
+			// eliminate from list
+			if n := len(list) - 1; n > 0 {
+				// not the last entry - swap in last element and shorten list by 1
+				list[index] = list[n]
+				errmap[pos] = list[:n]
+			} else {
+				// last entry - remove list from map
+				delete(errmap, pos)
+			}
+		} else {
+			t.Errorf("%s: no error expected: %q", pos, gotMsg)
+		}
+	}
+}
+
+func checkFiles(t *testing.T, filenames string) {
+	// parse files and collect parser errors
+	files, errlist := parseFiles(t, filenames)
+
+	pkgName := "<no package>"
+	if len(files) > 0 {
+		pkgName = files[0].Name.Name
+	}
+
+	if *listErrors && len(errlist) > 0 {
+		t.Errorf("--- %s:", pkgName)
+		for _, err := range errlist {
+			t.Error(err)
+		}
+	}
+
+	// typecheck and collect typechecker errors
+	var conf Config
+	conf.Error = func(err error) {
+		if *listErrors {
+			t.Error(err)
+			return
+		}
+		// Ignore secondary error messages starting with "\t";
+		// they are clarifying messages for a primary error.
+		if !strings.Contains(err.Error(), ": \t") {
+			errlist = append(errlist, err)
+		}
+	}
+	conf.Check(pkgName, fset, files, nil)
+
+	if *listErrors {
+		return
+	}
+
+	// match and eliminate errors;
+	// we are expecting the following errors
+	errmap := errMap(t, pkgName, files)
+	eliminate(t, errmap, errlist)
+
+	// there should be no expected errors left
+	if len(errmap) > 0 {
+		t.Errorf("--- %s: %d source positions with expected (but not reported) errors:", pkgName, len(errmap))
+		for pos, list := range errmap {
+			for _, rx := range list {
+				t.Errorf("%s: %q", pos, rx)
+			}
+		}
+	}
+}
+
+func TestCheck(t *testing.T) {
+	skipSpecialPlatforms(t)
+
+	// Declare builtins for testing.
+	DefPredeclaredTestFuncs()
+
+	// If explicit test files are specified, only check those.
+	if *testFiles != "" {
+		checkFiles(t, *testFiles)
+		return
+	}
+
+	// Otherwise, run all the tests.
+	for _, test := range tests {
+		if test.cond == nil || test.cond() {
+			checkFiles(t, test.files)
+		}
+	}
+}
diff --git a/go/types/conversions.go b/go/types/conversions.go
new file mode 100644
index 0000000..6e279ca
--- /dev/null
+++ b/go/types/conversions.go
@@ -0,0 +1,146 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file implements typechecking of conversions.
+
+package types
+
+import "golang.org/x/tools/go/exact"
+
+// Conversion type-checks the conversion T(x).
+// The result is in x.
+func (check *Checker) conversion(x *operand, T Type) {
+	constArg := x.mode == constant
+
+	var ok bool
+	switch {
+	case constArg && isConstType(T):
+		// constant conversion
+		switch t := T.Underlying().(*Basic); {
+		case representableConst(x.val, check.conf, t.kind, &x.val):
+			ok = true
+		case isInteger(x.typ) && isString(t):
+			codepoint := int64(-1)
+			if i, ok := exact.Int64Val(x.val); ok {
+				codepoint = i
+			}
+			// If codepoint < 0 the absolute value is too large (or unknown) for
+			// conversion. This is the same as converting any other out-of-range
+			// value - let string(codepoint) do the work.
+			x.val = exact.MakeString(string(codepoint))
+			ok = true
+		}
+	case x.convertibleTo(check.conf, T):
+		// non-constant conversion
+		x.mode = value
+		ok = true
+	}
+
+	if !ok {
+		check.errorf(x.pos(), "cannot convert %s to %s", x, T)
+		x.mode = invalid
+		return
+	}
+
+	// The conversion argument types are final. For untyped values the
+	// conversion provides the type, per the spec: "A constant may be
+	// given a type explicitly by a constant declaration or conversion,...".
+	final := x.typ
+	if isUntyped(x.typ) {
+		final = T
+		// - For conversions to interfaces, use the argument's default type.
+		// - For conversions of untyped constants to non-constant types, also
+		//   use the default type (e.g., []byte("foo") should report string
+		//   not []byte as type for the constant "foo").
+		// - Keep untyped nil for untyped nil arguments.
+		if IsInterface(T) || constArg && !isConstType(T) {
+			final = defaultType(x.typ)
+		}
+		check.updateExprType(x.expr, final, true)
+	}
+
+	x.typ = T
+}
+
+func (x *operand) convertibleTo(conf *Config, T Type) bool {
+	// "x is assignable to T"
+	if x.assignableTo(conf, T) {
+		return true
+	}
+
+	// "x's type and T have identical underlying types"
+	V := x.typ
+	Vu := V.Underlying()
+	Tu := T.Underlying()
+	if Identical(Vu, Tu) {
+		return true
+	}
+
+	// "x's type and T are unnamed pointer types and their pointer base types have identical underlying types"
+	if V, ok := V.(*Pointer); ok {
+		if T, ok := T.(*Pointer); ok {
+			if Identical(V.base.Underlying(), T.base.Underlying()) {
+				return true
+			}
+		}
+	}
+
+	// "x's type and T are both integer or floating point types"
+	if (isInteger(V) || isFloat(V)) && (isInteger(T) || isFloat(T)) {
+		return true
+	}
+
+	// "x's type and T are both complex types"
+	if isComplex(V) && isComplex(T) {
+		return true
+	}
+
+	// "x is an integer or a slice of bytes or runes and T is a string type"
+	if (isInteger(V) || isBytesOrRunes(Vu)) && isString(T) {
+		return true
+	}
+
+	// "x is a string and T is a slice of bytes or runes"
+	if isString(V) && isBytesOrRunes(Tu) {
+		return true
+	}
+
+	// package unsafe:
+	// "any pointer or value of underlying type uintptr can be converted into a unsafe.Pointer"
+	if (isPointer(Vu) || isUintptr(Vu)) && isUnsafePointer(T) {
+		return true
+	}
+	// "and vice versa"
+	if isUnsafePointer(V) && (isPointer(Tu) || isUintptr(Tu)) {
+		return true
+	}
+
+	return false
+}
+
+func isUintptr(typ Type) bool {
+	t, ok := typ.Underlying().(*Basic)
+	return ok && t.kind == Uintptr
+}
+
+func isUnsafePointer(typ Type) bool {
+	// TODO(gri): Is this (typ.Underlying() instead of just typ) correct?
+	//            The spec does not say so, but gc claims it is. See also
+	//            issue 6326.
+	t, ok := typ.Underlying().(*Basic)
+	return ok && t.kind == UnsafePointer
+}
+
+func isPointer(typ Type) bool {
+	_, ok := typ.Underlying().(*Pointer)
+	return ok
+}
+
+func isBytesOrRunes(typ Type) bool {
+	if s, ok := typ.(*Slice); ok {
+		t, ok := s.elem.Underlying().(*Basic)
+		return ok && (t.kind == Byte || t.kind == Rune)
+	}
+	return false
+}
diff --git a/go/types/decl.go b/go/types/decl.go
new file mode 100644
index 0000000..9eba85c
--- /dev/null
+++ b/go/types/decl.go
@@ -0,0 +1,431 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package types
+
+import (
+	"go/ast"
+	"go/token"
+
+	"golang.org/x/tools/go/exact"
+)
+
+func (check *Checker) reportAltDecl(obj Object) {
+	if pos := obj.Pos(); pos.IsValid() {
+		// We use "other" rather than "previous" here because
+		// the first declaration seen may not be textually
+		// earlier in the source.
+		check.errorf(pos, "\tother declaration of %s", obj.Name()) // secondary error, \t indented
+	}
+}
+
+func (check *Checker) declare(scope *Scope, id *ast.Ident, obj Object, pos token.Pos) {
+	// spec: "The blank identifier, represented by the underscore
+	// character _, may be used in a declaration like any other
+	// identifier but the declaration does not introduce a new
+	// binding."
+	if obj.Name() != "_" {
+		if alt := scope.Insert(obj); alt != nil {
+			check.errorf(obj.Pos(), "%s redeclared in this block", obj.Name())
+			check.reportAltDecl(alt)
+			return
+		}
+		obj.setScopePos(pos)
+	}
+	if id != nil {
+		check.recordDef(id, obj)
+	}
+}
+
+// objDecl type-checks the declaration of obj in its respective (file) context.
+// See check.typ for the details on def and path.
+func (check *Checker) objDecl(obj Object, def *Named, path []*TypeName) {
+	if obj.Type() != nil {
+		return // already checked - nothing to do
+	}
+
+	if trace {
+		check.trace(obj.Pos(), "-- declaring %s", obj.Name())
+		check.indent++
+		defer func() {
+			check.indent--
+			check.trace(obj.Pos(), "=> %s", obj)
+		}()
+	}
+
+	d := check.objMap[obj]
+	if d == nil {
+		check.dump("%s: %s should have been declared", obj.Pos(), obj.Name())
+		unreachable()
+	}
+
+	// save/restore current context and setup object context
+	defer func(ctxt context) {
+		check.context = ctxt
+	}(check.context)
+	check.context = context{
+		scope: d.file,
+	}
+
+	// Const and var declarations must not have initialization
+	// cycles. We track them by remembering the current declaration
+	// in check.decl. Initialization expressions depending on other
+	// consts, vars, or functions, add dependencies to the current
+	// check.decl.
+	switch obj := obj.(type) {
+	case *Const:
+		check.decl = d // new package-level const decl
+		check.constDecl(obj, d.typ, d.init)
+	case *Var:
+		check.decl = d // new package-level var decl
+		check.varDecl(obj, d.lhs, d.typ, d.init)
+	case *TypeName:
+		// invalid recursive types are detected via path
+		check.typeDecl(obj, d.typ, def, path)
+	case *Func:
+		// functions may be recursive - no need to track dependencies
+		check.funcDecl(obj, d)
+	default:
+		unreachable()
+	}
+}
+
+func (check *Checker) constDecl(obj *Const, typ, init ast.Expr) {
+	assert(obj.typ == nil)
+
+	if obj.visited {
+		obj.typ = Typ[Invalid]
+		return
+	}
+	obj.visited = true
+
+	// use the correct value of iota
+	assert(check.iota == nil)
+	check.iota = obj.val
+	defer func() { check.iota = nil }()
+
+	// provide valid constant value under all circumstances
+	obj.val = exact.MakeUnknown()
+
+	// determine type, if any
+	if typ != nil {
+		t := check.typ(typ)
+		if !isConstType(t) {
+			check.errorf(typ.Pos(), "invalid constant type %s", t)
+			obj.typ = Typ[Invalid]
+			return
+		}
+		obj.typ = t
+	}
+
+	// check initialization
+	var x operand
+	if init != nil {
+		check.expr(&x, init)
+	}
+	check.initConst(obj, &x)
+}
+
+func (check *Checker) varDecl(obj *Var, lhs []*Var, typ, init ast.Expr) {
+	assert(obj.typ == nil)
+
+	if obj.visited {
+		obj.typ = Typ[Invalid]
+		return
+	}
+	obj.visited = true
+
+	// var declarations cannot use iota
+	assert(check.iota == nil)
+
+	// determine type, if any
+	if typ != nil {
+		obj.typ = check.typ(typ)
+	}
+
+	// check initialization
+	if init == nil {
+		if typ == nil {
+			// error reported before by arityMatch
+			obj.typ = Typ[Invalid]
+		}
+		return
+	}
+
+	if lhs == nil || len(lhs) == 1 {
+		assert(lhs == nil || lhs[0] == obj)
+		var x operand
+		check.expr(&x, init)
+		check.initVar(obj, &x, false)
+		return
+	}
+
+	if debug {
+		// obj must be one of lhs
+		found := false
+		for _, lhs := range lhs {
+			if obj == lhs {
+				found = true
+				break
+			}
+		}
+		if !found {
+			panic("inconsistent lhs")
+		}
+	}
+	check.initVars(lhs, []ast.Expr{init}, token.NoPos)
+}
+
+// underlying returns the underlying type of typ; possibly by following
+// forward chains of named types. Such chains only exist while named types
+// are incomplete.
+func underlying(typ Type) Type {
+	for {
+		n, _ := typ.(*Named)
+		if n == nil {
+			break
+		}
+		typ = n.underlying
+	}
+	return typ
+}
+
+func (n *Named) setUnderlying(typ Type) {
+	if n != nil {
+		n.underlying = typ
+	}
+}
+
+func (check *Checker) typeDecl(obj *TypeName, typ ast.Expr, def *Named, path []*TypeName) {
+	assert(obj.typ == nil)
+
+	// type declarations cannot use iota
+	assert(check.iota == nil)
+
+	named := &Named{obj: obj}
+	def.setUnderlying(named)
+	obj.typ = named // make sure recursive type declarations terminate
+
+	// determine underlying type of named
+	check.typExpr(typ, named, append(path, obj))
+
+	// The underlying type of named may be itself a named type that is
+	// incomplete:
+	//
+	//	type (
+	//		A B
+	//		B *C
+	//		C A
+	//	)
+	//
+	// The type of C is the (named) type of A which is incomplete,
+	// and which has as its underlying type the named type B.
+	// Determine the (final, unnamed) underlying type by resolving
+	// any forward chain (they always end in an unnamed type).
+	named.underlying = underlying(named.underlying)
+
+	// check and add associated methods
+	// TODO(gri) It's easy to create pathological cases where the
+	// current approach is incorrect: In general we need to know
+	// and add all methods _before_ type-checking the type.
+	// See http://play.golang.org/p/WMpE0q2wK8
+	check.addMethodDecls(obj)
+}
+
+func (check *Checker) addMethodDecls(obj *TypeName) {
+	// get associated methods
+	methods := check.methods[obj.name]
+	if len(methods) == 0 {
+		return // no methods
+	}
+	delete(check.methods, obj.name)
+
+	// use an objset to check for name conflicts
+	var mset objset
+
+	// spec: "If the base type is a struct type, the non-blank method
+	// and field names must be distinct."
+	base := obj.typ.(*Named)
+	if t, _ := base.underlying.(*Struct); t != nil {
+		for _, fld := range t.fields {
+			if fld.name != "_" {
+				assert(mset.insert(fld) == nil)
+			}
+		}
+	}
+
+	// Checker.Files may be called multiple times; additional package files
+	// may add methods to already type-checked types. Add pre-existing methods
+	// so that we can detect redeclarations.
+	for _, m := range base.methods {
+		assert(m.name != "_")
+		assert(mset.insert(m) == nil)
+	}
+
+	// type-check methods
+	for _, m := range methods {
+		// spec: "For a base type, the non-blank names of methods bound
+		// to it must be unique."
+		if m.name != "_" {
+			if alt := mset.insert(m); alt != nil {
+				switch alt.(type) {
+				case *Var:
+					check.errorf(m.pos, "field and method with the same name %s", m.name)
+				case *Func:
+					check.errorf(m.pos, "method %s already declared for %s", m.name, base)
+				default:
+					unreachable()
+				}
+				check.reportAltDecl(alt)
+				continue
+			}
+		}
+		check.objDecl(m, nil, nil)
+		// methods with blank _ names cannot be found - don't keep them
+		if m.name != "_" {
+			base.methods = append(base.methods, m)
+		}
+	}
+}
+
+func (check *Checker) funcDecl(obj *Func, decl *declInfo) {
+	assert(obj.typ == nil)
+
+	// func declarations cannot use iota
+	assert(check.iota == nil)
+
+	sig := new(Signature)
+	obj.typ = sig // guard against cycles
+	fdecl := decl.fdecl
+	check.funcType(sig, fdecl.Recv, fdecl.Type)
+	if sig.recv == nil && obj.name == "init" && (sig.params.Len() > 0 || sig.results.Len() > 0) {
+		check.errorf(fdecl.Pos(), "func init must have no arguments and no return values")
+		// ok to continue
+	}
+
+	// function body must be type-checked after global declarations
+	// (functions implemented elsewhere have no body)
+	if !check.conf.IgnoreFuncBodies && fdecl.Body != nil {
+		check.later(obj.name, decl, sig, fdecl.Body)
+	}
+}
+
+func (check *Checker) declStmt(decl ast.Decl) {
+	pkg := check.pkg
+
+	switch d := decl.(type) {
+	case *ast.BadDecl:
+		// ignore
+
+	case *ast.GenDecl:
+		var last *ast.ValueSpec // last ValueSpec with type or init exprs seen
+		for iota, spec := range d.Specs {
+			switch s := spec.(type) {
+			case *ast.ValueSpec:
+				switch d.Tok {
+				case token.CONST:
+					// determine which init exprs to use
+					switch {
+					case s.Type != nil || len(s.Values) > 0:
+						last = s
+					case last == nil:
+						last = new(ast.ValueSpec) // make sure last exists
+					}
+
+					// declare all constants
+					lhs := make([]*Const, len(s.Names))
+					for i, name := range s.Names {
+						obj := NewConst(name.Pos(), pkg, name.Name, nil, exact.MakeInt64(int64(iota)))
+						lhs[i] = obj
+
+						var init ast.Expr
+						if i < len(last.Values) {
+							init = last.Values[i]
+						}
+
+						check.constDecl(obj, last.Type, init)
+					}
+
+					check.arityMatch(s, last)
+
+					// spec: "The scope of a constant or variable identifier declared
+					// inside a function begins at the end of the ConstSpec or VarSpec
+					// (ShortVarDecl for short variable declarations) and ends at the
+					// end of the innermost containing block."
+					scopePos := s.End()
+					for i, name := range s.Names {
+						check.declare(check.scope, name, lhs[i], scopePos)
+					}
+
+				case token.VAR:
+					lhs0 := make([]*Var, len(s.Names))
+					for i, name := range s.Names {
+						lhs0[i] = NewVar(name.Pos(), pkg, name.Name, nil)
+					}
+
+					// initialize all variables
+					for i, obj := range lhs0 {
+						var lhs []*Var
+						var init ast.Expr
+						switch len(s.Values) {
+						case len(s.Names):
+							// lhs and rhs match
+							init = s.Values[i]
+						case 1:
+							// rhs is expected to be a multi-valued expression
+							lhs = lhs0
+							init = s.Values[0]
+						default:
+							if i < len(s.Values) {
+								init = s.Values[i]
+							}
+						}
+						check.varDecl(obj, lhs, s.Type, init)
+						if len(s.Values) == 1 {
+							// If we have a single lhs variable we are done either way.
+							// If we have a single rhs expression, it must be a multi-
+							// valued expression, in which case handling the first lhs
+							// variable will cause all lhs variables to have a type
+							// assigned, and we are done as well.
+							if debug {
+								for _, obj := range lhs0 {
+									assert(obj.typ != nil)
+								}
+							}
+							break
+						}
+					}
+
+					check.arityMatch(s, nil)
+
+					// declare all variables
+					// (only at this point are the variable scopes (parents) set)
+					scopePos := s.End() // see constant declarations
+					for i, name := range s.Names {
+						// see constant declarations
+						check.declare(check.scope, name, lhs0[i], scopePos)
+					}
+
+				default:
+					check.invalidAST(s.Pos(), "invalid token %s", d.Tok)
+				}
+
+			case *ast.TypeSpec:
+				obj := NewTypeName(s.Name.Pos(), pkg, s.Name.Name, nil)
+				// spec: "The scope of a type identifier declared inside a function
+				// begins at the identifier in the TypeSpec and ends at the end of
+				// the innermost containing block."
+				scopePos := s.Name.Pos()
+				check.declare(check.scope, s.Name, obj, scopePos)
+				check.typeDecl(obj, s.Type, nil, nil)
+
+			default:
+				check.invalidAST(s.Pos(), "const, type, or var declaration expected")
+			}
+		}
+
+	default:
+		check.invalidAST(d.Pos(), "unknown ast.Decl node %T", d)
+	}
+}
diff --git a/go/types/errors.go b/go/types/errors.go
new file mode 100644
index 0000000..0c0049b
--- /dev/null
+++ b/go/types/errors.go
@@ -0,0 +1,103 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file implements various error reporters.
+
+package types
+
+import (
+	"fmt"
+	"go/ast"
+	"go/token"
+	"strings"
+)
+
+func assert(p bool) {
+	if !p {
+		panic("assertion failed")
+	}
+}
+
+func unreachable() {
+	panic("unreachable")
+}
+
+func (check *Checker) qualifier(pkg *Package) string {
+	if pkg != check.pkg {
+		return pkg.path
+	}
+	return ""
+}
+
+func (check *Checker) sprintf(format string, args ...interface{}) string {
+	for i, arg := range args {
+		switch a := arg.(type) {
+		case nil:
+			arg = "<nil>"
+		case operand:
+			panic("internal error: should always pass *operand")
+		case *operand:
+			arg = operandString(a, check.qualifier)
+		case token.Pos:
+			arg = check.fset.Position(a).String()
+		case ast.Expr:
+			arg = ExprString(a)
+		case Object:
+			arg = ObjectString(a, check.qualifier)
+		case Type:
+			arg = TypeString(a, check.qualifier)
+		}
+		args[i] = arg
+	}
+	return fmt.Sprintf(format, args...)
+}
+
+func (check *Checker) trace(pos token.Pos, format string, args ...interface{}) {
+	fmt.Printf("%s:\t%s%s\n",
+		check.fset.Position(pos),
+		strings.Repeat(".  ", check.indent),
+		check.sprintf(format, args...),
+	)
+}
+
+// dump is only needed for debugging
+func (check *Checker) dump(format string, args ...interface{}) {
+	fmt.Println(check.sprintf(format, args...))
+}
+
+func (check *Checker) err(pos token.Pos, msg string, soft bool) {
+	err := Error{check.fset, pos, msg, soft}
+	if check.firstErr == nil {
+		check.firstErr = err
+	}
+	f := check.conf.Error
+	if f == nil {
+		panic(bailout{}) // report only first error
+	}
+	f(err)
+}
+
+func (check *Checker) error(pos token.Pos, msg string) {
+	check.err(pos, msg, false)
+}
+
+func (check *Checker) errorf(pos token.Pos, format string, args ...interface{}) {
+	check.err(pos, check.sprintf(format, args...), false)
+}
+
+func (check *Checker) softErrorf(pos token.Pos, format string, args ...interface{}) {
+	check.err(pos, check.sprintf(format, args...), true)
+}
+
+func (check *Checker) invalidAST(pos token.Pos, format string, args ...interface{}) {
+	check.errorf(pos, "invalid AST: "+format, args...)
+}
+
+func (check *Checker) invalidArg(pos token.Pos, format string, args ...interface{}) {
+	check.errorf(pos, "invalid argument: "+format, args...)
+}
+
+func (check *Checker) invalidOp(pos token.Pos, format string, args ...interface{}) {
+	check.errorf(pos, "invalid operation: "+format, args...)
+}
diff --git a/go/types/eval.go b/go/types/eval.go
new file mode 100644
index 0000000..c09f2a3
--- /dev/null
+++ b/go/types/eval.go
@@ -0,0 +1,87 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package types
+
+import (
+	"fmt"
+	"go/parser"
+	"go/token"
+)
+
+// Eval returns the type and, if constant, the value for the
+// expression expr, evaluated at position pos of package pkg,
+// which must have been derived from type-checking an AST with
+// complete position information relative to the provided file
+// set.
+//
+// If the expression contains function literals, their bodies
+// are ignored (i.e., the bodies are not type-checked).
+//
+// If pkg == nil, the Universe scope is used and the provided
+// position pos is ignored. If pkg != nil, and pos is invalid,
+// the package scope is used. Otherwise, pos must belong to the
+// package.
+//
+// An error is returned if pos is not within the package or
+// if the node cannot be evaluated.
+//
+// Note: Eval should not be used instead of running Check to compute
+// types and values, but in addition to Check. Eval will re-evaluate
+// its argument each time, and it also does not know about the context
+// in which an expression is used (e.g., an assignment). Thus, top-
+// level untyped constants will return an untyped type rather then the
+// respective context-specific type.
+//
+func Eval(fset *token.FileSet, pkg *Package, pos token.Pos, expr string) (tv TypeAndValue, err error) {
+	// determine scope
+	var scope *Scope
+	if pkg == nil {
+		scope = Universe
+		pos = token.NoPos
+	} else if !pos.IsValid() {
+		scope = pkg.scope
+	} else {
+		// The package scope extent (position information) may be
+		// incorrect (files spread accross a wide range of fset
+		// positions) - ignore it and just consider its children
+		// (file scopes).
+		for _, fscope := range pkg.scope.children {
+			if scope = fscope.Innermost(pos); scope != nil {
+				break
+			}
+		}
+		if scope == nil || debug {
+			s := scope
+			for s != nil && s != pkg.scope {
+				s = s.parent
+			}
+			// s == nil || s == pkg.scope
+			if s == nil {
+				return TypeAndValue{}, fmt.Errorf("no position %s found in package %s", fset.Position(pos), pkg.name)
+			}
+		}
+	}
+
+	// parse expressions
+	// BUG(gri) In case of type-checking errors below, the type checker
+	//          doesn't have the correct file set for expr. The correct
+	//          solution requires a ParseExpr that uses the incoming
+	//          file set fset.
+	node, err := parser.ParseExpr(expr)
+	if err != nil {
+		return TypeAndValue{}, err
+	}
+
+	// initialize checker
+	check := NewChecker(nil, fset, pkg, nil)
+	check.scope = scope
+	check.pos = pos
+	defer check.handleBailout(&err)
+
+	// evaluate node
+	var x operand
+	check.rawExpr(&x, node, nil)
+	return TypeAndValue{x.mode, x.typ, x.val}, err
+}
diff --git a/go/types/eval_test.go b/go/types/eval_test.go
new file mode 100644
index 0000000..b68b244
--- /dev/null
+++ b/go/types/eval_test.go
@@ -0,0 +1,186 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file contains tests for Eval.
+
+package types_test
+
+import (
+	"go/ast"
+	"go/parser"
+	"go/token"
+	"strings"
+	"testing"
+
+	_ "golang.org/x/tools/go/gcimporter"
+	. "golang.org/x/tools/go/types"
+)
+
+func testEval(t *testing.T, fset *token.FileSet, pkg *Package, pos token.Pos, expr string, typ Type, typStr, valStr string) {
+	gotTv, err := Eval(fset, pkg, pos, expr)
+	if err != nil {
+		t.Errorf("Eval(%q) failed: %s", expr, err)
+		return
+	}
+	if gotTv.Type == nil {
+		t.Errorf("Eval(%q) got nil type but no error", expr)
+		return
+	}
+
+	// compare types
+	if typ != nil {
+		// we have a type, check identity
+		if !Identical(gotTv.Type, typ) {
+			t.Errorf("Eval(%q) got type %s, want %s", expr, gotTv.Type, typ)
+			return
+		}
+	} else {
+		// we have a string, compare type string
+		gotStr := gotTv.Type.String()
+		if gotStr != typStr {
+			t.Errorf("Eval(%q) got type %s, want %s", expr, gotStr, typStr)
+			return
+		}
+	}
+
+	// compare values
+	gotStr := ""
+	if gotTv.Value != nil {
+		gotStr = gotTv.Value.String()
+	}
+	if gotStr != valStr {
+		t.Errorf("Eval(%q) got value %s, want %s", expr, gotStr, valStr)
+	}
+}
+
+func TestEvalBasic(t *testing.T) {
+	fset := token.NewFileSet()
+	for _, typ := range Typ[Bool : String+1] {
+		testEval(t, fset, nil, token.NoPos, typ.Name(), typ, "", "")
+	}
+}
+
+func TestEvalComposite(t *testing.T) {
+	fset := token.NewFileSet()
+	for _, test := range independentTestTypes {
+		testEval(t, fset, nil, token.NoPos, test.src, nil, test.str, "")
+	}
+}
+
+func TestEvalArith(t *testing.T) {
+	var tests = []string{
+		`true`,
+		`false == false`,
+		`12345678 + 87654321 == 99999999`,
+		`10 * 20 == 200`,
+		`(1<<1000)*2 >> 100 == 2<<900`,
+		`"foo" + "bar" == "foobar"`,
+		`"abc" <= "bcd"`,
+		`len([10]struct{}{}) == 2*5`,
+	}
+	fset := token.NewFileSet()
+	for _, test := range tests {
+		testEval(t, fset, nil, token.NoPos, test, Typ[UntypedBool], "", "true")
+	}
+}
+
+func TestEvalPos(t *testing.T) {
+	skipSpecialPlatforms(t)
+
+	// The contents of /*-style comments are of the form
+	//	expr => value, type
+	// where value may be the empty string.
+	// Each expr is evaluated at the position of the comment
+	// and the result is compared with the expected value
+	// and type.
+	var sources = []string{
+		`
+		package p
+		import "fmt"
+		import m "math"
+		const c = 3.0
+		type T []int
+		func f(a int, s string) float64 {
+			fmt.Println("calling f")
+			_ = m.Pi // use package math
+			const d int = c + 1
+			var x int
+			x = a + len(s)
+			return float64(x)
+			/* true => true, untyped bool */
+			/* fmt.Println => , func(a ...interface{}) (n int, err error) */
+			/* c => 3, untyped float */
+			/* T => , p.T */
+			/* a => , int */
+			/* s => , string */
+			/* d => 4, int */
+			/* x => , int */
+			/* d/c => 1, int */
+			/* c/2 => 3/2, untyped float */
+			/* m.Pi < m.E => false, untyped bool */
+		}
+		`,
+		`
+		package p
+		/* c => 3, untyped float */
+		type T1 /* T1 => , p.T1 */ struct {}
+		var v1 /* v1 => , int */ = 42
+		func /* f1 => , func(v1 float64) */ f1(v1 float64) {
+			/* f1 => , func(v1 float64) */
+			/* v1 => , float64 */
+			var c /* c => 3, untyped float */ = "foo" /* c => , string */
+			{
+				var c struct {
+					c /* c => , string */ int
+				}
+				/* c => , struct{c int} */
+				_ = c
+			}
+			_ = func(a, b, c int) /* c => , string */ {
+				/* c => , int */
+			}
+			_ = c
+			type FT /* FT => , p.FT */ interface{}
+		}
+		`,
+		`
+		package p
+		/* T => , p.T */
+		`,
+	}
+
+	fset := token.NewFileSet()
+	var files []*ast.File
+	for i, src := range sources {
+		file, err := parser.ParseFile(fset, "p", src, parser.ParseComments)
+		if err != nil {
+			t.Fatalf("could not parse file %d: %s", i, err)
+		}
+		files = append(files, file)
+	}
+
+	pkg, err := Check("p", fset, files)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	for _, file := range files {
+		for _, group := range file.Comments {
+			for _, comment := range group.List {
+				s := comment.Text
+				if len(s) >= 4 && s[:2] == "/*" && s[len(s)-2:] == "*/" {
+					str, typ := split(s[2:len(s)-2], ", ")
+					str, val := split(str, "=>")
+					testEval(t, fset, pkg, comment.Pos(), str, nil, typ, val)
+				}
+			}
+		}
+	}
+}
+
+// split splits string s at the first occurrence of s.
+func split(s, sep string) (string, string) {
+	i := strings.Index(s, sep)
+	return strings.TrimSpace(s[:i]), strings.TrimSpace(s[i+len(sep):])
+}
diff --git a/go/types/expr.go b/go/types/expr.go
new file mode 100644
index 0000000..6efc7b4
--- /dev/null
+++ b/go/types/expr.go
@@ -0,0 +1,1497 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file implements typechecking of expressions.
+
+package types
+
+import (
+	"fmt"
+	"go/ast"
+	"go/token"
+	"math"
+
+	"golang.org/x/tools/go/exact"
+)
+
+/*
+Basic algorithm:
+
+Expressions are checked recursively, top down. Expression checker functions
+are generally of the form:
+
+  func f(x *operand, e *ast.Expr, ...)
+
+where e is the expression to be checked, and x is the result of the check.
+The check performed by f may fail in which case x.mode == invalid, and
+related error messages will have been issued by f.
+
+If a hint argument is present, it is the composite literal element type
+of an outer composite literal; it is used to type-check composite literal
+elements that have no explicit type specification in the source
+(e.g.: []T{{...}, {...}}, the hint is the type T in this case).
+
+All expressions are checked via rawExpr, which dispatches according
+to expression kind. Upon returning, rawExpr is recording the types and
+constant values for all expressions that have an untyped type (those types
+may change on the way up in the expression tree). Usually these are constants,
+but the results of comparisons or non-constant shifts of untyped constants
+may also be untyped, but not constant.
+
+Untyped expressions may eventually become fully typed (i.e., not untyped),
+typically when the value is assigned to a variable, or is used otherwise.
+The updateExprType method is used to record this final type and update
+the recorded types: the type-checked expression tree is again traversed down,
+and the new type is propagated as needed. Untyped constant expression values
+that become fully typed must now be representable by the full type (constant
+sub-expression trees are left alone except for their roots). This mechanism
+ensures that a client sees the actual (run-time) type an untyped value would
+have. It also permits type-checking of lhs shift operands "as if the shift
+were not present": when updateExprType visits an untyped lhs shift operand
+and assigns it it's final type, that type must be an integer type, and a
+constant lhs must be representable as an integer.
+
+When an expression gets its final type, either on the way out from rawExpr,
+on the way down in updateExprType, or at the end of the type checker run,
+the type (and constant value, if any) is recorded via Info.Types, if present.
+*/
+
+type opPredicates map[token.Token]func(Type) bool
+
+var unaryOpPredicates = opPredicates{
+	token.ADD: isNumeric,
+	token.SUB: isNumeric,
+	token.XOR: isInteger,
+	token.NOT: isBoolean,
+}
+
+func (check *Checker) op(m opPredicates, x *operand, op token.Token) bool {
+	if pred := m[op]; pred != nil {
+		if !pred(x.typ) {
+			check.invalidOp(x.pos(), "operator %s not defined for %s", op, x)
+			return false
+		}
+	} else {
+		check.invalidAST(x.pos(), "unknown operator %s", op)
+		return false
+	}
+	return true
+}
+
+// The unary expression e may be nil. It's passed in for better error messages only.
+func (check *Checker) unary(x *operand, e *ast.UnaryExpr, op token.Token) {
+	switch op {
+	case token.AND:
+		// spec: "As an exception to the addressability
+		// requirement x may also be a composite literal."
+		if _, ok := unparen(x.expr).(*ast.CompositeLit); !ok && x.mode != variable {
+			check.invalidOp(x.pos(), "cannot take address of %s", x)
+			x.mode = invalid
+			return
+		}
+		x.mode = value
+		x.typ = &Pointer{base: x.typ}
+		return
+
+	case token.ARROW:
+		typ, ok := x.typ.Underlying().(*Chan)
+		if !ok {
+			check.invalidOp(x.pos(), "cannot receive from non-channel %s", x)
+			x.mode = invalid
+			return
+		}
+		if typ.dir == SendOnly {
+			check.invalidOp(x.pos(), "cannot receive from send-only channel %s", x)
+			x.mode = invalid
+			return
+		}
+		x.mode = commaok
+		x.typ = typ.elem
+		check.hasCallOrRecv = true
+		return
+	}
+
+	if !check.op(unaryOpPredicates, x, op) {
+		x.mode = invalid
+		return
+	}
+
+	if x.mode == constant {
+		typ := x.typ.Underlying().(*Basic)
+		size := -1
+		if isUnsigned(typ) {
+			size = int(check.conf.sizeof(typ))
+		}
+		x.val = exact.UnaryOp(op, x.val, size)
+		// Typed constants must be representable in
+		// their type after each constant operation.
+		if isTyped(typ) {
+			if e != nil {
+				x.expr = e // for better error message
+			}
+			check.representable(x, typ)
+		}
+		return
+	}
+
+	x.mode = value
+	// x.typ remains unchanged
+}
+
+func isShift(op token.Token) bool {
+	return op == token.SHL || op == token.SHR
+}
+
+func isComparison(op token.Token) bool {
+	// Note: tokens are not ordered well to make this much easier
+	switch op {
+	case token.EQL, token.NEQ, token.LSS, token.LEQ, token.GTR, token.GEQ:
+		return true
+	}
+	return false
+}
+
+func fitsFloat32(x exact.Value) bool {
+	f32, _ := exact.Float32Val(x)
+	f := float64(f32)
+	return !math.IsInf(f, 0)
+}
+
+func roundFloat32(x exact.Value) exact.Value {
+	f32, _ := exact.Float32Val(x)
+	f := float64(f32)
+	if !math.IsInf(f, 0) {
+		return exact.MakeFloat64(f)
+	}
+	return nil
+}
+
+func fitsFloat64(x exact.Value) bool {
+	f, _ := exact.Float64Val(x)
+	return !math.IsInf(f, 0)
+}
+
+func roundFloat64(x exact.Value) exact.Value {
+	f, _ := exact.Float64Val(x)
+	if !math.IsInf(f, 0) {
+		return exact.MakeFloat64(f)
+	}
+	return nil
+}
+
+// representableConst reports whether x can be represented as
+// value of the given basic type kind and for the configuration
+// provided (only needed for int/uint sizes).
+//
+// If rounded != nil, *rounded is set to the rounded value of x for
+// representable floating-point values; it is left alone otherwise.
+// It is ok to provide the addressof the first argument for rounded.
+func representableConst(x exact.Value, conf *Config, as BasicKind, rounded *exact.Value) bool {
+	switch x.Kind() {
+	case exact.Unknown:
+		return true
+
+	case exact.Bool:
+		return as == Bool || as == UntypedBool
+
+	case exact.Int:
+		if x, ok := exact.Int64Val(x); ok {
+			switch as {
+			case Int:
+				var s = uint(conf.sizeof(Typ[as])) * 8
+				return int64(-1)<<(s-1) <= x && x <= int64(1)<<(s-1)-1
+			case Int8:
+				const s = 8
+				return -1<<(s-1) <= x && x <= 1<<(s-1)-1
+			case Int16:
+				const s = 16
+				return -1<<(s-1) <= x && x <= 1<<(s-1)-1
+			case Int32:
+				const s = 32
+				return -1<<(s-1) <= x && x <= 1<<(s-1)-1
+			case Int64:
+				return true
+			case Uint, Uintptr:
+				if s := uint(conf.sizeof(Typ[as])) * 8; s < 64 {
+					return 0 <= x && x <= int64(1)<<s-1
+				}
+				return 0 <= x
+			case Uint8:
+				const s = 8
+				return 0 <= x && x <= 1<<s-1
+			case Uint16:
+				const s = 16
+				return 0 <= x && x <= 1<<s-1
+			case Uint32:
+				const s = 32
+				return 0 <= x && x <= 1<<s-1
+			case Uint64:
+				return 0 <= x
+			case Float32, Float64, Complex64, Complex128,
+				UntypedInt, UntypedFloat, UntypedComplex:
+				return true
+			}
+		}
+
+		n := exact.BitLen(x)
+		switch as {
+		case Uint, Uintptr:
+			var s = uint(conf.sizeof(Typ[as])) * 8
+			return exact.Sign(x) >= 0 && n <= int(s)
+		case Uint64:
+			return exact.Sign(x) >= 0 && n <= 64
+		case Float32, Complex64:
+			if rounded == nil {
+				return fitsFloat32(x)
+			}
+			r := roundFloat32(x)
+			if r != nil {
+				*rounded = r
+				return true
+			}
+		case Float64, Complex128:
+			if rounded == nil {
+				return fitsFloat64(x)
+			}
+			r := roundFloat64(x)
+			if r != nil {
+				*rounded = r
+				return true
+			}
+		case UntypedInt, UntypedFloat, UntypedComplex:
+			return true
+		}
+
+	case exact.Float:
+		switch as {
+		case Float32, Complex64:
+			if rounded == nil {
+				return fitsFloat32(x)
+			}
+			r := roundFloat32(x)
+			if r != nil {
+				*rounded = r
+				return true
+			}
+		case Float64, Complex128:
+			if rounded == nil {
+				return fitsFloat64(x)
+			}
+			r := roundFloat64(x)
+			if r != nil {
+				*rounded = r
+				return true
+			}
+		case UntypedFloat, UntypedComplex:
+			return true
+		}
+
+	case exact.Complex:
+		switch as {
+		case Complex64:
+			if rounded == nil {
+				return fitsFloat32(exact.Real(x)) && fitsFloat32(exact.Imag(x))
+			}
+			re := roundFloat32(exact.Real(x))
+			im := roundFloat32(exact.Imag(x))
+			if re != nil && im != nil {
+				*rounded = exact.BinaryOp(re, token.ADD, exact.MakeImag(im))
+				return true
+			}
+		case Complex128:
+			if rounded == nil {
+				return fitsFloat64(exact.Real(x)) && fitsFloat64(exact.Imag(x))
+			}
+			re := roundFloat64(exact.Real(x))
+			im := roundFloat64(exact.Imag(x))
+			if re != nil && im != nil {
+				*rounded = exact.BinaryOp(re, token.ADD, exact.MakeImag(im))
+				return true
+			}
+		case UntypedComplex:
+			return true
+		}
+
+	case exact.String:
+		return as == String || as == UntypedString
+
+	default:
+		unreachable()
+	}
+
+	return false
+}
+
+// representable checks that a constant operand is representable in the given basic type.
+func (check *Checker) representable(x *operand, typ *Basic) {
+	assert(x.mode == constant)
+	if !representableConst(x.val, check.conf, typ.kind, &x.val) {
+		var msg string
+		if isNumeric(x.typ) && isNumeric(typ) {
+			// numeric conversion : error msg
+			//
+			// integer -> integer : overflows
+			// integer -> float   : overflows (actually not possible)
+			// float   -> integer : truncated
+			// float   -> float   : overflows
+			//
+			if !isInteger(x.typ) && isInteger(typ) {
+				msg = "%s truncated to %s"
+			} else {
+				msg = "%s overflows %s"
+			}
+		} else {
+			msg = "cannot convert %s to %s"
+		}
+		check.errorf(x.pos(), msg, x, typ)
+		x.mode = invalid
+	}
+}
+
+// updateExprType updates the type of x to typ and invokes itself
+// recursively for the operands of x, depending on expression kind.
+// If typ is still an untyped and not the final type, updateExprType
+// only updates the recorded untyped type for x and possibly its
+// operands. Otherwise (i.e., typ is not an untyped type anymore,
+// or it is the final type for x), the type and value are recorded.
+// Also, if x is a constant, it must be representable as a value of typ,
+// and if x is the (formerly untyped) lhs operand of a non-constant
+// shift, it must be an integer value.
+//
+func (check *Checker) updateExprType(x ast.Expr, typ Type, final bool) {
+	old, found := check.untyped[x]
+	if !found {
+		return // nothing to do
+	}
+
+	// update operands of x if necessary
+	switch x := x.(type) {
+	case *ast.BadExpr,
+		*ast.FuncLit,
+		*ast.CompositeLit,
+		*ast.IndexExpr,
+		*ast.SliceExpr,
+		*ast.TypeAssertExpr,
+		*ast.StarExpr,
+		*ast.KeyValueExpr,
+		*ast.ArrayType,
+		*ast.StructType,
+		*ast.FuncType,
+		*ast.InterfaceType,
+		*ast.MapType,
+		*ast.ChanType:
+		// These expression are never untyped - nothing to do.
+		// The respective sub-expressions got their final types
+		// upon assignment or use.
+		if debug {
+			check.dump("%s: found old type(%s): %s (new: %s)", x.Pos(), x, old.typ, typ)
+			unreachable()
+		}
+		return
+
+	case *ast.CallExpr:
+		// Resulting in an untyped constant (e.g., built-in complex).
+		// The respective calls take care of calling updateExprType
+		// for the arguments if necessary.
+
+	case *ast.Ident, *ast.BasicLit, *ast.SelectorExpr:
+		// An identifier denoting a constant, a constant literal,
+		// or a qualified identifier (imported untyped constant).
+		// No operands to take care of.
+
+	case *ast.ParenExpr:
+		check.updateExprType(x.X, typ, final)
+
+	case *ast.UnaryExpr:
+		// If x is a constant, the operands were constants.
+		// They don't need to be updated since they never
+		// get "materialized" into a typed value; and they
+		// will be processed at the end of the type check.
+		if old.val != nil {
+			break
+		}
+		check.updateExprType(x.X, typ, final)
+
+	case *ast.BinaryExpr:
+		if old.val != nil {
+			break // see comment for unary expressions
+		}
+		if isComparison(x.Op) {
+			// The result type is independent of operand types
+			// and the operand types must have final types.
+		} else if isShift(x.Op) {
+			// The result type depends only on lhs operand.
+			// The rhs type was updated when checking the shift.
+			check.updateExprType(x.X, typ, final)
+		} else {
+			// The operand types match the result type.
+			check.updateExprType(x.X, typ, final)
+			check.updateExprType(x.Y, typ, final)
+		}
+
+	default:
+		unreachable()
+	}
+
+	// If the new type is not final and still untyped, just
+	// update the recorded type.
+	if !final && isUntyped(typ) {
+		old.typ = typ.Underlying().(*Basic)
+		check.untyped[x] = old
+		return
+	}
+
+	// Otherwise we have the final (typed or untyped type).
+	// Remove it from the map of yet untyped expressions.
+	delete(check.untyped, x)
+
+	// If x is the lhs of a shift, its final type must be integer.
+	// We already know from the shift check that it is representable
+	// as an integer if it is a constant.
+	if old.isLhs && !isInteger(typ) {
+		check.invalidOp(x.Pos(), "shifted operand %s (type %s) must be integer", x, typ)
+		return
+	}
+
+	// Everything's fine, record final type and value for x.
+	check.recordTypeAndValue(x, old.mode, typ, old.val)
+}
+
+// updateExprVal updates the value of x to val.
+func (check *Checker) updateExprVal(x ast.Expr, val exact.Value) {
+	if info, ok := check.untyped[x]; ok {
+		info.val = val
+		check.untyped[x] = info
+	}
+}
+
+// convertUntyped attempts to set the type of an untyped value to the target type.
+func (check *Checker) convertUntyped(x *operand, target Type) {
+	if x.mode == invalid || isTyped(x.typ) || target == Typ[Invalid] {
+		return
+	}
+
+	// TODO(gri) Sloppy code - clean up. This function is central
+	//           to assignment and expression checking.
+
+	if isUntyped(target) {
+		// both x and target are untyped
+		xkind := x.typ.(*Basic).kind
+		tkind := target.(*Basic).kind
+		if isNumeric(x.typ) && isNumeric(target) {
+			if xkind < tkind {
+				x.typ = target
+				check.updateExprType(x.expr, target, false)
+			}
+		} else if xkind != tkind {
+			goto Error
+		}
+		return
+	}
+
+	// typed target
+	switch t := target.Underlying().(type) {
+	case *Basic:
+		if x.mode == constant {
+			check.representable(x, t)
+			if x.mode == invalid {
+				return
+			}
+			// expression value may have been rounded - update if needed
+			// TODO(gri) A floating-point value may silently underflow to
+			// zero. If it was negative, the sign is lost. See issue 6898.
+			check.updateExprVal(x.expr, x.val)
+		} else {
+			// Non-constant untyped values may appear as the
+			// result of comparisons (untyped bool), intermediate
+			// (delayed-checked) rhs operands of shifts, and as
+			// the value nil.
+			switch x.typ.(*Basic).kind {
+			case UntypedBool:
+				if !isBoolean(target) {
+					goto Error
+				}
+			case UntypedInt, UntypedRune, UntypedFloat, UntypedComplex:
+				if !isNumeric(target) {
+					goto Error
+				}
+			case UntypedString:
+				// Non-constant untyped string values are not
+				// permitted by the spec and should not occur.
+				unreachable()
+			case UntypedNil:
+				// Unsafe.Pointer is a basic type that includes nil.
+				if !hasNil(target) {
+					goto Error
+				}
+			default:
+				goto Error
+			}
+		}
+	case *Interface:
+		if !x.isNil() && !t.Empty() /* empty interfaces are ok */ {
+			goto Error
+		}
+		// Update operand types to the default type rather then
+		// the target (interface) type: values must have concrete
+		// dynamic types. If the value is nil, keep it untyped
+		// (this is important for tools such as go vet which need
+		// the dynamic type for argument checking of say, print
+		// functions)
+		if x.isNil() {
+			target = Typ[UntypedNil]
+		} else {
+			// cannot assign untyped values to non-empty interfaces
+			if !t.Empty() {
+				goto Error
+			}
+			target = defaultType(x.typ)
+		}
+	case *Pointer, *Signature, *Slice, *Map, *Chan:
+		if !x.isNil() {
+			goto Error
+		}
+		// keep nil untyped - see comment for interfaces, above
+		target = Typ[UntypedNil]
+	default:
+		goto Error
+	}
+
+	x.typ = target
+	check.updateExprType(x.expr, target, true) // UntypedNils are final
+	return
+
+Error:
+	check.errorf(x.pos(), "cannot convert %s to %s", x, target)
+	x.mode = invalid
+}
+
+func (check *Checker) comparison(x, y *operand, op token.Token) {
+	// spec: "In any comparison, the first operand must be assignable
+	// to the type of the second operand, or vice versa."
+	err := ""
+	if x.assignableTo(check.conf, y.typ) || y.assignableTo(check.conf, x.typ) {
+		defined := false
+		switch op {
+		case token.EQL, token.NEQ:
+			// spec: "The equality operators == and != apply to operands that are comparable."
+			defined = Comparable(x.typ) || x.isNil() && hasNil(y.typ) || y.isNil() && hasNil(x.typ)
+		case token.LSS, token.LEQ, token.GTR, token.GEQ:
+			// spec: The ordering operators <, <=, >, and >= apply to operands that are ordered."
+			defined = isOrdered(x.typ)
+		default:
+			unreachable()
+		}
+		if !defined {
+			typ := x.typ
+			if x.isNil() {
+				typ = y.typ
+			}
+			err = check.sprintf("operator %s not defined for %s", op, typ)
+		}
+	} else {
+		err = check.sprintf("mismatched types %s and %s", x.typ, y.typ)
+	}
+
+	if err != "" {
+		check.errorf(x.pos(), "cannot compare %s %s %s (%s)", x.expr, op, y.expr, err)
+		x.mode = invalid
+		return
+	}
+
+	if x.mode == constant && y.mode == constant {
+		x.val = exact.MakeBool(exact.Compare(x.val, op, y.val))
+		// The operands are never materialized; no need to update
+		// their types.
+	} else {
+		x.mode = value
+		// The operands have now their final types, which at run-
+		// time will be materialized. Update the expression trees.
+		// If the current types are untyped, the materialized type
+		// is the respective default type.
+		check.updateExprType(x.expr, defaultType(x.typ), true)
+		check.updateExprType(y.expr, defaultType(y.typ), true)
+	}
+
+	// spec: "Comparison operators compare two operands and yield
+	//        an untyped boolean value."
+	x.typ = Typ[UntypedBool]
+}
+
+func (check *Checker) shift(x, y *operand, op token.Token) {
+	untypedx := isUntyped(x.typ)
+
+	// The lhs must be of integer type or be representable
+	// as an integer; otherwise the shift has no chance.
+	if !x.isInteger() {
+		check.invalidOp(x.pos(), "shifted operand %s must be integer", x)
+		x.mode = invalid
+		return
+	}
+
+	// spec: "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."
+	switch {
+	case isInteger(y.typ) && isUnsigned(y.typ):
+		// nothing to do
+	case isUntyped(y.typ):
+		check.convertUntyped(y, Typ[UntypedInt])
+		if y.mode == invalid {
+			x.mode = invalid
+			return
+		}
+	default:
+		check.invalidOp(y.pos(), "shift count %s must be unsigned integer", y)
+		x.mode = invalid
+		return
+	}
+
+	if x.mode == constant {
+		if y.mode == constant {
+			// rhs must be an integer value
+			if !y.isInteger() {
+				check.invalidOp(y.pos(), "shift count %s must be unsigned integer", y)
+				x.mode = invalid
+				return
+			}
+			// rhs must be within reasonable bounds
+			const stupidShift = 1023 - 1 + 52 // so we can express smallestFloat64
+			s, ok := exact.Uint64Val(y.val)
+			if !ok || s > stupidShift {
+				check.invalidOp(y.pos(), "stupid shift count %s", y)
+				x.mode = invalid
+				return
+			}
+			// The lhs is representable as an integer but may not be an integer
+			// (e.g., 2.0, an untyped float) - this can only happen for untyped
+			// non-integer numeric constants. Correct the type so that the shift
+			// result is of integer type.
+			if !isInteger(x.typ) {
+				x.typ = Typ[UntypedInt]
+			}
+			x.val = exact.Shift(x.val, op, uint(s))
+			return
+		}
+
+		// non-constant shift with constant lhs
+		if untypedx {
+			// spec: "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.".
+			//
+			// Delay operand checking until we know the final type:
+			// The lhs expression must be in the untyped map, mark
+			// the entry as lhs shift operand.
+			info, found := check.untyped[x.expr]
+			assert(found)
+			info.isLhs = true
+			check.untyped[x.expr] = info
+			// keep x's type
+			x.mode = value
+			return
+		}
+	}
+
+	// constant rhs must be >= 0
+	if y.mode == constant && exact.Sign(y.val) < 0 {
+		check.invalidOp(y.pos(), "shift count %s must not be negative", y)
+	}
+
+	// non-constant shift - lhs must be an integer
+	if !isInteger(x.typ) {
+		check.invalidOp(x.pos(), "shifted operand %s must be integer", x)
+		x.mode = invalid
+		return
+	}
+
+	x.mode = value
+}
+
+var binaryOpPredicates = opPredicates{
+	token.ADD: func(typ Type) bool { return isNumeric(typ) || isString(typ) },
+	token.SUB: isNumeric,
+	token.MUL: isNumeric,
+	token.QUO: isNumeric,
+	token.REM: isInteger,
+
+	token.AND:     isInteger,
+	token.OR:      isInteger,
+	token.XOR:     isInteger,
+	token.AND_NOT: isInteger,
+
+	token.LAND: isBoolean,
+	token.LOR:  isBoolean,
+}
+
+// The binary expression e may be nil. It's passed in for better error messages only.
+func (check *Checker) binary(x *operand, e *ast.BinaryExpr, lhs, rhs ast.Expr, op token.Token) {
+	var y operand
+
+	check.expr(x, lhs)
+	check.expr(&y, rhs)
+
+	if x.mode == invalid {
+		return
+	}
+	if y.mode == invalid {
+		x.mode = invalid
+		x.expr = y.expr
+		return
+	}
+
+	if isShift(op) {
+		check.shift(x, &y, op)
+		return
+	}
+
+	check.convertUntyped(x, y.typ)
+	if x.mode == invalid {
+		return
+	}
+	check.convertUntyped(&y, x.typ)
+	if y.mode == invalid {
+		x.mode = invalid
+		return
+	}
+
+	if isComparison(op) {
+		check.comparison(x, &y, op)
+		return
+	}
+
+	if !Identical(x.typ, y.typ) {
+		// only report an error if we have valid types
+		// (otherwise we had an error reported elsewhere already)
+		if x.typ != Typ[Invalid] && y.typ != Typ[Invalid] {
+			check.invalidOp(x.pos(), "mismatched types %s and %s", x.typ, y.typ)
+		}
+		x.mode = invalid
+		return
+	}
+
+	if !check.op(binaryOpPredicates, x, op) {
+		x.mode = invalid
+		return
+	}
+
+	if (op == token.QUO || op == token.REM) && (x.mode == constant || isInteger(x.typ)) && y.mode == constant && exact.Sign(y.val) == 0 {
+		check.invalidOp(y.pos(), "division by zero")
+		x.mode = invalid
+		return
+	}
+
+	if x.mode == constant && y.mode == constant {
+		typ := x.typ.Underlying().(*Basic)
+		// force integer division of integer operands
+		if op == token.QUO && isInteger(typ) {
+			op = token.QUO_ASSIGN
+		}
+		x.val = exact.BinaryOp(x.val, op, y.val)
+		// Typed constants must be representable in
+		// their type after each constant operation.
+		if isTyped(typ) {
+			if e != nil {
+				x.expr = e // for better error message
+			}
+			check.representable(x, typ)
+		}
+		return
+	}
+
+	x.mode = value
+	// x.typ is unchanged
+}
+
+// index checks an index expression for validity.
+// If max >= 0, it is the upper bound for index.
+// If index is valid and the result i >= 0, then i is the constant value of index.
+func (check *Checker) index(index ast.Expr, max int64) (i int64, valid bool) {
+	var x operand
+	check.expr(&x, index)
+	if x.mode == invalid {
+		return
+	}
+
+	// an untyped constant must be representable as Int
+	check.convertUntyped(&x, Typ[Int])
+	if x.mode == invalid {
+		return
+	}
+
+	// the index must be of integer type
+	if !isInteger(x.typ) {
+		check.invalidArg(x.pos(), "index %s must be integer", &x)
+		return
+	}
+
+	// a constant index i must be in bounds
+	if x.mode == constant {
+		if exact.Sign(x.val) < 0 {
+			check.invalidArg(x.pos(), "index %s must not be negative", &x)
+			return
+		}
+		i, valid = exact.Int64Val(x.val)
+		if !valid || max >= 0 && i >= max {
+			check.errorf(x.pos(), "index %s is out of bounds", &x)
+			return i, false
+		}
+		// 0 <= i [ && i < max ]
+		return i, true
+	}
+
+	return -1, true
+}
+
+// indexElts checks the elements (elts) of an array or slice composite literal
+// against the literal's element type (typ), and the element indices against
+// the literal length if known (length >= 0). It returns the length of the
+// literal (maximum index value + 1).
+//
+func (check *Checker) indexedElts(elts []ast.Expr, typ Type, length int64) int64 {
+	visited := make(map[int64]bool, len(elts))
+	var index, max int64
+	for _, e := range elts {
+		// determine and check index
+		validIndex := false
+		eval := e
+		if kv, _ := e.(*ast.KeyValueExpr); kv != nil {
+			if i, ok := check.index(kv.Key, length); ok {
+				if i >= 0 {
+					index = i
+					validIndex = true
+				} else {
+					check.errorf(e.Pos(), "index %s must be integer constant", kv.Key)
+				}
+			}
+			eval = kv.Value
+		} else if length >= 0 && index >= length {
+			check.errorf(e.Pos(), "index %d is out of bounds (>= %d)", index, length)
+		} else {
+			validIndex = true
+		}
+
+		// if we have a valid index, check for duplicate entries
+		if validIndex {
+			if visited[index] {
+				check.errorf(e.Pos(), "duplicate index %d in array or slice literal", index)
+			}
+			visited[index] = true
+		}
+		index++
+		if index > max {
+			max = index
+		}
+
+		// check element against composite literal element type
+		var x operand
+		check.exprWithHint(&x, eval, typ)
+		if !check.assignment(&x, typ) && x.mode != invalid {
+			check.errorf(x.pos(), "cannot use %s as %s value in array or slice literal", &x, typ)
+		}
+	}
+	return max
+}
+
+// exprKind describes the kind of an expression; the kind
+// determines if an expression is valid in 'statement context'.
+type exprKind int
+
+const (
+	conversion exprKind = iota
+	expression
+	statement
+)
+
+// rawExpr typechecks expression e and initializes x with the expression
+// value or type. If an error occurred, x.mode is set to invalid.
+// If hint != nil, it is the type of a composite literal element.
+//
+func (check *Checker) rawExpr(x *operand, e ast.Expr, hint Type) exprKind {
+	if trace {
+		check.trace(e.Pos(), "%s", e)
+		check.indent++
+		defer func() {
+			check.indent--
+			check.trace(e.Pos(), "=> %s", x)
+		}()
+	}
+
+	kind := check.exprInternal(x, e, hint)
+
+	// convert x into a user-friendly set of values
+	// TODO(gri) this code can be simplified
+	var typ Type
+	var val exact.Value
+	switch x.mode {
+	case invalid:
+		typ = Typ[Invalid]
+	case novalue:
+		typ = (*Tuple)(nil)
+	case constant:
+		typ = x.typ
+		val = x.val
+	default:
+		typ = x.typ
+	}
+	assert(x.expr != nil && typ != nil)
+
+	if isUntyped(typ) {
+		// delay type and value recording until we know the type
+		// or until the end of type checking
+		check.rememberUntyped(x.expr, false, x.mode, typ.(*Basic), val)
+	} else {
+		check.recordTypeAndValue(e, x.mode, typ, val)
+	}
+
+	return kind
+}
+
+// exprInternal contains the core of type checking of expressions.
+// Must only be called by rawExpr.
+//
+func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
+	// make sure x has a valid state in case of bailout
+	// (was issue 5770)
+	x.mode = invalid
+	x.typ = Typ[Invalid]
+
+	switch e := e.(type) {
+	case *ast.BadExpr:
+		goto Error // error was reported before
+
+	case *ast.Ident:
+		check.ident(x, e, nil, nil)
+
+	case *ast.Ellipsis:
+		// ellipses are handled explicitly where they are legal
+		// (array composite literals and parameter lists)
+		check.error(e.Pos(), "invalid use of '...'")
+		goto Error
+
+	case *ast.BasicLit:
+		x.setConst(e.Kind, e.Value)
+		if x.mode == invalid {
+			check.invalidAST(e.Pos(), "invalid literal %v", e.Value)
+			goto Error
+		}
+
+	case *ast.FuncLit:
+		if sig, ok := check.typ(e.Type).(*Signature); ok {
+			// Anonymous functions are considered part of the
+			// init expression/func declaration which contains
+			// them: use existing package-level declaration info.
+			check.funcBody(check.decl, "", sig, e.Body)
+			x.mode = value
+			x.typ = sig
+		} else {
+			check.invalidAST(e.Pos(), "invalid function literal %s", e)
+			goto Error
+		}
+
+	case *ast.CompositeLit:
+		typ := hint
+		openArray := false
+		if e.Type != nil {
+			// [...]T array types may only appear with composite literals.
+			// Check for them here so we don't have to handle ... in general.
+			typ = nil
+			if atyp, _ := e.Type.(*ast.ArrayType); atyp != nil && atyp.Len != nil {
+				if ellip, _ := atyp.Len.(*ast.Ellipsis); ellip != nil && ellip.Elt == nil {
+					// We have an "open" [...]T array type.
+					// Create a new ArrayType with unknown length (-1)
+					// and finish setting it up after analyzing the literal.
+					typ = &Array{len: -1, elem: check.typ(atyp.Elt)}
+					openArray = true
+				}
+			}
+			if typ == nil {
+				typ = check.typ(e.Type)
+			}
+		}
+		if typ == nil {
+			// TODO(gri) provide better error messages depending on context
+			check.error(e.Pos(), "missing type in composite literal")
+			goto Error
+		}
+
+		switch typ, _ := deref(typ); utyp := typ.Underlying().(type) {
+		case *Struct:
+			if len(e.Elts) == 0 {
+				break
+			}
+			fields := utyp.fields
+			if _, ok := e.Elts[0].(*ast.KeyValueExpr); ok {
+				// all elements must have keys
+				visited := make([]bool, len(fields))
+				for _, e := range e.Elts {
+					kv, _ := e.(*ast.KeyValueExpr)
+					if kv == nil {
+						check.error(e.Pos(), "mixture of field:value and value elements in struct literal")
+						continue
+					}
+					key, _ := kv.Key.(*ast.Ident)
+					if key == nil {
+						check.errorf(kv.Pos(), "invalid field name %s in struct literal", kv.Key)
+						continue
+					}
+					i := fieldIndex(utyp.fields, check.pkg, key.Name)
+					if i < 0 {
+						check.errorf(kv.Pos(), "unknown field %s in struct literal", key.Name)
+						continue
+					}
+					fld := fields[i]
+					check.recordUse(key, fld)
+					// 0 <= i < len(fields)
+					if visited[i] {
+						check.errorf(kv.Pos(), "duplicate field name %s in struct literal", key.Name)
+						continue
+					}
+					visited[i] = true
+					check.expr(x, kv.Value)
+					etyp := fld.typ
+					if !check.assignment(x, etyp) {
+						if x.mode != invalid {
+							check.errorf(x.pos(), "cannot use %s as %s value in struct literal", x, etyp)
+						}
+						continue
+					}
+				}
+			} else {
+				// no element must have a key
+				for i, e := range e.Elts {
+					if kv, _ := e.(*ast.KeyValueExpr); kv != nil {
+						check.error(kv.Pos(), "mixture of field:value and value elements in struct literal")
+						continue
+					}
+					check.expr(x, e)
+					if i >= len(fields) {
+						check.error(x.pos(), "too many values in struct literal")
+						break // cannot continue
+					}
+					// i < len(fields)
+					fld := fields[i]
+					if !fld.Exported() && fld.pkg != check.pkg {
+						check.errorf(x.pos(), "implicit assignment to unexported field %s in %s literal", fld.name, typ)
+						continue
+					}
+					etyp := fld.typ
+					if !check.assignment(x, etyp) {
+						if x.mode != invalid {
+							check.errorf(x.pos(), "cannot use %s as %s value in struct literal", x, etyp)
+						}
+						continue
+					}
+				}
+				if len(e.Elts) < len(fields) {
+					check.error(e.Rbrace, "too few values in struct literal")
+					// ok to continue
+				}
+			}
+
+		case *Array:
+			n := check.indexedElts(e.Elts, utyp.elem, utyp.len)
+			// if we have an "open" [...]T array, set the length now that we know it
+			if openArray {
+				utyp.len = n
+			}
+
+		case *Slice:
+			check.indexedElts(e.Elts, utyp.elem, -1)
+
+		case *Map:
+			visited := make(map[interface{}][]Type, len(e.Elts))
+			for _, e := range e.Elts {
+				kv, _ := e.(*ast.KeyValueExpr)
+				if kv == nil {
+					check.error(e.Pos(), "missing key in map literal")
+					continue
+				}
+				check.exprWithHint(x, kv.Key, utyp.key)
+				if !check.assignment(x, utyp.key) {
+					if x.mode != invalid {
+						check.errorf(x.pos(), "cannot use %s as %s key in map literal", x, utyp.key)
+					}
+					continue
+				}
+				if x.mode == constant {
+					duplicate := false
+					// if the key is of interface type, the type is also significant when checking for duplicates
+					if _, ok := utyp.key.Underlying().(*Interface); ok {
+						for _, vtyp := range visited[x.val] {
+							if Identical(vtyp, x.typ) {
+								duplicate = true
+								break
+							}
+						}
+						visited[x.val] = append(visited[x.val], x.typ)
+					} else {
+						_, duplicate = visited[x.val]
+						visited[x.val] = nil
+					}
+					if duplicate {
+						check.errorf(x.pos(), "duplicate key %s in map literal", x.val)
+						continue
+					}
+				}
+				check.exprWithHint(x, kv.Value, utyp.elem)
+				if !check.assignment(x, utyp.elem) {
+					if x.mode != invalid {
+						check.errorf(x.pos(), "cannot use %s as %s value in map literal", x, utyp.elem)
+					}
+					continue
+				}
+			}
+
+		default:
+			// if utyp is invalid, an error was reported before
+			if utyp != Typ[Invalid] {
+				check.errorf(e.Pos(), "invalid composite literal type %s", typ)
+				goto Error
+			}
+		}
+
+		x.mode = value
+		x.typ = typ
+
+	case *ast.ParenExpr:
+		kind := check.rawExpr(x, e.X, nil)
+		x.expr = e
+		return kind
+
+	case *ast.SelectorExpr:
+		check.selector(x, e)
+
+	case *ast.IndexExpr:
+		check.expr(x, e.X)
+		if x.mode == invalid {
+			goto Error
+		}
+
+		valid := false
+		length := int64(-1) // valid if >= 0
+		switch typ := x.typ.Underlying().(type) {
+		case *Basic:
+			if isString(typ) {
+				valid = true
+				if x.mode == constant {
+					length = int64(len(exact.StringVal(x.val)))
+				}
+				// an indexed string always yields a byte value
+				// (not a constant) even if the string and the
+				// index are constant
+				x.mode = value
+				x.typ = universeByte // use 'byte' name
+			}
+
+		case *Array:
+			valid = true
+			length = typ.len
+			if x.mode != variable {
+				x.mode = value
+			}
+			x.typ = typ.elem
+
+		case *Pointer:
+			if typ, _ := typ.base.Underlying().(*Array); typ != nil {
+				valid = true
+				length = typ.len
+				x.mode = variable
+				x.typ = typ.elem
+			}
+
+		case *Slice:
+			valid = true
+			x.mode = variable
+			x.typ = typ.elem
+
+		case *Map:
+			var key operand
+			check.expr(&key, e.Index)
+			if !check.assignment(&key, typ.key) {
+				if key.mode != invalid {
+					check.invalidOp(key.pos(), "cannot use %s as map index of type %s", &key, typ.key)
+				}
+				goto Error
+			}
+			x.mode = mapindex
+			x.typ = typ.elem
+			x.expr = e
+			return expression
+		}
+
+		if !valid {
+			check.invalidOp(x.pos(), "cannot index %s", x)
+			goto Error
+		}
+
+		if e.Index == nil {
+			check.invalidAST(e.Pos(), "missing index for %s", x)
+			goto Error
+		}
+
+		check.index(e.Index, length)
+		// ok to continue
+
+	case *ast.SliceExpr:
+		check.expr(x, e.X)
+		if x.mode == invalid {
+			goto Error
+		}
+
+		valid := false
+		length := int64(-1) // valid if >= 0
+		switch typ := x.typ.Underlying().(type) {
+		case *Basic:
+			if isString(typ) {
+				if slice3(e) {
+					check.invalidOp(x.pos(), "3-index slice of string")
+					goto Error
+				}
+				valid = true
+				if x.mode == constant {
+					length = int64(len(exact.StringVal(x.val)))
+				}
+				// spec: "For untyped string operands the result
+				// is a non-constant value of type string."
+				if typ.kind == UntypedString {
+					x.typ = Typ[String]
+				}
+			}
+
+		case *Array:
+			valid = true
+			length = typ.len
+			if x.mode != variable {
+				check.invalidOp(x.pos(), "cannot slice %s (value not addressable)", x)
+				goto Error
+			}
+			x.typ = &Slice{elem: typ.elem}
+
+		case *Pointer:
+			if typ, _ := typ.base.Underlying().(*Array); typ != nil {
+				valid = true
+				length = typ.len
+				x.typ = &Slice{elem: typ.elem}
+			}
+
+		case *Slice:
+			valid = true
+			// x.typ doesn't change
+		}
+
+		if !valid {
+			check.invalidOp(x.pos(), "cannot slice %s", x)
+			goto Error
+		}
+
+		x.mode = value
+
+		// spec: "Only the first index may be omitted; it defaults to 0."
+		if slice3(e) && (e.High == nil || sliceMax(e) == nil) {
+			check.error(e.Rbrack, "2nd and 3rd index required in 3-index slice")
+			goto Error
+		}
+
+		// check indices
+		var ind [3]int64
+		for i, expr := range []ast.Expr{e.Low, e.High, sliceMax(e)} {
+			x := int64(-1)
+			switch {
+			case expr != nil:
+				// The "capacity" is only known statically for strings, arrays,
+				// and pointers to arrays, and it is the same as the length for
+				// those types.
+				max := int64(-1)
+				if length >= 0 {
+					max = length + 1
+				}
+				if t, ok := check.index(expr, max); ok && t >= 0 {
+					x = t
+				}
+			case i == 0:
+				// default is 0 for the first index
+				x = 0
+			case length >= 0:
+				// default is length (== capacity) otherwise
+				x = length
+			}
+			ind[i] = x
+		}
+
+		// constant indices must be in range
+		// (check.index already checks that existing indices >= 0)
+	L:
+		for i, x := range ind[:len(ind)-1] {
+			if x > 0 {
+				for _, y := range ind[i+1:] {
+					if y >= 0 && x > y {
+						check.errorf(e.Rbrack, "invalid slice indices: %d > %d", x, y)
+						break L // only report one error, ok to continue
+					}
+				}
+			}
+		}
+
+	case *ast.TypeAssertExpr:
+		check.expr(x, e.X)
+		if x.mode == invalid {
+			goto Error
+		}
+		xtyp, _ := x.typ.Underlying().(*Interface)
+		if xtyp == nil {
+			check.invalidOp(x.pos(), "%s is not an interface", x)
+			goto Error
+		}
+		// x.(type) expressions are handled explicitly in type switches
+		if e.Type == nil {
+			check.invalidAST(e.Pos(), "use of .(type) outside type switch")
+			goto Error
+		}
+		T := check.typ(e.Type)
+		if T == Typ[Invalid] {
+			goto Error
+		}
+		check.typeAssertion(x.pos(), x, xtyp, T)
+		x.mode = commaok
+		x.typ = T
+
+	case *ast.CallExpr:
+		return check.call(x, e)
+
+	case *ast.StarExpr:
+		check.exprOrType(x, e.X)
+		switch x.mode {
+		case invalid:
+			goto Error
+		case typexpr:
+			x.typ = &Pointer{base: x.typ}
+		default:
+			if typ, ok := x.typ.Underlying().(*Pointer); ok {
+				x.mode = variable
+				x.typ = typ.base
+			} else {
+				check.invalidOp(x.pos(), "cannot indirect %s", x)
+				goto Error
+			}
+		}
+
+	case *ast.UnaryExpr:
+		check.expr(x, e.X)
+		if x.mode == invalid {
+			goto Error
+		}
+		check.unary(x, e, e.Op)
+		if x.mode == invalid {
+			goto Error
+		}
+		if e.Op == token.ARROW {
+			x.expr = e
+			return statement // receive operations may appear in statement context
+		}
+
+	case *ast.BinaryExpr:
+		check.binary(x, e, e.X, e.Y, e.Op)
+		if x.mode == invalid {
+			goto Error
+		}
+
+	case *ast.KeyValueExpr:
+		// key:value expressions are handled in composite literals
+		check.invalidAST(e.Pos(), "no key:value expected")
+		goto Error
+
+	case *ast.ArrayType, *ast.StructType, *ast.FuncType,
+		*ast.InterfaceType, *ast.MapType, *ast.ChanType:
+		x.mode = typexpr
+		x.typ = check.typ(e)
+		// Note: rawExpr (caller of exprInternal) will call check.recordTypeAndValue
+		// even though check.typ has already called it. This is fine as both
+		// times the same expression and type are recorded. It is also not a
+		// performance issue because we only reach here for composite literal
+		// types, which are comparatively rare.
+
+	default:
+		panic(fmt.Sprintf("%s: unknown expression type %T", check.fset.Position(e.Pos()), e))
+	}
+
+	// everything went well
+	x.expr = e
+	return expression
+
+Error:
+	x.mode = invalid
+	x.expr = e
+	return statement // avoid follow-up errors
+}
+
+// typeAssertion checks that x.(T) is legal; xtyp must be the type of x.
+func (check *Checker) typeAssertion(pos token.Pos, x *operand, xtyp *Interface, T Type) {
+	method, wrongType := assertableTo(xtyp, T)
+	if method == nil {
+		return
+	}
+
+	var msg string
+	if wrongType {
+		msg = "wrong type for method"
+	} else {
+		msg = "missing method"
+	}
+	check.errorf(pos, "%s cannot have dynamic type %s (%s %s)", x, T, msg, method.name)
+}
+
+// expr typechecks expression e and initializes x with the expression value.
+// If an error occurred, x.mode is set to invalid.
+//
+func (check *Checker) expr(x *operand, e ast.Expr) {
+	check.rawExpr(x, e, nil)
+	var msg string
+	switch x.mode {
+	default:
+		return
+	case novalue:
+		msg = "used as value"
+	case builtin:
+		msg = "must be called"
+	case typexpr:
+		msg = "is not an expression"
+	}
+	check.errorf(x.pos(), "%s %s", x, msg)
+	x.mode = invalid
+}
+
+// exprWithHint typechecks expression e and initializes x with the expression value.
+// If an error occurred, x.mode is set to invalid.
+// If hint != nil, it is the type of a composite literal element.
+//
+func (check *Checker) exprWithHint(x *operand, e ast.Expr, hint Type) {
+	assert(hint != nil)
+	check.rawExpr(x, e, hint)
+	var msg string
+	switch x.mode {
+	default:
+		return
+	case novalue:
+		msg = "used as value"
+	case builtin:
+		msg = "must be called"
+	case typexpr:
+		msg = "is not an expression"
+	}
+	check.errorf(x.pos(), "%s %s", x, msg)
+	x.mode = invalid
+}
+
+// exprOrType typechecks expression or type e and initializes x with the expression value or type.
+// If an error occurred, x.mode is set to invalid.
+//
+func (check *Checker) exprOrType(x *operand, e ast.Expr) {
+	check.rawExpr(x, e, nil)
+	if x.mode == novalue {
+		check.errorf(x.pos(), "%s used as value or type", x)
+		x.mode = invalid
+	}
+}
diff --git a/go/types/exprstring.go b/go/types/exprstring.go
new file mode 100644
index 0000000..370bdf3
--- /dev/null
+++ b/go/types/exprstring.go
@@ -0,0 +1,220 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file implements printing of expressions.
+
+package types
+
+import (
+	"bytes"
+	"go/ast"
+)
+
+// ExprString returns the (possibly simplified) string representation for x.
+func ExprString(x ast.Expr) string {
+	var buf bytes.Buffer
+	WriteExpr(&buf, x)
+	return buf.String()
+}
+
+// WriteExpr writes the (possibly simplified) string representation for x to buf.
+func WriteExpr(buf *bytes.Buffer, x ast.Expr) {
+	// The AST preserves source-level parentheses so there is
+	// no need to introduce them here to correct for different
+	// operator precedences. (This assumes that the AST was
+	// generated by a Go parser.)
+
+	switch x := x.(type) {
+	default:
+		buf.WriteString("(bad expr)") // nil, ast.BadExpr, ast.KeyValueExpr
+
+	case *ast.Ident:
+		buf.WriteString(x.Name)
+
+	case *ast.Ellipsis:
+		buf.WriteString("...")
+		if x.Elt != nil {
+			WriteExpr(buf, x.Elt)
+		}
+
+	case *ast.BasicLit:
+		buf.WriteString(x.Value)
+
+	case *ast.FuncLit:
+		buf.WriteByte('(')
+		WriteExpr(buf, x.Type)
+		buf.WriteString(" literal)") // simplified
+
+	case *ast.CompositeLit:
+		buf.WriteByte('(')
+		WriteExpr(buf, x.Type)
+		buf.WriteString(" literal)") // simplified
+
+	case *ast.ParenExpr:
+		buf.WriteByte('(')
+		WriteExpr(buf, x.X)
+		buf.WriteByte(')')
+
+	case *ast.SelectorExpr:
+		WriteExpr(buf, x.X)
+		buf.WriteByte('.')
+		buf.WriteString(x.Sel.Name)
+
+	case *ast.IndexExpr:
+		WriteExpr(buf, x.X)
+		buf.WriteByte('[')
+		WriteExpr(buf, x.Index)
+		buf.WriteByte(']')
+
+	case *ast.SliceExpr:
+		WriteExpr(buf, x.X)
+		buf.WriteByte('[')
+		if x.Low != nil {
+			WriteExpr(buf, x.Low)
+		}
+		buf.WriteByte(':')
+		if x.High != nil {
+			WriteExpr(buf, x.High)
+		}
+		if x.Slice3 {
+			buf.WriteByte(':')
+			if x.Max != nil {
+				WriteExpr(buf, x.Max)
+			}
+		}
+		buf.WriteByte(']')
+
+	case *ast.TypeAssertExpr:
+		WriteExpr(buf, x.X)
+		buf.WriteString(".(")
+		WriteExpr(buf, x.Type)
+		buf.WriteByte(')')
+
+	case *ast.CallExpr:
+		WriteExpr(buf, x.Fun)
+		buf.WriteByte('(')
+		for i, arg := range x.Args {
+			if i > 0 {
+				buf.WriteString(", ")
+			}
+			WriteExpr(buf, arg)
+		}
+		if x.Ellipsis.IsValid() {
+			buf.WriteString("...")
+		}
+		buf.WriteByte(')')
+
+	case *ast.StarExpr:
+		buf.WriteByte('*')
+		WriteExpr(buf, x.X)
+
+	case *ast.UnaryExpr:
+		buf.WriteString(x.Op.String())
+		WriteExpr(buf, x.X)
+
+	case *ast.BinaryExpr:
+		WriteExpr(buf, x.X)
+		buf.WriteByte(' ')
+		buf.WriteString(x.Op.String())
+		buf.WriteByte(' ')
+		WriteExpr(buf, x.Y)
+
+	case *ast.ArrayType:
+		buf.WriteByte('[')
+		if x.Len != nil {
+			WriteExpr(buf, x.Len)
+		}
+		buf.WriteByte(']')
+		WriteExpr(buf, x.Elt)
+
+	case *ast.StructType:
+		buf.WriteString("struct{")
+		writeFieldList(buf, x.Fields, "; ", false)
+		buf.WriteByte('}')
+
+	case *ast.FuncType:
+		buf.WriteString("func")
+		writeSigExpr(buf, x)
+
+	case *ast.InterfaceType:
+		buf.WriteString("interface{")
+		writeFieldList(buf, x.Methods, "; ", true)
+		buf.WriteByte('}')
+
+	case *ast.MapType:
+		buf.WriteString("map[")
+		WriteExpr(buf, x.Key)
+		buf.WriteByte(']')
+		WriteExpr(buf, x.Value)
+
+	case *ast.ChanType:
+		var s string
+		switch x.Dir {
+		case ast.SEND:
+			s = "chan<- "
+		case ast.RECV:
+			s = "<-chan "
+		default:
+			s = "chan "
+		}
+		buf.WriteString(s)
+		WriteExpr(buf, x.Value)
+	}
+}
+
+func writeSigExpr(buf *bytes.Buffer, sig *ast.FuncType) {
+	buf.WriteByte('(')
+	writeFieldList(buf, sig.Params, ", ", false)
+	buf.WriteByte(')')
+
+	res := sig.Results
+	n := res.NumFields()
+	if n == 0 {
+		// no result
+		return
+	}
+
+	buf.WriteByte(' ')
+	if n == 1 && len(res.List[0].Names) == 0 {
+		// single unnamed result
+		WriteExpr(buf, res.List[0].Type)
+		return
+	}
+
+	// multiple or named result(s)
+	buf.WriteByte('(')
+	writeFieldList(buf, res, ", ", false)
+	buf.WriteByte(')')
+}
+
+func writeFieldList(buf *bytes.Buffer, fields *ast.FieldList, sep string, iface bool) {
+	for i, f := range fields.List {
+		if i > 0 {
+			buf.WriteString(sep)
+		}
+
+		// field list names
+		for i, name := range f.Names {
+			if i > 0 {
+				buf.WriteString(", ")
+			}
+			buf.WriteString(name.Name)
+		}
+
+		// types of interface methods consist of signatures only
+		if sig, _ := f.Type.(*ast.FuncType); sig != nil && iface {
+			writeSigExpr(buf, sig)
+			continue
+		}
+
+		// named fields are separated with a blank from the field type
+		if len(f.Names) > 0 {
+			buf.WriteByte(' ')
+		}
+
+		WriteExpr(buf, f.Type)
+
+		// ignore tag
+	}
+}
diff --git a/go/types/exprstring_test.go b/go/types/exprstring_test.go
new file mode 100644
index 0000000..cfd1472
--- /dev/null
+++ b/go/types/exprstring_test.go
@@ -0,0 +1,94 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package types_test
+
+import (
+	"go/parser"
+	"testing"
+
+	. "golang.org/x/tools/go/types"
+)
+
+var testExprs = []testEntry{
+	// basic type literals
+	dup("x"),
+	dup("true"),
+	dup("42"),
+	dup("3.1415"),
+	dup("2.71828i"),
+	dup(`'a'`),
+	dup(`"foo"`),
+	dup("`bar`"),
+
+	// func and composite literals
+	{"func(){}", "(func() literal)"},
+	{"func(x int) complex128 {}", "(func(x int) complex128 literal)"},
+	{"[]int{1, 2, 3}", "([]int literal)"},
+
+	// non-type expressions
+	dup("(x)"),
+	dup("x.f"),
+	dup("a[i]"),
+
+	dup("s[:]"),
+	dup("s[i:]"),
+	dup("s[:j]"),
+	dup("s[i:j]"),
+	dup("s[:j:k]"),
+	dup("s[i:j:k]"),
+
+	dup("x.(T)"),
+
+	dup("x.([10]int)"),
+	dup("x.([...]int)"),
+
+	dup("x.(struct{})"),
+	dup("x.(struct{x int; y, z float32; E})"),
+
+	dup("x.(func())"),
+	dup("x.(func(x int))"),
+	dup("x.(func() int)"),
+	dup("x.(func(x, y int, z float32) (r int))"),
+	dup("x.(func(a, b, c int))"),
+	dup("x.(func(x ...T))"),
+
+	dup("x.(interface{})"),
+	dup("x.(interface{m(); n(x int); E})"),
+	dup("x.(interface{m(); n(x int) T; E; F})"),
+
+	dup("x.(map[K]V)"),
+
+	dup("x.(chan E)"),
+	dup("x.(<-chan E)"),
+	dup("x.(chan<- chan int)"),
+	dup("x.(chan<- <-chan int)"),
+	dup("x.(<-chan chan int)"),
+	dup("x.(chan (<-chan int))"),
+
+	dup("f()"),
+	dup("f(x)"),
+	dup("int(x)"),
+	dup("f(x, x + y)"),
+	dup("f(s...)"),
+	dup("f(a, s...)"),
+
+	dup("*x"),
+	dup("&x"),
+	dup("x + y"),
+	dup("x + y << (2 * s)"),
+}
+
+func TestExprString(t *testing.T) {
+	for _, test := range testExprs {
+		x, err := parser.ParseExpr(test.src)
+		if err != nil {
+			t.Errorf("%s: %s", test.src, err)
+			continue
+		}
+		if got := ExprString(x); got != test.str {
+			t.Errorf("%s: got %s, want %s", test.src, got, test.str)
+		}
+	}
+}
diff --git a/go/types/go11.go b/go/types/go11.go
new file mode 100644
index 0000000..cf41cab
--- /dev/null
+++ b/go/types/go11.go
@@ -0,0 +1,17 @@
+// Copyright 2013 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !go1.2
+
+package types
+
+import "go/ast"
+
+func slice3(x *ast.SliceExpr) bool {
+	return false
+}
+
+func sliceMax(x *ast.SliceExpr) ast.Expr {
+	return nil
+}
diff --git a/go/types/go12.go b/go/types/go12.go
new file mode 100644
index 0000000..2017442
--- /dev/null
+++ b/go/types/go12.go
@@ -0,0 +1,17 @@
+// Copyright 2013 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build go1.2
+
+package types
+
+import "go/ast"
+
+func slice3(x *ast.SliceExpr) bool {
+	return x.Slice3
+}
+
+func sliceMax(x *ast.SliceExpr) ast.Expr {
+	return x.Max
+}
diff --git a/go/types/hilbert_test.go b/go/types/hilbert_test.go
new file mode 100644
index 0000000..b555721
--- /dev/null
+++ b/go/types/hilbert_test.go
@@ -0,0 +1,232 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package types_test
+
+import (
+	"bytes"
+	"flag"
+	"fmt"
+	"go/ast"
+	"go/parser"
+	"go/token"
+	"io/ioutil"
+	"testing"
+
+	. "golang.org/x/tools/go/types"
+)
+
+var (
+	H   = flag.Int("H", 5, "Hilbert matrix size")
+	out = flag.String("out", "", "write generated program to out")
+)
+
+func TestHilbert(t *testing.T) {
+	// generate source
+	src := program(*H, *out)
+	if *out != "" {
+		ioutil.WriteFile(*out, src, 0666)
+		return
+	}
+
+	// parse source
+	fset := token.NewFileSet()
+	f, err := parser.ParseFile(fset, "hilbert.go", src, 0)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	// type-check file
+	DefPredeclaredTestFuncs() // define assert built-in
+	_, err = Check(f.Name.Name, fset, []*ast.File{f})
+	if err != nil {
+		t.Fatal(err)
+	}
+}
+
+func program(n int, out string) []byte {
+	var g gen
+
+	g.p(`// WARNING: GENERATED FILE - DO NOT MODIFY MANUALLY!
+// (To generate, in go/types directory: go test -run=Hilbert -H=%d -out=%q)
+
+// This program tests arbitrary precision constant arithmetic
+// by generating the constant elements of a Hilbert matrix H,
+// its inverse I, and the product P = H*I. The product should
+// be the identity matrix.
+package main
+
+func main() {
+	if !ok {
+		printProduct()
+		return
+	}
+	println("PASS")
+}
+
+`, n, out)
+	g.hilbert(n)
+	g.inverse(n)
+	g.product(n)
+	g.verify(n)
+	g.printProduct(n)
+	g.binomials(2*n - 1)
+	g.factorials(2*n - 1)
+
+	return g.Bytes()
+}
+
+type gen struct {
+	bytes.Buffer
+}
+
+func (g *gen) p(format string, args ...interface{}) {
+	fmt.Fprintf(&g.Buffer, format, args...)
+}
+
+func (g *gen) hilbert(n int) {
+	g.p(`// Hilbert matrix, n = %d
+const (
+`, n)
+	for i := 0; i < n; i++ {
+		g.p("\t")
+		for j := 0; j < n; j++ {
+			if j > 0 {
+				g.p(", ")
+			}
+			g.p("h%d_%d", i, j)
+		}
+		if i == 0 {
+			g.p(" = ")
+			for j := 0; j < n; j++ {
+				if j > 0 {
+					g.p(", ")
+				}
+				g.p("1.0/(iota + %d)", j+1)
+			}
+		}
+		g.p("\n")
+	}
+	g.p(")\n\n")
+}
+
+func (g *gen) inverse(n int) {
+	g.p(`// Inverse Hilbert matrix
+const (
+`)
+	for i := 0; i < n; i++ {
+		for j := 0; j < n; j++ {
+			s := "+"
+			if (i+j)&1 != 0 {
+				s = "-"
+			}
+			g.p("\ti%d_%d = %s%d * b%d_%d * b%d_%d * b%d_%d * b%d_%d\n",
+				i, j, s, i+j+1, n+i, n-j-1, n+j, n-i-1, i+j, i, i+j, i)
+		}
+		g.p("\n")
+	}
+	g.p(")\n\n")
+}
+
+func (g *gen) product(n int) {
+	g.p(`// Product matrix
+const (
+`)
+	for i := 0; i < n; i++ {
+		for j := 0; j < n; j++ {
+			g.p("\tp%d_%d = ", i, j)
+			for k := 0; k < n; k++ {
+				if k > 0 {
+					g.p(" + ")
+				}
+				g.p("h%d_%d*i%d_%d", i, k, k, j)
+			}
+			g.p("\n")
+		}
+		g.p("\n")
+	}
+	g.p(")\n\n")
+}
+
+func (g *gen) verify(n int) {
+	g.p(`// Verify that product is the identity matrix
+const ok =
+`)
+	for i := 0; i < n; i++ {
+		for j := 0; j < n; j++ {
+			if j == 0 {
+				g.p("\t")
+			} else {
+				g.p(" && ")
+			}
+			v := 0
+			if i == j {
+				v = 1
+			}
+			g.p("p%d_%d == %d", i, j, v)
+		}
+		g.p(" &&\n")
+	}
+	g.p("\ttrue\n\n")
+
+	// verify ok at type-check time
+	if *out == "" {
+		g.p("const _ = assert(ok)\n\n")
+	}
+}
+
+func (g *gen) printProduct(n int) {
+	g.p("func printProduct() {\n")
+	for i := 0; i < n; i++ {
+		g.p("\tprintln(")
+		for j := 0; j < n; j++ {
+			if j > 0 {
+				g.p(", ")
+			}
+			g.p("p%d_%d", i, j)
+		}
+		g.p(")\n")
+	}
+	g.p("}\n\n")
+}
+
+func (g *gen) mulRange(a, b int) {
+	if a > b {
+		g.p("1")
+		return
+	}
+	for i := a; i <= b; i++ {
+		if i > a {
+			g.p("*")
+		}
+		g.p("%d", i)
+	}
+}
+
+func (g *gen) binomials(n int) {
+	g.p(`// Binomials
+const (
+`)
+	for j := 0; j <= n; j++ {
+		if j > 0 {
+			g.p("\n")
+		}
+		for k := 0; k <= j; k++ {
+			g.p("\tb%d_%d = f%d / (f%d*f%d)\n", j, k, j, k, j-k)
+		}
+	}
+	g.p(")\n\n")
+}
+
+func (g *gen) factorials(n int) {
+	g.p(`// Factorials
+const (
+	f0 = 1
+	f1 = 1
+`)
+	for i := 2; i <= n; i++ {
+		g.p("\tf%d = f%d * %d\n", i, i-1, i)
+	}
+	g.p(")\n\n")
+}
diff --git a/go/types/initorder.go b/go/types/initorder.go
new file mode 100644
index 0000000..0fd567b
--- /dev/null
+++ b/go/types/initorder.go
@@ -0,0 +1,222 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package types
+
+import (
+	"container/heap"
+	"fmt"
+)
+
+// initOrder computes the Info.InitOrder for package variables.
+func (check *Checker) initOrder() {
+	// An InitOrder may already have been computed if a package is
+	// built from several calls to (*Checker).Files.  Clear it.
+	check.Info.InitOrder = check.Info.InitOrder[:0]
+
+	// compute the object dependency graph and
+	// initialize a priority queue with the list
+	// of graph nodes
+	pq := nodeQueue(dependencyGraph(check.objMap))
+	heap.Init(&pq)
+
+	const debug = false
+	if debug {
+		fmt.Printf("package %s: object dependency graph\n", check.pkg.Name())
+		for _, n := range pq {
+			for _, o := range n.out {
+				fmt.Printf("\t%s -> %s\n", n.obj.Name(), o.obj.Name())
+			}
+		}
+		fmt.Println()
+		fmt.Printf("package %s: initialization order\n", check.pkg.Name())
+	}
+
+	// determine initialization order by removing the highest priority node
+	// (the one with the fewest dependencies) and its edges from the graph,
+	// repeatedly, until there are no nodes left.
+	// In a valid Go program, those nodes always have zero dependencies (after
+	// removing all incoming dependencies), otherwise there are initialization
+	// cycles.
+	mark := 0
+	emitted := make(map[*declInfo]bool)
+	for len(pq) > 0 {
+		// get the next node
+		n := heap.Pop(&pq).(*objNode)
+
+		// if n still depends on other nodes, we have a cycle
+		if n.in > 0 {
+			mark++ // mark nodes using a different value each time
+			cycle := findPath(n, n, mark)
+			if i := valIndex(cycle); i >= 0 {
+				check.reportCycle(cycle, i)
+			}
+			// ok to continue, but the variable initialization order
+			// will be incorrect at this point since it assumes no
+			// cycle errors
+		}
+
+		// reduce dependency count of all dependent nodes
+		// and update priority queue
+		for _, out := range n.out {
+			out.in--
+			heap.Fix(&pq, out.index)
+		}
+
+		// record the init order for variables with initializers only
+		v, _ := n.obj.(*Var)
+		info := check.objMap[v]
+		if v == nil || !info.hasInitializer() {
+			continue
+		}
+
+		// n:1 variable declarations such as: a, b = f()
+		// introduce a node for each lhs variable (here: a, b);
+		// but they all have the same initializer - emit only
+		// one, for the first variable seen
+		if emitted[info] {
+			continue // initializer already emitted, if any
+		}
+		emitted[info] = true
+
+		infoLhs := info.lhs // possibly nil (see declInfo.lhs field comment)
+		if infoLhs == nil {
+			infoLhs = []*Var{v}
+		}
+		init := &Initializer{infoLhs, info.init}
+		check.Info.InitOrder = append(check.Info.InitOrder, init)
+
+		if debug {
+			fmt.Printf("\t%s\n", init)
+		}
+	}
+
+	if debug {
+		fmt.Println()
+	}
+}
+
+// findPath returns the (reversed) list of nodes z, ... c, b, a,
+// such that there is a path (list of edges) from a to z.
+// If there is no such path, the result is nil.
+// Nodes marked with the value mark are considered "visited";
+// unvisited nodes are marked during the graph search.
+func findPath(a, z *objNode, mark int) []*objNode {
+	if a.mark == mark {
+		return nil // node already seen
+	}
+	a.mark = mark
+
+	for _, n := range a.out {
+		if n == z {
+			return []*objNode{z}
+		}
+		if P := findPath(n, z, mark); P != nil {
+			return append(P, n)
+		}
+	}
+
+	return nil
+}
+
+// valIndex returns the index of the first constant or variable in a,
+// if any; or a value < 0.
+func valIndex(a []*objNode) int {
+	for i, n := range a {
+		switch n.obj.(type) {
+		case *Const, *Var:
+			return i
+		}
+	}
+	return -1
+}
+
+// reportCycle reports an error for the cycle starting at i.
+func (check *Checker) reportCycle(cycle []*objNode, i int) {
+	obj := cycle[i].obj
+	check.errorf(obj.Pos(), "initialization cycle for %s", obj.Name())
+	// print cycle
+	for _ = range cycle {
+		check.errorf(obj.Pos(), "\t%s refers to", obj.Name()) // secondary error, \t indented
+		i++
+		if i >= len(cycle) {
+			i = 0
+		}
+		obj = cycle[i].obj
+	}
+	check.errorf(obj.Pos(), "\t%s", obj.Name())
+}
+
+// An objNode represents a node in the object dependency graph.
+// Each node b in a.out represents an edge a->b indicating that
+// b depends on a.
+// Nodes may be marked for cycle detection. A node n is marked
+// if n.mark corresponds to the current mark value.
+type objNode struct {
+	obj   Object     // object represented by this node
+	in    int        // number of nodes this node depends on
+	out   []*objNode // list of nodes that depend on this node
+	index int        // node index in list of nodes
+	mark  int        // for cycle detection
+}
+
+// dependencyGraph computes the transposed object dependency graph
+// from the given objMap. The transposed graph is returned as a list
+// of nodes; an edge d->n indicates that node n depends on node d.
+func dependencyGraph(objMap map[Object]*declInfo) []*objNode {
+	// M maps each object to its corresponding node
+	M := make(map[Object]*objNode, len(objMap))
+	for obj := range objMap {
+		M[obj] = &objNode{obj: obj}
+	}
+
+	// G is the graph of nodes n
+	G := make([]*objNode, len(M))
+	i := 0
+	for obj, n := range M {
+		deps := objMap[obj].deps
+		n.in = len(deps)
+		for d := range deps {
+			d := M[d]                // node n depends on node d
+			d.out = append(d.out, n) // add edge d->n
+		}
+
+		G[i] = n
+		n.index = i
+		i++
+	}
+
+	return G
+}
+
+// nodeQueue implements the container/heap interface;
+// a nodeQueue may be used as a priority queue.
+type nodeQueue []*objNode
+
+func (a nodeQueue) Len() int { return len(a) }
+
+func (a nodeQueue) Swap(i, j int) {
+	x, y := a[i], a[j]
+	a[i], a[j] = y, x
+	x.index, y.index = j, i
+}
+
+func (a nodeQueue) Less(i, j int) bool {
+	x, y := a[i], a[j]
+	// nodes are prioritized by number of incoming dependencies (1st key)
+	// and source order (2nd key)
+	return x.in < y.in || x.in == y.in && x.obj.order() < y.obj.order()
+}
+
+func (a *nodeQueue) Push(x interface{}) {
+	panic("unreachable")
+}
+
+func (a *nodeQueue) Pop() interface{} {
+	n := len(*a)
+	x := (*a)[n-1]
+	x.index = -1 // for safety
+	*a = (*a)[:n-1]
+	return x
+}
diff --git a/go/types/issues_test.go b/go/types/issues_test.go
new file mode 100644
index 0000000..04d8b37
--- /dev/null
+++ b/go/types/issues_test.go
@@ -0,0 +1,205 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file implements tests for various issues.
+
+package types_test
+
+import (
+	"fmt"
+	"go/ast"
+	"go/parser"
+	"sort"
+	"strings"
+	"testing"
+
+	_ "golang.org/x/tools/go/gcimporter"
+	. "golang.org/x/tools/go/types"
+)
+
+func TestIssue5770(t *testing.T) {
+	src := `package p; type S struct{T}`
+	f, err := parser.ParseFile(fset, "", src, 0)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	_, err = Check(f.Name.Name, fset, []*ast.File{f}) // do not crash
+	want := "undeclared name: T"
+	if err == nil || !strings.Contains(err.Error(), want) {
+		t.Errorf("got: %v; want: %s", err, want)
+	}
+}
+
+func TestIssue5849(t *testing.T) {
+	src := `
+package p
+var (
+	s uint
+	_ = uint8(8)
+	_ = uint16(16) << s
+	_ = uint32(32 << s)
+	_ = uint64(64 << s + s)
+	_ = (interface{})("foo")
+	_ = (interface{})(nil)
+)`
+	f, err := parser.ParseFile(fset, "", src, 0)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	var conf Config
+	types := make(map[ast.Expr]TypeAndValue)
+	_, err = conf.Check(f.Name.Name, fset, []*ast.File{f}, &Info{Types: types})
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	for x, tv := range types {
+		var want Type
+		switch x := x.(type) {
+		case *ast.BasicLit:
+			switch x.Value {
+			case `8`:
+				want = Typ[Uint8]
+			case `16`:
+				want = Typ[Uint16]
+			case `32`:
+				want = Typ[Uint32]
+			case `64`:
+				want = Typ[Uint] // because of "+ s", s is of type uint
+			case `"foo"`:
+				want = Typ[String]
+			}
+		case *ast.Ident:
+			if x.Name == "nil" {
+				want = Typ[UntypedNil]
+			}
+		}
+		if want != nil && !Identical(tv.Type, want) {
+			t.Errorf("got %s; want %s", tv.Type, want)
+		}
+	}
+}
+
+func TestIssue6413(t *testing.T) {
+	src := `
+package p
+func f() int {
+	defer f()
+	go f()
+	return 0
+}
+`
+	f, err := parser.ParseFile(fset, "", src, 0)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	var conf Config
+	types := make(map[ast.Expr]TypeAndValue)
+	_, err = conf.Check(f.Name.Name, fset, []*ast.File{f}, &Info{Types: types})
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	want := Typ[Int]
+	n := 0
+	for x, tv := range types {
+		if _, ok := x.(*ast.CallExpr); ok {
+			if tv.Type != want {
+				t.Errorf("%s: got %s; want %s", fset.Position(x.Pos()), tv.Type, want)
+			}
+			n++
+		}
+	}
+
+	if n != 2 {
+		t.Errorf("got %d CallExprs; want 2", n)
+	}
+}
+
+func TestIssue7245(t *testing.T) {
+	src := `
+package p
+func (T) m() (res bool) { return }
+type T struct{} // receiver type after method declaration
+`
+	f, err := parser.ParseFile(fset, "", src, 0)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	var conf Config
+	defs := make(map[*ast.Ident]Object)
+	_, err = conf.Check(f.Name.Name, fset, []*ast.File{f}, &Info{Defs: defs})
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	m := f.Decls[0].(*ast.FuncDecl)
+	res1 := defs[m.Name].(*Func).Type().(*Signature).Results().At(0)
+	res2 := defs[m.Type.Results.List[0].Names[0]].(*Var)
+
+	if res1 != res2 {
+		t.Errorf("got %s (%p) != %s (%p)", res1, res2, res1, res2)
+	}
+}
+
+// This tests that uses of existing vars on the LHS of an assignment
+// are Uses, not Defs; and also that the (illegal) use of a non-var on
+// the LHS of an assignment is a Use nonetheless.
+func TestIssue7827(t *testing.T) {
+	const src = `
+package p
+func _() {
+	const w = 1        // defs w
+        x, y := 2, 3       // defs x, y
+        w, x, z := 4, 5, 6 // uses w, x, defs z; error: cannot assign to w
+        _, _, _ = x, y, z  // uses x, y, z
+}
+`
+	const want = `L3 defs func p._()
+L4 defs const w untyped int
+L5 defs var x int
+L5 defs var y int
+L6 defs var z int
+L6 uses const w untyped int
+L6 uses var x int
+L7 uses var x int
+L7 uses var y int
+L7 uses var z int`
+
+	f, err := parser.ParseFile(fset, "", src, 0)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	// don't abort at the first error
+	conf := Config{Error: func(err error) { t.Log(err) }}
+	defs := make(map[*ast.Ident]Object)
+	uses := make(map[*ast.Ident]Object)
+	_, err = conf.Check(f.Name.Name, fset, []*ast.File{f}, &Info{Defs: defs, Uses: uses})
+	if s := fmt.Sprint(err); !strings.HasSuffix(s, "cannot assign to w") {
+		t.Errorf("Check: unexpected error: %s", s)
+	}
+
+	var facts []string
+	for id, obj := range defs {
+		if obj != nil {
+			fact := fmt.Sprintf("L%d defs %s", fset.Position(id.Pos()).Line, obj)
+			facts = append(facts, fact)
+		}
+	}
+	for id, obj := range uses {
+		fact := fmt.Sprintf("L%d uses %s", fset.Position(id.Pos()).Line, obj)
+		facts = append(facts, fact)
+	}
+	sort.Strings(facts)
+
+	got := strings.Join(facts, "\n")
+	if got != want {
+		t.Errorf("Unexpected defs/uses\ngot:\n%s\nwant:\n%s", got, want)
+	}
+}
diff --git a/go/types/labels.go b/go/types/labels.go
new file mode 100644
index 0000000..7364d4d
--- /dev/null
+++ b/go/types/labels.go
@@ -0,0 +1,268 @@
+// Copyright 2013 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package types
+
+import (
+	"go/ast"
+	"go/token"
+)
+
+// labels checks correct label use in body.
+func (check *Checker) labels(body *ast.BlockStmt) {
+	// set of all labels in this body
+	all := NewScope(nil, body.Pos(), body.End(), "label")
+
+	fwdJumps := check.blockBranches(all, nil, nil, body.List)
+
+	// If there are any forward jumps left, no label was found for
+	// the corresponding goto statements. Either those labels were
+	// never defined, or they are inside blocks and not reachable
+	// for the respective gotos.
+	for _, jmp := range fwdJumps {
+		var msg string
+		name := jmp.Label.Name
+		if alt := all.Lookup(name); alt != nil {
+			msg = "goto %s jumps into block"
+			alt.(*Label).used = true // avoid another error
+		} else {
+			msg = "label %s not declared"
+		}
+		check.errorf(jmp.Label.Pos(), msg, name)
+	}
+
+	// spec: "It is illegal to define a label that is never used."
+	for _, obj := range all.elems {
+		if lbl := obj.(*Label); !lbl.used {
+			check.softErrorf(lbl.pos, "label %s declared but not used", lbl.name)
+		}
+	}
+}
+
+// A block tracks label declarations in a block and its enclosing blocks.
+type block struct {
+	parent *block                      // enclosing block
+	lstmt  *ast.LabeledStmt            // labeled statement to which this block belongs, or nil
+	labels map[string]*ast.LabeledStmt // allocated lazily
+}
+
+// insert records a new label declaration for the current block.
+// The label must not have been declared before in any block.
+func (b *block) insert(s *ast.LabeledStmt) {
+	name := s.Label.Name
+	if debug {
+		assert(b.gotoTarget(name) == nil)
+	}
+	labels := b.labels
+	if labels == nil {
+		labels = make(map[string]*ast.LabeledStmt)
+		b.labels = labels
+	}
+	labels[name] = s
+}
+
+// gotoTarget returns the labeled statement in the current
+// or an enclosing block with the given label name, or nil.
+func (b *block) gotoTarget(name string) *ast.LabeledStmt {
+	for s := b; s != nil; s = s.parent {
+		if t := s.labels[name]; t != nil {
+			return t
+		}
+	}
+	return nil
+}
+
+// enclosingTarget returns the innermost enclosing labeled
+// statement with the given label name, or nil.
+func (b *block) enclosingTarget(name string) *ast.LabeledStmt {
+	for s := b; s != nil; s = s.parent {
+		if t := s.lstmt; t != nil && t.Label.Name == name {
+			return t
+		}
+	}
+	return nil
+}
+
+// blockBranches processes a block's statement list and returns the set of outgoing forward jumps.
+// all is the scope of all declared labels, parent the set of labels declared in the immediately
+// enclosing block, and lstmt is the labeled statement this block is associated with (or nil).
+func (check *Checker) blockBranches(all *Scope, parent *block, lstmt *ast.LabeledStmt, list []ast.Stmt) []*ast.BranchStmt {
+	b := &block{parent: parent, lstmt: lstmt}
+
+	var (
+		varDeclPos         token.Pos
+		fwdJumps, badJumps []*ast.BranchStmt
+	)
+
+	// All forward jumps jumping over a variable declaration are possibly
+	// invalid (they may still jump out of the block and be ok).
+	// recordVarDecl records them for the given position.
+	recordVarDecl := func(pos token.Pos) {
+		varDeclPos = pos
+		badJumps = append(badJumps[:0], fwdJumps...) // copy fwdJumps to badJumps
+	}
+
+	jumpsOverVarDecl := func(jmp *ast.BranchStmt) bool {
+		if varDeclPos.IsValid() {
+			for _, bad := range badJumps {
+				if jmp == bad {
+					return true
+				}
+			}
+		}
+		return false
+	}
+
+	blockBranches := func(lstmt *ast.LabeledStmt, list []ast.Stmt) {
+		// Unresolved forward jumps inside the nested block
+		// become forward jumps in the current block.
+		fwdJumps = append(fwdJumps, check.blockBranches(all, b, lstmt, list)...)
+	}
+
+	var stmtBranches func(ast.Stmt)
+	stmtBranches = func(s ast.Stmt) {
+		switch s := s.(type) {
+		case *ast.DeclStmt:
+			if d, _ := s.Decl.(*ast.GenDecl); d != nil && d.Tok == token.VAR {
+				recordVarDecl(d.Pos())
+			}
+
+		case *ast.LabeledStmt:
+			// declare non-blank label
+			if name := s.Label.Name; name != "_" {
+				lbl := NewLabel(s.Label.Pos(), check.pkg, name)
+				if alt := all.Insert(lbl); alt != nil {
+					check.softErrorf(lbl.pos, "label %s already declared", name)
+					check.reportAltDecl(alt)
+					// ok to continue
+				} else {
+					b.insert(s)
+					check.recordDef(s.Label, lbl)
+				}
+				// resolve matching forward jumps and remove them from fwdJumps
+				i := 0
+				for _, jmp := range fwdJumps {
+					if jmp.Label.Name == name {
+						// match
+						lbl.used = true
+						check.recordUse(jmp.Label, lbl)
+						if jumpsOverVarDecl(jmp) {
+							check.softErrorf(
+								jmp.Label.Pos(),
+								"goto %s jumps over variable declaration at line %d",
+								name,
+								check.fset.Position(varDeclPos).Line,
+							)
+							// ok to continue
+						}
+					} else {
+						// no match - record new forward jump
+						fwdJumps[i] = jmp
+						i++
+					}
+				}
+				fwdJumps = fwdJumps[:i]
+				lstmt = s
+			}
+			stmtBranches(s.Stmt)
+
+		case *ast.BranchStmt:
+			if s.Label == nil {
+				return // checked in 1st pass (check.stmt)
+			}
+
+			// determine and validate target
+			name := s.Label.Name
+			switch s.Tok {
+			case token.BREAK:
+				// spec: "If there is a label, it must be that of an enclosing
+				// "for", "switch", or "select" statement, and that is the one
+				// whose execution terminates."
+				valid := false
+				if t := b.enclosingTarget(name); t != nil {
+					switch t.Stmt.(type) {
+					case *ast.SwitchStmt, *ast.TypeSwitchStmt, *ast.SelectStmt, *ast.ForStmt, *ast.RangeStmt:
+						valid = true
+					}
+				}
+				if !valid {
+					check.errorf(s.Label.Pos(), "invalid break label %s", name)
+					return
+				}
+
+			case token.CONTINUE:
+				// spec: "If there is a label, it must be that of an enclosing
+				// "for" statement, and that is the one whose execution advances."
+				valid := false
+				if t := b.enclosingTarget(name); t != nil {
+					switch t.Stmt.(type) {
+					case *ast.ForStmt, *ast.RangeStmt:
+						valid = true
+					}
+				}
+				if !valid {
+					check.errorf(s.Label.Pos(), "invalid continue label %s", name)
+					return
+				}
+
+			case token.GOTO:
+				if b.gotoTarget(name) == nil {
+					// label may be declared later - add branch to forward jumps
+					fwdJumps = append(fwdJumps, s)
+					return
+				}
+
+			default:
+				check.invalidAST(s.Pos(), "branch statement: %s %s", s.Tok, name)
+				return
+			}
+
+			// record label use
+			obj := all.Lookup(name)
+			obj.(*Label).used = true
+			check.recordUse(s.Label, obj)
+
+		case *ast.AssignStmt:
+			if s.Tok == token.DEFINE {
+				recordVarDecl(s.Pos())
+			}
+
+		case *ast.BlockStmt:
+			blockBranches(lstmt, s.List)
+
+		case *ast.IfStmt:
+			stmtBranches(s.Body)
+			if s.Else != nil {
+				stmtBranches(s.Else)
+			}
+
+		case *ast.CaseClause:
+			blockBranches(nil, s.Body)
+
+		case *ast.SwitchStmt:
+			stmtBranches(s.Body)
+
+		case *ast.TypeSwitchStmt:
+			stmtBranches(s.Body)
+
+		case *ast.CommClause:
+			blockBranches(nil, s.Body)
+
+		case *ast.SelectStmt:
+			stmtBranches(s.Body)
+
+		case *ast.ForStmt:
+			stmtBranches(s.Body)
+
+		case *ast.RangeStmt:
+			stmtBranches(s.Body)
+		}
+	}
+
+	for _, s := range list {
+		stmtBranches(s)
+	}
+
+	return fwdJumps
+}
diff --git a/go/types/lookup.go b/go/types/lookup.go
new file mode 100644
index 0000000..3caca55
--- /dev/null
+++ b/go/types/lookup.go
@@ -0,0 +1,341 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file implements various field and method lookup functions.
+
+package types
+
+// LookupFieldOrMethod looks up a field or method with given package and name
+// in T and returns the corresponding *Var or *Func, an index sequence, and a
+// bool indicating if there were any pointer indirections on the path to the
+// field or method. If addressable is set, T is the type of an addressable
+// variable (only matters for method lookups).
+//
+// The last index entry is the field or method index in the (possibly embedded)
+// type where the entry was found, either:
+//
+//	1) the list of declared methods of a named type; or
+//	2) the list of all methods (method set) of an interface type; or
+//	3) the list of fields of a struct type.
+//
+// The earlier index entries are the indices of the anonymous struct fields
+// traversed to get to the found entry, starting at depth 0.
+//
+// If no entry is found, a nil object is returned. In this case, the returned
+// index and indirect values have the following meaning:
+//
+//	- If index != nil, the index sequence points to an ambiguous entry
+//	(the same name appeared more than once at the same embedding level).
+//
+//	- If indirect is set, a method with a pointer receiver type was found
+//      but there was no pointer on the path from the actual receiver type to
+//	the method's formal receiver base type, nor was the receiver addressable.
+//
+func LookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string) (obj Object, index []int, indirect bool) {
+	// Methods cannot be associated to a named pointer type
+	// (spec: "The type denoted by T is called the receiver base type;
+	// it must not be a pointer or interface type and it must be declared
+	// in the same package as the method.").
+	// Thus, if we have a named pointer type, proceed with the underlying
+	// pointer type but discard the result if it is a method since we would
+	// not have found it for T (see also issue 8590).
+	if t, _ := T.(*Named); t != nil {
+		if p, _ := t.underlying.(*Pointer); p != nil {
+			obj, index, indirect = lookupFieldOrMethod(p, false, pkg, name)
+			if _, ok := obj.(*Func); ok {
+				return nil, nil, false
+			}
+			return
+		}
+	}
+
+	return lookupFieldOrMethod(T, addressable, pkg, name)
+}
+
+// TODO(gri) The named type consolidation and seen maps below must be
+//           indexed by unique keys for a given type. Verify that named
+//           types always have only one representation (even when imported
+//           indirectly via different packages.)
+
+func lookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string) (obj Object, index []int, indirect bool) {
+	// WARNING: The code in this function is extremely subtle - do not modify casually!
+	//          This function and NewMethodSet should be kept in sync.
+
+	if name == "_" {
+		return // blank fields/methods are never found
+	}
+
+	typ, isPtr := deref(T)
+	named, _ := typ.(*Named)
+
+	// *typ where typ is an interface has no methods.
+	if isPtr {
+		utyp := typ
+		if named != nil {
+			utyp = named.underlying
+		}
+		if _, ok := utyp.(*Interface); ok {
+			return
+		}
+	}
+
+	// Start with typ as single entry at shallowest depth.
+	// If typ is not a named type, insert a nil type instead.
+	current := []embeddedType{{named, nil, isPtr, false}}
+
+	// named types that we have seen already, allocated lazily
+	var seen map[*Named]bool
+
+	// search current depth
+	for len(current) > 0 {
+		var next []embeddedType // embedded types found at current depth
+
+		// look for (pkg, name) in all types at current depth
+		for _, e := range current {
+			// The very first time only, e.typ may be nil.
+			// In this case, we don't have a named type and
+			// we simply continue with the underlying type.
+			if e.typ != nil {
+				if seen[e.typ] {
+					// We have seen this type before, at a more shallow depth
+					// (note that multiples of this type at the current depth
+					// were consolidated before). The type at that depth shadows
+					// this same type at the current depth, so we can ignore
+					// this one.
+					continue
+				}
+				if seen == nil {
+					seen = make(map[*Named]bool)
+				}
+				seen[e.typ] = true
+
+				// look for a matching attached method
+				if i, m := lookupMethod(e.typ.methods, pkg, name); m != nil {
+					// potential match
+					assert(m.typ != nil)
+					index = concat(e.index, i)
+					if obj != nil || e.multiples {
+						return nil, index, false // collision
+					}
+					obj = m
+					indirect = e.indirect
+					continue // we can't have a matching field or interface method
+				}
+
+				// continue with underlying type
+				typ = e.typ.underlying
+			}
+
+			switch t := typ.(type) {
+			case *Struct:
+				// look for a matching field and collect embedded types
+				for i, f := range t.fields {
+					if f.sameId(pkg, name) {
+						assert(f.typ != nil)
+						index = concat(e.index, i)
+						if obj != nil || e.multiples {
+							return nil, index, false // collision
+						}
+						obj = f
+						indirect = e.indirect
+						continue // we can't have a matching interface method
+					}
+					// Collect embedded struct fields for searching the next
+					// lower depth, but only if we have not seen a match yet
+					// (if we have a match it is either the desired field or
+					// we have a name collision on the same depth; in either
+					// case we don't need to look further).
+					// Embedded fields are always of the form T or *T where
+					// T is a named type. If e.typ appeared multiple times at
+					// this depth, f.typ appears multiple times at the next
+					// depth.
+					if obj == nil && f.anonymous {
+						// Ignore embedded basic types - only user-defined
+						// named types can have methods or struct fields.
+						typ, isPtr := deref(f.typ)
+						if t, _ := typ.(*Named); t != nil {
+							next = append(next, embeddedType{t, concat(e.index, i), e.indirect || isPtr, e.multiples})
+						}
+					}
+				}
+
+			case *Interface:
+				// look for a matching method
+				// TODO(gri) t.allMethods is sorted - use binary search
+				if i, m := lookupMethod(t.allMethods, pkg, name); m != nil {
+					assert(m.typ != nil)
+					index = concat(e.index, i)
+					if obj != nil || e.multiples {
+						return nil, index, false // collision
+					}
+					obj = m
+					indirect = e.indirect
+				}
+			}
+		}
+
+		if obj != nil {
+			// found a potential match
+			// spec: "A method call x.m() is valid if the method set of (the type of) x
+			//        contains m and the argument list can be assigned to the parameter
+			//        list of m. If x is addressable and &x's method set contains m, x.m()
+			//        is shorthand for (&x).m()".
+			if f, _ := obj.(*Func); f != nil && ptrRecv(f) && !indirect && !addressable {
+				return nil, nil, true // pointer/addressable receiver required
+			}
+			return
+		}
+
+		current = consolidateMultiples(next)
+	}
+
+	return nil, nil, false // not found
+}
+
+// embeddedType represents an embedded named type
+type embeddedType struct {
+	typ       *Named // nil means use the outer typ variable instead
+	index     []int  // embedded field indices, starting with index at depth 0
+	indirect  bool   // if set, there was a pointer indirection on the path to this field
+	multiples bool   // if set, typ appears multiple times at this depth
+}
+
+// consolidateMultiples collects multiple list entries with the same type
+// into a single entry marked as containing multiples. The result is the
+// consolidated list.
+func consolidateMultiples(list []embeddedType) []embeddedType {
+	if len(list) <= 1 {
+		return list // at most one entry - nothing to do
+	}
+
+	n := 0                       // number of entries w/ unique type
+	prev := make(map[*Named]int) // index at which type was previously seen
+	for _, e := range list {
+		if i, found := prev[e.typ]; found {
+			list[i].multiples = true
+			// ignore this entry
+		} else {
+			prev[e.typ] = n
+			list[n] = e
+			n++
+		}
+	}
+	return list[:n]
+}
+
+// MissingMethod returns (nil, false) if V implements T, otherwise it
+// returns a missing method required by T and whether it is missing or
+// just has the wrong type.
+//
+// For non-interface types V, or if static is set, V implements T if all
+// methods of T are present in V. Otherwise (V is an interface and static
+// is not set), MissingMethod only checks that methods of T which are also
+// present in V have matching types (e.g., for a type assertion x.(T) where
+// x is of interface type V).
+//
+func MissingMethod(V Type, T *Interface, static bool) (method *Func, wrongType bool) {
+	// fast path for common case
+	if T.Empty() {
+		return
+	}
+
+	// TODO(gri) Consider using method sets here. Might be more efficient.
+
+	if ityp, _ := V.Underlying().(*Interface); ityp != nil {
+		// TODO(gri) allMethods is sorted - can do this more efficiently
+		for _, m := range T.allMethods {
+			_, obj := lookupMethod(ityp.allMethods, m.pkg, m.name)
+			switch {
+			case obj == nil:
+				if static {
+					return m, false
+				}
+			case !Identical(obj.Type(), m.typ):
+				return m, true
+			}
+		}
+		return
+	}
+
+	// A concrete type implements T if it implements all methods of T.
+	for _, m := range T.allMethods {
+		obj, _, _ := lookupFieldOrMethod(V, false, m.pkg, m.name)
+
+		f, _ := obj.(*Func)
+		if f == nil {
+			return m, false
+		}
+
+		if !Identical(f.typ, m.typ) {
+			return m, true
+		}
+	}
+
+	return
+}
+
+// assertableTo reports whether a value of type V can be asserted to have type T.
+// It returns (nil, false) as affirmative answer. Otherwise it returns a missing
+// method required by V and whether it is missing or just has the wrong type.
+func assertableTo(V *Interface, T Type) (method *Func, wrongType bool) {
+	// no static check is required if T is an interface
+	// spec: "If T is an interface type, x.(T) asserts that the
+	//        dynamic type of x implements the interface T."
+	if _, ok := T.Underlying().(*Interface); ok && !strict {
+		return
+	}
+	return MissingMethod(T, V, false)
+}
+
+// deref dereferences typ if it is a *Pointer and returns its base and true.
+// Otherwise it returns (typ, false).
+func deref(typ Type) (Type, bool) {
+	if p, _ := typ.(*Pointer); p != nil {
+		return p.base, true
+	}
+	return typ, false
+}
+
+// derefStructPtr dereferences typ if it is a (named or unnamed) pointer to a
+// (named or unnamed) struct and returns its base. Otherwise it returns typ.
+func derefStructPtr(typ Type) Type {
+	if p, _ := typ.Underlying().(*Pointer); p != nil {
+		if _, ok := p.base.Underlying().(*Struct); ok {
+			return p.base
+		}
+	}
+	return typ
+}
+
+// concat returns the result of concatenating list and i.
+// The result does not share its underlying array with list.
+func concat(list []int, i int) []int {
+	var t []int
+	t = append(t, list...)
+	return append(t, i)
+}
+
+// fieldIndex returns the index for the field with matching package and name, or a value < 0.
+func fieldIndex(fields []*Var, pkg *Package, name string) int {
+	if name != "_" {
+		for i, f := range fields {
+			if f.sameId(pkg, name) {
+				return i
+			}
+		}
+	}
+	return -1
+}
+
+// lookupMethod returns the index of and method with matching package and name, or (-1, nil).
+func lookupMethod(methods []*Func, pkg *Package, name string) (int, *Func) {
+	if name != "_" {
+		for i, m := range methods {
+			if m.sameId(pkg, name) {
+				return i, m
+			}
+		}
+	}
+	return -1, nil
+}
diff --git a/go/types/methodset.go b/go/types/methodset.go
new file mode 100644
index 0000000..8aff6f9
--- /dev/null
+++ b/go/types/methodset.go
@@ -0,0 +1,271 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file implements method sets.
+
+package types
+
+import (
+	"bytes"
+	"fmt"
+	"sort"
+)
+
+// A MethodSet is an ordered set of concrete or abstract (interface) methods;
+// a method is a MethodVal selection, and they are ordered by ascending m.Obj().Id().
+// The zero value for a MethodSet is a ready-to-use empty method set.
+type MethodSet struct {
+	list []*Selection
+}
+
+func (s *MethodSet) String() string {
+	if s.Len() == 0 {
+		return "MethodSet {}"
+	}
+
+	var buf bytes.Buffer
+	fmt.Fprintln(&buf, "MethodSet {")
+	for _, f := range s.list {
+		fmt.Fprintf(&buf, "\t%s\n", f)
+	}
+	fmt.Fprintln(&buf, "}")
+	return buf.String()
+}
+
+// Len returns the number of methods in s.
+func (s *MethodSet) Len() int { return len(s.list) }
+
+// At returns the i'th method in s for 0 <= i < s.Len().
+func (s *MethodSet) At(i int) *Selection { return s.list[i] }
+
+// Lookup returns the method with matching package and name, or nil if not found.
+func (s *MethodSet) Lookup(pkg *Package, name string) *Selection {
+	if s.Len() == 0 {
+		return nil
+	}
+
+	key := Id(pkg, name)
+	i := sort.Search(len(s.list), func(i int) bool {
+		m := s.list[i]
+		return m.obj.Id() >= key
+	})
+	if i < len(s.list) {
+		m := s.list[i]
+		if m.obj.Id() == key {
+			return m
+		}
+	}
+	return nil
+}
+
+// Shared empty method set.
+var emptyMethodSet MethodSet
+
+// NewMethodSet returns the method set for the given type T.  It
+// always returns a non-nil method set, even if it is empty.
+//
+// A MethodSetCache handles repeat queries more efficiently.
+//
+func NewMethodSet(T Type) *MethodSet {
+	// WARNING: The code in this function is extremely subtle - do not modify casually!
+	//          This function and lookupFieldOrMethod should be kept in sync.
+
+	// method set up to the current depth, allocated lazily
+	var base methodSet
+
+	typ, isPtr := deref(T)
+	named, _ := typ.(*Named)
+
+	// *typ where typ is an interface has no methods.
+	if isPtr {
+		utyp := typ
+		if named != nil {
+			utyp = named.underlying
+		}
+		if _, ok := utyp.(*Interface); ok {
+			return &emptyMethodSet
+		}
+	}
+
+	// Start with typ as single entry at shallowest depth.
+	// If typ is not a named type, insert a nil type instead.
+	current := []embeddedType{{named, nil, isPtr, false}}
+
+	// named types that we have seen already, allocated lazily
+	var seen map[*Named]bool
+
+	// collect methods at current depth
+	for len(current) > 0 {
+		var next []embeddedType // embedded types found at current depth
+
+		// field and method sets at current depth, allocated lazily
+		var fset fieldSet
+		var mset methodSet
+
+		for _, e := range current {
+			// The very first time only, e.typ may be nil.
+			// In this case, we don't have a named type and
+			// we simply continue with the underlying type.
+			if e.typ != nil {
+				if seen[e.typ] {
+					// We have seen this type before, at a more shallow depth
+					// (note that multiples of this type at the current depth
+					// were consolidated before). The type at that depth shadows
+					// this same type at the current depth, so we can ignore
+					// this one.
+					continue
+				}
+				if seen == nil {
+					seen = make(map[*Named]bool)
+				}
+				seen[e.typ] = true
+
+				mset = mset.add(e.typ.methods, e.index, e.indirect, e.multiples)
+
+				// continue with underlying type
+				typ = e.typ.underlying
+			}
+
+			switch t := typ.(type) {
+			case *Struct:
+				for i, f := range t.fields {
+					fset = fset.add(f, e.multiples)
+
+					// Embedded fields are always of the form T or *T where
+					// T is a named type. If typ appeared multiple times at
+					// this depth, f.Type appears multiple times at the next
+					// depth.
+					if f.anonymous {
+						// Ignore embedded basic types - only user-defined
+						// named types can have methods or struct fields.
+						typ, isPtr := deref(f.typ)
+						if t, _ := typ.(*Named); t != nil {
+							next = append(next, embeddedType{t, concat(e.index, i), e.indirect || isPtr, e.multiples})
+						}
+					}
+				}
+
+			case *Interface:
+				mset = mset.add(t.allMethods, e.index, true, e.multiples)
+			}
+		}
+
+		// Add methods and collisions at this depth to base if no entries with matching
+		// names exist already.
+		for k, m := range mset {
+			if _, found := base[k]; !found {
+				// Fields collide with methods of the same name at this depth.
+				if _, found := fset[k]; found {
+					m = nil // collision
+				}
+				if base == nil {
+					base = make(methodSet)
+				}
+				base[k] = m
+			}
+		}
+
+		// Multiple fields with matching names collide at this depth and shadow all
+		// entries further down; add them as collisions to base if no entries with
+		// matching names exist already.
+		for k, f := range fset {
+			if f == nil {
+				if _, found := base[k]; !found {
+					if base == nil {
+						base = make(methodSet)
+					}
+					base[k] = nil // collision
+				}
+			}
+		}
+
+		current = consolidateMultiples(next)
+	}
+
+	if len(base) == 0 {
+		return &emptyMethodSet
+	}
+
+	// collect methods
+	var list []*Selection
+	for _, m := range base {
+		if m != nil {
+			m.recv = T
+			list = append(list, m)
+		}
+	}
+	sort.Sort(byUniqueName(list))
+	return &MethodSet{list}
+}
+
+// A fieldSet is a set of fields and name collisions.
+// A collision indicates that multiple fields with the
+// same unique id appeared.
+type fieldSet map[string]*Var // a nil entry indicates a name collision
+
+// Add adds field f to the field set s.
+// If multiples is set, f appears multiple times
+// and is treated as a collision.
+func (s fieldSet) add(f *Var, multiples bool) fieldSet {
+	if s == nil {
+		s = make(fieldSet)
+	}
+	key := f.Id()
+	// if f is not in the set, add it
+	if !multiples {
+		if _, found := s[key]; !found {
+			s[key] = f
+			return s
+		}
+	}
+	s[key] = nil // collision
+	return s
+}
+
+// A methodSet is a set of methods and name collisions.
+// A collision indicates that multiple methods with the
+// same unique id appeared.
+type methodSet map[string]*Selection // a nil entry indicates a name collision
+
+// Add adds all functions in list to the method set s.
+// If multiples is set, every function in list appears multiple times
+// and is treated as a collision.
+func (s methodSet) add(list []*Func, index []int, indirect bool, multiples bool) methodSet {
+	if len(list) == 0 {
+		return s
+	}
+	if s == nil {
+		s = make(methodSet)
+	}
+	for i, f := range list {
+		key := f.Id()
+		// if f is not in the set, add it
+		if !multiples {
+			// TODO(gri) A found method may not be added because it's not in the method set
+			// (!indirect && ptrRecv(f)). A 2nd method on the same level may be in the method
+			// set and may not collide with the first one, thus leading to a false positive.
+			// Is that possible? Investigate.
+			if _, found := s[key]; !found && (indirect || !ptrRecv(f)) {
+				s[key] = &Selection{MethodVal, nil, f, concat(index, i), indirect}
+				continue
+			}
+		}
+		s[key] = nil // collision
+	}
+	return s
+}
+
+// ptrRecv reports whether the receiver is of the form *T.
+// The receiver must exist.
+func ptrRecv(f *Func) bool {
+	_, isPtr := deref(f.typ.(*Signature).recv.typ)
+	return isPtr
+}
+
+// byUniqueName function lists can be sorted by their unique names.
+type byUniqueName []*Selection
+
+func (a byUniqueName) Len() int           { return len(a) }
+func (a byUniqueName) Less(i, j int) bool { return a[i].obj.Id() < a[j].obj.Id() }
+func (a byUniqueName) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
diff --git a/go/types/object.go b/go/types/object.go
new file mode 100644
index 0000000..a9b6c43
--- /dev/null
+++ b/go/types/object.go
@@ -0,0 +1,361 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package types
+
+import (
+	"bytes"
+	"fmt"
+	"go/ast"
+	"go/token"
+
+	"golang.org/x/tools/go/exact"
+)
+
+// TODO(gri) Document factory, accessor methods, and fields. General clean-up.
+
+// An Object describes a named language entity such as a package,
+// constant, type, variable, function (incl. methods), or label.
+// All objects implement the Object interface.
+//
+type Object interface {
+	Parent() *Scope // scope in which this object is declared
+	Pos() token.Pos // position of object identifier in declaration
+	Pkg() *Package  // nil for objects in the Universe scope and labels
+	Name() string   // package local object name
+	Type() Type     // object type
+	Exported() bool // reports whether the name starts with a capital letter
+	Id() string     // object id (see Id below)
+
+	// String returns a human-readable string of the object.
+	String() string
+
+	// order reflects a package-level object's source order: if object
+	// a is before object b in the source, then a.order() < b.order().
+	// order returns a value > 0 for package-level objects; it returns
+	// 0 for all other objects (including objects in file scopes).
+	order() uint32
+
+	// setOrder sets the order number of the object. It must be > 0.
+	setOrder(uint32)
+
+	// setParent sets the parent scope of the object.
+	setParent(*Scope)
+
+	// sameId reports whether obj.Id() and Id(pkg, name) are the same.
+	sameId(pkg *Package, name string) bool
+
+	// scopePos returns the start position of the scope of this Object
+	scopePos() token.Pos
+
+	// setScopePos sets the start position of the scope for this Object.
+	setScopePos(pos token.Pos)
+}
+
+// Id returns name if it is exported, otherwise it
+// returns the name qualified with the package path.
+func Id(pkg *Package, name string) string {
+	if ast.IsExported(name) {
+		return name
+	}
+	// unexported names need the package path for differentiation
+	// (if there's no package, make sure we don't start with '.'
+	// as that may change the order of methods between a setup
+	// inside a package and outside a package - which breaks some
+	// tests)
+	path := "_"
+	// TODO(gri): shouldn't !ast.IsExported(name) => pkg != nil be an precondition?
+	// if pkg == nil {
+	// 	panic("nil package in lookup of unexported name")
+	// }
+	if pkg != nil {
+		path = pkg.path
+		if path == "" {
+			path = "_"
+		}
+	}
+	return path + "." + name
+}
+
+// An object implements the common parts of an Object.
+type object struct {
+	parent    *Scope
+	pos       token.Pos
+	pkg       *Package
+	name      string
+	typ       Type
+	order_    uint32
+	scopePos_ token.Pos
+}
+
+func (obj *object) Parent() *Scope      { return obj.parent }
+func (obj *object) Pos() token.Pos      { return obj.pos }
+func (obj *object) Pkg() *Package       { return obj.pkg }
+func (obj *object) Name() string        { return obj.name }
+func (obj *object) Type() Type          { return obj.typ }
+func (obj *object) Exported() bool      { return ast.IsExported(obj.name) }
+func (obj *object) Id() string          { return Id(obj.pkg, obj.name) }
+func (obj *object) String() string      { panic("abstract") }
+func (obj *object) order() uint32       { return obj.order_ }
+func (obj *object) scopePos() token.Pos { return obj.scopePos_ }
+
+func (obj *object) setParent(parent *Scope)   { obj.parent = parent }
+func (obj *object) setOrder(order uint32)     { assert(order > 0); obj.order_ = order }
+func (obj *object) setScopePos(pos token.Pos) { obj.scopePos_ = pos }
+
+func (obj *object) sameId(pkg *Package, name string) bool {
+	// spec:
+	// "Two identifiers are different if they are spelled differently,
+	// or if they appear in different packages and are not exported.
+	// Otherwise, they are the same."
+	if name != obj.name {
+		return false
+	}
+	// obj.Name == name
+	if obj.Exported() {
+		return true
+	}
+	// not exported, so packages must be the same (pkg == nil for
+	// fields in Universe scope; this can only happen for types
+	// introduced via Eval)
+	if pkg == nil || obj.pkg == nil {
+		return pkg == obj.pkg
+	}
+	// pkg != nil && obj.pkg != nil
+	return pkg.path == obj.pkg.path
+}
+
+// A PkgName represents an imported Go package.
+type PkgName struct {
+	object
+	imported *Package
+	used     bool // set if the package was used
+}
+
+func NewPkgName(pos token.Pos, pkg *Package, name string, imported *Package) *PkgName {
+	return &PkgName{object{nil, pos, pkg, name, Typ[Invalid], 0, token.NoPos}, imported, false}
+}
+
+// Imported returns the package that was imported.
+// It is distinct from Pkg(), which is the package containing the import statement.
+func (obj *PkgName) Imported() *Package { return obj.imported }
+
+// A Const represents a declared constant.
+type Const struct {
+	object
+	val     exact.Value
+	visited bool // for initialization cycle detection
+}
+
+func NewConst(pos token.Pos, pkg *Package, name string, typ Type, val exact.Value) *Const {
+	return &Const{object{nil, pos, pkg, name, typ, 0, token.NoPos}, val, false}
+}
+
+func (obj *Const) Val() exact.Value { return obj.val }
+
+// A TypeName represents a declared type.
+type TypeName struct {
+	object
+}
+
+func NewTypeName(pos token.Pos, pkg *Package, name string, typ Type) *TypeName {
+	return &TypeName{object{nil, pos, pkg, name, typ, 0, token.NoPos}}
+}
+
+// A Variable represents a declared variable (including function parameters and results, and struct fields).
+type Var struct {
+	object
+	anonymous bool // if set, the variable is an anonymous struct field, and name is the type name
+	visited   bool // for initialization cycle detection
+	isField   bool // var is struct field
+	used      bool // set if the variable was used
+}
+
+func NewVar(pos token.Pos, pkg *Package, name string, typ Type) *Var {
+	return &Var{object: object{nil, pos, pkg, name, typ, 0, token.NoPos}}
+}
+
+func NewParam(pos token.Pos, pkg *Package, name string, typ Type) *Var {
+	return &Var{object: object{nil, pos, pkg, name, typ, 0, token.NoPos}, used: true} // parameters are always 'used'
+}
+
+func NewField(pos token.Pos, pkg *Package, name string, typ Type, anonymous bool) *Var {
+	return &Var{object: object{nil, pos, pkg, name, typ, 0, token.NoPos}, anonymous: anonymous, isField: true}
+}
+
+func (obj *Var) Anonymous() bool { return obj.anonymous }
+
+func (obj *Var) IsField() bool { return obj.isField }
+
+// A Func represents a declared function, concrete method, or abstract
+// (interface) method.  Its Type() is always a *Signature.
+// An abstract method may belong to many interfaces due to embedding.
+type Func struct {
+	object
+}
+
+func NewFunc(pos token.Pos, pkg *Package, name string, sig *Signature) *Func {
+	// don't store a nil signature
+	var typ Type
+	if sig != nil {
+		typ = sig
+	}
+	return &Func{object{nil, pos, pkg, name, typ, 0, token.NoPos}}
+}
+
+// FullName returns the package- or receiver-type-qualified name of
+// function or method obj.
+func (obj *Func) FullName() string {
+	var buf bytes.Buffer
+	writeFuncName(&buf, obj, nil)
+	return buf.String()
+}
+
+func (obj *Func) Scope() *Scope {
+	return obj.typ.(*Signature).scope
+}
+
+// A Label represents a declared label.
+type Label struct {
+	object
+	used bool // set if the label was used
+}
+
+func NewLabel(pos token.Pos, pkg *Package, name string) *Label {
+	return &Label{object{pos: pos, pkg: pkg, name: name, typ: Typ[Invalid]}, false}
+}
+
+// A Builtin represents a built-in function.
+// Builtins don't have a valid type.
+type Builtin struct {
+	object
+	id builtinId
+}
+
+func newBuiltin(id builtinId) *Builtin {
+	return &Builtin{object{name: predeclaredFuncs[id].name, typ: Typ[Invalid]}, id}
+}
+
+// Nil represents the predeclared value nil.
+type Nil struct {
+	object
+}
+
+func writeObject(buf *bytes.Buffer, obj Object, qf Qualifier) {
+	typ := obj.Type()
+	switch obj := obj.(type) {
+	case *PkgName:
+		fmt.Fprintf(buf, "package %s", obj.Name())
+		if path := obj.imported.path; path != "" && path != obj.name {
+			fmt.Fprintf(buf, " (%q)", path)
+		}
+		return
+
+	case *Const:
+		buf.WriteString("const")
+
+	case *TypeName:
+		buf.WriteString("type")
+		typ = typ.Underlying()
+
+	case *Var:
+		if obj.isField {
+			buf.WriteString("field")
+		} else {
+			buf.WriteString("var")
+		}
+
+	case *Func:
+		buf.WriteString("func ")
+		writeFuncName(buf, obj, qf)
+		if typ != nil {
+			WriteSignature(buf, typ.(*Signature), qf)
+		}
+		return
+
+	case *Label:
+		buf.WriteString("label")
+		typ = nil
+
+	case *Builtin:
+		buf.WriteString("builtin")
+		typ = nil
+
+	case *Nil:
+		buf.WriteString("nil")
+		return
+
+	default:
+		panic(fmt.Sprintf("writeObject(%T)", obj))
+	}
+
+	buf.WriteByte(' ')
+
+	// For package-level objects, qualify the name.
+	if obj.Pkg() != nil && obj.Pkg().scope.Lookup(obj.Name()) == obj {
+		writePackage(buf, obj.Pkg(), qf)
+	}
+	buf.WriteString(obj.Name())
+	if typ != nil {
+		buf.WriteByte(' ')
+		WriteType(buf, typ, qf)
+	}
+}
+
+func writePackage(buf *bytes.Buffer, pkg *Package, qf Qualifier) {
+	if pkg == nil {
+		return
+	}
+	var s string
+	if qf != nil {
+		s = qf(pkg)
+	} else {
+		s = pkg.Path()
+	}
+	if s != "" {
+		buf.WriteString(s)
+		buf.WriteByte('.')
+	}
+}
+
+// ObjectString returns the string form of obj.
+// The Qualifier controls the printing of
+// package-level objects, and may be nil.
+func ObjectString(obj Object, qf Qualifier) string {
+	var buf bytes.Buffer
+	writeObject(&buf, obj, qf)
+	return buf.String()
+}
+
+func (obj *PkgName) String() string  { return ObjectString(obj, nil) }
+func (obj *Const) String() string    { return ObjectString(obj, nil) }
+func (obj *TypeName) String() string { return ObjectString(obj, nil) }
+func (obj *Var) String() string      { return ObjectString(obj, nil) }
+func (obj *Func) String() string     { return ObjectString(obj, nil) }
+func (obj *Label) String() string    { return ObjectString(obj, nil) }
+func (obj *Builtin) String() string  { return ObjectString(obj, nil) }
+func (obj *Nil) String() string      { return ObjectString(obj, nil) }
+
+func writeFuncName(buf *bytes.Buffer, f *Func, qf Qualifier) {
+	if f.typ != nil {
+		sig := f.typ.(*Signature)
+		if recv := sig.Recv(); recv != nil {
+			buf.WriteByte('(')
+			if _, ok := recv.Type().(*Interface); ok {
+				// gcimporter creates abstract methods of
+				// named interfaces using the interface type
+				// (not the named type) as the receiver.
+				// Don't print it in full.
+				buf.WriteString("interface")
+			} else {
+				WriteType(buf, recv.Type(), qf)
+			}
+			buf.WriteByte(')')
+			buf.WriteByte('.')
+		} else if f.pkg != nil {
+			writePackage(buf, f.pkg, qf)
+		}
+	}
+	buf.WriteString(f.name)
+}
diff --git a/go/types/objset.go b/go/types/objset.go
new file mode 100644
index 0000000..55eb74a
--- /dev/null
+++ b/go/types/objset.go
@@ -0,0 +1,31 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file implements objsets.
+//
+// An objset is similar to a Scope but objset elements
+// are identified by their unique id, instead of their
+// object name.
+
+package types
+
+// An objset is a set of objects identified by their unique id.
+// The zero value for objset is a ready-to-use empty objset.
+type objset map[string]Object // initialized lazily
+
+// insert attempts to insert an object obj into objset s.
+// If s already contains an alternative object alt with
+// the same name, insert leaves s unchanged and returns alt.
+// Otherwise it inserts obj and returns nil.
+func (s *objset) insert(obj Object) Object {
+	id := obj.Id()
+	if alt := (*s)[id]; alt != nil {
+		return alt
+	}
+	if *s == nil {
+		*s = make(map[string]Object)
+	}
+	(*s)[id] = obj
+	return nil
+}
diff --git a/go/types/operand.go b/go/types/operand.go
new file mode 100644
index 0000000..d52b30e
--- /dev/null
+++ b/go/types/operand.go
@@ -0,0 +1,288 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file defines operands and associated operations.
+
+package types
+
+import (
+	"bytes"
+	"go/ast"
+	"go/token"
+
+	"golang.org/x/tools/go/exact"
+)
+
+// An operandMode specifies the (addressing) mode of an operand.
+type operandMode byte
+
+const (
+	invalid  operandMode = iota // operand is invalid
+	novalue                     // operand represents no value (result of a function call w/o result)
+	builtin                     // operand is a built-in function
+	typexpr                     // operand is a type
+	constant                    // operand is a constant; the operand's typ is a Basic type
+	variable                    // operand is an addressable variable
+	mapindex                    // operand is a map index expression (acts like a variable on lhs, commaok on rhs of an assignment)
+	value                       // operand is a computed value
+	commaok                     // like value, but operand may be used in a comma,ok expression
+)
+
+var operandModeString = [...]string{
+	invalid:  "invalid operand",
+	novalue:  "no value",
+	builtin:  "built-in",
+	typexpr:  "type",
+	constant: "constant",
+	variable: "variable",
+	mapindex: "map index expression",
+	value:    "value",
+	commaok:  "comma, ok expression",
+}
+
+// An operand represents an intermediate value during type checking.
+// Operands have an (addressing) mode, the expression evaluating to
+// the operand, the operand's type, a value for constants, and an id
+// for built-in functions.
+// The zero value of operand is a ready to use invalid operand.
+//
+type operand struct {
+	mode operandMode
+	expr ast.Expr
+	typ  Type
+	val  exact.Value
+	id   builtinId
+}
+
+// pos returns the position of the expression corresponding to x.
+// If x is invalid the position is token.NoPos.
+//
+func (x *operand) pos() token.Pos {
+	// x.expr may not be set if x is invalid
+	if x.expr == nil {
+		return token.NoPos
+	}
+	return x.expr.Pos()
+}
+
+// Operand string formats
+// (not all "untyped" cases can appear due to the type system,
+// but they fall out naturally here)
+//
+// mode       format
+//
+// invalid    <expr> (               <mode>                    )
+// novalue    <expr> (               <mode>                    )
+// builtin    <expr> (               <mode>                    )
+// typexpr    <expr> (               <mode>                    )
+//
+// constant   <expr> (<untyped kind> <mode>                    )
+// constant   <expr> (               <mode>       of type <typ>)
+// constant   <expr> (<untyped kind> <mode> <val>              )
+// constant   <expr> (               <mode> <val> of type <typ>)
+//
+// variable   <expr> (<untyped kind> <mode>                    )
+// variable   <expr> (               <mode>       of type <typ>)
+//
+// mapindex   <expr> (<untyped kind> <mode>                    )
+// mapindex   <expr> (               <mode>       of type <typ>)
+//
+// value      <expr> (<untyped kind> <mode>                    )
+// value      <expr> (               <mode>       of type <typ>)
+//
+// commaok    <expr> (<untyped kind> <mode>                    )
+// commaok    <expr> (               <mode>       of type <typ>)
+//
+func operandString(x *operand, qf Qualifier) string {
+	var buf bytes.Buffer
+
+	var expr string
+	if x.expr != nil {
+		expr = ExprString(x.expr)
+	} else {
+		switch x.mode {
+		case builtin:
+			expr = predeclaredFuncs[x.id].name
+		case typexpr:
+			expr = TypeString(x.typ, qf)
+		case constant:
+			expr = x.val.String()
+		}
+	}
+
+	// <expr> (
+	if expr != "" {
+		buf.WriteString(expr)
+		buf.WriteString(" (")
+	}
+
+	// <untyped kind>
+	hasType := false
+	switch x.mode {
+	case invalid, novalue, builtin, typexpr:
+		// no type
+	default:
+		// has type
+		if isUntyped(x.typ) {
+			buf.WriteString(x.typ.(*Basic).name)
+			buf.WriteByte(' ')
+			break
+		}
+		hasType = true
+	}
+
+	// <mode>
+	buf.WriteString(operandModeString[x.mode])
+
+	// <val>
+	if x.mode == constant {
+		if s := x.val.String(); s != expr {
+			buf.WriteByte(' ')
+			buf.WriteString(s)
+		}
+	}
+
+	// <typ>
+	if hasType {
+		if x.typ != Typ[Invalid] {
+			buf.WriteString(" of type ")
+			WriteType(&buf, x.typ, qf)
+		} else {
+			buf.WriteString(" with invalid type")
+		}
+	}
+
+	// )
+	if expr != "" {
+		buf.WriteByte(')')
+	}
+
+	return buf.String()
+}
+
+func (x *operand) String() string {
+	return operandString(x, nil)
+}
+
+// setConst sets x to the untyped constant for literal lit.
+func (x *operand) setConst(tok token.Token, lit string) {
+	val := exact.MakeFromLiteral(lit, tok)
+	if val == nil {
+		// TODO(gri) Should we make it an unknown constant instead?
+		x.mode = invalid
+		return
+	}
+
+	var kind BasicKind
+	switch tok {
+	case token.INT:
+		kind = UntypedInt
+	case token.FLOAT:
+		kind = UntypedFloat
+	case token.IMAG:
+		kind = UntypedComplex
+	case token.CHAR:
+		kind = UntypedRune
+	case token.STRING:
+		kind = UntypedString
+	}
+
+	x.mode = constant
+	x.typ = Typ[kind]
+	x.val = val
+}
+
+// isNil reports whether x is the nil value.
+func (x *operand) isNil() bool {
+	return x.mode == value && x.typ == Typ[UntypedNil]
+}
+
+// TODO(gri) The functions operand.assignableTo, checker.convertUntyped,
+//           checker.representable, and checker.assignment are
+//           overlapping in functionality. Need to simplify and clean up.
+
+// assignableTo reports whether x is assignable to a variable of type T.
+func (x *operand) assignableTo(conf *Config, T Type) bool {
+	if x.mode == invalid || T == Typ[Invalid] {
+		return true // avoid spurious errors
+	}
+
+	V := x.typ
+
+	// x's type is identical to T
+	if Identical(V, T) {
+		return true
+	}
+
+	Vu := V.Underlying()
+	Tu := T.Underlying()
+
+	// T is an interface type and x implements T
+	// (Do this check first as it might succeed early.)
+	if Ti, ok := Tu.(*Interface); ok {
+		if Implements(x.typ, Ti) {
+			return true
+		}
+	}
+
+	// x's type V and T have identical underlying types
+	// and at least one of V or T is not a named type
+	if Identical(Vu, Tu) && (!isNamed(V) || !isNamed(T)) {
+		return true
+	}
+
+	// x is a bidirectional channel value, T is a channel
+	// type, x's type V and T have identical element types,
+	// and at least one of V or T is not a named type
+	if Vc, ok := Vu.(*Chan); ok && Vc.dir == SendRecv {
+		if Tc, ok := Tu.(*Chan); ok && Identical(Vc.elem, Tc.elem) {
+			return !isNamed(V) || !isNamed(T)
+		}
+	}
+
+	// x is the predeclared identifier nil and T is a pointer,
+	// function, slice, map, channel, or interface type
+	if x.isNil() {
+		switch t := Tu.(type) {
+		case *Basic:
+			if t.kind == UnsafePointer {
+				return true
+			}
+		case *Pointer, *Signature, *Slice, *Map, *Chan, *Interface:
+			return true
+		}
+		return false
+	}
+
+	// x is an untyped constant representable by a value of type T
+	// TODO(gri) This is borrowing from checker.convertUntyped and
+	//           checker.representable. Need to clean up.
+	if isUntyped(Vu) {
+		switch t := Tu.(type) {
+		case *Basic:
+			if x.mode == constant {
+				return representableConst(x.val, conf, t.kind, nil)
+			}
+			// The result of a comparison is an untyped boolean,
+			// but may not be a constant.
+			if Vb, _ := Vu.(*Basic); Vb != nil {
+				return Vb.kind == UntypedBool && isBoolean(Tu)
+			}
+		case *Interface:
+			return x.isNil() || t.Empty()
+		case *Pointer, *Signature, *Slice, *Map, *Chan:
+			return x.isNil()
+		}
+	}
+
+	return false
+}
+
+// isInteger reports whether x is a value of integer type
+// or an untyped constant representable as an integer.
+func (x *operand) isInteger() bool {
+	return x.mode == invalid ||
+		isInteger(x.typ) ||
+		isUntyped(x.typ) && x.mode == constant && representableConst(x.val, nil, UntypedInt, nil) // no *Config required for UntypedInt
+}
diff --git a/go/types/ordering.go b/go/types/ordering.go
new file mode 100644
index 0000000..6bb98f2
--- /dev/null
+++ b/go/types/ordering.go
@@ -0,0 +1,127 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file implements resolveOrder.
+
+package types
+
+import (
+	"go/ast"
+	"sort"
+)
+
+// resolveOrder computes the order in which package-level objects
+// must be type-checked.
+//
+// Interface types appear first in the list, sorted topologically
+// by dependencies on embedded interfaces that are also declared
+// in this package, followed by all other objects sorted in source
+// order.
+//
+// TODO(gri) Consider sorting all types by dependencies here, and
+// in the process check _and_ report type cycles. This may simplify
+// the full type-checking phase.
+//
+func (check *Checker) resolveOrder() []Object {
+	var ifaces, others []Object
+
+	// collect interface types with their dependencies, and all other objects
+	for obj := range check.objMap {
+		if ityp := check.interfaceFor(obj); ityp != nil {
+			ifaces = append(ifaces, obj)
+			// determine dependencies on embedded interfaces
+			for _, f := range ityp.Methods.List {
+				if len(f.Names) == 0 {
+					// Embedded interface: The type must be a (possibly
+					// qualified) identifier denoting another interface.
+					// Imported interfaces are already fully resolved,
+					// so we can ignore qualified identifiers.
+					if ident, _ := f.Type.(*ast.Ident); ident != nil {
+						embedded := check.pkg.scope.Lookup(ident.Name)
+						if check.interfaceFor(embedded) != nil {
+							check.objMap[obj].addDep(embedded)
+						}
+					}
+				}
+			}
+		} else {
+			others = append(others, obj)
+		}
+	}
+
+	// final object order
+	var order []Object
+
+	// sort interface types topologically by dependencies,
+	// and in source order if there are no dependencies
+	sort.Sort(inSourceOrder(ifaces))
+	if debug {
+		for _, obj := range ifaces {
+			assert(check.objMap[obj].mark == 0)
+		}
+	}
+	for _, obj := range ifaces {
+		check.appendInPostOrder(&order, obj)
+	}
+
+	// sort everything else in source order
+	sort.Sort(inSourceOrder(others))
+
+	return append(order, others...)
+}
+
+// interfaceFor returns the AST interface denoted by obj, or nil.
+func (check *Checker) interfaceFor(obj Object) *ast.InterfaceType {
+	tname, _ := obj.(*TypeName)
+	if tname == nil {
+		return nil // not a type
+	}
+	d := check.objMap[obj]
+	if d == nil {
+		check.dump("%s: %s should have been declared", obj.Pos(), obj.Name())
+		unreachable()
+	}
+	if d.typ == nil {
+		return nil // invalid AST - ignore (will be handled later)
+	}
+	ityp, _ := d.typ.(*ast.InterfaceType)
+	return ityp
+}
+
+func (check *Checker) appendInPostOrder(order *[]Object, obj Object) {
+	d := check.objMap[obj]
+	if d.mark != 0 {
+		// We've already seen this object; either because it's
+		// already added to order, or because we have a cycle.
+		// In both cases we stop. Cycle errors are reported
+		// when type-checking types.
+		return
+	}
+	d.mark = 1
+
+	for _, obj := range orderedSetObjects(d.deps) {
+		check.appendInPostOrder(order, obj)
+	}
+
+	*order = append(*order, obj)
+}
+
+func orderedSetObjects(set map[Object]bool) []Object {
+	list := make([]Object, len(set))
+	i := 0
+	for obj := range set {
+		// we don't care about the map element value
+		list[i] = obj
+		i++
+	}
+	sort.Sort(inSourceOrder(list))
+	return list
+}
+
+// inSourceOrder implements the sort.Sort interface.
+type inSourceOrder []Object
+
+func (a inSourceOrder) Len() int           { return len(a) }
+func (a inSourceOrder) Less(i, j int) bool { return a[i].order() < a[j].order() }
+func (a inSourceOrder) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
diff --git a/go/types/package.go b/go/types/package.go
new file mode 100644
index 0000000..48fe839
--- /dev/null
+++ b/go/types/package.go
@@ -0,0 +1,65 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package types
+
+import (
+	"fmt"
+	"go/token"
+)
+
+// A Package describes a Go package.
+type Package struct {
+	path     string
+	name     string
+	scope    *Scope
+	complete bool
+	imports  []*Package
+	fake     bool // scope lookup errors are silently dropped if package is fake (internal use only)
+}
+
+// NewPackage returns a new Package for the given package path and name;
+// the name must not be the blank identifier.
+// The package is not complete and contains no explicit imports.
+func NewPackage(path, name string) *Package {
+	if name == "_" {
+		panic("invalid package name _")
+	}
+	scope := NewScope(Universe, token.NoPos, token.NoPos, fmt.Sprintf("package %q", path))
+	return &Package{path: path, name: name, scope: scope}
+}
+
+// Path returns the package path.
+func (pkg *Package) Path() string { return pkg.path }
+
+// Name returns the package name.
+func (pkg *Package) Name() string { return pkg.name }
+
+// Scope returns the (complete or incomplete) package scope
+// holding the objects declared at package level (TypeNames,
+// Consts, Vars, and Funcs).
+func (pkg *Package) Scope() *Scope { return pkg.scope }
+
+// A package is complete if its scope contains (at least) all
+// exported objects; otherwise it is incomplete.
+func (pkg *Package) Complete() bool { return pkg.complete }
+
+// MarkComplete marks a package as complete.
+func (pkg *Package) MarkComplete() { pkg.complete = true }
+
+// Imports returns the list of packages directly imported by
+// pkg; the list is in source order. Package unsafe is excluded.
+//
+// If pkg was loaded from export data, Imports includes packages that
+// provide package-level objects referenced by pkg.  This may be more or
+// less than the set of packages directly imported by pkg's source code.
+func (pkg *Package) Imports() []*Package { return pkg.imports }
+
+// SetImports sets the list of explicitly imported packages to list.
+// It is the caller's responsibility to make sure list elements are unique.
+func (pkg *Package) SetImports(list []*Package) { pkg.imports = list }
+
+func (pkg *Package) String() string {
+	return fmt.Sprintf("package %s (%q)", pkg.name, pkg.path)
+}
diff --git a/go/types/predicates.go b/go/types/predicates.go
new file mode 100644
index 0000000..993c6d2
--- /dev/null
+++ b/go/types/predicates.go
@@ -0,0 +1,309 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file implements commonly used type predicates.
+
+package types
+
+import "sort"
+
+func isNamed(typ Type) bool {
+	if _, ok := typ.(*Basic); ok {
+		return ok
+	}
+	_, ok := typ.(*Named)
+	return ok
+}
+
+func isBoolean(typ Type) bool {
+	t, ok := typ.Underlying().(*Basic)
+	return ok && t.info&IsBoolean != 0
+}
+
+func isInteger(typ Type) bool {
+	t, ok := typ.Underlying().(*Basic)
+	return ok && t.info&IsInteger != 0
+}
+
+func isUnsigned(typ Type) bool {
+	t, ok := typ.Underlying().(*Basic)
+	return ok && t.info&IsUnsigned != 0
+}
+
+func isFloat(typ Type) bool {
+	t, ok := typ.Underlying().(*Basic)
+	return ok && t.info&IsFloat != 0
+}
+
+func isComplex(typ Type) bool {
+	t, ok := typ.Underlying().(*Basic)
+	return ok && t.info&IsComplex != 0
+}
+
+func isNumeric(typ Type) bool {
+	t, ok := typ.Underlying().(*Basic)
+	return ok && t.info&IsNumeric != 0
+}
+
+func isString(typ Type) bool {
+	t, ok := typ.Underlying().(*Basic)
+	return ok && t.info&IsString != 0
+}
+
+func isTyped(typ Type) bool {
+	t, ok := typ.Underlying().(*Basic)
+	return !ok || t.info&IsUntyped == 0
+}
+
+func isUntyped(typ Type) bool {
+	t, ok := typ.Underlying().(*Basic)
+	return ok && t.info&IsUntyped != 0
+}
+
+func isOrdered(typ Type) bool {
+	t, ok := typ.Underlying().(*Basic)
+	return ok && t.info&IsOrdered != 0
+}
+
+func isConstType(typ Type) bool {
+	t, ok := typ.Underlying().(*Basic)
+	return ok && t.info&IsConstType != 0
+}
+
+// IsInterface reports whether typ is an interface type.
+func IsInterface(typ Type) bool {
+	_, ok := typ.Underlying().(*Interface)
+	return ok
+}
+
+// Comparable reports whether values of type T are comparable.
+func Comparable(T Type) bool {
+	switch t := T.Underlying().(type) {
+	case *Basic:
+		// assume invalid types to be comparable
+		// to avoid follow-up errors
+		return t.kind != UntypedNil
+	case *Pointer, *Interface, *Chan:
+		return true
+	case *Struct:
+		for _, f := range t.fields {
+			if !Comparable(f.typ) {
+				return false
+			}
+		}
+		return true
+	case *Array:
+		return Comparable(t.elem)
+	}
+	return false
+}
+
+// hasNil reports whether a type includes the nil value.
+func hasNil(typ Type) bool {
+	switch t := typ.Underlying().(type) {
+	case *Basic:
+		return t.kind == UnsafePointer
+	case *Slice, *Pointer, *Signature, *Interface, *Map, *Chan:
+		return true
+	}
+	return false
+}
+
+// Identical reports whether x and y are identical.
+func Identical(x, y Type) bool {
+	return identical(x, y, nil)
+}
+
+// An ifacePair is a node in a stack of interface type pairs compared for identity.
+type ifacePair struct {
+	x, y *Interface
+	prev *ifacePair
+}
+
+func (p *ifacePair) identical(q *ifacePair) bool {
+	return p.x == q.x && p.y == q.y || p.x == q.y && p.y == q.x
+}
+
+func identical(x, y Type, p *ifacePair) bool {
+	if x == y {
+		return true
+	}
+
+	switch x := x.(type) {
+	case *Basic:
+		// Basic types are singletons except for the rune and byte
+		// aliases, thus we cannot solely rely on the x == y check
+		// above.
+		if y, ok := y.(*Basic); ok {
+			return x.kind == y.kind
+		}
+
+	case *Array:
+		// Two array types are identical if they have identical element types
+		// and the same array length.
+		if y, ok := y.(*Array); ok {
+			return x.len == y.len && identical(x.elem, y.elem, p)
+		}
+
+	case *Slice:
+		// Two slice types are identical if they have identical element types.
+		if y, ok := y.(*Slice); ok {
+			return identical(x.elem, y.elem, p)
+		}
+
+	case *Struct:
+		// Two struct types are identical if they have the same sequence of fields,
+		// and if corresponding fields have the same names, and identical types,
+		// and identical tags. Two anonymous fields are considered to have the same
+		// name. Lower-case field names from different packages are always different.
+		if y, ok := y.(*Struct); ok {
+			if x.NumFields() == y.NumFields() {
+				for i, f := range x.fields {
+					g := y.fields[i]
+					if f.anonymous != g.anonymous ||
+						x.Tag(i) != y.Tag(i) ||
+						!f.sameId(g.pkg, g.name) ||
+						!identical(f.typ, g.typ, p) {
+						return false
+					}
+				}
+				return true
+			}
+		}
+
+	case *Pointer:
+		// Two pointer types are identical if they have identical base types.
+		if y, ok := y.(*Pointer); ok {
+			return identical(x.base, y.base, p)
+		}
+
+	case *Tuple:
+		// Two tuples types are identical if they have the same number of elements
+		// and corresponding elements have identical types.
+		if y, ok := y.(*Tuple); ok {
+			if x.Len() == y.Len() {
+				if x != nil {
+					for i, v := range x.vars {
+						w := y.vars[i]
+						if !identical(v.typ, w.typ, p) {
+							return false
+						}
+					}
+				}
+				return true
+			}
+		}
+
+	case *Signature:
+		// Two function types are identical if they have the same number of parameters
+		// and result values, corresponding parameter and result types are identical,
+		// and either both functions are variadic or neither is. Parameter and result
+		// names are not required to match.
+		if y, ok := y.(*Signature); ok {
+			return x.variadic == y.variadic &&
+				identical(x.params, y.params, p) &&
+				identical(x.results, y.results, p)
+		}
+
+	case *Interface:
+		// Two interface types are identical if they have the same set of methods with
+		// the same names and identical function types. Lower-case method names from
+		// different packages are always different. The order of the methods is irrelevant.
+		if y, ok := y.(*Interface); ok {
+			a := x.allMethods
+			b := y.allMethods
+			if len(a) == len(b) {
+				// Interface types are the only types where cycles can occur
+				// that are not "terminated" via named types; and such cycles
+				// can only be created via method parameter types that are
+				// anonymous interfaces (directly or indirectly) embedding
+				// the current interface. Example:
+				//
+				//    type T interface {
+				//        m() interface{T}
+				//    }
+				//
+				// If two such (differently named) interfaces are compared,
+				// endless recursion occurs if the cycle is not detected.
+				//
+				// If x and y were compared before, they must be equal
+				// (if they were not, the recursion would have stopped);
+				// search the ifacePair stack for the same pair.
+				//
+				// This is a quadratic algorithm, but in practice these stacks
+				// are extremely short (bounded by the nesting depth of interface
+				// type declarations that recur via parameter types, an extremely
+				// rare occurrence). An alternative implementation might use a
+				// "visited" map, but that is probably less efficient overall.
+				q := &ifacePair{x, y, p}
+				for p != nil {
+					if p.identical(q) {
+						return true // same pair was compared before
+					}
+					p = p.prev
+				}
+				if debug {
+					assert(sort.IsSorted(byUniqueMethodName(a)))
+					assert(sort.IsSorted(byUniqueMethodName(b)))
+				}
+				for i, f := range a {
+					g := b[i]
+					if f.Id() != g.Id() || !identical(f.typ, g.typ, q) {
+						return false
+					}
+				}
+				return true
+			}
+		}
+
+	case *Map:
+		// Two map types are identical if they have identical key and value types.
+		if y, ok := y.(*Map); ok {
+			return identical(x.key, y.key, p) && identical(x.elem, y.elem, p)
+		}
+
+	case *Chan:
+		// Two channel types are identical if they have identical value types
+		// and the same direction.
+		if y, ok := y.(*Chan); ok {
+			return x.dir == y.dir && identical(x.elem, y.elem, p)
+		}
+
+	case *Named:
+		// Two named types are identical if their type names originate
+		// in the same type declaration.
+		if y, ok := y.(*Named); ok {
+			return x.obj == y.obj
+		}
+
+	default:
+		unreachable()
+	}
+
+	return false
+}
+
+// defaultType returns the default "typed" type for an "untyped" type;
+// it returns the incoming type for all other types. The default type
+// for untyped nil is untyped nil.
+//
+func defaultType(typ Type) Type {
+	if t, ok := typ.(*Basic); ok {
+		switch t.kind {
+		case UntypedBool:
+			return Typ[Bool]
+		case UntypedInt:
+			return Typ[Int]
+		case UntypedRune:
+			return universeRune // use 'rune' name
+		case UntypedFloat:
+			return Typ[Float64]
+		case UntypedComplex:
+			return Typ[Complex128]
+		case UntypedString:
+			return Typ[String]
+		}
+	}
+	return typ
+}
diff --git a/go/types/resolver.go b/go/types/resolver.go
new file mode 100644
index 0000000..374ffc2
--- /dev/null
+++ b/go/types/resolver.go
@@ -0,0 +1,453 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package types
+
+import (
+	"errors"
+	"fmt"
+	"go/ast"
+	"go/token"
+	pathLib "path"
+	"strconv"
+	"strings"
+	"unicode"
+
+	"golang.org/x/tools/go/exact"
+)
+
+// A declInfo describes a package-level const, type, var, or func declaration.
+type declInfo struct {
+	file  *Scope        // scope of file containing this declaration
+	lhs   []*Var        // lhs of n:1 variable declarations, or nil
+	typ   ast.Expr      // type, or nil
+	init  ast.Expr      // init expression, or nil
+	fdecl *ast.FuncDecl // func declaration, or nil
+
+	deps map[Object]bool // type and init dependencies; lazily allocated
+	mark int             // for dependency analysis
+}
+
+// hasInitializer reports whether the declared object has an initialization
+// expression or function body.
+func (d *declInfo) hasInitializer() bool {
+	return d.init != nil || d.fdecl != nil && d.fdecl.Body != nil
+}
+
+// addDep adds obj as a dependency to d.
+func (d *declInfo) addDep(obj Object) {
+	m := d.deps
+	if m == nil {
+		m = make(map[Object]bool)
+		d.deps = m
+	}
+	m[obj] = true
+}
+
+// arityMatch checks that the lhs and rhs of a const or var decl
+// have the appropriate number of names and init exprs. For const
+// decls, init is the value spec providing the init exprs; for
+// var decls, init is nil (the init exprs are in s in this case).
+func (check *Checker) arityMatch(s, init *ast.ValueSpec) {
+	l := len(s.Names)
+	r := len(s.Values)
+	if init != nil {
+		r = len(init.Values)
+	}
+
+	switch {
+	case init == nil && r == 0:
+		// var decl w/o init expr
+		if s.Type == nil {
+			check.errorf(s.Pos(), "missing type or init expr")
+		}
+	case l < r:
+		if l < len(s.Values) {
+			// init exprs from s
+			n := s.Values[l]
+			check.errorf(n.Pos(), "extra init expr %s", n)
+			// TODO(gri) avoid declared but not used error here
+		} else {
+			// init exprs "inherited"
+			check.errorf(s.Pos(), "extra init expr at %s", init.Pos())
+			// TODO(gri) avoid declared but not used error here
+		}
+	case l > r && (init != nil || r != 1):
+		n := s.Names[r]
+		check.errorf(n.Pos(), "missing init expr for %s", n)
+	}
+}
+
+func validatedImportPath(path string) (string, error) {
+	s, err := strconv.Unquote(path)
+	if err != nil {
+		return "", err
+	}
+	if s == "" {
+		return "", fmt.Errorf("empty string")
+	}
+	const illegalChars = `!"#$%&'()*,:;<=>?[\]^{|}` + "`\uFFFD"
+	for _, r := range s {
+		if !unicode.IsGraphic(r) || unicode.IsSpace(r) || strings.ContainsRune(illegalChars, r) {
+			return s, fmt.Errorf("invalid character %#U", r)
+		}
+	}
+	return s, nil
+}
+
+// declarePkgObj declares obj in the package scope, records its ident -> obj mapping,
+// and updates check.objMap. The object must not be a function or method.
+func (check *Checker) declarePkgObj(ident *ast.Ident, obj Object, d *declInfo) {
+	assert(ident.Name == obj.Name())
+
+	// spec: "A package-scope or file-scope identifier with name init
+	// may only be declared to be a function with this (func()) signature."
+	if ident.Name == "init" {
+		check.errorf(ident.Pos(), "cannot declare init - must be func")
+		return
+	}
+
+	check.declare(check.pkg.scope, ident, obj, token.NoPos)
+	check.objMap[obj] = d
+	obj.setOrder(uint32(len(check.objMap)))
+}
+
+// filename returns a filename suitable for debugging output.
+func (check *Checker) filename(fileNo int) string {
+	file := check.files[fileNo]
+	if pos := file.Pos(); pos.IsValid() {
+		return check.fset.File(pos).Name()
+	}
+	return fmt.Sprintf("file[%d]", fileNo)
+}
+
+// collectObjects collects all file and package objects and inserts them
+// into their respective scopes. It also performs imports and associates
+// methods with receiver base type names.
+func (check *Checker) collectObjects() {
+	pkg := check.pkg
+
+	importer := check.conf.Import
+	if importer == nil {
+		if DefaultImport != nil {
+			importer = DefaultImport
+		} else {
+			// Panic if we encounter an import.
+			importer = func(map[string]*Package, string) (*Package, error) {
+				panic(`no Config.Import or DefaultImport (missing import _ "golang.org/x/tools/go/gcimporter"?)`)
+			}
+		}
+	}
+
+	// pkgImports is the set of packages already imported by any package file seen
+	// so far. Used to avoid duplicate entries in pkg.imports. Allocate and populate
+	// it (pkg.imports may not be empty if we are checking test files incrementally).
+	var pkgImports = make(map[*Package]bool)
+	for _, imp := range pkg.imports {
+		pkgImports[imp] = true
+	}
+
+	for fileNo, file := range check.files {
+		// The package identifier denotes the current package,
+		// but there is no corresponding package object.
+		check.recordDef(file.Name, nil)
+
+		// Use the actual source file extent rather than *ast.File extent since the
+		// latter doesn't include comments which appear at the start or end of the file.
+		// Be conservative and use the *ast.File extent if we don't have a *token.File.
+		pos, end := file.Pos(), file.End()
+		if f := check.fset.File(file.Pos()); f != nil {
+			pos, end = token.Pos(f.Base()), token.Pos(f.Base()+f.Size())
+		}
+		fileScope := NewScope(check.pkg.scope, pos, end, check.filename(fileNo))
+		check.recordScope(file, fileScope)
+
+		for _, decl := range file.Decls {
+			switch d := decl.(type) {
+			case *ast.BadDecl:
+				// ignore
+
+			case *ast.GenDecl:
+				var last *ast.ValueSpec // last ValueSpec with type or init exprs seen
+				for iota, spec := range d.Specs {
+					switch s := spec.(type) {
+					case *ast.ImportSpec:
+						// import package
+						var imp *Package
+						path, err := validatedImportPath(s.Path.Value)
+						if err != nil {
+							check.errorf(s.Path.Pos(), "invalid import path (%s)", err)
+							continue
+						}
+						if path == "C" && check.conf.FakeImportC {
+							// TODO(gri) shouldn't create a new one each time
+							imp = NewPackage("C", "C")
+							imp.fake = true
+						} else {
+							var err error
+							imp, err = importer(check.conf.Packages, path)
+							if imp == nil && err == nil {
+								err = errors.New("Config.Import returned nil but no error")
+							}
+							if err != nil {
+								check.errorf(s.Path.Pos(), "could not import %s (%s)", path, err)
+								continue
+							}
+						}
+
+						// add package to list of explicit imports
+						// (this functionality is provided as a convenience
+						// for clients; it is not needed for type-checking)
+						if !pkgImports[imp] {
+							pkgImports[imp] = true
+							if imp != Unsafe {
+								pkg.imports = append(pkg.imports, imp)
+							}
+						}
+
+						// local name overrides imported package name
+						name := imp.name
+						if s.Name != nil {
+							name = s.Name.Name
+							if name == "init" {
+								check.errorf(s.Name.Pos(), "cannot declare init - must be func")
+								continue
+							}
+						}
+
+						obj := NewPkgName(s.Pos(), pkg, name, imp)
+						if s.Name != nil {
+							// in a dot-import, the dot represents the package
+							check.recordDef(s.Name, obj)
+						} else {
+							check.recordImplicit(s, obj)
+						}
+
+						// add import to file scope
+						if name == "." {
+							// merge imported scope with file scope
+							for _, obj := range imp.scope.elems {
+								// A package scope may contain non-exported objects,
+								// do not import them!
+								if obj.Exported() {
+									// TODO(gri) When we import a package, we create
+									// a new local package object. We should do the
+									// same for each dot-imported object. That way
+									// they can have correct position information.
+									// (We must not modify their existing position
+									// information because the same package - found
+									// via Config.Packages - may be dot-imported in
+									// another package!)
+									check.declare(fileScope, nil, obj, token.NoPos)
+									check.recordImplicit(s, obj)
+								}
+							}
+							// add position to set of dot-import positions for this file
+							// (this is only needed for "imported but not used" errors)
+							check.addUnusedDotImport(fileScope, imp, s.Pos())
+						} else {
+							// declare imported package object in file scope
+							check.declare(fileScope, nil, obj, token.NoPos)
+						}
+
+					case *ast.ValueSpec:
+						switch d.Tok {
+						case token.CONST:
+							// determine which initialization expressions to use
+							switch {
+							case s.Type != nil || len(s.Values) > 0:
+								last = s
+							case last == nil:
+								last = new(ast.ValueSpec) // make sure last exists
+							}
+
+							// declare all constants
+							for i, name := range s.Names {
+								obj := NewConst(name.Pos(), pkg, name.Name, nil, exact.MakeInt64(int64(iota)))
+
+								var init ast.Expr
+								if i < len(last.Values) {
+									init = last.Values[i]
+								}
+
+								d := &declInfo{file: fileScope, typ: last.Type, init: init}
+								check.declarePkgObj(name, obj, d)
+							}
+
+							check.arityMatch(s, last)
+
+						case token.VAR:
+							lhs := make([]*Var, len(s.Names))
+							// If there's exactly one rhs initializer, use
+							// the same declInfo d1 for all lhs variables
+							// so that each lhs variable depends on the same
+							// rhs initializer (n:1 var declaration).
+							var d1 *declInfo
+							if len(s.Values) == 1 {
+								// The lhs elements are only set up after the for loop below,
+								// but that's ok because declareVar only collects the declInfo
+								// for a later phase.
+								d1 = &declInfo{file: fileScope, lhs: lhs, typ: s.Type, init: s.Values[0]}
+							}
+
+							// declare all variables
+							for i, name := range s.Names {
+								obj := NewVar(name.Pos(), pkg, name.Name, nil)
+								lhs[i] = obj
+
+								d := d1
+								if d == nil {
+									// individual assignments
+									var init ast.Expr
+									if i < len(s.Values) {
+										init = s.Values[i]
+									}
+									d = &declInfo{file: fileScope, typ: s.Type, init: init}
+								}
+
+								check.declarePkgObj(name, obj, d)
+							}
+
+							check.arityMatch(s, nil)
+
+						default:
+							check.invalidAST(s.Pos(), "invalid token %s", d.Tok)
+						}
+
+					case *ast.TypeSpec:
+						obj := NewTypeName(s.Name.Pos(), pkg, s.Name.Name, nil)
+						check.declarePkgObj(s.Name, obj, &declInfo{file: fileScope, typ: s.Type})
+
+					default:
+						check.invalidAST(s.Pos(), "unknown ast.Spec node %T", s)
+					}
+				}
+
+			case *ast.FuncDecl:
+				name := d.Name.Name
+				obj := NewFunc(d.Name.Pos(), pkg, name, nil)
+				if d.Recv == nil {
+					// regular function
+					if name == "init" {
+						// don't declare init functions in the package scope - they are invisible
+						obj.parent = pkg.scope
+						check.recordDef(d.Name, obj)
+						// init functions must have a body
+						if d.Body == nil {
+							check.softErrorf(obj.pos, "missing function body")
+						}
+					} else {
+						check.declare(pkg.scope, d.Name, obj, token.NoPos)
+					}
+				} else {
+					// method
+					check.recordDef(d.Name, obj)
+					// Associate method with receiver base type name, if possible.
+					// Ignore methods that have an invalid receiver, or a blank _
+					// receiver name. They will be type-checked later, with regular
+					// functions.
+					if list := d.Recv.List; len(list) > 0 {
+						typ := list[0].Type
+						if ptr, _ := typ.(*ast.StarExpr); ptr != nil {
+							typ = ptr.X
+						}
+						if base, _ := typ.(*ast.Ident); base != nil && base.Name != "_" {
+							check.assocMethod(base.Name, obj)
+						}
+					}
+				}
+				info := &declInfo{file: fileScope, fdecl: d}
+				check.objMap[obj] = info
+				obj.setOrder(uint32(len(check.objMap)))
+
+			default:
+				check.invalidAST(d.Pos(), "unknown ast.Decl node %T", d)
+			}
+		}
+	}
+
+	// verify that objects in package and file scopes have different names
+	for _, scope := range check.pkg.scope.children /* file scopes */ {
+		for _, obj := range scope.elems {
+			if alt := pkg.scope.Lookup(obj.Name()); alt != nil {
+				if pkg, ok := obj.(*PkgName); ok {
+					check.errorf(alt.Pos(), "%s already declared through import of %s", alt.Name(), pkg.Imported())
+					check.reportAltDecl(pkg)
+				} else {
+					check.errorf(alt.Pos(), "%s already declared through dot-import of %s", alt.Name(), obj.Pkg())
+					// TODO(gri) dot-imported objects don't have a position; reportAltDecl won't print anything
+					check.reportAltDecl(obj)
+				}
+			}
+		}
+	}
+}
+
+// packageObjects typechecks all package objects in objList, but not function bodies.
+func (check *Checker) packageObjects(objList []Object) {
+	// add new methods to already type-checked types (from a prior Checker.Files call)
+	for _, obj := range objList {
+		if obj, _ := obj.(*TypeName); obj != nil && obj.typ != nil {
+			check.addMethodDecls(obj)
+		}
+	}
+
+	// pre-allocate space for type declaration paths so that the underlying array is reused
+	typePath := make([]*TypeName, 0, 8)
+
+	for _, obj := range objList {
+		check.objDecl(obj, nil, typePath)
+	}
+
+	// At this point we may have a non-empty check.methods map; this means that not all
+	// entries were deleted at the end of typeDecl because the respective receiver base
+	// types were not found. In that case, an error was reported when declaring those
+	// methods. We can now safely discard this map.
+	check.methods = nil
+}
+
+// functionBodies typechecks all function bodies.
+func (check *Checker) functionBodies() {
+	for _, f := range check.funcs {
+		check.funcBody(f.decl, f.name, f.sig, f.body)
+	}
+}
+
+// unusedImports checks for unused imports.
+func (check *Checker) unusedImports() {
+	// if function bodies are not checked, packages' uses are likely missing - don't check
+	if check.conf.IgnoreFuncBodies {
+		return
+	}
+
+	// spec: "It is illegal (...) to directly import a package without referring to
+	// any of its exported identifiers. To import a package solely for its side-effects
+	// (initialization), use the blank identifier as explicit package name."
+
+	// check use of regular imported packages
+	for _, scope := range check.pkg.scope.children /* file scopes */ {
+		for _, obj := range scope.elems {
+			if obj, ok := obj.(*PkgName); ok {
+				// Unused "blank imports" are automatically ignored
+				// since _ identifiers are not entered into scopes.
+				if !obj.used {
+					path := obj.imported.path
+					base := pathLib.Base(path)
+					if obj.name == base {
+						check.softErrorf(obj.pos, "%q imported but not used", path)
+					} else {
+						check.softErrorf(obj.pos, "%q imported but not used as %s", path, obj.name)
+					}
+				}
+			}
+		}
+	}
+
+	// check use of dot-imported packages
+	for _, unusedDotImports := range check.unusedDotImports {
+		for pkg, pos := range unusedDotImports {
+			check.softErrorf(pos, "%q imported but not used", pkg.path)
+		}
+	}
+}
diff --git a/go/types/resolver_test.go b/go/types/resolver_test.go
new file mode 100644
index 0000000..2ef1f18
--- /dev/null
+++ b/go/types/resolver_test.go
@@ -0,0 +1,189 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package types_test
+
+import (
+	"fmt"
+	"go/ast"
+	"go/parser"
+	"go/token"
+	"sort"
+	"testing"
+
+	_ "golang.org/x/tools/go/gcimporter"
+	. "golang.org/x/tools/go/types"
+)
+
+func TestResolveIdents(t *testing.T) {
+	skipSpecialPlatforms(t)
+
+	sources := []string{
+		`
+		package p
+		import "fmt"
+		import "math"
+		const pi = math.Pi
+		func sin(x float64) float64 {
+			return math.Sin(x)
+		}
+		var Println = fmt.Println
+		`,
+		`
+		package p
+		import "fmt"
+		type errorStringer struct { fmt.Stringer; error }
+		func f() string {
+			_ = "foo"
+			return fmt.Sprintf("%d", g())
+		}
+		func g() (x int) { return }
+		`,
+		`
+		package p
+		import . "go/parser"
+		import "sync"
+		func h() Mode { return ImportsOnly }
+		var _, x int = 1, 2
+		func init() {}
+		type T struct{ *sync.Mutex; a, b, c int}
+		type I interface{ m() }
+		var _ = T{a: 1, b: 2, c: 3}
+		func (_ T) m() {}
+		func (T) _() {}
+		var i I
+		var _ = i.m
+		func _(s []int) { for i, x := range s { _, _ = i, x } }
+		func _(x interface{}) {
+			switch x := x.(type) {
+			case int:
+				_ = x
+			}
+			switch {} // implicit 'true' tag
+		}
+		`,
+		`
+		package p
+		type S struct{}
+		func (T) _() {}
+		func (T) _() {}
+		`,
+		`
+		package p
+		func _() {
+		L0:
+		L1:
+			goto L0
+			for {
+				goto L1
+			}
+			if true {
+				goto L2
+			}
+		L2:
+		}
+		`,
+	}
+
+	pkgnames := []string{
+		"fmt",
+		"math",
+	}
+
+	// parse package files
+	fset := token.NewFileSet()
+	var files []*ast.File
+	for i, src := range sources {
+		f, err := parser.ParseFile(fset, fmt.Sprintf("sources[%d]", i), src, parser.DeclarationErrors)
+		if err != nil {
+			t.Fatal(err)
+		}
+		files = append(files, f)
+	}
+
+	// resolve and type-check package AST
+	var conf Config
+	uses := make(map[*ast.Ident]Object)
+	defs := make(map[*ast.Ident]Object)
+	_, err := conf.Check("testResolveIdents", fset, files, &Info{Defs: defs, Uses: uses})
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	// check that all packages were imported
+	for _, name := range pkgnames {
+		if conf.Packages[name] == nil {
+			t.Errorf("package %s not imported", name)
+		}
+	}
+
+	// check that qualified identifiers are resolved
+	for _, f := range files {
+		ast.Inspect(f, func(n ast.Node) bool {
+			if s, ok := n.(*ast.SelectorExpr); ok {
+				if x, ok := s.X.(*ast.Ident); ok {
+					obj := uses[x]
+					if obj == nil {
+						t.Errorf("%s: unresolved qualified identifier %s", fset.Position(x.Pos()), x.Name)
+						return false
+					}
+					if _, ok := obj.(*PkgName); ok && uses[s.Sel] == nil {
+						t.Errorf("%s: unresolved selector %s", fset.Position(s.Sel.Pos()), s.Sel.Name)
+						return false
+					}
+					return false
+				}
+				return false
+			}
+			return true
+		})
+	}
+
+	for id, obj := range uses {
+		if obj == nil {
+			t.Errorf("%s: Uses[%s] == nil", fset.Position(id.Pos()), id.Name)
+		}
+	}
+
+	// check that each identifier in the source is found in uses or defs or both
+	var both []string
+	for _, f := range files {
+		ast.Inspect(f, func(n ast.Node) bool {
+			if x, ok := n.(*ast.Ident); ok {
+				var objects int
+				if _, found := uses[x]; found {
+					objects |= 1
+					delete(uses, x)
+				}
+				if _, found := defs[x]; found {
+					objects |= 2
+					delete(defs, x)
+				}
+				if objects == 0 {
+					t.Errorf("%s: unresolved identifier %s", fset.Position(x.Pos()), x.Name)
+				} else if objects == 3 {
+					both = append(both, x.Name)
+				}
+				return false
+			}
+			return true
+		})
+	}
+
+	// check the expected set of idents that are simultaneously uses and defs
+	sort.Strings(both)
+	if got, want := fmt.Sprint(both), "[Mutex Stringer error]"; got != want {
+		t.Errorf("simultaneous uses/defs = %s, want %s", got, want)
+	}
+
+	// any left-over identifiers didn't exist in the source
+	for x := range uses {
+		t.Errorf("%s: identifier %s not present in source", fset.Position(x.Pos()), x.Name)
+	}
+	for x := range defs {
+		t.Errorf("%s: identifier %s not present in source", fset.Position(x.Pos()), x.Name)
+	}
+
+	// TODO(gri) add tests to check ImplicitObj callbacks
+}
diff --git a/go/types/return.go b/go/types/return.go
new file mode 100644
index 0000000..6628985
--- /dev/null
+++ b/go/types/return.go
@@ -0,0 +1,185 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file implements isTerminating.
+
+package types
+
+import (
+	"go/ast"
+	"go/token"
+)
+
+// isTerminating reports if s is a terminating statement.
+// If s is labeled, label is the label name; otherwise s
+// is "".
+func (check *Checker) isTerminating(s ast.Stmt, label string) bool {
+	switch s := s.(type) {
+	default:
+		unreachable()
+
+	case *ast.BadStmt, *ast.DeclStmt, *ast.EmptyStmt, *ast.SendStmt,
+		*ast.IncDecStmt, *ast.AssignStmt, *ast.GoStmt, *ast.DeferStmt,
+		*ast.RangeStmt:
+		// no chance
+
+	case *ast.LabeledStmt:
+		return check.isTerminating(s.Stmt, s.Label.Name)
+
+	case *ast.ExprStmt:
+		// the predeclared (possibly parenthesized) panic() function is terminating
+		if call, _ := unparen(s.X).(*ast.CallExpr); call != nil {
+			if id, _ := call.Fun.(*ast.Ident); id != nil {
+				if _, obj := check.scope.LookupParent(id.Name, token.NoPos); obj != nil {
+					if b, _ := obj.(*Builtin); b != nil && b.id == _Panic {
+						return true
+					}
+				}
+			}
+		}
+
+	case *ast.ReturnStmt:
+		return true
+
+	case *ast.BranchStmt:
+		if s.Tok == token.GOTO || s.Tok == token.FALLTHROUGH {
+			return true
+		}
+
+	case *ast.BlockStmt:
+		return check.isTerminatingList(s.List, "")
+
+	case *ast.IfStmt:
+		if s.Else != nil &&
+			check.isTerminating(s.Body, "") &&
+			check.isTerminating(s.Else, "") {
+			return true
+		}
+
+	case *ast.SwitchStmt:
+		return check.isTerminatingSwitch(s.Body, label)
+
+	case *ast.TypeSwitchStmt:
+		return check.isTerminatingSwitch(s.Body, label)
+
+	case *ast.SelectStmt:
+		for _, s := range s.Body.List {
+			cc := s.(*ast.CommClause)
+			if !check.isTerminatingList(cc.Body, "") || hasBreakList(cc.Body, label, true) {
+				return false
+			}
+
+		}
+		return true
+
+	case *ast.ForStmt:
+		if s.Cond == nil && !hasBreak(s.Body, label, true) {
+			return true
+		}
+	}
+
+	return false
+}
+
+func (check *Checker) isTerminatingList(list []ast.Stmt, label string) bool {
+	n := len(list)
+	return n > 0 && check.isTerminating(list[n-1], label)
+}
+
+func (check *Checker) isTerminatingSwitch(body *ast.BlockStmt, label string) bool {
+	hasDefault := false
+	for _, s := range body.List {
+		cc := s.(*ast.CaseClause)
+		if cc.List == nil {
+			hasDefault = true
+		}
+		if !check.isTerminatingList(cc.Body, "") || hasBreakList(cc.Body, label, true) {
+			return false
+		}
+	}
+	return hasDefault
+}
+
+// TODO(gri) For nested breakable statements, the current implementation of hasBreak
+//	     will traverse the same subtree repeatedly, once for each label. Replace
+//           with a single-pass label/break matching phase.
+
+// hasBreak reports if s is or contains a break statement
+// referring to the label-ed statement or implicit-ly the
+// closest outer breakable statement.
+func hasBreak(s ast.Stmt, label string, implicit bool) bool {
+	switch s := s.(type) {
+	default:
+		unreachable()
+
+	case *ast.BadStmt, *ast.DeclStmt, *ast.EmptyStmt, *ast.ExprStmt,
+		*ast.SendStmt, *ast.IncDecStmt, *ast.AssignStmt, *ast.GoStmt,
+		*ast.DeferStmt, *ast.ReturnStmt:
+		// no chance
+
+	case *ast.LabeledStmt:
+		return hasBreak(s.Stmt, label, implicit)
+
+	case *ast.BranchStmt:
+		if s.Tok == token.BREAK {
+			if s.Label == nil {
+				return implicit
+			}
+			if s.Label.Name == label {
+				return true
+			}
+		}
+
+	case *ast.BlockStmt:
+		return hasBreakList(s.List, label, implicit)
+
+	case *ast.IfStmt:
+		if hasBreak(s.Body, label, implicit) ||
+			s.Else != nil && hasBreak(s.Else, label, implicit) {
+			return true
+		}
+
+	case *ast.CaseClause:
+		return hasBreakList(s.Body, label, implicit)
+
+	case *ast.SwitchStmt:
+		if label != "" && hasBreak(s.Body, label, false) {
+			return true
+		}
+
+	case *ast.TypeSwitchStmt:
+		if label != "" && hasBreak(s.Body, label, false) {
+			return true
+		}
+
+	case *ast.CommClause:
+		return hasBreakList(s.Body, label, implicit)
+
+	case *ast.SelectStmt:
+		if label != "" && hasBreak(s.Body, label, false) {
+			return true
+		}
+
+	case *ast.ForStmt:
+		if label != "" && hasBreak(s.Body, label, false) {
+			return true
+		}
+
+	case *ast.RangeStmt:
+		if label != "" && hasBreak(s.Body, label, false) {
+			return true
+		}
+	}
+
+	return false
+}
+
+func hasBreakList(list []ast.Stmt, label string, implicit bool) bool {
+	for _, s := range list {
+		if hasBreak(s, label, implicit) {
+			return true
+		}
+	}
+	return false
+}
diff --git a/go/types/scope.go b/go/types/scope.go
new file mode 100644
index 0000000..3502840
--- /dev/null
+++ b/go/types/scope.go
@@ -0,0 +1,190 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file implements Scopes.
+
+package types
+
+import (
+	"bytes"
+	"fmt"
+	"go/token"
+	"io"
+	"sort"
+	"strings"
+)
+
+// TODO(gri) Provide scopes with a name or other mechanism so that
+//           objects can use that information for better printing.
+
+// A Scope maintains a set of objects and links to its containing
+// (parent) and contained (children) scopes. Objects may be inserted
+// and looked up by name. The zero value for Scope is a ready-to-use
+// empty scope.
+type Scope struct {
+	parent   *Scope
+	children []*Scope
+	elems    map[string]Object // lazily allocated
+	pos, end token.Pos         // scope extent; may be invalid
+	comment  string            // for debugging only
+}
+
+// NewScope returns a new, empty scope contained in the given parent
+// scope, if any.  The comment is for debugging only.
+func NewScope(parent *Scope, pos, end token.Pos, comment string) *Scope {
+	s := &Scope{parent, nil, nil, pos, end, comment}
+	// don't add children to Universe scope!
+	if parent != nil && parent != Universe {
+		parent.children = append(parent.children, s)
+	}
+	return s
+}
+
+// Parent returns the scope's containing (parent) scope.
+func (s *Scope) Parent() *Scope { return s.parent }
+
+// Len() returns the number of scope elements.
+func (s *Scope) Len() int { return len(s.elems) }
+
+// Names returns the scope's element names in sorted order.
+func (s *Scope) Names() []string {
+	names := make([]string, len(s.elems))
+	i := 0
+	for name := range s.elems {
+		names[i] = name
+		i++
+	}
+	sort.Strings(names)
+	return names
+}
+
+// NumChildren() returns the number of scopes nested in s.
+func (s *Scope) NumChildren() int { return len(s.children) }
+
+// Child returns the i'th child scope for 0 <= i < NumChildren().
+func (s *Scope) Child(i int) *Scope { return s.children[i] }
+
+// Lookup returns the object in scope s with the given name if such an
+// object exists; otherwise the result is nil.
+func (s *Scope) Lookup(name string) Object {
+	return s.elems[name]
+}
+
+// LookupParent follows the parent chain of scopes starting with s until
+// it finds a scope where Lookup(name) returns a non-nil object, and then
+// returns that scope and object. If a valid position pos is provided,
+// only objects that were declared at or before pos are considered.
+// If no such scope and object exists, the result is (nil, nil).
+//
+// Note that obj.Parent() may be different from the returned scope if the
+// object was inserted into the scope and already had a parent at that
+// time (see Insert, below). This can only happen for dot-imported objects
+// whose scope is the scope of the package that exported them.
+func (s *Scope) LookupParent(name string, pos token.Pos) (*Scope, Object) {
+	for ; s != nil; s = s.parent {
+		if obj := s.elems[name]; obj != nil && (!pos.IsValid() || obj.scopePos() <= pos) {
+			return s, obj
+		}
+	}
+	return nil, nil
+}
+
+// Insert attempts to insert an object obj into scope s.
+// If s already contains an alternative object alt with
+// the same name, Insert leaves s unchanged and returns alt.
+// Otherwise it inserts obj, sets the object's parent scope
+// if not already set, and returns nil.
+func (s *Scope) Insert(obj Object) Object {
+	name := obj.Name()
+	if alt := s.elems[name]; alt != nil {
+		return alt
+	}
+	if s.elems == nil {
+		s.elems = make(map[string]Object)
+	}
+	s.elems[name] = obj
+	if obj.Parent() == nil {
+		obj.setParent(s)
+	}
+	return nil
+}
+
+// Pos and End describe the scope's source code extent [pos, end).
+// The results are guaranteed to be valid only if the type-checked
+// AST has complete position information. The extent is undefined
+// for Universe and package scopes.
+func (s *Scope) Pos() token.Pos { return s.pos }
+func (s *Scope) End() token.Pos { return s.end }
+
+// Contains returns true if pos is within the scope's extent.
+// The result is guaranteed to be valid only if the type-checked
+// AST has complete position information.
+func (s *Scope) Contains(pos token.Pos) bool {
+	return s.pos <= pos && pos < s.end
+}
+
+// Innermost returns the innermost (child) scope containing
+// pos. If pos is not within any scope, the result is nil.
+// The result is also nil for the Universe scope.
+// The result is guaranteed to be valid only if the type-checked
+// AST has complete position information.
+func (s *Scope) Innermost(pos token.Pos) *Scope {
+	// Package scopes do not have extents since they may be
+	// discontiguous, so iterate over the package's files.
+	if s.parent == Universe {
+		for _, s := range s.children {
+			if inner := s.Innermost(pos); inner != nil {
+				return inner
+			}
+		}
+	}
+
+	if s.Contains(pos) {
+		for _, s := range s.children {
+			if s.Contains(pos) {
+				return s.Innermost(pos)
+			}
+		}
+		return s
+	}
+	return nil
+}
+
+// WriteTo writes a string representation of the scope to w,
+// with the scope elements sorted by name.
+// The level of indentation is controlled by n >= 0, with
+// n == 0 for no indentation.
+// If recurse is set, it also writes nested (children) scopes.
+func (s *Scope) WriteTo(w io.Writer, n int, recurse bool) {
+	const ind = ".  "
+	indn := strings.Repeat(ind, n)
+
+	fmt.Fprintf(w, "%s%s scope %p {", indn, s.comment, s)
+	if len(s.elems) == 0 {
+		fmt.Fprintf(w, "}\n")
+		return
+	}
+
+	fmt.Fprintln(w)
+	indn1 := indn + ind
+	for _, name := range s.Names() {
+		fmt.Fprintf(w, "%s%s\n", indn1, s.elems[name])
+	}
+
+	if recurse {
+		for _, s := range s.children {
+			fmt.Fprintln(w)
+			s.WriteTo(w, n+1, recurse)
+		}
+	}
+
+	fmt.Fprintf(w, "%s}", indn)
+}
+
+// String returns a string representation of the scope, for debugging.
+func (s *Scope) String() string {
+	var buf bytes.Buffer
+	s.WriteTo(&buf, 0, false)
+	return buf.String()
+}
diff --git a/go/types/selection.go b/go/types/selection.go
new file mode 100644
index 0000000..124e0d3
--- /dev/null
+++ b/go/types/selection.go
@@ -0,0 +1,143 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file implements Selections.
+
+package types
+
+import (
+	"bytes"
+	"fmt"
+)
+
+// SelectionKind describes the kind of a selector expression x.f
+// (excluding qualified identifiers).
+type SelectionKind int
+
+const (
+	FieldVal   SelectionKind = iota // x.f is a struct field selector
+	MethodVal                       // x.f is a method selector
+	MethodExpr                      // x.f is a method expression
+)
+
+// A Selection describes a selector expression x.f.
+// For the declarations:
+//
+//	type T struct{ x int; E }
+//	type E struct{}
+//	func (e E) m() {}
+//	var p *T
+//
+// the following relations exist:
+//
+//	Selector    Kind          Recv    Obj    Type               Index     Indirect
+//
+//	p.x         FieldVal      T       x      int                {0}       true
+//	p.m         MethodVal     *T      m      func (e *T) m()    {1, 0}    true
+//	T.m         MethodExpr    T       m      func m(_ T)        {1, 0}    false
+//
+type Selection struct {
+	kind     SelectionKind
+	recv     Type   // type of x
+	obj      Object // object denoted by x.f
+	index    []int  // path from x to x.f
+	indirect bool   // set if there was any pointer indirection on the path
+}
+
+// Kind returns the selection kind.
+func (s *Selection) Kind() SelectionKind { return s.kind }
+
+// Recv returns the type of x in x.f.
+func (s *Selection) Recv() Type { return s.recv }
+
+// Obj returns the object denoted by x.f; a *Var for
+// a field selection, and a *Func in all other cases.
+func (s *Selection) Obj() Object { return s.obj }
+
+// Type returns the type of x.f, which may be different from the type of f.
+// See Selection for more information.
+func (s *Selection) Type() Type {
+	switch s.kind {
+	case MethodVal:
+		// The type of x.f is a method with its receiver type set
+		// to the type of x.
+		sig := *s.obj.(*Func).typ.(*Signature)
+		recv := *sig.recv
+		recv.typ = s.recv
+		sig.recv = &recv
+		return &sig
+
+	case MethodExpr:
+		// The type of x.f is a function (without receiver)
+		// and an additional first argument with the same type as x.
+		// TODO(gri) Similar code is already in call.go - factor!
+		// TODO(gri) Compute this eagerly to avoid allocations.
+		sig := *s.obj.(*Func).typ.(*Signature)
+		arg0 := *sig.recv
+		sig.recv = nil
+		arg0.typ = s.recv
+		var params []*Var
+		if sig.params != nil {
+			params = sig.params.vars
+		}
+		sig.params = NewTuple(append([]*Var{&arg0}, params...)...)
+		return &sig
+	}
+
+	// In all other cases, the type of x.f is the type of x.
+	return s.obj.Type()
+}
+
+// Index describes the path from x to f in x.f.
+// The last index entry is the field or method index of the type declaring f;
+// either:
+//
+//	1) the list of declared methods of a named type; or
+//	2) the list of methods of an interface type; or
+//	3) the list of fields of a struct type.
+//
+// The earlier index entries are the indices of the embedded fields implicitly
+// traversed to get from (the type of) x to f, starting at embedding depth 0.
+func (s *Selection) Index() []int { return s.index }
+
+// Indirect reports whether any pointer indirection was required to get from
+// x to f in x.f.
+func (s *Selection) Indirect() bool { return s.indirect }
+
+func (s *Selection) String() string { return SelectionString(s, nil) }
+
+// SelectionString returns the string form of s.
+// The Qualifier controls the printing of
+// package-level objects, and may be nil.
+//
+// Examples:
+//	"field (T) f int"
+//	"method (T) f(X) Y"
+//	"method expr (T) f(X) Y"
+//
+func SelectionString(s *Selection, qf Qualifier) string {
+	var k string
+	switch s.kind {
+	case FieldVal:
+		k = "field "
+	case MethodVal:
+		k = "method "
+	case MethodExpr:
+		k = "method expr "
+	default:
+		unreachable()
+	}
+	var buf bytes.Buffer
+	buf.WriteString(k)
+	buf.WriteByte('(')
+	WriteType(&buf, s.Recv(), qf)
+	fmt.Fprintf(&buf, ") %s", s.obj.Name())
+	if T := s.Type(); s.kind == FieldVal {
+		buf.WriteByte(' ')
+		WriteType(&buf, T, qf)
+	} else {
+		WriteSignature(&buf, T.(*Signature), qf)
+	}
+	return buf.String()
+}
diff --git a/go/types/self_test.go b/go/types/self_test.go
new file mode 100644
index 0000000..01d12c7
--- /dev/null
+++ b/go/types/self_test.go
@@ -0,0 +1,101 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package types_test
+
+import (
+	"flag"
+	"fmt"
+	"go/ast"
+	"go/parser"
+	"go/token"
+	"path/filepath"
+	"testing"
+	"time"
+
+	_ "golang.org/x/tools/go/gcimporter"
+	. "golang.org/x/tools/go/types"
+)
+
+var benchmark = flag.Bool("b", false, "run benchmarks")
+
+func TestSelf(t *testing.T) {
+	fset := token.NewFileSet()
+	files, err := pkgFiles(fset, ".")
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	_, err = Check("go/types", fset, files)
+	if err != nil {
+		// Importing go.tools/go/exact doensn't work in the
+		// build dashboard environment. Don't report an error
+		// for now so that the build remains green.
+		// TODO(gri) fix this
+		t.Log(err) // replace w/ t.Fatal eventually
+		return
+	}
+}
+
+func TestBenchmark(t *testing.T) {
+	if !*benchmark {
+		return
+	}
+
+	// We're not using testing's benchmarking mechanism directly
+	// because we want custom output.
+
+	for _, p := range []string{"types", "exact", "gcimporter"} {
+		path := filepath.Join("..", p)
+		runbench(t, path, false)
+		runbench(t, path, true)
+		fmt.Println()
+	}
+}
+
+func runbench(t *testing.T, path string, ignoreFuncBodies bool) {
+	fset := token.NewFileSet()
+	files, err := pkgFiles(fset, path)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	b := testing.Benchmark(func(b *testing.B) {
+		for i := 0; i < b.N; i++ {
+			conf := Config{IgnoreFuncBodies: ignoreFuncBodies}
+			conf.Check(path, fset, files, nil)
+		}
+	})
+
+	// determine line count
+	lines := 0
+	fset.Iterate(func(f *token.File) bool {
+		lines += f.LineCount()
+		return true
+	})
+
+	d := time.Duration(b.NsPerOp())
+	fmt.Printf(
+		"%s: %s for %d lines (%d lines/s), ignoreFuncBodies = %v\n",
+		filepath.Base(path), d, lines, int64(float64(lines)/d.Seconds()), ignoreFuncBodies,
+	)
+}
+
+func pkgFiles(fset *token.FileSet, path string) ([]*ast.File, error) {
+	filenames, err := pkgFilenames(path) // from stdlib_test.go
+	if err != nil {
+		return nil, err
+	}
+
+	var files []*ast.File
+	for _, filename := range filenames {
+		file, err := parser.ParseFile(fset, filename, nil, 0)
+		if err != nil {
+			return nil, err
+		}
+		files = append(files, file)
+	}
+
+	return files, nil
+}
diff --git a/go/types/sizes.go b/go/types/sizes.go
new file mode 100644
index 0000000..56fb310
--- /dev/null
+++ b/go/types/sizes.go
@@ -0,0 +1,211 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file implements Sizes.
+
+package types
+
+// Sizes defines the sizing functions for package unsafe.
+type Sizes interface {
+	// Alignof returns the alignment of a variable of type T.
+	// Alignof must implement the alignment guarantees required by the spec.
+	Alignof(T Type) int64
+
+	// Offsetsof returns the offsets of the given struct fields, in bytes.
+	// Offsetsof must implement the offset guarantees required by the spec.
+	Offsetsof(fields []*Var) []int64
+
+	// Sizeof returns the size of a variable of type T.
+	// Sizeof must implement the size guarantees required by the spec.
+	Sizeof(T Type) int64
+}
+
+// StdSizes is a convenience type for creating commonly used Sizes.
+// It makes the following simplifying assumptions:
+//
+//	- The size of explicitly sized basic types (int16, etc.) is the
+//	  specified size.
+//	- The size of strings and interfaces is 2*WordSize.
+//	- The size of slices is 3*WordSize.
+//	- The size of an array of n elements corresponds to the size of
+//	  a struct of n consecutive fields of the array's element type.
+//      - The size of a struct is the offset of the last field plus that
+//	  field's size. As with all element types, if the struct is used
+//	  in an array its size must first be aligned to a multiple of the
+//	  struct's alignment.
+//	- All other types have size WordSize.
+//	- Arrays and structs are aligned per spec definition; all other
+//	  types are naturally aligned with a maximum alignment MaxAlign.
+//
+// *StdSizes implements Sizes.
+//
+type StdSizes struct {
+	WordSize int64 // word size in bytes - must be >= 4 (32bits)
+	MaxAlign int64 // maximum alignment in bytes - must be >= 1
+}
+
+func (s *StdSizes) Alignof(T Type) int64 {
+	// For arrays and structs, alignment is defined in terms
+	// of alignment of the elements and fields, respectively.
+	switch t := T.Underlying().(type) {
+	case *Array:
+		// spec: "For a variable x of array type: unsafe.Alignof(x)
+		// is the same as unsafe.Alignof(x[0]), but at least 1."
+		return s.Alignof(t.elem)
+	case *Struct:
+		// spec: "For a variable x of struct type: unsafe.Alignof(x)
+		// is the largest of the values unsafe.Alignof(x.f) for each
+		// field f of x, but at least 1."
+		max := int64(1)
+		for _, f := range t.fields {
+			if a := s.Alignof(f.typ); a > max {
+				max = a
+			}
+		}
+		return max
+	}
+	a := s.Sizeof(T) // may be 0
+	// spec: "For a variable x of any type: unsafe.Alignof(x) is at least 1."
+	if a < 1 {
+		return 1
+	}
+	if a > s.MaxAlign {
+		return s.MaxAlign
+	}
+	return a
+}
+
+func (s *StdSizes) Offsetsof(fields []*Var) []int64 {
+	offsets := make([]int64, len(fields))
+	var o int64
+	for i, f := range fields {
+		a := s.Alignof(f.typ)
+		o = align(o, a)
+		offsets[i] = o
+		o += s.Sizeof(f.typ)
+	}
+	return offsets
+}
+
+var basicSizes = [...]byte{
+	Bool:       1,
+	Int8:       1,
+	Int16:      2,
+	Int32:      4,
+	Int64:      8,
+	Uint8:      1,
+	Uint16:     2,
+	Uint32:     4,
+	Uint64:     8,
+	Float32:    4,
+	Float64:    8,
+	Complex64:  8,
+	Complex128: 16,
+}
+
+func (s *StdSizes) Sizeof(T Type) int64 {
+	switch t := T.Underlying().(type) {
+	case *Basic:
+		assert(isTyped(T))
+		k := t.kind
+		if int(k) < len(basicSizes) {
+			if s := basicSizes[k]; s > 0 {
+				return int64(s)
+			}
+		}
+		if k == String {
+			return s.WordSize * 2
+		}
+	case *Array:
+		n := t.len
+		if n == 0 {
+			return 0
+		}
+		a := s.Alignof(t.elem)
+		z := s.Sizeof(t.elem)
+		return align(z, a)*(n-1) + z
+	case *Slice:
+		return s.WordSize * 3
+	case *Struct:
+		n := t.NumFields()
+		if n == 0 {
+			return 0
+		}
+		offsets := t.offsets
+		if t.offsets == nil {
+			// compute offsets on demand
+			offsets = s.Offsetsof(t.fields)
+			t.offsets = offsets
+		}
+		return offsets[n-1] + s.Sizeof(t.fields[n-1].typ)
+	case *Interface:
+		return s.WordSize * 2
+	}
+	return s.WordSize // catch-all
+}
+
+// stdSizes is used if Config.Sizes == nil.
+var stdSizes = StdSizes{8, 8}
+
+func (conf *Config) alignof(T Type) int64 {
+	if s := conf.Sizes; s != nil {
+		if a := s.Alignof(T); a >= 1 {
+			return a
+		}
+		panic("Config.Sizes.Alignof returned an alignment < 1")
+	}
+	return stdSizes.Alignof(T)
+}
+
+func (conf *Config) offsetsof(T *Struct) []int64 {
+	offsets := T.offsets
+	if offsets == nil && T.NumFields() > 0 {
+		// compute offsets on demand
+		if s := conf.Sizes; s != nil {
+			offsets = s.Offsetsof(T.fields)
+			// sanity checks
+			if len(offsets) != T.NumFields() {
+				panic("Config.Sizes.Offsetsof returned the wrong number of offsets")
+			}
+			for _, o := range offsets {
+				if o < 0 {
+					panic("Config.Sizes.Offsetsof returned an offset < 0")
+				}
+			}
+		} else {
+			offsets = stdSizes.Offsetsof(T.fields)
+		}
+		T.offsets = offsets
+	}
+	return offsets
+}
+
+// offsetof returns the offset of the field specified via
+// the index sequence relative to typ. All embedded fields
+// must be structs (rather than pointer to structs).
+func (conf *Config) offsetof(typ Type, index []int) int64 {
+	var o int64
+	for _, i := range index {
+		s := typ.Underlying().(*Struct)
+		o += conf.offsetsof(s)[i]
+		typ = s.fields[i].typ
+	}
+	return o
+}
+
+func (conf *Config) sizeof(T Type) int64 {
+	if s := conf.Sizes; s != nil {
+		if z := s.Sizeof(T); z >= 0 {
+			return z
+		}
+		panic("Config.Sizes.Sizeof returned a size < 0")
+	}
+	return stdSizes.Sizeof(T)
+}
+
+// align returns the smallest y >= x such that y % a == 0.
+func align(x, a int64) int64 {
+	y := x + a - 1
+	return y - y%a
+}
diff --git a/go/types/stdlib_test.go b/go/types/stdlib_test.go
new file mode 100644
index 0000000..d6aa82a
--- /dev/null
+++ b/go/types/stdlib_test.go
@@ -0,0 +1,270 @@
+// Copyright 2013 The Go 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 tests types.Check by using it to
+// typecheck the standard library and tests.
+
+package types_test
+
+import (
+	"fmt"
+	"go/ast"
+	"go/build"
+	"go/parser"
+	"go/scanner"
+	"go/token"
+	"io/ioutil"
+	"os"
+	"path/filepath"
+	"runtime"
+	"strings"
+	"testing"
+	"time"
+
+	_ "golang.org/x/tools/go/gcimporter"
+	. "golang.org/x/tools/go/types"
+)
+
+var (
+	pkgCount int // number of packages processed
+	start    = time.Now()
+)
+
+func TestStdlib(t *testing.T) {
+	skipSpecialPlatforms(t)
+
+	walkDirs(t, filepath.Join(runtime.GOROOT(), "src"))
+	if testing.Verbose() {
+		fmt.Println(pkgCount, "packages typechecked in", time.Since(start))
+	}
+}
+
+// firstComment returns the contents of the first comment in
+// the given file, assuming there's one within the first KB.
+func firstComment(filename string) string {
+	f, err := os.Open(filename)
+	if err != nil {
+		return ""
+	}
+	defer f.Close()
+
+	var src [1 << 10]byte // read at most 1KB
+	n, _ := f.Read(src[:])
+
+	var s scanner.Scanner
+	s.Init(fset.AddFile("", fset.Base(), n), src[:n], nil, scanner.ScanComments)
+	for {
+		_, tok, lit := s.Scan()
+		switch tok {
+		case token.COMMENT:
+			// remove trailing */ of multi-line comment
+			if lit[1] == '*' {
+				lit = lit[:len(lit)-2]
+			}
+			return strings.TrimSpace(lit[2:])
+		case token.EOF:
+			return ""
+		}
+	}
+}
+
+func testTestDir(t *testing.T, path string, ignore ...string) {
+	files, err := ioutil.ReadDir(path)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	excluded := make(map[string]bool)
+	for _, filename := range ignore {
+		excluded[filename] = true
+	}
+
+	fset := token.NewFileSet()
+	for _, f := range files {
+		// filter directory contents
+		if f.IsDir() || !strings.HasSuffix(f.Name(), ".go") || excluded[f.Name()] {
+			continue
+		}
+
+		// get per-file instructions
+		expectErrors := false
+		filename := filepath.Join(path, f.Name())
+		if cmd := firstComment(filename); cmd != "" {
+			switch cmd {
+			case "skip", "compiledir":
+				continue // ignore this file
+			case "errorcheck":
+				expectErrors = true
+			}
+		}
+
+		// parse and type-check file
+		file, err := parser.ParseFile(fset, filename, nil, 0)
+		if err == nil {
+			_, err = Check(filename, fset, []*ast.File{file})
+		}
+
+		if expectErrors {
+			if err == nil {
+				t.Errorf("expected errors but found none in %s", filename)
+			}
+		} else {
+			if err != nil {
+				t.Error(err)
+			}
+		}
+	}
+}
+
+func TestStdTest(t *testing.T) {
+	skipSpecialPlatforms(t)
+
+	// test/recover4.go is only built for Linux and Darwin.
+	// TODO(gri) Remove once tests consider +build tags (issue 10370).
+	if runtime.GOOS != "linux" && runtime.GOOS != "darwin" {
+		return
+	}
+
+	testTestDir(t, filepath.Join(runtime.GOROOT(), "test"),
+		"cmplxdivide.go", // also needs file cmplxdivide1.go - ignore
+		"sigchld.go",     // don't work on Windows; testTestDir should consult build tags
+	)
+}
+
+func TestStdFixed(t *testing.T) {
+	skipSpecialPlatforms(t)
+
+	testTestDir(t, filepath.Join(runtime.GOROOT(), "test", "fixedbugs"),
+		"bug248.go", "bug302.go", "bug369.go", // complex test instructions - ignore
+		"bug459.go",      // possibly incorrect test - see issue 6703 (pending spec clarification)
+		"issue3924.go",   // possibly incorrect test - see issue 6671 (pending spec clarification)
+		"issue6889.go",   // gc-specific test
+		"issue7746.go",   // large constants - consumes too much memory
+		"issue11326.go",  // large constants
+		"issue11326b.go", // large constants
+	)
+}
+
+func TestStdKen(t *testing.T) {
+	skipSpecialPlatforms(t)
+
+	testTestDir(t, filepath.Join(runtime.GOROOT(), "test", "ken"))
+}
+
+// Package paths of excluded packages.
+var excluded = map[string]bool{
+	"builtin": true,
+}
+
+// typecheck typechecks the given package files.
+func typecheck(t *testing.T, path string, filenames []string) {
+	fset := token.NewFileSet()
+
+	// parse package files
+	var files []*ast.File
+	for _, filename := range filenames {
+		file, err := parser.ParseFile(fset, filename, nil, parser.AllErrors)
+		if err != nil {
+			// the parser error may be a list of individual errors; report them all
+			if list, ok := err.(scanner.ErrorList); ok {
+				for _, err := range list {
+					t.Error(err)
+				}
+				return
+			}
+			t.Error(err)
+			return
+		}
+
+		if testing.Verbose() {
+			if len(files) == 0 {
+				fmt.Println("package", file.Name.Name)
+			}
+			fmt.Println("\t", filename)
+		}
+
+		files = append(files, file)
+	}
+
+	// typecheck package files
+	var conf Config
+	conf.Error = func(err error) { t.Error(err) }
+	info := Info{Uses: make(map[*ast.Ident]Object)}
+	conf.Check(path, fset, files, &info)
+	pkgCount++
+
+	// Perform checks of API invariants.
+
+	// All Objects have a package, except predeclared ones.
+	errorError := Universe.Lookup("error").Type().Underlying().(*Interface).ExplicitMethod(0) // (error).Error
+	for id, obj := range info.Uses {
+		predeclared := obj == Universe.Lookup(obj.Name()) || obj == errorError
+		if predeclared == (obj.Pkg() != nil) {
+			posn := fset.Position(id.Pos())
+			if predeclared {
+				t.Errorf("%s: predeclared object with package: %s", posn, obj)
+			} else {
+				t.Errorf("%s: user-defined object without package: %s", posn, obj)
+			}
+		}
+	}
+}
+
+// pkgFilenames returns the list of package filenames for the given directory.
+func pkgFilenames(dir string) ([]string, error) {
+	ctxt := build.Default
+	ctxt.CgoEnabled = false
+	pkg, err := ctxt.ImportDir(dir, 0)
+	if err != nil {
+		if _, nogo := err.(*build.NoGoError); nogo {
+			return nil, nil // no *.go files, not an error
+		}
+		return nil, err
+	}
+	if excluded[pkg.ImportPath] {
+		return nil, nil
+	}
+	var filenames []string
+	for _, name := range pkg.GoFiles {
+		filenames = append(filenames, filepath.Join(pkg.Dir, name))
+	}
+	for _, name := range pkg.TestGoFiles {
+		filenames = append(filenames, filepath.Join(pkg.Dir, name))
+	}
+	return filenames, nil
+}
+
+// Note: Could use filepath.Walk instead of walkDirs but that wouldn't
+//       necessarily be shorter or clearer after adding the code to
+//       terminate early for -short tests.
+
+func walkDirs(t *testing.T, dir string) {
+	// limit run time for short tests
+	if testing.Short() && time.Since(start) >= 750*time.Millisecond {
+		return
+	}
+
+	fis, err := ioutil.ReadDir(dir)
+	if err != nil {
+		t.Error(err)
+		return
+	}
+
+	// typecheck package in directory
+	files, err := pkgFilenames(dir)
+	if err != nil {
+		t.Error(err)
+		return
+	}
+	if files != nil {
+		typecheck(t, dir, files)
+	}
+
+	// traverse subdirectories, but don't walk into testdata
+	for _, fi := range fis {
+		if fi.IsDir() && fi.Name() != "testdata" {
+			walkDirs(t, filepath.Join(dir, fi.Name()))
+		}
+	}
+}
diff --git a/go/types/stmt.go b/go/types/stmt.go
new file mode 100644
index 0000000..eeb2c31
--- /dev/null
+++ b/go/types/stmt.go
@@ -0,0 +1,745 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file implements typechecking of statements.
+
+package types
+
+import (
+	"fmt"
+	"go/ast"
+	"go/token"
+
+	"golang.org/x/tools/go/exact"
+)
+
+func (check *Checker) funcBody(decl *declInfo, name string, sig *Signature, body *ast.BlockStmt) {
+	if trace {
+		if name == "" {
+			name = "<function literal>"
+		}
+		fmt.Printf("--- %s: %s {\n", name, sig)
+		defer fmt.Println("--- <end>")
+	}
+
+	// set function scope extent
+	sig.scope.pos = body.Pos()
+	sig.scope.end = body.End()
+
+	// save/restore current context and setup function context
+	// (and use 0 indentation at function start)
+	defer func(ctxt context, indent int) {
+		check.context = ctxt
+		check.indent = indent
+	}(check.context, check.indent)
+	check.context = context{
+		decl:  decl,
+		scope: sig.scope,
+		sig:   sig,
+	}
+	check.indent = 0
+
+	check.stmtList(0, body.List)
+
+	if check.hasLabel {
+		check.labels(body)
+	}
+
+	if sig.results.Len() > 0 && !check.isTerminating(body, "") {
+		check.error(body.Rbrace, "missing return")
+	}
+
+	// spec: "Implementation restriction: A compiler may make it illegal to
+	// declare a variable inside a function body if the variable is never used."
+	// (One could check each scope after use, but that distributes this check
+	// over several places because CloseScope is not always called explicitly.)
+	check.usage(sig.scope)
+}
+
+func (check *Checker) usage(scope *Scope) {
+	for _, obj := range scope.elems {
+		if v, _ := obj.(*Var); v != nil && !v.used {
+			check.softErrorf(v.pos, "%s declared but not used", v.name)
+		}
+	}
+	for _, scope := range scope.children {
+		check.usage(scope)
+	}
+}
+
+// stmtContext is a bitset describing which
+// control-flow statements are permissible.
+type stmtContext uint
+
+const (
+	breakOk stmtContext = 1 << iota
+	continueOk
+	fallthroughOk
+)
+
+func (check *Checker) simpleStmt(s ast.Stmt) {
+	if s != nil {
+		check.stmt(0, s)
+	}
+}
+
+func (check *Checker) stmtList(ctxt stmtContext, list []ast.Stmt) {
+	ok := ctxt&fallthroughOk != 0
+	inner := ctxt &^ fallthroughOk
+	for i, s := range list {
+		inner := inner
+		if ok && i+1 == len(list) {
+			inner |= fallthroughOk
+		}
+		check.stmt(inner, s)
+	}
+}
+
+func (check *Checker) multipleDefaults(list []ast.Stmt) {
+	var first ast.Stmt
+	for _, s := range list {
+		var d ast.Stmt
+		switch c := s.(type) {
+		case *ast.CaseClause:
+			if len(c.List) == 0 {
+				d = s
+			}
+		case *ast.CommClause:
+			if c.Comm == nil {
+				d = s
+			}
+		default:
+			check.invalidAST(s.Pos(), "case/communication clause expected")
+		}
+		if d != nil {
+			if first != nil {
+				check.errorf(d.Pos(), "multiple defaults (first at %s)", first.Pos())
+			} else {
+				first = d
+			}
+		}
+	}
+}
+
+func (check *Checker) openScope(s ast.Stmt, comment string) {
+	scope := NewScope(check.scope, s.Pos(), s.End(), comment)
+	check.recordScope(s, scope)
+	check.scope = scope
+}
+
+func (check *Checker) closeScope() {
+	check.scope = check.scope.Parent()
+}
+
+func assignOp(op token.Token) token.Token {
+	// token_test.go verifies the token ordering this function relies on
+	if token.ADD_ASSIGN <= op && op <= token.AND_NOT_ASSIGN {
+		return op + (token.ADD - token.ADD_ASSIGN)
+	}
+	return token.ILLEGAL
+}
+
+func (check *Checker) suspendedCall(keyword string, call *ast.CallExpr) {
+	var x operand
+	var msg string
+	switch check.rawExpr(&x, call, nil) {
+	case conversion:
+		msg = "requires function call, not conversion"
+	case expression:
+		msg = "discards result of"
+	case statement:
+		return
+	default:
+		unreachable()
+	}
+	check.errorf(x.pos(), "%s %s %s", keyword, msg, &x)
+}
+
+func (check *Checker) caseValues(x operand /* copy argument (not *operand!) */, values []ast.Expr) {
+	// No duplicate checking for now. See issue 4524.
+	for _, e := range values {
+		var y operand
+		check.expr(&y, e)
+		if y.mode == invalid {
+			return
+		}
+		// TODO(gri) The convertUntyped call pair below appears in other places. Factor!
+		// Order matters: By comparing y against x, error positions are at the case values.
+		check.convertUntyped(&y, x.typ)
+		if y.mode == invalid {
+			return
+		}
+		check.convertUntyped(&x, y.typ)
+		if x.mode == invalid {
+			return
+		}
+		check.comparison(&y, &x, token.EQL)
+	}
+}
+
+func (check *Checker) caseTypes(x *operand, xtyp *Interface, types []ast.Expr, seen map[Type]token.Pos) (T Type) {
+L:
+	for _, e := range types {
+		T = check.typOrNil(e)
+		if T == Typ[Invalid] {
+			continue
+		}
+		// complain about duplicate types
+		// TODO(gri) use a type hash to avoid quadratic algorithm
+		for t, pos := range seen {
+			if T == nil && t == nil || T != nil && t != nil && Identical(T, t) {
+				// talk about "case" rather than "type" because of nil case
+				check.error(e.Pos(), "duplicate case in type switch")
+				check.errorf(pos, "\tprevious case %s", T) // secondary error, \t indented
+				continue L
+			}
+		}
+		seen[T] = e.Pos()
+		if T != nil {
+			check.typeAssertion(e.Pos(), x, xtyp, T)
+		}
+	}
+	return
+}
+
+// stmt typechecks statement s.
+func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) {
+	// statements cannot use iota in general
+	// (constant declarations set it explicitly)
+	assert(check.iota == nil)
+
+	// statements must end with the same top scope as they started with
+	if debug {
+		defer func(scope *Scope) {
+			// don't check if code is panicking
+			if p := recover(); p != nil {
+				panic(p)
+			}
+			assert(scope == check.scope)
+		}(check.scope)
+	}
+
+	inner := ctxt &^ fallthroughOk
+	switch s := s.(type) {
+	case *ast.BadStmt, *ast.EmptyStmt:
+		// ignore
+
+	case *ast.DeclStmt:
+		check.declStmt(s.Decl)
+
+	case *ast.LabeledStmt:
+		check.hasLabel = true
+		check.stmt(ctxt, s.Stmt)
+
+	case *ast.ExprStmt:
+		// spec: "With the exception of specific built-in functions,
+		// function and method calls and receive operations can appear
+		// in statement context. Such statements may be parenthesized."
+		var x operand
+		kind := check.rawExpr(&x, s.X, nil)
+		var msg string
+		switch x.mode {
+		default:
+			if kind == statement {
+				return
+			}
+			msg = "is not used"
+		case builtin:
+			msg = "must be called"
+		case typexpr:
+			msg = "is not an expression"
+		}
+		check.errorf(x.pos(), "%s %s", &x, msg)
+
+	case *ast.SendStmt:
+		var ch, x operand
+		check.expr(&ch, s.Chan)
+		check.expr(&x, s.Value)
+		if ch.mode == invalid || x.mode == invalid {
+			return
+		}
+		if tch, ok := ch.typ.Underlying().(*Chan); !ok || tch.dir == RecvOnly || !check.assignment(&x, tch.elem) {
+			if x.mode != invalid {
+				check.invalidOp(ch.pos(), "cannot send %s to channel %s", &x, &ch)
+			}
+		}
+
+	case *ast.IncDecStmt:
+		var op token.Token
+		switch s.Tok {
+		case token.INC:
+			op = token.ADD
+		case token.DEC:
+			op = token.SUB
+		default:
+			check.invalidAST(s.TokPos, "unknown inc/dec operation %s", s.Tok)
+			return
+		}
+		var x operand
+		Y := &ast.BasicLit{ValuePos: s.X.Pos(), Kind: token.INT, Value: "1"} // use x's position
+		check.binary(&x, nil, s.X, Y, op)
+		if x.mode == invalid {
+			return
+		}
+		check.assignVar(s.X, &x)
+
+	case *ast.AssignStmt:
+		switch s.Tok {
+		case token.ASSIGN, token.DEFINE:
+			if len(s.Lhs) == 0 {
+				check.invalidAST(s.Pos(), "missing lhs in assignment")
+				return
+			}
+			if s.Tok == token.DEFINE {
+				check.shortVarDecl(s.TokPos, s.Lhs, s.Rhs)
+			} else {
+				// regular assignment
+				check.assignVars(s.Lhs, s.Rhs)
+			}
+
+		default:
+			// assignment operations
+			if len(s.Lhs) != 1 || len(s.Rhs) != 1 {
+				check.errorf(s.TokPos, "assignment operation %s requires single-valued expressions", s.Tok)
+				return
+			}
+			op := assignOp(s.Tok)
+			if op == token.ILLEGAL {
+				check.invalidAST(s.TokPos, "unknown assignment operation %s", s.Tok)
+				return
+			}
+			var x operand
+			check.binary(&x, nil, s.Lhs[0], s.Rhs[0], op)
+			if x.mode == invalid {
+				return
+			}
+			check.assignVar(s.Lhs[0], &x)
+		}
+
+	case *ast.GoStmt:
+		check.suspendedCall("go", s.Call)
+
+	case *ast.DeferStmt:
+		check.suspendedCall("defer", s.Call)
+
+	case *ast.ReturnStmt:
+		res := check.sig.results
+		if res.Len() > 0 {
+			// function returns results
+			// (if one, say the first, result parameter is named, all of them are named)
+			if len(s.Results) == 0 && res.vars[0].name != "" {
+				// spec: "Implementation restriction: A compiler may disallow an empty expression
+				// list in a "return" statement if a different entity (constant, type, or variable)
+				// with the same name as a result parameter is in scope at the place of the return."
+				for _, obj := range res.vars {
+					if _, alt := check.scope.LookupParent(obj.name, check.pos); alt != nil && alt != obj {
+						check.errorf(s.Pos(), "result parameter %s not in scope at return", obj.name)
+						check.errorf(alt.Pos(), "\tinner declaration of %s", obj)
+						// ok to continue
+					}
+				}
+			} else {
+				// return has results or result parameters are unnamed
+				check.initVars(res.vars, s.Results, s.Return)
+			}
+		} else if len(s.Results) > 0 {
+			check.error(s.Results[0].Pos(), "no result values expected")
+			check.use(s.Results...)
+		}
+
+	case *ast.BranchStmt:
+		if s.Label != nil {
+			check.hasLabel = true
+			return // checked in 2nd pass (check.labels)
+		}
+		switch s.Tok {
+		case token.BREAK:
+			if ctxt&breakOk == 0 {
+				check.error(s.Pos(), "break not in for, switch, or select statement")
+			}
+		case token.CONTINUE:
+			if ctxt&continueOk == 0 {
+				check.error(s.Pos(), "continue not in for statement")
+			}
+		case token.FALLTHROUGH:
+			if ctxt&fallthroughOk == 0 {
+				check.error(s.Pos(), "fallthrough statement out of place")
+			}
+		default:
+			check.invalidAST(s.Pos(), "branch statement: %s", s.Tok)
+		}
+
+	case *ast.BlockStmt:
+		check.openScope(s, "block")
+		defer check.closeScope()
+
+		check.stmtList(inner, s.List)
+
+	case *ast.IfStmt:
+		check.openScope(s, "if")
+		defer check.closeScope()
+
+		check.simpleStmt(s.Init)
+		var x operand
+		check.expr(&x, s.Cond)
+		if x.mode != invalid && !isBoolean(x.typ) {
+			check.error(s.Cond.Pos(), "non-boolean condition in if statement")
+		}
+		check.stmt(inner, s.Body)
+		if s.Else != nil {
+			check.stmt(inner, s.Else)
+		}
+
+	case *ast.SwitchStmt:
+		inner |= breakOk
+		check.openScope(s, "switch")
+		defer check.closeScope()
+
+		check.simpleStmt(s.Init)
+		var x operand
+		if s.Tag != nil {
+			check.expr(&x, s.Tag)
+		} else {
+			// spec: "A missing switch expression is
+			// equivalent to the boolean value true."
+			x.mode = constant
+			x.typ = Typ[Bool]
+			x.val = exact.MakeBool(true)
+			x.expr = &ast.Ident{NamePos: s.Body.Lbrace, Name: "true"}
+		}
+
+		check.multipleDefaults(s.Body.List)
+
+		for i, c := range s.Body.List {
+			clause, _ := c.(*ast.CaseClause)
+			if clause == nil {
+				check.invalidAST(c.Pos(), "incorrect expression switch case")
+				continue
+			}
+			if x.mode != invalid {
+				check.caseValues(x, clause.List)
+			}
+			check.openScope(clause, "case")
+			inner := inner
+			if i+1 < len(s.Body.List) {
+				inner |= fallthroughOk
+			}
+			check.stmtList(inner, clause.Body)
+			check.closeScope()
+		}
+
+	case *ast.TypeSwitchStmt:
+		inner |= breakOk
+		check.openScope(s, "type switch")
+		defer check.closeScope()
+
+		check.simpleStmt(s.Init)
+
+		// A type switch guard must be of the form:
+		//
+		//     TypeSwitchGuard = [ identifier ":=" ] PrimaryExpr "." "(" "type" ")" .
+		//
+		// The parser is checking syntactic correctness;
+		// remaining syntactic errors are considered AST errors here.
+		// TODO(gri) better factoring of error handling (invalid ASTs)
+		//
+		var lhs *ast.Ident // lhs identifier or nil
+		var rhs ast.Expr
+		switch guard := s.Assign.(type) {
+		case *ast.ExprStmt:
+			rhs = guard.X
+		case *ast.AssignStmt:
+			if len(guard.Lhs) != 1 || guard.Tok != token.DEFINE || len(guard.Rhs) != 1 {
+				check.invalidAST(s.Pos(), "incorrect form of type switch guard")
+				return
+			}
+
+			lhs, _ = guard.Lhs[0].(*ast.Ident)
+			if lhs == nil {
+				check.invalidAST(s.Pos(), "incorrect form of type switch guard")
+				return
+			}
+
+			if lhs.Name == "_" {
+				// _ := x.(type) is an invalid short variable declaration
+				check.softErrorf(lhs.Pos(), "no new variable on left side of :=")
+				lhs = nil // avoid declared but not used error below
+			} else {
+				check.recordDef(lhs, nil) // lhs variable is implicitly declared in each cause clause
+			}
+
+			rhs = guard.Rhs[0]
+
+		default:
+			check.invalidAST(s.Pos(), "incorrect form of type switch guard")
+			return
+		}
+
+		// rhs must be of the form: expr.(type) and expr must be an interface
+		expr, _ := rhs.(*ast.TypeAssertExpr)
+		if expr == nil || expr.Type != nil {
+			check.invalidAST(s.Pos(), "incorrect form of type switch guard")
+			return
+		}
+		var x operand
+		check.expr(&x, expr.X)
+		if x.mode == invalid {
+			return
+		}
+		xtyp, _ := x.typ.Underlying().(*Interface)
+		if xtyp == nil {
+			check.errorf(x.pos(), "%s is not an interface", &x)
+			return
+		}
+
+		check.multipleDefaults(s.Body.List)
+
+		var lhsVars []*Var               // list of implicitly declared lhs variables
+		seen := make(map[Type]token.Pos) // map of seen types to positions
+		for _, s := range s.Body.List {
+			clause, _ := s.(*ast.CaseClause)
+			if clause == nil {
+				check.invalidAST(s.Pos(), "incorrect type switch case")
+				continue
+			}
+			// Check each type in this type switch case.
+			T := check.caseTypes(&x, xtyp, clause.List, seen)
+			check.openScope(clause, "case")
+			// If lhs exists, declare a corresponding variable in the case-local scope.
+			if lhs != nil {
+				// spec: "The TypeSwitchGuard may include a short variable declaration.
+				// When that form is used, the variable is declared at the beginning of
+				// the implicit block in each clause. In clauses with a case listing
+				// exactly one type, the variable has that type; otherwise, the variable
+				// has the type of the expression in the TypeSwitchGuard."
+				if len(clause.List) != 1 || T == nil {
+					T = x.typ
+				}
+				obj := NewVar(lhs.Pos(), check.pkg, lhs.Name, T)
+				scopePos := clause.End()
+				if len(clause.Body) > 0 {
+					scopePos = clause.Body[0].Pos()
+				}
+				check.declare(check.scope, nil, obj, scopePos)
+				check.recordImplicit(clause, obj)
+				// For the "declared but not used" error, all lhs variables act as
+				// one; i.e., if any one of them is 'used', all of them are 'used'.
+				// Collect them for later analysis.
+				lhsVars = append(lhsVars, obj)
+			}
+			check.stmtList(inner, clause.Body)
+			check.closeScope()
+		}
+
+		// If lhs exists, we must have at least one lhs variable that was used.
+		if lhs != nil {
+			var used bool
+			for _, v := range lhsVars {
+				if v.used {
+					used = true
+				}
+				v.used = true // avoid usage error when checking entire function
+			}
+			if !used {
+				check.softErrorf(lhs.Pos(), "%s declared but not used", lhs.Name)
+			}
+		}
+
+	case *ast.SelectStmt:
+		inner |= breakOk
+
+		check.multipleDefaults(s.Body.List)
+
+		for _, s := range s.Body.List {
+			clause, _ := s.(*ast.CommClause)
+			if clause == nil {
+				continue // error reported before
+			}
+
+			// clause.Comm must be a SendStmt, RecvStmt, or default case
+			valid := false
+			var rhs ast.Expr // rhs of RecvStmt, or nil
+			switch s := clause.Comm.(type) {
+			case nil, *ast.SendStmt:
+				valid = true
+			case *ast.AssignStmt:
+				if len(s.Rhs) == 1 {
+					rhs = s.Rhs[0]
+				}
+			case *ast.ExprStmt:
+				rhs = s.X
+			}
+
+			// if present, rhs must be a receive operation
+			if rhs != nil {
+				if x, _ := unparen(rhs).(*ast.UnaryExpr); x != nil && x.Op == token.ARROW {
+					valid = true
+				}
+			}
+
+			if !valid {
+				check.error(clause.Comm.Pos(), "select case must be send or receive (possibly with assignment)")
+				continue
+			}
+
+			check.openScope(s, "case")
+			if clause.Comm != nil {
+				check.stmt(inner, clause.Comm)
+			}
+			check.stmtList(inner, clause.Body)
+			check.closeScope()
+		}
+
+	case *ast.ForStmt:
+		inner |= breakOk | continueOk
+		check.openScope(s, "for")
+		defer check.closeScope()
+
+		check.simpleStmt(s.Init)
+		if s.Cond != nil {
+			var x operand
+			check.expr(&x, s.Cond)
+			if x.mode != invalid && !isBoolean(x.typ) {
+				check.error(s.Cond.Pos(), "non-boolean condition in for statement")
+			}
+		}
+		check.simpleStmt(s.Post)
+		// spec: "The init statement may be a short variable
+		// declaration, but the post statement must not."
+		if s, _ := s.Post.(*ast.AssignStmt); s != nil && s.Tok == token.DEFINE {
+			check.softErrorf(s.Pos(), "cannot declare in post statement")
+			check.use(s.Lhs...) // avoid follow-up errors
+		}
+		check.stmt(inner, s.Body)
+
+	case *ast.RangeStmt:
+		inner |= breakOk | continueOk
+		check.openScope(s, "for")
+		defer check.closeScope()
+
+		// check expression to iterate over
+		var x operand
+		check.expr(&x, s.X)
+
+		// determine key/value types
+		var key, val Type
+		if x.mode != invalid {
+			switch typ := x.typ.Underlying().(type) {
+			case *Basic:
+				if isString(typ) {
+					key = Typ[Int]
+					val = universeRune // use 'rune' name
+				}
+			case *Array:
+				key = Typ[Int]
+				val = typ.elem
+			case *Slice:
+				key = Typ[Int]
+				val = typ.elem
+			case *Pointer:
+				if typ, _ := typ.base.Underlying().(*Array); typ != nil {
+					key = Typ[Int]
+					val = typ.elem
+				}
+			case *Map:
+				key = typ.key
+				val = typ.elem
+			case *Chan:
+				key = typ.elem
+				val = Typ[Invalid]
+				if typ.dir == SendOnly {
+					check.errorf(x.pos(), "cannot range over send-only channel %s", &x)
+					// ok to continue
+				}
+				if s.Value != nil {
+					check.errorf(s.Value.Pos(), "iteration over %s permits only one iteration variable", &x)
+					// ok to continue
+				}
+			}
+		}
+
+		if key == nil {
+			check.errorf(x.pos(), "cannot range over %s", &x)
+			// ok to continue
+		}
+
+		// check assignment to/declaration of iteration variables
+		// (irregular assignment, cannot easily map to existing assignment checks)
+
+		// lhs expressions and initialization value (rhs) types
+		lhs := [2]ast.Expr{s.Key, s.Value}
+		rhs := [2]Type{key, val} // key, val may be nil
+
+		if s.Tok == token.DEFINE {
+			// short variable declaration; variable scope starts after the range clause
+			// (the for loop opens a new scope, so variables on the lhs never redeclare
+			// previously declared variables)
+			var vars []*Var
+			for i, lhs := range lhs {
+				if lhs == nil {
+					continue
+				}
+
+				// determine lhs variable
+				var obj *Var
+				if ident, _ := lhs.(*ast.Ident); ident != nil {
+					// declare new variable
+					name := ident.Name
+					obj = NewVar(ident.Pos(), check.pkg, name, nil)
+					check.recordDef(ident, obj)
+					// _ variables don't count as new variables
+					if name != "_" {
+						vars = append(vars, obj)
+					}
+				} else {
+					check.errorf(lhs.Pos(), "cannot declare %s", lhs)
+					obj = NewVar(lhs.Pos(), check.pkg, "_", nil) // dummy variable
+				}
+
+				// initialize lhs variable
+				if typ := rhs[i]; typ != nil {
+					x.mode = value
+					x.expr = lhs // we don't have a better rhs expression to use here
+					x.typ = typ
+					check.initVar(obj, &x, false)
+				} else {
+					obj.typ = Typ[Invalid]
+					obj.used = true // don't complain about unused variable
+				}
+			}
+
+			// declare variables
+			if len(vars) > 0 {
+				for _, obj := range vars {
+					// spec: "The scope of a constant or variable identifier declared inside
+					// a function begins at the end of the ConstSpec or VarSpec (ShortVarDecl
+					// for short variable declarations) and ends at the end of the innermost
+					// containing block."
+					scopePos := s.End()
+					check.declare(check.scope, nil /* recordDef already called */, obj, scopePos)
+				}
+			} else {
+				check.error(s.TokPos, "no new variables on left side of :=")
+			}
+		} else {
+			// ordinary assignment
+			for i, lhs := range lhs {
+				if lhs == nil {
+					continue
+				}
+				if typ := rhs[i]; typ != nil {
+					x.mode = value
+					x.expr = lhs // we don't have a better rhs expression to use here
+					x.typ = typ
+					check.assignVar(lhs, &x)
+				}
+			}
+		}
+
+		check.stmt(inner, s.Body)
+
+	default:
+		check.error(s.Pos(), "invalid statement")
+	}
+}
diff --git a/go/types/testdata/blank.src b/go/types/testdata/blank.src
new file mode 100644
index 0000000..6a2507f
--- /dev/null
+++ b/go/types/testdata/blank.src
@@ -0,0 +1,5 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package _ /* ERROR invalid package name */
diff --git a/go/types/testdata/builtins.src b/go/types/testdata/builtins.src
new file mode 100644
index 0000000..9eb551d
--- /dev/null
+++ b/go/types/testdata/builtins.src
@@ -0,0 +1,881 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// builtin calls
+
+package builtins
+
+import "unsafe"
+
+func f0() {}
+
+func append1() {
+	var b byte
+	var x int
+	var s []byte
+	_ = append() // ERROR not enough arguments
+	_ = append("foo" /* ERROR not a slice */ )
+	_ = append(nil /* ERROR not a slice */ , s)
+	_ = append(x /* ERROR not a slice */ , s)
+	_ = append(s)
+	append /* ERROR not used */ (s)
+
+	_ = append(s, b)
+	_ = append(s, x /* ERROR cannot pass argument x */ )
+	_ = append(s, s /* ERROR cannot pass argument s */ )
+	_ = append(s... /* ERROR can only use ... with matching parameter */ )
+	_ = append(s, b, s... /* ERROR can only use ... with matching parameter */ )
+	_ = append(s, 1, 2, 3)
+	_ = append(s, 1, 2, 3, x /* ERROR cannot pass argument x */ , 5, 6, 6)
+	_ = append(s, 1, 2, s... /* ERROR can only use ... with matching parameter */ )
+	_ = append([]interface{}(nil), 1, 2, "foo", x, 3.1425, false)
+
+	type S []byte
+	type T string
+	var t T
+	_ = append(s, "foo" /* ERROR cannot convert */ )
+	_ = append(s, "foo"...)
+	_ = append(S(s), "foo" /* ERROR cannot convert */ )
+	_ = append(S(s), "foo"...)
+	_ = append(s, t /* ERROR cannot pass argument t */ )
+	_ = append(s, t...)
+	_ = append(s, T("foo")...)
+	_ = append(S(s), t /* ERROR cannot pass argument t */ )
+	_ = append(S(s), t...)
+	_ = append(S(s), T("foo")...)
+	_ = append([]string{}, t /* ERROR cannot pass argument t */ , "foo")
+	_ = append([]T{}, t, "foo")
+}
+
+// from the spec
+func append2() {
+	s0 := []int{0, 0}
+	s1 := append(s0, 2)                // append a single element     s1 == []int{0, 0, 2}
+	s2 := append(s1, 3, 5, 7)          // append multiple elements    s2 == []int{0, 0, 2, 3, 5, 7}
+	s3 := append(s2, s0...)            // append a slice              s3 == []int{0, 0, 2, 3, 5, 7, 0, 0}
+	s4 := append(s3[3:6], s3[2:]...)   // append overlapping slice    s4 == []int{3, 5, 7, 2, 3, 5, 7, 0, 0}
+
+	var t []interface{}
+	t = append(t, 42, 3.1415, "foo")   //                             t == []interface{}{42, 3.1415, "foo"}
+
+	var b []byte
+	b = append(b, "bar"...)            // append string contents      b == []byte{'b', 'a', 'r' }
+
+	_ = s4
+}
+
+func append3() {
+	f1 := func() (s []int) { return }
+	f2 := func() (s []int, x int) { return }
+	f3 := func() (s []int, x, y int) { return }
+	f5 := func() (s []interface{}, x int, y float32, z string, b bool) { return }
+	ff := func() (int, float32) { return 0, 0 }
+	_ = append(f0 /* ERROR used as value */ ())
+	_ = append(f1())
+	_ = append(f2())
+	_ = append(f3())
+	_ = append(f5())
+	_ = append(ff /* ERROR not a slice */ ()) // TODO(gri) better error message
+}
+
+func cap1() {
+	var a [10]bool
+	var p *[20]int
+	var c chan string
+	_ = cap() // ERROR not enough arguments
+	_ = cap(1, 2) // ERROR too many arguments
+	_ = cap(42 /* ERROR invalid */)
+	const _3 = cap(a)
+	assert(_3 == 10)
+	const _4 = cap(p)
+	assert(_4 == 20)
+	_ = cap(c)
+	cap /* ERROR not used */ (c)
+
+	// issue 4744
+	type T struct{ a [10]int }
+	const _ = cap(((*T)(nil)).a)
+
+	var s [][]byte
+	_ = cap(s)
+	_ = cap(s... /* ERROR invalid use of \.\.\. */ )
+}
+
+func cap2() {
+	f1a := func() (a [10]int) { return }
+	f1s := func() (s []int) { return }
+	f2 := func() (s []int, x int) { return }
+	_ = cap(f0 /* ERROR used as value */ ())
+	_ = cap(f1a())
+	_ = cap(f1s())
+	_ = cap(f2()) // ERROR too many arguments
+}
+
+// test cases for issue 7387
+func cap3() {
+	var f = func() int { return 0 }
+	var x = f()
+	const (
+		_ = cap([4]int{})
+		_ = cap([4]int{x})
+		_ = cap /* ERROR not constant */ ([4]int{f()})
+		_ = cap /* ERROR not constant */ ([4]int{cap([]int{})})
+		_ = cap([4]int{cap([4]int{})})
+	)
+	var y float64
+	var z complex128
+	const (
+		_ = cap([4]float64{})
+		_ = cap([4]float64{y})
+		_ = cap([4]float64{real(2i)})
+		_ = cap /* ERROR not constant */ ([4]float64{real(z)})
+	)
+	var ch chan [10]int
+	const (
+		_ = cap /* ERROR not constant */ (<-ch)
+		_ = cap /* ERROR not constant */ ([4]int{(<-ch)[0]})
+	)
+}
+
+func close1() {
+	var c chan int
+	var r <-chan int
+	close() // ERROR not enough arguments
+	close(1, 2) // ERROR too many arguments
+	close(42 /* ERROR not a channel */)
+	close(r /* ERROR receive-only channel */)
+	close(c)
+	_ = close /* ERROR used as value */ (c)
+
+	var s []chan int
+	close(s... /* ERROR invalid use of \.\.\. */ )
+}
+
+func close2() {
+	f1 := func() (ch chan int) { return }
+	f2 := func() (ch chan int, x int) { return }
+	close(f0 /* ERROR used as value */ ())
+	close(f1())
+	close(f2()) // ERROR too many arguments
+}
+
+func complex1() {
+	var i32 int32
+	var f32 float32
+	var f64 float64
+	var c64 complex64
+	var c128 complex128
+	_ = complex() // ERROR not enough arguments
+	_ = complex(1) // ERROR not enough arguments
+	_ = complex(true /* ERROR invalid argument */ , 0)
+	_ = complex(i32 /* ERROR invalid argument */ , 0)
+	_ = complex("foo" /* ERROR invalid argument */ , 0)
+	_ = complex(c64 /* ERROR invalid argument */ , 0)
+	_ = complex(0, true /* ERROR invalid argument */ )
+	_ = complex(0, i32 /* ERROR invalid argument */ )
+	_ = complex(0, "foo" /* ERROR invalid argument */ )
+	_ = complex(0, c64 /* ERROR invalid argument */ )
+	_ = complex(f32, f32)
+	_ = complex(f32, 1)
+	_ = complex(f32, 1.0)
+	_ = complex(f32, 'a')
+	_ = complex(f64, f64)
+	_ = complex(f64, 1)
+	_ = complex(f64, 1.0)
+	_ = complex(f64, 'a')
+	_ = complex(f32 /* ERROR mismatched types */ , f64)
+	_ = complex(f64 /* ERROR mismatched types */ , f32)
+	_ = complex(1, 1)
+	_ = complex(1, 1.1)
+	_ = complex(1, 'a')
+	complex /* ERROR not used */ (1, 2)
+
+	var _ complex64 = complex(f32, f32)
+	var _ complex64 = complex /* ERROR cannot initialize */ (f64, f64)
+
+	var _ complex128 = complex /* ERROR cannot initialize */ (f32, f32)
+	var _ complex128 = complex(f64, f64)
+
+	// untyped constants
+	const _ int = complex(1, 0)
+	const _ float32 = complex(1, 0)
+	const _ complex64 = complex(1, 0)
+	const _ complex128 = complex(1, 0)
+
+	const _ int = complex /* ERROR int */ (1.1, 0)
+	const _ float32 = complex /* ERROR float32 */ (1, 2)
+
+	// untyped values
+	var s uint
+	_ = complex(1 /* ERROR integer */ <<s, 0)
+	const _ = complex /* ERROR not constant */ (1 /* ERROR integer */ <<s, 0)
+	var _ int = complex /* ERROR cannot initialize */ (1 /* ERROR integer */ <<s, 0)
+
+	// floating-point argument types must be identical
+	type F32 float32
+	type F64 float64
+	var x32 F32
+	var x64 F64
+	c64 = complex(x32, x32)
+	_ = complex(x32 /* ERROR mismatched types */ , f32)
+	_ = complex(f32 /* ERROR mismatched types */ , x32)
+	c128 = complex(x64, x64)
+	_ = c128
+	_ = complex(x64 /* ERROR mismatched types */ , f64)
+	_ = complex(f64 /* ERROR mismatched types */ , x64)
+
+	var t []float32
+	_ = complex(t... /* ERROR invalid use of \.\.\. */ )
+}
+
+func complex2() {
+	f1 := func() (x float32) { return }
+	f2 := func() (x, y float32) { return }
+	f3 := func() (x, y, z float32) { return }
+	_ = complex(f0 /* ERROR used as value */ ())
+	_ = complex(f1()) // ERROR not enough arguments
+	_ = complex(f2())
+	_ = complex(f3()) // ERROR too many arguments
+}
+
+func copy1() {
+	copy() // ERROR not enough arguments
+	copy("foo") // ERROR not enough arguments
+	copy([ /* ERROR copy expects slice arguments */ ...]int{}, []int{})
+	copy([ /* ERROR copy expects slice arguments */ ]int{}, [...]int{})
+	copy([ /* ERROR different element types */ ]int8{}, "foo")
+
+	// spec examples
+	var a = [...]int{0, 1, 2, 3, 4, 5, 6, 7}
+	var s = make([]int, 6)
+	var b = make([]byte, 5)
+	n1 := copy(s, a[0:])            // n1 == 6, s == []int{0, 1, 2, 3, 4, 5}
+	n2 := copy(s, s[2:])            // n2 == 4, s == []int{2, 3, 4, 5, 4, 5}
+	n3 := copy(b, "Hello, World!")  // n3 == 5, b == []byte("Hello")
+	_, _, _ = n1, n2, n3
+
+	var t [][]int
+	copy(t, t)
+	copy(t /* ERROR copy expects slice arguments */ , nil)
+	copy(nil /* ERROR copy expects slice arguments */ , t)
+	copy(nil /* ERROR copy expects slice arguments */ , nil)
+	copy(t... /* ERROR invalid use of \.\.\. */ )
+}
+
+func copy2() {
+	f1 := func() (a []int) { return }
+	f2 := func() (a, b []int) { return }
+	f3 := func() (a, b, c []int) { return }
+	copy(f0 /* ERROR used as value */ ())
+	copy(f1()) // ERROR not enough arguments
+	copy(f2())
+	copy(f3()) // ERROR too many arguments
+}
+
+func delete1() {
+	var m map[string]int
+	var s string
+	delete() // ERROR not enough arguments
+	delete(1) // ERROR not enough arguments
+	delete(1, 2, 3) // ERROR too many arguments
+	delete(m, 0 /* ERROR not assignable */)
+	delete(m, s)
+	_ = delete /* ERROR used as value */ (m, s)
+
+	var t []map[string]string
+	delete(t... /* ERROR invalid use of \.\.\. */ )
+}
+
+func delete2() {
+	f1 := func() (m map[string]int) { return }
+	f2 := func() (m map[string]int, k string) { return }
+	f3 := func() (m map[string]int, k string, x float32) { return }
+	delete(f0 /* ERROR used as value */ ())
+	delete(f1()) // ERROR not enough arguments
+	delete(f2())
+	delete(f3()) // ERROR too many arguments
+}
+
+func imag1() {
+	var f32 float32
+	var f64 float64
+	var c64 complex64
+	var c128 complex128
+	_ = imag() // ERROR not enough arguments
+	_ = imag(1, 2) // ERROR too many arguments
+	_ = imag(10 /* ERROR must be a complex number */)
+	_ = imag(2.7182818 /* ERROR must be a complex number */)
+	_ = imag("foo" /* ERROR must be a complex number */)
+	const _5 = imag(1 + 2i)
+	assert(_5 == 2)
+	f32 = _5
+	f64 = _5
+	const _6 = imag(0i)
+	assert(_6 == 0)
+	f32 = imag(c64)
+	f64 = imag(c128)
+	f32 = imag /* ERROR cannot assign */ (c128)
+	f64 = imag /* ERROR cannot assign */ (c64)
+	imag /* ERROR not used */ (c64)
+	_, _ = f32, f64
+
+	// complex type may not be predeclared
+	type C64 complex64
+	type C128 complex128
+	var x64 C64
+	var x128 C128
+	f32 = imag(x64)
+	f64 = imag(x128)
+
+	var s []complex64
+	_ = imag(s... /* ERROR invalid use of \.\.\. */ )
+}
+
+func imag2() {
+	f1 := func() (x complex128) { return }
+	f2 := func() (x, y complex128) { return }
+	_ = imag(f0 /* ERROR used as value */ ())
+	_ = imag(f1())
+	_ = imag(f2()) // ERROR too many arguments
+}
+
+func len1() {
+	const c = "foobar"
+	var a [10]bool
+	var p *[20]int
+	var m map[string]complex128
+	_ = len() // ERROR not enough arguments
+	_ = len(1, 2) // ERROR too many arguments
+	_ = len(42 /* ERROR invalid */)
+	const _3 = len(c)
+	assert(_3 == 6)
+	const _4 = len(a)
+	assert(_4 == 10)
+	const _5 = len(p)
+	assert(_5 == 20)
+	_ = len(m)
+	len /* ERROR not used */ (c)
+
+	// esoteric case
+	var t string
+	var hash map[interface{}][]*[10]int
+	const n = len /* ERROR not constant */ (hash[recover()][len(t)])
+	assert(n == 10) // ok because n has unknown value and no error is reported
+	var ch <-chan int
+	const nn = len /* ERROR not constant */ (hash[<-ch][len(t)])
+
+	// issue 4744
+	type T struct{ a [10]int }
+	const _ = len(((*T)(nil)).a)
+
+	var s [][]byte
+	_ = len(s)
+	_ = len(s... /* ERROR invalid use of \.\.\. */ )
+}
+
+func len2() {
+	f1 := func() (x []int) { return }
+	f2 := func() (x, y []int) { return }
+	_ = len(f0 /* ERROR used as value */ ())
+	_ = len(f1())
+	_ = len(f2()) // ERROR too many arguments
+}
+
+// test cases for issue 7387
+func len3() {
+	var f = func() int { return 0 }
+	var x = f()
+	const (
+		_ = len([4]int{})
+		_ = len([4]int{x})
+		_ = len /* ERROR not constant */ ([4]int{f()})
+		_ = len /* ERROR not constant */ ([4]int{len([]int{})})
+		_ = len([4]int{len([4]int{})})
+	)
+	var y float64
+	var z complex128
+	const (
+		_ = len([4]float64{})
+		_ = len([4]float64{y})
+		_ = len([4]float64{real(2i)})
+		_ = len /* ERROR not constant */ ([4]float64{real(z)})
+	)
+	var ch chan [10]int
+	const (
+		_ = len /* ERROR not constant */ (<-ch)
+		_ = len /* ERROR not constant */ ([4]int{(<-ch)[0]})
+	)
+}
+
+func make1() {
+	var n int
+	var m float32
+	var s uint
+
+	_ = make() // ERROR not enough arguments
+	_ = make(1 /* ERROR not a type */)
+	_ = make(int /* ERROR cannot make */)
+
+	// slices
+	_ = make/* ERROR arguments */ ([]int)
+	_ = make/* ERROR arguments */ ([]int, 2, 3, 4)
+	_ = make([]int, int /* ERROR not an expression */)
+	_ = make([]int, 10, float32 /* ERROR not an expression */)
+	_ = make([]int, "foo" /* ERROR cannot convert */)
+	_ = make([]int, 10, 2.3 /* ERROR truncated */)
+	_ = make([]int, 5, 10.0)
+	_ = make([]int, 0i)
+	_ = make([]int, 1.0)
+	_ = make([]int, 1.0<<s)
+	_ = make([]int, 1.1 /* ERROR int */ <<s)
+	_ = make([]int, - /* ERROR must not be negative */ 1, 10)
+	_ = make([]int, 0, - /* ERROR must not be negative */ 1)
+	_ = make([]int, - /* ERROR must not be negative */ 1, - /* ERROR must not be negative */ 1)
+	_ = make([]int, 1 /* ERROR overflows */ <<100, 1 /* ERROR overflows */ <<100)
+	_ = make([]int, 10 /* ERROR length and capacity swapped */ , 9)
+	_ = make([]int, 1 /* ERROR overflows */ <<100, 12345)
+	_ = make([]int, m /* ERROR must be integer */ )
+        _ = &make /* ERROR cannot take address */ ([]int, 0)
+
+	// maps
+	_ = make /* ERROR arguments */ (map[int]string, 10, 20)
+	_ = make(map[int]float32, int /* ERROR not an expression */)
+	_ = make(map[int]float32, "foo" /* ERROR cannot convert */)
+	_ = make(map[int]float32, 10)
+	_ = make(map[int]float32, n)
+	_ = make(map[int]float32, int64(n))
+	_ = make(map[string]bool, 10.0)
+	_ = make(map[string]bool, 10.0<<s)
+        _ = &make /* ERROR cannot take address */ (map[string]bool)
+
+	// channels
+	_ = make /* ERROR arguments */ (chan int, 10, 20)
+	_ = make(chan int, int /* ERROR not an expression */)
+	_ = make(chan<- int, "foo" /* ERROR cannot convert */)
+	_ = make(chan int, - /* ERROR must not be negative */ 10)
+	_ = make(<-chan float64, 10)
+	_ = make(chan chan int, n)
+	_ = make(chan string, int64(n))
+	_ = make(chan bool, 10.0)
+	_ = make(chan bool, 10.0<<s)
+        _ = &make /* ERROR cannot take address */ (chan bool)
+
+	make /* ERROR not used */ ([]int, 10)
+
+	var t []int
+	_ = make([]int, t[0], t[1])
+	_ = make([]int, t... /* ERROR invalid use of \.\.\. */ )
+}
+
+func make2() {
+	f1 /* ERROR not used */ := func() (x []int) { return }
+	_ = make(f0 /* ERROR not a type */ ())
+	_ = make(f1 /* ERROR not a type */ ())
+}
+
+func new1() {
+	_ = new() // ERROR not enough arguments
+	_ = new(1, 2) // ERROR too many arguments
+	_ = new("foo" /* ERROR not a type */)
+	p := new(float64)
+	_ = new(struct{ x, y int })
+	q := new(*float64)
+	_ = *p == **q
+	new /* ERROR not used */ (int)
+        _ = &new /* ERROR cannot take address */ (int)
+
+	_ = new(int... /* ERROR invalid use of \.\.\. */ )
+}
+
+func new2() {
+	f1 /* ERROR not used */ := func() (x []int) { return }
+	_ = new(f0 /* ERROR not a type */ ())
+	_ = new(f1 /* ERROR not a type */ ())
+}
+
+func panic1() {
+	panic() // ERROR not enough arguments
+	panic(1, 2) // ERROR too many arguments
+	panic(0)
+	panic("foo")
+	panic(false)
+	panic(1<<10)
+	panic(1 /* ERROR overflows */ <<1000)
+	_ = panic /* ERROR used as value */ (0)
+
+	var s []byte
+	panic(s)
+	panic(s... /* ERROR invalid use of \.\.\. */ )
+}
+
+func panic2() {
+	f1 := func() (x int) { return }
+	f2 := func() (x, y int) { return }
+	panic(f0 /* ERROR used as value */ ())
+	panic(f1())
+	panic(f2()) // ERROR too many arguments
+}
+
+func print1() {
+	print()
+	print(1)
+	print(1, 2)
+	print("foo")
+	print(2.718281828)
+	print(false)
+	print(1<<10)
+	print(1 /* ERROR overflows */ <<1000)
+	println(nil /* ERROR untyped nil */ )
+
+	var s []int
+	print(s... /* ERROR invalid use of \.\.\. */ )
+	_ = print /* ERROR used as value */ ()
+}
+
+func print2() {
+	f1 := func() (x int) { return }
+	f2 := func() (x, y int) { return }
+	f3 := func() (x int, y float32, z string) { return }
+	print(f0 /* ERROR used as value */ ())
+	print(f1())
+	print(f2())
+	print(f3())
+}
+
+func println1() {
+	println()
+	println(1)
+	println(1, 2)
+	println("foo")
+	println(2.718281828)
+	println(false)
+	println(1<<10)
+	println(1 /* ERROR overflows */ <<1000)
+	println(nil /* ERROR untyped nil */ )
+
+	var s []int
+	println(s... /* ERROR invalid use of \.\.\. */ )
+	_ = println /* ERROR used as value */ ()
+}
+
+func println2() {
+	f1 := func() (x int) { return }
+	f2 := func() (x, y int) { return }
+	f3 := func() (x int, y float32, z string) { return }
+	println(f0 /* ERROR used as value */ ())
+	println(f1())
+	println(f2())
+	println(f3())
+}
+
+func real1() {
+	var f32 float32
+	var f64 float64
+	var c64 complex64
+	var c128 complex128
+	_ = real() // ERROR not enough arguments
+	_ = real(1, 2) // ERROR too many arguments
+	_ = real(10 /* ERROR must be a complex number */)
+	_ = real(2.7182818 /* ERROR must be a complex number */)
+	_ = real("foo" /* ERROR must be a complex number */)
+	const _5 = real(1 + 2i)
+	assert(_5 == 1)
+	f32 = _5
+	f64 = _5
+	const _6 = real(0i)
+	assert(_6 == 0)
+	f32 = real(c64)
+	f64 = real(c128)
+	f32 = real /* ERROR cannot assign */ (c128)
+	f64 = real /* ERROR cannot assign */ (c64)
+	real /* ERROR not used */ (c64)
+
+	// complex type may not be predeclared
+	type C64 complex64
+	type C128 complex128
+	var x64 C64
+	var x128 C128
+	f32 = imag(x64)
+	f64 = imag(x128)
+
+	var s []complex64
+	_ = real(s... /* ERROR invalid use of \.\.\. */ )
+	_, _ = f32, f64
+}
+
+func real2() {
+	f1 := func() (x complex128) { return }
+	f2 := func() (x, y complex128) { return }
+	_ = real(f0 /* ERROR used as value */ ())
+	_ = real(f1())
+	_ = real(f2()) // ERROR too many arguments
+}
+
+func recover1() {
+	_ = recover()
+	_ = recover(10) // ERROR too many arguments
+	recover()
+
+	var s []int
+	recover(s... /* ERROR invalid use of \.\.\. */ )
+}
+
+func recover2() {
+	f1 := func() (x int) { return }
+	f2 := func() (x, y int) { return }
+	_ = recover(f0 /* ERROR used as value */ ())
+	_ = recover(f1()) // ERROR too many arguments
+	_ = recover(f2()) // ERROR too many arguments
+}
+
+// assuming types.DefaultPtrSize == 8
+type S0 struct{      // offset
+	a bool       //  0
+	b rune       //  4
+	c *int       //  8
+	d bool       // 16
+	e complex128 // 24
+}                    // 40
+
+type S1 struct{   // offset
+	x float32 //  0
+	y string  //  8
+	z *S1     // 24
+	S0        // 32
+}                 // 72
+
+type S2 struct{ // offset
+	*S1     //  0
+}               //  8
+
+type S3 struct { // offset
+	a int64  //  0
+	b int32  //  8
+}                // 12
+
+type S4 struct { // offset
+	S3       //  0
+	int32    // 12
+}                // 16
+
+type S5 struct {   // offset
+	a [3]int32 //  0
+	b int32    // 12
+}                  // 16
+
+func (S2) m() {}
+
+func Alignof1() {
+	var x int
+	_ = unsafe.Alignof() // ERROR not enough arguments
+	_ = unsafe.Alignof(1, 2) // ERROR too many arguments
+	_ = unsafe.Alignof(int /* ERROR not an expression */)
+	_ = unsafe.Alignof(42)
+	_ = unsafe.Alignof(new(struct{}))
+	_ = unsafe.Alignof(1<<10)
+	_ = unsafe.Alignof(1 /* ERROR overflows */ <<1000)
+	_ = unsafe.Alignof(nil /* ERROR "untyped nil */ )
+	unsafe /* ERROR not used */ .Alignof(x)
+
+	var y S0
+	assert(unsafe.Alignof(y.a) == 1)
+	assert(unsafe.Alignof(y.b) == 4)
+	assert(unsafe.Alignof(y.c) == 8)
+	assert(unsafe.Alignof(y.d) == 1)
+	assert(unsafe.Alignof(y.e) == 8)
+
+	var s []byte
+	_ = unsafe.Alignof(s)
+	_ = unsafe.Alignof(s... /* ERROR invalid use of \.\.\. */ )
+}
+
+func Alignof2() {
+	f1 := func() (x int32) { return }
+	f2 := func() (x, y int32) { return }
+	_ = unsafe.Alignof(f0 /* ERROR used as value */ ())
+	assert(unsafe.Alignof(f1()) == 4)
+	_ = unsafe.Alignof(f2()) // ERROR too many arguments
+}
+
+func Offsetof1() {
+	var x struct{ f int }
+	_ = unsafe.Offsetof() // ERROR not enough arguments
+	_ = unsafe.Offsetof(1, 2) // ERROR too many arguments
+	_ = unsafe.Offsetof(int /* ERROR not a selector expression */ )
+	_ = unsafe.Offsetof(x /* ERROR not a selector expression */ )
+	_ = unsafe.Offsetof(nil /* ERROR not a selector expression */ )
+	_ = unsafe.Offsetof(x.f)
+	_ = unsafe.Offsetof((x.f))
+	_ = unsafe.Offsetof((((((((x))).f)))))
+	unsafe /* ERROR not used */ .Offsetof(x.f)
+
+	var y0 S0
+	assert(unsafe.Offsetof(y0.a) == 0)
+	assert(unsafe.Offsetof(y0.b) == 4)
+	assert(unsafe.Offsetof(y0.c) == 8)
+	assert(unsafe.Offsetof(y0.d) == 16)
+	assert(unsafe.Offsetof(y0.e) == 24)
+
+	var y1 S1
+	assert(unsafe.Offsetof(y1.x) == 0)
+	assert(unsafe.Offsetof(y1.y) == 8)
+	assert(unsafe.Offsetof(y1.z) == 24)
+	assert(unsafe.Offsetof(y1.S0) == 32)
+
+	assert(unsafe.Offsetof(y1.S0.a) == 0) // relative to S0
+	assert(unsafe.Offsetof(y1.a) == 32)   // relative to S1
+	assert(unsafe.Offsetof(y1.b) == 36)   // relative to S1
+	assert(unsafe.Offsetof(y1.c) == 40)   // relative to S1
+	assert(unsafe.Offsetof(y1.d) == 48)   // relative to S1
+	assert(unsafe.Offsetof(y1.e) == 56)   // relative to S1
+
+	var y1p *S1
+	assert(unsafe.Offsetof(y1p.S0) == 32)
+
+	type P *S1
+	var p P = y1p
+	assert(unsafe.Offsetof(p.S0) == 32)
+
+	var y2 S2
+	assert(unsafe.Offsetof(y2.S1) == 0)
+	_ = unsafe.Offsetof(y2 /* ERROR embedded via a pointer */ .x)
+	_ = unsafe.Offsetof(y2 /* ERROR method value */ .m)
+
+	var s []byte
+	_ = unsafe.Offsetof(s... /* ERROR invalid use of \.\.\. */ )
+}
+
+func Offsetof2() {
+	f1 := func() (x int32) { return }
+	f2 := func() (x, y int32) { return }
+	_ = unsafe.Offsetof(f0 /* ERROR not a selector expression */ ())
+	_ = unsafe.Offsetof(f1 /* ERROR not a selector expression */ ())
+	_ = unsafe.Offsetof(f2 /* ERROR not a selector expression */ ())
+}
+
+func Sizeof1() {
+	var x int
+	_ = unsafe.Sizeof() // ERROR not enough arguments
+	_ = unsafe.Sizeof(1, 2) // ERROR too many arguments
+	_ = unsafe.Sizeof(int /* ERROR not an expression */)
+	_ = unsafe.Sizeof(42)
+	_ = unsafe.Sizeof(new(complex128))
+	_ = unsafe.Sizeof(1<<10)
+	_ = unsafe.Sizeof(1 /* ERROR overflows */ <<1000)
+	_ = unsafe.Sizeof(nil /* ERROR untyped nil */ )
+	unsafe /* ERROR not used */ .Sizeof(x)
+
+	// basic types have size guarantees
+	assert(unsafe.Sizeof(byte(0)) == 1)
+	assert(unsafe.Sizeof(uint8(0)) == 1)
+	assert(unsafe.Sizeof(int8(0)) == 1)
+	assert(unsafe.Sizeof(uint16(0)) == 2)
+	assert(unsafe.Sizeof(int16(0)) == 2)
+	assert(unsafe.Sizeof(uint32(0)) == 4)
+	assert(unsafe.Sizeof(int32(0)) == 4)
+	assert(unsafe.Sizeof(float32(0)) == 4)
+	assert(unsafe.Sizeof(uint64(0)) == 8)
+	assert(unsafe.Sizeof(int64(0)) == 8)
+	assert(unsafe.Sizeof(float64(0)) == 8)
+	assert(unsafe.Sizeof(complex64(0)) == 8)
+	assert(unsafe.Sizeof(complex128(0)) == 16)
+
+	var y0 S0
+	assert(unsafe.Sizeof(y0.a) == 1)
+	assert(unsafe.Sizeof(y0.b) == 4)
+	assert(unsafe.Sizeof(y0.c) == 8)
+	assert(unsafe.Sizeof(y0.d) == 1)
+	assert(unsafe.Sizeof(y0.e) == 16)
+	assert(unsafe.Sizeof(y0) == 40)
+
+	var y1 S1
+	assert(unsafe.Sizeof(y1) == 72)
+
+	var y2 S2
+	assert(unsafe.Sizeof(y2) == 8)
+
+	var y3 S3
+	assert(unsafe.Sizeof(y3) == 12)
+
+	var y4 S4
+	assert(unsafe.Sizeof(y4) == 16)
+
+	var y5 S5
+	assert(unsafe.Sizeof(y5) == 16)
+
+	var a3 [10]S3
+	assert(unsafe.Sizeof(a3) == 156)
+
+	// test case for issue 5670
+	type T struct {
+		a int32
+		_ int32
+		c int32
+	}
+	assert(unsafe.Sizeof(T{}) == 12)
+
+	var s []byte
+	_ = unsafe.Sizeof(s)
+	_ = unsafe.Sizeof(s... /* ERROR invalid use of \.\.\. */ )
+}
+
+func Sizeof2() {
+	f1 := func() (x int64) { return }
+	f2 := func() (x, y int64) { return }
+	_ = unsafe.Sizeof(f0 /* ERROR used as value */ ())
+	assert(unsafe.Sizeof(f1()) == 8)
+	_ = unsafe.Sizeof(f2()) // ERROR too many arguments
+}
+
+// self-testing only
+func assert1() {
+	var x int
+	assert() /* ERROR not enough arguments */
+	assert(1, 2) /* ERROR too many arguments */
+	assert("foo" /* ERROR boolean constant */ )
+	assert(x /* ERROR boolean constant */)
+	assert(true)
+	assert /* ERROR failed */ (false)
+	_ = assert(true)
+
+	var s []byte
+	assert(s... /* ERROR invalid use of \.\.\. */ )
+}
+
+func assert2() {
+	f1 := func() (x bool) { return }
+	f2 := func() (x bool) { return }
+	assert(f0 /* ERROR used as value */ ())
+	assert(f1 /* ERROR boolean constant */ ())
+	assert(f2 /* ERROR boolean constant */ ())
+}
+
+// self-testing only
+func trace1() {
+	// Uncomment the code below to test trace - will produce console output
+	// _ = trace /* ERROR no value */ ()
+	// _ = trace(1)
+	// _ = trace(true, 1.2, '\'', "foo", 42i, "foo" <= "bar")
+
+	var s []byte
+	trace(s... /* ERROR invalid use of \.\.\. */ )
+}
+
+func trace2() {
+	f1 := func() (x int) { return }
+	f2 := func() (x int, y string) { return }
+	f3 := func() (x int, y string, z []int) { return }
+	_ = f1
+	_ = f2
+	_ = f3
+	// Uncomment the code below to test trace - will produce console output
+	// trace(f0())
+	// trace(f1())
+	// trace(f2())
+	// trace(f3())
+	// trace(f0(), 1)
+	// trace(f1(), 1, 2)
+	// trace(f2(), 1, 2, 3)
+	// trace(f3(), 1, 2, 3, 4)
+}
diff --git a/go/types/testdata/const0.src b/go/types/testdata/const0.src
new file mode 100644
index 0000000..c4419ab
--- /dev/null
+++ b/go/types/testdata/const0.src
@@ -0,0 +1,282 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// constant declarations
+
+package const0
+
+// constants declarations must be initialized by constants
+var x = 0
+const c0 = x /* ERROR "not constant" */
+
+// typed constants must have constant types
+const _ interface /* ERROR invalid constant type */ {} = 0
+
+func _ () {
+	const _ interface /* ERROR invalid constant type */ {} = 0
+	for i := 0; i < 10; i++ {} // don't crash with non-nil iota here
+}
+
+// untyped constants
+const (
+	// boolean values
+	ub0 = false
+	ub1 = true
+	ub2 = 2 < 1
+	ub3 = ui1 == uf1
+	ub4 = true /* ERROR "cannot convert" */ == 0
+
+	// integer values
+	ui0 = 0
+	ui1 = 1
+	ui2 = 42
+	ui3 = 3141592653589793238462643383279502884197169399375105820974944592307816406286
+	ui4 = -10
+
+	ui5 = ui0 + ui1
+	ui6 = ui1 - ui1
+	ui7 = ui2 * ui1
+	ui8 = ui3 / ui3
+	ui9 = ui3 % ui3
+
+	ui10 = 1 / 0 /* ERROR "division by zero" */
+	ui11 = ui1 / 0 /* ERROR "division by zero" */
+	ui12 = ui3 / ui0 /* ERROR "division by zero" */
+	ui13 = 1 % 0 /* ERROR "division by zero" */
+	ui14 = ui1 % 0 /* ERROR "division by zero" */
+	ui15 = ui3 % ui0 /* ERROR "division by zero" */
+
+	ui16 = ui2 & ui3
+	ui17 = ui2 | ui3
+	ui18 = ui2 ^ ui3
+	ui19 = 1 /* ERROR "invalid operation" */ % 1.0
+
+	// floating point values
+	uf0 = 0.
+	uf1 = 1.
+	uf2 = 4.2e1
+	uf3 = 3.141592653589793238462643383279502884197169399375105820974944592307816406286
+	uf4 = 1e-1
+
+	uf5 = uf0 + uf1
+	uf6 = uf1 - uf1
+	uf7 = uf2 * uf1
+	uf8 = uf3 / uf3
+	uf9 = uf3 /* ERROR "not defined" */ % uf3
+
+	uf10 = 1 / 0 /* ERROR "division by zero" */
+	uf11 = uf1 / 0 /* ERROR "division by zero" */
+	uf12 = uf3 / uf0 /* ERROR "division by zero" */
+
+	uf16 = uf2 /* ERROR "not defined" */ & uf3
+	uf17 = uf2 /* ERROR "not defined" */ | uf3
+	uf18 = uf2 /* ERROR "not defined" */ ^ uf3
+
+	// complex values
+	uc0 = 0.i
+	uc1 = 1.i
+	uc2 = 4.2e1i
+	uc3 = 3.141592653589793238462643383279502884197169399375105820974944592307816406286i
+	uc4 = 1e-1i
+
+	uc5 = uc0 + uc1
+	uc6 = uc1 - uc1
+	uc7 = uc2 * uc1
+	uc8 = uc3 / uc3
+	uc9 = uc3 /* ERROR "not defined" */ % uc3
+
+	uc10 = 1 / 0 /* ERROR "division by zero" */
+	uc11 = uc1 / 0 /* ERROR "division by zero" */
+	uc12 = uc3 / uc0 /* ERROR "division by zero" */
+
+	uc16 = uc2 /* ERROR "not defined" */ & uc3
+	uc17 = uc2 /* ERROR "not defined" */ | uc3
+	uc18 = uc2 /* ERROR "not defined" */ ^ uc3
+)
+
+type (
+	mybool bool
+	myint int
+	myfloat float64
+	mycomplex complex128
+)
+
+// typed constants
+const (
+	// boolean values
+	tb0 bool = false
+	tb1 bool = true
+	tb2 mybool = 2 < 1
+	tb3 mybool = ti1 /* ERROR "mismatched types" */ == tf1
+
+	// integer values
+	ti0 int8 = ui0
+	ti1 int32 = ui1
+	ti2 int64 = ui2
+	ti3 myint = ui3 /* ERROR "overflows" */
+	ti4 myint = ui4
+
+	ti5 = ti0 /* ERROR "mismatched types" */ + ti1
+	ti6 = ti1 - ti1
+	ti7 = ti2 /* ERROR "mismatched types" */ * ti1
+	ti8 = ti3 / ti3
+	ti9 = ti3 % ti3
+
+	ti10 = 1 / 0 /* ERROR "division by zero" */
+	ti11 = ti1 / 0 /* ERROR "division by zero" */
+	ti12 = ti3 /* ERROR "mismatched types" */ / ti0
+	ti13 = 1 % 0 /* ERROR "division by zero" */
+	ti14 = ti1 % 0 /* ERROR "division by zero" */
+	ti15 = ti3 /* ERROR "mismatched types" */ % ti0
+
+	ti16 = ti2 /* ERROR "mismatched types" */ & ti3
+	ti17 = ti2 /* ERROR "mismatched types" */ | ti4
+	ti18 = ti2 ^ ti5 // no mismatched types error because the type of ti5 is unknown
+
+	// floating point values
+	tf0 float32 = 0.
+	tf1 float32 = 1.
+	tf2 float64 = 4.2e1
+	tf3 myfloat = 3.141592653589793238462643383279502884197169399375105820974944592307816406286
+	tf4 myfloat = 1e-1
+
+	tf5 = tf0 + tf1
+	tf6 = tf1 - tf1
+	tf7 = tf2 /* ERROR "mismatched types" */ * tf1
+	tf8 = tf3 / tf3
+	tf9 = tf3 /* ERROR "not defined" */ % tf3
+
+	tf10 = 1 / 0 /* ERROR "division by zero" */
+	tf11 = tf1 / 0 /* ERROR "division by zero" */
+	tf12 = tf3 /* ERROR "mismatched types" */ / tf0
+
+	tf16 = tf2 /* ERROR "mismatched types" */ & tf3
+	tf17 = tf2 /* ERROR "mismatched types" */ | tf3
+	tf18 = tf2 /* ERROR "mismatched types" */ ^ tf3
+
+	// complex values
+	tc0 = 0.i
+	tc1 = 1.i
+	tc2 = 4.2e1i
+	tc3 = 3.141592653589793238462643383279502884197169399375105820974944592307816406286i
+	tc4 = 1e-1i
+
+	tc5 = tc0 + tc1
+	tc6 = tc1 - tc1
+	tc7 = tc2 * tc1
+	tc8 = tc3 / tc3
+	tc9 = tc3 /* ERROR "not defined" */ % tc3
+
+	tc10 = 1 / 0 /* ERROR "division by zero" */
+	tc11 = tc1 / 0 /* ERROR "division by zero" */
+	tc12 = tc3 / tc0 /* ERROR "division by zero" */
+
+	tc16 = tc2 /* ERROR "not defined" */ & tc3
+	tc17 = tc2 /* ERROR "not defined" */ | tc3
+	tc18 = tc2 /* ERROR "not defined" */ ^ tc3
+)
+
+// initialization cycles
+const (
+	a /* ERROR "initialization cycle" */ = a
+	b /* ERROR "initialization cycle" */ , c /* ERROR "initialization cycle" */, d, e = e, d, c, b // TODO(gri) should only have one cycle error
+	f float64 = d
+)
+
+// multiple initialization
+const (
+	a1, a2, a3 = 7, 3.1415926, "foo"
+	b1, b2, b3 = b3, b1, 42
+	c1, c2, c3  /* ERROR "missing init expr for c3" */ = 1, 2
+	d1, d2, d3 = 1, 2, 3, 4 /* ERROR "extra init expr 4" */
+	_p0 = assert(a1 == 7)
+	_p1 = assert(a2 == 3.1415926)
+	_p2 = assert(a3 == "foo")
+	_p3 = assert(b1 == 42)
+	_p4 = assert(b2 == 42)
+	_p5 = assert(b3 == 42)
+)
+
+func _() {
+	const (
+		a1, a2, a3 = 7, 3.1415926, "foo"
+		b1, b2, b3 = b3, b1, 42
+		c1, c2, c3  /* ERROR "missing init expr for c3" */ = 1, 2
+		d1, d2, d3 = 1, 2, 3, 4 /* ERROR "extra init expr 4" */
+		_p0 = assert(a1 == 7)
+		_p1 = assert(a2 == 3.1415926)
+		_p2 = assert(a3 == "foo")
+		_p3 = assert(b1 == 42)
+		_p4 = assert(b2 == 42)
+		_p5 = assert(b3 == 42)
+	)
+}
+
+// iota
+const (
+	iota0 = iota
+	iota1 = iota
+	iota2 = iota*2
+	_a0 = assert(iota0 == 0)
+	_a1 = assert(iota1 == 1)
+	_a2 = assert(iota2 == 4)
+	iota6 = iota*3
+
+	iota7
+	iota8
+	_a3 = assert(iota7 == 21)
+	_a4 = assert(iota8 == 24)
+)
+
+const (
+	_b0 = iota
+	_b1 = assert(iota + iota2 == 5)
+	_b2 = len([iota]int{}) // iota may appear in a type!
+	_b3 = assert(_b2 == 2)
+	_b4 = len(A{})
+)
+
+type A [iota /* ERROR "cannot use iota" */ ]int
+
+// constant expressions with operands accross different
+// constant declarations must use the right iota values
+const (
+	_c0 = iota
+	_c1
+	_c2
+	_x = _c2 + _d1 + _e0 // 3
+)
+
+const (
+	_d0 = iota
+	_d1
+)
+
+const (
+	_e0 = iota
+)
+
+var _ = assert(_x == 3)
+
+// special cases
+const (
+	_n0 = nil /* ERROR "not constant" */
+	_n1 = [ /* ERROR "not constant" */ ]int{}
+)
+
+// iotas must not be usable in expressions outside constant declarations
+type _ [iota /* ERROR "iota outside constant decl" */ ]byte
+var _ = iota /* ERROR "iota outside constant decl" */
+func _() {
+	_ = iota /* ERROR "iota outside constant decl" */
+	const _ = iota
+	_ = iota /* ERROR "iota outside constant decl" */
+}
+
+func _() {
+	iota := 123
+	const x = iota /* ERROR "is not constant" */
+	var y = iota
+	_ = y
+}
diff --git a/go/types/testdata/const1.src b/go/types/testdata/const1.src
new file mode 100644
index 0000000..88e9fad
--- /dev/null
+++ b/go/types/testdata/const1.src
@@ -0,0 +1,314 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// constant conversions
+
+package const1
+
+const(
+	mi = ^int(0)
+	mu = ^uint(0)
+	mp = ^uintptr(0)
+
+	logSizeofInt     = uint(mi>>8&1 + mi>>16&1 + mi>>32&1)
+	logSizeofUint    = uint(mu>>8&1 + mu>>16&1 + mu>>32&1)
+	logSizeofUintptr = uint(mp>>8&1 + mp>>16&1 + mp>>32&1)
+)
+
+const (
+	minInt8 = -1<<(8<<iota - 1)
+	minInt16
+	minInt32
+	minInt64
+	minInt = -1<<(8<<logSizeofInt - 1)
+)
+
+const (
+	maxInt8 = 1<<(8<<iota - 1) - 1
+	maxInt16
+	maxInt32
+	maxInt64
+	maxInt = 1<<(8<<logSizeofInt - 1) - 1
+)
+
+const (
+	maxUint8 = 1<<(8<<iota) - 1
+	maxUint16
+	maxUint32
+	maxUint64
+	maxUint    = 1<<(8<<logSizeofUint) - 1
+	maxUintptr = 1<<(8<<logSizeofUintptr) - 1
+)
+
+const (
+	smallestFloat32 = 1.0 / (1<<(127 - 1 + 23))
+	smallestFloat64 = 1.0 / (1<<(1023 - 1 + 52))
+)
+
+const (
+	_ = assert(smallestFloat32 > 0)
+	_ = assert(smallestFloat64 > 0)
+)
+
+const (
+	maxFloat32 = 1<<127 * (1<<24 - 1) / (1.0<<23)
+	maxFloat64 = 1<<1023 * (1<<53 - 1) / (1.0<<52)
+)
+
+const (
+	_ int8 = minInt8 /* ERROR "overflows" */ - 1
+	_ int8 = minInt8
+	_ int8 = maxInt8
+	_ int8 = maxInt8 /* ERROR "overflows" */ + 1
+	_ int8 = smallestFloat64 /* ERROR "truncated" */
+
+	_ = int8(minInt8 /* ERROR "cannot convert" */ - 1)
+	_ = int8(minInt8)
+	_ = int8(maxInt8)
+	_ = int8(maxInt8 /* ERROR "cannot convert" */ + 1)
+	_ = int8(smallestFloat64 /* ERROR "cannot convert" */)
+)
+
+const (
+	_ int16 = minInt16 /* ERROR "overflows" */ - 1
+	_ int16 = minInt16
+	_ int16 = maxInt16
+	_ int16 = maxInt16 /* ERROR "overflows" */ + 1
+	_ int16 = smallestFloat64 /* ERROR "truncated" */
+
+	_ = int16(minInt16 /* ERROR "cannot convert" */ - 1)
+	_ = int16(minInt16)
+	_ = int16(maxInt16)
+	_ = int16(maxInt16 /* ERROR "cannot convert" */ + 1)
+	_ = int16(smallestFloat64 /* ERROR "cannot convert" */)
+)
+
+const (
+	_ int32 = minInt32 /* ERROR "overflows" */ - 1
+	_ int32 = minInt32
+	_ int32 = maxInt32
+	_ int32 = maxInt32 /* ERROR "overflows" */ + 1
+	_ int32 = smallestFloat64 /* ERROR "truncated" */
+
+	_ = int32(minInt32 /* ERROR "cannot convert" */ - 1)
+	_ = int32(minInt32)
+	_ = int32(maxInt32)
+	_ = int32(maxInt32 /* ERROR "cannot convert" */ + 1)
+	_ = int32(smallestFloat64 /* ERROR "cannot convert" */)
+)
+
+const (
+	_ int64 = minInt64 /* ERROR "overflows" */ - 1
+	_ int64 = minInt64
+	_ int64 = maxInt64
+	_ int64 = maxInt64 /* ERROR "overflows" */ + 1
+	_ int64 = smallestFloat64 /* ERROR "truncated" */
+
+	_ = int64(minInt64 /* ERROR "cannot convert" */ - 1)
+	_ = int64(minInt64)
+	_ = int64(maxInt64)
+	_ = int64(maxInt64 /* ERROR "cannot convert" */ + 1)
+	_ = int64(smallestFloat64 /* ERROR "cannot convert" */)
+)
+
+const (
+	_ int = minInt /* ERROR "overflows" */ - 1
+	_ int = minInt
+	_ int = maxInt
+	_ int = maxInt /* ERROR "overflows" */ + 1
+	_ int = smallestFloat64 /* ERROR "truncated" */
+
+	_ = int(minInt /* ERROR "cannot convert" */ - 1)
+	_ = int(minInt)
+	_ = int(maxInt)
+	_ = int(maxInt /* ERROR "cannot convert" */ + 1)
+	_ = int(smallestFloat64 /* ERROR "cannot convert" */)
+)
+
+const (
+	_ uint8 = 0 /* ERROR "overflows" */ - 1
+	_ uint8 = 0
+	_ uint8 = maxUint8
+	_ uint8 = maxUint8 /* ERROR "overflows" */ + 1
+	_ uint8 = smallestFloat64 /* ERROR "truncated" */
+
+	_ = uint8(0 /* ERROR "cannot convert" */ - 1)
+	_ = uint8(0)
+	_ = uint8(maxUint8)
+	_ = uint8(maxUint8 /* ERROR "cannot convert" */ + 1)
+	_ = uint8(smallestFloat64 /* ERROR "cannot convert" */)
+)
+
+const (
+	_ uint16 = 0 /* ERROR "overflows" */ - 1
+	_ uint16 = 0
+	_ uint16 = maxUint16
+	_ uint16 = maxUint16 /* ERROR "overflows" */ + 1
+	_ uint16 = smallestFloat64 /* ERROR "truncated" */
+
+	_ = uint16(0 /* ERROR "cannot convert" */ - 1)
+	_ = uint16(0)
+	_ = uint16(maxUint16)
+	_ = uint16(maxUint16 /* ERROR "cannot convert" */ + 1)
+	_ = uint16(smallestFloat64 /* ERROR "cannot convert" */)
+)
+
+const (
+	_ uint32 = 0 /* ERROR "overflows" */ - 1
+	_ uint32 = 0
+	_ uint32 = maxUint32
+	_ uint32 = maxUint32 /* ERROR "overflows" */ + 1
+	_ uint32 = smallestFloat64 /* ERROR "truncated" */
+
+	_ = uint32(0 /* ERROR "cannot convert" */ - 1)
+	_ = uint32(0)
+	_ = uint32(maxUint32)
+	_ = uint32(maxUint32 /* ERROR "cannot convert" */ + 1)
+	_ = uint32(smallestFloat64 /* ERROR "cannot convert" */)
+)
+
+const (
+	_ uint64 = 0 /* ERROR "overflows" */ - 1
+	_ uint64 = 0
+	_ uint64 = maxUint64
+	_ uint64 = maxUint64 /* ERROR "overflows" */ + 1
+	_ uint64 = smallestFloat64 /* ERROR "truncated" */
+
+	_ = uint64(0 /* ERROR "cannot convert" */ - 1)
+	_ = uint64(0)
+	_ = uint64(maxUint64)
+	_ = uint64(maxUint64 /* ERROR "cannot convert" */ + 1)
+	_ = uint64(smallestFloat64 /* ERROR "cannot convert" */)
+)
+
+const (
+	_ uint = 0 /* ERROR "overflows" */ - 1
+	_ uint = 0
+	_ uint = maxUint
+	_ uint = maxUint /* ERROR "overflows" */ + 1
+	_ uint = smallestFloat64 /* ERROR "truncated" */
+
+	_ = uint(0 /* ERROR "cannot convert" */ - 1)
+	_ = uint(0)
+	_ = uint(maxUint)
+	_ = uint(maxUint /* ERROR "cannot convert" */ + 1)
+	_ = uint(smallestFloat64 /* ERROR "cannot convert" */)
+)
+
+const (
+	_ uintptr = 0 /* ERROR "overflows" */ - 1
+	_ uintptr = 0
+	_ uintptr = maxUintptr
+	_ uintptr = maxUintptr /* ERROR "overflows" */ + 1
+	_ uintptr = smallestFloat64 /* ERROR "truncated" */
+
+	_ = uintptr(0 /* ERROR "cannot convert" */ - 1)
+	_ = uintptr(0)
+	_ = uintptr(maxUintptr)
+	_ = uintptr(maxUintptr /* ERROR "cannot convert" */ + 1)
+	_ = uintptr(smallestFloat64 /* ERROR "cannot convert" */)
+)
+
+const (
+	_ float32 = minInt64
+	_ float64 = minInt64
+	_ complex64 = minInt64
+	_ complex128 = minInt64
+
+	_ = float32(minInt64)
+	_ = float64(minInt64)
+	_ = complex64(minInt64)
+	_ = complex128(minInt64)
+)
+
+const (
+	_ float32 = maxUint64
+	_ float64 = maxUint64
+	_ complex64 = maxUint64
+	_ complex128 = maxUint64
+
+	_ = float32(maxUint64)
+	_ = float64(maxUint64)
+	_ = complex64(maxUint64)
+	_ = complex128(maxUint64)
+)
+
+// TODO(gri) find smaller deltas below
+
+const delta32 = maxFloat32/(1 << 23)
+
+const (
+	_ float32 = - /* ERROR "overflow" */ (maxFloat32 + delta32)
+	_ float32 = -maxFloat32
+	_ float32 = maxFloat32
+	_ float32 = maxFloat32 /* ERROR "overflow" */ + delta32
+
+	_ = float32(- /* ERROR "cannot convert" */ (maxFloat32 + delta32))
+	_ = float32(-maxFloat32)
+	_ = float32(maxFloat32)
+	_ = float32(maxFloat32 /* ERROR "cannot convert" */ + delta32)
+
+	_ = assert(float32(smallestFloat32) == smallestFloat32)
+	_ = assert(float32(smallestFloat32/2) == 0)
+	_ = assert(float32(smallestFloat64) == 0)
+	_ = assert(float32(smallestFloat64/2) == 0)
+)
+
+const delta64 = maxFloat64/(1 << 52)
+
+const (
+	_ float64 = - /* ERROR "overflow" */ (maxFloat64 + delta64)
+	_ float64 = -maxFloat64
+	_ float64 = maxFloat64
+	_ float64 = maxFloat64 /* ERROR "overflow" */ + delta64
+
+	_ = float64(- /* ERROR "cannot convert" */ (maxFloat64 + delta64))
+	_ = float64(-maxFloat64)
+	_ = float64(maxFloat64)
+	_ = float64(maxFloat64 /* ERROR "cannot convert" */ + delta64)
+
+	_ = assert(float64(smallestFloat32) == smallestFloat32)
+	_ = assert(float64(smallestFloat32/2) == smallestFloat32/2)
+	_ = assert(float64(smallestFloat64) == smallestFloat64)
+	_ = assert(float64(smallestFloat64/2) == 0)
+)
+
+const (
+	_ complex64 = - /* ERROR "overflow" */ (maxFloat32 + delta32)
+	_ complex64 = -maxFloat32
+	_ complex64 = maxFloat32
+	_ complex64 = maxFloat32 /* ERROR "overflow" */ + delta32
+
+	_ = complex64(- /* ERROR "cannot convert" */ (maxFloat32 + delta32))
+	_ = complex64(-maxFloat32)
+	_ = complex64(maxFloat32)
+	_ = complex64(maxFloat32 /* ERROR "cannot convert" */ + delta32)
+)
+
+const (
+	_ complex128 = - /* ERROR "overflow" */ (maxFloat64 + delta64)
+	_ complex128 = -maxFloat64
+	_ complex128 = maxFloat64
+	_ complex128 = maxFloat64 /* ERROR "overflow" */ + delta64
+
+	_ = complex128(- /* ERROR "cannot convert" */ (maxFloat64 + delta64))
+	_ = complex128(-maxFloat64)
+	_ = complex128(maxFloat64)
+	_ = complex128(maxFloat64 /* ERROR "cannot convert" */ + delta64)
+)
+
+// Initialization of typed constant and conversion are the same:
+const (
+	f32 = 1 + smallestFloat32
+	x32 float32 = f32
+	y32 = float32(f32)
+	_ = assert(x32 - y32 == 0)
+)
+
+const (
+	f64 = 1 + smallestFloat64
+	x64 float64 = f64
+	y64 = float64(f64)
+	_ = assert(x64 - y64 == 0)
+)
diff --git a/go/types/testdata/constdecl.src b/go/types/testdata/constdecl.src
new file mode 100644
index 0000000..6de9b13
--- /dev/null
+++ b/go/types/testdata/constdecl.src
@@ -0,0 +1,97 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package constdecl
+
+import "math"
+
+var v int
+
+// Const decls must be initialized by constants.
+const _ = v /* ERROR "not constant" */
+const _ = math /* ERROR "not constant" */ .Sin(0)
+const _ = int /* ERROR "not an expression" */
+
+func _() {
+	const _ = v /* ERROR "not constant" */
+	const _ = math /* ERROR "not constant" */ .Sin(0)
+	const _ = int /* ERROR "not an expression" */
+}
+
+// Identifier and expression arity must match.
+// The first error message is produced by the parser.
+// In a real-world scenario, the type-checker would not be run
+// in this case and the 2nd error message would not appear.
+const _ /* ERROR "missing constant value" */ /* ERROR "missing init expr for _" */
+const _ = 1, 2 /* ERROR "extra init expr 2" */
+
+const _ /* ERROR "missing constant value" */ /* ERROR "missing init expr for _" */ int
+const _ int = 1, 2 /* ERROR "extra init expr 2" */
+
+const (
+	_ /* ERROR "missing constant value" */ /* ERROR "missing init expr for _" */
+	_ = 1, 2 /* ERROR "extra init expr 2" */
+
+	_ /* ERROR "missing constant value" */ /* ERROR "missing init expr for _" */ int
+	_ int = 1, 2 /* ERROR "extra init expr 2" */
+)
+
+const (
+	_ = 1
+	_
+	_, _ /* ERROR "missing init expr for _" */
+	_
+)
+
+const (
+	_, _ = 1, 2
+	_, _
+	_ /* ERROR "extra init expr at" */
+	_, _
+	_, _, _ /* ERROR "missing init expr for _" */
+	_, _
+)
+
+func _() {
+	const _ /* ERROR "missing constant value" */ /* ERROR "missing init expr for _" */
+	const _ = 1, 2 /* ERROR "extra init expr 2" */
+
+	const _ /* ERROR "missing constant value" */ /* ERROR "missing init expr for _" */ int
+	const _ int = 1, 2 /* ERROR "extra init expr 2" */
+
+	const (
+		_ /* ERROR "missing constant value" */ /* ERROR "missing init expr for _" */
+		_ = 1, 2 /* ERROR "extra init expr 2" */
+
+		_ /* ERROR "missing constant value" */ /* ERROR "missing init expr for _" */ int
+		_ int = 1, 2 /* ERROR "extra init expr 2" */
+	)
+
+	const (
+		_ = 1
+		_
+		_, _ /* ERROR "missing init expr for _" */
+		_
+	)
+
+	const (
+		_, _ = 1, 2
+		_, _
+		_ /* ERROR "extra init expr at" */
+		_, _
+		_, _, _ /* ERROR "missing init expr for _" */
+		_, _
+	)
+}
+
+// Test case for constant with invalid initialization.
+// Caused panic because the constant value was not set up (gri - 7/8/2014).
+func _() {
+	const (
+	    x string = missing /* ERROR "undeclared name" */
+	    y = x + ""
+	)
+}
+
+// TODO(gri) move extra tests from testdata/const0.src into here
diff --git a/go/types/testdata/conversions.src b/go/types/testdata/conversions.src
new file mode 100644
index 0000000..e1336c0
--- /dev/null
+++ b/go/types/testdata/conversions.src
@@ -0,0 +1,93 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// conversions
+
+package conversions
+
+import "unsafe"
+
+// argument count
+var (
+	_ = int() /* ERROR "missing argument" */
+	_ = int(1, 2 /* ERROR "too many arguments" */ )
+)
+
+// numeric constant conversions are in const1.src.
+
+func string_conversions() {
+	const A = string(65)
+	assert(A == "A")
+	const E = string(-1)
+	assert(E == "\uFFFD")
+	assert(E == string(1234567890))
+
+	type myint int
+	assert(A == string(myint(65)))
+
+	type mystring string
+	const _ mystring = mystring("foo")
+
+	const _ = string(true /* ERROR "cannot convert" */ )
+	const _ = string(1.2 /* ERROR "cannot convert" */ )
+	const _ = string(nil /* ERROR "cannot convert" */ )
+
+	// issues 11357, 11353: argument must be of integer type
+	_ = string(0.0 /* ERROR "cannot convert" */ )
+	_ = string(0i /* ERROR "cannot convert" */ )
+	_ = string(1 /* ERROR "cannot convert" */ + 2i)
+}
+
+func interface_conversions() {
+	type E interface{}
+
+	type I1 interface{
+		m1()
+	}
+
+	type I2 interface{
+		m1()
+		m2(x int)
+	}
+
+	type I3 interface{
+		m1()
+		m2() int
+	}
+
+	var e E
+	var i1 I1
+	var i2 I2
+	var i3 I3
+
+	_ = E(0)
+	_ = E(nil)
+	_ = E(e)
+	_ = E(i1)
+	_ = E(i2)
+
+	_ = I1(0 /* ERROR "cannot convert" */ )
+	_ = I1(nil)
+	_ = I1(i1)
+	_ = I1(e /* ERROR "cannot convert" */ )
+	_ = I1(i2)
+
+	_ = I2(nil)
+	_ = I2(i1 /* ERROR "cannot convert" */ )
+	_ = I2(i2)
+	_ = I2(i3 /* ERROR "cannot convert" */ )
+
+	_ = I3(nil)
+	_ = I3(i1 /* ERROR "cannot convert" */ )
+	_ = I3(i2 /* ERROR "cannot convert" */ )
+	_ = I3(i3)
+
+	// TODO(gri) add more tests, improve error message
+}
+
+func issue6326() {
+	type T unsafe.Pointer
+	var x T
+	_ = uintptr(x) // see issue 6326
+}
diff --git a/go/types/testdata/cycles.src b/go/types/testdata/cycles.src
new file mode 100644
index 0000000..621d83c
--- /dev/null
+++ b/go/types/testdata/cycles.src
@@ -0,0 +1,143 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package cycles
+
+type (
+	T0 int
+	T1 /* ERROR cycle */ T1
+	T2 *T2
+
+	T3 /* ERROR cycle */ T4
+	T4 T5
+	T5 T3
+
+	T6 T7
+	T7 *T8
+	T8 T6
+
+	// arrays
+	A0 /* ERROR cycle */ [10]A0
+	A1 [10]*A1
+
+	A2 /* ERROR cycle */ [10]A3
+	A3 [10]A4
+	A4 A2
+
+	A5 [10]A6
+	A6 *A5
+
+	// slices
+	L0 []L0
+
+	// structs
+	S0 /* ERROR cycle */ struct{ _ S0 }
+	S1 /* ERROR cycle */ struct{ S1 }
+	S2 struct{ _ *S2 }
+	S3 struct{ *S3 }
+
+	S4 /* ERROR cycle */ struct{ S5 }
+	S5 struct{ S6 }
+	S6 S4
+
+	// pointers
+	P0 *P0
+
+	// functions
+	F0 func(F0)
+	F1 func() F1
+	F2 func(F2) F2
+
+	// interfaces
+	I0 /* ERROR cycle */ interface{ I0 }
+
+	I1 interface{ I2 }
+	I2 interface{ I3 }
+	I3 /* ERROR cycle */ interface{ I1 }
+
+	I4 interface{ f(I4) }
+
+	// testcase for issue 5090
+	I5 interface{ f(I6) }
+	I6 interface{ I5 }
+
+	// maps
+	M0 map[M0 /* ERROR invalid map key */ ]M0
+
+	// channels
+	C0 chan C0
+)
+
+func _() {
+	type (
+		t1 /* ERROR cycle */ t1
+		t2 *t2
+
+		t3 t4 /* ERROR undeclared */
+		t4 t5 /* ERROR undeclared */
+		t5 t3
+
+		// arrays
+		a0 /* ERROR cycle */ [10]a0
+		a1 [10]*a1
+
+		// slices
+		l0 []l0
+
+		// structs
+		s0 /* ERROR cycle */ struct{ _ s0 }
+		s1 /* ERROR cycle */ struct{ s1 }
+		s2 struct{ _ *s2 }
+		s3 struct{ *s3 }
+
+		// pointers
+		p0 *p0
+
+		// functions
+		f0 func(f0)
+		f1 func() f1
+		f2 func(f2) f2
+
+		// interfaces
+		i0 /* ERROR cycle */ interface{ i0 }
+
+		// maps
+		m0 map[m0 /* ERROR invalid map key */ ]m0
+
+		// channels
+		c0 chan c0
+	)
+}
+
+// test cases for issue 6667
+
+type A [10]map[A /* ERROR invalid map key */ ]bool
+
+type S struct {
+	m map[S /* ERROR invalid map key */ ]bool
+}
+
+// test cases for issue 7236
+// (cycle detection must not be dependent on starting point of resolution)
+
+type (
+	P1 *T9
+	T9 /* ERROR cycle */ T9
+
+	T10 /* ERROR cycle */ T10
+	P2 *T10
+)
+
+func (T11) m() {}
+
+type T11 /* ERROR cycle */ struct{ T11 }
+
+type T12 /* ERROR cycle */ struct{ T12 }
+
+func (*T12) m() {}
+
+type (
+	P3 *T13
+	T13 /* ERROR cycle */ T13
+)
\ No newline at end of file
diff --git a/go/types/testdata/cycles1.src b/go/types/testdata/cycles1.src
new file mode 100644
index 0000000..ae2b38e
--- /dev/null
+++ b/go/types/testdata/cycles1.src
@@ -0,0 +1,77 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+type (
+	A interface {
+		a() interface {
+			ABC1
+		}
+	}
+	B interface {
+		b() interface {
+			ABC2
+		}
+	}
+	C interface {
+		c() interface {
+			ABC3
+		}
+	}
+
+	AB interface {
+		A
+		B
+	}
+	BC interface {
+		B
+		C
+	}
+
+	ABC1 interface {
+		A
+		B
+		C
+	}
+	ABC2 interface {
+		AB
+		C
+	}
+	ABC3 interface {
+		A
+		BC
+	}
+)
+
+var (
+	x1 ABC1
+	x2 ABC2
+	x3 ABC3
+)
+
+func _() {
+	// all types have the same method set
+	x1 = x2
+	x2 = x1
+
+	x1 = x3
+	x3 = x1
+
+	x2 = x3
+	x3 = x2
+
+	// all methods return the same type again
+	x1 = x1.a()
+	x1 = x1.b()
+	x1 = x1.c()
+
+	x2 = x2.a()
+	x2 = x2.b()
+	x2 = x2.c()
+
+	x3 = x3.a()
+	x3 = x3.b()
+	x3 = x3.c()
+}
diff --git a/go/types/testdata/cycles2.src b/go/types/testdata/cycles2.src
new file mode 100644
index 0000000..345ab56
--- /dev/null
+++ b/go/types/testdata/cycles2.src
@@ -0,0 +1,118 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+import "unsafe"
+
+// Test case for issue 5090
+
+type t interface {
+	f(u)
+}
+
+type u interface {
+	t
+}
+
+func _() {
+	var t t
+	var u u
+
+	t.f(t)
+	t.f(u)
+	
+	u.f(t)
+	u.f(u)
+}
+
+
+// Test case for issue 6589.
+
+type A interface {
+	a() interface {
+		AB
+	}
+}
+
+type B interface {
+	a() interface {
+		AB
+	}
+}
+
+type AB interface {
+	a() interface {
+		A
+		B /* ERROR a redeclared */
+	}
+	b() interface {
+		A
+		B /* ERROR a redeclared */
+	}
+}
+
+var x AB
+var y interface {
+	A
+	B /* ERROR a redeclared */
+}
+var _ = x /* ERROR cannot compare */ == y
+
+
+// Test case for issue 6638.
+
+type T interface {
+	m() [T /* ERROR no value */ (nil).m()[0]]int
+}
+
+// Variations of this test case.
+
+type T1 interface {
+	m() [x1 /* ERROR no value */ .m()[0]]int
+}
+
+var x1 T1
+
+type T2 interface {
+	m() [len(x2 /* ERROR no value */ .m())]int
+}
+
+var x2 T2
+
+type T3 interface {
+	m() [unsafe.Sizeof(x3.m)]int
+}
+
+var x3 T3
+
+// The test case below should also report an error for
+// the cast inside the T4 interface (like it does for the
+// variable initialization). The reason why it does not is
+// that inside T4, the method x4.m depends on T4 which is not
+// fully set up yet. The x4.m method happens to have an empty
+// signature which is why the cast is permitted.
+// TODO(gri) Consider marking methods as incomplete and provide
+// a better error message in that case.
+
+type T4 interface {
+	m() [unsafe.Sizeof(cast4(x4.m))]int
+}
+
+var x4 T4
+var _ = cast4(x4 /* ERROR cannot convert */.m)
+
+type cast4 func()
+
+// This test is symmetric to the T4 case: Here the cast is
+// "correct", but it doesn't work inside the T5 interface.
+
+type T5 interface {
+	m() [unsafe.Sizeof(cast5(x5 /* ERROR cannot convert */ .m))]int
+}
+
+var x5 T5
+var _ = cast5(x5.m)
+
+type cast5 func() [0]int
diff --git a/go/types/testdata/cycles3.src b/go/types/testdata/cycles3.src
new file mode 100644
index 0000000..3da4fb5
--- /dev/null
+++ b/go/types/testdata/cycles3.src
@@ -0,0 +1,60 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+import "unsafe"
+
+var (
+	_ A = A(nil).a().b().c().d().e().f()
+	_ A = A(nil).b().c().d().e().f()
+	_ A = A(nil).c().d().e().f()
+	_ A = A(nil).d().e().f()
+	_ A = A(nil).e().f()
+	_ A = A(nil).f()
+	_ A = A(nil)
+)
+
+type (
+	A interface {
+		a() B
+		B
+	}
+
+	B interface {
+		b() C
+		C
+	}
+
+	C interface {
+		c() D
+		D
+	}
+
+	D interface {
+		d() E
+		E
+	}
+
+	E interface {
+		e() F
+		F
+	}
+
+	F interface {
+		f() A
+	}
+)
+
+type (
+	U interface {
+		V
+	}
+
+	V interface {
+		v() [unsafe.Sizeof(u)]int
+	}
+)
+
+var u U
diff --git a/go/types/testdata/cycles4.src b/go/types/testdata/cycles4.src
new file mode 100644
index 0000000..445babc
--- /dev/null
+++ b/go/types/testdata/cycles4.src
@@ -0,0 +1,110 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+// Check that all methods of T are collected before
+// determining the result type of m (which embeds
+// all methods of T).
+
+type T interface {
+	m() interface {T}
+	E
+}
+
+var _ = T.m(nil).m().e()
+
+type E interface {
+	e() int
+}
+
+// Check that unresolved forward chains are followed
+// (see also comment in resolver.go, checker.typeDecl).
+
+var _ = C.m(nil).m().e()
+
+type A B
+
+type B interface {
+	m() interface{C}
+	E
+}
+
+type C A
+
+// Check that interface type comparison for identity
+// does not recur endlessly.
+
+type T1 interface {
+	m() interface{T1}
+}
+
+type T2 interface {
+	m() interface{T2}
+}
+
+func _(x T1, y T2) {
+	// Checking for assignability of interfaces must check
+	// if all methods of x are present in y, and that they
+	// have identical signatures. The signatures recur via
+	// the result type, which is an interface that embeds
+	// a single method m that refers to the very interface
+	// that contains it. This requires cycle detection in
+	// identity checks for interface types.
+	x = y
+}
+
+type T3 interface {
+	m() interface{T4}
+}
+
+type T4 interface {
+	m() interface{T3}
+}
+
+func _(x T1, y T3) {
+	x = y
+}
+
+// Check that interfaces are type-checked in order of
+// (embedded interface) dependencies (was issue 7158).
+
+var x1 T5 = T7(nil)
+
+type T5 interface {
+	T6
+}
+
+type T6 interface {
+	m() T7
+}
+type T7 interface {
+	T5
+}
+
+// Actual test case from issue 7158.
+
+func wrapNode() Node {
+	return wrapElement()
+}
+
+func wrapElement() Element {
+	return nil
+}
+
+type EventTarget interface {
+	AddEventListener(Event)
+}
+
+type Node interface {
+	EventTarget
+}
+
+type Element interface {
+	Node
+}
+
+type Event interface {
+	Target() Element
+}
diff --git a/go/types/testdata/decls0.src b/go/types/testdata/decls0.src
new file mode 100644
index 0000000..21baafe
--- /dev/null
+++ b/go/types/testdata/decls0.src
@@ -0,0 +1,207 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// type declarations
+
+package decls0
+
+import "unsafe"
+
+const pi = 3.1415
+
+type (
+	N undeclared /* ERROR "undeclared" */
+	B bool
+	I int32
+	A [10]P
+	T struct {
+		x, y P
+	}
+	P *T
+	R (*R)
+	F func(A) I
+	Y interface {
+		f(A) I
+	}
+	S [](((P)))
+	M map[I]F
+	C chan<- I
+
+	// blank types must be typechecked
+	_ pi /* ERROR "not a type" */
+	_ struct{}
+	_ struct{ pi /* ERROR "not a type" */ }
+)
+
+
+// declarations of init
+const _, init /* ERROR "cannot declare init" */ , _ = 0, 1, 2
+type init /* ERROR "cannot declare init" */ struct{}
+var _, init /* ERROR "cannot declare init" */ int
+
+func init() {}
+func init /* ERROR "missing function body" */ ()
+
+func _() { const init = 0 }
+func _() { type init int }
+func _() { var init int; _ = init }
+
+// invalid array types
+type (
+	iA0 [... /* ERROR "invalid use of '...'" */ ]byte
+	iA1 [1 /* ERROR "invalid array length" */ <<100]int
+	iA2 [- /* ERROR "invalid array length" */ 1]complex128
+	iA3 ["foo" /* ERROR "must be integer" */ ]string
+	iA4 [float64 /* ERROR "must be integer" */ (0)]int
+)
+
+
+type (
+	p1 pi /* ERROR "no field or method foo" */ .foo
+	p2 unsafe.Pointer
+)
+
+
+type (
+	Pi pi /* ERROR "not a type" */
+
+	a /* ERROR "illegal cycle" */ a
+	a /* ERROR "redeclared" */ int
+
+	// where the cycle error appears depends on the
+	// order in which declarations are processed
+	// (which depends on the order in which a map
+	// is iterated through)
+	b /* ERROR "illegal cycle" */ c
+	c d
+	d e
+	e b
+
+	t *t
+
+	U V
+	V *W
+	W U
+
+	P1 *S2
+	P2 P1
+
+	S0 struct {
+	}
+	S1 struct {
+		a, b, c int
+		u, v, a /* ERROR "redeclared" */ float32
+	}
+	S2 struct {
+		S0 // anonymous field
+		S0 /* ERROR "redeclared" */ int
+	}
+	S3 struct {
+		x S2
+	}
+	S4/* ERROR "illegal cycle" */ struct {
+		S4
+	}
+	S5 /* ERROR "illegal cycle" */ struct {
+		S6
+	}
+	S6 struct {
+		field S7
+	}
+	S7 struct {
+		S5
+	}
+
+	L1 []L1
+	L2 []int
+
+	A1 [10.0]int
+	A2 /* ERROR "illegal cycle" */ [10]A2
+	A3 /* ERROR "illegal cycle" */ [10]struct {
+		x A4
+	}
+	A4 [10]A3
+
+	F1 func()
+	F2 func(x, y, z float32)
+	F3 func(x, y, x /* ERROR "redeclared" */ float32)
+	F4 func() (x, y, x /* ERROR "redeclared" */ float32)
+	F5 func(x int) (x /* ERROR "redeclared" */ float32)
+	F6 func(x ...int)
+
+	I1 interface{}
+	I2 interface {
+		m1()
+	}
+	I3 interface {
+		m1()
+		m1 /* ERROR "redeclared" */ ()
+	}
+	I4 interface {
+		m1(x, y, x /* ERROR "redeclared" */ float32)
+		m2() (x, y, x /* ERROR "redeclared" */ float32)
+		m3(x int) (x /* ERROR "redeclared" */ float32)
+	}
+	I5 interface {
+		m1(I5)
+	}
+	I6 interface {
+		S0 /* ERROR "not an interface" */
+	}
+	I7 interface {
+		I1
+		I1
+	}
+	I8 /* ERROR "illegal cycle" */ interface {
+		I8
+	}
+	I9 interface {
+		I10
+	}
+	I10 interface {
+		I11
+	}
+	I11 /* ERROR "illegal cycle" */ interface {
+		I9
+	}
+
+	C1 chan int
+	C2 <-chan int
+	C3 chan<- C3
+	C4 chan C5
+	C5 chan C6
+	C6 chan C4
+
+	M1 map[Last]string
+	M2 map[string]M2
+
+	Last int
+)
+
+// cycles in function/method declarations
+// (test cases for issue 5217 and variants)
+func f1(x f1 /* ERROR "not a type" */ ) {}
+func f2(x *f2 /* ERROR "not a type" */ ) {}
+func f3() (x f3 /* ERROR "not a type" */ ) { return }
+func f4() (x *f4 /* ERROR "not a type" */ ) { return }
+
+func (S0) m1(x S0 /* ERROR "field or method" */ .m1) {}
+func (S0) m2(x *S0 /* ERROR "field or method" */ .m2) {}
+func (S0) m3() (x S0 /* ERROR "field or method" */ .m3) { return }
+func (S0) m4() (x *S0 /* ERROR "field or method" */ .m4) { return }
+
+// interfaces may not have any blank methods
+type BlankI interface {
+	_ /* ERROR "invalid method name" */ ()
+	_ /* ERROR "invalid method name" */ (float32) int
+	m()
+}
+
+// non-interface types may have multiple blank methods
+type BlankT struct{}
+
+func (BlankT) _() {}
+func (BlankT) _(int) {}
+func (BlankT) _() int { return 0 }
+func (BlankT) _(int) int { return 0}
diff --git a/go/types/testdata/decls1.src b/go/types/testdata/decls1.src
new file mode 100644
index 0000000..7855e46
--- /dev/null
+++ b/go/types/testdata/decls1.src
@@ -0,0 +1,144 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// variable declarations
+
+package decls1
+
+import (
+	"math"
+)
+
+// Global variables without initialization
+var (
+	a, b bool
+	c byte
+	d uint8
+	r rune
+	i int
+	j, k, l int
+	x, y float32
+	xx, yy float64
+	u, v complex64
+	uu, vv complex128
+	s, t string
+	array []byte
+	iface interface{}
+	
+	blank _ /* ERROR "cannot use _" */
+)
+
+// Global variables with initialization
+var (
+	s1 = i + j
+	s2 = i /* ERROR "mismatched types" */ + x
+	s3 = c + d
+	s4 = s + t
+	s5 = s /* ERROR "invalid operation" */ / t
+	s6 = array[t1]
+	s7 = array[x /* ERROR "integer" */]
+	s8 = &a
+	s10 = &42 /* ERROR "cannot take address" */
+	s11 = &v
+	s12 = -(u + *t11) / *&v
+	s13 = a /* ERROR "shifted operand" */ << d
+	s14 = i << j /* ERROR "must be unsigned" */ 
+	s18 = math.Pi * 10.0
+	s19 = s1 /* ERROR "cannot call" */ ()
+ 	s20 = f0 /* ERROR "no value" */ ()
+	s21 = f6(1, s1, i)
+	s22 = f6(1, s1, uu /* ERROR "cannot pass argument" */ )
+	
+	t1 int = i + j
+	t2 int = i /* ERROR "mismatched types" */ + x
+	t3 int = c /* ERROR "cannot initialize" */ + d
+	t4 string = s + t
+	t5 string = s /* ERROR "invalid operation" */ / t
+	t6 byte = array[t1]
+	t7 byte = array[x /* ERROR "must be integer" */]
+	t8 *int = & /* ERROR "cannot initialize" */ a
+	t10 *int = &42 /* ERROR "cannot take address" */
+	t11 *complex64 = &v
+	t12 complex64 = -(u + *t11) / *&v
+	t13 int = a /* ERROR "shifted operand" */ << d
+	t14 int = i << j /* ERROR "must be unsigned" */ 
+	t15 math /* ERROR "not in selector" */
+	t16 math /* ERROR "not declared" */ .xxx
+	t17 math /* ERROR "not a type" */ .Pi
+	t18 float64 = math.Pi * 10.0
+	t19 int = t1 /* ERROR "cannot call" */ ()
+	t20 int = f0 /* ERROR "no value" */ ()
+	t21 int = a /* ERROR "cannot initialize" */
+)
+
+// Various more complex expressions
+var (
+	u1 = x /* ERROR "not an interface" */ .(int)
+	u2 = iface.([]int)
+	u3 = iface.(a /* ERROR "not a type" */ )
+	u4, ok = iface.(int)
+	u5, ok2, ok3 = iface /* ERROR "assignment count mismatch" */ .(int)
+)
+
+// Constant expression initializations
+var (
+	v1 = 1 /* ERROR "cannot convert" */ + "foo"
+	v2 = c + 255
+	v3 = c + 256 /* ERROR "overflows" */
+	v4 = r + 2147483647
+	v5 = r + 2147483648 /* ERROR "overflows" */
+	v6 = 42
+	v7 = v6 + 9223372036854775807
+	v8 = v6 + 9223372036854775808 /* ERROR "overflows" */
+	v9 = i + 1 << 10
+	v10 byte = 1024 /* ERROR "overflows" */
+	v11 = xx/yy*yy - xx
+	v12 = true && false
+	v13 = nil /* ERROR "use of untyped nil" */
+)
+
+// Multiple assignment expressions
+var (
+	m1a, m1b = 1, 2
+	m2a, m2b, m2c /* ERROR "missing init expr for m2c" */ = 1, 2
+	m3a, m3b = 1, 2, 3 /* ERROR "extra init expr 3" */
+)
+
+func _() {
+	var (
+		m1a, m1b = 1, 2
+		m2a, m2b, m2c /* ERROR "missing init expr for m2c" */ = 1, 2
+		m3a, m3b = 1, 2, 3 /* ERROR "extra init expr 3" */
+	)
+
+	_, _ = m1a, m1b
+	_, _, _ = m2a, m2b, m2c
+	_, _ = m3a, m3b
+}
+
+// Declaration of parameters and results
+func f0() {}
+func f1(a /* ERROR "not a type" */) {}
+func f2(a, b, c d /* ERROR "not a type" */) {}
+
+func f3() int { return 0 }
+func f4() a /* ERROR "not a type" */ { return 0 }
+func f5() (a, b, c d /* ERROR "not a type" */) { return }
+
+func f6(a, b, c int) complex128 { return 0 }
+
+// Declaration of receivers
+type T struct{}
+
+func (T) m0() {}
+func (*T) m1() {}
+func (x T) m2() {}
+func (x *T) m3() {}
+
+// Initialization functions
+func init() {}
+func /* ERROR "no arguments and no return values" */ init(int) {}
+func /* ERROR "no arguments and no return values" */ init() int { return 0 }
+func /* ERROR "no arguments and no return values" */ init(int) int { return 0 }
+func (T) init(int) int { return 0 }
diff --git a/go/types/testdata/decls2a.src b/go/types/testdata/decls2a.src
new file mode 100644
index 0000000..bdbecd9
--- /dev/null
+++ b/go/types/testdata/decls2a.src
@@ -0,0 +1,111 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// method declarations
+
+package decls2
+
+import "time"
+import "unsafe"
+
+// T1 declared before its methods.
+type T1 struct{
+	f int
+}
+
+func (T1) m() {}
+func (T1) m /* ERROR "already declared" */ () {}
+func (x *T1) f /* ERROR "field and method" */ () {}
+
+// Conflict between embedded field and method name,
+// with the embedded field being a basic type.
+type T1b struct {
+	int
+}
+
+func (T1b) int /* ERROR "field and method" */ () {}
+
+type T1c struct {
+	time.Time
+}
+
+func (T1c) Time /* ERROR "field and method" */ () int { return 0 }
+
+// Disabled for now: LookupFieldOrMethod will find Pointer even though
+// it's double-declared (it would cost extra in the common case to verify
+// this). But the MethodSet computation will not find it due to the name
+// collision caused by the double-declaration, leading to an internal
+// inconsistency while we are verifying one computation against the other.
+// var _ = T1c{}.Pointer
+
+// T2's method declared before the type.
+func (*T2) f /* ERROR "field and method" */ () {}
+
+type T2 struct {
+	f int
+}
+
+// Methods declared without a declared type.
+func (undeclared /* ERROR "undeclared" */) m() {}
+func (x *undeclared /* ERROR "undeclared" */) m() {}
+
+func (pi /* ERROR "not a type" */) m1() {}
+func (x pi /* ERROR "not a type" */) m2() {}
+func (x *pi /* ERROR "not a type" */ ) m3() {}
+
+// Blank types.
+type _ struct { m int }
+type _ struct { m int }
+
+func (_ /* ERROR "cannot use _" */) m() {}
+func m(_ /* ERROR "cannot use _" */) {}
+
+// Methods with receiver base type declared in another file.
+func (T3) m1() {}
+func (*T3) m2() {}
+func (x T3) m3() {}
+func (x *T3) f /* ERROR "field and method" */ () {}
+
+// Methods of non-struct type.
+type T4 func()
+
+func (self T4) m() func() { return self }
+
+// Methods associated with an interface.
+type T5 interface {
+	m() int
+}
+
+func (T5 /* ERROR "invalid receiver" */ ) m1() {}
+func (T5 /* ERROR "invalid receiver" */ ) m2() {}
+
+// Methods associated with a named pointer type.
+type ptr *int
+func (ptr /* ERROR "invalid receiver" */ ) _() {}
+func (* /* ERROR "invalid receiver" */ ptr) _() {}
+
+// Methods with zero or multiple receivers.
+func ( /* ERROR "missing receiver" */ ) _() {}
+func (T3, * /* ERROR "exactly one receiver" */ T3) _() {}
+func (T3, T3, T3 /* ERROR "exactly one receiver" */ ) _() {}
+func (a, b /* ERROR "exactly one receiver" */ T3) _() {}
+func (a, b, c /* ERROR "exactly one receiver" */ T3) _() {}
+
+// Methods associated with non-local or unnamed types.
+func (int /* ERROR "invalid receiver" */ ) m() {}
+func ([ /* ERROR "invalid receiver" */ ]int) m() {}
+func (time /* ERROR "invalid receiver" */ .Time) m() {}
+func (* /* ERROR "invalid receiver" */ time.Time) m() {}
+func (x /* ERROR "invalid receiver" */ interface{}) m() {}
+
+// Unsafe.Pointer is treated like a pointer when used as receiver type.
+type UP unsafe.Pointer
+func (UP /* ERROR "invalid" */ ) m1() {}
+func (* /* ERROR "invalid" */ UP) m2() {}
+
+// Double declarations across package files
+const c_double = 0
+type t_double int
+var v_double int
+func f_double() {}
diff --git a/go/types/testdata/decls2b.src b/go/types/testdata/decls2b.src
new file mode 100644
index 0000000..e7bc394
--- /dev/null
+++ b/go/types/testdata/decls2b.src
@@ -0,0 +1,65 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// method declarations
+
+package decls2
+
+import "io"
+
+const pi = 3.1415
+
+func (T1) m /* ERROR "already declared" */ () {}
+func (T2) m(io.Writer) {}
+
+type T3 struct {
+	f *T3
+}
+
+type T6 struct {
+	x int
+}
+
+func (t *T6) m1() int {
+	return t.x
+}
+
+func f() {
+	var t *T6
+	t.m1()
+}
+
+// Double declarations across package files
+const c_double /* ERROR "redeclared" */ = 0
+type t_double  /* ERROR "redeclared" */ int
+var v_double /* ERROR "redeclared" */ int
+func f_double /* ERROR "redeclared" */ () {}
+
+// Blank methods need to be type-checked.
+// Verify by checking that errors are reported.
+func (T /* ERROR "undeclared" */ ) _() {}
+func (T1) _(undeclared /* ERROR "undeclared" */ ) {}
+func (T1) _() int { return "foo" /* ERROR "cannot convert" */ }
+
+// Methods with undeclared receiver type can still be checked.
+// Verify by checking that errors are reported.
+func (Foo /* ERROR "undeclared" */ ) m() {}
+func (Foo /* ERROR "undeclared" */ ) m(undeclared /* ERROR "undeclared" */ ) {}
+func (Foo /* ERROR "undeclared" */ ) m() int { return "foo" /* ERROR "cannot convert" */ }
+
+func (Foo /* ERROR "undeclared" */ ) _() {}
+func (Foo /* ERROR "undeclared" */ ) _(undeclared /* ERROR "undeclared" */ ) {}
+func (Foo /* ERROR "undeclared" */ ) _() int { return "foo" /* ERROR "cannot convert" */ }
+
+// Receiver declarations are regular parameter lists;
+// receiver types may use parentheses, and the list
+// may have a trailing comma.
+type T7 struct {}
+
+func (T7) m1() {}
+func ((T7)) m2() {}
+func ((*T7)) m3() {}
+func (x *(T7),) m4() {}
+func (x (*(T7)),) m5() {}
+func (x ((*((T7)))),) m6() {}
diff --git a/go/types/testdata/decls3.src b/go/types/testdata/decls3.src
new file mode 100644
index 0000000..80d2bc8
--- /dev/null
+++ b/go/types/testdata/decls3.src
@@ -0,0 +1,309 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// embedded types
+
+package decls3
+
+import "unsafe"
+import "fmt"
+
+// fields with the same name at the same level cancel each other out
+
+func _() {
+	type (
+		T1 struct { X int }
+		T2 struct { X int }
+		T3 struct { T1; T2 } // X is embedded twice at the same level via T1->X, T2->X
+	)
+
+	var t T3
+	_ = t /* ERROR "ambiguous selector" */ .X
+}
+
+func _() {
+	type (
+		T1 struct { X int }
+		T2 struct { T1 }
+		T3 struct { T1 }
+		T4 struct { T2; T3 } // X is embedded twice at the same level via T2->T1->X, T3->T1->X
+	)
+
+	var t T4
+	_ = t /* ERROR "ambiguous selector" */ .X
+}
+
+func issue4355() {
+	type (
+	    T1 struct {X int}
+	    T2 struct {T1}
+	    T3 struct {T2}
+	    T4 struct {T2}
+	    T5 struct {T3; T4} // X is embedded twice at the same level via T3->T2->T1->X, T4->T2->T1->X
+	)	
+
+	var t T5
+	_ = t /* ERROR "ambiguous selector" */ .X
+}
+
+func _() {
+	type State int
+	type A struct{ State }
+	type B struct{ fmt.State }
+	type T struct{ A; B }
+
+	var t T
+	_ = t /* ERROR "ambiguous selector" */ .State
+}
+
+// Embedded fields can be predeclared types.
+
+func _() {
+	type T0 struct{
+		int
+		float32
+		f int
+	}
+	var x T0
+	_ = x.int
+	_ = x.float32
+	_ = x.f
+
+	type T1 struct{
+		T0
+	}
+	var y T1
+	_ = y.int
+	_ = y.float32
+	_ = y.f
+}
+
+// Restrictions on embedded field types.
+
+func _() {
+	type I1 interface{}
+	type I2 interface{}
+	type P1 *int
+	type P2 *int
+	type UP unsafe.Pointer
+
+	type T1 struct {
+		I1
+		* /* ERROR "cannot be a pointer to an interface" */ I2
+		* /* ERROR "cannot be a pointer to an interface" */ error
+		P1 /* ERROR "cannot be a pointer" */
+		* /* ERROR "cannot be a pointer" */ P2
+	}
+
+	// unsafe.Pointers are treated like regular pointers when embedded
+	type T2 struct {
+		unsafe /* ERROR "cannot be unsafe.Pointer" */ .Pointer
+		*/* ERROR "cannot be unsafe.Pointer" */ unsafe.Pointer
+		UP /* ERROR "cannot be unsafe.Pointer" */
+		* /* ERROR "cannot be unsafe.Pointer" */ UP
+	}
+}
+
+// Named types that are pointers.
+
+type S struct{ x int }
+func (*S) m() {}
+type P *S
+
+func _() {
+	var s *S
+	_ = s.x
+	_ = s.m
+
+	var p P
+	_ = p.x
+	_ = p /* ERROR "no field or method" */ .m
+	_ = P /* ERROR "no field or method" */ .m
+}
+
+// Borrowed from the FieldByName test cases in reflect/all_test.go.
+
+type D1 struct {
+	d int
+}
+type D2 struct {
+	d int
+}
+
+type S0 struct {
+	A, B, C int
+	D1
+	D2
+}
+
+type S1 struct {
+	B int
+	S0
+}
+
+type S2 struct {
+	A int
+	*S1
+}
+
+type S1x struct {
+	S1
+}
+
+type S1y struct {
+	S1
+}
+
+type S3 struct {
+	S1x
+	S2
+	D, E int
+	*S1y
+}
+
+type S4 struct {
+	*S4
+	A int
+}
+
+// The X in S6 and S7 annihilate, but they also block the X in S8.S9.
+type S5 struct {
+	S6
+	S7
+	S8
+}
+
+type S6 struct {
+	X int
+}
+
+type S7 S6
+
+type S8 struct {
+	S9
+}
+
+type S9 struct {
+	X int
+	Y int
+}
+
+// The X in S11.S6 and S12.S6 annihilate, but they also block the X in S13.S8.S9.
+type S10 struct {
+	S11
+	S12
+	S13
+}
+
+type S11 struct {
+	S6
+}
+
+type S12 struct {
+	S6
+}
+
+type S13 struct {
+	S8
+}
+
+func _() {
+	_ = struct /* ERROR "no field or method" */ {}{}.Foo
+	_ = S0{}.A
+	_ = S0 /* ERROR "no field or method" */ {}.D
+	_ = S1{}.A
+	_ = S1{}.B
+	_ = S1{}.S0
+	_ = S1{}.C
+	_ = S2{}.A
+	_ = S2{}.S1
+	_ = S2{}.B
+	_ = S2{}.C
+	_ = S2 /* ERROR "no field or method" */ {}.D
+	_ = S3 /* ERROR "ambiguous selector" */ {}.S1
+	_ = S3{}.A
+	_ = S3 /* ERROR "ambiguous selector" */ {}.B
+	_ = S3{}.D
+	_ = S3{}.E
+	_ = S4{}.A
+	_ = S4 /* ERROR "no field or method" */ {}.B
+	_ = S5 /* ERROR "ambiguous selector" */ {}.X
+	_ = S5{}.Y
+	_ = S10 /* ERROR "ambiguous selector" */ {}.X
+	_ = S10{}.Y
+}
+
+// Borrowed from the FieldByName benchmark in reflect/all_test.go.
+
+type R0 struct {
+	*R1
+	*R2
+	*R3
+	*R4
+}
+
+type R1 struct {
+	*R5
+	*R6
+	*R7
+	*R8
+}
+
+type R2 R1
+type R3 R1
+type R4 R1
+
+type R5 struct {
+	*R9
+	*R10
+	*R11
+	*R12
+}
+
+type R6 R5
+type R7 R5
+type R8 R5
+
+type R9 struct {
+	*R13
+	*R14
+	*R15
+	*R16
+}
+
+type R10 R9
+type R11 R9
+type R12 R9
+
+type R13 struct {
+	*R17
+	*R18
+	*R19
+	*R20
+}
+
+type R14 R13
+type R15 R13
+type R16 R13
+
+type R17 struct {
+	*R21
+	*R22
+	*R23
+	*R24
+}
+
+type R18 R17
+type R19 R17
+type R20 R17
+
+type R21 struct {
+	X int
+}
+
+type R22 R21
+type R23 R21
+type R24 R21
+
+var _ = R0 /* ERROR "ambiguous selector" */ {}.X
\ No newline at end of file
diff --git a/go/types/testdata/errors.src b/go/types/testdata/errors.src
new file mode 100644
index 0000000..45bd45a
--- /dev/null
+++ b/go/types/testdata/errors.src
@@ -0,0 +1,55 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package errors
+
+// Testing precise operand formatting in error messages
+// (matching messages are regular expressions, hence the \'s).
+func f(x int, m map[string]int) {
+	// no values
+	_ = f /* ERROR "f\(0, m\) \(no value\) used as value" */ (0, m)
+
+	// built-ins
+	_ = println /* ERROR "println \(built-in\) must be called" */
+
+	// types
+	_ = complex128 /* ERROR "complex128 \(type\) is not an expression" */
+
+	// constants
+	const c1 = 991
+	const c2 float32 = 0.5
+	0 /* ERROR "0 \(untyped int constant\) is not used" */
+	c1 /* ERROR "c1 \(untyped int constant 991\) is not used" */
+	c2 /* ERROR "c2 \(constant 1/2 of type float32\) is not used" */
+	c1 /* ERROR "c1 \+ c2 \(constant 1983/2 of type float32\) is not used" */ + c2
+
+	// variables
+	x /* ERROR "x \(variable of type int\) is not used" */
+
+	// values
+	x /* ERROR "x != x \(untyped bool value\) is not used" */ != x
+	x /* ERROR "x \+ x \(value of type int\) is not used" */ + x
+
+	// value, ok's
+	const s = "foo"
+	m /* ERROR "m\[s\] \(map index expression of type int\) is not used" */ [s]
+}
+
+// Valid ERROR comments can have a variety of forms.
+func _() {
+	0 /* ERROR "0 .* is not used" */
+	0 /* ERROR 0 .* is not used */
+	0 // ERROR "0 .* is not used"
+	0 // ERROR 0 .* is not used
+}
+
+// Don't report spurious errors as a consequence of earlier errors.
+// Add more tests as needed.
+func _() {
+	if err := foo /* ERROR undeclared */ (); err != nil /* no error here */ {}
+}
+
+// Use unqualified names for package-local objects.
+type T struct{}
+var _ int = T /* ERROR value of type T */ {} // use T in error message rather then errors.T
diff --git a/go/types/testdata/expr0.src b/go/types/testdata/expr0.src
new file mode 100644
index 0000000..3120c6f
--- /dev/null
+++ b/go/types/testdata/expr0.src
@@ -0,0 +1,174 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// unary expressions
+
+package expr0 
+
+type mybool bool
+
+var (
+	// bool
+	b0 = true
+	b1 bool = b0
+	b2 = !true
+	b3 = !b1
+	b4 bool = !true
+	b5 bool = !b4
+	b6 = +b0 /* ERROR "not defined" */
+	b7 = -b0 /* ERROR "not defined" */
+	b8 = ^b0 /* ERROR "not defined" */
+	b9 = *b0 /* ERROR "cannot indirect" */
+	b10 = &true /* ERROR "cannot take address" */
+	b11 = &b0
+	b12 = <-b0 /* ERROR "cannot receive" */
+	b13 = & & /* ERROR "cannot take address" */ b0
+
+	// byte
+	_ = byte(0)
+	_ = byte(- /* ERROR "cannot convert" */ 1)
+	_ = - /* ERROR "-byte\(1\) \(constant -1 of type byte\) overflows byte" */ byte(1) // test for issue 11367
+	_ = byte /* ERROR "overflows byte" */ (0) - byte(1)
+
+	// int
+	i0 = 1
+	i1 int = i0
+	i2 = +1
+	i3 = +i0
+	i4 int = +1
+	i5 int = +i4
+	i6 = -1
+	i7 = -i0
+	i8 int = -1
+	i9 int = -i4
+	i10 = !i0 /* ERROR "not defined" */
+	i11 = ^1
+	i12 = ^i0
+	i13 int = ^1
+	i14 int = ^i4
+	i15 = *i0 /* ERROR "cannot indirect" */
+	i16 = &i0
+	i17 = *i16
+	i18 = <-i16 /* ERROR "cannot receive" */
+
+	// uint
+	u0 = uint(1)
+	u1 uint = u0
+	u2 = +1
+	u3 = +u0
+	u4 uint = +1
+	u5 uint = +u4
+	u6 = -1
+	u7 = -u0
+	u8 uint = - /* ERROR "overflows" */ 1
+	u9 uint = -u4
+	u10 = !u0 /* ERROR "not defined" */
+	u11 = ^1
+	u12 = ^i0
+	u13 uint = ^ /* ERROR "overflows" */ 1
+	u14 uint = ^u4
+	u15 = *u0 /* ERROR "cannot indirect" */
+	u16 = &u0
+	u17 = *u16
+	u18 = <-u16 /* ERROR "cannot receive" */
+	u19 = ^uint(0)
+
+	// float64
+	f0 = float64(1)
+	f1 float64 = f0
+	f2 = +1
+	f3 = +f0
+	f4 float64 = +1
+	f5 float64 = +f4
+	f6 = -1
+	f7 = -f0
+	f8 float64 = -1
+	f9 float64 = -f4
+	f10 = !f0 /* ERROR "not defined" */
+	f11 = ^1
+	f12 = ^i0
+	f13 float64 = ^1
+	f14 float64 = ^f4 /* ERROR "not defined" */
+	f15 = *f0 /* ERROR "cannot indirect" */
+	f16 = &f0
+	f17 = *u16
+	f18 = <-u16 /* ERROR "cannot receive" */
+
+	// complex128
+	c0 = complex128(1)
+	c1 complex128 = c0
+	c2 = +1
+	c3 = +c0
+	c4 complex128 = +1
+	c5 complex128 = +c4
+	c6 = -1
+	c7 = -c0
+	c8 complex128 = -1
+	c9 complex128 = -c4
+	c10 = !c0 /* ERROR "not defined" */
+	c11 = ^1
+	c12 = ^i0
+	c13 complex128 = ^1
+	c14 complex128 = ^c4 /* ERROR "not defined" */
+	c15 = *c0 /* ERROR "cannot indirect" */
+	c16 = &c0
+	c17 = *u16
+	c18 = <-u16 /* ERROR "cannot receive" */
+
+	// string
+	s0 = "foo"
+	s1 = +"foo" /* ERROR "not defined" */
+	s2 = -s0 /* ERROR "not defined" */
+	s3 = !s0 /* ERROR "not defined" */
+	s4 = ^s0 /* ERROR "not defined" */
+	s5 = *s4
+	s6 = &s4
+	s7 = *s6
+	s8 = <-s7
+
+	// channel
+	ch chan int
+	rc <-chan float64
+	sc chan <- string
+	ch0 = +ch /* ERROR "not defined" */
+	ch1 = -ch /* ERROR "not defined" */
+	ch2 = !ch /* ERROR "not defined" */
+	ch3 = ^ch /* ERROR "not defined" */
+	ch4 = *ch /* ERROR "cannot indirect" */
+	ch5 = &ch
+	ch6 = *ch5
+	ch7 = <-ch
+	ch8 = <-rc
+	ch9 = <-sc /* ERROR "cannot receive" */
+	ch10, ok = <-ch
+	// ok is of type bool
+	ch11, myok = <-ch
+	_ mybool = myok /* ERROR "cannot initialize" */
+)
+
+// address of composite literals
+type T struct{x, y int}
+
+func f() T { return T{} }
+
+var (
+	_ = &T{1, 2}
+	_ = &[...]int{}
+	_ = &[]int{}
+	_ = &[]int{}
+	_ = &map[string]T{}
+	_ = &(T{1, 2})
+	_ = &((((T{1, 2}))))
+	_ = &f /* ERROR "cannot take address" */ ()
+)
+
+// recursive pointer types
+type P *P
+
+var (
+	p1 P = new(P)
+	p2 P = *p1
+	p3 P = &p2
+)
+
diff --git a/go/types/testdata/expr1.src b/go/types/testdata/expr1.src
new file mode 100644
index 0000000..8ef0aed
--- /dev/null
+++ b/go/types/testdata/expr1.src
@@ -0,0 +1,7 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// binary expressions
+
+package expr1
diff --git a/go/types/testdata/expr2.src b/go/types/testdata/expr2.src
new file mode 100644
index 0000000..31dc5f0
--- /dev/null
+++ b/go/types/testdata/expr2.src
@@ -0,0 +1,247 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// comparisons
+
+package expr2
+
+func _bool() {
+	const t = true == true
+	const f = true == false
+	_ = t /* ERROR "cannot compare" */ < f
+	_ = 0 /* ERROR "cannot convert" */ == t
+	var b bool
+	var x, y float32
+	b = x < y
+	_ = b
+	_ = struct{b bool}{x < y}
+}
+
+// corner cases
+var (
+	v0 = nil /* ERROR "cannot compare" */ == nil
+)
+
+func arrays() {
+	// basics
+	var a, b [10]int
+	_ = a == b
+	_ = a != b
+	_ = a /* ERROR < not defined */ < b
+	_ = a == nil /* ERROR cannot convert */
+
+	type C [10]int
+	var c C
+	_ = a == c
+
+	type D [10]int
+	var d D
+	_ = c /* ERROR mismatched types */ == d
+
+	var e [10]func() int
+	_ = e /* ERROR == not defined */ == e
+}
+
+func structs() {
+	// basics
+	var s, t struct {
+		x int
+		a [10]float32
+		_ bool
+	}
+	_ = s == t
+	_ = s != t
+	_ = s /* ERROR < not defined */ < t
+	_ = s == nil /* ERROR cannot convert */
+
+	type S struct {
+		x int
+		a [10]float32
+		_ bool
+	}
+	type T struct {
+		x int
+		a [10]float32
+		_ bool
+	}
+	var ss S
+	var tt T
+	_ = s == ss
+	_ = ss /* ERROR mismatched types */ == tt
+
+	var u struct {
+		x int
+		a [10]map[string]int
+	}
+	_ = u /* ERROR cannot compare */ == u
+}
+
+func pointers() {
+	// nil
+	_ = nil /* ERROR == not defined */ == nil
+	_ = nil /* ERROR != not defined */ != nil
+	_ = nil /* ERROR < not defined */ < nil
+	_ = nil /* ERROR <= not defined */ <= nil
+	_ = nil /* ERROR > not defined */ > nil
+	_ = nil /* ERROR >= not defined */ >= nil
+
+	// basics
+	var p, q *int
+	_ = p == q
+	_ = p != q
+
+	_ = p == nil
+	_ = p != nil
+	_ = nil == q
+	_ = nil != q
+
+	_ = p /* ERROR < not defined */ < q
+	_ = p /* ERROR <= not defined */ <= q
+	_ = p /* ERROR > not defined */ > q
+	_ = p /* ERROR >= not defined */ >= q
+
+	// various element types
+	type (
+		S1 struct{}
+		S2 struct{}
+		P1 *S1
+		P2 *S2
+	)
+	var (
+		ps1 *S1
+		ps2 *S2
+		p1 P1
+		p2 P2
+	)
+	_ = ps1 == ps1
+	_ = ps1 /* ERROR mismatched types */ == ps2
+	_ = ps2 /* ERROR mismatched types */ == ps1
+
+	_ = p1 == p1
+	_ = p1 /* ERROR mismatched types */ == p2
+
+	_ = p1 == ps1
+}
+
+func channels() {
+	// basics
+	var c, d chan int
+	_ = c == d
+	_ = c != d
+	_ = c == nil
+	_ = c /* ERROR < not defined */ < d
+
+	// various element types (named types)
+	type (
+		C1 chan int
+		C1r <-chan int
+		C1s chan<- int
+		C2 chan float32
+	)
+	var (
+		c1 C1
+		c1r C1r
+		c1s C1s
+		c1a chan int
+		c2 C2
+	)
+	_ = c1 == c1
+	_ = c1 /* ERROR mismatched types */ == c1r
+	_ = c1 /* ERROR mismatched types */ == c1s
+	_ = c1r /* ERROR mismatched types */ == c1s
+	_ = c1 == c1a
+	_ = c1a == c1
+	_ = c1 /* ERROR mismatched types */ == c2
+	_ = c1a /* ERROR mismatched types */ == c2
+
+	// various element types (unnamed types)
+	var (
+		d1 chan int
+		d1r <-chan int
+		d1s chan<- int
+		d1a chan<- int
+		d2 chan float32
+	)
+	_ = d1 == d1
+	_ = d1 == d1r
+	_ = d1 == d1s
+	_ = d1r /* ERROR mismatched types */ == d1s
+	_ = d1 == d1a
+	_ = d1a == d1
+	_ = d1 /* ERROR mismatched types */ == d2
+	_ = d1a /* ERROR mismatched types */ == d2
+}
+
+// for interfaces test
+type S1 struct{}
+type S11 struct{}
+type S2 struct{}
+func (*S1) m() int
+func (*S11) m() int
+func (*S11) n()
+func (*S2) m() float32
+
+func interfaces() {
+	// basics
+	var i, j interface{ m() int }
+	_ = i == j
+	_ = i != j
+	_ = i == nil
+	_ = i /* ERROR < not defined */ < j
+
+	// various interfaces
+	var ii interface { m() int; n() }
+	var k interface { m() float32 }
+	_ = i == ii
+	_ = i /* ERROR mismatched types */ == k
+
+	// interfaces vs values
+	var s1 S1
+	var s11 S11
+	var s2 S2
+
+	_ = i == 0 /* ERROR cannot convert */
+	_ = i /* ERROR mismatched types */ == s1
+	_ = i == &s1
+	_ = i == &s11
+
+	_ = i /* ERROR mismatched types */ == s2
+	_ = i /* ERROR mismatched types */ == &s2
+}
+
+func slices() {
+	// basics
+	var s []int
+	_ = s == nil
+	_ = s != nil
+	_ = s /* ERROR < not defined */ < nil
+
+	// slices are not otherwise comparable
+	_ = s /* ERROR == not defined */ == s
+	_ = s /* ERROR < not defined */ < s
+}
+
+func maps() {
+	// basics
+	var m map[string]int
+	_ = m == nil
+	_ = m != nil
+	_ = m /* ERROR < not defined */ < nil
+
+	// maps are not otherwise comparable
+	_ = m /* ERROR == not defined */ == m
+	_ = m /* ERROR < not defined */ < m
+}
+
+func funcs() {
+	// basics
+	var f func(int) float32
+	_ = f == nil
+	_ = f != nil
+	_ = f /* ERROR < not defined */ < nil
+
+	// funcs are not otherwise comparable
+	_ = f /* ERROR == not defined */ == f
+	_ = f /* ERROR < not defined */ < f
+}
diff --git a/go/types/testdata/expr3.src b/go/types/testdata/expr3.src
new file mode 100644
index 0000000..5772095
--- /dev/null
+++ b/go/types/testdata/expr3.src
@@ -0,0 +1,534 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package expr3
+
+import "time"
+
+func indexes() {
+	_ = 1 /* ERROR "cannot index" */ [0]
+	_ = indexes /* ERROR "cannot index" */ [0]
+	_ = ( /* ERROR "cannot slice" */ 12 + 3)[1:2]
+
+	var a [10]int
+	_ = a[true /* ERROR "cannot convert" */ ]
+	_ = a["foo" /* ERROR "cannot convert" */ ]
+	_ = a[1.1 /* ERROR "truncated" */ ]
+	_ = a[1.0]
+	_ = a[- /* ERROR "negative" */ 1]
+	_ = a[- /* ERROR "negative" */ 1 :]
+	_ = a[: - /* ERROR "negative" */ 1]
+	_ = a[: /* ERROR "2nd index required" */ : /* ERROR "3rd index required" */ ]
+	_ = a[0: /* ERROR "2nd index required" */ : /* ERROR "3rd index required" */ ]
+	_ = a[0: /* ERROR "2nd index required" */ :10]
+	_ = a[:10:10]
+
+	var a0 int
+	a0 = a[0]
+	_ = a0
+	var a1 int32
+	a1 = a /* ERROR "cannot assign" */ [1]
+	_ = a1
+
+	_ = a[9]
+	_ = a[10 /* ERROR "index .* out of bounds" */ ]
+	_ = a[1 /* ERROR "overflows" */ <<100]
+	_ = a[10:]
+	_ = a[:10]
+	_ = a[10:10]
+	_ = a[11 /* ERROR "index .* out of bounds" */ :]
+	_ = a[: 11 /* ERROR "index .* out of bounds" */ ]
+	_ = a[: 1 /* ERROR "overflows" */ <<100]
+	_ = a[:10:10]
+	_ = a[:11 /* ERROR "index .* out of bounds" */ :10]
+	_ = a[:10:11 /* ERROR "index .* out of bounds" */ ]
+	_ = a[10:0:10] /* ERROR "invalid slice indices" */
+	_ = a[0:10:0] /* ERROR "invalid slice indices" */
+	_ = a[10:0:0] /* ERROR "invalid slice indices" */
+	_ = &a /* ERROR "cannot take address" */ [:10]
+
+	pa := &a
+	_ = pa[9]
+	_ = pa[10 /* ERROR "index .* out of bounds" */ ]
+	_ = pa[1 /* ERROR "overflows" */ <<100]
+	_ = pa[10:]
+	_ = pa[:10]
+	_ = pa[10:10]
+	_ = pa[11 /* ERROR "index .* out of bounds" */ :]
+	_ = pa[: 11 /* ERROR "index .* out of bounds" */ ]
+	_ = pa[: 1 /* ERROR "overflows" */ <<100]
+	_ = pa[:10:10]
+	_ = pa[:11 /* ERROR "index .* out of bounds" */ :10]
+	_ = pa[:10:11 /* ERROR "index .* out of bounds" */ ]
+	_ = pa[10:0:10] /* ERROR "invalid slice indices" */
+	_ = pa[0:10:0] /* ERROR "invalid slice indices" */
+	_ = pa[10:0:0] /* ERROR "invalid slice indices" */
+	_ = &pa /* ERROR "cannot take address" */ [:10]
+
+	var b [0]int
+	_ = b[0 /* ERROR "index .* out of bounds" */ ]
+	_ = b[:]
+	_ = b[0:]
+	_ = b[:0]
+	_ = b[0:0]
+	_ = b[0:0:0]
+	_ = b[1 /* ERROR "index .* out of bounds" */ :0:0]
+
+	var s []int
+	_ = s[- /* ERROR "negative" */ 1]
+	_ = s[- /* ERROR "negative" */ 1 :]
+	_ = s[: - /* ERROR "negative" */ 1]
+	_ = s[0]
+	_ = s[1:2]
+	_ = s[2:1] /* ERROR "invalid slice indices" */
+	_ = s[2:]
+	_ = s[: 1 /* ERROR "overflows" */ <<100]
+	_ = s[1 /* ERROR "overflows" */ <<100 :]
+	_ = s[1 /* ERROR "overflows" */ <<100 : 1 /* ERROR "overflows" */ <<100]
+	_ = s[: /* ERROR "2nd index required" */ :  /* ERROR "3rd index required" */ ]
+	_ = s[:10:10]
+	_ = s[10:0:10] /* ERROR "invalid slice indices" */
+	_ = s[0:10:0] /* ERROR "invalid slice indices" */
+	_ = s[10:0:0] /* ERROR "invalid slice indices" */
+	_ = &s /* ERROR "cannot take address" */ [:10]
+
+	var m map[string]int
+	_ = m[0 /* ERROR "cannot convert" */ ]
+	_ = m /* ERROR "cannot slice" */ ["foo" : "bar"]
+	_ = m["foo"]
+	// ok is of type bool
+	type mybool bool
+	var ok mybool
+	_, ok = m["bar"]
+	_ = ok
+
+	var t string
+	_ = t[- /* ERROR "negative" */ 1]
+	_ = t[- /* ERROR "negative" */ 1 :]
+	_ = t[: - /* ERROR "negative" */ 1]
+	_ = t /* ERROR "3-index slice of string" */ [1:2:3]
+	_ = "foo" /* ERROR "3-index slice of string" */ [1:2:3]
+	var t0 byte
+	t0 = t[0]
+	_ = t0
+	var t1 rune
+	t1 = t /* ERROR "cannot assign" */ [2]
+	_ = t1
+	_ = ("foo" + "bar")[5]
+	_ = ("foo" + "bar")[6 /* ERROR "index .* out of bounds" */ ]
+
+	const c = "foo"
+	_ = c[- /* ERROR "negative" */ 1]
+	_ = c[- /* ERROR "negative" */ 1 :]
+	_ = c[: - /* ERROR "negative" */ 1]
+	var c0 byte
+	c0 = c[0]
+	_ = c0
+	var c2 float32
+	c2 = c /* ERROR "cannot assign" */ [2]
+	_ = c[3 /* ERROR "index .* out of bounds" */ ]
+	_ = ""[0 /* ERROR "index .* out of bounds" */ ]
+	_ = c2
+
+	_ = s[1<<30] // no compile-time error here
+
+	// issue 4913
+	type mystring string
+	var ss string
+	var ms mystring
+	var i, j int
+	ss = "foo"[1:2]
+	ss = "foo"[i:j]
+	ms = "foo" /* ERROR "cannot assign" */ [1:2]
+	ms = "foo" /* ERROR "cannot assign" */ [i:j]
+	_, _ = ss, ms
+}
+
+type T struct {
+	x int
+	y func()
+}
+
+func (*T) m() {}
+
+func method_expressions() {
+	_ = T /* ERROR "no field or method" */ .a
+	_ = T /* ERROR "has no method" */ .x
+	_ = T /* ERROR "not in method set" */ .m
+	_ = (*T).m
+
+	var f func(*T) = T /* ERROR "not in method set" */ .m
+	var g func(*T) = (*T).m
+	_, _ = f, g
+
+	_ = T /* ERROR "has no method" */ .y
+	_ = ( /* ERROR "has no method" */ *T).y
+}
+
+func struct_literals() {
+	type T0 struct {
+		a, b, c int
+	}
+
+	type T1 struct {
+		T0
+		a, b int
+		u float64
+		s string
+	}
+
+	// keyed elements
+	_ = T1{}
+	_ = T1{a: 0, 1 /* ERROR "mixture of .* elements" */ }
+	_ = T1{aa /* ERROR "unknown field" */ : 0}
+	_ = T1{1 /* ERROR "invalid field name" */ : 0}
+	_ = T1{a: 0, s: "foo", u: 0, a /* ERROR "duplicate field" */: 10}
+	_ = T1{a: "foo" /* ERROR "cannot convert" */ }
+	_ = T1{c /* ERROR "unknown field" */ : 0}
+	_ = T1{T0: { /* ERROR "missing type" */ }} // struct literal element type may not be elided
+	_ = T1{T0: T0{}}
+	_ = T1{T0 /* ERROR "invalid field name" */ .a: 0}
+
+	// unkeyed elements
+	_ = T0{1, 2, 3}
+	_ = T0{1, b /* ERROR "mixture" */ : 2, 3}
+	_ = T0{1, 2} /* ERROR "too few values" */
+	_ = T0{1, 2, 3, 4  /* ERROR "too many values" */ }
+	_ = T0{1, "foo" /* ERROR "cannot convert" */, 3.4  /* ERROR "truncated" */}
+
+	// invalid type
+	type P *struct{
+		x int
+	}
+	_ = P /* ERROR "invalid composite literal type" */ {}
+
+	// unexported fields
+	_ = time.Time{}
+	_ = time.Time{sec /* ERROR "unknown field" */ : 0}
+	_ = time.Time{
+		0 /* ERROR implicit assignment to unexported field sec in time.Time literal */,
+		0 /* ERROR implicit assignment */ ,
+		nil /* ERROR implicit assignment */ ,
+	}
+}
+
+func array_literals() {
+	type A0 [0]int
+	_ = A0{}
+	_ = A0{0 /* ERROR "index .* out of bounds" */}
+	_ = A0{0 /* ERROR "index .* out of bounds" */ : 0}
+
+	type A1 [10]int
+	_ = A1{}
+	_ = A1{0, 1, 2}
+	_ = A1{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
+	_ = A1{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 /* ERROR "index .* out of bounds" */ }
+	_ = A1{- /* ERROR "negative" */ 1: 0}
+	_ = A1{8: 8, 9}
+	_ = A1{8: 8, 9, 10 /* ERROR "index .* out of bounds" */ }
+	_ = A1{0, 1, 2, 0 /* ERROR "duplicate index" */ : 0, 3: 3, 4}
+	_ = A1{5: 5, 6, 7, 3: 3, 4}
+	_ = A1{5: 5, 6, 7, 3: 3, 4, 5 /* ERROR "duplicate index" */ }
+	_ = A1{10 /* ERROR "index .* out of bounds" */ : 10, 10 /* ERROR "index .* out of bounds" */ : 10}
+	_ = A1{5: 5, 6, 7, 3: 3, 1 /* ERROR "overflows" */ <<100: 4, 5 /* ERROR "duplicate index" */ }
+	_ = A1{5: 5, 6, 7, 4: 4, 1 /* ERROR "overflows" */ <<100: 4}
+	_ = A1{2.0}
+	_ = A1{2.1 /* ERROR "truncated" */ }
+	_ = A1{"foo" /* ERROR "cannot convert" */ }
+
+	// indices must be integer constants
+	i := 1
+	const f = 2.1
+	const s = "foo"
+	_ = A1{i /* ERROR "index i must be integer constant" */ : 0}
+	_ = A1{f /* ERROR "truncated" */ : 0}
+	_ = A1{s /* ERROR "cannot convert" */ : 0}
+
+	a0 := [...]int{}
+	assert(len(a0) == 0)
+
+	a1 := [...]int{0, 1, 2}
+	assert(len(a1) == 3)
+	var a13 [3]int
+	var a14 [4]int
+	a13 = a1
+	a14 = a1 /* ERROR "cannot assign" */
+	_, _ = a13, a14
+
+	a2 := [...]int{- /* ERROR "negative" */ 1: 0}
+	_ = a2
+
+	a3 := [...]int{0, 1, 2, 0 /* ERROR "duplicate index" */ : 0, 3: 3, 4}
+	assert(len(a3) == 5) // somewhat arbitrary
+
+	a4 := [...]complex128{0, 1, 2, 1<<10-2: -1i, 1i, 400: 10, 12, 14}
+	assert(len(a4) == 1024)
+
+	// composite literal element types may be elided
+	type T []int
+	_ = [10]T{T{}, {}, 5: T{1, 2, 3}, 7: {1, 2, 3}}
+	a6 := [...]T{T{}, {}, 5: T{1, 2, 3}, 7: {1, 2, 3}}
+	assert(len(a6) == 8)
+
+	// recursively so
+	_ = [10][10]T{{}, [10]T{{}}, {{1, 2, 3}}}
+
+	// from the spec
+	type Point struct { x, y float32 }
+	_ = [...]Point{Point{1.5, -3.5}, Point{0, 0}}
+	_ = [...]Point{{1.5, -3.5}, {0, 0}}
+	_ = [][]int{[]int{1, 2, 3}, []int{4, 5}}
+	_ = [][]int{{1, 2, 3}, {4, 5}}
+	_ = [...]*Point{&Point{1.5, -3.5}, &Point{0, 0}}
+	_ = [...]*Point{{1.5, -3.5}, {0, 0}}
+}
+
+func slice_literals() {
+	type S0 []int
+	_ = S0{}
+	_ = S0{0, 1, 2}
+	_ = S0{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
+	_ = S0{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
+	_ = S0{- /* ERROR "negative" */ 1: 0}
+	_ = S0{8: 8, 9}
+	_ = S0{8: 8, 9, 10}
+	_ = S0{0, 1, 2, 0 /* ERROR "duplicate index" */ : 0, 3: 3, 4}
+	_ = S0{5: 5, 6, 7, 3: 3, 4}
+	_ = S0{5: 5, 6, 7, 3: 3, 4, 5 /* ERROR "duplicate index" */ }
+	_ = S0{10: 10, 10 /* ERROR "duplicate index" */ : 10}
+	_ = S0{5: 5, 6, 7, 3: 3, 1 /* ERROR "overflows" */ <<100: 4, 5 /* ERROR "duplicate index" */ }
+	_ = S0{5: 5, 6, 7, 4: 4, 1 /* ERROR "overflows" */ <<100: 4}
+	_ = S0{2.0}
+	_ = S0{2.1 /* ERROR "truncated" */ }
+	_ = S0{"foo" /* ERROR "cannot convert" */ }
+
+	// indices must be resolved correctly
+	const index1 = 1
+	_ = S0{index1: 1}
+	_ = S0{index2: 2}
+	_ = S0{index3 /* ERROR "undeclared name" */ : 3}
+
+	// indices must be integer constants
+	i := 1
+	const f = 2.1
+	const s = "foo"
+	_ = S0{i /* ERROR "index i must be integer constant" */ : 0}
+	_ = S0{f /* ERROR "truncated" */ : 0}
+	_ = S0{s /* ERROR "cannot convert" */ : 0}
+
+	// composite literal element types may be elided
+	type T []int
+	_ = []T{T{}, {}, 5: T{1, 2, 3}, 7: {1, 2, 3}}
+	_ = [][]int{{1, 2, 3}, {4, 5}}
+
+	// recursively so
+	_ = [][]T{{}, []T{{}}, {{1, 2, 3}}}
+}
+
+const index2 int = 2
+
+type N int
+func (N) f() {}
+
+func map_literals() {
+	type M0 map[string]int
+	type M1 map[bool]int
+	type M2 map[*int]int
+
+	_ = M0{}
+	_ = M0{1 /* ERROR "missing key" */ }
+	_ = M0{1 /* ERROR "cannot convert" */ : 2}
+	_ = M0{"foo": "bar" /* ERROR "cannot convert" */ }
+	_ = M0{"foo": 1, "bar": 2, "foo" /* ERROR "duplicate key" */ : 3 }
+
+	_ = map[interface{}]int{2: 1, 2 /* ERROR "duplicate key" */ : 1}
+	_ = map[interface{}]int{int(2): 1, int16(2): 1}
+	_ = map[interface{}]int{int16(2): 1, int16 /* ERROR "duplicate key" */ (2): 1}
+
+	type S string
+
+	_ = map[interface{}]int{"a": 1, "a" /* ERROR "duplicate key" */ : 1}
+	_ = map[interface{}]int{"a": 1, S("a"): 1}
+	_ = map[interface{}]int{S("a"): 1, S /* ERROR "duplicate key" */ ("a"): 1}
+
+	type I interface {
+		f()
+	}
+
+	_ = map[I]int{N(0): 1, N(2): 1}
+	_ = map[I]int{N(2): 1, N /* ERROR "duplicate key" */ (2): 1}
+
+	// map keys must be resolved correctly
+	key1 := "foo"
+	_ = M0{key1: 1}
+	_ = M0{key2: 2}
+	_ = M0{key3 /* ERROR "undeclared name" */ : 2}
+
+	var value int
+	_ = M1{true: 1, false: 0}
+	_ = M2{nil: 0, &value: 1}
+
+	// composite literal element types may be elided
+	type T [2]int
+	_ = map[int]T{0: T{3, 4}, 1: {5, 6}}
+
+	// recursively so
+	_ = map[int][]T{0: {}, 1: {{}, T{1, 2}}}
+
+	// composite literal key types may be elided
+	_ = map[T]int{T{3, 4}: 0, {5, 6}: 1}
+
+	// recursively so
+	_ = map[[2]T]int{{}: 0, {{}}: 1, [2]T{{}}: 2, {T{1, 2}}: 3}
+
+	// composite literal element and key types may be elided
+	_ = map[T]T{{}: {}, {1, 2}: T{3, 4}, T{4, 5}: {}}
+	_ = map[T]M0{{} : {}, T{1, 2}: M0{"foo": 0}, {1, 3}: {"foo": 1}}
+
+	// recursively so
+	_ = map[[2]T][]T{{}: {}, {{}}: {{}, T{1, 2}}, [2]T{{}}: nil, {T{1, 2}}: {{}, {}}}
+
+	// from the spec
+	type Point struct { x, y float32 }
+	_ = map[string]Point{"orig": {0, 0}}
+	_ = map[*Point]string{{0, 0}: "orig"}
+}
+
+var key2 string = "bar"
+
+type I interface {
+	m()
+}
+
+type I2 interface {
+	m(int)
+}
+
+type T1 struct{}
+type T2 struct{}
+
+func (T2) m(int) {}
+
+type mybool bool
+
+func type_asserts() {
+	var x int
+	_ = x /* ERROR "not an interface" */ .(int)
+
+	var e interface{}
+	var ok bool
+	x, ok = e.(int)
+	_ = ok
+
+	// ok value is of type bool
+	var myok mybool
+	_, myok = e.(int)
+	_ = myok
+
+	var t I
+	_ = t /* ERROR "use of .* outside type switch" */ .(type)
+	_ = t /* ERROR "missing method m" */ .(T)
+	_ = t.(*T)
+	_ = t /* ERROR "missing method m" */ .(T1)
+	_ = t /* ERROR "wrong type for method m" */ .(T2)
+	_ = t /* STRICT "wrong type for method m" */ .(I2) // only an error in strict mode (issue 8561)
+
+	// e doesn't statically have an m, but may have one dynamically.
+	_ = e.(I2)
+}
+
+func f0() {}
+func f1(x int) {}
+func f2(u float32, s string) {}
+func fs(s []byte) {}
+func fv(x ...int) {}
+func fi(x ... interface{}) {}
+func (T) fm(x ...int)
+
+func g0() {}
+func g1() int { return 0}
+func g2() (u float32, s string) { return }
+func gs() []byte { return nil }
+
+func _calls() {
+	var x int
+	var y float32
+	var s []int
+
+	f0()
+	_ = f0 /* ERROR "used as value" */ ()
+	f0(g0 /* ERROR "too many arguments" */ )
+
+	f1(0)
+	f1(x)
+	f1(10.0)
+	f1() /* ERROR "too few arguments" */
+	f1(x, y /* ERROR "too many arguments" */ )
+	f1(s /* ERROR "cannot pass" */ )
+	f1(x ... /* ERROR "cannot use ..." */ )
+	f1(g0 /* ERROR "used as value" */ ())
+	f1(g1())
+	// f1(g2()) // TODO(gri) missing position in error message
+
+	f2() /* ERROR "too few arguments" */
+	f2(3.14) /* ERROR "too few arguments" */
+	f2(3.14, "foo")
+	f2(x /* ERROR "cannot pass" */ , "foo")
+	f2(g0 /* ERROR "used as value" */ ())
+	f2(g1 /* ERROR "cannot pass" */ ()) /* ERROR "too few arguments" */
+	f2(g2())
+
+	fs() /* ERROR "too few arguments" */
+	fs(g0 /* ERROR "used as value" */ ())
+	fs(g1 /* ERROR "cannot pass" */ ())
+	fs(g2 /* ERROR "cannot pass" */ /* ERROR "too many arguments" */ ())
+	fs(gs())
+
+	fv()
+	fv(1, 2.0, x)
+	fv(s /* ERROR "cannot pass" */ )
+	fv(s...)
+	fv(x /* ERROR "cannot use" */ ...)
+	fv(1, s... /* ERROR "can only use ... with matching parameter" */ )
+	fv(gs /* ERROR "cannot pass" */ ())
+	fv(gs /* ERROR "cannot pass" */ ()...)
+
+	var t T
+	t.fm()
+	t.fm(1, 2.0, x)
+	t.fm(s /* ERROR "cannot pass" */ )
+	t.fm(g1())
+	t.fm(1, s... /* ERROR "can only use ... with matching parameter" */ )
+	t.fm(gs /* ERROR "cannot pass" */ ())
+	t.fm(gs /* ERROR "cannot pass" */ ()...)
+
+	T.fm(t, )
+	T.fm(t, 1, 2.0, x)
+	T.fm(t, s /* ERROR "cannot pass" */ )
+	T.fm(t, g1())
+	T.fm(t, 1, s... /* ERROR "can only use ... with matching parameter" */ )
+	T.fm(t, gs /* ERROR "cannot pass" */ ())
+	T.fm(t, gs /* ERROR "cannot pass" */ ()...)
+
+	var i interface{ fm(x ...int) } = t
+	i.fm()
+	i.fm(1, 2.0, x)
+	i.fm(s /* ERROR "cannot pass" */ )
+	i.fm(g1())
+	i.fm(1, s... /* ERROR "can only use ... with matching parameter" */ )
+	i.fm(gs /* ERROR "cannot pass" */ ())
+	i.fm(gs /* ERROR "cannot pass" */ ()...)
+
+	fi()
+	fi(1, 2.0, x, 3.14, "foo")
+	fi(g2())
+	fi(0, g2)
+	fi(0, g2 /* ERROR "2-valued expression" */ ())
+}
+
+func issue6344() {
+	type T []interface{}
+	var x T
+	fi(x...) // ... applies also to named slices
+}
diff --git a/go/types/testdata/gotos.src b/go/types/testdata/gotos.src
new file mode 100644
index 0000000..0c7ee44
--- /dev/null
+++ b/go/types/testdata/gotos.src
@@ -0,0 +1,560 @@
+// Copyright 2011 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file is a modified copy of $GOROOT/test/goto.go.
+
+package gotos
+
+var (
+	i, n int
+	x    []int
+	c    chan int
+	m    map[int]int
+	s    string
+)
+
+// goto after declaration okay
+func _() {
+	x := 1
+	goto L
+L:
+	_ = x
+}
+
+// goto before declaration okay
+func _() {
+	goto L
+L:
+	x := 1
+	_ = x
+}
+
+// goto across declaration not okay
+func _() {
+	goto L /* ERROR "goto L jumps over variable declaration at line 36" */
+	x := 1
+	_ = x
+L:
+}
+
+// goto across declaration in inner scope okay
+func _() {
+	goto L
+	{
+		x := 1
+		_ = x
+	}
+L:
+}
+
+// goto across declaration after inner scope not okay
+func _() {
+	goto L /* ERROR "goto L jumps over variable declaration at line 58" */
+	{
+		x := 1
+		_ = x
+	}
+	x := 1
+	_ = x
+L:
+}
+
+// goto across declaration in reverse okay
+func _() {
+L:
+	x := 1
+	_ = x
+	goto L
+}
+
+func _() {
+L: L1:
+	x := 1
+	_ = x
+	goto L
+	goto L1
+}
+
+// error shows first offending variable
+func _() {
+	goto L /* ERROR "goto L jumps over variable declaration at line 84" */
+	x := 1
+	_ = x
+	y := 1
+	_ = y
+L:
+}
+
+// goto not okay even if code path is dead
+func _() {
+	goto L /* ERROR "goto L jumps over variable declaration" */
+	x := 1
+	_ = x
+	y := 1
+	_ = y
+	return
+L:
+}
+
+// goto into outer block okay
+func _() {
+	{
+		goto L
+	}
+L:
+}
+
+func _() {
+	{
+		goto L
+		goto L1
+	}
+L: L1:
+}
+
+// goto backward into outer block okay
+func _() {
+L:
+	{
+		goto L
+	}
+}
+
+func _() {
+L: L1:
+	{
+		goto L
+		goto L1
+	}
+}
+
+// goto into inner block not okay
+func _() {
+	goto L /* ERROR "goto L jumps into block" */
+	{
+	L:
+	}
+}
+
+func _() {
+	goto L /* ERROR "goto L jumps into block" */
+	goto L1 /* ERROR "goto L1 jumps into block" */
+	{
+	L: L1:
+	}
+}
+
+// goto backward into inner block still not okay
+func _() {
+	{
+	L:
+	}
+	goto L /* ERROR "goto L jumps into block" */
+}
+
+func _() {
+	{
+	L: L1:
+	}
+	goto L /* ERROR "goto L jumps into block" */
+	goto L1 /* ERROR "goto L1 jumps into block" */
+}
+
+// error shows first (outermost) offending block
+func _() {
+	goto L /* ERROR "goto L jumps into block" */
+	{
+		{
+			{
+			L:
+			}
+		}
+	}
+}
+
+// error prefers block diagnostic over declaration diagnostic
+func _() {
+	goto L /* ERROR "goto L jumps into block" */
+	x := 1
+	_ = x
+	{
+	L:
+	}
+}
+
+// many kinds of blocks, all invalid to jump into or among,
+// but valid to jump out of
+
+// if
+
+func _() {
+L:
+	if true {
+		goto L
+	}
+}
+
+func _() {
+L:
+	if true {
+		goto L
+	} else {
+	}
+}
+
+func _() {
+L:
+	if false {
+	} else {
+		goto L
+	}
+}
+
+func _() {
+	goto L /* ERROR "goto L jumps into block" */
+	if true {
+	L:
+	}
+}
+
+func _() {
+	goto L /* ERROR "goto L jumps into block" */
+	if true {
+	L:
+	} else {
+	}
+}
+
+func _() {
+	goto L /* ERROR "goto L jumps into block" */
+	if true {
+	} else {
+	L:
+	}
+}
+
+func _() {
+	if false {
+	L:
+	} else {
+		goto L /* ERROR "goto L jumps into block" */
+	}
+}
+
+func _() {
+	if true {
+		goto L /* ERROR "goto L jumps into block" */
+	} else {
+	L:
+	}
+}
+
+func _() {
+	if true {
+		goto L /* ERROR "goto L jumps into block" */
+	} else if false {
+	L:
+	}
+}
+
+func _() {
+	if true {
+		goto L /* ERROR "goto L jumps into block" */
+	} else if false {
+	L:
+	} else {
+	}
+}
+
+func _() {
+	if true {
+		goto L /* ERROR "goto L jumps into block" */
+	} else if false {
+	} else {
+	L:
+	}
+}
+
+func _() {
+	if true {
+		goto L /* ERROR "goto L jumps into block" */
+	} else {
+		L:
+	}
+}
+
+func _() {
+	if true {
+		L:
+	} else {
+		goto L /* ERROR "goto L jumps into block" */
+	}
+}
+
+// for
+
+func _() {
+	for {
+		goto L
+	}
+L:
+}
+
+func _() {
+	for {
+		goto L
+	L:
+	}
+}
+
+func _() {
+	for {
+	L:
+	}
+	goto L /* ERROR "goto L jumps into block" */
+}
+
+func _() {
+	for {
+		goto L
+	L1:
+	}
+L:
+	goto L1 /* ERROR "goto L1 jumps into block" */
+}
+
+func _() {
+	for i < n {
+	L:
+	}
+	goto L /* ERROR "goto L jumps into block" */
+}
+
+func _() {
+	for i = 0; i < n; i++ {
+	L:
+	}
+	goto L /* ERROR "goto L jumps into block" */
+}
+
+func _() {
+	for i = range x {
+	L:
+	}
+	goto L /* ERROR "goto L jumps into block" */
+}
+
+func _() {
+	for i = range c {
+	L:
+	}
+	goto L /* ERROR "goto L jumps into block" */
+}
+
+func _() {
+	for i = range m {
+	L:
+	}
+	goto L /* ERROR "goto L jumps into block" */
+}
+
+func _() {
+	for i = range s {
+	L:
+	}
+	goto L /* ERROR "goto L jumps into block" */
+}
+
+// switch
+
+func _() {
+L:
+	switch i {
+	case 0:
+		goto L
+	}
+}
+
+func _() {
+L:
+	switch i {
+	case 0:
+
+	default:
+		goto L
+	}
+}
+
+func _() {
+	switch i {
+	case 0:
+
+	default:
+	L:
+		goto L
+	}
+}
+
+func _() {
+	switch i {
+	case 0:
+
+	default:
+		goto L
+	L:
+	}
+}
+
+func _() {
+	switch i {
+	case 0:
+		goto L
+	L:
+		;
+	default:
+	}
+}
+
+func _() {
+	goto L /* ERROR "goto L jumps into block" */
+	switch i {
+	case 0:
+	L:
+	}
+}
+
+func _() {
+	goto L /* ERROR "goto L jumps into block" */
+	switch i {
+	case 0:
+	L:
+		;
+	default:
+	}
+}
+
+func _() {
+	goto L /* ERROR "goto L jumps into block" */
+	switch i {
+	case 0:
+	default:
+	L:
+	}
+}
+
+func _() {
+	switch i {
+	default:
+		goto L /* ERROR "goto L jumps into block" */
+	case 0:
+	L:
+	}
+}
+
+func _() {
+	switch i {
+	case 0:
+	L:
+		;
+	default:
+		goto L /* ERROR "goto L jumps into block" */
+	}
+}
+
+// select
+// different from switch.  the statement has no implicit block around it.
+
+func _() {
+L:
+	select {
+	case <-c:
+		goto L
+	}
+}
+
+func _() {
+L:
+	select {
+	case c <- 1:
+
+	default:
+		goto L
+	}
+}
+
+func _() {
+	select {
+	case <-c:
+
+	default:
+	L:
+		goto L
+	}
+}
+
+func _() {
+	select {
+	case c <- 1:
+
+	default:
+		goto L
+	L:
+	}
+}
+
+func _() {
+	select {
+	case <-c:
+		goto L
+	L:
+		;
+	default:
+	}
+}
+
+func _() {
+	goto L /* ERROR "goto L jumps into block" */
+	select {
+	case c <- 1:
+	L:
+	}
+}
+
+func _() {
+	goto L /* ERROR "goto L jumps into block" */
+	select {
+	case c <- 1:
+	L:
+		;
+	default:
+	}
+}
+
+func _() {
+	goto L /* ERROR "goto L jumps into block" */
+	select {
+	case <-c:
+	default:
+	L:
+	}
+}
+
+func _() {
+	select {
+	default:
+		goto L /* ERROR "goto L jumps into block" */
+	case <-c:
+	L:
+	}
+}
+
+func _() {
+	select {
+	case <-c:
+	L:
+		;
+	default:
+		goto L /* ERROR "goto L jumps into block" */
+	}
+}
diff --git a/go/types/testdata/importdecl0a.src b/go/types/testdata/importdecl0a.src
new file mode 100644
index 0000000..463dcd0
--- /dev/null
+++ b/go/types/testdata/importdecl0a.src
@@ -0,0 +1,53 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package importdecl0
+
+import ()
+
+import (
+	// we can have multiple blank imports (was bug)
+	_ "math"
+	_ "net/rpc"
+	init /* ERROR "cannot declare init" */ "fmt"
+	// reflect defines a type "flag" which shows up in the gc export data
+	"reflect"
+	. /* ERROR "imported but not used" */ "reflect"
+)
+
+import "math" /* ERROR "imported but not used" */
+import m /* ERROR "imported but not used as m" */ "math"
+import _ "math"
+
+import (
+	"math/big" /* ERROR "imported but not used" */
+	b /* ERROR "imported but not used" */ "math/big"
+	_ "math/big"
+)
+
+import "fmt"
+import f1 "fmt"
+import f2 "fmt"
+
+// reflect.flag must not be visible in this package
+type flag int
+type _ reflect /* ERROR "not exported" */ .flag
+
+// imported package name may conflict with local objects
+type reflect /* ERROR "reflect already declared" */ int
+
+// dot-imported exported objects may conflict with local objects
+type Value /* ERROR "Value already declared through dot-import of package reflect" */ struct{}
+
+var _ = fmt.Println // use "fmt"
+
+func _() {
+	f1.Println() // use "fmt"
+}
+
+func _() {
+	_ = func() {
+		f2.Println() // use "fmt"
+	}
+}
diff --git a/go/types/testdata/importdecl0b.src b/go/types/testdata/importdecl0b.src
new file mode 100644
index 0000000..6844e70
--- /dev/null
+++ b/go/types/testdata/importdecl0b.src
@@ -0,0 +1,33 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package importdecl0
+
+import "math"
+import m "math"
+
+import . "testing" // declares T in file scope
+import . /* ERROR "imported but not used" */ "unsafe"
+import . "fmt"     // declares Println in file scope
+
+import (
+	// TODO(gri) At the moment, 2 errors are reported because both go/parser
+	// and the type checker report it. Eventually, this test should not be
+	// done by the parser anymore.
+	"" /* ERROR invalid import path */ /* ERROR invalid import path */
+	"a!b" /* ERROR invalid import path */ /* ERROR invalid import path */
+	"abc\xffdef" /* ERROR invalid import path */ /* ERROR invalid import path */
+)
+
+// using "math" in this file doesn't affect its use in other files
+const Pi0 = math.Pi
+const Pi1 = m.Pi
+
+type _ T // use "testing"
+
+func _() func() interface{} {
+	return func() interface{} {
+		return Println // use "fmt"
+	}
+}
diff --git a/go/types/testdata/importdecl1a.src b/go/types/testdata/importdecl1a.src
new file mode 100644
index 0000000..8301820
--- /dev/null
+++ b/go/types/testdata/importdecl1a.src
@@ -0,0 +1,11 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Test case for issue 8969.
+
+package importdecl1
+
+import . "unsafe"
+
+var _ Pointer // use dot-imported package unsafe
diff --git a/go/types/testdata/importdecl1b.src b/go/types/testdata/importdecl1b.src
new file mode 100644
index 0000000..f24bb9a
--- /dev/null
+++ b/go/types/testdata/importdecl1b.src
@@ -0,0 +1,7 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package importdecl1
+
+import . /* ERROR "imported but not used" */ "unsafe"
diff --git a/go/types/testdata/init0.src b/go/types/testdata/init0.src
new file mode 100644
index 0000000..ef0349c
--- /dev/null
+++ b/go/types/testdata/init0.src
@@ -0,0 +1,106 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// initialization cycles
+
+package init0
+
+// initialization cycles (we don't know the types)
+const (
+	s0 /* ERROR initialization cycle */ = s0
+
+	x0 /* ERROR initialization cycle */ = y0
+	y0 = x0
+
+	a0 = b0
+	b0 /* ERROR initialization cycle */ = c0
+	c0 = d0
+	d0 = b0
+)
+
+var (
+	s1 /* ERROR initialization cycle */ = s1
+
+	x1 /* ERROR initialization cycle */ = y1
+	y1 = x1
+
+	a1 = b1
+	b1 /* ERROR initialization cycle */ = c1
+	c1 = d1
+	d1 = b1
+)
+
+// initialization cycles (we know the types)
+const (
+	s2 /* ERROR initialization cycle */ int = s2
+
+	x2 /* ERROR initialization cycle */ int = y2
+	y2 = x2
+
+	a2 = b2
+	b2 /* ERROR initialization cycle */ int = c2
+	c2 = d2
+	d2 = b2
+)
+
+var (
+	s3 /* ERROR initialization cycle */ int = s3
+
+	x3 /* ERROR initialization cycle */ int = y3
+	y3 = x3
+
+	a3 = b3
+	b3 /* ERROR initialization cycle */ int = c3
+	c3 = d3
+	d3 = b3
+)
+
+// cycles via struct fields
+
+type S1 struct {
+	f int
+}
+const cx3 S1 /* ERROR invalid constant type */ = S1{cx3.f}
+var vx3 /* ERROR initialization cycle */ S1 = S1{vx3.f}
+
+// cycles via functions
+
+var x4 = x5
+var x5 /* ERROR initialization cycle */ = f1()
+func f1() int { return x5*10 }
+
+var x6, x7 /* ERROR initialization cycle */ = f2()
+var x8 = x7
+func f2() (int, int) { return f3() + f3(), 0 }
+func f3() int { return x8 }
+
+// cycles via closures
+
+var x9 /* ERROR initialization cycle */ = func() int { return x9 }()
+
+var x10 /* ERROR initialization cycle */ = f4()
+
+func f4() int {
+	_ = func() {
+		_ = x10
+	}
+	return 0
+}
+
+// cycles via method expressions
+
+type T1 struct{}
+
+func (T1) m() bool { _ = x11; return false }
+
+var x11 /* ERROR initialization cycle */ = T1.m(T1{})
+
+// cycles via method values
+
+type T2 struct{}
+
+func (T2) m() bool { _ = x12; return false }
+
+var t1 T2
+var x12 /* ERROR initialization cycle */ = t1.m
diff --git a/go/types/testdata/init1.src b/go/types/testdata/init1.src
new file mode 100644
index 0000000..39ca314
--- /dev/null
+++ b/go/types/testdata/init1.src
@@ -0,0 +1,97 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// initialization cycles
+
+package init1
+
+// issue 6683 (marked as WorkingAsIntended)
+
+type T0 struct{}
+
+func (T0) m() int { return y0 }
+
+var x0 = T0{}
+
+var y0 /* ERROR initialization cycle */ = x0.m()
+
+type T1 struct{}
+
+func (T1) m() int { return y1 }
+
+var x1 interface {
+	m() int
+} = T1{}
+
+var y1 = x1.m() // no cycle reported, x1 is of interface type
+
+// issue 6703 (modified)
+
+var x2 /* ERROR initialization cycle */ = T2.m
+
+var y2 = x2
+
+type T2 struct{}
+
+func (T2) m() int {
+	_ = y2
+	return 0
+}
+
+var x3 /* ERROR initialization cycle */ = T3.m(T3{}) // <<<< added (T3{})
+
+var y3 = x3
+
+type T3 struct{}
+
+func (T3) m() int {
+	_ = y3
+	return 0
+}
+
+var x4 /* ERROR initialization cycle */ = T4{}.m // <<<< added {}
+
+var y4 = x4
+
+type T4 struct{}
+
+func (T4) m() int {
+	_ = y4
+	return 0
+}
+
+var x5 /* ERROR initialization cycle */ = T5{}.m() // <<<< added ()
+
+var y5 = x5
+
+type T5 struct{}
+
+func (T5) m() int {
+	_ = y5
+	return 0
+}
+
+// issue 4847
+// simplified test case
+
+var x6 = f6
+var y6 /* ERROR initialization cycle */ = f6
+func f6() { _ = y6 }
+
+// full test case
+
+type (
+      E int
+      S int
+)
+
+type matcher func(s *S) E
+
+func matchList(s *S) E { return matcher(matchAnyFn)(s) }
+
+var foo = matcher(matchList)
+
+var matchAny /* ERROR initialization cycle */ = matcher(matchList)
+
+func matchAnyFn(s *S) (err E) { return matchAny(s) }
\ No newline at end of file
diff --git a/go/types/testdata/init2.src b/go/types/testdata/init2.src
new file mode 100644
index 0000000..614db6c
--- /dev/null
+++ b/go/types/testdata/init2.src
@@ -0,0 +1,139 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// initialization cycles
+
+package init2
+
+// cycles through functions
+
+func f1() int { _ = x1; return 0 }
+var x1 /* ERROR initialization cycle */ = f1
+
+func f2() int { _ = x2; return 0 }
+var x2 /* ERROR initialization cycle */ = f2()
+
+// cycles through method expressions
+
+type T3 int
+func (T3) m() int { _ = x3; return 0 }
+var x3 /* ERROR initialization cycle */ = T3.m
+
+type T4 int
+func (T4) m() int { _ = x4; return 0 }
+var x4 /* ERROR initialization cycle */ = T4.m(0)
+
+type T3p int
+func (*T3p) m() int { _ = x3p; return 0 }
+var x3p /* ERROR initialization cycle */ = (*T3p).m
+
+type T4p int
+func (*T4p) m() int { _ = x4p; return 0 }
+var x4p /* ERROR initialization cycle */ = (*T4p).m(nil)
+
+// cycles through method expressions of embedded methods
+
+type T5 struct { E5 }
+type E5 int
+func (E5) m() int { _ = x5; return 0 }
+var x5 /* ERROR initialization cycle */ = T5.m
+
+type T6 struct { E6 }
+type E6 int
+func (E6) m() int { _ = x6; return 0 }
+var x6 /* ERROR initialization cycle */ = T6.m(T6{0})
+
+type T5p struct { E5p }
+type E5p int
+func (*E5p) m() int { _ = x5p; return 0 }
+var x5p /* ERROR initialization cycle */ = (*T5p).m
+
+type T6p struct { E6p }
+type E6p int
+func (*E6p) m() int { _ = x6p; return 0 }
+var x6p /* ERROR initialization cycle */ = (*T6p).m(nil)
+
+// cycles through method values
+
+type T7 int
+func (T7) m() int { _ = x7; return 0 }
+var x7 /* ERROR initialization cycle */ = T7(0).m
+
+type T8 int
+func (T8) m() int { _ = x8; return 0 }
+var x8 /* ERROR initialization cycle */ = T8(0).m()
+
+type T7p int
+func (*T7p) m() int { _ = x7p; return 0 }
+var x7p /* ERROR initialization cycle */ = new(T7p).m
+
+type T8p int
+func (*T8p) m() int { _ = x8p; return 0 }
+var x8p /* ERROR initialization cycle */ = new(T8p).m()
+
+type T7v int
+func (T7v) m() int { _ = x7v; return 0 }
+var x7var T7v
+var x7v /* ERROR initialization cycle */ = x7var.m
+
+type T8v int
+func (T8v) m() int { _ = x8v; return 0 }
+var x8var T8v
+var x8v /* ERROR initialization cycle */ = x8var.m()
+
+type T7pv int
+func (*T7pv) m() int { _ = x7pv; return 0 }
+var x7pvar *T7pv
+var x7pv /* ERROR initialization cycle */ = x7pvar.m
+
+type T8pv int
+func (*T8pv) m() int { _ = x8pv; return 0 }
+var x8pvar *T8pv
+var x8pv /* ERROR initialization cycle */ = x8pvar.m()
+
+// cycles through method values of embedded methods
+
+type T9 struct { E9 }
+type E9 int
+func (E9) m() int { _ = x9; return 0 }
+var x9 /* ERROR initialization cycle */ = T9{0}.m
+
+type T10 struct { E10 }
+type E10 int
+func (E10) m() int { _ = x10; return 0 }
+var x10 /* ERROR initialization cycle */ = T10{0}.m()
+
+type T9p struct { E9p }
+type E9p int
+func (*E9p) m() int { _ = x9p; return 0 }
+var x9p /* ERROR initialization cycle */ = new(T9p).m
+
+type T10p struct { E10p }
+type E10p int
+func (*E10p) m() int { _ = x10p; return 0 }
+var x10p /* ERROR initialization cycle */ = new(T10p).m()
+
+type T9v struct { E9v }
+type E9v int
+func (E9v) m() int { _ = x9v; return 0 }
+var x9var T9v
+var x9v /* ERROR initialization cycle */ = x9var.m
+
+type T10v struct { E10v }
+type E10v int
+func (E10v) m() int { _ = x10v; return 0 }
+var x10var T10v
+var x10v /* ERROR initialization cycle */ = x10var.m()
+
+type T9pv struct { E9pv }
+type E9pv int
+func (*E9pv) m() int { _ = x9pv; return 0 }
+var x9pvar *T9pv
+var x9pv /* ERROR initialization cycle */ = x9pvar.m
+
+type T10pv struct { E10pv }
+type E10pv int
+func (*E10pv) m() int { _ = x10pv; return 0 }
+var x10pvar *T10pv
+var x10pv /* ERROR initialization cycle */ = x10pvar.m()
diff --git a/go/types/testdata/issues.src b/go/types/testdata/issues.src
new file mode 100644
index 0000000..595a634
--- /dev/null
+++ b/go/types/testdata/issues.src
@@ -0,0 +1,97 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package issues
+
+import "fmt"
+
+func issue7035() {
+	type T struct{ X int }
+	_ = func() {
+		fmt.Println() // must refer to imported fmt rather than the fmt below
+	}
+	fmt := new(T)
+	_ = fmt.X
+}
+
+func issue8066() {
+	const (
+		// TODO(gri) Enable test below for releases 1.4 and higher
+		// _ = float32(340282356779733661637539395458142568447)
+		_ = float32(340282356779733661637539395458142568448 /* ERROR cannot convert */ )
+	)
+}
+
+// Check that a missing identifier doesn't lead to a spurious error cascade.
+func issue8799a() {
+	x, ok := missing /* ERROR undeclared */ ()
+	_ = !ok
+	_ = x
+}
+
+func issue8799b(x int, ok bool) {
+	x, ok = missing /* ERROR undeclared */ ()
+	_ = !ok
+	_ = x
+}
+
+func issue9182() {
+	type Point C /* ERROR undeclared */ .Point
+	// no error for composite literal based on unknown type
+	_ = Point{x: 1, y: 2}
+}
+
+func f0() (a []int)         { return }
+func f1() (a []int, b int)  { return }
+func f2() (a, b []int)      { return }
+
+func append_([]int, ...int) {}
+
+func issue9473(a []int, b ...int) {
+	// variadic builtin function
+	_ = append(f0())
+	_ = append(f0(), f0()...)
+	_ = append(f1())
+	_ = append(f2 /* ERROR cannot pass argument */ ())
+	_ = append(f2()... /* ERROR cannot use ... */ )
+	_ = append(f0(), f1 /* ERROR 2-valued expression */ ())
+	_ = append(f0(), f2 /* ERROR 2-valued expression */ ())
+	_ = append(f0(), f1()... /* ERROR cannot use ... */ )
+	_ = append(f0(), f2()... /* ERROR cannot use ... */ )
+
+	// variadic user-defined function
+	append_(f0())
+	append_(f0(), f0()...)
+	append_(f1())
+	append_(f2 /* ERROR cannot pass argument */ ())
+	append_(f2()... /* ERROR cannot use ... */ )
+	append_(f0(), f1 /* ERROR 2-valued expression */ ())
+	append_(f0(), f2 /* ERROR 2-valued expression */ ())
+	append_(f0(), f1()... /* ERROR cannot use */ )
+	append_(f0(), f2()... /* ERROR cannot use */ )
+}
+
+// Check that embedding a non-interface type in an interface results in a good error message.
+func issue10979() {
+	type _ interface {
+		int /* ERROR int is not an interface */
+	}
+	type T struct{}
+	type _ interface {
+		T /* ERROR T is not an interface */
+	}
+	type _ interface {
+		nosuchtype /* ERROR undeclared name: nosuchtype */
+	}
+	type _ interface {
+		fmt /* ERROR Nosuchtype not declared by package fmt */ .Nosuchtype
+	}
+	type _ interface {
+		nosuchpkg /* ERROR undeclared name: nosuchpkg */ .Nosuchtype
+	}
+	type I interface {
+		I /* ERROR I\.m \(value of type func\(I\)\) is not a type */ .m
+		m()
+	}
+}
diff --git a/go/types/testdata/labels.src b/go/types/testdata/labels.src
new file mode 100644
index 0000000..102ffc7
--- /dev/null
+++ b/go/types/testdata/labels.src
@@ -0,0 +1,207 @@
+// Copyright 2011 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file is a modified concatenation of the files
+// $GOROOT/test/label.go and $GOROOT/test/label1.go.
+
+package labels
+
+var x int
+
+func f0() {
+L1 /* ERROR "label L1 declared but not used" */ :
+	for {
+	}
+L2 /* ERROR "label L2 declared but not used" */ :
+	select {
+	}
+L3 /* ERROR "label L3 declared but not used" */ :
+	switch {
+	}
+L4 /* ERROR "label L4 declared but not used" */ :
+	if true {
+	}
+L5 /* ERROR "label L5 declared but not used" */ :
+	f0()
+L6:
+	f0()
+L6 /* ERROR "label L6 already declared" */ :
+	f0()
+	if x == 20 {
+		goto L6
+	}
+
+L7:
+	for {
+		break L7
+		break L8 /* ERROR "invalid break label L8" */
+	}
+
+// A label must be directly associated with a switch, select, or
+// for statement; it cannot be the label of a labeled statement.
+
+L7a /* ERROR "declared but not used" */ : L7b:
+	for {
+		break L7a /* ERROR "invalid break label L7a" */
+		continue L7a /* ERROR "invalid continue label L7a" */
+		continue L7b
+	}
+
+L8:
+	for {
+		if x == 21 {
+			continue L8
+			continue L7 /* ERROR "invalid continue label L7" */
+		}
+	}
+
+L9:
+	switch {
+	case true:
+		break L9
+	defalt /* ERROR "label defalt declared but not used" */ :
+	}
+
+L10:
+	select {
+	default:
+		break L10
+		break L9 /* ERROR "invalid break label L9" */
+	}
+
+	goto L10a
+L10a: L10b:
+	select {
+	default:
+		break L10a /* ERROR "invalid break label L10a" */
+		break L10b
+		continue L10b /* ERROR "invalid continue label L10b" */
+	}
+}
+
+func f1() {
+L1:
+	for {
+		if x == 0 {
+			break L1
+		}
+		if x == 1 {
+			continue L1
+		}
+		goto L1
+	}
+
+L2:
+	select {
+	default:
+		if x == 0 {
+			break L2
+		}
+		if x == 1 {
+			continue L2 /* ERROR "invalid continue label L2" */
+		}
+		goto L2
+	}
+
+L3:
+	switch {
+	case x > 10:
+		if x == 11 {
+			break L3
+		}
+		if x == 12 {
+			continue L3 /* ERROR "invalid continue label L3" */
+		}
+		goto L3
+	}
+
+L4:
+	if true {
+		if x == 13 {
+			break L4 /* ERROR "invalid break label L4" */
+		}
+		if x == 14 {
+			continue L4 /* ERROR "invalid continue label L4" */
+		}
+		if x == 15 {
+			goto L4
+		}
+	}
+
+L5:
+	f1()
+	if x == 16 {
+		break L5 /* ERROR "invalid break label L5" */
+	}
+	if x == 17 {
+		continue L5 /* ERROR "invalid continue label L5" */
+	}
+	if x == 18 {
+		goto L5
+	}
+
+	for {
+		if x == 19 {
+			break L1 /* ERROR "invalid break label L1" */
+		}
+		if x == 20 {
+			continue L1 /* ERROR "invalid continue label L1" */
+		}
+		if x == 21 {
+			goto L1
+		}
+	}
+}
+
+// Additional tests not in the original files.
+
+func f2() {
+L1 /* ERROR "label L1 declared but not used" */ :
+	if x == 0 {
+		for {
+			continue L1 /* ERROR "invalid continue label L1" */
+		}
+	}
+}
+
+func f3() {
+L1:
+L2:
+L3:
+	for {
+		break L1 /* ERROR "invalid break label L1" */
+		break L2 /* ERROR "invalid break label L2" */
+		break L3
+		continue L1 /* ERROR "invalid continue label L1" */
+		continue L2 /* ERROR "invalid continue label L2" */
+		continue L3
+		goto L1
+		goto L2
+		goto L3
+	}
+}
+
+// Blank labels are never declared.
+
+func f4() {
+_:
+_: // multiple blank labels are ok
+	goto _ /* ERROR "label _ not declared" */
+}
+
+func f5() {
+_:
+	for {
+		break _ /* ERROR "invalid break label _" */
+		continue _ /* ERROR "invalid continue label _" */
+	}
+}
+
+func f6() {
+_:
+	switch {
+	default:
+		break _ /* ERROR "invalid break label _" */
+	}
+}
diff --git a/go/types/testdata/methodsets.src b/go/types/testdata/methodsets.src
new file mode 100644
index 0000000..8921146
--- /dev/null
+++ b/go/types/testdata/methodsets.src
@@ -0,0 +1,214 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package methodsets
+
+type T0 struct {}
+
+func (T0) v0() {}
+func (*T0) p0() {}
+
+type T1 struct {} // like T0 with different method names
+
+func (T1) v1() {}
+func (*T1) p1() {}
+
+type T2 interface {
+	v2()
+	p2()
+}
+
+type T3 struct {
+	T0
+	*T1
+	T2
+}
+
+// Method expressions
+func _() {
+	var (
+		_ func(T0) = T0.v0
+		_ = T0 /* ERROR "not in method set" */ .p0
+
+		_ func (*T0) = (*T0).v0
+		_ func (*T0) = (*T0).p0
+
+		// T1 is like T0
+
+		_ func(T2) = T2.v2
+		_ func(T2) = T2.p2
+
+		_ func(T3) = T3.v0
+		_ func(T3) = T3 /* ERROR "not in method set" */ .p0
+		_ func(T3) = T3.v1
+		_ func(T3) = T3.p1
+		_ func(T3) = T3.v2
+		_ func(T3) = T3.p2
+
+		_ func(*T3) = (*T3).v0
+		_ func(*T3) = (*T3).p0
+		_ func(*T3) = (*T3).v1
+		_ func(*T3) = (*T3).p1
+		_ func(*T3) = (*T3).v2
+		_ func(*T3) = (*T3).p2
+	)
+}
+
+// Method values with addressable receivers
+func _() {
+	var (
+		v0 T0
+		_ func() = v0.v0
+		_ func() = v0.p0
+	)
+
+	var (
+		p0 *T0
+		_ func() = p0.v0
+		_ func() = p0.p0
+	)
+
+	// T1 is like T0
+
+	var (
+		v2 T2
+		_ func() = v2.v2
+		_ func() = v2.p2
+	)
+
+	var (
+		v4 T3
+		_ func() = v4.v0
+		_ func() = v4.p0
+		_ func() = v4.v1
+		_ func() = v4.p1
+		_ func() = v4.v2
+		_ func() = v4.p2
+	)
+
+	var (
+		p4 *T3
+		_ func() = p4.v0
+		_ func() = p4.p0
+		_ func() = p4.v1
+		_ func() = p4.p1
+		_ func() = p4.v2
+		_ func() = p4.p2
+	)
+}
+
+// Method calls with addressable receivers
+func _() {
+	var v0 T0
+	v0.v0()
+	v0.p0()
+
+	var p0 *T0
+	p0.v0()
+	p0.p0()
+
+	// T1 is like T0
+
+	var v2 T2
+	v2.v2()
+	v2.p2()
+
+	var v4 T3
+	v4.v0()
+	v4.p0()
+	v4.v1()
+	v4.p1()
+	v4.v2()
+	v4.p2()
+
+	var p4 *T3
+	p4.v0()
+	p4.p0()
+	p4.v1()
+	p4.p1()
+	p4.v2()
+	p4.p2()
+}
+
+// Method values with value receivers
+func _() {
+	var (
+		_ func() = T0{}.v0
+		_ func() = T0 /* ERROR "not in method set" */ {}.p0
+
+		_ func() = (&T0{}).v0
+		_ func() = (&T0{}).p0
+
+		// T1 is like T0
+
+		// no values for T2
+
+		_ func() = T3{}.v0
+		_ func() = T3 /* ERROR "not in method set" */ {}.p0
+		_ func() = T3{}.v1
+		_ func() = T3{}.p1
+		_ func() = T3{}.v2
+		_ func() = T3{}.p2
+
+		_ func() = (&T3{}).v0
+		_ func() = (&T3{}).p0
+		_ func() = (&T3{}).v1
+		_ func() = (&T3{}).p1
+		_ func() = (&T3{}).v2
+		_ func() = (&T3{}).p2
+	)
+}
+
+// Method calls with value receivers
+func _() {
+	T0{}.v0()
+	T0 /* ERROR "not in method set" */ {}.p0()
+
+	(&T0{}).v0()
+	(&T0{}).p0()
+
+	// T1 is like T0
+
+	// no values for T2
+
+	T3{}.v0()
+	T3 /* ERROR "not in method set" */ {}.p0()
+	T3{}.v1()
+	T3{}.p1()
+	T3{}.v2()
+	T3{}.p2()
+
+	(&T3{}).v0()
+	(&T3{}).p0()
+	(&T3{}).v1()
+	(&T3{}).p1()
+	(&T3{}).v2()
+	(&T3{}).p2()
+}
+
+// *T has no methods if T is an interface type
+func issue5918() {
+	var (
+		err error
+		_ = err.Error()
+		_ func() string = err.Error
+		_ func(error) string = error.Error
+
+		perr = &err
+		_ = perr /* ERROR "no field or method" */ .Error()
+		_ func() string = perr /* ERROR "no field or method" */ .Error
+		_ func(*error) string = ( /* ERROR "no field or method" */ *error).Error
+	)
+
+	type T *interface{ m() int }
+	var (
+		x T
+		_ = (*x).m()
+		_ = (*x).m
+
+		_ = x /* ERROR "no field or method" */ .m()
+		_ = x /* ERROR "no field or method" */ .m
+		_ = T /* ERROR "no field or method" */ .m
+	)
+}
diff --git a/go/types/testdata/shifts.src b/go/types/testdata/shifts.src
new file mode 100644
index 0000000..fa4de9e
--- /dev/null
+++ b/go/types/testdata/shifts.src
@@ -0,0 +1,341 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package shifts
+
+func shifts0() {
+	// basic constant shifts
+	const (
+		s = 10
+		_ = 0<<0
+		_ = 1<<s
+		_ = 1<<- /* ERROR "stupid shift" */ 1
+		_ = 1<<1075 /* ERROR "stupid shift" */
+		_ = 2.0<<1
+
+		_ int = 2<<s
+		_ float32 = 2<<s
+		_ complex64 = 2<<s
+
+		_ int = 2.0<<s
+		_ float32 = 2.0<<s
+		_ complex64 = 2.0<<s
+
+		_ int = 'a'<<s
+		_ float32 = 'a'<<s
+		_ complex64 = 'a'<<s
+	)
+}
+
+func shifts1() {
+	// basic non-constant shifts
+	var (
+		i int
+		u uint
+
+		_ = 1<<0
+		_ = 1<<i /* ERROR "must be unsigned" */
+		_ = 1<<u
+		_ = 1<<"foo" /* ERROR "cannot convert" */
+		_ = i<<0
+		_ = i<<- /* ERROR "must not be negative" */ 1
+		_ = 1 /* ERROR "overflows" */ <<100
+
+		_ uint = 1 << 0
+		_ uint = 1 << u
+		_ float32 = 1 /* ERROR "must be integer" */ << u
+	)
+}
+
+func shifts2() {
+	// 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     // 1.0 has type int
+		n = 1.0<<s != i    // 1.0 has type int; n == false if ints are 32bits in size
+		o = 1<<s == 2<<s   // 1 and 2 have type int; o == true if ints are 32bits in size
+		p = 1<<s == 1<<33  // illegal if ints are 32bits in size: 1 has type int, but 1<<33 overflows int
+		u = 1.0 /* ERROR "must be integer" */ <<s         // illegal: 1.0 has type float64, cannot shift
+		u1 = 1.0 /* ERROR "must be integer" */ <<s != 0   // illegal: 1.0 has type float64, cannot shift
+		u2 = 1 /* ERROR "must be integer" */ <<s != 1.0   // illegal: 1 has type float64, cannot shift
+		v float32 = 1 /* ERROR "must be integer" */ <<s   // illegal: 1 has type float32, cannot shift
+		w int64 = 1.0<<33  // 1.0<<33 is a constant shift expression
+	)
+	_, _, _, _, _, _, _, _, _, _, _, _ = i, j, k, m, n, o, p, u, u1, u2, v, w
+}
+
+func shifts3(a int16, b float32) {
+	// random tests
+	var (
+		s uint = 11
+		u = 1 /* ERROR "must be integer" */ <<s + 1.0
+		v complex128 = 1 /* ERROR "must be integer" */ << s + 1.0 /* ERROR "must be integer" */ << s + 1
+	)
+	x := 1.0 /* ERROR "must be integer" */ <<s + 1
+	shifts3(1.0 << s, 1 /* ERROR "must be integer" */ >> s)
+	_, _, _ = u, v, x
+}
+
+func shifts4() {
+	// shifts in comparisons w/ untyped operands
+	var s uint
+
+	_ = 1<<s == 1
+	_ = 1 /* ERROR "integer" */ <<s == 1.
+	_ = 1. /* ERROR "integer" */ <<s == 1
+	_ = 1. /* ERROR "integer" */ <<s == 1.
+
+	_ = 1<<s + 1 == 1
+	_ = 1 /* ERROR "integer" */ <<s + 1 == 1.
+	_ = 1 /* ERROR "integer" */ <<s + 1. == 1
+	_ = 1 /* ERROR "integer" */ <<s + 1. == 1.
+	_ = 1. /* ERROR "integer" */ <<s + 1 == 1
+	_ = 1. /* ERROR "integer" */ <<s + 1 == 1.
+	_ = 1. /* ERROR "integer" */ <<s + 1. == 1
+	_ = 1. /* ERROR "integer" */ <<s + 1. == 1.
+
+	_ = 1<<s == 1<<s
+	_ = 1 /* ERROR "integer" */ <<s == 1. /* ERROR "integer" */ <<s
+	_ = 1. /* ERROR "integer" */ <<s == 1 /* ERROR "integer" */ <<s
+	_ = 1. /* ERROR "integer" */ <<s == 1. /* ERROR "integer" */ <<s
+
+	_ = 1<<s + 1<<s == 1
+	_ = 1 /* ERROR "integer" */ <<s + 1 /* ERROR "integer" */ <<s == 1.
+	_ = 1 /* ERROR "integer" */ <<s + 1. /* ERROR "integer" */ <<s == 1
+	_ = 1 /* ERROR "integer" */ <<s + 1. /* ERROR "integer" */ <<s == 1.
+	_ = 1. /* ERROR "integer" */ <<s + 1 /* ERROR "integer" */ <<s == 1
+	_ = 1. /* ERROR "integer" */ <<s + 1 /* ERROR "integer" */ <<s == 1.
+	_ = 1. /* ERROR "integer" */ <<s + 1. /* ERROR "integer" */ <<s == 1
+	_ = 1. /* ERROR "integer" */ <<s + 1. /* ERROR "integer" */ <<s == 1.
+
+	_ = 1<<s + 1<<s == 1<<s + 1<<s
+	_ = 1 /* ERROR "integer" */ <<s + 1 /* ERROR "integer" */ <<s == 1 /* ERROR "integer" */ <<s + 1. /* ERROR "integer" */ <<s
+	_ = 1 /* ERROR "integer" */ <<s + 1 /* ERROR "integer" */ <<s == 1. /* ERROR "integer" */ <<s + 1 /* ERROR "integer" */ <<s
+	_ = 1 /* ERROR "integer" */ <<s + 1 /* ERROR "integer" */ <<s == 1. /* ERROR "integer" */ <<s + 1. /* ERROR "integer" */ <<s
+	_ = 1 /* ERROR "integer" */ <<s + 1. /* ERROR "integer" */ <<s == 1 /* ERROR "integer" */ <<s + 1 /* ERROR "integer" */ <<s
+	_ = 1 /* ERROR "integer" */ <<s + 1. /* ERROR "integer" */ <<s == 1 /* ERROR "integer" */ <<s + 1. /* ERROR "integer" */ <<s
+	_ = 1 /* ERROR "integer" */ <<s + 1. /* ERROR "integer" */ <<s == 1. /* ERROR "integer" */ <<s + 1 /* ERROR "integer" */ <<s
+	_ = 1 /* ERROR "integer" */ <<s + 1. /* ERROR "integer" */ <<s == 1. /* ERROR "integer" */ <<s + 1. /* ERROR "integer" */ <<s
+	_ = 1. /* ERROR "integer" */ <<s + 1 /* ERROR "integer" */ <<s == 1 /* ERROR "integer" */ <<s + 1 /* ERROR "integer" */ <<s
+	_ = 1. /* ERROR "integer" */ <<s + 1 /* ERROR "integer" */ <<s == 1 /* ERROR "integer" */ <<s + 1. /* ERROR "integer" */ <<s
+	_ = 1. /* ERROR "integer" */ <<s + 1 /* ERROR "integer" */ <<s == 1. /* ERROR "integer" */ <<s + 1 /* ERROR "integer" */ <<s
+	_ = 1. /* ERROR "integer" */ <<s + 1 /* ERROR "integer" */ <<s == 1. /* ERROR "integer" */ <<s + 1. /* ERROR "integer" */ <<s
+	_ = 1. /* ERROR "integer" */ <<s + 1. /* ERROR "integer" */ <<s == 1 /* ERROR "integer" */ <<s + 1 /* ERROR "integer" */ <<s
+	_ = 1. /* ERROR "integer" */ <<s + 1. /* ERROR "integer" */ <<s == 1 /* ERROR "integer" */ <<s + 1. /* ERROR "integer" */ <<s
+	_ = 1. /* ERROR "integer" */ <<s + 1. /* ERROR "integer" */ <<s == 1. /* ERROR "integer" */ <<s + 1 /* ERROR "integer" */ <<s
+	_ = 1. /* ERROR "integer" */ <<s + 1. /* ERROR "integer" */ <<s == 1. /* ERROR "integer" */ <<s + 1. /* ERROR "integer" */ <<s
+}
+
+func shifts5() {
+	// shifts in comparisons w/ typed operands
+	var s uint
+	var x int
+
+	_ = 1<<s == x
+	_ = 1.<<s == x
+	_ = 1.1 /* ERROR "int" */ <<s == x
+
+	_ = 1<<s + x == 1
+	_ = 1<<s + x == 1.
+	_ = 1<<s + x == 1.1 /* ERROR "int" */
+	_ = 1.<<s + x == 1
+	_ = 1.<<s + x == 1.
+	_ = 1.<<s + x == 1.1 /* ERROR "int" */
+	_ = 1.1 /* ERROR "int" */ <<s + x == 1
+	_ = 1.1 /* ERROR "int" */ <<s + x == 1.
+	_ = 1.1 /* ERROR "int" */ <<s + x == 1.1
+
+	_ = 1<<s == x<<s
+	_ = 1.<<s == x<<s
+	_ = 1.1  /* ERROR "int" */ <<s == x<<s
+}
+
+func shifts6() {
+	// shifts as operands in non-arithmetic operations and as arguments
+	var a [10]int
+	var s uint
+
+	_ = a[1<<s]
+	_ = a[1.0]
+	_ = a[1.0<<s]
+
+	_ = make([]int, 1.0)
+	_ = make([]int, 1.0<<s)
+	_ = make([]int, 1.1 /* ERROR "must be integer" */ <<s)
+
+	_ = float32(1)
+	_ = float32(1 /* ERROR "must be integer" */ <<s)
+	_ = float32(1.0)
+	_ = float32(1.0 /* ERROR "must be integer" */ <<s)
+	_ = float32(1.1 /* ERROR "must be integer" */ <<s)
+
+	var b []int
+	_ = append(b, 1<<s)
+	_ = append(b, 1.0<<s)
+	_ = append(b, 1.1 /* ERROR "must be integer" */ <<s)
+
+	_ = append(b, 1<<s)
+	_ = append(b, 1.0<<s) // should fail - see TODO in append code
+	_ = append(b, 1.1 /* ERROR "must be integer" */ <<s)
+
+	_ = complex(1.0 /* ERROR "must be integer" */ <<s, 0)
+	_ = complex(1.1 /* ERROR "must be integer" */ <<s, 0)
+	_ = complex(0, 1.0 /* ERROR "must be integer" */ <<s)
+	_ = complex(0, 1.1 /* ERROR "must be integer" */ <<s)
+
+	// TODO(gri) The delete below is not type-checked correctly yet.
+	// var m1 map[int]string
+	// delete(m1, 1<<s)
+}
+
+func shifts7() {
+	// shifts of shifts
+	var s uint
+	var x int
+	_ = x
+
+	_ = 1<<(1<<s)
+	_ = 1<<(1.<<s)
+	_ = 1. /* ERROR "integer" */ <<(1<<s)
+	_ = 1. /* ERROR "integer" */ <<(1.<<s)
+
+	x = 1<<(1<<s)
+	x = 1<<(1.<<s)
+	x = 1.<<(1<<s)
+	x = 1.<<(1.<<s)
+
+	_ = (1<<s)<<(1<<s)
+	_ = (1<<s)<<(1.<<s)
+	_ = ( /* ERROR "integer" */ 1.<<s)<<(1<<s)
+	_ = ( /* ERROR "integer" */ 1.<<s)<<(1.<<s)
+
+	x = (1<<s)<<(1<<s)
+	x = (1<<s)<<(1.<<s)
+	x = ( /* ERROR "integer" */ 1.<<s)<<(1<<s)
+	x = ( /* ERROR "integer" */ 1.<<s)<<(1.<<s)
+}
+
+func shifts8() {
+	// shift examples from shift discussion: better error messages
+	var s uint
+	_ = 1.0 /* ERROR "shifted operand 1.0 \(type float64\) must be integer" */ <<s == 1
+	_ = 1.0 /* ERROR "shifted operand 1.0 \(type float64\) must be integer" */ <<s == 1.0
+	_ = 1 /* ERROR "shifted operand 1 \(type float64\) must be integer" */ <<s == 1.0
+	_ = 1 /* ERROR "shifted operand 1 \(type float64\) must be integer" */ <<s + 1.0 == 1
+	_ = 1 /* ERROR "shifted operand 1 \(type float64\) must be integer" */ <<s + 1.1 == 1
+	_ = 1 /* ERROR "shifted operand 1 \(type float64\) must be integer" */ <<s + 1 == 1.0
+
+	// additional cases
+	_ = complex(1.0 /* ERROR "shifted operand 1.0 \(type float64\) must be integer" */ <<s, 1)
+	_ = complex(1.0, 1 /* ERROR "shifted operand 1 \(type float64\) must be integer" */ <<s)
+
+	_ = int(1.<<s)
+	_ = int(1.1 /* ERROR "shifted operand .* must be integer" */ <<s)
+	_ = float32(1 /* ERROR "shifted operand .* must be integer" */ <<s)
+	_ = float32(1. /* ERROR "shifted operand .* must be integer" */ <<s)
+	_ = float32(1.1 /* ERROR "shifted operand .* must be integer" */ <<s)
+	// TODO(gri) the error messages for these two are incorrect - disabled for now
+	// _ = complex64(1<<s)
+	// _ = complex64(1.<<s)
+	_ = complex64(1.1 /* ERROR "shifted operand .* must be integer" */ <<s)
+}
+
+func shifts9() {
+	// various originally failing snippets of code from the std library
+	// from src/compress/lzw/reader.go:90
+	{
+		var d struct {
+			bits     uint32
+			width    uint
+		}
+		_ = uint16(d.bits & (1<<d.width - 1))
+	}
+
+	// from src/debug/dwarf/buf.go:116
+	{
+		var ux uint64
+		var bits uint
+		x := int64(ux)
+		if x&(1<<(bits-1)) != 0 {}
+	}
+
+	// from src/encoding/asn1/asn1.go:160
+	{
+		var bytes []byte
+		if bytes[len(bytes)-1]&((1<<bytes[0])-1) != 0 {}
+	}
+
+	// from src/math/big/rat.go:140
+	{
+		var exp int
+		var mantissa uint64
+		shift := uint64(-1022 - (exp - 1)) // [1..53)
+		_ = mantissa & (1<<shift - 1)
+	}
+
+	// from src/net/interface.go:51
+	{
+		type Flags uint
+		var f Flags
+		var i int
+		if f&(1<<uint(i)) != 0 {}
+	}
+
+	// from src/runtime/softfloat64.go:234
+	{
+		var gm uint64
+		var shift uint
+		_ = gm & (1<<shift - 1)
+	}
+
+	// from src/strconv/atof.go:326
+	{
+		var mant uint64
+		var mantbits uint
+		if mant == 2<<mantbits {}
+	}
+
+	// from src/route_bsd.go:82
+	{
+		var Addrs int32
+		const rtaRtMask = 1
+		var i uint
+		if Addrs&rtaRtMask&(1<<i) == 0 {}
+	}
+
+	// from src/text/scanner/scanner.go:540
+	{
+		var s struct { Whitespace uint64 }
+		var ch rune
+		for s.Whitespace&(1<<uint(ch)) != 0 {}
+	}
+}
+
+func issue5895() {
+	var x = 'a' << 1 // type of x must be rune
+	var _ rune = x
+}
+
+func issue11325() {
+	var _ = 0 >> 1.1 /* ERROR "must be unsigned integer" */ // example from issue 11325
+	_ = 0 >> 1.1 /* ERROR "must be unsigned integer" */
+	_ = 0 << 1.1 /* ERROR "must be unsigned integer" */
+	_ = 0 >> 1.
+	_ = 1 >> 1.1 /* ERROR "must be unsigned integer" */
+	_ = 1 >> 1.
+	_ = 1. >> 1
+	_ = 1. >> 1.
+	_ = 1.1 /* ERROR "must be integer" */ >> 1
+}
+
+func issue11594() {
+	var _ = complex64 /* ERROR "must be integer" */ (1) << 2 // example from issue 11594
+	_ = float32 /* ERROR "must be integer" */ (0) << 1
+	_ = float64 /* ERROR "must be integer" */ (0) >> 2
+	_ = complex64 /* ERROR "must be integer" */ (0) << 3
+	_ = complex64 /* ERROR "must be integer" */ (0) >> 4
+}
diff --git a/go/types/testdata/stmt0.src b/go/types/testdata/stmt0.src
new file mode 100644
index 0000000..fd1ddba
--- /dev/null
+++ b/go/types/testdata/stmt0.src
@@ -0,0 +1,833 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// statements
+
+package stmt0
+
+func assignments0() (int, int) {
+	var a, b, c int
+	var ch chan int
+	f0 := func() {}
+	f1 := func() int { return 1 }
+	f2 := func() (int, int) { return 1, 2 }
+	f3 := func() (int, int, int) { return 1, 2, 3 }
+
+	a, b, c = 1, 2, 3
+	a, b, c = 1 /* ERROR "assignment count mismatch" */ , 2
+	a, b, c = 1 /* ERROR "assignment count mismatch" */ , 2, 3, 4
+	_, _, _ = a, b, c
+
+	a = f0 /* ERROR "used as value" */ ()
+	a = f1()
+	a = f2 /* ERROR "assignment count mismatch" */ ()
+	a, b = f2()
+	a, b, c = f2 /* ERROR "assignment count mismatch" */ ()
+	a, b, c = f3()
+	a, b = f3 /* ERROR "assignment count mismatch" */ ()
+
+	a, b, c = <- /* ERROR "assignment count mismatch" */ ch
+
+	return /* ERROR "wrong number of return values" */
+	return /* ERROR "wrong number of return values" */ 1
+	return 1, 2
+	return /* ERROR "wrong number of return values" */ 1, 2, 3
+}
+
+func assignments1() {
+	b, i, f, c, s := false, 1, 1.0, 1i, "foo"
+	b = i /* ERROR "cannot assign" */
+	i = f /* ERROR "cannot assign" */
+	f = c /* ERROR "cannot assign" */
+	c = s /* ERROR "cannot assign" */
+	s = b /* ERROR "cannot assign" */
+
+	v0, v1, v2 := 1 /* ERROR "mismatch" */ , 2, 3, 4
+	_, _, _ = v0, v1, v2
+
+	b = true
+
+	i += 1
+	i += "foo" /* ERROR "cannot convert.*int" */
+
+	f -= 1
+	f /= 0
+	f = float32(0)/0 /* ERROR "division by zero" */
+	f -= "foo" /* ERROR "cannot convert.*float64" */
+
+	c *= 1
+	c /= 0
+
+	s += "bar"
+	s += 1 /* ERROR "cannot convert.*string" */
+
+	var u64 uint64
+	u64 += 1<<u64
+
+	undeclared /* ERROR "undeclared" */ = 991
+
+	// test cases for issue 5800
+	var (
+		_ int = nil /* ERROR "untyped nil value" */
+		_ [10]int = nil /* ERROR "untyped nil value" */
+		_ []byte = nil
+		_ struct{} = nil /* ERROR "untyped nil value" */
+		_ func() = nil
+		_ map[int]string = nil
+		_ chan int = nil
+	)
+
+	// test cases for issue 5500
+	_ = func() (int, bool) {
+		var m map[int]int
+		return /* ERROR "wrong number of return values" */ m[0]
+	}
+
+	g := func(int, bool){}
+	var m map[int]int
+	g(m[0]) /* ERROR "too few arguments" */
+
+	// assignments to _
+	_ = nil /* ERROR "use of untyped nil" */
+	_ = 1 /* ERROR overflow */ <<1000
+	(_) = 0
+}
+
+func assignments2() {
+	type mybool bool
+	var m map[string][]bool
+	var s []bool
+	var b bool
+	var d mybool
+	_ = s
+	_ = b
+	_ = d
+
+	// assignments to map index expressions are ok
+	s, b = m["foo"]
+	_, d = m["bar"]
+	m["foo"] = nil
+	m["foo"] = nil /* ERROR assignment count mismatch */ , false
+	_ = append(m["foo"])
+	_ = append(m["foo"], true)
+
+	var c chan int
+	_, b = <-c
+	_, d = <-c
+	<- /* ERROR cannot assign */ c = 0
+	<-c = 0 /* ERROR assignment count mismatch */ , false
+
+	var x interface{}
+	_, b = x.(int)
+	x /* ERROR cannot assign */ .(int) = 0
+	x.(int) = 0 /* ERROR assignment count mismatch */ , false
+
+	assignments2 /* ERROR used as value */ () = nil
+	int /* ERROR not an expression */ = 0
+}
+
+func issue6487() {
+	type S struct{x int}
+	_ = &S /* ERROR "cannot take address" */ {}.x
+	_ = &( /* ERROR "cannot take address" */ S{}.x)
+	_ = (&S{}).x
+	S /* ERROR "cannot assign" */ {}.x = 0
+	(&S{}).x = 0
+
+	type M map[string]S
+	var m M
+	m /* ERROR "cannot assign" */ ["foo"].x = 0
+	_ = &( /* ERROR "cannot take address" */ m["foo"].x)
+	_ = &m /* ERROR "cannot take address" */ ["foo"].x
+}
+
+func issue6766a() {
+	a, a /* ERROR redeclared */ := 1, 2
+	_ = a
+	a, b, b /* ERROR redeclared */ := 1, 2, 3
+	_ = b
+	c, c /* ERROR redeclared */, b := 1, 2, 3
+	_ = c
+	a, b := /* ERROR no new variables */ 1, 2
+}
+
+func shortVarDecls1() {
+	const c = 0
+	type d int
+	a, b, c /* ERROR "cannot assign" */ , d /* ERROR "cannot assign" */  := 1, "zwei", 3.0, 4
+	var _ int = a // a is of type int
+	var _ string = b // b is of type string
+}
+
+func incdecs() {
+	const c = 3.14
+	c /* ERROR "cannot assign" */ ++
+	s := "foo"
+	s /* ERROR "cannot convert" */ --
+	3.14 /* ERROR "cannot assign" */ ++
+	var (
+		x int
+		y float32
+		z complex128
+	)
+	x++
+	y--
+	z++
+}
+
+func sends() {
+	var ch chan int
+	var rch <-chan int
+	var x int
+	x /* ERROR "cannot send" */ <- x
+	rch /* ERROR "cannot send" */ <- x
+	ch <- "foo" /* ERROR "cannot convert" */
+	ch <- x
+}
+
+func selects() {
+	select {}
+	var (
+		ch chan int
+		sc chan <- bool
+	)
+	select {
+	case <-ch:
+	case (<-ch):
+	case t := <-ch:
+		_ = t
+	case t := (<-ch):
+		_ = t
+	case t, ok := <-ch:
+		_, _ = t, ok
+	case t, ok := (<-ch):
+		_, _ = t, ok
+	case <-sc /* ERROR "cannot receive from send-only channel" */ :
+	}
+	select {
+	default:
+	default /* ERROR "multiple defaults" */ :
+	}
+	select {
+	case a, b := <-ch:
+		_, b = a, b
+	case x /* ERROR send or receive */ :
+	case a /* ERROR send or receive */ := ch:
+	}
+
+	// test for issue 9570: ch2 in second case falsely resolved to
+	// ch2 declared in body of first case
+	ch1 := make(chan int)
+	ch2 := make(chan int)
+	select {
+	case <-ch1:
+		var ch2 /* ERROR ch2 declared but not used */ chan bool
+	case i := <-ch2:
+		print(i + 1)
+	}
+}
+
+func gos() {
+	go 1 /* ERROR HERE "function must be invoked" */
+	go int /* ERROR "go requires function call, not conversion" */ (0)
+	go gos()
+	var c chan int
+	go close(c)
+	go len /* ERROR "go discards result" */ (c)
+}
+
+func defers() {
+	defer 1 /* ERROR HERE "function must be invoked" */
+	defer int /* ERROR "defer requires function call, not conversion" */ (0)
+	defer defers()
+	var c chan int
+	defer close(c)
+	defer len /* ERROR "defer discards result" */ (c)
+}
+
+func breaks() {
+	var x, y int
+
+	break /* ERROR "break" */
+	{
+		break /* ERROR "break" */
+	}
+	if x < y {
+		break /* ERROR "break" */
+	}
+
+	switch x {
+	case 0:
+		break
+	case 1:
+		if x == y {
+			break
+		}
+	default:
+		break
+		break
+	}
+
+	var z interface{}
+	switch z.(type) {
+	case int:
+		break
+	}
+
+	for {
+		break
+	}
+
+	var a []int
+	for _ = range a {
+		break
+	}
+
+	for {
+		if x == y {
+			break
+		}
+	}
+
+	var ch chan int
+	select {
+	case <-ch:
+		break
+	}
+
+	select {
+	case <-ch:
+		if x == y {
+			break
+		}
+	default:
+		break
+	}
+}
+
+func continues() {
+	var x, y int
+
+	continue /* ERROR "continue" */
+	{
+		continue /* ERROR "continue" */
+	}
+
+	if x < y {
+		continue /* ERROR "continue" */
+	}
+
+	switch x {
+	case 0:
+		continue /* ERROR "continue" */
+	}
+
+	var z interface{}
+	switch z.(type) {
+	case int:
+		continue /* ERROR "continue" */
+	}
+
+	var ch chan int
+	select {
+	case <-ch:
+		continue /* ERROR "continue" */
+	}
+
+	for i := 0; i < 10; i++ {
+		continue
+		if x < y {
+			continue
+			break
+		}
+		switch x {
+		case y:
+			continue
+		default:
+			break
+		}
+		select {
+		case <-ch:
+			continue
+		}
+	}
+
+	var a []int
+	for _ = range a {
+		continue
+		if x < y {
+			continue
+			break
+		}
+		switch x {
+		case y:
+			continue
+		default:
+			break
+		}
+		select {
+		case <-ch:
+			continue
+		}
+	}
+}
+
+func returns0() {
+	return
+	return 0 /* ERROR no result values expected */
+}
+
+func returns1(x float64) (int, *float64) {
+	return 0, &x
+	return /* ERROR wrong number of return values */
+	return "foo" /* ERROR "cannot convert" */, x /* ERROR "cannot return" */
+	return /* ERROR wrong number of return values */ 0, &x, 1
+}
+
+func returns2() (a, b int) {
+	return
+	return 1, "foo" /* ERROR cannot convert */
+	return /* ERROR wrong number of return values */ 1, 2, 3
+	{
+		type a int
+		return 1, 2
+		return /* ERROR a not in scope at return */
+	}
+}
+
+func returns3() (_ int) {
+	return
+	{
+		var _ int // blank (_) identifiers never shadow since they are in no scope
+		return
+	}
+}
+
+func switches0() {
+	var x int
+
+	switch x {
+	}
+
+	switch x {
+	default:
+	default /* ERROR "multiple defaults" */ :
+	}
+
+	switch {
+	case 1  /* ERROR "cannot convert" */ :
+	}
+
+	true := "false"
+	_ = true
+	// A tagless switch is equivalent to the bool 
+        // constant true, not the identifier 'true'.
+	switch {
+	case "false" /* ERROR "cannot convert" */:
+	}
+
+	switch int32(x) {
+	case 1, 2:
+	case x /* ERROR "cannot compare" */ :
+	}
+
+	switch x {
+	case 1 /* ERROR "overflows" */ << 100:
+	}
+
+	switch x {
+	case 1:
+	case 1 /* DISABLED "duplicate case" */ :
+	case 2, 3, 4:
+	case 1 /* DISABLED "duplicate case" */ :
+	}
+
+	switch uint64(x) {
+	case 1 /* DISABLED duplicate case */ <<64-1:
+	case 1 /* DISABLED duplicate case */ <<64-1:
+	}
+}
+
+func switches1() {
+	fallthrough /* ERROR "fallthrough statement out of place" */
+
+	var x int
+	switch x {
+	case 0:
+		fallthrough /* ERROR "fallthrough statement out of place" */
+		break
+	case 1:
+		fallthrough
+	case 2:
+	default:
+		fallthrough
+	case 3:
+		fallthrough /* ERROR "fallthrough statement out of place" */
+	}
+
+	var y interface{}
+	switch y.(type) {
+	case int:
+		fallthrough /* ERROR "fallthrough statement out of place" */
+	default:
+	}
+
+	switch x {
+	case 0:
+		if x == 0 {
+			fallthrough /* ERROR "fallthrough statement out of place" */
+		}
+	}
+
+	switch x {
+	case 0:
+		goto L1
+		L1: fallthrough
+	case 1:
+		goto L2
+		goto L3
+		goto L4
+		L2: L3: L4: fallthrough
+	default:
+	}
+
+	switch x {
+	case 0:
+		goto L5
+		L5: fallthrough
+	default:
+		goto L6
+		goto L7
+		goto L8
+		L6: L7: L8: fallthrough /* ERROR "fallthrough statement out of place" */
+	}
+
+	switch x {
+	case 0:
+		{
+			fallthrough /* ERROR "fallthrough statement out of place" */
+		}
+	default:
+	}
+}
+
+type I interface {
+	m()
+}
+
+type I2 interface {
+	m(int)
+}
+
+type T struct{}
+type T1 struct{}
+type T2 struct{}
+
+func (T) m() {}
+func (T2) m(int) {}
+
+func typeswitches() {
+	var i int
+	var x interface{}
+
+	switch x.(type) {}
+	switch (x /* ERROR "outside type switch" */ .(type)) {}
+
+	switch x.(type) {
+	default:
+	default /* ERROR "multiple defaults" */ :
+	}
+
+	switch x /* ERROR "declared but not used" */ := x.(type) {}
+	switch _ /* ERROR "no new variable on left side of :=" */ := x.(type) {}
+
+	switch x := x.(type) {
+	case int:
+		var y int = x
+		_ = y
+	}
+
+	switch x := i /* ERROR "not an interface" */ .(type) {}
+
+	switch t := x.(type) {
+	case nil:
+		var v bool = t /* ERROR "cannot initialize" */
+		_ = v
+	case int:
+		var v int = t
+		_ = v
+	case float32, complex64:
+		var v float32 = t /* ERROR "cannot initialize" */
+		_ = v
+	default:
+		var v float32 = t /* ERROR "cannot initialize" */
+		_ = v
+	}
+
+	var t I
+	switch t.(type) {
+	case T:
+	case T1 /* ERROR "missing method m" */ :
+	case T2 /* ERROR "wrong type for method m" */ :
+	case I2 /* STRICT "wrong type for method m" */ : // only an error in strict mode (issue 8561)
+	}
+}
+
+// Test that each case clause uses the correct type of the variable
+// declared by the type switch (issue 5504).
+func typeswitch0() {
+	switch y := interface{}(nil).(type) {
+	case int:
+		func() int { return y + 0 }()
+	case float32:
+		func() float32 { return y }()
+	}
+}
+
+// Test correct scope setup.
+// (no redeclaration errors expected in the type switch)
+func typeswitch1() {
+	var t I
+	switch t := t; t := t.(type) {
+	case nil:
+		var _ I = t
+	case T:
+		var _ T = t
+	default:
+		var _ I = t
+	}
+}
+
+// Test correct typeswitch against interface types.
+type A interface { a() }
+type B interface { b() }
+type C interface { a(int) }
+
+func typeswitch2() {
+	switch A(nil).(type) {
+	case A:
+	case B:
+	case C /* STRICT "cannot have dynamic type" */: // only an error in strict mode (issue 8561)
+	}
+}
+
+func typeswitch3(x interface{}) {
+	switch x.(type) {
+	case int:
+	case float64:
+	case int /* ERROR duplicate case */ :
+	}
+
+	switch x.(type) {
+	case nil:
+	case int:
+	case nil /* ERROR duplicate case */ , nil /* ERROR duplicate case */ :
+	}
+
+	type F func(int)
+	switch x.(type) {
+	case nil:
+	case int, func(int):
+	case float32, func /* ERROR duplicate case */ (x int):
+	case F:
+	}
+}
+
+func fors1() {
+	for {}
+	var i string
+	_ = i
+	for i := 0; i < 10; i++ {}
+	for i := 0; i < 10; j /* ERROR cannot declare */ := 0 {}
+}
+
+func rangeloops1() {
+	var (
+		x int
+		a [10]float32
+		b []string
+		p *[10]complex128
+		pp **[10]complex128
+		s string
+		m map[int]bool
+		c chan int
+		sc chan<- int
+		rc <-chan int
+	)
+
+	for range x /* ERROR "cannot range over" */ {}
+	for _ = range x /* ERROR "cannot range over" */ {}
+	for i := range x /* ERROR "cannot range over" */ {}
+
+	for range a {}
+	for i := range a {
+		var ii int
+		ii = i
+		_ = ii
+	}
+	for i, x := range a {
+		var ii int
+		ii = i
+		_ = ii
+		var xx float64
+		xx = x /* ERROR "cannot assign" */
+		_ = xx
+	}
+	var ii int
+	var xx float32
+	for ii, xx = range a {}
+	_, _ = ii, xx
+
+	for range b {}
+	for i := range b {
+		var ii int
+		ii = i
+		_ = ii
+	}
+	for i, x := range b {
+		var ii int
+		ii = i
+		_ = ii
+		var xx string
+		xx = x
+		_ = xx
+	}
+
+	for range s {}
+	for i := range s {
+		var ii int
+		ii = i
+		_ = ii
+	}
+	for i, x := range s {
+		var ii int
+		ii = i
+		_ = ii
+		var xx rune
+		xx = x
+		_ = xx
+	}
+
+	for range p {}
+	for _, x := range p {
+		var xx complex128
+		xx = x
+		_ = xx
+	}
+
+	for range pp /* ERROR "cannot range over" */ {}
+	for _, x := range pp /* ERROR "cannot range over" */ {}
+
+	for range m {}
+	for k := range m {
+		var kk int32
+		kk = k /* ERROR "cannot assign" */
+		_ = kk
+	}
+	for k, v := range m {
+		var kk int
+		kk = k
+		_ = kk
+		if v {}
+	}
+
+	for range c {}
+	for _, _ /* ERROR "only one iteration variable" */ = range c {}
+	for e := range c {
+		var ee int
+		ee = e
+		_ = ee
+	}
+	for _ = range sc /* ERROR "cannot range over send-only channel" */ {}
+	for _ = range rc {}
+
+	// constant strings
+	const cs = "foo"
+	for range cs {}
+	for range "" {}
+	for i, x := range cs { _, _ = i, x }
+	for i, x := range "" {
+		var ii int
+		ii = i
+		_ = ii
+		var xx rune
+		xx = x
+		_ = xx
+	}
+}
+
+func rangeloops2() {
+	type I int
+	type R rune
+
+	var a [10]int
+	var i I
+	_ = i
+	for i /* ERROR cannot assign */ = range a {}
+	for i /* ERROR cannot assign */ = range &a {}
+	for i /* ERROR cannot assign */ = range a[:] {}
+
+	var s string
+	var r R
+	_ = r
+	for i /* ERROR cannot assign */ = range s {}
+	for i /* ERROR cannot assign */ = range "foo" {}
+	for _, r /* ERROR cannot assign */ = range s {}
+	for _, r /* ERROR cannot assign */ = range "foo" {}
+}
+
+func issue6766b() {
+	for _ := /* ERROR no new variables */ range "" {}
+	for a, a /* ERROR redeclared */ := range "" { _ = a }
+	var a int
+	_ = a
+	for a, a /* ERROR redeclared */ := range []int{1, 2, 3} { _ = a }
+}
+
+// Test that despite errors in the range clause,
+// the loop body is still type-checked (and thus
+// errors reported).
+func issue10148() {
+	for y /* ERROR declared but not used */ := range "" {
+		_ = "" /* ERROR cannot convert */ + 1
+	}
+	for range 1 /* ERROR cannot range over 1 */ {
+		_ = "" /* ERROR cannot convert */ + 1
+	}
+	for y := range 1 /* ERROR cannot range over 1 */ {
+		_ = "" /* ERROR cannot convert */ + 1
+	}
+}
+
+func labels0() {
+	goto L0
+	goto L1
+	L0:
+	L1:
+	L1 /* ERROR "already declared" */ :
+	if true {
+		goto L2		
+		L2:
+		L0 /* ERROR "already declared" */ :
+	}
+	_ = func() {
+		goto L0
+		goto L1
+		goto L2
+		L0:
+		L1:
+		L2:
+	}
+}
+
+func expression_statements(ch chan int) {
+	expression_statements(ch)
+	<-ch
+	println()
+
+	0 /* ERROR "not used" */
+	1 /* ERROR "not used" */ +2
+	cap /* ERROR "not used" */ (ch)
+	println /* ERROR "must be called" */
+}
diff --git a/go/types/testdata/stmt1.src b/go/types/testdata/stmt1.src
new file mode 100644
index 0000000..a2955e6
--- /dev/null
+++ b/go/types/testdata/stmt1.src
@@ -0,0 +1,165 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// terminating statements
+
+package stmt1
+
+func _() {}
+
+func _() int {} /* ERROR "missing return" */
+
+func _() int { panic(0) }
+func _() int { (panic(0)) }
+
+// block statements
+func _(x, y int) (z int) {
+	{
+		return
+	}
+}
+
+func _(x, y int) (z int) {
+	{
+	}
+} /* ERROR "missing return" */
+
+// if statements
+func _(x, y int) (z int) {
+	if x < y { return }
+	return 1
+}
+
+func _(x, y int) (z int) {
+	if x < y { return }
+} /* ERROR "missing return" */
+
+func _(x, y int) (z int) {
+	if x < y {
+	} else { return 1
+	}
+} /* ERROR "missing return" */
+
+func _(x, y int) (z int) {
+	if x < y { return
+	} else { return
+	}
+}
+
+// for statements
+func _(x, y int) (z int) {
+	for x < y {
+		return
+	}
+} /* ERROR "missing return" */
+
+func _(x, y int) (z int) {
+	for {
+		return
+	}
+}
+
+func _(x, y int) (z int) {
+	for {
+		return
+		break
+	}
+} /* ERROR "missing return" */
+
+func _(x, y int) (z int) {
+	for {
+		for { break }
+		return
+	}
+}
+
+func _(x, y int) (z int) {
+L:	for {
+		for { break L }
+		return
+	}
+} /* ERROR "missing return" */
+
+// switch statements
+func _(x, y int) (z int) {
+	switch x {
+	case 0: return
+	default: return
+	}
+}
+
+func _(x, y int) (z int) {
+	switch x {
+	case 0: return
+	}
+} /* ERROR "missing return" */
+
+func _(x, y int) (z int) {
+	switch x {
+	case 0: return
+	case 1: break
+	}
+} /* ERROR "missing return" */
+
+func _(x, y int) (z int) {
+	switch x {
+	case 0: return
+	default:
+		switch y {
+		case 0: break
+		}
+		panic(0)
+	}
+}
+
+func _(x, y int) (z int) {
+L:	switch x {
+	case 0: return
+	default:
+		switch y {
+		case 0: break L
+		}
+		panic(0)
+	}
+} /* ERROR "missing return" */
+
+// select statements
+func _(ch chan int) (z int) {
+	select {}
+} // nice!
+
+func _(ch chan int) (z int) {
+	select {
+	default: break
+	}
+} /* ERROR "missing return" */
+
+func _(ch chan int) (z int) {
+	select {
+	case <-ch: return
+	default: break
+	}
+} /* ERROR "missing return" */
+
+func _(ch chan int) (z int) {
+	select {
+	case <-ch: return
+	default:
+		for i := 0; i < 10; i++ {
+			break
+		}
+		return
+	}
+}
+
+func _(ch chan int) (z int) {
+L:	select {
+	case <-ch: return
+	default:
+		for i := 0; i < 10; i++ {
+			break L
+		}
+		return
+	}
+} /* ERROR "missing return" */
diff --git a/go/types/testdata/vardecl.src b/go/types/testdata/vardecl.src
new file mode 100644
index 0000000..fb6b5f7
--- /dev/null
+++ b/go/types/testdata/vardecl.src
@@ -0,0 +1,186 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package vardecl
+
+// Prerequisites.
+import "math"
+func f() {}
+func g() (x, y int) { return }
+var m map[string]int
+
+// Var decls must have a type or an initializer.
+var _ int
+var _, _ int
+
+// The first error message is produced by the parser.
+// In a real-world scenario, the type-checker would not be run
+// in this case and the 2nd error message would not appear.
+var _ /* ERROR "missing variable type" */ /* ERROR "missing type or init expr" */
+var _ /* ERROR "missing variable type" */ /* ERROR "missing type or init expr" */, _
+var _ /* ERROR "missing variable type" */ /* ERROR "missing type or init expr" */, _, _
+
+// The initializer must be an expression.
+var _ = int /* ERROR "not an expression" */
+var _ = f /* ERROR "used as value" */ ()
+
+// Identifier and expression arity must match.
+var _, _ = 1, 2
+var _ = 1, 2 /* ERROR "extra init expr 2" */
+var _, _ = 1 /* ERROR "assignment count mismatch" */
+var _, _, _ /* ERROR "missing init expr for _" */ = 1, 2
+
+var _ = g /* ERROR "2-valued expr" */ ()
+var _, _ = g()
+var _, _, _ = g /* ERROR "assignment count mismatch" */ ()
+
+var _ = m["foo"]
+var _, _ = m["foo"]
+var _, _, _ = m  /* ERROR "assignment count mismatch" */ ["foo"]
+
+var _, _ int = 1, 2
+var _ int = 1, 2 /* ERROR "extra init expr 2" */
+var _, _ int = 1 /* ERROR "assignment count mismatch" */
+var _, _, _ /* ERROR "missing init expr for _" */ int = 1, 2
+
+var (
+	_, _ = 1, 2
+	_ = 1, 2 /* ERROR "extra init expr 2" */
+	_, _ = 1 /* ERROR "assignment count mismatch" */
+	_, _, _ /* ERROR "missing init expr for _" */ = 1, 2
+
+	_ = g /* ERROR "2-valued expr" */ ()
+	_, _ = g()
+	_, _, _ = g /* ERROR "assignment count mismatch" */ ()
+
+	_ = m["foo"]
+	_, _ = m["foo"]
+	_, _, _ = m /* ERROR "assignment count mismatch" */ ["foo"]
+
+	_, _ int = 1, 2
+	_ int = 1, 2 /* ERROR "extra init expr 2" */
+	_, _ int = 1 /* ERROR "assignment count mismatch" */
+	_, _, _ /* ERROR "missing init expr for _" */ int = 1, 2
+)
+
+// Variables declared in function bodies must be 'used'.
+type T struct{}
+func (r T) _(a, b, c int) (u, v, w int) {
+	var x1 /* ERROR "declared but not used" */ int
+	var x2 /* ERROR "declared but not used" */ int
+	x1 = 1
+	(x2) = 2
+
+	y1 /* ERROR "declared but not used" */ := 1
+	y2 /* ERROR "declared but not used" */ := 2
+	y1 = 1
+	(y1) = 2
+
+	{
+		var x1 /* ERROR "declared but not used" */ int
+		var x2 /* ERROR "declared but not used" */ int
+		x1 = 1
+		(x2) = 2
+
+		y1 /* ERROR "declared but not used" */ := 1
+		y2 /* ERROR "declared but not used" */ := 2
+		y1 = 1
+		(y1) = 2
+	}
+
+	if x /* ERROR "declared but not used" */ := 0; a < b {}
+
+	switch x /* ERROR "declared but not used" */, y := 0, 1; a {
+	case 0:
+		_ = y
+	case 1:
+		x /* ERROR "declared but not used" */ := 0
+	}
+
+	var t interface{}
+	switch t /* ERROR "declared but not used" */ := t.(type) {}
+
+	switch t /* ERROR "declared but not used" */ := t.(type) {
+	case int:
+	}
+
+	switch t /* ERROR "declared but not used" */ := t.(type) {
+	case int:
+	case float32, complex64:
+		t = nil
+	}
+
+	switch t := t.(type) {
+	case int:
+	case float32, complex64:
+		_ = t
+	}
+
+	switch t := t.(type) {
+	case int:
+	case float32:
+	case string:
+		_ = func() string {
+			return t
+		}
+	}
+
+	switch t := t; t /* ERROR "declared but not used" */ := t.(type) {}
+
+	var z1 /* ERROR "declared but not used" */ int
+	var z2 int
+	_ = func(a, b, c int) (u, v, w int) {
+		z1 = a
+		(z1) = b
+		a = z2
+		return
+	}
+
+	var s []int
+	var i /* ERROR "declared but not used" */ , j int
+	for i, j = range s {
+		_ = j
+	}
+
+	for i, j /* ERROR "declared but not used" */ := range s {
+		_ = func() int {
+			return i
+		}
+	}
+	return
+}
+
+// Invalid (unused) expressions must not lead to spurious "declared but not used errors"
+func _() {
+	var a, b, c int
+	var x, y int
+	x, y = a /* ERROR assignment count mismatch */ , b, c
+	_ = x
+	_ = y
+}
+
+func _() {
+	var x int
+	return x /* ERROR no result values expected */
+	return math /* ERROR no result values expected */ .Sin(0)
+}
+
+func _() int {
+	var x, y int
+	return /* ERROR wrong number of return values */ x, y
+}
+
+// Short variable declarations must declare at least one new non-blank variable.
+func _() {
+	_ := /* ERROR no new variables */ 0
+	_, a := 0, 1
+	_, a := /* ERROR no new variables */ 0, 1
+	_, a, b := 0, 1, 2
+	_, _, _ := /* ERROR no new variables */ 0, 1, 2
+
+	_ = a
+	_ = b
+}
+
+// TODO(gri) consolidate other var decl checks in this file
\ No newline at end of file
diff --git a/go/types/token_test.go b/go/types/token_test.go
new file mode 100644
index 0000000..705bb29
--- /dev/null
+++ b/go/types/token_test.go
@@ -0,0 +1,47 @@
+// Copyright 2013 The Go 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 checks invariants of token.Token ordering that we rely on
+// since package go/token doesn't provide any guarantees at the moment.
+
+package types
+
+import (
+	"go/token"
+	"testing"
+)
+
+var assignOps = map[token.Token]token.Token{
+	token.ADD_ASSIGN:     token.ADD,
+	token.SUB_ASSIGN:     token.SUB,
+	token.MUL_ASSIGN:     token.MUL,
+	token.QUO_ASSIGN:     token.QUO,
+	token.REM_ASSIGN:     token.REM,
+	token.AND_ASSIGN:     token.AND,
+	token.OR_ASSIGN:      token.OR,
+	token.XOR_ASSIGN:     token.XOR,
+	token.SHL_ASSIGN:     token.SHL,
+	token.SHR_ASSIGN:     token.SHR,
+	token.AND_NOT_ASSIGN: token.AND_NOT,
+}
+
+func TestZeroTok(t *testing.T) {
+	// zero value for token.Token must be token.ILLEGAL
+	var zero token.Token
+	if token.ILLEGAL != zero {
+		t.Errorf("%s == %d; want 0", token.ILLEGAL, zero)
+	}
+}
+
+func TestAssignOp(t *testing.T) {
+	// there are fewer than 256 tokens
+	for i := 0; i < 256; i++ {
+		tok := token.Token(i)
+		got := assignOp(tok)
+		want := assignOps[tok]
+		if got != want {
+			t.Errorf("for assignOp(%s): got %s; want %s", tok, got, want)
+		}
+	}
+}
diff --git a/go/types/type.go b/go/types/type.go
new file mode 100644
index 0000000..1df8b45
--- /dev/null
+++ b/go/types/type.go
@@ -0,0 +1,454 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package types
+
+import "sort"
+
+// TODO(gri) Revisit factory functions - make sure they have all relevant parameters.
+
+// A Type represents a type of Go.
+// All types implement the Type interface.
+type Type interface {
+	// Underlying returns the underlying type of a type.
+	Underlying() Type
+
+	// String returns a string representation of a type.
+	String() string
+}
+
+// BasicKind describes the kind of basic type.
+type BasicKind int
+
+const (
+	Invalid BasicKind = iota // type is invalid
+
+	// predeclared types
+	Bool
+	Int
+	Int8
+	Int16
+	Int32
+	Int64
+	Uint
+	Uint8
+	Uint16
+	Uint32
+	Uint64
+	Uintptr
+	Float32
+	Float64
+	Complex64
+	Complex128
+	String
+	UnsafePointer
+
+	// types for untyped values
+	UntypedBool
+	UntypedInt
+	UntypedRune
+	UntypedFloat
+	UntypedComplex
+	UntypedString
+	UntypedNil
+
+	// aliases
+	Byte = Uint8
+	Rune = Int32
+)
+
+// BasicInfo is a set of flags describing properties of a basic type.
+type BasicInfo int
+
+// Properties of basic types.
+const (
+	IsBoolean BasicInfo = 1 << iota
+	IsInteger
+	IsUnsigned
+	IsFloat
+	IsComplex
+	IsString
+	IsUntyped
+
+	IsOrdered   = IsInteger | IsFloat | IsString
+	IsNumeric   = IsInteger | IsFloat | IsComplex
+	IsConstType = IsBoolean | IsNumeric | IsString
+)
+
+// A Basic represents a basic type.
+type Basic struct {
+	kind BasicKind
+	info BasicInfo
+	name string
+}
+
+// Kind returns the kind of basic type b.
+func (b *Basic) Kind() BasicKind { return b.kind }
+
+// Info returns information about properties of basic type b.
+func (b *Basic) Info() BasicInfo { return b.info }
+
+// Name returns the name of basic type b.
+func (b *Basic) Name() string { return b.name }
+
+// An Array represents an array type.
+type Array struct {
+	len  int64
+	elem Type
+}
+
+// NewArray returns a new array type for the given element type and length.
+func NewArray(elem Type, len int64) *Array { return &Array{len, elem} }
+
+// Len returns the length of array a.
+func (a *Array) Len() int64 { return a.len }
+
+// Elem returns element type of array a.
+func (a *Array) Elem() Type { return a.elem }
+
+// A Slice represents a slice type.
+type Slice struct {
+	elem Type
+}
+
+// NewSlice returns a new slice type for the given element type.
+func NewSlice(elem Type) *Slice { return &Slice{elem} }
+
+// Elem returns the element type of slice s.
+func (s *Slice) Elem() Type { return s.elem }
+
+// A Struct represents a struct type.
+type Struct struct {
+	fields []*Var
+	tags   []string // field tags; nil if there are no tags
+	// TODO(gri) access to offsets is not threadsafe - fix this
+	offsets []int64 // field offsets in bytes, lazily initialized
+}
+
+// NewStruct returns a new struct with the given fields and corresponding field tags.
+// If a field with index i has a tag, tags[i] must be that tag, but len(tags) may be
+// only as long as required to hold the tag with the largest index i. Consequently,
+// if no field has a tag, tags may be nil.
+func NewStruct(fields []*Var, tags []string) *Struct {
+	var fset objset
+	for _, f := range fields {
+		if f.name != "_" && fset.insert(f) != nil {
+			panic("multiple fields with the same name")
+		}
+	}
+	if len(tags) > len(fields) {
+		panic("more tags than fields")
+	}
+	return &Struct{fields: fields, tags: tags}
+}
+
+// NumFields returns the number of fields in the struct (including blank and anonymous fields).
+func (s *Struct) NumFields() int { return len(s.fields) }
+
+// Field returns the i'th field for 0 <= i < NumFields().
+func (s *Struct) Field(i int) *Var { return s.fields[i] }
+
+// Tag returns the i'th field tag for 0 <= i < NumFields().
+func (s *Struct) Tag(i int) string {
+	if i < len(s.tags) {
+		return s.tags[i]
+	}
+	return ""
+}
+
+// A Pointer represents a pointer type.
+type Pointer struct {
+	base Type // element type
+}
+
+// NewPointer returns a new pointer type for the given element (base) type.
+func NewPointer(elem Type) *Pointer { return &Pointer{base: elem} }
+
+// Elem returns the element type for the given pointer p.
+func (p *Pointer) Elem() Type { return p.base }
+
+// A Tuple represents an ordered list of variables; a nil *Tuple is a valid (empty) tuple.
+// Tuples are used as components of signatures and to represent the type of multiple
+// assignments; they are not first class types of Go.
+type Tuple struct {
+	vars []*Var
+}
+
+// NewTuple returns a new tuple for the given variables.
+func NewTuple(x ...*Var) *Tuple {
+	if len(x) > 0 {
+		return &Tuple{x}
+	}
+	return nil
+}
+
+// Len returns the number variables of tuple t.
+func (t *Tuple) Len() int {
+	if t != nil {
+		return len(t.vars)
+	}
+	return 0
+}
+
+// At returns the i'th variable of tuple t.
+func (t *Tuple) At(i int) *Var { return t.vars[i] }
+
+// A Signature represents a (non-builtin) function or method type.
+type Signature struct {
+	// We need to keep the scope in Signature (rather than passing it around
+	// and store it in the Func Object) because when type-checking a function
+	// literal we call the general type checker which returns a general Type.
+	// We then unpack the *Signature and use the scope for the literal body.
+	scope    *Scope // function scope, present for package-local signatures
+	recv     *Var   // nil if not a method
+	params   *Tuple // (incoming) parameters from left to right; or nil
+	results  *Tuple // (outgoing) results from left to right; or nil
+	variadic bool   // true if the last parameter's type is of the form ...T (or string, for append built-in only)
+}
+
+// NewSignature returns a new function type for the given receiver, parameters,
+// and results, either of which may be nil. If variadic is set, the function
+// is variadic, it must have at least one parameter, and the last parameter
+// must be of unnamed slice type.
+func NewSignature(recv *Var, params, results *Tuple, variadic bool) *Signature {
+	if variadic {
+		n := params.Len()
+		if n == 0 {
+			panic("types.NewSignature: variadic function must have at least one parameter")
+		}
+		if _, ok := params.At(n - 1).typ.(*Slice); !ok {
+			panic("types.NewSignature: variadic parameter must be of unnamed slice type")
+		}
+	}
+	return &Signature{nil, recv, params, results, variadic}
+}
+
+// Recv returns the receiver of signature s (if a method), or nil if a
+// function.
+//
+// For an abstract method, Recv returns the enclosing interface either
+// as a *Named or an *Interface.  Due to embedding, an interface may
+// contain methods whose receiver type is a different interface.
+func (s *Signature) Recv() *Var { return s.recv }
+
+// Params returns the parameters of signature s, or nil.
+func (s *Signature) Params() *Tuple { return s.params }
+
+// Results returns the results of signature s, or nil.
+func (s *Signature) Results() *Tuple { return s.results }
+
+// Variadic reports whether the signature s is variadic.
+func (s *Signature) Variadic() bool { return s.variadic }
+
+// An Interface represents an interface type.
+type Interface struct {
+	methods   []*Func  // ordered list of explicitly declared methods
+	embeddeds []*Named // ordered list of explicitly embedded types
+
+	allMethods []*Func // ordered list of methods declared with or embedded in this interface (TODO(gri): replace with mset)
+}
+
+// NewInterface returns a new interface for the given methods and embedded types.
+func NewInterface(methods []*Func, embeddeds []*Named) *Interface {
+	typ := new(Interface)
+
+	var mset objset
+	for _, m := range methods {
+		if mset.insert(m) != nil {
+			panic("multiple methods with the same name")
+		}
+		// set receiver
+		// TODO(gri) Ideally, we should use a named type here instead of
+		// typ, for less verbose printing of interface method signatures.
+		m.typ.(*Signature).recv = NewVar(m.pos, m.pkg, "", typ)
+	}
+	sort.Sort(byUniqueMethodName(methods))
+
+	if embeddeds == nil {
+		sort.Sort(byUniqueTypeName(embeddeds))
+	}
+
+	typ.methods = methods
+	typ.embeddeds = embeddeds
+	return typ
+}
+
+// NumExplicitMethods returns the number of explicitly declared methods of interface t.
+func (t *Interface) NumExplicitMethods() int { return len(t.methods) }
+
+// ExplicitMethod returns the i'th explicitly declared method of interface t for 0 <= i < t.NumExplicitMethods().
+// The methods are ordered by their unique Id.
+func (t *Interface) ExplicitMethod(i int) *Func { return t.methods[i] }
+
+// NumEmbeddeds returns the number of embedded types in interface t.
+func (t *Interface) NumEmbeddeds() int { return len(t.embeddeds) }
+
+// Embedded returns the i'th embedded type of interface t for 0 <= i < t.NumEmbeddeds().
+// The types are ordered by the corresponding TypeName's unique Id.
+func (t *Interface) Embedded(i int) *Named { return t.embeddeds[i] }
+
+// NumMethods returns the total number of methods of interface t.
+func (t *Interface) NumMethods() int { return len(t.allMethods) }
+
+// Method returns the i'th method of interface t for 0 <= i < t.NumMethods().
+// The methods are ordered by their unique Id.
+func (t *Interface) Method(i int) *Func { return t.allMethods[i] }
+
+// Empty returns true if t is the empty interface.
+func (t *Interface) Empty() bool { return len(t.allMethods) == 0 }
+
+// Complete computes the interface's method set. It must be called by users of
+// NewInterface after the interface's embedded types are fully defined and
+// before using the interface type in any way other than to form other types.
+// Complete returns the receiver.
+func (t *Interface) Complete() *Interface {
+	if t.allMethods != nil {
+		return t
+	}
+
+	var allMethods []*Func
+	if t.embeddeds == nil {
+		if t.methods == nil {
+			allMethods = make([]*Func, 0, 1)
+		} else {
+			allMethods = t.methods
+		}
+	} else {
+		allMethods = append(allMethods, t.methods...)
+		for _, et := range t.embeddeds {
+			it := et.Underlying().(*Interface)
+			it.Complete()
+			for _, tm := range it.allMethods {
+				// Make a copy of the method and adjust its receiver type.
+				newm := *tm
+				newmtyp := *tm.typ.(*Signature)
+				newm.typ = &newmtyp
+				newmtyp.recv = NewVar(newm.pos, newm.pkg, "", t)
+				allMethods = append(allMethods, &newm)
+			}
+		}
+		sort.Sort(byUniqueMethodName(allMethods))
+	}
+	t.allMethods = allMethods
+
+	return t
+}
+
+// A Map represents a map type.
+type Map struct {
+	key, elem Type
+}
+
+// NewMap returns a new map for the given key and element types.
+func NewMap(key, elem Type) *Map {
+	return &Map{key, elem}
+}
+
+// Key returns the key type of map m.
+func (m *Map) Key() Type { return m.key }
+
+// Elem returns the element type of map m.
+func (m *Map) Elem() Type { return m.elem }
+
+// A Chan represents a channel type.
+type Chan struct {
+	dir  ChanDir
+	elem Type
+}
+
+// A ChanDir value indicates a channel direction.
+type ChanDir int
+
+// The direction of a channel is indicated by one of the following constants.
+const (
+	SendRecv ChanDir = iota
+	SendOnly
+	RecvOnly
+)
+
+// NewChan returns a new channel type for the given direction and element type.
+func NewChan(dir ChanDir, elem Type) *Chan {
+	return &Chan{dir, elem}
+}
+
+// Dir returns the direction of channel c.
+func (c *Chan) Dir() ChanDir { return c.dir }
+
+// Elem returns the element type of channel c.
+func (c *Chan) Elem() Type { return c.elem }
+
+// A Named represents a named type.
+type Named struct {
+	obj        *TypeName // corresponding declared object
+	underlying Type      // possibly a *Named during setup; never a *Named once set up completely
+	methods    []*Func   // methods declared for this type (not the method set of this type)
+}
+
+// NewNamed returns a new named type for the given type name, underlying type, and associated methods.
+// The underlying type must not be a *Named.
+func NewNamed(obj *TypeName, underlying Type, methods []*Func) *Named {
+	if _, ok := underlying.(*Named); ok {
+		panic("types.NewNamed: underlying type must not be *Named")
+	}
+	typ := &Named{obj: obj, underlying: underlying, methods: methods}
+	if obj.typ == nil {
+		obj.typ = typ
+	}
+	return typ
+}
+
+// TypeName returns the type name for the named type t.
+func (t *Named) Obj() *TypeName { return t.obj }
+
+// NumMethods returns the number of explicit methods whose receiver is named type t.
+func (t *Named) NumMethods() int { return len(t.methods) }
+
+// Method returns the i'th method of named type t for 0 <= i < t.NumMethods().
+func (t *Named) Method(i int) *Func { return t.methods[i] }
+
+// SetUnderlying sets the underlying type and marks t as complete.
+// TODO(gri) determine if there's a better solution rather than providing this function
+func (t *Named) SetUnderlying(underlying Type) {
+	if underlying == nil {
+		panic("types.Named.SetUnderlying: underlying type must not be nil")
+	}
+	if _, ok := underlying.(*Named); ok {
+		panic("types.Named.SetUnderlying: underlying type must not be *Named")
+	}
+	t.underlying = underlying
+}
+
+// AddMethod adds method m unless it is already in the method list.
+// TODO(gri) find a better solution instead of providing this function
+func (t *Named) AddMethod(m *Func) {
+	if i, _ := lookupMethod(t.methods, m.pkg, m.name); i < 0 {
+		t.methods = append(t.methods, m)
+	}
+}
+
+// Implementations for Type methods.
+
+func (t *Basic) Underlying() Type     { return t }
+func (t *Array) Underlying() Type     { return t }
+func (t *Slice) Underlying() Type     { return t }
+func (t *Struct) Underlying() Type    { return t }
+func (t *Pointer) Underlying() Type   { return t }
+func (t *Tuple) Underlying() Type     { return t }
+func (t *Signature) Underlying() Type { return t }
+func (t *Interface) Underlying() Type { return t }
+func (t *Map) Underlying() Type       { return t }
+func (t *Chan) Underlying() Type      { return t }
+func (t *Named) Underlying() Type     { return t.underlying }
+
+func (t *Basic) String() string     { return TypeString(t, nil) }
+func (t *Array) String() string     { return TypeString(t, nil) }
+func (t *Slice) String() string     { return TypeString(t, nil) }
+func (t *Struct) String() string    { return TypeString(t, nil) }
+func (t *Pointer) String() string   { return TypeString(t, nil) }
+func (t *Tuple) String() string     { return TypeString(t, nil) }
+func (t *Signature) String() string { return TypeString(t, nil) }
+func (t *Interface) String() string { return TypeString(t, nil) }
+func (t *Map) String() string       { return TypeString(t, nil) }
+func (t *Chan) String() string      { return TypeString(t, nil) }
+func (t *Named) String() string     { return TypeString(t, nil) }
diff --git a/go/types/typestring.go b/go/types/typestring.go
new file mode 100644
index 0000000..abee8ab
--- /dev/null
+++ b/go/types/typestring.go
@@ -0,0 +1,292 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file implements printing of types.
+
+package types
+
+import (
+	"bytes"
+	"fmt"
+)
+
+// A Qualifier controls how named package-level objects are printed in
+// calls to TypeString, ObjectString, and SelectionString.
+//
+// These three formatting routines call the Qualifier for each
+// package-level object O, and if the Qualifier returns a non-empty
+// string p, the object is printed in the form p.O.
+// If it returns an empty string, only the object name O is printed.
+//
+// Using a nil Qualifier is equivalent to using (*Package).Path: the
+// object is qualified by the import path, e.g., "encoding/json.Marshal".
+//
+type Qualifier func(*Package) string
+
+// RelativeTo(pkg) returns a Qualifier that fully qualifies members of
+// all packages other than pkg.
+func RelativeTo(pkg *Package) Qualifier {
+	if pkg == nil {
+		return nil
+	}
+	return func(other *Package) string {
+		if pkg == other {
+			return "" // same package; unqualified
+		}
+		return other.Path()
+	}
+}
+
+// If GcCompatibilityMode is set, printing of types is modified
+// to match the representation of some types in the gc compiler:
+//
+//	- byte and rune lose their alias name and simply stand for
+//	  uint8 and int32 respectively
+//	- embedded interfaces get flattened (the embedding info is lost,
+//	  and certain recursive interface types cannot be printed anymore)
+//
+// This makes it easier to compare packages computed with the type-
+// checker vs packages imported from gc export data.
+//
+// Caution: This flag affects all uses of WriteType, globally.
+// It is only provided for testing in conjunction with
+// gc-generated data. It may be removed at any time.
+var GcCompatibilityMode bool
+
+// TypeString returns the string representation of typ.
+// The Qualifier controls the printing of
+// package-level objects, and may be nil.
+func TypeString(typ Type, qf Qualifier) string {
+	var buf bytes.Buffer
+	WriteType(&buf, typ, qf)
+	return buf.String()
+}
+
+// WriteType writes the string representation of typ to buf.
+// The Qualifier controls the printing of
+// package-level objects, and may be nil.
+func WriteType(buf *bytes.Buffer, typ Type, qf Qualifier) {
+	writeType(buf, typ, qf, make([]Type, 8))
+}
+
+func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) {
+	// Theoretically, this is a quadratic lookup algorithm, but in
+	// practice deeply nested composite types with unnamed component
+	// types are uncommon. This code is likely more efficient than
+	// using a map.
+	for _, t := range visited {
+		if t == typ {
+			fmt.Fprintf(buf, "○%T", typ) // cycle to typ
+			return
+		}
+	}
+	visited = append(visited, typ)
+
+	switch t := typ.(type) {
+	case nil:
+		buf.WriteString("<nil>")
+
+	case *Basic:
+		if t.kind == UnsafePointer {
+			buf.WriteString("unsafe.")
+		}
+		if GcCompatibilityMode {
+			// forget the alias names
+			switch t.kind {
+			case Byte:
+				t = Typ[Uint8]
+			case Rune:
+				t = Typ[Int32]
+			}
+		}
+		buf.WriteString(t.name)
+
+	case *Array:
+		fmt.Fprintf(buf, "[%d]", t.len)
+		writeType(buf, t.elem, qf, visited)
+
+	case *Slice:
+		buf.WriteString("[]")
+		writeType(buf, t.elem, qf, visited)
+
+	case *Struct:
+		buf.WriteString("struct{")
+		for i, f := range t.fields {
+			if i > 0 {
+				buf.WriteString("; ")
+			}
+			if !f.anonymous {
+				buf.WriteString(f.name)
+				buf.WriteByte(' ')
+			}
+			writeType(buf, f.typ, qf, visited)
+			if tag := t.Tag(i); tag != "" {
+				fmt.Fprintf(buf, " %q", tag)
+			}
+		}
+		buf.WriteByte('}')
+
+	case *Pointer:
+		buf.WriteByte('*')
+		writeType(buf, t.base, qf, visited)
+
+	case *Tuple:
+		writeTuple(buf, t, false, qf, visited)
+
+	case *Signature:
+		buf.WriteString("func")
+		writeSignature(buf, t, qf, visited)
+
+	case *Interface:
+		// We write the source-level methods and embedded types rather
+		// than the actual method set since resolved method signatures
+		// may have non-printable cycles if parameters have anonymous
+		// interface types that (directly or indirectly) embed the
+		// current interface. For instance, consider the result type
+		// of m:
+		//
+		//     type T interface{
+		//         m() interface{ T }
+		//     }
+		//
+		buf.WriteString("interface{")
+		if GcCompatibilityMode {
+			// print flattened interface
+			// (useful to compare against gc-generated interfaces)
+			for i, m := range t.allMethods {
+				if i > 0 {
+					buf.WriteString("; ")
+				}
+				buf.WriteString(m.name)
+				writeSignature(buf, m.typ.(*Signature), qf, visited)
+			}
+		} else {
+			// print explicit interface methods and embedded types
+			for i, m := range t.methods {
+				if i > 0 {
+					buf.WriteString("; ")
+				}
+				buf.WriteString(m.name)
+				writeSignature(buf, m.typ.(*Signature), qf, visited)
+			}
+			for i, typ := range t.embeddeds {
+				if i > 0 || len(t.methods) > 0 {
+					buf.WriteString("; ")
+				}
+				writeType(buf, typ, qf, visited)
+			}
+		}
+		buf.WriteByte('}')
+
+	case *Map:
+		buf.WriteString("map[")
+		writeType(buf, t.key, qf, visited)
+		buf.WriteByte(']')
+		writeType(buf, t.elem, qf, visited)
+
+	case *Chan:
+		var s string
+		var parens bool
+		switch t.dir {
+		case SendRecv:
+			s = "chan "
+			// chan (<-chan T) requires parentheses
+			if c, _ := t.elem.(*Chan); c != nil && c.dir == RecvOnly {
+				parens = true
+			}
+		case SendOnly:
+			s = "chan<- "
+		case RecvOnly:
+			s = "<-chan "
+		default:
+			panic("unreachable")
+		}
+		buf.WriteString(s)
+		if parens {
+			buf.WriteByte('(')
+		}
+		writeType(buf, t.elem, qf, visited)
+		if parens {
+			buf.WriteByte(')')
+		}
+
+	case *Named:
+		s := "<Named w/o object>"
+		if obj := t.obj; obj != nil {
+			if obj.pkg != nil {
+				writePackage(buf, obj.pkg, qf)
+			}
+			// TODO(gri): function-local named types should be displayed
+			// differently from named types at package level to avoid
+			// ambiguity.
+			s = obj.name
+		}
+		buf.WriteString(s)
+
+	default:
+		// For externally defined implementations of Type.
+		buf.WriteString(t.String())
+	}
+}
+
+func writeTuple(buf *bytes.Buffer, tup *Tuple, variadic bool, qf Qualifier, visited []Type) {
+	buf.WriteByte('(')
+	if tup != nil {
+		for i, v := range tup.vars {
+			if i > 0 {
+				buf.WriteString(", ")
+			}
+			if v.name != "" {
+				buf.WriteString(v.name)
+				buf.WriteByte(' ')
+			}
+			typ := v.typ
+			if variadic && i == len(tup.vars)-1 {
+				if s, ok := typ.(*Slice); ok {
+					buf.WriteString("...")
+					typ = s.elem
+				} else {
+					// special case:
+					// append(s, "foo"...) leads to signature func([]byte, string...)
+					if t, ok := typ.Underlying().(*Basic); !ok || t.kind != String {
+						panic("internal error: string type expected")
+					}
+					writeType(buf, typ, qf, visited)
+					buf.WriteString("...")
+					continue
+				}
+			}
+			writeType(buf, typ, qf, visited)
+		}
+	}
+	buf.WriteByte(')')
+}
+
+// WriteSignature writes the representation of the signature sig to buf,
+// without a leading "func" keyword.
+// The Qualifier controls the printing of
+// package-level objects, and may be nil.
+func WriteSignature(buf *bytes.Buffer, sig *Signature, qf Qualifier) {
+	writeSignature(buf, sig, qf, make([]Type, 8))
+}
+
+func writeSignature(buf *bytes.Buffer, sig *Signature, qf Qualifier, visited []Type) {
+	writeTuple(buf, sig.params, sig.variadic, qf, visited)
+
+	n := sig.results.Len()
+	if n == 0 {
+		// no result
+		return
+	}
+
+	buf.WriteByte(' ')
+	if n == 1 && sig.results.vars[0].name == "" {
+		// single unnamed result
+		writeType(buf, sig.results.vars[0].typ, qf, visited)
+		return
+	}
+
+	// multiple or named result(s)
+	writeTuple(buf, sig.results, false, qf, visited)
+}
diff --git a/go/types/typestring_test.go b/go/types/typestring_test.go
new file mode 100644
index 0000000..975b623
--- /dev/null
+++ b/go/types/typestring_test.go
@@ -0,0 +1,166 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package types_test
+
+import (
+	"go/ast"
+	"go/parser"
+	"go/token"
+	"testing"
+
+	_ "golang.org/x/tools/go/gcimporter"
+	. "golang.org/x/tools/go/types"
+)
+
+const filename = "<src>"
+
+func makePkg(t *testing.T, src string) (*Package, error) {
+	fset := token.NewFileSet()
+	file, err := parser.ParseFile(fset, filename, src, parser.DeclarationErrors)
+	if err != nil {
+		return nil, err
+	}
+	// use the package name as package path
+	return Check(file.Name.Name, fset, []*ast.File{file})
+}
+
+type testEntry struct {
+	src, str string
+}
+
+// dup returns a testEntry where both src and str are the same.
+func dup(s string) testEntry {
+	return testEntry{s, s}
+}
+
+// types that don't depend on any other type declarations
+var independentTestTypes = []testEntry{
+	// basic types
+	dup("int"),
+	dup("float32"),
+	dup("string"),
+
+	// arrays
+	dup("[10]int"),
+
+	// slices
+	dup("[]int"),
+	dup("[][]int"),
+
+	// structs
+	dup("struct{}"),
+	dup("struct{x int}"),
+	{`struct {
+		x, y int
+		z float32 "foo"
+	}`, `struct{x int; y int; z float32 "foo"}`},
+	{`struct {
+		string
+		elems []complex128
+	}`, `struct{string; elems []complex128}`},
+
+	// pointers
+	dup("*int"),
+	dup("***struct{}"),
+	dup("*struct{a int; b float32}"),
+
+	// functions
+	dup("func()"),
+	dup("func(x int)"),
+	{"func(x, y int)", "func(x int, y int)"},
+	{"func(x, y int, z string)", "func(x int, y int, z string)"},
+	dup("func(int)"),
+	{"func(int, string, byte)", "func(int, string, byte)"},
+
+	dup("func() int"),
+	{"func() (string)", "func() string"},
+	dup("func() (u int)"),
+	{"func() (u, v int, w string)", "func() (u int, v int, w string)"},
+
+	dup("func(int) string"),
+	dup("func(x int) string"),
+	dup("func(x int) (u string)"),
+	{"func(x, y int) (u string)", "func(x int, y int) (u string)"},
+
+	dup("func(...int) string"),
+	dup("func(x ...int) string"),
+	dup("func(x ...int) (u string)"),
+	{"func(x, y ...int) (u string)", "func(x int, y ...int) (u string)"},
+
+	// interfaces
+	dup("interface{}"),
+	dup("interface{m()}"),
+	dup(`interface{String() string; m(int) float32}`),
+
+	// maps
+	dup("map[string]int"),
+	{"map[struct{x, y int}][]byte", "map[struct{x int; y int}][]byte"},
+
+	// channels
+	dup("chan<- chan int"),
+	dup("chan<- <-chan int"),
+	dup("<-chan <-chan int"),
+	dup("chan (<-chan int)"),
+	dup("chan<- func()"),
+	dup("<-chan []func() int"),
+}
+
+// types that depend on other type declarations (src in TestTypes)
+var dependentTestTypes = []testEntry{
+	// interfaces
+	dup(`interface{io.Reader; io.Writer}`),
+	dup(`interface{m() int; io.Writer}`),
+	{`interface{m() interface{T}}`, `interface{m() interface{p.T}}`},
+}
+
+func TestTypeString(t *testing.T) {
+	skipSpecialPlatforms(t)
+
+	var tests []testEntry
+	tests = append(tests, independentTestTypes...)
+	tests = append(tests, dependentTestTypes...)
+
+	for _, test := range tests {
+		src := `package p; import "io"; type _ io.Writer; type T ` + test.src
+		pkg, err := makePkg(t, src)
+		if err != nil {
+			t.Errorf("%s: %s", src, err)
+			continue
+		}
+		typ := pkg.Scope().Lookup("T").Type().Underlying()
+		if got := typ.String(); got != test.str {
+			t.Errorf("%s: got %s, want %s", test.src, got, test.str)
+		}
+	}
+}
+
+func TestQualifiedTypeString(t *testing.T) {
+	p, _ := pkgFor("p.go", "package p; type T int", nil)
+	q, _ := pkgFor("q.go", "package q", nil)
+
+	pT := p.Scope().Lookup("T").Type()
+	for _, test := range []struct {
+		typ  Type
+		this *Package
+		want string
+	}{
+		{pT, nil, "p.T"},
+		{pT, p, "T"},
+		{pT, q, "p.T"},
+		{NewPointer(pT), p, "*T"},
+		{NewPointer(pT), q, "*p.T"},
+	} {
+		qualifier := func(pkg *Package) string {
+			if pkg != test.this {
+				return pkg.Name()
+			}
+			return ""
+		}
+		if got := TypeString(test.typ, qualifier); got != test.want {
+			t.Errorf("TypeString(%s, %s) = %s, want %s",
+				test.this, test.typ, got, test.want)
+		}
+	}
+}
diff --git a/go/types/typeutil/example_test.go b/go/types/typeutil/example_test.go
new file mode 100644
index 0000000..9e3ada7
--- /dev/null
+++ b/go/types/typeutil/example_test.go
@@ -0,0 +1,68 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package typeutil_test
+
+import (
+	"fmt"
+	"sort"
+
+	"go/ast"
+	"go/parser"
+	"go/token"
+
+	"golang.org/x/tools/go/types"
+	"golang.org/x/tools/go/types/typeutil"
+)
+
+func ExampleMap() {
+	const source = `package P
+
+var X []string
+var Y []string
+
+const p, q = 1.0, 2.0
+
+func f(offset int32) (value byte, ok bool)
+func g(rune) (uint8, bool)
+`
+
+	// Parse and type-check the package.
+	fset := token.NewFileSet()
+	f, err := parser.ParseFile(fset, "P.go", source, 0)
+	if err != nil {
+		panic(err)
+	}
+	pkg, err := new(types.Config).Check("P", fset, []*ast.File{f}, nil)
+	if err != nil {
+		panic(err)
+	}
+
+	scope := pkg.Scope()
+
+	// Group names of package-level objects by their type.
+	var namesByType typeutil.Map // value is []string
+	for _, name := range scope.Names() {
+		T := scope.Lookup(name).Type()
+
+		names, _ := namesByType.At(T).([]string)
+		names = append(names, name)
+		namesByType.Set(T, names)
+	}
+
+	// Format, sort, and print the map entries.
+	var lines []string
+	namesByType.Iterate(func(T types.Type, names interface{}) {
+		lines = append(lines, fmt.Sprintf("%s   %s", names, T))
+	})
+	sort.Strings(lines)
+	for _, line := range lines {
+		fmt.Println(line)
+	}
+
+	// Output:
+	// [X Y]   []string
+	// [f g]   func(offset int32) (value byte, ok bool)
+	// [p q]   untyped float
+}
diff --git a/go/types/typeutil/imports.go b/go/types/typeutil/imports.go
new file mode 100644
index 0000000..967fe1e
--- /dev/null
+++ b/go/types/typeutil/imports.go
@@ -0,0 +1,31 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package typeutil
+
+import "golang.org/x/tools/go/types"
+
+// Dependencies returns all dependencies of the specified packages.
+//
+// Dependent packages appear in topological order: if package P imports
+// package Q, Q appears earlier than P in the result.
+// The algorithm follows import statements in the order they
+// appear in the source code, so the result is a total order.
+//
+func Dependencies(pkgs ...*types.Package) []*types.Package {
+	var result []*types.Package
+	seen := make(map[*types.Package]bool)
+	var visit func(pkgs []*types.Package)
+	visit = func(pkgs []*types.Package) {
+		for _, p := range pkgs {
+			if !seen[p] {
+				seen[p] = true
+				visit(p.Imports())
+				result = append(result, p)
+			}
+		}
+	}
+	visit(pkgs)
+	return result
+}
diff --git a/go/types/typeutil/imports_test.go b/go/types/typeutil/imports_test.go
new file mode 100644
index 0000000..8071ae1
--- /dev/null
+++ b/go/types/typeutil/imports_test.go
@@ -0,0 +1,79 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package typeutil_test
+
+import (
+	"fmt"
+	"go/ast"
+	"go/parser"
+	"go/token"
+	"testing"
+
+	"golang.org/x/tools/go/types"
+	"golang.org/x/tools/go/types/typeutil"
+)
+
+func TestDependencies(t *testing.T) {
+	packages := make(map[string]*types.Package)
+	conf := types.Config{
+		Packages: packages,
+		Import: func(_ map[string]*types.Package, path string) (*types.Package, error) {
+			return packages[path], nil
+		},
+	}
+	fset := token.NewFileSet()
+
+	// All edges go to the right.
+	//  /--D--B--A
+	// F    \_C_/
+	//  \__E_/
+	for i, content := range []string{
+		`package A`,
+		`package C; import (_ "A")`,
+		`package B; import (_ "A")`,
+		`package E; import (_ "C")`,
+		`package D; import (_ "B"; _ "C")`,
+		`package F; import (_ "D"; _ "E")`,
+	} {
+		f, err := parser.ParseFile(fset, fmt.Sprintf("%d.go", i), content, 0)
+		if err != nil {
+			t.Fatal(err)
+		}
+		pkg, err := conf.Check(f.Name.Name, fset, []*ast.File{f}, nil)
+		if err != nil {
+			t.Fatal(err)
+		}
+		packages[pkg.Path()] = pkg
+	}
+
+	for _, test := range []struct {
+		roots, want string
+	}{
+		{"A", "A"},
+		{"B", "AB"},
+		{"C", "AC"},
+		{"D", "ABCD"},
+		{"E", "ACE"},
+		{"F", "ABCDEF"},
+
+		{"BE", "ABCE"},
+		{"EB", "ACEB"},
+		{"DE", "ABCDE"},
+		{"ED", "ACEBD"},
+		{"EF", "ACEBDF"},
+	} {
+		var pkgs []*types.Package
+		for _, r := range test.roots {
+			pkgs = append(pkgs, conf.Packages[string(r)])
+		}
+		var got string
+		for _, p := range typeutil.Dependencies(pkgs...) {
+			got += p.Path()
+		}
+		if got != test.want {
+			t.Errorf("Dependencies(%q) = %q, want %q", test.roots, got, test.want)
+		}
+	}
+}
diff --git a/go/types/typeutil/map.go b/go/types/typeutil/map.go
new file mode 100644
index 0000000..b3a04cc
--- /dev/null
+++ b/go/types/typeutil/map.go
@@ -0,0 +1,314 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package typeutil defines various utilities for types, such as Map,
+// a mapping from types.Type to interface{} values.
+package typeutil // import "golang.org/x/tools/go/types/typeutil"
+
+import (
+	"bytes"
+	"fmt"
+	"reflect"
+
+	"golang.org/x/tools/go/types"
+)
+
+// Map is a hash-table-based mapping from types (types.Type) to
+// arbitrary interface{} values.  The concrete types that implement
+// the Type interface are pointers.  Since they are not canonicalized,
+// == cannot be used to check for equivalence, and thus we cannot
+// simply use a Go map.
+//
+// Just as with map[K]V, a nil *Map is a valid empty map.
+//
+// Not thread-safe.
+//
+type Map struct {
+	hasher Hasher             // shared by many Maps
+	table  map[uint32][]entry // maps hash to bucket; entry.key==nil means unused
+	length int                // number of map entries
+}
+
+// entry is an entry (key/value association) in a hash bucket.
+type entry struct {
+	key   types.Type
+	value interface{}
+}
+
+// SetHasher sets the hasher used by Map.
+//
+// All Hashers are functionally equivalent but contain internal state
+// used to cache the results of hashing previously seen types.
+//
+// A single Hasher created by MakeHasher() may be shared among many
+// Maps.  This is recommended if the instances have many keys in
+// common, as it will amortize the cost of hash computation.
+//
+// A Hasher may grow without bound as new types are seen.  Even when a
+// type is deleted from the map, the Hasher never shrinks, since other
+// types in the map may reference the deleted type indirectly.
+//
+// Hashers are not thread-safe, and read-only operations such as
+// Map.Lookup require updates to the hasher, so a full Mutex lock (not a
+// read-lock) is require around all Map operations if a shared
+// hasher is accessed from multiple threads.
+//
+// If SetHasher is not called, the Map will create a private hasher at
+// the first call to Insert.
+//
+func (m *Map) SetHasher(hasher Hasher) {
+	m.hasher = hasher
+}
+
+// Delete removes the entry with the given key, if any.
+// It returns true if the entry was found.
+//
+func (m *Map) Delete(key types.Type) bool {
+	if m != nil && m.table != nil {
+		hash := m.hasher.Hash(key)
+		bucket := m.table[hash]
+		for i, e := range bucket {
+			if e.key != nil && types.Identical(key, e.key) {
+				// We can't compact the bucket as it
+				// would disturb iterators.
+				bucket[i] = entry{}
+				m.length--
+				return true
+			}
+		}
+	}
+	return false
+}
+
+// At returns the map entry for the given key.
+// The result is nil if the entry is not present.
+//
+func (m *Map) At(key types.Type) interface{} {
+	if m != nil && m.table != nil {
+		for _, e := range m.table[m.hasher.Hash(key)] {
+			if e.key != nil && types.Identical(key, e.key) {
+				return e.value
+			}
+		}
+	}
+	return nil
+}
+
+// Set sets the map entry for key to val,
+// and returns the previous entry, if any.
+func (m *Map) Set(key types.Type, value interface{}) (prev interface{}) {
+	if m.table != nil {
+		hash := m.hasher.Hash(key)
+		bucket := m.table[hash]
+		var hole *entry
+		for i, e := range bucket {
+			if e.key == nil {
+				hole = &bucket[i]
+			} else if types.Identical(key, e.key) {
+				prev = e.value
+				bucket[i].value = value
+				return
+			}
+		}
+
+		if hole != nil {
+			*hole = entry{key, value} // overwrite deleted entry
+		} else {
+			m.table[hash] = append(bucket, entry{key, value})
+		}
+	} else {
+		if m.hasher.memo == nil {
+			m.hasher = MakeHasher()
+		}
+		hash := m.hasher.Hash(key)
+		m.table = map[uint32][]entry{hash: {entry{key, value}}}
+	}
+
+	m.length++
+	return
+}
+
+// Len returns the number of map entries.
+func (m *Map) Len() int {
+	if m != nil {
+		return m.length
+	}
+	return 0
+}
+
+// Iterate calls function f on each entry in the map in unspecified order.
+//
+// If f should mutate the map, Iterate provides the same guarantees as
+// Go maps: if f deletes a map entry that Iterate has not yet reached,
+// f will not be invoked for it, but if f inserts a map entry that
+// Iterate has not yet reached, whether or not f will be invoked for
+// it is unspecified.
+//
+func (m *Map) Iterate(f func(key types.Type, value interface{})) {
+	if m != nil {
+		for _, bucket := range m.table {
+			for _, e := range bucket {
+				if e.key != nil {
+					f(e.key, e.value)
+				}
+			}
+		}
+	}
+}
+
+// Keys returns a new slice containing the set of map keys.
+// The order is unspecified.
+func (m *Map) Keys() []types.Type {
+	keys := make([]types.Type, 0, m.Len())
+	m.Iterate(func(key types.Type, _ interface{}) {
+		keys = append(keys, key)
+	})
+	return keys
+}
+
+func (m *Map) toString(values bool) string {
+	if m == nil {
+		return "{}"
+	}
+	var buf bytes.Buffer
+	fmt.Fprint(&buf, "{")
+	sep := ""
+	m.Iterate(func(key types.Type, value interface{}) {
+		fmt.Fprint(&buf, sep)
+		sep = ", "
+		fmt.Fprint(&buf, key)
+		if values {
+			fmt.Fprintf(&buf, ": %q", value)
+		}
+	})
+	fmt.Fprint(&buf, "}")
+	return buf.String()
+}
+
+// String returns a string representation of the map's entries.
+// Values are printed using fmt.Sprintf("%v", v).
+// Order is unspecified.
+//
+func (m *Map) String() string {
+	return m.toString(true)
+}
+
+// KeysString returns a string representation of the map's key set.
+// Order is unspecified.
+//
+func (m *Map) KeysString() string {
+	return m.toString(false)
+}
+
+////////////////////////////////////////////////////////////////////////
+// Hasher
+
+// A Hasher maps each type to its hash value.
+// For efficiency, a hasher uses memoization; thus its memory
+// footprint grows monotonically over time.
+// Hashers are not thread-safe.
+// Hashers have reference semantics.
+// Call MakeHasher to create a Hasher.
+type Hasher struct {
+	memo map[types.Type]uint32
+}
+
+// MakeHasher returns a new Hasher instance.
+func MakeHasher() Hasher {
+	return Hasher{make(map[types.Type]uint32)}
+}
+
+// Hash computes a hash value for the given type t such that
+// Identical(t, t') => Hash(t) == Hash(t').
+func (h Hasher) Hash(t types.Type) uint32 {
+	hash, ok := h.memo[t]
+	if !ok {
+		hash = h.hashFor(t)
+		h.memo[t] = hash
+	}
+	return hash
+}
+
+// hashString computes the Fowler–Noll–Vo hash of s.
+func hashString(s string) uint32 {
+	var h uint32
+	for i := 0; i < len(s); i++ {
+		h ^= uint32(s[i])
+		h *= 16777619
+	}
+	return h
+}
+
+// hashFor computes the hash of t.
+func (h Hasher) hashFor(t types.Type) uint32 {
+	// See Identical for rationale.
+	switch t := t.(type) {
+	case *types.Basic:
+		return uint32(t.Kind())
+
+	case *types.Array:
+		return 9043 + 2*uint32(t.Len()) + 3*h.Hash(t.Elem())
+
+	case *types.Slice:
+		return 9049 + 2*h.Hash(t.Elem())
+
+	case *types.Struct:
+		var hash uint32 = 9059
+		for i, n := 0, t.NumFields(); i < n; i++ {
+			f := t.Field(i)
+			if f.Anonymous() {
+				hash += 8861
+			}
+			hash += hashString(t.Tag(i))
+			hash += hashString(f.Name()) // (ignore f.Pkg)
+			hash += h.Hash(f.Type())
+		}
+		return hash
+
+	case *types.Pointer:
+		return 9067 + 2*h.Hash(t.Elem())
+
+	case *types.Signature:
+		var hash uint32 = 9091
+		if t.Variadic() {
+			hash *= 8863
+		}
+		return hash + 3*h.hashTuple(t.Params()) + 5*h.hashTuple(t.Results())
+
+	case *types.Interface:
+		var hash uint32 = 9103
+		for i, n := 0, t.NumMethods(); i < n; i++ {
+			// See go/types.identicalMethods for rationale.
+			// Method order is not significant.
+			// Ignore m.Pkg().
+			m := t.Method(i)
+			hash += 3*hashString(m.Name()) + 5*h.Hash(m.Type())
+		}
+		return hash
+
+	case *types.Map:
+		return 9109 + 2*h.Hash(t.Key()) + 3*h.Hash(t.Elem())
+
+	case *types.Chan:
+		return 9127 + 2*uint32(t.Dir()) + 3*h.Hash(t.Elem())
+
+	case *types.Named:
+		// Not safe with a copying GC; objects may move.
+		return uint32(reflect.ValueOf(t.Obj()).Pointer())
+
+	case *types.Tuple:
+		return h.hashTuple(t)
+	}
+	panic(t)
+}
+
+func (h Hasher) hashTuple(tuple *types.Tuple) uint32 {
+	// See go/types.identicalTypes for rationale.
+	n := tuple.Len()
+	var hash uint32 = 9137 + 2*uint32(n)
+	for i := 0; i < n; i++ {
+		hash += 3 * h.Hash(tuple.At(i).Type())
+	}
+	return hash
+}
diff --git a/go/types/typeutil/map_test.go b/go/types/typeutil/map_test.go
new file mode 100644
index 0000000..776b5e2
--- /dev/null
+++ b/go/types/typeutil/map_test.go
@@ -0,0 +1,174 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package typeutil_test
+
+// TODO(adonovan):
+// - test use of explicit hasher across two maps.
+// - test hashcodes are consistent with equals for a range of types
+//   (e.g. all types generated by type-checking some body of real code).
+
+import (
+	"testing"
+
+	"golang.org/x/tools/go/types"
+	"golang.org/x/tools/go/types/typeutil"
+)
+
+var (
+	tStr      = types.Typ[types.String]             // string
+	tPStr1    = types.NewPointer(tStr)              // *string
+	tPStr2    = types.NewPointer(tStr)              // *string, again
+	tInt      = types.Typ[types.Int]                // int
+	tChanInt1 = types.NewChan(types.RecvOnly, tInt) // <-chan int
+	tChanInt2 = types.NewChan(types.RecvOnly, tInt) // <-chan int, again
+)
+
+func checkEqualButNotIdentical(t *testing.T, x, y types.Type, comment string) {
+	if !types.Identical(x, y) {
+		t.Errorf("%s: not equal: %s, %s", comment, x, y)
+	}
+	if x == y {
+		t.Errorf("%s: identical: %v, %v", comment, x, y)
+	}
+}
+
+func TestAxioms(t *testing.T) {
+	checkEqualButNotIdentical(t, tPStr1, tPStr2, "tPstr{1,2}")
+	checkEqualButNotIdentical(t, tChanInt1, tChanInt2, "tChanInt{1,2}")
+}
+
+func TestMap(t *testing.T) {
+	var tmap *typeutil.Map
+
+	// All methods but Set are safe on on (*T)(nil).
+	tmap.Len()
+	tmap.At(tPStr1)
+	tmap.Delete(tPStr1)
+	tmap.KeysString()
+	tmap.String()
+
+	tmap = new(typeutil.Map)
+
+	// Length of empty map.
+	if l := tmap.Len(); l != 0 {
+		t.Errorf("Len() on empty Map: got %d, want 0", l)
+	}
+	// At of missing key.
+	if v := tmap.At(tPStr1); v != nil {
+		t.Errorf("At() on empty Map: got %v, want nil", v)
+	}
+	// Deletion of missing key.
+	if tmap.Delete(tPStr1) {
+		t.Errorf("Delete() on empty Map: got true, want false")
+	}
+	// Set of new key.
+	if prev := tmap.Set(tPStr1, "*string"); prev != nil {
+		t.Errorf("Set() on empty Map returned non-nil previous value %s", prev)
+	}
+
+	// Now: {*string: "*string"}
+
+	// Length of non-empty map.
+	if l := tmap.Len(); l != 1 {
+		t.Errorf("Len(): got %d, want 1", l)
+	}
+	// At via insertion key.
+	if v := tmap.At(tPStr1); v != "*string" {
+		t.Errorf("At(): got %q, want \"*string\"", v)
+	}
+	// At via equal key.
+	if v := tmap.At(tPStr2); v != "*string" {
+		t.Errorf("At(): got %q, want \"*string\"", v)
+	}
+	// Iteration over sole entry.
+	tmap.Iterate(func(key types.Type, value interface{}) {
+		if key != tPStr1 {
+			t.Errorf("Iterate: key: got %s, want %s", key, tPStr1)
+		}
+		if want := "*string"; value != want {
+			t.Errorf("Iterate: value: got %s, want %s", value, want)
+		}
+	})
+
+	// Setion with key equal to present one.
+	if prev := tmap.Set(tPStr2, "*string again"); prev != "*string" {
+		t.Errorf("Set() previous value: got %s, want \"*string\"", prev)
+	}
+
+	// Setion of another association.
+	if prev := tmap.Set(tChanInt1, "<-chan int"); prev != nil {
+		t.Errorf("Set() previous value: got %s, want nil", prev)
+	}
+
+	// Now: {*string: "*string again", <-chan int: "<-chan int"}
+
+	want1 := "{*string: \"*string again\", <-chan int: \"<-chan int\"}"
+	want2 := "{<-chan int: \"<-chan int\", *string: \"*string again\"}"
+	if s := tmap.String(); s != want1 && s != want2 {
+		t.Errorf("String(): got %s, want %s", s, want1)
+	}
+
+	want1 = "{*string, <-chan int}"
+	want2 = "{<-chan int, *string}"
+	if s := tmap.KeysString(); s != want1 && s != want2 {
+		t.Errorf("KeysString(): got %s, want %s", s, want1)
+	}
+
+	// Keys().
+	I := types.Identical
+	switch k := tmap.Keys(); {
+	case I(k[0], tChanInt1) && I(k[1], tPStr1): // ok
+	case I(k[1], tChanInt1) && I(k[0], tPStr1): // ok
+	default:
+		t.Errorf("Keys(): got %v, want %s", k, want2)
+	}
+
+	if l := tmap.Len(); l != 2 {
+		t.Errorf("Len(): got %d, want 1", l)
+	}
+	// At via original key.
+	if v := tmap.At(tPStr1); v != "*string again" {
+		t.Errorf("At(): got %q, want \"*string again\"", v)
+	}
+	hamming := 1
+	tmap.Iterate(func(key types.Type, value interface{}) {
+		switch {
+		case I(key, tChanInt1):
+			hamming *= 2 // ok
+		case I(key, tPStr1):
+			hamming *= 3 // ok
+		}
+	})
+	if hamming != 6 {
+		t.Errorf("Iterate: hamming: got %d, want %d", hamming, 6)
+	}
+
+	if v := tmap.At(tChanInt2); v != "<-chan int" {
+		t.Errorf("At(): got %q, want \"<-chan int\"", v)
+	}
+	// Deletion with key equal to present one.
+	if !tmap.Delete(tChanInt2) {
+		t.Errorf("Delete() of existing key: got false, want true")
+	}
+
+	// Now: {*string: "*string again"}
+
+	if l := tmap.Len(); l != 1 {
+		t.Errorf("Len(): got %d, want 1", l)
+	}
+	// Deletion again.
+	if !tmap.Delete(tPStr2) {
+		t.Errorf("Delete() of existing key: got false, want true")
+	}
+
+	// Now: {}
+
+	if l := tmap.Len(); l != 0 {
+		t.Errorf("Len(): got %d, want %d", l, 0)
+	}
+	if s := tmap.String(); s != "{}" {
+		t.Errorf("Len(): got %q, want %q", s, "")
+	}
+}
diff --git a/go/types/typeutil/methodsetcache.go b/go/types/typeutil/methodsetcache.go
new file mode 100644
index 0000000..daad644
--- /dev/null
+++ b/go/types/typeutil/methodsetcache.go
@@ -0,0 +1,73 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file implements a cache of method sets.
+
+package typeutil
+
+import (
+	"sync"
+
+	"golang.org/x/tools/go/types"
+)
+
+// A MethodSetCache records the method set of each type T for which
+// MethodSet(T) is called so that repeat queries are fast.
+// The zero value is a ready-to-use cache instance.
+type MethodSetCache struct {
+	mu     sync.Mutex
+	named  map[*types.Named]struct{ value, pointer *types.MethodSet } // method sets for named N and *N
+	others map[types.Type]*types.MethodSet                            // all other types
+}
+
+// MethodSet returns the method set of type T.  It is thread-safe.
+//
+// If cache is nil, this function is equivalent to types.NewMethodSet(T).
+// Utility functions can thus expose an optional *MethodSetCache
+// parameter to clients that care about performance.
+//
+func (cache *MethodSetCache) MethodSet(T types.Type) *types.MethodSet {
+	if cache == nil {
+		return types.NewMethodSet(T)
+	}
+	cache.mu.Lock()
+	defer cache.mu.Unlock()
+
+	switch T := T.(type) {
+	case *types.Named:
+		return cache.lookupNamed(T).value
+
+	case *types.Pointer:
+		if N, ok := T.Elem().(*types.Named); ok {
+			return cache.lookupNamed(N).pointer
+		}
+	}
+
+	// all other types
+	// (The map uses pointer equivalence, not type identity.)
+	mset := cache.others[T]
+	if mset == nil {
+		mset = types.NewMethodSet(T)
+		if cache.others == nil {
+			cache.others = make(map[types.Type]*types.MethodSet)
+		}
+		cache.others[T] = mset
+	}
+	return mset
+}
+
+func (cache *MethodSetCache) lookupNamed(named *types.Named) struct{ value, pointer *types.MethodSet } {
+	if cache.named == nil {
+		cache.named = make(map[*types.Named]struct{ value, pointer *types.MethodSet })
+	}
+	// Avoid recomputing mset(*T) for each distinct Pointer
+	// instance whose underlying type is a named type.
+	msets, ok := cache.named[named]
+	if !ok {
+		msets.value = types.NewMethodSet(named)
+		msets.pointer = types.NewMethodSet(types.NewPointer(named))
+		cache.named[named] = msets
+	}
+	return msets
+}
diff --git a/go/types/typeutil/ui.go b/go/types/typeutil/ui.go
new file mode 100644
index 0000000..20c5249
--- /dev/null
+++ b/go/types/typeutil/ui.go
@@ -0,0 +1,38 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package typeutil
+
+// This file defines utilities for user interfaces that display types.
+
+import "golang.org/x/tools/go/types"
+
+// IntuitiveMethodSet returns the intuitive method set of a type, T.
+//
+// The result contains MethodSet(T) and additionally, if T is a
+// concrete type, methods belonging to *T if there is no identically
+// named method on T itself.  This corresponds to user intuition about
+// method sets; this function is intended only for user interfaces.
+//
+// The order of the result is as for types.MethodSet(T).
+//
+func IntuitiveMethodSet(T types.Type, msets *MethodSetCache) []*types.Selection {
+	var result []*types.Selection
+	mset := msets.MethodSet(T)
+	if _, ok := T.Underlying().(*types.Interface); ok {
+		for i, n := 0, mset.Len(); i < n; i++ {
+			result = append(result, mset.At(i))
+		}
+	} else {
+		pmset := msets.MethodSet(types.NewPointer(T))
+		for i, n := 0, pmset.Len(); i < n; i++ {
+			meth := pmset.At(i)
+			if m := mset.Lookup(meth.Obj().Pkg(), meth.Obj().Name()); m != nil {
+				meth = m
+			}
+			result = append(result, meth)
+		}
+	}
+	return result
+}
diff --git a/go/types/typexpr.go b/go/types/typexpr.go
new file mode 100644
index 0000000..bd2d7ba
--- /dev/null
+++ b/go/types/typexpr.go
@@ -0,0 +1,713 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file implements type-checking of identifiers and type expressions.
+
+package types
+
+import (
+	"go/ast"
+	"go/token"
+	"sort"
+	"strconv"
+
+	"golang.org/x/tools/go/exact"
+)
+
+// ident type-checks identifier e and initializes x with the value or type of e.
+// If an error occurred, x.mode is set to invalid.
+// For the meaning of def and path, see check.typ, below.
+//
+func (check *Checker) ident(x *operand, e *ast.Ident, def *Named, path []*TypeName) {
+	x.mode = invalid
+	x.expr = e
+
+	scope, obj := check.scope.LookupParent(e.Name, check.pos)
+	if obj == nil {
+		if e.Name == "_" {
+			check.errorf(e.Pos(), "cannot use _ as value or type")
+		} else {
+			check.errorf(e.Pos(), "undeclared name: %s", e.Name)
+		}
+		return
+	}
+	check.recordUse(e, obj)
+
+	check.objDecl(obj, def, path)
+	typ := obj.Type()
+	assert(typ != nil)
+
+	// The object may be dot-imported: If so, remove its package from
+	// the map of unused dot imports for the respective file scope.
+	// (This code is only needed for dot-imports. Without them,
+	// we only have to mark variables, see *Var case below).
+	if pkg := obj.Pkg(); pkg != check.pkg && pkg != nil {
+		delete(check.unusedDotImports[scope], pkg)
+	}
+
+	switch obj := obj.(type) {
+	case *PkgName:
+		check.errorf(e.Pos(), "use of package %s not in selector", obj.name)
+		return
+
+	case *Const:
+		check.addDeclDep(obj)
+		if typ == Typ[Invalid] {
+			return
+		}
+		if obj == universeIota {
+			if check.iota == nil {
+				check.errorf(e.Pos(), "cannot use iota outside constant declaration")
+				return
+			}
+			x.val = check.iota
+		} else {
+			x.val = obj.val
+		}
+		assert(x.val != nil)
+		x.mode = constant
+
+	case *TypeName:
+		x.mode = typexpr
+		// check for cycle
+		// (it's ok to iterate forward because each named type appears at most once in path)
+		for i, prev := range path {
+			if prev == obj {
+				check.errorf(obj.pos, "illegal cycle in declaration of %s", obj.name)
+				// print cycle
+				for _, obj := range path[i:] {
+					check.errorf(obj.Pos(), "\t%s refers to", obj.Name()) // secondary error, \t indented
+				}
+				check.errorf(obj.Pos(), "\t%s", obj.Name())
+				// maintain x.mode == typexpr despite error
+				typ = Typ[Invalid]
+				break
+			}
+		}
+
+	case *Var:
+		if obj.pkg == check.pkg {
+			obj.used = true
+		}
+		check.addDeclDep(obj)
+		if typ == Typ[Invalid] {
+			return
+		}
+		x.mode = variable
+
+	case *Func:
+		check.addDeclDep(obj)
+		x.mode = value
+
+	case *Builtin:
+		x.id = obj.id
+		x.mode = builtin
+
+	case *Nil:
+		x.mode = value
+
+	default:
+		unreachable()
+	}
+
+	x.typ = typ
+}
+
+// typExpr type-checks the type expression e and returns its type, or Typ[Invalid].
+// If def != nil, e is the type specification for the named type def, declared
+// in a type declaration, and def.underlying will be set to the type of e before
+// any components of e are type-checked. Path contains the path of named types
+// referring to this type.
+//
+func (check *Checker) typExpr(e ast.Expr, def *Named, path []*TypeName) (T Type) {
+	if trace {
+		check.trace(e.Pos(), "%s", e)
+		check.indent++
+		defer func() {
+			check.indent--
+			check.trace(e.Pos(), "=> %s", T)
+		}()
+	}
+
+	T = check.typExprInternal(e, def, path)
+	assert(isTyped(T))
+	check.recordTypeAndValue(e, typexpr, T, nil)
+
+	return
+}
+
+func (check *Checker) typ(e ast.Expr) Type {
+	return check.typExpr(e, nil, nil)
+}
+
+// funcType type-checks a function or method type.
+func (check *Checker) funcType(sig *Signature, recvPar *ast.FieldList, ftyp *ast.FuncType) {
+	scope := NewScope(check.scope, token.NoPos, token.NoPos, "function")
+	check.recordScope(ftyp, scope)
+
+	recvList, _ := check.collectParams(scope, recvPar, false)
+	params, variadic := check.collectParams(scope, ftyp.Params, true)
+	results, _ := check.collectParams(scope, ftyp.Results, false)
+
+	if recvPar != nil {
+		// recv parameter list present (may be empty)
+		// spec: "The receiver is specified via an extra parameter section preceeding the
+		// method name. That parameter section must declare a single parameter, the receiver."
+		var recv *Var
+		switch len(recvList) {
+		case 0:
+			check.error(recvPar.Pos(), "method is missing receiver")
+			recv = NewParam(0, nil, "", Typ[Invalid]) // ignore recv below
+		default:
+			// more than one receiver
+			check.error(recvList[len(recvList)-1].Pos(), "method must have exactly one receiver")
+			fallthrough // continue with first receiver
+		case 1:
+			recv = recvList[0]
+		}
+		// spec: "The receiver type must be of the form T or *T where T is a type name."
+		// (ignore invalid types - error was reported before)
+		if t, _ := deref(recv.typ); t != Typ[Invalid] {
+			var err string
+			if T, _ := t.(*Named); T != nil {
+				// spec: "The type denoted by T is called the receiver base type; it must not
+				// be a pointer or interface type and it must be declared in the same package
+				// as the method."
+				if T.obj.pkg != check.pkg {
+					err = "type not defined in this package"
+				} else {
+					// TODO(gri) This is not correct if the underlying type is unknown yet.
+					switch u := T.underlying.(type) {
+					case *Basic:
+						// unsafe.Pointer is treated like a regular pointer
+						if u.kind == UnsafePointer {
+							err = "unsafe.Pointer"
+						}
+					case *Pointer, *Interface:
+						err = "pointer or interface type"
+					}
+				}
+			} else {
+				err = "basic or unnamed type"
+			}
+			if err != "" {
+				check.errorf(recv.pos, "invalid receiver %s (%s)", recv.typ, err)
+				// ok to continue
+			}
+		}
+		sig.recv = recv
+	}
+
+	sig.scope = scope
+	sig.params = NewTuple(params...)
+	sig.results = NewTuple(results...)
+	sig.variadic = variadic
+}
+
+// typExprInternal drives type checking of types.
+// Must only be called by typExpr.
+//
+func (check *Checker) typExprInternal(e ast.Expr, def *Named, path []*TypeName) Type {
+	switch e := e.(type) {
+	case *ast.BadExpr:
+		// ignore - error reported before
+
+	case *ast.Ident:
+		var x operand
+		check.ident(&x, e, def, path)
+
+		switch x.mode {
+		case typexpr:
+			typ := x.typ
+			def.setUnderlying(typ)
+			return typ
+		case invalid:
+			// ignore - error reported before
+		case novalue:
+			check.errorf(x.pos(), "%s used as type", &x)
+		default:
+			check.errorf(x.pos(), "%s is not a type", &x)
+		}
+
+	case *ast.SelectorExpr:
+		var x operand
+		check.selector(&x, e)
+
+		switch x.mode {
+		case typexpr:
+			typ := x.typ
+			def.setUnderlying(typ)
+			return typ
+		case invalid:
+			// ignore - error reported before
+		case novalue:
+			check.errorf(x.pos(), "%s used as type", &x)
+		default:
+			check.errorf(x.pos(), "%s is not a type", &x)
+		}
+
+	case *ast.ParenExpr:
+		return check.typExpr(e.X, def, path)
+
+	case *ast.ArrayType:
+		if e.Len != nil {
+			typ := new(Array)
+			def.setUnderlying(typ)
+			typ.len = check.arrayLength(e.Len)
+			typ.elem = check.typExpr(e.Elt, nil, path)
+			return typ
+
+		} else {
+			typ := new(Slice)
+			def.setUnderlying(typ)
+			typ.elem = check.typ(e.Elt)
+			return typ
+		}
+
+	case *ast.StructType:
+		typ := new(Struct)
+		def.setUnderlying(typ)
+		check.structType(typ, e, path)
+		return typ
+
+	case *ast.StarExpr:
+		typ := new(Pointer)
+		def.setUnderlying(typ)
+		typ.base = check.typ(e.X)
+		return typ
+
+	case *ast.FuncType:
+		typ := new(Signature)
+		def.setUnderlying(typ)
+		check.funcType(typ, nil, e)
+		return typ
+
+	case *ast.InterfaceType:
+		typ := new(Interface)
+		def.setUnderlying(typ)
+		check.interfaceType(typ, e, def, path)
+		return typ
+
+	case *ast.MapType:
+		typ := new(Map)
+		def.setUnderlying(typ)
+
+		typ.key = check.typ(e.Key)
+		typ.elem = check.typ(e.Value)
+
+		// spec: "The comparison operators == and != must be fully defined
+		// for operands of the key type; thus the key type must not be a
+		// function, map, or slice."
+		//
+		// Delay this check because it requires fully setup types;
+		// it is safe to continue in any case (was issue 6667).
+		check.delay(func() {
+			if !Comparable(typ.key) {
+				check.errorf(e.Key.Pos(), "invalid map key type %s", typ.key)
+			}
+		})
+
+		return typ
+
+	case *ast.ChanType:
+		typ := new(Chan)
+		def.setUnderlying(typ)
+
+		dir := SendRecv
+		switch e.Dir {
+		case ast.SEND | ast.RECV:
+			// nothing to do
+		case ast.SEND:
+			dir = SendOnly
+		case ast.RECV:
+			dir = RecvOnly
+		default:
+			check.invalidAST(e.Pos(), "unknown channel direction %d", e.Dir)
+			// ok to continue
+		}
+
+		typ.dir = dir
+		typ.elem = check.typ(e.Value)
+		return typ
+
+	default:
+		check.errorf(e.Pos(), "%s is not a type", e)
+	}
+
+	typ := Typ[Invalid]
+	def.setUnderlying(typ)
+	return typ
+}
+
+// typeOrNil type-checks the type expression (or nil value) e
+// and returns the typ of e, or nil.
+// If e is neither a type nor nil, typOrNil returns Typ[Invalid].
+//
+func (check *Checker) typOrNil(e ast.Expr) Type {
+	var x operand
+	check.rawExpr(&x, e, nil)
+	switch x.mode {
+	case invalid:
+		// ignore - error reported before
+	case novalue:
+		check.errorf(x.pos(), "%s used as type", &x)
+	case typexpr:
+		return x.typ
+	case value:
+		if x.isNil() {
+			return nil
+		}
+		fallthrough
+	default:
+		check.errorf(x.pos(), "%s is not a type", &x)
+	}
+	return Typ[Invalid]
+}
+
+func (check *Checker) arrayLength(e ast.Expr) int64 {
+	var x operand
+	check.expr(&x, e)
+	if x.mode != constant {
+		if x.mode != invalid {
+			check.errorf(x.pos(), "array length %s must be constant", &x)
+		}
+		return 0
+	}
+	if !x.isInteger() {
+		check.errorf(x.pos(), "array length %s must be integer", &x)
+		return 0
+	}
+	n, ok := exact.Int64Val(x.val)
+	if !ok || n < 0 {
+		check.errorf(x.pos(), "invalid array length %s", &x)
+		return 0
+	}
+	return n
+}
+
+func (check *Checker) collectParams(scope *Scope, list *ast.FieldList, variadicOk bool) (params []*Var, variadic bool) {
+	if list == nil {
+		return
+	}
+
+	var named, anonymous bool
+	for i, field := range list.List {
+		ftype := field.Type
+		if t, _ := ftype.(*ast.Ellipsis); t != nil {
+			ftype = t.Elt
+			if variadicOk && i == len(list.List)-1 {
+				variadic = true
+			} else {
+				check.invalidAST(field.Pos(), "... not permitted")
+				// ignore ... and continue
+			}
+		}
+		typ := check.typ(ftype)
+		// The parser ensures that f.Tag is nil and we don't
+		// care if a constructed AST contains a non-nil tag.
+		if len(field.Names) > 0 {
+			// named parameter
+			for _, name := range field.Names {
+				if name.Name == "" {
+					check.invalidAST(name.Pos(), "anonymous parameter")
+					// ok to continue
+				}
+				par := NewParam(name.Pos(), check.pkg, name.Name, typ)
+				check.declare(scope, name, par, scope.pos)
+				params = append(params, par)
+			}
+			named = true
+		} else {
+			// anonymous parameter
+			par := NewParam(ftype.Pos(), check.pkg, "", typ)
+			check.recordImplicit(field, par)
+			params = append(params, par)
+			anonymous = true
+		}
+	}
+
+	if named && anonymous {
+		check.invalidAST(list.Pos(), "list contains both named and anonymous parameters")
+		// ok to continue
+	}
+
+	// For a variadic function, change the last parameter's type from T to []T.
+	if variadic && len(params) > 0 {
+		last := params[len(params)-1]
+		last.typ = &Slice{elem: last.typ}
+	}
+
+	return
+}
+
+func (check *Checker) declareInSet(oset *objset, pos token.Pos, obj Object) bool {
+	if alt := oset.insert(obj); alt != nil {
+		check.errorf(pos, "%s redeclared", obj.Name())
+		check.reportAltDecl(alt)
+		return false
+	}
+	return true
+}
+
+func (check *Checker) interfaceType(iface *Interface, ityp *ast.InterfaceType, def *Named, path []*TypeName) {
+	// empty interface: common case
+	if ityp.Methods == nil {
+		return
+	}
+
+	// The parser ensures that field tags are nil and we don't
+	// care if a constructed AST contains non-nil tags.
+
+	// use named receiver type if available (for better error messages)
+	var recvTyp Type = iface
+	if def != nil {
+		recvTyp = def
+	}
+
+	// Phase 1: Collect explicitly declared methods, the corresponding
+	//          signature (AST) expressions, and the list of embedded
+	//          type (AST) expressions. Do not resolve signatures or
+	//          embedded types yet to avoid cycles referring to this
+	//          interface.
+
+	var (
+		mset       objset
+		signatures []ast.Expr // list of corresponding method signatures
+		embedded   []ast.Expr // list of embedded types
+	)
+	for _, f := range ityp.Methods.List {
+		if len(f.Names) > 0 {
+			// The parser ensures that there's only one method
+			// and we don't care if a constructed AST has more.
+			name := f.Names[0]
+			pos := name.Pos()
+			// spec: "As with all method sets, in an interface type,
+			// each method must have a unique non-blank name."
+			if name.Name == "_" {
+				check.errorf(pos, "invalid method name _")
+				continue
+			}
+			// Don't type-check signature yet - use an
+			// empty signature now and update it later.
+			// Since we know the receiver, set it up now
+			// (required to avoid crash in ptrRecv; see
+			// e.g. test case for issue 6638).
+			// TODO(gri) Consider marking methods signatures
+			// as incomplete, for better error messages. See
+			// also the T4 and T5 tests in testdata/cycles2.src.
+			sig := new(Signature)
+			sig.recv = NewVar(pos, check.pkg, "", recvTyp)
+			m := NewFunc(pos, check.pkg, name.Name, sig)
+			if check.declareInSet(&mset, pos, m) {
+				iface.methods = append(iface.methods, m)
+				iface.allMethods = append(iface.allMethods, m)
+				signatures = append(signatures, f.Type)
+				check.recordDef(name, m)
+			}
+		} else {
+			// embedded type
+			embedded = append(embedded, f.Type)
+		}
+	}
+
+	// Phase 2: Resolve embedded interfaces. Because an interface must not
+	//          embed itself (directly or indirectly), each embedded interface
+	//          can be fully resolved without depending on any method of this
+	//          interface (if there is a cycle or another error, the embedded
+	//          type resolves to an invalid type and is ignored).
+	//          In particular, the list of methods for each embedded interface
+	//          must be complete (it cannot depend on this interface), and so
+	//          those methods can be added to the list of all methods of this
+	//          interface.
+
+	for _, e := range embedded {
+		pos := e.Pos()
+		typ := check.typExpr(e, nil, path)
+		// Determine underlying embedded (possibly incomplete) type
+		// by following its forward chain.
+		named, _ := typ.(*Named)
+		under := underlying(named)
+		embed, _ := under.(*Interface)
+		if embed == nil {
+			if typ != Typ[Invalid] {
+				check.errorf(pos, "%s is not an interface", typ)
+			}
+			continue
+		}
+		iface.embeddeds = append(iface.embeddeds, named)
+		// collect embedded methods
+		for _, m := range embed.allMethods {
+			if check.declareInSet(&mset, pos, m) {
+				iface.allMethods = append(iface.allMethods, m)
+			}
+		}
+	}
+
+	// Phase 3: At this point all methods have been collected for this interface.
+	//          It is now safe to type-check the signatures of all explicitly
+	//          declared methods, even if they refer to this interface via a cycle
+	//          and embed the methods of this interface in a parameter of interface
+	//          type.
+
+	for i, m := range iface.methods {
+		expr := signatures[i]
+		typ := check.typ(expr)
+		sig, _ := typ.(*Signature)
+		if sig == nil {
+			if typ != Typ[Invalid] {
+				check.invalidAST(expr.Pos(), "%s is not a method signature", typ)
+			}
+			continue // keep method with empty method signature
+		}
+		// update signature, but keep recv that was set up before
+		old := m.typ.(*Signature)
+		sig.recv = old.recv
+		*old = *sig // update signature (don't replace it!)
+	}
+
+	// TODO(gri) The list of explicit methods is only sorted for now to
+	// produce the same Interface as NewInterface. We may be able to
+	// claim source order in the future. Revisit.
+	sort.Sort(byUniqueMethodName(iface.methods))
+
+	// TODO(gri) The list of embedded types is only sorted for now to
+	// produce the same Interface as NewInterface. We may be able to
+	// claim source order in the future. Revisit.
+	sort.Sort(byUniqueTypeName(iface.embeddeds))
+
+	sort.Sort(byUniqueMethodName(iface.allMethods))
+}
+
+// byUniqueTypeName named type lists can be sorted by their unique type names.
+type byUniqueTypeName []*Named
+
+func (a byUniqueTypeName) Len() int           { return len(a) }
+func (a byUniqueTypeName) Less(i, j int) bool { return a[i].obj.Id() < a[j].obj.Id() }
+func (a byUniqueTypeName) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
+
+// byUniqueMethodName method lists can be sorted by their unique method names.
+type byUniqueMethodName []*Func
+
+func (a byUniqueMethodName) Len() int           { return len(a) }
+func (a byUniqueMethodName) Less(i, j int) bool { return a[i].Id() < a[j].Id() }
+func (a byUniqueMethodName) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
+
+func (check *Checker) tag(t *ast.BasicLit) string {
+	if t != nil {
+		if t.Kind == token.STRING {
+			if val, err := strconv.Unquote(t.Value); err == nil {
+				return val
+			}
+		}
+		check.invalidAST(t.Pos(), "incorrect tag syntax: %q", t.Value)
+	}
+	return ""
+}
+
+func (check *Checker) structType(styp *Struct, e *ast.StructType, path []*TypeName) {
+	list := e.Fields
+	if list == nil {
+		return
+	}
+
+	// struct fields and tags
+	var fields []*Var
+	var tags []string
+
+	// for double-declaration checks
+	var fset objset
+
+	// current field typ and tag
+	var typ Type
+	var tag string
+	// anonymous != nil indicates an anonymous field.
+	add := func(field *ast.Field, ident *ast.Ident, anonymous *TypeName, pos token.Pos) {
+		if tag != "" && tags == nil {
+			tags = make([]string, len(fields))
+		}
+		if tags != nil {
+			tags = append(tags, tag)
+		}
+
+		name := ident.Name
+		fld := NewField(pos, check.pkg, name, typ, anonymous != nil)
+		// spec: "Within a struct, non-blank field names must be unique."
+		if name == "_" || check.declareInSet(&fset, pos, fld) {
+			fields = append(fields, fld)
+			check.recordDef(ident, fld)
+		}
+		if anonymous != nil {
+			check.recordUse(ident, anonymous)
+		}
+	}
+
+	for _, f := range list.List {
+		typ = check.typExpr(f.Type, nil, path)
+		tag = check.tag(f.Tag)
+		if len(f.Names) > 0 {
+			// named fields
+			for _, name := range f.Names {
+				add(f, name, nil, name.Pos())
+			}
+		} else {
+			// anonymous field
+			name := anonymousFieldIdent(f.Type)
+			pos := f.Type.Pos()
+			t, isPtr := deref(typ)
+			switch t := t.(type) {
+			case *Basic:
+				if t == Typ[Invalid] {
+					// error was reported before
+					continue
+				}
+				// unsafe.Pointer is treated like a regular pointer
+				if t.kind == UnsafePointer {
+					check.errorf(pos, "anonymous field type cannot be unsafe.Pointer")
+					continue
+				}
+				add(f, name, Universe.Lookup(t.name).(*TypeName), pos)
+
+			case *Named:
+				// spec: "An embedded type must be specified as a type name
+				// T or as a pointer to a non-interface type name *T, and T
+				// itself may not be a pointer type."
+				switch u := t.underlying.(type) {
+				case *Basic:
+					// unsafe.Pointer is treated like a regular pointer
+					if u.kind == UnsafePointer {
+						check.errorf(pos, "anonymous field type cannot be unsafe.Pointer")
+						continue
+					}
+				case *Pointer:
+					check.errorf(pos, "anonymous field type cannot be a pointer")
+					continue
+				case *Interface:
+					if isPtr {
+						check.errorf(pos, "anonymous field type cannot be a pointer to an interface")
+						continue
+					}
+				}
+				add(f, name, t.obj, pos)
+
+			default:
+				check.invalidAST(pos, "anonymous field type %s must be named", typ)
+			}
+		}
+	}
+
+	styp.fields = fields
+	styp.tags = tags
+}
+
+func anonymousFieldIdent(e ast.Expr) *ast.Ident {
+	switch e := e.(type) {
+	case *ast.Ident:
+		return e
+	case *ast.StarExpr:
+		return anonymousFieldIdent(e.X)
+	case *ast.SelectorExpr:
+		return e.Sel
+	}
+	return nil // invalid anonymous field
+}
diff --git a/go/types/universe.go b/go/types/universe.go
new file mode 100644
index 0000000..12a34ef
--- /dev/null
+++ b/go/types/universe.go
@@ -0,0 +1,224 @@
+// Copyright 2011 The Go 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 sets up the universe scope and the unsafe package.
+
+package types
+
+import (
+	"go/token"
+	"strings"
+
+	"golang.org/x/tools/go/exact"
+)
+
+var (
+	Universe     *Scope
+	Unsafe       *Package
+	universeIota *Const
+	universeByte *Basic // uint8 alias, but has name "byte"
+	universeRune *Basic // int32 alias, but has name "rune"
+)
+
+var Typ = []*Basic{
+	Invalid: {Invalid, 0, "invalid type"},
+
+	Bool:          {Bool, IsBoolean, "bool"},
+	Int:           {Int, IsInteger, "int"},
+	Int8:          {Int8, IsInteger, "int8"},
+	Int16:         {Int16, IsInteger, "int16"},
+	Int32:         {Int32, IsInteger, "int32"},
+	Int64:         {Int64, IsInteger, "int64"},
+	Uint:          {Uint, IsInteger | IsUnsigned, "uint"},
+	Uint8:         {Uint8, IsInteger | IsUnsigned, "uint8"},
+	Uint16:        {Uint16, IsInteger | IsUnsigned, "uint16"},
+	Uint32:        {Uint32, IsInteger | IsUnsigned, "uint32"},
+	Uint64:        {Uint64, IsInteger | IsUnsigned, "uint64"},
+	Uintptr:       {Uintptr, IsInteger | IsUnsigned, "uintptr"},
+	Float32:       {Float32, IsFloat, "float32"},
+	Float64:       {Float64, IsFloat, "float64"},
+	Complex64:     {Complex64, IsComplex, "complex64"},
+	Complex128:    {Complex128, IsComplex, "complex128"},
+	String:        {String, IsString, "string"},
+	UnsafePointer: {UnsafePointer, 0, "Pointer"},
+
+	UntypedBool:    {UntypedBool, IsBoolean | IsUntyped, "untyped bool"},
+	UntypedInt:     {UntypedInt, IsInteger | IsUntyped, "untyped int"},
+	UntypedRune:    {UntypedRune, IsInteger | IsUntyped, "untyped rune"},
+	UntypedFloat:   {UntypedFloat, IsFloat | IsUntyped, "untyped float"},
+	UntypedComplex: {UntypedComplex, IsComplex | IsUntyped, "untyped complex"},
+	UntypedString:  {UntypedString, IsString | IsUntyped, "untyped string"},
+	UntypedNil:     {UntypedNil, IsUntyped, "untyped nil"},
+}
+
+var aliases = [...]*Basic{
+	{Byte, IsInteger | IsUnsigned, "byte"},
+	{Rune, IsInteger, "rune"},
+}
+
+func defPredeclaredTypes() {
+	for _, t := range Typ {
+		def(NewTypeName(token.NoPos, nil, t.name, t))
+	}
+	for _, t := range aliases {
+		def(NewTypeName(token.NoPos, nil, t.name, t))
+	}
+
+	// Error has a nil package in its qualified name since it is in no package
+	res := NewVar(token.NoPos, nil, "", Typ[String])
+	sig := &Signature{results: NewTuple(res)}
+	err := NewFunc(token.NoPos, nil, "Error", sig)
+	typ := &Named{underlying: NewInterface([]*Func{err}, nil).Complete()}
+	sig.recv = NewVar(token.NoPos, nil, "", typ)
+	def(NewTypeName(token.NoPos, nil, "error", typ))
+}
+
+var predeclaredConsts = [...]struct {
+	name string
+	kind BasicKind
+	val  exact.Value
+}{
+	{"true", UntypedBool, exact.MakeBool(true)},
+	{"false", UntypedBool, exact.MakeBool(false)},
+	{"iota", UntypedInt, exact.MakeInt64(0)},
+}
+
+func defPredeclaredConsts() {
+	for _, c := range predeclaredConsts {
+		def(NewConst(token.NoPos, nil, c.name, Typ[c.kind], c.val))
+	}
+}
+
+func defPredeclaredNil() {
+	def(&Nil{object{name: "nil", typ: Typ[UntypedNil]}})
+}
+
+// A builtinId is the id of a builtin function.
+type builtinId int
+
+const (
+	// universe scope
+	_Append builtinId = iota
+	_Cap
+	_Close
+	_Complex
+	_Copy
+	_Delete
+	_Imag
+	_Len
+	_Make
+	_New
+	_Panic
+	_Print
+	_Println
+	_Real
+	_Recover
+
+	// package unsafe
+	_Alignof
+	_Offsetof
+	_Sizeof
+
+	// testing support
+	_Assert
+	_Trace
+)
+
+var predeclaredFuncs = [...]struct {
+	name     string
+	nargs    int
+	variadic bool
+	kind     exprKind
+}{
+	_Append:  {"append", 1, true, expression},
+	_Cap:     {"cap", 1, false, expression},
+	_Close:   {"close", 1, false, statement},
+	_Complex: {"complex", 2, false, expression},
+	_Copy:    {"copy", 2, false, statement},
+	_Delete:  {"delete", 2, false, statement},
+	_Imag:    {"imag", 1, false, expression},
+	_Len:     {"len", 1, false, expression},
+	_Make:    {"make", 1, true, expression},
+	_New:     {"new", 1, false, expression},
+	_Panic:   {"panic", 1, false, statement},
+	_Print:   {"print", 0, true, statement},
+	_Println: {"println", 0, true, statement},
+	_Real:    {"real", 1, false, expression},
+	_Recover: {"recover", 0, false, statement},
+
+	_Alignof:  {"Alignof", 1, false, expression},
+	_Offsetof: {"Offsetof", 1, false, expression},
+	_Sizeof:   {"Sizeof", 1, false, expression},
+
+	_Assert: {"assert", 1, false, statement},
+	_Trace:  {"trace", 0, true, statement},
+}
+
+func defPredeclaredFuncs() {
+	for i := range predeclaredFuncs {
+		id := builtinId(i)
+		if id == _Assert || id == _Trace {
+			continue // only define these in testing environment
+		}
+		def(newBuiltin(id))
+	}
+}
+
+// DefPredeclaredTestFuncs defines the assert and trace built-ins.
+// These built-ins are intended for debugging and testing of this
+// package only.
+func DefPredeclaredTestFuncs() {
+	if Universe.Lookup("assert") != nil {
+		return // already defined
+	}
+	def(newBuiltin(_Assert))
+	def(newBuiltin(_Trace))
+}
+
+func init() {
+	Universe = NewScope(nil, token.NoPos, token.NoPos, "universe")
+	Unsafe = NewPackage("unsafe", "unsafe")
+	Unsafe.complete = true
+
+	defPredeclaredTypes()
+	defPredeclaredConsts()
+	defPredeclaredNil()
+	defPredeclaredFuncs()
+
+	universeIota = Universe.Lookup("iota").(*Const)
+	universeByte = Universe.Lookup("byte").(*TypeName).typ.(*Basic)
+	universeRune = Universe.Lookup("rune").(*TypeName).typ.(*Basic)
+}
+
+// Objects with names containing blanks are internal and not entered into
+// a scope. Objects with exported names are inserted in the unsafe package
+// scope; other objects are inserted in the universe scope.
+//
+func def(obj Object) {
+	name := obj.Name()
+	if strings.Index(name, " ") >= 0 {
+		return // nothing to do
+	}
+	// fix Obj link for named types
+	if typ, ok := obj.Type().(*Named); ok {
+		typ.obj = obj.(*TypeName)
+	}
+	// exported identifiers go into package unsafe
+	scope := Universe
+	if obj.Exported() {
+		scope = Unsafe.scope
+		// set Pkg field
+		switch obj := obj.(type) {
+		case *TypeName:
+			obj.pkg = Unsafe
+		case *Builtin:
+			obj.pkg = Unsafe
+		default:
+			unreachable()
+		}
+	}
+	if scope.Insert(obj) != nil {
+		panic("internal error: double declaration")
+	}
+}
diff --git a/go/vcs/discovery.go b/go/vcs/discovery.go
new file mode 100644
index 0000000..c4b0e3d
--- /dev/null
+++ b/go/vcs/discovery.go
@@ -0,0 +1,76 @@
+// Copyright 2012 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package vcs
+
+import (
+	"encoding/xml"
+	"fmt"
+	"io"
+	"strings"
+)
+
+// charsetReader returns a reader for the given charset. Currently
+// it only supports UTF-8 and ASCII. Otherwise, it returns a meaningful
+// error which is printed by go get, so the user can find why the package
+// wasn't downloaded if the encoding is not supported. Note that, in
+// order to reduce potential errors, ASCII is treated as UTF-8 (i.e. characters
+// greater than 0x7f are not rejected).
+func charsetReader(charset string, input io.Reader) (io.Reader, error) {
+	switch strings.ToLower(charset) {
+	case "ascii":
+		return input, nil
+	default:
+		return nil, fmt.Errorf("can't decode XML document using charset %q", charset)
+	}
+}
+
+// parseMetaGoImports returns meta imports from the HTML in r.
+// Parsing ends at the end of the <head> section or the beginning of the <body>.
+func parseMetaGoImports(r io.Reader) (imports []metaImport, err error) {
+	d := xml.NewDecoder(r)
+	d.CharsetReader = charsetReader
+	d.Strict = false
+	var t xml.Token
+	for {
+		t, err = d.Token()
+		if err != nil {
+			if err == io.EOF {
+				err = nil
+			}
+			return
+		}
+		if e, ok := t.(xml.StartElement); ok && strings.EqualFold(e.Name.Local, "body") {
+			return
+		}
+		if e, ok := t.(xml.EndElement); ok && strings.EqualFold(e.Name.Local, "head") {
+			return
+		}
+		e, ok := t.(xml.StartElement)
+		if !ok || !strings.EqualFold(e.Name.Local, "meta") {
+			continue
+		}
+		if attrValue(e.Attr, "name") != "go-import" {
+			continue
+		}
+		if f := strings.Fields(attrValue(e.Attr, "content")); len(f) == 3 {
+			imports = append(imports, metaImport{
+				Prefix:   f[0],
+				VCS:      f[1],
+				RepoRoot: f[2],
+			})
+		}
+	}
+}
+
+// attrValue returns the attribute value for the case-insensitive key
+// `name', or the empty string if nothing is found.
+func attrValue(attrs []xml.Attr, name string) string {
+	for _, a := range attrs {
+		if strings.EqualFold(a.Name.Local, name) {
+			return a.Value
+		}
+	}
+	return ""
+}
diff --git a/go/vcs/env.go b/go/vcs/env.go
new file mode 100644
index 0000000..e846f5b
--- /dev/null
+++ b/go/vcs/env.go
@@ -0,0 +1,39 @@
+// Copyright 2013 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package vcs
+
+import (
+	"os"
+	"strings"
+)
+
+// envForDir returns a copy of the environment
+// suitable for running in the given directory.
+// The environment is the current process's environment
+// but with an updated $PWD, so that an os.Getwd in the
+// child will be faster.
+func envForDir(dir string) []string {
+	env := os.Environ()
+	// Internally we only use rooted paths, so dir is rooted.
+	// Even if dir is not rooted, no harm done.
+	return mergeEnvLists([]string{"PWD=" + dir}, env)
+}
+
+// mergeEnvLists merges the two environment lists such that
+// variables with the same name in "in" replace those in "out".
+func mergeEnvLists(in, out []string) []string {
+NextVar:
+	for _, inkv := range in {
+		k := strings.SplitAfterN(inkv, "=", 2)[0]
+		for i, outkv := range out {
+			if strings.HasPrefix(outkv, k) {
+				out[i] = inkv
+				continue NextVar
+			}
+		}
+		out = append(out, inkv)
+	}
+	return out
+}
diff --git a/go/vcs/http.go b/go/vcs/http.go
new file mode 100644
index 0000000..9618818
--- /dev/null
+++ b/go/vcs/http.go
@@ -0,0 +1,80 @@
+// Copyright 2012 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package vcs
+
+import (
+	"fmt"
+	"io"
+	"io/ioutil"
+	"log"
+	"net/http"
+	"net/url"
+)
+
+// httpClient is the default HTTP client, but a variable so it can be
+// changed by tests, without modifying http.DefaultClient.
+var httpClient = http.DefaultClient
+
+// httpGET returns the data from an HTTP GET request for the given URL.
+func httpGET(url string) ([]byte, error) {
+	resp, err := httpClient.Get(url)
+	if err != nil {
+		return nil, err
+	}
+	defer resp.Body.Close()
+	if resp.StatusCode != 200 {
+		return nil, fmt.Errorf("%s: %s", url, resp.Status)
+	}
+	b, err := ioutil.ReadAll(resp.Body)
+	if err != nil {
+		return nil, fmt.Errorf("%s: %v", url, err)
+	}
+	return b, nil
+}
+
+// httpsOrHTTP returns the body of either the importPath's
+// https resource or, if unavailable, the http resource.
+func httpsOrHTTP(importPath string) (urlStr string, body io.ReadCloser, err error) {
+	fetch := func(scheme string) (urlStr string, res *http.Response, err error) {
+		u, err := url.Parse(scheme + "://" + importPath)
+		if err != nil {
+			return "", nil, err
+		}
+		u.RawQuery = "go-get=1"
+		urlStr = u.String()
+		if Verbose {
+			log.Printf("Fetching %s", urlStr)
+		}
+		res, err = httpClient.Get(urlStr)
+		return
+	}
+	closeBody := func(res *http.Response) {
+		if res != nil {
+			res.Body.Close()
+		}
+	}
+	urlStr, res, err := fetch("https")
+	if err != nil || res.StatusCode != 200 {
+		if Verbose {
+			if err != nil {
+				log.Printf("https fetch failed.")
+			} else {
+				log.Printf("ignoring https fetch with status code %d", res.StatusCode)
+			}
+		}
+		closeBody(res)
+		urlStr, res, err = fetch("http")
+	}
+	if err != nil {
+		closeBody(res)
+		return "", nil, err
+	}
+	// Note: accepting a non-200 OK here, so people can serve a
+	// meta import in their http 404 page.
+	if Verbose {
+		log.Printf("Parsing meta tags from %s (status code %d)", urlStr, res.StatusCode)
+	}
+	return urlStr, res.Body, nil
+}
diff --git a/go/vcs/vcs.go b/go/vcs/vcs.go
new file mode 100644
index 0000000..2d9b7de
--- /dev/null
+++ b/go/vcs/vcs.go
@@ -0,0 +1,754 @@
+// Copyright 2012 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package vcs // import "golang.org/x/tools/go/vcs"
+
+import (
+	"bytes"
+	"encoding/json"
+	"errors"
+	"fmt"
+	"log"
+	"os"
+	"os/exec"
+	"path/filepath"
+	"regexp"
+	"strconv"
+	"strings"
+)
+
+// Verbose enables verbose operation logging.
+var Verbose bool
+
+// ShowCmd controls whether VCS commands are printed.
+var ShowCmd bool
+
+// A Cmd describes how to use a version control system
+// like Mercurial, Git, or Subversion.
+type Cmd struct {
+	Name string
+	Cmd  string // name of binary to invoke command
+
+	CreateCmd   string // command to download a fresh copy of a repository
+	DownloadCmd string // command to download updates into an existing repository
+
+	TagCmd         []TagCmd // commands to list tags
+	TagLookupCmd   []TagCmd // commands to lookup tags before running tagSyncCmd
+	TagSyncCmd     string   // command to sync to specific tag
+	TagSyncDefault string   // command to sync to default tag
+
+	LogCmd string // command to list repository changelogs in an XML format
+
+	Scheme  []string
+	PingCmd string
+}
+
+// A TagCmd describes a command to list available tags
+// that can be passed to Cmd.TagSyncCmd.
+type TagCmd struct {
+	Cmd     string // command to list tags
+	Pattern string // regexp to extract tags from list
+}
+
+// vcsList lists the known version control systems
+var vcsList = []*Cmd{
+	vcsHg,
+	vcsGit,
+	vcsSvn,
+	vcsBzr,
+}
+
+// ByCmd returns the version control system for the given
+// command name (hg, git, svn, bzr).
+func ByCmd(cmd string) *Cmd {
+	for _, vcs := range vcsList {
+		if vcs.Cmd == cmd {
+			return vcs
+		}
+	}
+	return nil
+}
+
+// vcsHg describes how to use Mercurial.
+var vcsHg = &Cmd{
+	Name: "Mercurial",
+	Cmd:  "hg",
+
+	CreateCmd:   "clone -U {repo} {dir}",
+	DownloadCmd: "pull",
+
+	// We allow both tag and branch names as 'tags'
+	// for selecting a version.  This lets people have
+	// a go.release.r60 branch and a go1 branch
+	// and make changes in both, without constantly
+	// editing .hgtags.
+	TagCmd: []TagCmd{
+		{"tags", `^(\S+)`},
+		{"branches", `^(\S+)`},
+	},
+	TagSyncCmd:     "update -r {tag}",
+	TagSyncDefault: "update default",
+
+	LogCmd: "log --encoding=utf-8 --limit={limit} --template={template}",
+
+	Scheme:  []string{"https", "http", "ssh"},
+	PingCmd: "identify {scheme}://{repo}",
+}
+
+// vcsGit describes how to use Git.
+var vcsGit = &Cmd{
+	Name: "Git",
+	Cmd:  "git",
+
+	CreateCmd:   "clone {repo} {dir}",
+	DownloadCmd: "pull --ff-only",
+
+	TagCmd: []TagCmd{
+		// tags/xxx matches a git tag named xxx
+		// origin/xxx matches a git branch named xxx on the default remote repository
+		{"show-ref", `(?:tags|origin)/(\S+)$`},
+	},
+	TagLookupCmd: []TagCmd{
+		{"show-ref tags/{tag} origin/{tag}", `((?:tags|origin)/\S+)$`},
+	},
+	TagSyncCmd:     "checkout {tag}",
+	TagSyncDefault: "checkout master",
+
+	Scheme:  []string{"git", "https", "http", "git+ssh"},
+	PingCmd: "ls-remote {scheme}://{repo}",
+}
+
+// vcsBzr describes how to use Bazaar.
+var vcsBzr = &Cmd{
+	Name: "Bazaar",
+	Cmd:  "bzr",
+
+	CreateCmd: "branch {repo} {dir}",
+
+	// Without --overwrite bzr will not pull tags that changed.
+	// Replace by --overwrite-tags after http://pad.lv/681792 goes in.
+	DownloadCmd: "pull --overwrite",
+
+	TagCmd:         []TagCmd{{"tags", `^(\S+)`}},
+	TagSyncCmd:     "update -r {tag}",
+	TagSyncDefault: "update -r revno:-1",
+
+	Scheme:  []string{"https", "http", "bzr", "bzr+ssh"},
+	PingCmd: "info {scheme}://{repo}",
+}
+
+// vcsSvn describes how to use Subversion.
+var vcsSvn = &Cmd{
+	Name: "Subversion",
+	Cmd:  "svn",
+
+	CreateCmd:   "checkout {repo} {dir}",
+	DownloadCmd: "update",
+
+	// There is no tag command in subversion.
+	// The branch information is all in the path names.
+
+	LogCmd: "log --xml --limit={limit}",
+
+	Scheme:  []string{"https", "http", "svn", "svn+ssh"},
+	PingCmd: "info {scheme}://{repo}",
+}
+
+func (v *Cmd) String() string {
+	return v.Name
+}
+
+// run runs the command line cmd in the given directory.
+// keyval is a list of key, value pairs.  run expands
+// instances of {key} in cmd into value, but only after
+// splitting cmd into individual arguments.
+// If an error occurs, run prints the command line and the
+// command's combined stdout+stderr to standard error.
+// Otherwise run discards the command's output.
+func (v *Cmd) run(dir string, cmd string, keyval ...string) error {
+	_, err := v.run1(dir, cmd, keyval, true)
+	return err
+}
+
+// runVerboseOnly is like run but only generates error output to standard error in verbose mode.
+func (v *Cmd) runVerboseOnly(dir string, cmd string, keyval ...string) error {
+	_, err := v.run1(dir, cmd, keyval, false)
+	return err
+}
+
+// runOutput is like run but returns the output of the command.
+func (v *Cmd) runOutput(dir string, cmd string, keyval ...string) ([]byte, error) {
+	return v.run1(dir, cmd, keyval, true)
+}
+
+// run1 is the generalized implementation of run and runOutput.
+func (v *Cmd) run1(dir string, cmdline string, keyval []string, verbose bool) ([]byte, error) {
+	m := make(map[string]string)
+	for i := 0; i < len(keyval); i += 2 {
+		m[keyval[i]] = keyval[i+1]
+	}
+	args := strings.Fields(cmdline)
+	for i, arg := range args {
+		args[i] = expand(m, arg)
+	}
+
+	_, err := exec.LookPath(v.Cmd)
+	if err != nil {
+		fmt.Fprintf(os.Stderr,
+			"go: missing %s command. See http://golang.org/s/gogetcmd\n",
+			v.Name)
+		return nil, err
+	}
+
+	cmd := exec.Command(v.Cmd, args...)
+	cmd.Dir = dir
+	cmd.Env = envForDir(cmd.Dir)
+	if ShowCmd {
+		fmt.Printf("cd %s\n", dir)
+		fmt.Printf("%s %s\n", v.Cmd, strings.Join(args, " "))
+	}
+	var buf bytes.Buffer
+	cmd.Stdout = &buf
+	cmd.Stderr = &buf
+	err = cmd.Run()
+	out := buf.Bytes()
+	if err != nil {
+		if verbose || Verbose {
+			fmt.Fprintf(os.Stderr, "# cd %s; %s %s\n", dir, v.Cmd, strings.Join(args, " "))
+			os.Stderr.Write(out)
+		}
+		return nil, err
+	}
+	return out, nil
+}
+
+// Ping pings the repo to determine if scheme used is valid.
+// This repo must be pingable with this scheme and VCS.
+func (v *Cmd) Ping(scheme, repo string) error {
+	return v.runVerboseOnly(".", v.PingCmd, "scheme", scheme, "repo", repo)
+}
+
+// Create creates a new copy of repo in dir.
+// The parent of dir must exist; dir must not.
+func (v *Cmd) Create(dir, repo string) error {
+	return v.run(".", v.CreateCmd, "dir", dir, "repo", repo)
+}
+
+// CreateAtRev creates a new copy of repo in dir at revision rev.
+// The parent of dir must exist; dir must not.
+// rev must be a valid revision in repo.
+func (v *Cmd) CreateAtRev(dir, repo, rev string) error {
+	if err := v.Create(dir, repo); err != nil {
+		return err
+	}
+	return v.run(dir, v.TagSyncCmd, "tag", rev)
+}
+
+// Download downloads any new changes for the repo in dir.
+// dir must be a valid VCS repo compatible with v.
+func (v *Cmd) Download(dir string) error {
+	return v.run(dir, v.DownloadCmd)
+}
+
+// Tags returns the list of available tags for the repo in dir.
+// dir must be a valid VCS repo compatible with v.
+func (v *Cmd) Tags(dir string) ([]string, error) {
+	var tags []string
+	for _, tc := range v.TagCmd {
+		out, err := v.runOutput(dir, tc.Cmd)
+		if err != nil {
+			return nil, err
+		}
+		re := regexp.MustCompile(`(?m-s)` + tc.Pattern)
+		for _, m := range re.FindAllStringSubmatch(string(out), -1) {
+			tags = append(tags, m[1])
+		}
+	}
+	return tags, nil
+}
+
+// TagSync syncs the repo in dir to the named tag,
+// which either is a tag returned by tags or is v.TagDefault.
+// dir must be a valid VCS repo compatible with v and the tag must exist.
+func (v *Cmd) TagSync(dir, tag string) error {
+	if v.TagSyncCmd == "" {
+		return nil
+	}
+	if tag != "" {
+		for _, tc := range v.TagLookupCmd {
+			out, err := v.runOutput(dir, tc.Cmd, "tag", tag)
+			if err != nil {
+				return err
+			}
+			re := regexp.MustCompile(`(?m-s)` + tc.Pattern)
+			m := re.FindStringSubmatch(string(out))
+			if len(m) > 1 {
+				tag = m[1]
+				break
+			}
+		}
+	}
+	if tag == "" && v.TagSyncDefault != "" {
+		return v.run(dir, v.TagSyncDefault)
+	}
+	return v.run(dir, v.TagSyncCmd, "tag", tag)
+}
+
+// Log logs the changes for the repo in dir.
+// dir must be a valid VCS repo compatible with v.
+func (v *Cmd) Log(dir, logTemplate string) ([]byte, error) {
+	if err := v.Download(dir); err != nil {
+		return []byte{}, err
+	}
+
+	const N = 50 // how many revisions to grab
+	return v.runOutput(dir, v.LogCmd, "limit", strconv.Itoa(N), "template", logTemplate)
+}
+
+// LogAtRev logs the change for repo in dir at the rev revision.
+// dir must be a valid VCS repo compatible with v.
+// rev must be a valid revision for the repo in dir.
+func (v *Cmd) LogAtRev(dir, rev, logTemplate string) ([]byte, error) {
+	if err := v.Download(dir); err != nil {
+		return []byte{}, err
+	}
+
+	// Append revision flag to LogCmd.
+	logAtRevCmd := v.LogCmd + " --rev=" + rev
+	return v.runOutput(dir, logAtRevCmd, "limit", strconv.Itoa(1), "template", logTemplate)
+}
+
+// A vcsPath describes how to convert an import path into a
+// version control system and repository name.
+type vcsPath struct {
+	prefix string                              // prefix this description applies to
+	re     string                              // pattern for import path
+	repo   string                              // repository to use (expand with match of re)
+	vcs    string                              // version control system to use (expand with match of re)
+	check  func(match map[string]string) error // additional checks
+	ping   bool                                // ping for scheme to use to download repo
+
+	regexp *regexp.Regexp // cached compiled form of re
+}
+
+// FromDir inspects dir and its parents to determine the
+// version control system and code repository to use.
+// On return, root is the import path
+// corresponding to the root of the repository
+// (thus root is a prefix of importPath).
+func FromDir(dir, srcRoot string) (vcs *Cmd, root string, err error) {
+	// Clean and double-check that dir is in (a subdirectory of) srcRoot.
+	dir = filepath.Clean(dir)
+	srcRoot = filepath.Clean(srcRoot)
+	if len(dir) <= len(srcRoot) || dir[len(srcRoot)] != filepath.Separator {
+		return nil, "", fmt.Errorf("directory %q is outside source root %q", dir, srcRoot)
+	}
+
+	for len(dir) > len(srcRoot) {
+		for _, vcs := range vcsList {
+			if fi, err := os.Stat(filepath.Join(dir, "."+vcs.Cmd)); err == nil && fi.IsDir() {
+				return vcs, dir[len(srcRoot)+1:], nil
+			}
+		}
+
+		// Move to parent.
+		ndir := filepath.Dir(dir)
+		if len(ndir) >= len(dir) {
+			// Shouldn't happen, but just in case, stop.
+			break
+		}
+		dir = ndir
+	}
+
+	return nil, "", fmt.Errorf("directory %q is not using a known version control system", dir)
+}
+
+// RepoRoot represents a version control system, a repo, and a root of
+// where to put it on disk.
+type RepoRoot struct {
+	VCS *Cmd
+
+	// repo is the repository URL, including scheme
+	Repo string
+
+	// root is the import path corresponding to the root of the
+	// repository
+	Root string
+}
+
+// RepoRootForImportPath analyzes importPath to determine the
+// version control system, and code repository to use.
+func RepoRootForImportPath(importPath string, verbose bool) (*RepoRoot, error) {
+	rr, err := RepoRootForImportPathStatic(importPath, "")
+	if err == errUnknownSite {
+		rr, err = RepoRootForImportDynamic(importPath, verbose)
+
+		// RepoRootForImportDynamic returns error detail
+		// that is irrelevant if the user didn't intend to use a
+		// dynamic import in the first place.
+		// Squelch it.
+		if err != nil {
+			if Verbose {
+				log.Printf("import %q: %v", importPath, err)
+			}
+			err = fmt.Errorf("unrecognized import path %q", importPath)
+		}
+	}
+
+	if err == nil && strings.Contains(importPath, "...") && strings.Contains(rr.Root, "...") {
+		// Do not allow wildcards in the repo root.
+		rr = nil
+		err = fmt.Errorf("cannot expand ... in %q", importPath)
+	}
+	return rr, err
+}
+
+var errUnknownSite = errors.New("dynamic lookup required to find mapping")
+
+// RepoRootForImportPathStatic attempts to map importPath to a
+// RepoRoot using the commonly-used VCS hosting sites in vcsPaths
+// (github.com/user/dir), or from a fully-qualified importPath already
+// containing its VCS type (foo.com/repo.git/dir)
+//
+// If scheme is non-empty, that scheme is forced.
+func RepoRootForImportPathStatic(importPath, scheme string) (*RepoRoot, error) {
+	if strings.Contains(importPath, "://") {
+		return nil, fmt.Errorf("invalid import path %q", importPath)
+	}
+	for _, srv := range vcsPaths {
+		if !strings.HasPrefix(importPath, srv.prefix) {
+			continue
+		}
+		m := srv.regexp.FindStringSubmatch(importPath)
+		if m == nil {
+			if srv.prefix != "" {
+				return nil, fmt.Errorf("invalid %s import path %q", srv.prefix, importPath)
+			}
+			continue
+		}
+
+		// Build map of named subexpression matches for expand.
+		match := map[string]string{
+			"prefix": srv.prefix,
+			"import": importPath,
+		}
+		for i, name := range srv.regexp.SubexpNames() {
+			if name != "" && match[name] == "" {
+				match[name] = m[i]
+			}
+		}
+		if srv.vcs != "" {
+			match["vcs"] = expand(match, srv.vcs)
+		}
+		if srv.repo != "" {
+			match["repo"] = expand(match, srv.repo)
+		}
+		if srv.check != nil {
+			if err := srv.check(match); err != nil {
+				return nil, err
+			}
+		}
+		vcs := ByCmd(match["vcs"])
+		if vcs == nil {
+			return nil, fmt.Errorf("unknown version control system %q", match["vcs"])
+		}
+		if srv.ping {
+			if scheme != "" {
+				match["repo"] = scheme + "://" + match["repo"]
+			} else {
+				for _, scheme := range vcs.Scheme {
+					if vcs.Ping(scheme, match["repo"]) == nil {
+						match["repo"] = scheme + "://" + match["repo"]
+						break
+					}
+				}
+			}
+		}
+		rr := &RepoRoot{
+			VCS:  vcs,
+			Repo: match["repo"],
+			Root: match["root"],
+		}
+		return rr, nil
+	}
+	return nil, errUnknownSite
+}
+
+// RepoRootForImportDynamic finds a *RepoRoot for a custom domain that's not
+// statically known by RepoRootForImportPathStatic.
+//
+// This handles "vanity import paths" like "name.tld/pkg/foo".
+func RepoRootForImportDynamic(importPath string, verbose bool) (*RepoRoot, error) {
+	slash := strings.Index(importPath, "/")
+	if slash < 0 {
+		return nil, errors.New("import path doesn't contain a slash")
+	}
+	host := importPath[:slash]
+	if !strings.Contains(host, ".") {
+		return nil, errors.New("import path doesn't contain a hostname")
+	}
+	urlStr, body, err := httpsOrHTTP(importPath)
+	if err != nil {
+		return nil, fmt.Errorf("http/https fetch: %v", err)
+	}
+	defer body.Close()
+	imports, err := parseMetaGoImports(body)
+	if err != nil {
+		return nil, fmt.Errorf("parsing %s: %v", importPath, err)
+	}
+	metaImport, err := matchGoImport(imports, importPath)
+	if err != nil {
+		if err != errNoMatch {
+			return nil, fmt.Errorf("parse %s: %v", urlStr, err)
+		}
+		return nil, fmt.Errorf("parse %s: no go-import meta tags", urlStr)
+	}
+	if verbose {
+		log.Printf("get %q: found meta tag %#v at %s", importPath, metaImport, urlStr)
+	}
+	// If the import was "uni.edu/bob/project", which said the
+	// prefix was "uni.edu" and the RepoRoot was "evilroot.com",
+	// make sure we don't trust Bob and check out evilroot.com to
+	// "uni.edu" yet (possibly overwriting/preempting another
+	// non-evil student).  Instead, first verify the root and see
+	// if it matches Bob's claim.
+	if metaImport.Prefix != importPath {
+		if verbose {
+			log.Printf("get %q: verifying non-authoritative meta tag", importPath)
+		}
+		urlStr0 := urlStr
+		urlStr, body, err = httpsOrHTTP(metaImport.Prefix)
+		if err != nil {
+			return nil, fmt.Errorf("fetch %s: %v", urlStr, err)
+		}
+		imports, err := parseMetaGoImports(body)
+		if err != nil {
+			return nil, fmt.Errorf("parsing %s: %v", importPath, err)
+		}
+		if len(imports) == 0 {
+			return nil, fmt.Errorf("fetch %s: no go-import meta tag", urlStr)
+		}
+		metaImport2, err := matchGoImport(imports, importPath)
+		if err != nil || metaImport != metaImport2 {
+			return nil, fmt.Errorf("%s and %s disagree about go-import for %s", urlStr0, urlStr, metaImport.Prefix)
+		}
+	}
+
+	if !strings.Contains(metaImport.RepoRoot, "://") {
+		return nil, fmt.Errorf("%s: invalid repo root %q; no scheme", urlStr, metaImport.RepoRoot)
+	}
+	rr := &RepoRoot{
+		VCS:  ByCmd(metaImport.VCS),
+		Repo: metaImport.RepoRoot,
+		Root: metaImport.Prefix,
+	}
+	if rr.VCS == nil {
+		return nil, fmt.Errorf("%s: unknown vcs %q", urlStr, metaImport.VCS)
+	}
+	return rr, nil
+}
+
+// metaImport represents the parsed <meta name="go-import"
+// content="prefix vcs reporoot" /> tags from HTML files.
+type metaImport struct {
+	Prefix, VCS, RepoRoot string
+}
+
+// errNoMatch is returned from matchGoImport when there's no applicable match.
+var errNoMatch = errors.New("no import match")
+
+// matchGoImport returns the metaImport from imports matching importPath.
+// An error is returned if there are multiple matches.
+// errNoMatch is returned if none match.
+func matchGoImport(imports []metaImport, importPath string) (_ metaImport, err error) {
+	match := -1
+	for i, im := range imports {
+		if !strings.HasPrefix(importPath, im.Prefix) {
+			continue
+		}
+		if match != -1 {
+			err = fmt.Errorf("multiple meta tags match import path %q", importPath)
+			return
+		}
+		match = i
+	}
+	if match == -1 {
+		err = errNoMatch
+		return
+	}
+	return imports[match], nil
+}
+
+// expand rewrites s to replace {k} with match[k] for each key k in match.
+func expand(match map[string]string, s string) string {
+	for k, v := range match {
+		s = strings.Replace(s, "{"+k+"}", v, -1)
+	}
+	return s
+}
+
+// vcsPaths lists the known vcs paths.
+var vcsPaths = []*vcsPath{
+	// go.googlesource.com
+	{
+		prefix: "go.googlesource.com",
+		re:     `^(?P<root>go\.googlesource\.com/[A-Za-z0-9_.\-]+/?)$`,
+		vcs:    "git",
+		repo:   "https://{root}",
+		check:  noVCSSuffix,
+	},
+
+	// Google Code - new syntax
+	{
+		prefix: "code.google.com/",
+		re:     `^(?P<root>code\.google\.com/[pr]/(?P<project>[a-z0-9\-]+)(\.(?P<subrepo>[a-z0-9\-]+))?)(/[A-Za-z0-9_.\-]+)*$`,
+		repo:   "https://{root}",
+		check:  googleCodeVCS,
+	},
+
+	// Google Code - old syntax
+	{
+		re:    `^(?P<project>[a-z0-9_\-.]+)\.googlecode\.com/(git|hg|svn)(?P<path>/.*)?$`,
+		check: oldGoogleCode,
+	},
+
+	// Github
+	{
+		prefix: "github.com/",
+		re:     `^(?P<root>github\.com/[A-Za-z0-9_.\-]+/[A-Za-z0-9_.\-]+)(/[A-Za-z0-9_.\-]+)*$`,
+		vcs:    "git",
+		repo:   "https://{root}",
+		check:  noVCSSuffix,
+	},
+
+	// Bitbucket
+	{
+		prefix: "bitbucket.org/",
+		re:     `^(?P<root>bitbucket\.org/(?P<bitname>[A-Za-z0-9_.\-]+/[A-Za-z0-9_.\-]+))(/[A-Za-z0-9_.\-]+)*$`,
+		repo:   "https://{root}",
+		check:  bitbucketVCS,
+	},
+
+	// Launchpad
+	{
+		prefix: "launchpad.net/",
+		re:     `^(?P<root>launchpad\.net/((?P<project>[A-Za-z0-9_.\-]+)(?P<series>/[A-Za-z0-9_.\-]+)?|~[A-Za-z0-9_.\-]+/(\+junk|[A-Za-z0-9_.\-]+)/[A-Za-z0-9_.\-]+))(/[A-Za-z0-9_.\-]+)*$`,
+		vcs:    "bzr",
+		repo:   "https://{root}",
+		check:  launchpadVCS,
+	},
+
+	// General syntax for any server.
+	{
+		re:   `^(?P<root>(?P<repo>([a-z0-9.\-]+\.)+[a-z0-9.\-]+(:[0-9]+)?/[A-Za-z0-9_.\-/]*?)\.(?P<vcs>bzr|git|hg|svn))(/[A-Za-z0-9_.\-]+)*$`,
+		ping: true,
+	},
+}
+
+func init() {
+	// fill in cached regexps.
+	// Doing this eagerly discovers invalid regexp syntax
+	// without having to run a command that needs that regexp.
+	for _, srv := range vcsPaths {
+		srv.regexp = regexp.MustCompile(srv.re)
+	}
+}
+
+// noVCSSuffix checks that the repository name does not
+// end in .foo for any version control system foo.
+// The usual culprit is ".git".
+func noVCSSuffix(match map[string]string) error {
+	repo := match["repo"]
+	for _, vcs := range vcsList {
+		if strings.HasSuffix(repo, "."+vcs.Cmd) {
+			return fmt.Errorf("invalid version control suffix in %s path", match["prefix"])
+		}
+	}
+	return nil
+}
+
+var googleCheckout = regexp.MustCompile(`id="checkoutcmd">(hg|git|svn)`)
+
+// googleCodeVCS determines the version control system for
+// a code.google.com repository, by scraping the project's
+// /source/checkout page.
+func googleCodeVCS(match map[string]string) error {
+	if err := noVCSSuffix(match); err != nil {
+		return err
+	}
+	data, err := httpGET(expand(match, "https://code.google.com/p/{project}/source/checkout?repo={subrepo}"))
+	if err != nil {
+		return err
+	}
+
+	if m := googleCheckout.FindSubmatch(data); m != nil {
+		if vcs := ByCmd(string(m[1])); vcs != nil {
+			// Subversion requires the old URLs.
+			// TODO: Test.
+			if vcs == vcsSvn {
+				if match["subrepo"] != "" {
+					return fmt.Errorf("sub-repositories not supported in Google Code Subversion projects")
+				}
+				match["repo"] = expand(match, "https://{project}.googlecode.com/svn")
+			}
+			match["vcs"] = vcs.Cmd
+			return nil
+		}
+	}
+
+	return fmt.Errorf("unable to detect version control system for code.google.com/ path")
+}
+
+// oldGoogleCode is invoked for old-style foo.googlecode.com paths.
+// It prints an error giving the equivalent new path.
+func oldGoogleCode(match map[string]string) error {
+	return fmt.Errorf("invalid Google Code import path: use %s instead",
+		expand(match, "code.google.com/p/{project}{path}"))
+}
+
+// bitbucketVCS determines the version control system for a
+// Bitbucket repository, by using the Bitbucket API.
+func bitbucketVCS(match map[string]string) error {
+	if err := noVCSSuffix(match); err != nil {
+		return err
+	}
+
+	var resp struct {
+		SCM string `json:"scm"`
+	}
+	url := expand(match, "https://api.bitbucket.org/1.0/repositories/{bitname}")
+	data, err := httpGET(url)
+	if err != nil {
+		return err
+	}
+	if err := json.Unmarshal(data, &resp); err != nil {
+		return fmt.Errorf("decoding %s: %v", url, err)
+	}
+
+	if ByCmd(resp.SCM) != nil {
+		match["vcs"] = resp.SCM
+		if resp.SCM == "git" {
+			match["repo"] += ".git"
+		}
+		return nil
+	}
+
+	return fmt.Errorf("unable to detect version control system for bitbucket.org/ path")
+}
+
+// launchpadVCS solves the ambiguity for "lp.net/project/foo". In this case,
+// "foo" could be a series name registered in Launchpad with its own branch,
+// and it could also be the name of a directory within the main project
+// branch one level up.
+func launchpadVCS(match map[string]string) error {
+	if match["project"] == "" || match["series"] == "" {
+		return nil
+	}
+	_, err := httpGET(expand(match, "https://code.launchpad.net/{project}{series}/.bzr/branch-format"))
+	if err != nil {
+		match["root"] = expand(match, "launchpad.net/{project}")
+		match["repo"] = expand(match, "https://{root}")
+	}
+	return nil
+}
diff --git a/go/vcs/vcs_test.go b/go/vcs/vcs_test.go
new file mode 100644
index 0000000..d77f20b
--- /dev/null
+++ b/go/vcs/vcs_test.go
@@ -0,0 +1,135 @@
+// Copyright 2013 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package vcs
+
+import (
+	"io/ioutil"
+	"os"
+	"path/filepath"
+	"reflect"
+	"runtime"
+	"strings"
+	"testing"
+)
+
+// Test that RepoRootForImportPath creates the correct RepoRoot for a given importPath.
+// TODO(cmang): Add tests for SVN and BZR.
+func TestRepoRootForImportPath(t *testing.T) {
+	if runtime.GOOS == "android" {
+		t.Skipf("incomplete source tree on %s", runtime.GOOS)
+	}
+
+	tests := []struct {
+		path string
+		want *RepoRoot
+	}{
+		{
+			"code.google.com/p/go",
+			&RepoRoot{
+				VCS:  vcsHg,
+				Repo: "https://code.google.com/p/go",
+			},
+		},
+		{
+			"code.google.com/r/go",
+			&RepoRoot{
+				VCS:  vcsHg,
+				Repo: "https://code.google.com/r/go",
+			},
+		},
+		{
+			"github.com/golang/groupcache",
+			&RepoRoot{
+				VCS:  vcsGit,
+				Repo: "https://github.com/golang/groupcache",
+			},
+		},
+	}
+
+	for _, test := range tests {
+		got, err := RepoRootForImportPath(test.path, false)
+		if err != nil {
+			t.Errorf("RepoRootForImport(%q): %v", test.path, err)
+			continue
+		}
+		want := test.want
+		if got.VCS.Name != want.VCS.Name || got.Repo != want.Repo {
+			t.Errorf("RepoRootForImport(%q) = VCS(%s) Repo(%s), want VCS(%s) Repo(%s)", test.path, got.VCS, got.Repo, want.VCS, want.Repo)
+		}
+	}
+}
+
+// Test that FromDir correctly inspects a given directory and returns the right VCS.
+func TestFromDir(t *testing.T) {
+	type testStruct struct {
+		path string
+		want *Cmd
+	}
+
+	tests := make([]testStruct, len(vcsList))
+	tempDir, err := ioutil.TempDir("", "vcstest")
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer os.RemoveAll(tempDir)
+
+	for i, vcs := range vcsList {
+		tests[i] = testStruct{
+			filepath.Join(tempDir, vcs.Name, "."+vcs.Cmd),
+			vcs,
+		}
+	}
+
+	for _, test := range tests {
+		os.MkdirAll(test.path, 0755)
+		got, _, _ := FromDir(test.path, tempDir)
+		if got.Name != test.want.Name {
+			t.Errorf("FromDir(%q, %q) = %s, want %s", test.path, tempDir, got, test.want)
+		}
+		os.RemoveAll(test.path)
+	}
+}
+
+var parseMetaGoImportsTests = []struct {
+	in  string
+	out []metaImport
+}{
+	{
+		`<meta name="go-import" content="foo/bar git https://github.com/rsc/foo/bar">`,
+		[]metaImport{{"foo/bar", "git", "https://github.com/rsc/foo/bar"}},
+	},
+	{
+		`<meta name="go-import" content="foo/bar git https://github.com/rsc/foo/bar">
+		<meta name="go-import" content="baz/quux git http://github.com/rsc/baz/quux">`,
+		[]metaImport{
+			{"foo/bar", "git", "https://github.com/rsc/foo/bar"},
+			{"baz/quux", "git", "http://github.com/rsc/baz/quux"},
+		},
+	},
+	{
+		`<head>
+		<meta name="go-import" content="foo/bar git https://github.com/rsc/foo/bar">
+		</head>`,
+		[]metaImport{{"foo/bar", "git", "https://github.com/rsc/foo/bar"}},
+	},
+	{
+		`<meta name="go-import" content="foo/bar git https://github.com/rsc/foo/bar">
+		<body>`,
+		[]metaImport{{"foo/bar", "git", "https://github.com/rsc/foo/bar"}},
+	},
+}
+
+func TestParseMetaGoImports(t *testing.T) {
+	for i, tt := range parseMetaGoImportsTests {
+		out, err := parseMetaGoImports(strings.NewReader(tt.in))
+		if err != nil {
+			t.Errorf("test#%d: %v", i, err)
+			continue
+		}
+		if !reflect.DeepEqual(out, tt.out) {
+			t.Errorf("test#%d:\n\thave %q\n\twant %q", i, out, tt.out)
+		}
+	}
+}
diff --git a/godoc/analysis/README b/godoc/analysis/README
new file mode 100644
index 0000000..411af1c
--- /dev/null
+++ b/godoc/analysis/README
@@ -0,0 +1,111 @@
+
+Type and Pointer Analysis to-do list
+====================================
+
+Alan Donovan <adonovan@google.com>
+
+
+Overall design
+--------------
+
+We should re-run the type and pointer analyses periodically,
+as we do with the indexer.
+
+Version skew: how to mitigate the bad effects of stale URLs in old pages?
+We could record the file's length/CRC32/mtime in the go/loader, and
+refuse to decorate it with links unless they match at serving time.
+
+Use the VFS mechanism when (a) enumerating packages and (b) loading
+them.  (Requires planned changes to go/loader.)
+
+Future work: shard this using map/reduce for larger corpora.
+
+Testing: how does one test that a web page "looks right"?
+
+
+Bugs
+----
+
+(*ssa.Program).Create requires transitively error-free packages.  We
+can make this more robust by making the requirement transitively free
+of "hard" errors; soft errors are fine.
+
+Markup of compiler errors is slightly buggy because they overlap with
+other selections (e.g. Idents).  Fix.
+
+
+User Interface
+--------------
+
+CALLGRAPH:
+- Add a search box: given a search node, expand path from each entry
+  point to it.
+- Cause hovering over a given node to highlight that node, and all
+  nodes that are logically identical to it.
+- Initially expand the callgraph trees (but not their toggle divs).
+
+CALLEES:
+- The '(' links are not very discoverable.  Highlight them?
+
+Type info:
+- In the source viewer's lower pane, use a toggle div around the
+  IMPLEMENTS and METHODSETS lists, like we do in the pacakge view.
+  Only expand them initially if short.
+- Include IMPLEMENTS and METHOD SETS information in search index.
+- URLs in IMPLEMENTS/METHOD SETS always link to source, even from the
+  package docs view.  This makes sense for links to non-exported
+  types, but links to exported types and funcs should probably go to
+  other package docs.
+- Suppress toggle divs for empty method sets.
+
+Misc:
+- The [X] button in the lower pane is subject to scrolling.
+- Should the lower pane be floating?  An iframe?
+  When we change document.location by clicking on a link, it will go away.
+  How do we prevent that (a la Gmail's chat windows)?
+- Progress/status: for each file, display its analysis status, one of:
+   - not in analysis scope
+   - type analysis running...
+   - type analysis complete
+     (+ optionally: there were type errors in this file)
+   And if PTA requested:
+   - type analysis complete; PTA not attempted due to type errors
+   - PTA running...
+   - PTA complete
+- Scroll the selection into view, e.g. the vertical center, or better
+  still, under the pointer (assuming we have a mouse).
+
+
+More features
+-------------
+
+Display the REFERRERS relation?  (Useful but potentially large.)
+
+Display the INSTANTIATIONS relation? i.e. given a type T, show the set of
+syntactic constructs that can instantiate it:
+    var x T
+    x := T{...}
+    x = new(T)
+    x = make([]T, n)
+    etc
+    + all INSTANTIATIONS of all S defined as struct{t T} or [n]T
+(Potentially a lot of information.)
+(Add this to oracle too.)
+
+
+Optimisations
+-------------
+
+Each call to addLink takes a (per-file) lock.  The locking is
+fine-grained so server latency isn't terrible, but overall it makes
+the link computation quite slow.  Batch update might be better.
+
+Memory usage is now about 1.5GB for GOROOT + go.tools.  It used to be 700MB.
+
+Optimize for time and space.  The main slowdown is the network I/O
+time caused by an increase in page size of about 3x: about 2x from
+HTML, and 0.7--2.1x from JSON (unindented vs indented).  The JSON
+contains a lot of filenames (e.g. 820 copies of 16 distinct
+filenames).  20% of the HTML is L%d spans (now disabled).  The HTML
+also contains lots of tooltips for long struct/interface types.
+De-dup or just abbreviate?  The actual formatting is very fast.
diff --git a/godoc/analysis/analysis.go b/godoc/analysis/analysis.go
new file mode 100644
index 0000000..c11ecbd
--- /dev/null
+++ b/godoc/analysis/analysis.go
@@ -0,0 +1,620 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package analysis performs type and pointer analysis
+// and generates mark-up for the Go source view.
+//
+// The Run method populates a Result object by running type and
+// (optionally) pointer analysis.  The Result object is thread-safe
+// and at all times may be accessed by a serving thread, even as it is
+// progressively populated as analysis facts are derived.
+//
+// The Result is a mapping from each godoc file URL
+// (e.g. /src/fmt/print.go) to information about that file.  The
+// information is a list of HTML markup links and a JSON array of
+// structured data values.  Some of the links call client-side
+// JavaScript functions that index this array.
+//
+// The analysis computes mark-up for the following relations:
+//
+// IMPORTS: for each ast.ImportSpec, the package that it denotes.
+//
+// RESOLUTION: for each ast.Ident, its kind and type, and the location
+// of its definition.
+//
+// METHOD SETS, IMPLEMENTS: for each ast.Ident defining a named type,
+// its method-set, the set of interfaces it implements or is
+// implemented by, and its size/align values.
+//
+// CALLERS, CALLEES: for each function declaration ('func' token), its
+// callers, and for each call-site ('(' token), its callees.
+//
+// CALLGRAPH: the package docs include an interactive viewer for the
+// intra-package call graph of "fmt".
+//
+// CHANNEL PEERS: for each channel operation make/<-/close, the set of
+// other channel ops that alias the same channel(s).
+//
+// ERRORS: for each locus of a frontend (scanner/parser/type) error, the
+// location is highlighted in red and hover text provides the compiler
+// error message.
+//
+package analysis // import "golang.org/x/tools/godoc/analysis"
+
+import (
+	"fmt"
+	"go/build"
+	"go/scanner"
+	"go/token"
+	"html"
+	"io"
+	"log"
+	"os"
+	"path/filepath"
+	"runtime"
+	"sort"
+	"strings"
+	"sync"
+
+	"golang.org/x/tools/go/exact"
+	"golang.org/x/tools/go/loader"
+	"golang.org/x/tools/go/pointer"
+	"golang.org/x/tools/go/ssa"
+	"golang.org/x/tools/go/ssa/ssautil"
+	"golang.org/x/tools/go/types"
+)
+
+// -- links ------------------------------------------------------------
+
+// A Link is an HTML decoration of the bytes [Start, End) of a file.
+// Write is called before/after those bytes to emit the mark-up.
+type Link interface {
+	Start() int
+	End() int
+	Write(w io.Writer, _ int, start bool) // the godoc.LinkWriter signature
+}
+
+// An <a> element.
+type aLink struct {
+	start, end int    // =godoc.Segment
+	title      string // hover text
+	onclick    string // JS code (NB: trusted)
+	href       string // URL     (NB: trusted)
+}
+
+func (a aLink) Start() int { return a.start }
+func (a aLink) End() int   { return a.end }
+func (a aLink) Write(w io.Writer, _ int, start bool) {
+	if start {
+		fmt.Fprintf(w, `<a title='%s'`, html.EscapeString(a.title))
+		if a.onclick != "" {
+			fmt.Fprintf(w, ` onclick='%s'`, html.EscapeString(a.onclick))
+		}
+		if a.href != "" {
+			// TODO(adonovan): I think that in principle, a.href must first be
+			// url.QueryEscape'd, but if I do that, a leading slash becomes "%2F",
+			// which causes the browser to treat the path as relative, not absolute.
+			// WTF?
+			fmt.Fprintf(w, ` href='%s'`, html.EscapeString(a.href))
+		}
+		fmt.Fprintf(w, ">")
+	} else {
+		fmt.Fprintf(w, "</a>")
+	}
+}
+
+// An <a class='error'> element.
+type errorLink struct {
+	start int
+	msg   string
+}
+
+func (e errorLink) Start() int { return e.start }
+func (e errorLink) End() int   { return e.start + 1 }
+
+func (e errorLink) Write(w io.Writer, _ int, start bool) {
+	// <span> causes havoc, not sure why, so use <a>.
+	if start {
+		fmt.Fprintf(w, `<a class='error' title='%s'>`, html.EscapeString(e.msg))
+	} else {
+		fmt.Fprintf(w, "</a>")
+	}
+}
+
+// -- fileInfo ---------------------------------------------------------
+
+// FileInfo holds analysis information for the source file view.
+// Clients must not mutate it.
+type FileInfo struct {
+	Data  []interface{} // JSON serializable values
+	Links []Link        // HTML link markup
+}
+
+// A fileInfo is the server's store of hyperlinks and JSON data for a
+// particular file.
+type fileInfo struct {
+	mu        sync.Mutex
+	data      []interface{} // JSON objects
+	links     []Link
+	sorted    bool
+	hasErrors bool // TODO(adonovan): surface this in the UI
+}
+
+// addLink adds a link to the Go source file fi.
+func (fi *fileInfo) addLink(link Link) {
+	fi.mu.Lock()
+	fi.links = append(fi.links, link)
+	fi.sorted = false
+	if _, ok := link.(errorLink); ok {
+		fi.hasErrors = true
+	}
+	fi.mu.Unlock()
+}
+
+// addData adds the structured value x to the JSON data for the Go
+// source file fi.  Its index is returned.
+func (fi *fileInfo) addData(x interface{}) int {
+	fi.mu.Lock()
+	index := len(fi.data)
+	fi.data = append(fi.data, x)
+	fi.mu.Unlock()
+	return index
+}
+
+// get returns the file info in external form.
+// Callers must not mutate its fields.
+func (fi *fileInfo) get() FileInfo {
+	var r FileInfo
+	// Copy slices, to avoid races.
+	fi.mu.Lock()
+	r.Data = append(r.Data, fi.data...)
+	if !fi.sorted {
+		sort.Sort(linksByStart(fi.links))
+		fi.sorted = true
+	}
+	r.Links = append(r.Links, fi.links...)
+	fi.mu.Unlock()
+	return r
+}
+
+// PackageInfo holds analysis information for the package view.
+// Clients must not mutate it.
+type PackageInfo struct {
+	CallGraph      []*PCGNodeJSON
+	CallGraphIndex map[string]int
+	Types          []*TypeInfoJSON
+}
+
+type pkgInfo struct {
+	mu             sync.Mutex
+	callGraph      []*PCGNodeJSON
+	callGraphIndex map[string]int  // keys are (*ssa.Function).RelString()
+	types          []*TypeInfoJSON // type info for exported types
+}
+
+func (pi *pkgInfo) setCallGraph(callGraph []*PCGNodeJSON, callGraphIndex map[string]int) {
+	pi.mu.Lock()
+	pi.callGraph = callGraph
+	pi.callGraphIndex = callGraphIndex
+	pi.mu.Unlock()
+}
+
+func (pi *pkgInfo) addType(t *TypeInfoJSON) {
+	pi.mu.Lock()
+	pi.types = append(pi.types, t)
+	pi.mu.Unlock()
+}
+
+// get returns the package info in external form.
+// Callers must not mutate its fields.
+func (pi *pkgInfo) get() PackageInfo {
+	var r PackageInfo
+	// Copy slices, to avoid races.
+	pi.mu.Lock()
+	r.CallGraph = append(r.CallGraph, pi.callGraph...)
+	r.CallGraphIndex = pi.callGraphIndex
+	r.Types = append(r.Types, pi.types...)
+	pi.mu.Unlock()
+	return r
+}
+
+// -- Result -----------------------------------------------------------
+
+// Result contains the results of analysis.
+// The result contains a mapping from filenames to a set of HTML links
+// and JavaScript data referenced by the links.
+type Result struct {
+	mu        sync.Mutex           // guards maps (but not their contents)
+	status    string               // global analysis status
+	fileInfos map[string]*fileInfo // keys are godoc file URLs
+	pkgInfos  map[string]*pkgInfo  // keys are import paths
+}
+
+// fileInfo returns the fileInfo for the specified godoc file URL,
+// constructing it as needed.  Thread-safe.
+func (res *Result) fileInfo(url string) *fileInfo {
+	res.mu.Lock()
+	fi, ok := res.fileInfos[url]
+	if !ok {
+		if res.fileInfos == nil {
+			res.fileInfos = make(map[string]*fileInfo)
+		}
+		fi = new(fileInfo)
+		res.fileInfos[url] = fi
+	}
+	res.mu.Unlock()
+	return fi
+}
+
+// Status returns a human-readable description of the current analysis status.
+func (res *Result) Status() string {
+	res.mu.Lock()
+	defer res.mu.Unlock()
+	return res.status
+}
+
+func (res *Result) setStatusf(format string, args ...interface{}) {
+	res.mu.Lock()
+	res.status = fmt.Sprintf(format, args...)
+	log.Printf(format, args...)
+	res.mu.Unlock()
+}
+
+// FileInfo returns new slices containing opaque JSON values and the
+// HTML link markup for the specified godoc file URL.  Thread-safe.
+// Callers must not mutate the elements.
+// It returns "zero" if no data is available.
+//
+func (res *Result) FileInfo(url string) (fi FileInfo) {
+	return res.fileInfo(url).get()
+}
+
+// pkgInfo returns the pkgInfo for the specified import path,
+// constructing it as needed.  Thread-safe.
+func (res *Result) pkgInfo(importPath string) *pkgInfo {
+	res.mu.Lock()
+	pi, ok := res.pkgInfos[importPath]
+	if !ok {
+		if res.pkgInfos == nil {
+			res.pkgInfos = make(map[string]*pkgInfo)
+		}
+		pi = new(pkgInfo)
+		res.pkgInfos[importPath] = pi
+	}
+	res.mu.Unlock()
+	return pi
+}
+
+// PackageInfo returns new slices of JSON values for the callgraph and
+// type info for the specified package.  Thread-safe.
+// Callers must not mutate its fields.
+// PackageInfo returns "zero" if no data is available.
+//
+func (res *Result) PackageInfo(importPath string) PackageInfo {
+	return res.pkgInfo(importPath).get()
+}
+
+// -- analysis ---------------------------------------------------------
+
+type analysis struct {
+	result    *Result
+	prog      *ssa.Program
+	ops       []chanOp       // all channel ops in program
+	allNamed  []*types.Named // all named types in the program
+	ptaConfig pointer.Config
+	path2url  map[string]string // maps openable path to godoc file URL (/src/fmt/print.go)
+	pcgs      map[*ssa.Package]*packageCallGraph
+}
+
+// fileAndOffset returns the file and offset for a given pos.
+func (a *analysis) fileAndOffset(pos token.Pos) (fi *fileInfo, offset int) {
+	return a.fileAndOffsetPosn(a.prog.Fset.Position(pos))
+}
+
+// fileAndOffsetPosn returns the file and offset for a given position.
+func (a *analysis) fileAndOffsetPosn(posn token.Position) (fi *fileInfo, offset int) {
+	url := a.path2url[posn.Filename]
+	return a.result.fileInfo(url), posn.Offset
+}
+
+// posURL returns the URL of the source extent [pos, pos+len).
+func (a *analysis) posURL(pos token.Pos, len int) string {
+	if pos == token.NoPos {
+		return ""
+	}
+	posn := a.prog.Fset.Position(pos)
+	url := a.path2url[posn.Filename]
+	return fmt.Sprintf("%s?s=%d:%d#L%d",
+		url, posn.Offset, posn.Offset+len, posn.Line)
+}
+
+// ----------------------------------------------------------------------
+
+// Run runs program analysis and computes the resulting markup,
+// populating *result in a thread-safe manner, first with type
+// information then later with pointer analysis information if
+// enabled by the pta flag.
+//
+func Run(pta bool, result *Result) {
+	conf := loader.Config{
+		AllowErrors: true,
+	}
+
+	// Silence the default error handler.
+	// Don't print all errors; we'll report just
+	// one per errant package later.
+	conf.TypeChecker.Error = func(e error) {}
+
+	var roots, args []string // roots[i] ends with os.PathSeparator
+
+	// Enumerate packages in $GOROOT.
+	root := filepath.Join(runtime.GOROOT(), "src") + string(os.PathSeparator)
+	roots = append(roots, root)
+	args = allPackages(root)
+	log.Printf("GOROOT=%s: %s\n", root, args)
+
+	// Enumerate packages in $GOPATH.
+	for i, dir := range filepath.SplitList(build.Default.GOPATH) {
+		root := filepath.Join(dir, "src") + string(os.PathSeparator)
+		roots = append(roots, root)
+		pkgs := allPackages(root)
+		log.Printf("GOPATH[%d]=%s: %s\n", i, root, pkgs)
+		args = append(args, pkgs...)
+	}
+
+	// Uncomment to make startup quicker during debugging.
+	//args = []string{"golang.org/x/tools/cmd/godoc"}
+	//args = []string{"fmt"}
+
+	if _, err := conf.FromArgs(args, true); err != nil {
+		// TODO(adonovan): degrade gracefully, not fail totally.
+		// (The crippling case is a parse error in an external test file.)
+		result.setStatusf("Analysis failed: %s.", err) // import error
+		return
+	}
+
+	result.setStatusf("Loading and type-checking packages...")
+	iprog, err := conf.Load()
+	if iprog != nil {
+		// Report only the first error of each package.
+		for _, info := range iprog.AllPackages {
+			for _, err := range info.Errors {
+				fmt.Fprintln(os.Stderr, err)
+				break
+			}
+		}
+		log.Printf("Loaded %d packages.", len(iprog.AllPackages))
+	}
+	if err != nil {
+		result.setStatusf("Loading failed: %s.\n", err)
+		return
+	}
+
+	// Create SSA-form program representation.
+	// Only the transitively error-free packages are used.
+	prog := ssautil.CreateProgram(iprog, ssa.GlobalDebug)
+
+	// Compute the set of main packages, including testmain.
+	allPackages := prog.AllPackages()
+	var mainPkgs []*ssa.Package
+	if testmain := prog.CreateTestMainPackage(allPackages...); testmain != nil {
+		mainPkgs = append(mainPkgs, testmain)
+		if p := testmain.Const("packages"); p != nil {
+			log.Printf("Tested packages: %v", exact.StringVal(p.Value.Value))
+		}
+	}
+	for _, pkg := range allPackages {
+		if pkg.Object.Name() == "main" && pkg.Func("main") != nil {
+			mainPkgs = append(mainPkgs, pkg)
+		}
+	}
+	log.Print("Transitively error-free main packages: ", mainPkgs)
+
+	// Build SSA code for bodies of all functions in the whole program.
+	result.setStatusf("Constructing SSA form...")
+	prog.BuildAll()
+	log.Print("SSA construction complete")
+
+	a := analysis{
+		result: result,
+		prog:   prog,
+		pcgs:   make(map[*ssa.Package]*packageCallGraph),
+	}
+
+	// Build a mapping from openable filenames to godoc file URLs,
+	// i.e. "/src/" plus path relative to GOROOT/src or GOPATH[i]/src.
+	a.path2url = make(map[string]string)
+	for _, info := range iprog.AllPackages {
+	nextfile:
+		for _, f := range info.Files {
+			if f.Pos() == 0 {
+				continue // e.g. files generated by cgo
+			}
+			abs := iprog.Fset.File(f.Pos()).Name()
+			// Find the root to which this file belongs.
+			for _, root := range roots {
+				rel := strings.TrimPrefix(abs, root)
+				if len(rel) < len(abs) {
+					a.path2url[abs] = "/src/" + filepath.ToSlash(rel)
+					continue nextfile
+				}
+			}
+
+			log.Printf("Can't locate file %s (package %q) beneath any root",
+				abs, info.Pkg.Path())
+		}
+	}
+
+	// Add links for scanner, parser, type-checker errors.
+	// TODO(adonovan): fix: these links can overlap with
+	// identifier markup, causing the renderer to emit some
+	// characters twice.
+	errors := make(map[token.Position][]string)
+	for _, info := range iprog.AllPackages {
+		for _, err := range info.Errors {
+			switch err := err.(type) {
+			case types.Error:
+				posn := a.prog.Fset.Position(err.Pos)
+				errors[posn] = append(errors[posn], err.Msg)
+			case scanner.ErrorList:
+				for _, e := range err {
+					errors[e.Pos] = append(errors[e.Pos], e.Msg)
+				}
+			default:
+				log.Printf("Package %q has error (%T) without position: %v\n",
+					info.Pkg.Path(), err, err)
+			}
+		}
+	}
+	for posn, errs := range errors {
+		fi, offset := a.fileAndOffsetPosn(posn)
+		fi.addLink(errorLink{
+			start: offset,
+			msg:   strings.Join(errs, "\n"),
+		})
+	}
+
+	// ---------- type-based analyses ----------
+
+	// Compute the all-pairs IMPLEMENTS relation.
+	// Collect all named types, even local types
+	// (which can have methods via promotion)
+	// and the built-in "error".
+	errorType := types.Universe.Lookup("error").Type().(*types.Named)
+	a.allNamed = append(a.allNamed, errorType)
+	for _, info := range iprog.AllPackages {
+		for _, obj := range info.Defs {
+			if obj, ok := obj.(*types.TypeName); ok {
+				a.allNamed = append(a.allNamed, obj.Type().(*types.Named))
+			}
+		}
+	}
+	log.Print("Computing implements relation...")
+	facts := computeImplements(&a.prog.MethodSets, a.allNamed)
+
+	// Add the type-based analysis results.
+	log.Print("Extracting type info...")
+	for _, info := range iprog.AllPackages {
+		a.doTypeInfo(info, facts)
+	}
+
+	a.visitInstrs(pta)
+
+	result.setStatusf("Type analysis complete.")
+
+	if pta {
+		a.pointer(mainPkgs)
+	}
+}
+
+// visitInstrs visits all SSA instructions in the program.
+func (a *analysis) visitInstrs(pta bool) {
+	log.Print("Visit instructions...")
+	for fn := range ssautil.AllFunctions(a.prog) {
+		for _, b := range fn.Blocks {
+			for _, instr := range b.Instrs {
+				// CALLEES (static)
+				// (Dynamic calls require pointer analysis.)
+				//
+				// We use the SSA representation to find the static callee,
+				// since in many cases it does better than the
+				// types.Info.{Refs,Selection} information.  For example:
+				//
+				//   defer func(){}()      // static call to anon function
+				//   f := func(){}; f()    // static call to anon function
+				//   f := fmt.Println; f() // static call to named function
+				//
+				// The downside is that we get no static callee information
+				// for packages that (transitively) contain errors.
+				if site, ok := instr.(ssa.CallInstruction); ok {
+					if callee := site.Common().StaticCallee(); callee != nil {
+						// TODO(adonovan): callgraph: elide wrappers.
+						// (Do static calls ever go to wrappers?)
+						if site.Common().Pos() != token.NoPos {
+							a.addCallees(site, []*ssa.Function{callee})
+						}
+					}
+				}
+
+				if !pta {
+					continue
+				}
+
+				// CHANNEL PEERS
+				// Collect send/receive/close instructions in the whole ssa.Program.
+				for _, op := range chanOps(instr) {
+					a.ops = append(a.ops, op)
+					a.ptaConfig.AddQuery(op.ch) // add channel ssa.Value to PTA query
+				}
+			}
+		}
+	}
+	log.Print("Visit instructions complete")
+}
+
+// pointer runs the pointer analysis.
+func (a *analysis) pointer(mainPkgs []*ssa.Package) {
+	// Run the pointer analysis and build the complete callgraph.
+	a.ptaConfig.Mains = mainPkgs
+	a.ptaConfig.BuildCallGraph = true
+	a.ptaConfig.Reflection = false // (for now)
+
+	a.result.setStatusf("Pointer analysis running...")
+
+	ptares, err := pointer.Analyze(&a.ptaConfig)
+	if err != nil {
+		// If this happens, it indicates a bug.
+		a.result.setStatusf("Pointer analysis failed: %s.", err)
+		return
+	}
+	log.Print("Pointer analysis complete.")
+
+	// Add the results of pointer analysis.
+
+	a.result.setStatusf("Computing channel peers...")
+	a.doChannelPeers(ptares.Queries)
+	a.result.setStatusf("Computing dynamic call graph edges...")
+	a.doCallgraph(ptares.CallGraph)
+
+	a.result.setStatusf("Analysis complete.")
+}
+
+type linksByStart []Link
+
+func (a linksByStart) Less(i, j int) bool { return a[i].Start() < a[j].Start() }
+func (a linksByStart) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
+func (a linksByStart) Len() int           { return len(a) }
+
+// allPackages returns a new sorted slice of all packages beneath the
+// specified package root directory, e.g. $GOROOT/src or $GOPATH/src.
+// Derived from from go/ssa/stdlib_test.go
+// root must end with os.PathSeparator.
+//
+// TODO(adonovan): use buildutil.AllPackages when the tree thaws.
+func allPackages(root string) []string {
+	var pkgs []string
+	filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
+		if info == nil {
+			return nil // non-existent root directory?
+		}
+		if !info.IsDir() {
+			return nil // not a directory
+		}
+		// Prune the search if we encounter any of these names:
+		base := filepath.Base(path)
+		if base == "testdata" || strings.HasPrefix(base, ".") {
+			return filepath.SkipDir
+		}
+		pkg := filepath.ToSlash(strings.TrimPrefix(path, root))
+		switch pkg {
+		case "builtin":
+			return filepath.SkipDir
+		case "":
+			return nil // ignore root of tree
+		}
+		pkgs = append(pkgs, pkg)
+		return nil
+	})
+	return pkgs
+}
diff --git a/godoc/analysis/callgraph.go b/godoc/analysis/callgraph.go
new file mode 100644
index 0000000..a98d294
--- /dev/null
+++ b/godoc/analysis/callgraph.go
@@ -0,0 +1,351 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package analysis
+
+// This file computes the CALLERS and CALLEES relations from the call
+// graph.  CALLERS/CALLEES information is displayed in the lower pane
+// when a "func" token or ast.CallExpr.Lparen is clicked, respectively.
+
+import (
+	"fmt"
+	"go/ast"
+	"go/token"
+	"log"
+	"math/big"
+	"sort"
+
+	"golang.org/x/tools/go/callgraph"
+	"golang.org/x/tools/go/ssa"
+	"golang.org/x/tools/go/types"
+)
+
+// doCallgraph computes the CALLEES and CALLERS relations.
+func (a *analysis) doCallgraph(cg *callgraph.Graph) {
+	log.Print("Deleting synthetic nodes...")
+	// TODO(adonovan): opt: DeleteSyntheticNodes is asymptotically
+	// inefficient and can be (unpredictably) slow.
+	cg.DeleteSyntheticNodes()
+	log.Print("Synthetic nodes deleted")
+
+	// Populate nodes of package call graphs (PCGs).
+	for _, n := range cg.Nodes {
+		a.pcgAddNode(n.Func)
+	}
+	// Within each PCG, sort funcs by name.
+	for _, pcg := range a.pcgs {
+		pcg.sortNodes()
+	}
+
+	calledFuncs := make(map[ssa.CallInstruction]map[*ssa.Function]bool)
+	callingSites := make(map[*ssa.Function]map[ssa.CallInstruction]bool)
+	for _, n := range cg.Nodes {
+		for _, e := range n.Out {
+			if e.Site == nil {
+				continue // a call from a synthetic node such as <root>
+			}
+
+			// Add (site pos, callee) to calledFuncs.
+			// (Dynamic calls only.)
+			callee := e.Callee.Func
+
+			a.pcgAddEdge(n.Func, callee)
+
+			if callee.Synthetic != "" {
+				continue // call of a package initializer
+			}
+
+			if e.Site.Common().StaticCallee() == nil {
+				// dynamic call
+				// (CALLEES information for static calls
+				// is computed using SSA information.)
+				lparen := e.Site.Common().Pos()
+				if lparen != token.NoPos {
+					fns := calledFuncs[e.Site]
+					if fns == nil {
+						fns = make(map[*ssa.Function]bool)
+						calledFuncs[e.Site] = fns
+					}
+					fns[callee] = true
+				}
+			}
+
+			// Add (callee, site) to callingSites.
+			fns := callingSites[callee]
+			if fns == nil {
+				fns = make(map[ssa.CallInstruction]bool)
+				callingSites[callee] = fns
+			}
+			fns[e.Site] = true
+		}
+	}
+
+	// CALLEES.
+	log.Print("Callees...")
+	for site, fns := range calledFuncs {
+		var funcs funcsByPos
+		for fn := range fns {
+			funcs = append(funcs, fn)
+		}
+		sort.Sort(funcs)
+
+		a.addCallees(site, funcs)
+	}
+
+	// CALLERS
+	log.Print("Callers...")
+	for callee, sites := range callingSites {
+		pos := funcToken(callee)
+		if pos == token.NoPos {
+			log.Printf("CALLERS: skipping %s: no pos", callee)
+			continue
+		}
+
+		var this *types.Package // for relativizing names
+		if callee.Pkg != nil {
+			this = callee.Pkg.Object
+		}
+
+		// Compute sites grouped by parent, with text and URLs.
+		sitesByParent := make(map[*ssa.Function]sitesByPos)
+		for site := range sites {
+			fn := site.Parent()
+			sitesByParent[fn] = append(sitesByParent[fn], site)
+		}
+		var funcs funcsByPos
+		for fn := range sitesByParent {
+			funcs = append(funcs, fn)
+		}
+		sort.Sort(funcs)
+
+		v := callersJSON{
+			Callee:  callee.String(),
+			Callers: []callerJSON{}, // (JS wants non-nil)
+		}
+		for _, fn := range funcs {
+			caller := callerJSON{
+				Func:  prettyFunc(this, fn),
+				Sites: []anchorJSON{}, // (JS wants non-nil)
+			}
+			sites := sitesByParent[fn]
+			sort.Sort(sites)
+			for _, site := range sites {
+				pos := site.Common().Pos()
+				if pos != token.NoPos {
+					caller.Sites = append(caller.Sites, anchorJSON{
+						Text: fmt.Sprintf("%d", a.prog.Fset.Position(pos).Line),
+						Href: a.posURL(pos, len("(")),
+					})
+				}
+			}
+			v.Callers = append(v.Callers, caller)
+		}
+
+		fi, offset := a.fileAndOffset(pos)
+		fi.addLink(aLink{
+			start:   offset,
+			end:     offset + len("func"),
+			title:   fmt.Sprintf("%d callers", len(sites)),
+			onclick: fmt.Sprintf("onClickCallers(%d)", fi.addData(v)),
+		})
+	}
+
+	// PACKAGE CALLGRAPH
+	log.Print("Package call graph...")
+	for pkg, pcg := range a.pcgs {
+		// Maps (*ssa.Function).RelString() to index in JSON CALLGRAPH array.
+		index := make(map[string]int)
+
+		// Treat exported functions (and exported methods of
+		// exported named types) as roots even if they aren't
+		// actually called from outside the package.
+		for i, n := range pcg.nodes {
+			if i == 0 || n.fn.Object() == nil || !n.fn.Object().Exported() {
+				continue
+			}
+			recv := n.fn.Signature.Recv()
+			if recv == nil || deref(recv.Type()).(*types.Named).Obj().Exported() {
+				roots := &pcg.nodes[0].edges
+				roots.SetBit(roots, i, 1)
+			}
+			index[n.fn.RelString(pkg.Object)] = i
+		}
+
+		json := a.pcgJSON(pcg)
+
+		// TODO(adonovan): pkg.Path() is not unique!
+		// It is possible to declare a non-test package called x_test.
+		a.result.pkgInfo(pkg.Object.Path()).setCallGraph(json, index)
+	}
+}
+
+// addCallees adds client data and links for the facts that site calls fns.
+func (a *analysis) addCallees(site ssa.CallInstruction, fns []*ssa.Function) {
+	v := calleesJSON{
+		Descr:   site.Common().Description(),
+		Callees: []anchorJSON{}, // (JS wants non-nil)
+	}
+	var this *types.Package // for relativizing names
+	if p := site.Parent().Package(); p != nil {
+		this = p.Object
+	}
+
+	for _, fn := range fns {
+		v.Callees = append(v.Callees, anchorJSON{
+			Text: prettyFunc(this, fn),
+			Href: a.posURL(funcToken(fn), len("func")),
+		})
+	}
+
+	fi, offset := a.fileAndOffset(site.Common().Pos())
+	fi.addLink(aLink{
+		start:   offset,
+		end:     offset + len("("),
+		title:   fmt.Sprintf("%d callees", len(v.Callees)),
+		onclick: fmt.Sprintf("onClickCallees(%d)", fi.addData(v)),
+	})
+}
+
+// -- utilities --------------------------------------------------------
+
+// stable order within packages but undefined across packages.
+type funcsByPos []*ssa.Function
+
+func (a funcsByPos) Less(i, j int) bool { return a[i].Pos() < a[j].Pos() }
+func (a funcsByPos) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
+func (a funcsByPos) Len() int           { return len(a) }
+
+type sitesByPos []ssa.CallInstruction
+
+func (a sitesByPos) Less(i, j int) bool { return a[i].Common().Pos() < a[j].Common().Pos() }
+func (a sitesByPos) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
+func (a sitesByPos) Len() int           { return len(a) }
+
+func funcToken(fn *ssa.Function) token.Pos {
+	switch syntax := fn.Syntax().(type) {
+	case *ast.FuncLit:
+		return syntax.Type.Func
+	case *ast.FuncDecl:
+		return syntax.Type.Func
+	}
+	return token.NoPos
+}
+
+// prettyFunc pretty-prints fn for the user interface.
+// TODO(adonovan): return HTML so we have more markup freedom.
+func prettyFunc(this *types.Package, fn *ssa.Function) string {
+	if fn.Parent() != nil {
+		return fmt.Sprintf("%s in %s",
+			types.TypeString(fn.Signature, types.RelativeTo(this)),
+			prettyFunc(this, fn.Parent()))
+	}
+	if fn.Synthetic != "" && fn.Name() == "init" {
+		// (This is the actual initializer, not a declared 'func init').
+		if fn.Pkg.Object == this {
+			return "package initializer"
+		}
+		return fmt.Sprintf("%q package initializer", fn.Pkg.Object.Path())
+	}
+	return fn.RelString(this)
+}
+
+// -- intra-package callgraph ------------------------------------------
+
+// pcgNode represents a node in the package call graph (PCG).
+type pcgNode struct {
+	fn     *ssa.Function
+	pretty string  // cache of prettyFunc(fn)
+	edges  big.Int // set of callee func indices
+}
+
+// A packageCallGraph represents the intra-package edges of the global call graph.
+// The zeroth node indicates "all external functions".
+type packageCallGraph struct {
+	nodeIndex map[*ssa.Function]int // maps func to node index (a small int)
+	nodes     []*pcgNode            // maps node index to node
+}
+
+// sortNodes populates pcg.nodes in name order and updates the nodeIndex.
+func (pcg *packageCallGraph) sortNodes() {
+	nodes := make([]*pcgNode, 0, len(pcg.nodeIndex))
+	nodes = append(nodes, &pcgNode{fn: nil, pretty: "<external>"})
+	for fn := range pcg.nodeIndex {
+		nodes = append(nodes, &pcgNode{
+			fn:     fn,
+			pretty: prettyFunc(fn.Pkg.Object, fn),
+		})
+	}
+	sort.Sort(pcgNodesByPretty(nodes[1:]))
+	for i, n := range nodes {
+		pcg.nodeIndex[n.fn] = i
+	}
+	pcg.nodes = nodes
+}
+
+func (pcg *packageCallGraph) addEdge(caller, callee *ssa.Function) {
+	var callerIndex int
+	if caller.Pkg == callee.Pkg {
+		// intra-package edge
+		callerIndex = pcg.nodeIndex[caller]
+		if callerIndex < 1 {
+			panic(caller)
+		}
+	}
+	edges := &pcg.nodes[callerIndex].edges
+	edges.SetBit(edges, pcg.nodeIndex[callee], 1)
+}
+
+func (a *analysis) pcgAddNode(fn *ssa.Function) {
+	if fn.Pkg == nil {
+		return
+	}
+	pcg, ok := a.pcgs[fn.Pkg]
+	if !ok {
+		pcg = &packageCallGraph{nodeIndex: make(map[*ssa.Function]int)}
+		a.pcgs[fn.Pkg] = pcg
+	}
+	pcg.nodeIndex[fn] = -1
+}
+
+func (a *analysis) pcgAddEdge(caller, callee *ssa.Function) {
+	if callee.Pkg != nil {
+		a.pcgs[callee.Pkg].addEdge(caller, callee)
+	}
+}
+
+// pcgJSON returns a new slice of callgraph JSON values.
+func (a *analysis) pcgJSON(pcg *packageCallGraph) []*PCGNodeJSON {
+	var nodes []*PCGNodeJSON
+	for _, n := range pcg.nodes {
+
+		// TODO(adonovan): why is there no good way to iterate
+		// over the set bits of a big.Int?
+		var callees []int
+		nbits := n.edges.BitLen()
+		for j := 0; j < nbits; j++ {
+			if n.edges.Bit(j) == 1 {
+				callees = append(callees, j)
+			}
+		}
+
+		var pos token.Pos
+		if n.fn != nil {
+			pos = funcToken(n.fn)
+		}
+		nodes = append(nodes, &PCGNodeJSON{
+			Func: anchorJSON{
+				Text: n.pretty,
+				Href: a.posURL(pos, len("func")),
+			},
+			Callees: callees,
+		})
+	}
+	return nodes
+}
+
+type pcgNodesByPretty []*pcgNode
+
+func (a pcgNodesByPretty) Less(i, j int) bool { return a[i].pretty < a[j].pretty }
+func (a pcgNodesByPretty) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
+func (a pcgNodesByPretty) Len() int           { return len(a) }
diff --git a/godoc/analysis/implements.go b/godoc/analysis/implements.go
new file mode 100644
index 0000000..bee04d0
--- /dev/null
+++ b/godoc/analysis/implements.go
@@ -0,0 +1,195 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package analysis
+
+// This file computes the "implements" relation over all pairs of
+// named types in the program.  (The mark-up is done by typeinfo.go.)
+
+// TODO(adonovan): do we want to report implements(C, I) where C and I
+// belong to different packages and at least one is not exported?
+
+import (
+	"sort"
+
+	"golang.org/x/tools/go/types"
+	"golang.org/x/tools/go/types/typeutil"
+)
+
+// computeImplements computes the "implements" relation over all pairs
+// of named types in allNamed.
+func computeImplements(cache *typeutil.MethodSetCache, allNamed []*types.Named) map[*types.Named]implementsFacts {
+	// Information about a single type's method set.
+	type msetInfo struct {
+		typ          types.Type
+		mset         *types.MethodSet
+		mask1, mask2 uint64
+	}
+
+	initMsetInfo := func(info *msetInfo, typ types.Type) {
+		info.typ = typ
+		info.mset = cache.MethodSet(typ)
+		for i := 0; i < info.mset.Len(); i++ {
+			name := info.mset.At(i).Obj().Name()
+			info.mask1 |= 1 << methodBit(name[0])
+			info.mask2 |= 1 << methodBit(name[len(name)-1])
+		}
+	}
+
+	// satisfies(T, U) reports whether type T satisfies type U.
+	// U must be an interface.
+	//
+	// Since there are thousands of types (and thus millions of
+	// pairs of types) and types.Assignable(T, U) is relatively
+	// expensive, we compute assignability directly from the
+	// method sets.  (At least one of T and U must be an
+	// interface.)
+	//
+	// We use a trick (thanks gri!) related to a Bloom filter to
+	// quickly reject most tests, which are false.  For each
+	// method set, we precompute a mask, a set of bits, one per
+	// distinct initial byte of each method name.  Thus the mask
+	// for io.ReadWriter would be {'R','W'}.  AssignableTo(T, U)
+	// cannot be true unless mask(T)&mask(U)==mask(U).
+	//
+	// As with a Bloom filter, we can improve precision by testing
+	// additional hashes, e.g. using the last letter of each
+	// method name, so long as the subset mask property holds.
+	//
+	// When analyzing the standard library, there are about 1e6
+	// calls to satisfies(), of which 0.6% return true.  With a
+	// 1-hash filter, 95% of calls avoid the expensive check; with
+	// a 2-hash filter, this grows to 98.2%.
+	satisfies := func(T, U *msetInfo) bool {
+		return T.mask1&U.mask1 == U.mask1 &&
+			T.mask2&U.mask2 == U.mask2 &&
+			containsAllIdsOf(T.mset, U.mset)
+	}
+
+	// Information about a named type N, and perhaps also *N.
+	type namedInfo struct {
+		isInterface bool
+		base        msetInfo // N
+		ptr         msetInfo // *N, iff N !isInterface
+	}
+
+	var infos []namedInfo
+
+	// Precompute the method sets and their masks.
+	for _, N := range allNamed {
+		var info namedInfo
+		initMsetInfo(&info.base, N)
+		_, info.isInterface = N.Underlying().(*types.Interface)
+		if !info.isInterface {
+			initMsetInfo(&info.ptr, types.NewPointer(N))
+		}
+
+		if info.base.mask1|info.ptr.mask1 == 0 {
+			continue // neither N nor *N has methods
+		}
+
+		infos = append(infos, info)
+	}
+
+	facts := make(map[*types.Named]implementsFacts)
+
+	// Test all pairs of distinct named types (T, U).
+	// TODO(adonovan): opt: compute (U, T) at the same time.
+	for t := range infos {
+		T := &infos[t]
+		var to, from, fromPtr []types.Type
+		for u := range infos {
+			if t == u {
+				continue
+			}
+			U := &infos[u]
+			switch {
+			case T.isInterface && U.isInterface:
+				if satisfies(&U.base, &T.base) {
+					to = append(to, U.base.typ)
+				}
+				if satisfies(&T.base, &U.base) {
+					from = append(from, U.base.typ)
+				}
+			case T.isInterface: // U concrete
+				if satisfies(&U.base, &T.base) {
+					to = append(to, U.base.typ)
+				} else if satisfies(&U.ptr, &T.base) {
+					to = append(to, U.ptr.typ)
+				}
+			case U.isInterface: // T concrete
+				if satisfies(&T.base, &U.base) {
+					from = append(from, U.base.typ)
+				} else if satisfies(&T.ptr, &U.base) {
+					fromPtr = append(fromPtr, U.base.typ)
+				}
+			}
+		}
+
+		// Sort types (arbitrarily) to avoid nondeterminism.
+		sort.Sort(typesByString(to))
+		sort.Sort(typesByString(from))
+		sort.Sort(typesByString(fromPtr))
+
+		facts[T.base.typ.(*types.Named)] = implementsFacts{to, from, fromPtr}
+	}
+
+	return facts
+}
+
+type implementsFacts struct {
+	to      []types.Type // named or ptr-to-named types assignable to interface T
+	from    []types.Type // named interfaces assignable from T
+	fromPtr []types.Type // named interfaces assignable only from *T
+}
+
+type typesByString []types.Type
+
+func (p typesByString) Len() int           { return len(p) }
+func (p typesByString) Less(i, j int) bool { return p[i].String() < p[j].String() }
+func (p typesByString) Swap(i, j int)      { p[i], p[j] = p[j], p[i] }
+
+// methodBit returns the index of x in [a-zA-Z], or 52 if not found.
+func methodBit(x byte) uint64 {
+	switch {
+	case 'a' <= x && x <= 'z':
+		return uint64(x - 'a')
+	case 'A' <= x && x <= 'Z':
+		return uint64(26 + x - 'A')
+	}
+	return 52 // all other bytes
+}
+
+// containsAllIdsOf reports whether the method identifiers of T are a
+// superset of those in U.  If U belongs to an interface type, the
+// result is equal to types.Assignable(T, U), but is cheaper to compute.
+//
+// TODO(gri): make this a method of *types.MethodSet.
+//
+func containsAllIdsOf(T, U *types.MethodSet) bool {
+	t, tlen := 0, T.Len()
+	u, ulen := 0, U.Len()
+	for t < tlen && u < ulen {
+		tMeth := T.At(t).Obj()
+		uMeth := U.At(u).Obj()
+		tId := tMeth.Id()
+		uId := uMeth.Id()
+		if tId > uId {
+			// U has a method T lacks: fail.
+			return false
+		}
+		if tId < uId {
+			// T has a method U lacks: ignore it.
+			t++
+			continue
+		}
+		// U and T both have a method of this Id.  Check types.
+		if !types.Identical(tMeth.Type(), uMeth.Type()) {
+			return false // type mismatch
+		}
+		u++
+		t++
+	}
+	return u == ulen
+}
diff --git a/godoc/analysis/json.go b/godoc/analysis/json.go
new file mode 100644
index 0000000..f897618
--- /dev/null
+++ b/godoc/analysis/json.go
@@ -0,0 +1,69 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package analysis
+
+// This file defines types used by client-side JavaScript.
+
+type anchorJSON struct {
+	Text string // HTML
+	Href string // URL
+}
+
+type commOpJSON struct {
+	Op anchorJSON
+	Fn string
+}
+
+// JavaScript's onClickComm() expects a commJSON.
+type commJSON struct {
+	Ops []commOpJSON
+}
+
+// Indicates one of these forms of fact about a type T:
+// T "is implemented by <ByKind> type <Other>"  (ByKind != "", e.g. "array")
+// T "implements <Other>"                       (ByKind == "")
+type implFactJSON struct {
+	ByKind string `json:",omitempty"`
+	Other  anchorJSON
+}
+
+// Implements facts are grouped by form, for ease of reading.
+type implGroupJSON struct {
+	Descr string
+	Facts []implFactJSON
+}
+
+// JavaScript's onClickIdent() expects a TypeInfoJSON.
+type TypeInfoJSON struct {
+	Name        string // type name
+	Size, Align int64
+	Methods     []anchorJSON
+	ImplGroups  []implGroupJSON
+}
+
+// JavaScript's onClickCallees() expects a calleesJSON.
+type calleesJSON struct {
+	Descr   string
+	Callees []anchorJSON // markup for called function
+}
+
+type callerJSON struct {
+	Func  string
+	Sites []anchorJSON
+}
+
+// JavaScript's onClickCallers() expects a callersJSON.
+type callersJSON struct {
+	Callee  string
+	Callers []callerJSON
+}
+
+// JavaScript's cgAddChild requires a global array of PCGNodeJSON
+// called CALLGRAPH, representing the intra-package call graph.
+// The first element is special and represents "all external callers".
+type PCGNodeJSON struct {
+	Func    anchorJSON
+	Callees []int // indices within CALLGRAPH of nodes called by this one
+}
diff --git a/godoc/analysis/peers.go b/godoc/analysis/peers.go
new file mode 100644
index 0000000..e1696e2
--- /dev/null
+++ b/godoc/analysis/peers.go
@@ -0,0 +1,154 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package analysis
+
+// This file computes the channel "peers" relation over all pairs of
+// channel operations in the program.  The peers are displayed in the
+// lower pane when a channel operation (make, <-, close) is clicked.
+
+// TODO(adonovan): handle calls to reflect.{Select,Recv,Send,Close} too,
+// then enable reflection in PTA.
+
+import (
+	"fmt"
+	"go/token"
+
+	"golang.org/x/tools/go/pointer"
+	"golang.org/x/tools/go/ssa"
+	"golang.org/x/tools/go/types"
+)
+
+func (a *analysis) doChannelPeers(ptsets map[ssa.Value]pointer.Pointer) {
+	addSendRecv := func(j *commJSON, op chanOp) {
+		j.Ops = append(j.Ops, commOpJSON{
+			Op: anchorJSON{
+				Text: op.mode,
+				Href: a.posURL(op.pos, op.len),
+			},
+			Fn: prettyFunc(nil, op.fn),
+		})
+	}
+
+	// Build an undirected bipartite multigraph (binary relation)
+	// of MakeChan ops and send/recv/close ops.
+	//
+	// TODO(adonovan): opt: use channel element types to partition
+	// the O(n^2) problem into subproblems.
+	aliasedOps := make(map[*ssa.MakeChan][]chanOp)
+	opToMakes := make(map[chanOp][]*ssa.MakeChan)
+	for _, op := range a.ops {
+		// Combine the PT sets from all contexts.
+		var makes []*ssa.MakeChan // aliased ops
+		ptr, ok := ptsets[op.ch]
+		if !ok {
+			continue // e.g. channel op in dead code
+		}
+		for _, label := range ptr.PointsTo().Labels() {
+			makechan, ok := label.Value().(*ssa.MakeChan)
+			if !ok {
+				continue // skip intrinsically-created channels for now
+			}
+			if makechan.Pos() == token.NoPos {
+				continue // not possible?
+			}
+			makes = append(makes, makechan)
+			aliasedOps[makechan] = append(aliasedOps[makechan], op)
+		}
+		opToMakes[op] = makes
+	}
+
+	// Now that complete relation is built, build links for ops.
+	for _, op := range a.ops {
+		v := commJSON{
+			Ops: []commOpJSON{}, // (JS wants non-nil)
+		}
+		ops := make(map[chanOp]bool)
+		for _, makechan := range opToMakes[op] {
+			v.Ops = append(v.Ops, commOpJSON{
+				Op: anchorJSON{
+					Text: "made",
+					Href: a.posURL(makechan.Pos()-token.Pos(len("make")),
+						len("make")),
+				},
+				Fn: makechan.Parent().RelString(op.fn.Package().Object),
+			})
+			for _, op := range aliasedOps[makechan] {
+				ops[op] = true
+			}
+		}
+		for op := range ops {
+			addSendRecv(&v, op)
+		}
+
+		// Add links for each aliased op.
+		fi, offset := a.fileAndOffset(op.pos)
+		fi.addLink(aLink{
+			start:   offset,
+			end:     offset + op.len,
+			title:   "show channel ops",
+			onclick: fmt.Sprintf("onClickComm(%d)", fi.addData(v)),
+		})
+	}
+	// Add links for makechan ops themselves.
+	for makechan, ops := range aliasedOps {
+		v := commJSON{
+			Ops: []commOpJSON{}, // (JS wants non-nil)
+		}
+		for _, op := range ops {
+			addSendRecv(&v, op)
+		}
+
+		fi, offset := a.fileAndOffset(makechan.Pos())
+		fi.addLink(aLink{
+			start:   offset - len("make"),
+			end:     offset,
+			title:   "show channel ops",
+			onclick: fmt.Sprintf("onClickComm(%d)", fi.addData(v)),
+		})
+	}
+}
+
+// -- utilities --------------------------------------------------------
+
+// chanOp abstracts an ssa.Send, ssa.Unop(ARROW), close(), or a SelectState.
+// Derived from oracle/peers.go.
+type chanOp struct {
+	ch   ssa.Value
+	mode string // sent|received|closed
+	pos  token.Pos
+	len  int
+	fn   *ssa.Function
+}
+
+// chanOps returns a slice of all the channel operations in the instruction.
+// Derived from oracle/peers.go.
+func chanOps(instr ssa.Instruction) []chanOp {
+	fn := instr.Parent()
+	var ops []chanOp
+	switch instr := instr.(type) {
+	case *ssa.UnOp:
+		if instr.Op == token.ARROW {
+			// TODO(adonovan): don't assume <-ch; could be 'range ch'.
+			ops = append(ops, chanOp{instr.X, "received", instr.Pos(), len("<-"), fn})
+		}
+	case *ssa.Send:
+		ops = append(ops, chanOp{instr.Chan, "sent", instr.Pos(), len("<-"), fn})
+	case *ssa.Select:
+		for _, st := range instr.States {
+			mode := "received"
+			if st.Dir == types.SendOnly {
+				mode = "sent"
+			}
+			ops = append(ops, chanOp{st.Chan, mode, st.Pos, len("<-"), fn})
+		}
+	case ssa.CallInstruction:
+		call := instr.Common()
+		if blt, ok := call.Value.(*ssa.Builtin); ok && blt.Name() == "close" {
+			pos := instr.Common().Pos()
+			ops = append(ops, chanOp{call.Args[0], "closed", pos - token.Pos(len("close")), len("close("), fn})
+		}
+	}
+	return ops
+}
diff --git a/godoc/analysis/typeinfo.go b/godoc/analysis/typeinfo.go
new file mode 100644
index 0000000..83e19c1
--- /dev/null
+++ b/godoc/analysis/typeinfo.go
@@ -0,0 +1,232 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package analysis
+
+// This file computes the markup for information from go/types:
+// IMPORTS, identifier RESOLUTION, METHOD SETS, size/alignment, and
+// the IMPLEMENTS relation.
+//
+// IMPORTS links connect import specs to the documentation for the
+// imported package.
+//
+// RESOLUTION links referring identifiers to their defining
+// identifier, and adds tooltips for kind and type.
+//
+// METHOD SETS, size/alignment, and the IMPLEMENTS relation are
+// displayed in the lower pane when a type's defining identifier is
+// clicked.
+
+import (
+	"fmt"
+	"reflect"
+	"strconv"
+	"strings"
+
+	"golang.org/x/tools/go/loader"
+	"golang.org/x/tools/go/types"
+	"golang.org/x/tools/go/types/typeutil"
+)
+
+// TODO(adonovan): audit to make sure it's safe on ill-typed packages.
+
+// TODO(adonovan): use same Sizes as loader.Config.
+var sizes = types.StdSizes{8, 8}
+
+func (a *analysis) doTypeInfo(info *loader.PackageInfo, implements map[*types.Named]implementsFacts) {
+	// We must not assume the corresponding SSA packages were
+	// created (i.e. were transitively error-free).
+
+	// IMPORTS
+	for _, f := range info.Files {
+		// Package decl.
+		fi, offset := a.fileAndOffset(f.Name.Pos())
+		fi.addLink(aLink{
+			start: offset,
+			end:   offset + len(f.Name.Name),
+			title: "Package docs for " + info.Pkg.Path(),
+			// TODO(adonovan): fix: we're putting the untrusted Path()
+			// into a trusted field.  What's the appropriate sanitizer?
+			href: "/pkg/" + info.Pkg.Path(),
+		})
+
+		// Import specs.
+		for _, imp := range f.Imports {
+			// Remove quotes.
+			L := int(imp.End()-imp.Path.Pos()) - len(`""`)
+			path, _ := strconv.Unquote(imp.Path.Value)
+			fi, offset := a.fileAndOffset(imp.Path.Pos())
+			fi.addLink(aLink{
+				start: offset + 1,
+				end:   offset + 1 + L,
+				title: "Package docs for " + path,
+				// TODO(adonovan): fix: we're putting the untrusted path
+				// into a trusted field.  What's the appropriate sanitizer?
+				href: "/pkg/" + path,
+			})
+		}
+	}
+
+	// RESOLUTION
+	qualifier := types.RelativeTo(info.Pkg)
+	for id, obj := range info.Uses {
+		// Position of the object definition.
+		pos := obj.Pos()
+		Len := len(obj.Name())
+
+		// Correct the position for non-renaming import specs.
+		//  import "sync/atomic"
+		//          ^^^^^^^^^^^
+		if obj, ok := obj.(*types.PkgName); ok && id.Name == obj.Imported().Name() {
+			// Assume this is a non-renaming import.
+			// NB: not true for degenerate renamings: `import foo "foo"`.
+			pos++
+			Len = len(obj.Imported().Path())
+		}
+
+		if obj.Pkg() == nil {
+			continue // don't mark up built-ins.
+		}
+
+		fi, offset := a.fileAndOffset(id.NamePos)
+		fi.addLink(aLink{
+			start: offset,
+			end:   offset + len(id.Name),
+			title: types.ObjectString(obj, qualifier),
+			href:  a.posURL(pos, Len),
+		})
+	}
+
+	// IMPLEMENTS & METHOD SETS
+	for _, obj := range info.Defs {
+		if obj, ok := obj.(*types.TypeName); ok {
+			a.namedType(obj, implements)
+		}
+	}
+}
+
+func (a *analysis) namedType(obj *types.TypeName, implements map[*types.Named]implementsFacts) {
+	qualifier := types.RelativeTo(obj.Pkg())
+	T := obj.Type().(*types.Named)
+	v := &TypeInfoJSON{
+		Name:    obj.Name(),
+		Size:    sizes.Sizeof(T),
+		Align:   sizes.Alignof(T),
+		Methods: []anchorJSON{}, // (JS wants non-nil)
+	}
+
+	// addFact adds the fact "is implemented by T" (by) or
+	// "implements T" (!by) to group.
+	addFact := func(group *implGroupJSON, T types.Type, by bool) {
+		Tobj := deref(T).(*types.Named).Obj()
+		var byKind string
+		if by {
+			// Show underlying kind of implementing type,
+			// e.g. "slice", "array", "struct".
+			s := reflect.TypeOf(T.Underlying()).String()
+			byKind = strings.ToLower(strings.TrimPrefix(s, "*types."))
+		}
+		group.Facts = append(group.Facts, implFactJSON{
+			ByKind: byKind,
+			Other: anchorJSON{
+				Href: a.posURL(Tobj.Pos(), len(Tobj.Name())),
+				Text: types.TypeString(T, qualifier),
+			},
+		})
+	}
+
+	// IMPLEMENTS
+	if r, ok := implements[T]; ok {
+		if isInterface(T) {
+			// "T is implemented by <conc>" ...
+			// "T is implemented by <iface>"...
+			// "T implements        <iface>"...
+			group := implGroupJSON{
+				Descr: types.TypeString(T, qualifier),
+			}
+			// Show concrete types first; use two passes.
+			for _, sub := range r.to {
+				if !isInterface(sub) {
+					addFact(&group, sub, true)
+				}
+			}
+			for _, sub := range r.to {
+				if isInterface(sub) {
+					addFact(&group, sub, true)
+				}
+			}
+			for _, super := range r.from {
+				addFact(&group, super, false)
+			}
+			v.ImplGroups = append(v.ImplGroups, group)
+		} else {
+			// T is concrete.
+			if r.from != nil {
+				// "T implements <iface>"...
+				group := implGroupJSON{
+					Descr: types.TypeString(T, qualifier),
+				}
+				for _, super := range r.from {
+					addFact(&group, super, false)
+				}
+				v.ImplGroups = append(v.ImplGroups, group)
+			}
+			if r.fromPtr != nil {
+				// "*C implements <iface>"...
+				group := implGroupJSON{
+					Descr: "*" + types.TypeString(T, qualifier),
+				}
+				for _, psuper := range r.fromPtr {
+					addFact(&group, psuper, false)
+				}
+				v.ImplGroups = append(v.ImplGroups, group)
+			}
+		}
+	}
+
+	// METHOD SETS
+	for _, sel := range typeutil.IntuitiveMethodSet(T, &a.prog.MethodSets) {
+		meth := sel.Obj().(*types.Func)
+		pos := meth.Pos() // may be 0 for error.Error
+		v.Methods = append(v.Methods, anchorJSON{
+			Href: a.posURL(pos, len(meth.Name())),
+			Text: types.SelectionString(sel, qualifier),
+		})
+	}
+
+	// Since there can be many specs per decl, we
+	// can't attach the link to the keyword 'type'
+	// (as we do with 'func'); we use the Ident.
+	fi, offset := a.fileAndOffset(obj.Pos())
+	fi.addLink(aLink{
+		start:   offset,
+		end:     offset + len(obj.Name()),
+		title:   fmt.Sprintf("type info for %s", obj.Name()),
+		onclick: fmt.Sprintf("onClickTypeInfo(%d)", fi.addData(v)),
+	})
+
+	// Add info for exported package-level types to the package info.
+	if obj.Exported() && isPackageLevel(obj) {
+		// TODO(adonovan): Path is not unique!
+		// It is possible to declare a non-test package called x_test.
+		a.result.pkgInfo(obj.Pkg().Path()).addType(v)
+	}
+}
+
+// -- utilities --------------------------------------------------------
+
+func isInterface(T types.Type) bool { return types.IsInterface(T) }
+
+// deref returns a pointer's element type; otherwise it returns typ.
+func deref(typ types.Type) types.Type {
+	if p, ok := typ.Underlying().(*types.Pointer); ok {
+		return p.Elem()
+	}
+	return typ
+}
+
+// isPackageLevel reports whether obj is a package-level object.
+func isPackageLevel(obj types.Object) bool {
+	return obj.Pkg().Scope().Lookup(obj.Name()) == obj
+}
diff --git a/godoc/cmdline.go b/godoc/cmdline.go
new file mode 100644
index 0000000..9502ebb
--- /dev/null
+++ b/godoc/cmdline.go
@@ -0,0 +1,207 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package godoc
+
+import (
+	"fmt"
+	"go/ast"
+	"go/build"
+	"io"
+	"log"
+	"os"
+	pathpkg "path"
+	"path/filepath"
+	"regexp"
+	"strings"
+
+	"golang.org/x/tools/godoc/vfs"
+)
+
+const (
+	target    = "/target"
+	cmdPrefix = "cmd/"
+	srcPrefix = "src/"
+	toolsPath = "golang.org/x/tools/cmd/"
+)
+
+// CommandLine returns godoc results to w.
+// Note that it may add a /target path to fs.
+func CommandLine(w io.Writer, fs vfs.NameSpace, pres *Presentation, args []string) error {
+	path := args[0]
+	srcMode := pres.SrcMode
+	cmdMode := strings.HasPrefix(path, cmdPrefix)
+	if strings.HasPrefix(path, srcPrefix) {
+		path = strings.TrimPrefix(path, srcPrefix)
+		srcMode = true
+	}
+	var abspath, relpath string
+	if cmdMode {
+		path = strings.TrimPrefix(path, cmdPrefix)
+	} else {
+		abspath, relpath = paths(fs, pres, path)
+	}
+
+	var mode PageInfoMode
+	if relpath == builtinPkgPath {
+		// the fake built-in package contains unexported identifiers
+		mode = NoFiltering | NoTypeAssoc
+	}
+	if srcMode {
+		// only filter exports if we don't have explicit command-line filter arguments
+		if len(args) > 1 {
+			mode |= NoFiltering
+		}
+		mode |= ShowSource
+	}
+
+	// First, try as package unless forced as command.
+	var info *PageInfo
+	if !cmdMode {
+		info = pres.GetPkgPageInfo(abspath, relpath, mode)
+	}
+
+	// Second, try as command (if the path is not absolute).
+	var cinfo *PageInfo
+	if !filepath.IsAbs(path) {
+		// First try go.tools/cmd.
+		abspath = pathpkg.Join(pres.PkgFSRoot(), toolsPath+path)
+		cinfo = pres.GetCmdPageInfo(abspath, relpath, mode)
+		if cinfo.IsEmpty() {
+			// Then try $GOROOT/cmd.
+			abspath = pathpkg.Join(pres.CmdFSRoot(), path)
+			cinfo = pres.GetCmdPageInfo(abspath, relpath, mode)
+		}
+	}
+
+	// determine what to use
+	if info == nil || info.IsEmpty() {
+		if cinfo != nil && !cinfo.IsEmpty() {
+			// only cinfo exists - switch to cinfo
+			info = cinfo
+		}
+	} else if cinfo != nil && !cinfo.IsEmpty() {
+		// both info and cinfo exist - use cinfo if info
+		// contains only subdirectory information
+		if info.PAst == nil && info.PDoc == nil {
+			info = cinfo
+		} else if relpath != target {
+			// The above check handles the case where an operating system path
+			// is provided (see documentation for paths below).  In that case,
+			// relpath is set to "/target" (in anticipation of accessing packages there),
+			// and is therefore not expected to match a command.
+			fmt.Fprintf(w, "use 'godoc %s%s' for documentation on the %s command \n\n", cmdPrefix, relpath, relpath)
+		}
+	}
+
+	if info == nil {
+		return fmt.Errorf("%s: no such directory or package", args[0])
+	}
+	if info.Err != nil {
+		return info.Err
+	}
+
+	if info.PDoc != nil && info.PDoc.ImportPath == target {
+		// Replace virtual /target with actual argument from command line.
+		info.PDoc.ImportPath = args[0]
+	}
+
+	// If we have more than one argument, use the remaining arguments for filtering.
+	if len(args) > 1 {
+		info.IsFiltered = true
+		filterInfo(args[1:], info)
+	}
+
+	packageText := pres.PackageText
+	if pres.HTMLMode {
+		packageText = pres.PackageHTML
+	}
+	if err := packageText.Execute(w, info); err != nil {
+		return err
+	}
+	return nil
+}
+
+// paths determines the paths to use.
+//
+// If we are passed an operating system path like . or ./foo or /foo/bar or c:\mysrc,
+// we need to map that path somewhere in the fs name space so that routines
+// like getPageInfo will see it.  We use the arbitrarily-chosen virtual path "/target"
+// for this.  That is, if we get passed a directory like the above, we map that
+// directory so that getPageInfo sees it as /target.
+// Returns the absolute and relative paths.
+func paths(fs vfs.NameSpace, pres *Presentation, path string) (string, string) {
+	if filepath.IsAbs(path) {
+		fs.Bind(target, vfs.OS(path), "/", vfs.BindReplace)
+		return target, target
+	}
+	if build.IsLocalImport(path) {
+		cwd, _ := os.Getwd() // ignore errors
+		path = filepath.Join(cwd, path)
+		fs.Bind(target, vfs.OS(path), "/", vfs.BindReplace)
+		return target, target
+	}
+	if bp, _ := build.Import(path, "", build.FindOnly); bp.Dir != "" && bp.ImportPath != "" {
+		fs.Bind(target, vfs.OS(bp.Dir), "/", vfs.BindReplace)
+		return target, bp.ImportPath
+	}
+	return pathpkg.Join(pres.PkgFSRoot(), path), path
+}
+
+// filterInfo updates info to include only the nodes that match the given
+// filter args.
+func filterInfo(args []string, info *PageInfo) {
+	rx, err := makeRx(args)
+	if err != nil {
+		log.Fatalf("illegal regular expression from %v: %v", args, err)
+	}
+
+	filter := func(s string) bool { return rx.MatchString(s) }
+	switch {
+	case info.PAst != nil:
+		newPAst := map[string]*ast.File{}
+		for name, a := range info.PAst {
+			cmap := ast.NewCommentMap(info.FSet, a, a.Comments)
+			a.Comments = []*ast.CommentGroup{} // remove all comments.
+			ast.FilterFile(a, filter)
+			if len(a.Decls) > 0 {
+				newPAst[name] = a
+			}
+			for _, d := range a.Decls {
+				// add back the comments associated with d only
+				comments := cmap.Filter(d).Comments()
+				a.Comments = append(a.Comments, comments...)
+			}
+		}
+		info.PAst = newPAst // add only matching files.
+	case info.PDoc != nil:
+		info.PDoc.Filter(filter)
+	}
+}
+
+// Does s look like a regular expression?
+func isRegexp(s string) bool {
+	return strings.IndexAny(s, ".(|)*+?^$[]") >= 0
+}
+
+// Make a regular expression of the form
+// names[0]|names[1]|...names[len(names)-1].
+// Returns an error if the regular expression is illegal.
+func makeRx(names []string) (*regexp.Regexp, error) {
+	if len(names) == 0 {
+		return nil, fmt.Errorf("no expression provided")
+	}
+	s := ""
+	for i, name := range names {
+		if i > 0 {
+			s += "|"
+		}
+		if isRegexp(name) {
+			s += name
+		} else {
+			s += "^" + name + "$" // must match exactly
+		}
+	}
+	return regexp.Compile(s)
+}
diff --git a/godoc/cmdline_test.go b/godoc/cmdline_test.go
new file mode 100644
index 0000000..602f2bb
--- /dev/null
+++ b/godoc/cmdline_test.go
@@ -0,0 +1,294 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package godoc
+
+import (
+	"bytes"
+	"go/build"
+	"io/ioutil"
+	"os"
+	"path/filepath"
+	"reflect"
+	"regexp"
+	"runtime"
+	"testing"
+	"text/template"
+
+	"golang.org/x/tools/godoc/vfs"
+	"golang.org/x/tools/godoc/vfs/mapfs"
+)
+
+// setupGoroot creates temporary directory to act as GOROOT when running tests
+// that depend upon the build package.  It updates build.Default to point to the
+// new GOROOT.
+// It returns a function that can be called to reset build.Default and remove
+// the temporary directory.
+func setupGoroot(t *testing.T) (cleanup func()) {
+	var stdLib = map[string]string{
+		"src/fmt/fmt.go": `// Package fmt implements formatted I/O.
+package fmt
+
+type Stringer interface {
+	String() string
+}
+`,
+	}
+	goroot, err := ioutil.TempDir("", "cmdline_test")
+	if err != nil {
+		t.Fatal(err)
+	}
+	origContext := build.Default
+	build.Default = build.Context{
+		GOROOT:   goroot,
+		Compiler: "gc",
+	}
+	for relname, contents := range stdLib {
+		name := filepath.Join(goroot, relname)
+		if err := os.MkdirAll(filepath.Dir(name), 0770); err != nil {
+			t.Fatal(err)
+		}
+		if err := ioutil.WriteFile(name, []byte(contents), 0770); err != nil {
+			t.Fatal(err)
+		}
+	}
+
+	return func() {
+		if err := os.RemoveAll(goroot); err != nil {
+			t.Log(err)
+		}
+		build.Default = origContext
+	}
+}
+
+func TestPaths(t *testing.T) {
+	cleanup := setupGoroot(t)
+	defer cleanup()
+
+	pres := &Presentation{
+		pkgHandler: handlerServer{
+			fsRoot: "/fsroot",
+		},
+	}
+	fs := make(vfs.NameSpace)
+
+	absPath := "/foo/fmt"
+	if runtime.GOOS == "windows" {
+		absPath = `c:\foo\fmt`
+	}
+
+	for _, tc := range []struct {
+		desc   string
+		path   string
+		expAbs string
+		expRel string
+	}{
+		{
+			"Absolute path",
+			absPath,
+			"/target",
+			"/target",
+		},
+		{
+			"Local import",
+			"../foo/fmt",
+			"/target",
+			"/target",
+		},
+		{
+			"Import",
+			"fmt",
+			"/target",
+			"fmt",
+		},
+		{
+			"Default",
+			"unknownpkg",
+			"/fsroot/unknownpkg",
+			"unknownpkg",
+		},
+	} {
+		abs, rel := paths(fs, pres, tc.path)
+		if abs != tc.expAbs || rel != tc.expRel {
+			t.Errorf("%s: paths(%q) = %s,%s; want %s,%s", tc.desc, tc.path, abs, rel, tc.expAbs, tc.expRel)
+		}
+	}
+}
+
+func TestMakeRx(t *testing.T) {
+	for _, tc := range []struct {
+		desc  string
+		names []string
+		exp   string
+	}{
+		{
+			desc:  "empty string",
+			names: []string{""},
+			exp:   `^$`,
+		},
+		{
+			desc:  "simple text",
+			names: []string{"a"},
+			exp:   `^a$`,
+		},
+		{
+			desc:  "two words",
+			names: []string{"foo", "bar"},
+			exp:   `^foo$|^bar$`,
+		},
+		{
+			desc:  "word & non-trivial",
+			names: []string{"foo", `ab?c`},
+			exp:   `^foo$|ab?c`,
+		},
+		{
+			desc:  "bad regexp",
+			names: []string{`(."`},
+			exp:   `(."`,
+		},
+	} {
+		expRE, expErr := regexp.Compile(tc.exp)
+		if re, err := makeRx(tc.names); !reflect.DeepEqual(err, expErr) && !reflect.DeepEqual(re, expRE) {
+			t.Errorf("%s: makeRx(%v) = %q,%q; want %q,%q", tc.desc, tc.names, re, err, expRE, expErr)
+		}
+	}
+}
+
+func TestCommandLine(t *testing.T) {
+	cleanup := setupGoroot(t)
+	defer cleanup()
+	mfs := mapfs.New(map[string]string{
+		"src/bar/bar.go": `// Package bar is an example.
+package bar
+`,
+		"src/foo/foo.go": `// Package foo.
+package foo
+
+// First function is first.
+func First() {
+}
+
+// Second function is second.
+func Second() {
+}
+`,
+		"src/gen/gen.go": `// Package gen
+package gen
+
+//line notgen.go:3
+// F doc //line 1 should appear
+// line 2 should appear
+func F()
+//line foo.go:100`, // no newline on end to check corner cases!
+		"src/vet/vet.go": `// Package vet
+package vet
+`,
+		"src/cmd/go/doc.go": `// The go command
+package main
+`,
+		"src/cmd/gofmt/doc.go": `// The gofmt command
+package main
+`,
+		"src/cmd/vet/vet.go": `// The vet command
+package main
+`,
+	})
+	fs := make(vfs.NameSpace)
+	fs.Bind("/", mfs, "/", vfs.BindReplace)
+	c := NewCorpus(fs)
+	p := &Presentation{Corpus: c}
+	p.cmdHandler = handlerServer{
+		p:       p,
+		c:       c,
+		pattern: "/cmd/",
+		fsRoot:  "/src/cmd",
+	}
+	p.pkgHandler = handlerServer{
+		p:       p,
+		c:       c,
+		pattern: "/pkg/",
+		fsRoot:  "/src",
+		exclude: []string{"/src/cmd"},
+	}
+	p.initFuncMap()
+	p.PackageText = template.Must(template.New("PackageText").Funcs(p.FuncMap()).Parse(`{{$info := .}}{{$filtered := .IsFiltered}}{{if $filtered}}{{range .PAst}}{{range .Decls}}{{node $info .}}{{end}}{{end}}{{else}}{{with .PAst}}{{range $filename, $ast := .}}{{$filename}}:
+{{node $ $ast}}{{end}}{{end}}{{end}}{{with .PDoc}}{{if $.IsMain}}COMMAND {{.Doc}}{{else}}PACKAGE {{.Doc}}{{end}}{{with .Funcs}}
+{{range .}}{{node $ .Decl}}
+{{comment_text .Doc "    " "\t"}}{{end}}{{end}}{{end}}`))
+
+	for _, tc := range []struct {
+		desc string
+		args []string
+		exp  string
+		err  bool
+	}{
+		{
+			desc: "standard package",
+			args: []string{"fmt"},
+			exp:  "PACKAGE Package fmt implements formatted I/O.\n",
+		},
+		{
+			desc: "package",
+			args: []string{"bar"},
+			exp:  "PACKAGE Package bar is an example.\n",
+		},
+		{
+			desc: "package w. filter",
+			args: []string{"foo", "First"},
+			exp:  "PACKAGE \nfunc First()\n    First function is first.\n",
+		},
+		{
+			desc: "package w. bad filter",
+			args: []string{"foo", "DNE"},
+			exp:  "PACKAGE ",
+		},
+		{
+			desc: "source mode",
+			args: []string{"src/bar"},
+			exp:  "bar/bar.go:\n// Package bar is an example.\npackage bar\n",
+		},
+		{
+			desc: "source mode w. filter",
+			args: []string{"src/foo", "Second"},
+			exp:  "// Second function is second.\nfunc Second() {\n}",
+		},
+		{
+			desc: "package w. //line comments",
+			args: []string{"gen", "F"},
+			exp:  "PACKAGE \nfunc F()\n    F doc //line 1 should appear line 2 should appear\n",
+		},
+		{
+			desc: "command",
+			args: []string{"go"},
+			exp:  "COMMAND The go command\n",
+		},
+		{
+			desc: "forced command",
+			args: []string{"cmd/gofmt"},
+			exp:  "COMMAND The gofmt command\n",
+		},
+		{
+			desc: "bad arg",
+			args: []string{"doesnotexist"},
+			err:  true,
+		},
+		{
+			desc: "both command and package",
+			args: []string{"vet"},
+			exp:  "use 'godoc cmd/vet' for documentation on the vet command \n\nPACKAGE Package vet\n",
+		},
+		{
+			desc: "root directory",
+			args: []string{"/"},
+			exp:  "",
+		},
+	} {
+		w := new(bytes.Buffer)
+		err := CommandLine(w, fs, p, tc.args)
+		if got, want := w.String(), tc.exp; got != want || tc.err == (err == nil) {
+			t.Errorf("%s: CommandLine(%v) = %q (%v); want %q (%v)",
+				tc.desc, tc.args, got, err, want, tc.err)
+		}
+	}
+}
diff --git a/godoc/corpus.go b/godoc/corpus.go
new file mode 100644
index 0000000..f2c7ebb
--- /dev/null
+++ b/godoc/corpus.go
@@ -0,0 +1,157 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package godoc
+
+import (
+	"errors"
+	pathpkg "path"
+	"time"
+
+	"golang.org/x/tools/godoc/analysis"
+	"golang.org/x/tools/godoc/util"
+	"golang.org/x/tools/godoc/vfs"
+)
+
+// A Corpus holds all the state related to serving and indexing a
+// collection of Go code.
+//
+// Construct a new Corpus with NewCorpus, then modify options,
+// then call its Init method.
+type Corpus struct {
+	fs vfs.FileSystem
+
+	// Verbose logging.
+	Verbose bool
+
+	// IndexEnabled controls whether indexing is enabled.
+	IndexEnabled bool
+
+	// IndexFiles specifies a glob pattern specifying index files.
+	// If not empty, the index is read from these files in sorted
+	// order.
+	IndexFiles string
+
+	// IndexThrottle specifies the indexing throttle value
+	// between 0.0 and 1.0. At 0.0, the indexer always sleeps.
+	// At 1.0, the indexer never sleeps. Because 0.0 is useless
+	// and redundant with setting IndexEnabled to false, the
+	// zero value for IndexThrottle means 0.9.
+	IndexThrottle float64
+
+	// IndexInterval specifies the time to sleep between reindexing
+	// all the sources.
+	// If zero, a default is used. If negative, the index is only
+	// built once.
+	IndexInterval time.Duration
+
+	// IndexDocs enables indexing of Go documentation.
+	// This will produce search results for exported types, functions,
+	// methods, variables, and constants, and will link to the godoc
+	// documentation for those identifiers.
+	IndexDocs bool
+
+	// IndexGoCode enables indexing of Go source code.
+	// This will produce search results for internal and external identifiers
+	// and will link to both declarations and uses of those identifiers in
+	// source code.
+	IndexGoCode bool
+
+	// IndexFullText enables full-text indexing.
+	// This will provide search results for any matching text in any file that
+	// is indexed, including non-Go files (see whitelisted in index.go).
+	// Regexp searching is supported via full-text indexing.
+	IndexFullText bool
+
+	// MaxResults optionally specifies the maximum results for indexing.
+	MaxResults int
+
+	// SummarizePackage optionally specifies a function to
+	// summarize a package. It exists as an optimization to
+	// avoid reading files to parse package comments.
+	//
+	// If SummarizePackage returns false for ok, the caller
+	// ignores all return values and parses the files in the package
+	// as if SummarizePackage were nil.
+	//
+	// If showList is false, the package is hidden from the
+	// package listing.
+	SummarizePackage func(pkg string) (summary string, showList, ok bool)
+
+	// IndexDirectory optionally specifies a function to determine
+	// whether the provided directory should be indexed.  The dir
+	// will be of the form "/src/cmd/6a", "/doc/play",
+	// "/src/io", etc.
+	// If nil, all directories are indexed if indexing is enabled.
+	IndexDirectory func(dir string) bool
+
+	testDir string // TODO(bradfitz,adg): migrate old godoc flag? looks unused.
+
+	// Send a value on this channel to trigger a metadata refresh.
+	// It is buffered so that if a signal is not lost if sent
+	// during a refresh.
+	refreshMetadataSignal chan bool
+
+	// file system information
+	fsTree      util.RWValue // *Directory tree of packages, updated with each sync (but sync code is removed now)
+	fsModified  util.RWValue // timestamp of last call to invalidateIndex
+	docMetadata util.RWValue // mapping from paths to *Metadata
+
+	// SearchIndex is the search index in use.
+	searchIndex util.RWValue
+
+	// Analysis is the result of type and pointer analysis.
+	Analysis analysis.Result
+}
+
+// NewCorpus returns a new Corpus from a filesystem.
+// The returned corpus has all indexing enabled and MaxResults set to 1000.
+// Change or set any options on Corpus before calling the Corpus.Init method.
+func NewCorpus(fs vfs.FileSystem) *Corpus {
+	c := &Corpus{
+		fs: fs,
+		refreshMetadataSignal: make(chan bool, 1),
+
+		MaxResults:    1000,
+		IndexEnabled:  true,
+		IndexDocs:     true,
+		IndexGoCode:   true,
+		IndexFullText: true,
+	}
+	return c
+}
+
+func (c *Corpus) CurrentIndex() (*Index, time.Time) {
+	v, t := c.searchIndex.Get()
+	idx, _ := v.(*Index)
+	return idx, t
+}
+
+func (c *Corpus) FSModifiedTime() time.Time {
+	_, ts := c.fsModified.Get()
+	return ts
+}
+
+// Init initializes Corpus, once options on Corpus are set.
+// It must be called before any subsequent method calls.
+func (c *Corpus) Init() error {
+	// TODO(bradfitz): do this in a goroutine because newDirectory might block for a long time?
+	// It used to be sometimes done in a goroutine before, at least in HTTP server mode.
+	if err := c.initFSTree(); err != nil {
+		return err
+	}
+	c.updateMetadata()
+	go c.refreshMetadataLoop()
+	return nil
+}
+
+func (c *Corpus) initFSTree() error {
+	dir := c.newDirectory(pathpkg.Join("/", c.testDir), -1)
+	if dir == nil {
+		return errors.New("godoc: corpus fstree is nil")
+	}
+	c.fsTree.Set(dir)
+	c.invalidateIndex()
+	return nil
+}
diff --git a/godoc/dirtrees.go b/godoc/dirtrees.go
new file mode 100644
index 0000000..a55b324
--- /dev/null
+++ b/godoc/dirtrees.go
@@ -0,0 +1,336 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file contains the code dealing with package directory trees.
+
+package godoc
+
+import (
+	"bytes"
+	"go/doc"
+	"go/parser"
+	"go/token"
+	"log"
+	"os"
+	pathpkg "path"
+	"strings"
+)
+
+// Conventional name for directories containing test data.
+// Excluded from directory trees.
+//
+const testdataDirName = "testdata"
+
+type Directory struct {
+	Depth    int
+	Path     string       // directory path; includes Name
+	Name     string       // directory name
+	HasPkg   bool         // true if the directory contains at least one package
+	Synopsis string       // package documentation, if any
+	Dirs     []*Directory // subdirectories
+}
+
+func isGoFile(fi os.FileInfo) bool {
+	name := fi.Name()
+	return !fi.IsDir() &&
+		len(name) > 0 && name[0] != '.' && // ignore .files
+		pathpkg.Ext(name) == ".go"
+}
+
+func isPkgFile(fi os.FileInfo) bool {
+	return isGoFile(fi) &&
+		!strings.HasSuffix(fi.Name(), "_test.go") // ignore test files
+}
+
+func isPkgDir(fi os.FileInfo) bool {
+	name := fi.Name()
+	return fi.IsDir() && len(name) > 0 &&
+		name[0] != '_' && name[0] != '.' // ignore _files and .files
+}
+
+type treeBuilder struct {
+	c        *Corpus
+	maxDepth int
+}
+
+func (b *treeBuilder) newDirTree(fset *token.FileSet, path, name string, depth int) *Directory {
+	if name == testdataDirName {
+		return nil
+	}
+
+	if depth >= b.maxDepth {
+		// return a dummy directory so that the parent directory
+		// doesn't get discarded just because we reached the max
+		// directory depth
+		return &Directory{
+			Depth: depth,
+			Path:  path,
+			Name:  name,
+		}
+	}
+
+	var synopses [3]string // prioritized package documentation (0 == highest priority)
+
+	show := true // show in package listing
+	hasPkgFiles := false
+	haveSummary := false
+
+	if hook := b.c.SummarizePackage; hook != nil {
+		if summary, show0, ok := hook(strings.TrimPrefix(path, "/src/")); ok {
+			hasPkgFiles = true
+			show = show0
+			synopses[0] = summary
+			haveSummary = true
+		}
+	}
+
+	list, _ := b.c.fs.ReadDir(path)
+
+	// determine number of subdirectories and if there are package files
+	var dirchs []chan *Directory
+
+	for _, d := range list {
+		switch {
+		case isPkgDir(d):
+			ch := make(chan *Directory, 1)
+			dirchs = append(dirchs, ch)
+			go func(d os.FileInfo) {
+				name := d.Name()
+				ch <- b.newDirTree(fset, pathpkg.Join(path, name), name, depth+1)
+			}(d)
+		case !haveSummary && isPkgFile(d):
+			// looks like a package file, but may just be a file ending in ".go";
+			// don't just count it yet (otherwise we may end up with hasPkgFiles even
+			// though the directory doesn't contain any real package files - was bug)
+			// no "optimal" package synopsis yet; continue to collect synopses
+			file, err := b.c.parseFile(fset, pathpkg.Join(path, d.Name()),
+				parser.ParseComments|parser.PackageClauseOnly)
+			if err == nil {
+				hasPkgFiles = true
+				if file.Doc != nil {
+					// prioritize documentation
+					i := -1
+					switch file.Name.Name {
+					case name:
+						i = 0 // normal case: directory name matches package name
+					case "main":
+						i = 1 // directory contains a main package
+					default:
+						i = 2 // none of the above
+					}
+					if 0 <= i && i < len(synopses) && synopses[i] == "" {
+						synopses[i] = doc.Synopsis(file.Doc.Text())
+					}
+				}
+				haveSummary = synopses[0] != ""
+			}
+		}
+	}
+
+	// create subdirectory tree
+	var dirs []*Directory
+	for _, ch := range dirchs {
+		if d := <-ch; d != nil {
+			dirs = append(dirs, d)
+		}
+	}
+
+	// if there are no package files and no subdirectories
+	// containing package files, ignore the directory
+	if !hasPkgFiles && len(dirs) == 0 {
+		return nil
+	}
+
+	// select the highest-priority synopsis for the directory entry, if any
+	synopsis := ""
+	for _, synopsis = range synopses {
+		if synopsis != "" {
+			break
+		}
+	}
+
+	return &Directory{
+		Depth:    depth,
+		Path:     path,
+		Name:     name,
+		HasPkg:   hasPkgFiles && show, // TODO(bradfitz): add proper Hide field?
+		Synopsis: synopsis,
+		Dirs:     dirs,
+	}
+}
+
+// newDirectory creates a new package directory tree with at most maxDepth
+// levels, anchored at root. The result tree is pruned such that it only
+// contains directories that contain package files or that contain
+// subdirectories containing package files (transitively). If a non-nil
+// pathFilter is provided, directory paths additionally must be accepted
+// by the filter (i.e., pathFilter(path) must be true). If a value >= 0 is
+// provided for maxDepth, nodes at larger depths are pruned as well; they
+// are assumed to contain package files even if their contents are not known
+// (i.e., in this case the tree may contain directories w/o any package files).
+//
+func (c *Corpus) newDirectory(root string, maxDepth int) *Directory {
+	// The root could be a symbolic link so use Stat not Lstat.
+	d, err := c.fs.Stat(root)
+	// If we fail here, report detailed error messages; otherwise
+	// is is hard to see why a directory tree was not built.
+	switch {
+	case err != nil:
+		log.Printf("newDirectory(%s): %s", root, err)
+		return nil
+	case root != "/" && !isPkgDir(d):
+		log.Printf("newDirectory(%s): not a package directory", root)
+		return nil
+	case root == "/" && !d.IsDir():
+		log.Printf("newDirectory(%s): not a directory", root)
+		return nil
+	}
+	if maxDepth < 0 {
+		maxDepth = 1e6 // "infinity"
+	}
+	b := treeBuilder{c, maxDepth}
+	// the file set provided is only for local parsing, no position
+	// information escapes and thus we don't need to save the set
+	return b.newDirTree(token.NewFileSet(), root, d.Name(), 0)
+}
+
+func (dir *Directory) writeLeafs(buf *bytes.Buffer) {
+	if dir != nil {
+		if len(dir.Dirs) == 0 {
+			buf.WriteString(dir.Path)
+			buf.WriteByte('\n')
+			return
+		}
+
+		for _, d := range dir.Dirs {
+			d.writeLeafs(buf)
+		}
+	}
+}
+
+func (dir *Directory) walk(c chan<- *Directory, skipRoot bool) {
+	if dir != nil {
+		if !skipRoot {
+			c <- dir
+		}
+		for _, d := range dir.Dirs {
+			d.walk(c, false)
+		}
+	}
+}
+
+func (dir *Directory) iter(skipRoot bool) <-chan *Directory {
+	c := make(chan *Directory)
+	go func() {
+		dir.walk(c, skipRoot)
+		close(c)
+	}()
+	return c
+}
+
+func (dir *Directory) lookupLocal(name string) *Directory {
+	for _, d := range dir.Dirs {
+		if d.Name == name {
+			return d
+		}
+	}
+	return nil
+}
+
+func splitPath(p string) []string {
+	p = strings.TrimPrefix(p, "/")
+	if p == "" {
+		return nil
+	}
+	return strings.Split(p, "/")
+}
+
+// lookup looks for the *Directory for a given path, relative to dir.
+func (dir *Directory) lookup(path string) *Directory {
+	d := splitPath(dir.Path)
+	p := splitPath(path)
+	i := 0
+	for i < len(d) {
+		if i >= len(p) || d[i] != p[i] {
+			return nil
+		}
+		i++
+	}
+	for dir != nil && i < len(p) {
+		dir = dir.lookupLocal(p[i])
+		i++
+	}
+	return dir
+}
+
+// DirEntry describes a directory entry. The Depth and Height values
+// are useful for presenting an entry in an indented fashion.
+//
+type DirEntry struct {
+	Depth    int    // >= 0
+	Height   int    // = DirList.MaxHeight - Depth, > 0
+	Path     string // directory path; includes Name, relative to DirList root
+	Name     string // directory name
+	HasPkg   bool   // true if the directory contains at least one package
+	Synopsis string // package documentation, if any
+}
+
+type DirList struct {
+	MaxHeight int // directory tree height, > 0
+	List      []DirEntry
+}
+
+// listing creates a (linear) directory listing from a directory tree.
+// If skipRoot is set, the root directory itself is excluded from the list.
+// If filter is set, only the directory entries whose paths match the filter
+// are included.
+//
+func (root *Directory) listing(skipRoot bool, filter func(string) bool) *DirList {
+	if root == nil {
+		return nil
+	}
+
+	// determine number of entries n and maximum height
+	n := 0
+	minDepth := 1 << 30 // infinity
+	maxDepth := 0
+	for d := range root.iter(skipRoot) {
+		n++
+		if minDepth > d.Depth {
+			minDepth = d.Depth
+		}
+		if maxDepth < d.Depth {
+			maxDepth = d.Depth
+		}
+	}
+	maxHeight := maxDepth - minDepth + 1
+
+	if n == 0 {
+		return nil
+	}
+
+	// create list
+	list := make([]DirEntry, 0, n)
+	for d := range root.iter(skipRoot) {
+		if filter != nil && !filter(d.Path) {
+			continue
+		}
+		var p DirEntry
+		p.Depth = d.Depth - minDepth
+		p.Height = maxHeight - p.Depth
+		// the path is relative to root.Path - remove the root.Path
+		// prefix (the prefix should always be present but avoid
+		// crashes and check)
+		path := strings.TrimPrefix(d.Path, root.Path)
+		// remove leading separator if any - path must be relative
+		path = strings.TrimPrefix(path, "/")
+		p.Path = path
+		p.Name = d.Name
+		p.HasPkg = d.HasPkg
+		p.Synopsis = d.Synopsis
+		list = append(list, p)
+	}
+
+	return &DirList{maxHeight, list}
+}
diff --git a/godoc/format.go b/godoc/format.go
new file mode 100644
index 0000000..6013238
--- /dev/null
+++ b/godoc/format.go
@@ -0,0 +1,371 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file implements FormatSelections and FormatText.
+// FormatText is used to HTML-format Go and non-Go source
+// text with line numbers and highlighted sections. It is
+// built on top of FormatSelections, a generic formatter
+// for "selected" text.
+
+package godoc
+
+import (
+	"fmt"
+	"go/scanner"
+	"go/token"
+	"io"
+	"regexp"
+	"strconv"
+	"text/template"
+)
+
+// ----------------------------------------------------------------------------
+// Implementation of FormatSelections
+
+// A Segment describes a text segment [start, end).
+// The zero value of a Segment is a ready-to-use empty segment.
+//
+type Segment struct {
+	start, end int
+}
+
+func (seg *Segment) isEmpty() bool { return seg.start >= seg.end }
+
+// A Selection is an "iterator" function returning a text segment.
+// Repeated calls to a selection return consecutive, non-overlapping,
+// non-empty segments, followed by an infinite sequence of empty
+// segments. The first empty segment marks the end of the selection.
+//
+type Selection func() Segment
+
+// A LinkWriter writes some start or end "tag" to w for the text offset offs.
+// It is called by FormatSelections at the start or end of each link segment.
+//
+type LinkWriter func(w io.Writer, offs int, start bool)
+
+// A SegmentWriter formats a text according to selections and writes it to w.
+// The selections parameter is a bit set indicating which selections provided
+// to FormatSelections overlap with the text segment: If the n'th bit is set
+// in selections, the n'th selection provided to FormatSelections is overlapping
+// with the text.
+//
+type SegmentWriter func(w io.Writer, text []byte, selections int)
+
+// FormatSelections takes a text and writes it to w using link and segment
+// writers lw and sw as follows: lw is invoked for consecutive segment starts
+// and ends as specified through the links selection, and sw is invoked for
+// consecutive segments of text overlapped by the same selections as specified
+// by selections. The link writer lw may be nil, in which case the links
+// Selection is ignored.
+//
+func FormatSelections(w io.Writer, text []byte, lw LinkWriter, links Selection, sw SegmentWriter, selections ...Selection) {
+	// If we have a link writer, make the links
+	// selection the last entry in selections
+	if lw != nil {
+		selections = append(selections, links)
+	}
+
+	// compute the sequence of consecutive segment changes
+	changes := newMerger(selections)
+
+	// The i'th bit in bitset indicates that the text
+	// at the current offset is covered by selections[i].
+	bitset := 0
+	lastOffs := 0
+
+	// Text segments are written in a delayed fashion
+	// such that consecutive segments belonging to the
+	// same selection can be combined (peephole optimization).
+	// last describes the last segment which has not yet been written.
+	var last struct {
+		begin, end int // valid if begin < end
+		bitset     int
+	}
+
+	// flush writes the last delayed text segment
+	flush := func() {
+		if last.begin < last.end {
+			sw(w, text[last.begin:last.end], last.bitset)
+		}
+		last.begin = last.end // invalidate last
+	}
+
+	// segment runs the segment [lastOffs, end) with the selection
+	// indicated by bitset through the segment peephole optimizer.
+	segment := func(end int) {
+		if lastOffs < end { // ignore empty segments
+			if last.end != lastOffs || last.bitset != bitset {
+				// the last segment is not adjacent to or
+				// differs from the new one
+				flush()
+				// start a new segment
+				last.begin = lastOffs
+			}
+			last.end = end
+			last.bitset = bitset
+		}
+	}
+
+	for {
+		// get the next segment change
+		index, offs, start := changes.next()
+		if index < 0 || offs > len(text) {
+			// no more segment changes or the next change
+			// is past the end of the text - we're done
+			break
+		}
+		// determine the kind of segment change
+		if lw != nil && index == len(selections)-1 {
+			// we have a link segment change (see start of this function):
+			// format the previous selection segment, write the
+			// link tag and start a new selection segment
+			segment(offs)
+			flush()
+			lastOffs = offs
+			lw(w, offs, start)
+		} else {
+			// we have a selection change:
+			// format the previous selection segment, determine
+			// the new selection bitset and start a new segment
+			segment(offs)
+			lastOffs = offs
+			mask := 1 << uint(index)
+			if start {
+				bitset |= mask
+			} else {
+				bitset &^= mask
+			}
+		}
+	}
+	segment(len(text))
+	flush()
+}
+
+// A merger merges a slice of Selections and produces a sequence of
+// consecutive segment change events through repeated next() calls.
+//
+type merger struct {
+	selections []Selection
+	segments   []Segment // segments[i] is the next segment of selections[i]
+}
+
+const infinity int = 2e9
+
+func newMerger(selections []Selection) *merger {
+	segments := make([]Segment, len(selections))
+	for i, sel := range selections {
+		segments[i] = Segment{infinity, infinity}
+		if sel != nil {
+			if seg := sel(); !seg.isEmpty() {
+				segments[i] = seg
+			}
+		}
+	}
+	return &merger{selections, segments}
+}
+
+// next returns the next segment change: index specifies the Selection
+// to which the segment belongs, offs is the segment start or end offset
+// as determined by the start value. If there are no more segment changes,
+// next returns an index value < 0.
+//
+func (m *merger) next() (index, offs int, start bool) {
+	// find the next smallest offset where a segment starts or ends
+	offs = infinity
+	index = -1
+	for i, seg := range m.segments {
+		switch {
+		case seg.start < offs:
+			offs = seg.start
+			index = i
+			start = true
+		case seg.end < offs:
+			offs = seg.end
+			index = i
+			start = false
+		}
+	}
+	if index < 0 {
+		// no offset found => all selections merged
+		return
+	}
+	// offset found - it's either the start or end offset but
+	// either way it is ok to consume the start offset: set it
+	// to infinity so it won't be considered in the following
+	// next call
+	m.segments[index].start = infinity
+	if start {
+		return
+	}
+	// end offset found - consume it
+	m.segments[index].end = infinity
+	// advance to the next segment for that selection
+	seg := m.selections[index]()
+	if !seg.isEmpty() {
+		m.segments[index] = seg
+	}
+	return
+}
+
+// ----------------------------------------------------------------------------
+// Implementation of FormatText
+
+// lineSelection returns the line segments for text as a Selection.
+func lineSelection(text []byte) Selection {
+	i, j := 0, 0
+	return func() (seg Segment) {
+		// find next newline, if any
+		for j < len(text) {
+			j++
+			if text[j-1] == '\n' {
+				break
+			}
+		}
+		if i < j {
+			// text[i:j] constitutes a line
+			seg = Segment{i, j}
+			i = j
+		}
+		return
+	}
+}
+
+// tokenSelection returns, as a selection, the sequence of
+// consecutive occurrences of token sel in the Go src text.
+//
+func tokenSelection(src []byte, sel token.Token) Selection {
+	var s scanner.Scanner
+	fset := token.NewFileSet()
+	file := fset.AddFile("", fset.Base(), len(src))
+	s.Init(file, src, nil, scanner.ScanComments)
+	return func() (seg Segment) {
+		for {
+			pos, tok, lit := s.Scan()
+			if tok == token.EOF {
+				break
+			}
+			offs := file.Offset(pos)
+			if tok == sel {
+				seg = Segment{offs, offs + len(lit)}
+				break
+			}
+		}
+		return
+	}
+}
+
+// makeSelection is a helper function to make a Selection from a slice of pairs.
+// Pairs describing empty segments are ignored.
+//
+func makeSelection(matches [][]int) Selection {
+	i := 0
+	return func() Segment {
+		for i < len(matches) {
+			m := matches[i]
+			i++
+			if m[0] < m[1] {
+				// non-empty segment
+				return Segment{m[0], m[1]}
+			}
+		}
+		return Segment{}
+	}
+}
+
+// regexpSelection computes the Selection for the regular expression expr in text.
+func regexpSelection(text []byte, expr string) Selection {
+	var matches [][]int
+	if rx, err := regexp.Compile(expr); err == nil {
+		matches = rx.FindAllIndex(text, -1)
+	}
+	return makeSelection(matches)
+}
+
+var selRx = regexp.MustCompile(`^([0-9]+):([0-9]+)`)
+
+// RangeSelection computes the Selection for a text range described
+// by the argument str; the range description must match the selRx
+// regular expression.
+func RangeSelection(str string) Selection {
+	m := selRx.FindStringSubmatch(str)
+	if len(m) >= 2 {
+		from, _ := strconv.Atoi(m[1])
+		to, _ := strconv.Atoi(m[2])
+		if from < to {
+			return makeSelection([][]int{{from, to}})
+		}
+	}
+	return nil
+}
+
+// Span tags for all the possible selection combinations that may
+// be generated by FormatText. Selections are indicated by a bitset,
+// and the value of the bitset specifies the tag to be used.
+//
+// bit 0: comments
+// bit 1: highlights
+// bit 2: selections
+//
+var startTags = [][]byte{
+	/* 000 */ []byte(``),
+	/* 001 */ []byte(`<span class="comment">`),
+	/* 010 */ []byte(`<span class="highlight">`),
+	/* 011 */ []byte(`<span class="highlight-comment">`),
+	/* 100 */ []byte(`<span class="selection">`),
+	/* 101 */ []byte(`<span class="selection-comment">`),
+	/* 110 */ []byte(`<span class="selection-highlight">`),
+	/* 111 */ []byte(`<span class="selection-highlight-comment">`),
+}
+
+var endTag = []byte(`</span>`)
+
+func selectionTag(w io.Writer, text []byte, selections int) {
+	if selections < len(startTags) {
+		if tag := startTags[selections]; len(tag) > 0 {
+			w.Write(tag)
+			template.HTMLEscape(w, text)
+			w.Write(endTag)
+			return
+		}
+	}
+	template.HTMLEscape(w, text)
+}
+
+// FormatText HTML-escapes text and writes it to w.
+// Consecutive text segments are wrapped in HTML spans (with tags as
+// defined by startTags and endTag) as follows:
+//
+//	- if line >= 0, line number (ln) spans are inserted before each line,
+//	  starting with the value of line
+//	- if the text is Go source, comments get the "comment" span class
+//	- each occurrence of the regular expression pattern gets the "highlight"
+//	  span class
+//	- text segments covered by selection get the "selection" span class
+//
+// Comments, highlights, and selections may overlap arbitrarily; the respective
+// HTML span classes are specified in the startTags variable.
+//
+func FormatText(w io.Writer, text []byte, line int, goSource bool, pattern string, selection Selection) {
+	var comments, highlights Selection
+	if goSource {
+		comments = tokenSelection(text, token.COMMENT)
+	}
+	if pattern != "" {
+		highlights = regexpSelection(text, pattern)
+	}
+	if line >= 0 || comments != nil || highlights != nil || selection != nil {
+		var lineTag LinkWriter
+		if line >= 0 {
+			lineTag = func(w io.Writer, _ int, start bool) {
+				if start {
+					fmt.Fprintf(w, "<span id=\"L%d\" class=\"ln\">%6d</span>\t", line, line)
+					line++
+				}
+			}
+		}
+		FormatSelections(w, text, lineTag, lineSelection(text), selectionTag, comments, highlights, selection)
+	} else {
+		template.HTMLEscape(w, text)
+	}
+}
diff --git a/godoc/godoc.go b/godoc/godoc.go
new file mode 100644
index 0000000..6b176c6
--- /dev/null
+++ b/godoc/godoc.go
@@ -0,0 +1,633 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package godoc is a work-in-progress (2013-07-17) package to
+// begin splitting up the godoc binary into multiple pieces.
+//
+// This package comment will evolve over time as this package splits
+// into smaller pieces.
+package godoc // import "golang.org/x/tools/godoc"
+
+import (
+	"bytes"
+	"fmt"
+	"go/ast"
+	"go/doc"
+	"go/format"
+	"go/printer"
+	"go/token"
+	htmltemplate "html/template"
+	"io"
+	"log"
+	"os"
+	pathpkg "path"
+	"regexp"
+	"strconv"
+	"strings"
+	"text/template"
+	"time"
+	"unicode"
+	"unicode/utf8"
+)
+
+// Fake relative package path for built-ins. Documentation for all globals
+// (not just exported ones) will be shown for packages in this directory.
+const builtinPkgPath = "builtin"
+
+// FuncMap defines template functions used in godoc templates.
+//
+// Convention: template function names ending in "_html" or "_url" produce
+//             HTML- or URL-escaped strings; all other function results may
+//             require explicit escaping in the template.
+func (p *Presentation) FuncMap() template.FuncMap {
+	p.initFuncMapOnce.Do(p.initFuncMap)
+	return p.funcMap
+}
+
+func (p *Presentation) TemplateFuncs() template.FuncMap {
+	p.initFuncMapOnce.Do(p.initFuncMap)
+	return p.templateFuncs
+}
+
+func (p *Presentation) initFuncMap() {
+	if p.Corpus == nil {
+		panic("nil Presentation.Corpus")
+	}
+	p.templateFuncs = template.FuncMap{
+		"code": p.code,
+	}
+	p.funcMap = template.FuncMap{
+		// various helpers
+		"filename": filenameFunc,
+		"repeat":   strings.Repeat,
+
+		// access to FileInfos (directory listings)
+		"fileInfoName": fileInfoNameFunc,
+		"fileInfoTime": fileInfoTimeFunc,
+
+		// access to search result information
+		"infoKind_html":    infoKind_htmlFunc,
+		"infoLine":         p.infoLineFunc,
+		"infoSnippet_html": p.infoSnippet_htmlFunc,
+
+		// formatting of AST nodes
+		"node":         p.nodeFunc,
+		"node_html":    p.node_htmlFunc,
+		"comment_html": comment_htmlFunc,
+		"comment_text": comment_textFunc,
+		"sanitize":     sanitizeFunc,
+
+		// support for URL attributes
+		"pkgLink":     pkgLinkFunc,
+		"srcLink":     srcLinkFunc,
+		"posLink_url": newPosLink_urlFunc(srcPosLinkFunc),
+		"docLink":     docLinkFunc,
+		"queryLink":   queryLinkFunc,
+
+		// formatting of Examples
+		"example_html":   p.example_htmlFunc,
+		"example_text":   p.example_textFunc,
+		"example_name":   p.example_nameFunc,
+		"example_suffix": p.example_suffixFunc,
+
+		// formatting of analysis information
+		"callgraph_html":  p.callgraph_htmlFunc,
+		"implements_html": p.implements_htmlFunc,
+		"methodset_html":  p.methodset_htmlFunc,
+
+		// formatting of Notes
+		"noteTitle": noteTitle,
+
+		// Number operation
+		"multiply": multiply,
+	}
+	if p.URLForSrc != nil {
+		p.funcMap["srcLink"] = p.URLForSrc
+	}
+	if p.URLForSrcPos != nil {
+		p.funcMap["posLink_url"] = newPosLink_urlFunc(p.URLForSrcPos)
+	}
+	if p.URLForSrcQuery != nil {
+		p.funcMap["queryLink"] = p.URLForSrcQuery
+	}
+}
+
+func multiply(a, b int) int { return a * b }
+
+func filenameFunc(path string) string {
+	_, localname := pathpkg.Split(path)
+	return localname
+}
+
+func fileInfoNameFunc(fi os.FileInfo) string {
+	name := fi.Name()
+	if fi.IsDir() {
+		name += "/"
+	}
+	return name
+}
+
+func fileInfoTimeFunc(fi os.FileInfo) string {
+	if t := fi.ModTime(); t.Unix() != 0 {
+		return t.Local().String()
+	}
+	return "" // don't return epoch if time is obviously not set
+}
+
+// The strings in infoKinds must be properly html-escaped.
+var infoKinds = [nKinds]string{
+	PackageClause: "package&nbsp;clause",
+	ImportDecl:    "import&nbsp;decl",
+	ConstDecl:     "const&nbsp;decl",
+	TypeDecl:      "type&nbsp;decl",
+	VarDecl:       "var&nbsp;decl",
+	FuncDecl:      "func&nbsp;decl",
+	MethodDecl:    "method&nbsp;decl",
+	Use:           "use",
+}
+
+func infoKind_htmlFunc(info SpotInfo) string {
+	return infoKinds[info.Kind()] // infoKind entries are html-escaped
+}
+
+func (p *Presentation) infoLineFunc(info SpotInfo) int {
+	line := info.Lori()
+	if info.IsIndex() {
+		index, _ := p.Corpus.searchIndex.Get()
+		if index != nil {
+			line = index.(*Index).Snippet(line).Line
+		} else {
+			// no line information available because
+			// we don't have an index - this should
+			// never happen; be conservative and don't
+			// crash
+			line = 0
+		}
+	}
+	return line
+}
+
+func (p *Presentation) infoSnippet_htmlFunc(info SpotInfo) string {
+	if info.IsIndex() {
+		index, _ := p.Corpus.searchIndex.Get()
+		// Snippet.Text was HTML-escaped when it was generated
+		return index.(*Index).Snippet(info.Lori()).Text
+	}
+	return `<span class="alert">no snippet text available</span>`
+}
+
+func (p *Presentation) nodeFunc(info *PageInfo, node interface{}) string {
+	var buf bytes.Buffer
+	p.writeNode(&buf, info.FSet, node)
+	return buf.String()
+}
+
+func (p *Presentation) node_htmlFunc(info *PageInfo, node interface{}, linkify bool) string {
+	var buf1 bytes.Buffer
+	p.writeNode(&buf1, info.FSet, node)
+
+	var buf2 bytes.Buffer
+	if n, _ := node.(ast.Node); n != nil && linkify && p.DeclLinks {
+		LinkifyText(&buf2, buf1.Bytes(), n)
+	} else {
+		FormatText(&buf2, buf1.Bytes(), -1, true, "", nil)
+	}
+
+	return buf2.String()
+}
+
+func comment_htmlFunc(comment string) string {
+	var buf bytes.Buffer
+	// TODO(gri) Provide list of words (e.g. function parameters)
+	//           to be emphasized by ToHTML.
+	doc.ToHTML(&buf, comment, nil) // does html-escaping
+	return buf.String()
+}
+
+// punchCardWidth is the number of columns of fixed-width
+// characters to assume when wrapping text.  Very few people
+// use terminals or cards smaller than 80 characters, so 80 it is.
+// We do not try to sniff the environment or the tty to adapt to
+// the situation; instead, by using a constant we make sure that
+// godoc always produces the same output regardless of context,
+// a consistency that is lost otherwise.  For example, if we sniffed
+// the environment or tty, then http://golang.org/pkg/math/?m=text
+// would depend on the width of the terminal where godoc started,
+// which is clearly bogus.  More generally, the Unix tools that behave
+// differently when writing to a tty than when writing to a file have
+// a history of causing confusion (compare `ls` and `ls | cat`), and we
+// want to avoid that mistake here.
+const punchCardWidth = 80
+
+func containsOnlySpace(buf []byte) bool {
+	isNotSpace := func(r rune) bool { return !unicode.IsSpace(r) }
+	return bytes.IndexFunc(buf, isNotSpace) == -1
+}
+
+func comment_textFunc(comment, indent, preIndent string) string {
+	var buf bytes.Buffer
+	doc.ToText(&buf, comment, indent, preIndent, punchCardWidth-2*len(indent))
+	if containsOnlySpace(buf.Bytes()) {
+		return ""
+	}
+	return buf.String()
+}
+
+// sanitizeFunc sanitizes the argument src by replacing newlines with
+// blanks, removing extra blanks, and by removing trailing whitespace
+// and commas before closing parentheses.
+func sanitizeFunc(src string) string {
+	buf := make([]byte, len(src))
+	j := 0      // buf index
+	comma := -1 // comma index if >= 0
+	for i := 0; i < len(src); i++ {
+		ch := src[i]
+		switch ch {
+		case '\t', '\n', ' ':
+			// ignore whitespace at the beginning, after a blank, or after opening parentheses
+			if j == 0 {
+				continue
+			}
+			if p := buf[j-1]; p == ' ' || p == '(' || p == '{' || p == '[' {
+				continue
+			}
+			// replace all whitespace with blanks
+			ch = ' '
+		case ',':
+			comma = j
+		case ')', '}', ']':
+			// remove any trailing comma
+			if comma >= 0 {
+				j = comma
+			}
+			// remove any trailing whitespace
+			if j > 0 && buf[j-1] == ' ' {
+				j--
+			}
+		default:
+			comma = -1
+		}
+		buf[j] = ch
+		j++
+	}
+	// remove trailing blank, if any
+	if j > 0 && buf[j-1] == ' ' {
+		j--
+	}
+	return string(buf[:j])
+}
+
+type PageInfo struct {
+	Dirname string // directory containing the package
+	Err     error  // error or nil
+
+	// package info
+	FSet       *token.FileSet         // nil if no package documentation
+	PDoc       *doc.Package           // nil if no package documentation
+	Examples   []*doc.Example         // nil if no example code
+	Notes      map[string][]*doc.Note // nil if no package Notes
+	PAst       map[string]*ast.File   // nil if no AST with package exports
+	IsMain     bool                   // true for package main
+	IsFiltered bool                   // true if results were filtered
+
+	// analysis info
+	TypeInfoIndex  map[string]int  // index of JSON datum for type T (if -analysis=type)
+	AnalysisData   htmltemplate.JS // array of TypeInfoJSON values
+	CallGraph      htmltemplate.JS // array of PCGNodeJSON values    (if -analysis=pointer)
+	CallGraphIndex map[string]int  // maps func name to index in CallGraph
+
+	// directory info
+	Dirs    *DirList  // nil if no directory information
+	DirTime time.Time // directory time stamp
+	DirFlat bool      // if set, show directory in a flat (non-indented) manner
+}
+
+func (info *PageInfo) IsEmpty() bool {
+	return info.Err != nil || info.PAst == nil && info.PDoc == nil && info.Dirs == nil
+}
+
+func pkgLinkFunc(path string) string {
+	// because of the irregular mapping under goroot
+	// we need to correct certain relative paths
+	path = strings.TrimPrefix(path, "/")
+	path = strings.TrimPrefix(path, "src/")
+	path = strings.TrimPrefix(path, "pkg/")
+	return "pkg/" + path
+}
+
+func newPosLink_urlFunc(srcPosLinkFunc func(s string, line, low, high int) string) func(info *PageInfo, n interface{}) string {
+	// n must be an ast.Node or a *doc.Note
+	return func(info *PageInfo, n interface{}) string {
+		var pos, end token.Pos
+
+		switch n := n.(type) {
+		case ast.Node:
+			pos = n.Pos()
+			end = n.End()
+		case *doc.Note:
+			pos = n.Pos
+			end = n.End
+		default:
+			panic(fmt.Sprintf("wrong type for posLink_url template formatter: %T", n))
+		}
+
+		var relpath string
+		var line int
+		var low, high int // selection offset range
+
+		if pos.IsValid() {
+			p := info.FSet.Position(pos)
+			relpath = p.Filename
+			line = p.Line
+			low = p.Offset
+		}
+		if end.IsValid() {
+			high = info.FSet.Position(end).Offset
+		}
+
+		return srcPosLinkFunc(relpath, line, low, high)
+	}
+}
+
+func srcPosLinkFunc(s string, line, low, high int) string {
+	s = srcLinkFunc(s)
+	var buf bytes.Buffer
+	template.HTMLEscape(&buf, []byte(s))
+	// selection ranges are of form "s=low:high"
+	if low < high {
+		fmt.Fprintf(&buf, "?s=%d:%d", low, high) // no need for URL escaping
+		// if we have a selection, position the page
+		// such that the selection is a bit below the top
+		line -= 10
+		if line < 1 {
+			line = 1
+		}
+	}
+	// line id's in html-printed source are of the
+	// form "L%d" where %d stands for the line number
+	if line > 0 {
+		fmt.Fprintf(&buf, "#L%d", line) // no need for URL escaping
+	}
+	return buf.String()
+}
+
+func srcLinkFunc(s string) string {
+	s = pathpkg.Clean("/" + s)
+	if !strings.HasPrefix(s, "/src/") {
+		s = "/src" + s
+	}
+	return s
+}
+
+// queryLinkFunc returns a URL for a line in a source file with a highlighted
+// query term.
+// s is expected to be a path to a source file.
+// query is expected to be a string that has already been appropriately escaped
+// for use in a URL query.
+func queryLinkFunc(s, query string, line int) string {
+	url := pathpkg.Clean("/"+s) + "?h=" + query
+	if line > 0 {
+		url += "#L" + strconv.Itoa(line)
+	}
+	return url
+}
+
+func docLinkFunc(s string, ident string) string {
+	return pathpkg.Clean("/pkg/"+s) + "/#" + ident
+}
+
+func (p *Presentation) example_textFunc(info *PageInfo, funcName, indent string) string {
+	if !p.ShowExamples {
+		return ""
+	}
+
+	var buf bytes.Buffer
+	first := true
+	for _, eg := range info.Examples {
+		name := stripExampleSuffix(eg.Name)
+		if name != funcName {
+			continue
+		}
+
+		if !first {
+			buf.WriteString("\n")
+		}
+		first = false
+
+		// print code
+		cnode := &printer.CommentedNode{Node: eg.Code, Comments: eg.Comments}
+		var buf1 bytes.Buffer
+		p.writeNode(&buf1, info.FSet, cnode)
+		code := buf1.String()
+		// Additional formatting if this is a function body.
+		if n := len(code); n >= 2 && code[0] == '{' && code[n-1] == '}' {
+			// remove surrounding braces
+			code = code[1 : n-1]
+			// unindent
+			code = strings.Replace(code, "\n    ", "\n", -1)
+		}
+		code = strings.Trim(code, "\n")
+		code = strings.Replace(code, "\n", "\n\t", -1)
+
+		buf.WriteString(indent)
+		buf.WriteString("Example:\n\t")
+		buf.WriteString(code)
+		buf.WriteString("\n")
+	}
+	return buf.String()
+}
+
+func (p *Presentation) example_htmlFunc(info *PageInfo, funcName string) string {
+	var buf bytes.Buffer
+	for _, eg := range info.Examples {
+		name := stripExampleSuffix(eg.Name)
+
+		if name != funcName {
+			continue
+		}
+
+		// print code
+		cnode := &printer.CommentedNode{Node: eg.Code, Comments: eg.Comments}
+		code := p.node_htmlFunc(info, cnode, true)
+		out := eg.Output
+		wholeFile := true
+
+		// Additional formatting if this is a function body.
+		if n := len(code); n >= 2 && code[0] == '{' && code[n-1] == '}' {
+			wholeFile = false
+			// remove surrounding braces
+			code = code[1 : n-1]
+			// unindent
+			code = strings.Replace(code, "\n    ", "\n", -1)
+			// remove output comment
+			if loc := exampleOutputRx.FindStringIndex(code); loc != nil {
+				code = strings.TrimSpace(code[:loc[0]])
+			}
+		}
+
+		// Write out the playground code in standard Go style
+		// (use tabs, no comment highlight, etc).
+		play := ""
+		if eg.Play != nil && p.ShowPlayground {
+			var buf bytes.Buffer
+			if err := format.Node(&buf, info.FSet, eg.Play); err != nil {
+				log.Print(err)
+			} else {
+				play = buf.String()
+			}
+		}
+
+		// Drop output, as the output comment will appear in the code.
+		if wholeFile && play == "" {
+			out = ""
+		}
+
+		if p.ExampleHTML == nil {
+			out = ""
+			return ""
+		}
+
+		err := p.ExampleHTML.Execute(&buf, struct {
+			Name, Doc, Code, Play, Output string
+		}{eg.Name, eg.Doc, code, play, out})
+		if err != nil {
+			log.Print(err)
+		}
+	}
+	return buf.String()
+}
+
+// example_nameFunc takes an example function name and returns its display
+// name. For example, "Foo_Bar_quux" becomes "Foo.Bar (Quux)".
+func (p *Presentation) example_nameFunc(s string) string {
+	name, suffix := splitExampleName(s)
+	// replace _ with . for method names
+	name = strings.Replace(name, "_", ".", 1)
+	// use "Package" if no name provided
+	if name == "" {
+		name = "Package"
+	}
+	return name + suffix
+}
+
+// example_suffixFunc takes an example function name and returns its suffix in
+// parenthesized form. For example, "Foo_Bar_quux" becomes " (Quux)".
+func (p *Presentation) example_suffixFunc(name string) string {
+	_, suffix := splitExampleName(name)
+	return suffix
+}
+
+// implements_html returns the "> Implements" toggle for a package-level named type.
+// Its contents are populated from JSON data by client-side JS at load time.
+func (p *Presentation) implements_htmlFunc(info *PageInfo, typeName string) string {
+	if p.ImplementsHTML == nil {
+		return ""
+	}
+	index, ok := info.TypeInfoIndex[typeName]
+	if !ok {
+		return ""
+	}
+	var buf bytes.Buffer
+	err := p.ImplementsHTML.Execute(&buf, struct{ Index int }{index})
+	if err != nil {
+		log.Print(err)
+	}
+	return buf.String()
+}
+
+// methodset_html returns the "> Method set" toggle for a package-level named type.
+// Its contents are populated from JSON data by client-side JS at load time.
+func (p *Presentation) methodset_htmlFunc(info *PageInfo, typeName string) string {
+	if p.MethodSetHTML == nil {
+		return ""
+	}
+	index, ok := info.TypeInfoIndex[typeName]
+	if !ok {
+		return ""
+	}
+	var buf bytes.Buffer
+	err := p.MethodSetHTML.Execute(&buf, struct{ Index int }{index})
+	if err != nil {
+		log.Print(err)
+	}
+	return buf.String()
+}
+
+// callgraph_html returns the "> Call graph" toggle for a package-level func.
+// Its contents are populated from JSON data by client-side JS at load time.
+func (p *Presentation) callgraph_htmlFunc(info *PageInfo, recv, name string) string {
+	if p.CallGraphHTML == nil {
+		return ""
+	}
+	if recv != "" {
+		// Format must match (*ssa.Function).RelString().
+		name = fmt.Sprintf("(%s).%s", recv, name)
+	}
+	index, ok := info.CallGraphIndex[name]
+	if !ok {
+		return ""
+	}
+	var buf bytes.Buffer
+	err := p.CallGraphHTML.Execute(&buf, struct{ Index int }{index})
+	if err != nil {
+		log.Print(err)
+	}
+	return buf.String()
+}
+
+func noteTitle(note string) string {
+	return strings.Title(strings.ToLower(note))
+}
+
+func startsWithUppercase(s string) bool {
+	r, _ := utf8.DecodeRuneInString(s)
+	return unicode.IsUpper(r)
+}
+
+var exampleOutputRx = regexp.MustCompile(`(?i)//[[:space:]]*output:`)
+
+// stripExampleSuffix strips lowercase braz in Foo_braz or Foo_Bar_braz from name
+// while keeping uppercase Braz in Foo_Braz.
+func stripExampleSuffix(name string) string {
+	if i := strings.LastIndex(name, "_"); i != -1 {
+		if i < len(name)-1 && !startsWithUppercase(name[i+1:]) {
+			name = name[:i]
+		}
+	}
+	return name
+}
+
+func splitExampleName(s string) (name, suffix string) {
+	i := strings.LastIndex(s, "_")
+	if 0 <= i && i < len(s)-1 && !startsWithUppercase(s[i+1:]) {
+		name = s[:i]
+		suffix = " (" + strings.Title(s[i+1:]) + ")"
+		return
+	}
+	name = s
+	return
+}
+
+// Write an AST node to w.
+func (p *Presentation) writeNode(w io.Writer, fset *token.FileSet, x interface{}) {
+	// convert trailing tabs into spaces using a tconv filter
+	// to ensure a good outcome in most browsers (there may still
+	// be tabs in comments and strings, but converting those into
+	// the right number of spaces is much harder)
+	//
+	// TODO(gri) rethink printer flags - perhaps tconv can be eliminated
+	//           with an another printer mode (which is more efficiently
+	//           implemented in the printer than here with another layer)
+	mode := printer.TabIndent | printer.UseSpaces
+	err := (&printer.Config{Mode: mode, Tabwidth: p.TabWidth}).Fprint(&tconv{p: p, output: w}, fset, x)
+	if err != nil {
+		log.Print(err)
+	}
+}
+
+// WriteNode writes x to w.
+// TODO(bgarcia) Is this method needed? It's just a wrapper for p.writeNode.
+func (p *Presentation) WriteNode(w io.Writer, fset *token.FileSet, x interface{}) {
+	p.writeNode(w, fset, x)
+}
diff --git a/godoc/godoc_test.go b/godoc/godoc_test.go
new file mode 100644
index 0000000..a10a1ab
--- /dev/null
+++ b/godoc/godoc_test.go
@@ -0,0 +1,118 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package godoc
+
+import (
+	"testing"
+)
+
+func TestPkgLinkFunc(t *testing.T) {
+	for _, tc := range []struct {
+		path string
+		want string
+	}{
+		{"/src/fmt", "pkg/fmt"},
+		{"src/fmt", "pkg/fmt"},
+		{"/fmt", "pkg/fmt"},
+		{"fmt", "pkg/fmt"},
+	} {
+		if got := pkgLinkFunc(tc.path); got != tc.want {
+			t.Errorf("pkgLinkFunc(%v) = %v; want %v", tc.path, got, tc.want)
+		}
+	}
+}
+
+func TestSrcPosLinkFunc(t *testing.T) {
+	for _, tc := range []struct {
+		src  string
+		line int
+		low  int
+		high int
+		want string
+	}{
+		{"/src/fmt/print.go", 42, 30, 50, "/src/fmt/print.go?s=30:50#L32"},
+		{"/src/fmt/print.go", 2, 1, 5, "/src/fmt/print.go?s=1:5#L1"},
+		{"/src/fmt/print.go", 2, 0, 0, "/src/fmt/print.go#L2"},
+		{"/src/fmt/print.go", 0, 0, 0, "/src/fmt/print.go"},
+		{"/src/fmt/print.go", 0, 1, 5, "/src/fmt/print.go?s=1:5#L1"},
+		{"fmt/print.go", 0, 0, 0, "/src/fmt/print.go"},
+		{"fmt/print.go", 0, 1, 5, "/src/fmt/print.go?s=1:5#L1"},
+	} {
+		if got := srcPosLinkFunc(tc.src, tc.line, tc.low, tc.high); got != tc.want {
+			t.Errorf("srcLinkFunc(%v, %v, %v, %v) = %v; want %v", tc.src, tc.line, tc.low, tc.high, got, tc.want)
+		}
+	}
+}
+
+func TestSrcLinkFunc(t *testing.T) {
+	for _, tc := range []struct {
+		src  string
+		want string
+	}{
+		{"/src/fmt/print.go", "/src/fmt/print.go"},
+		{"src/fmt/print.go", "/src/fmt/print.go"},
+		{"/fmt/print.go", "/src/fmt/print.go"},
+		{"fmt/print.go", "/src/fmt/print.go"},
+	} {
+		if got := srcLinkFunc(tc.src); got != tc.want {
+			t.Errorf("srcLinkFunc(%v) = %v; want %v", tc.src, got, tc.want)
+		}
+	}
+}
+
+func TestQueryLinkFunc(t *testing.T) {
+	for _, tc := range []struct {
+		src   string
+		query string
+		line  int
+		want  string
+	}{
+		{"/src/fmt/print.go", "Sprintf", 33, "/src/fmt/print.go?h=Sprintf#L33"},
+		{"/src/fmt/print.go", "Sprintf", 0, "/src/fmt/print.go?h=Sprintf"},
+		{"src/fmt/print.go", "EOF", 33, "/src/fmt/print.go?h=EOF#L33"},
+		{"src/fmt/print.go", "a%3f+%26b", 1, "/src/fmt/print.go?h=a%3f+%26b#L1"},
+	} {
+		if got := queryLinkFunc(tc.src, tc.query, tc.line); got != tc.want {
+			t.Errorf("queryLinkFunc(%v, %v, %v) = %v; want %v", tc.src, tc.query, tc.line, got, tc.want)
+		}
+	}
+}
+
+func TestDocLinkFunc(t *testing.T) {
+	for _, tc := range []struct {
+		src   string
+		ident string
+		want  string
+	}{
+		{"fmt", "Sprintf", "/pkg/fmt/#Sprintf"},
+		{"fmt", "EOF", "/pkg/fmt/#EOF"},
+	} {
+		if got := docLinkFunc(tc.src, tc.ident); got != tc.want {
+			t.Errorf("docLinkFunc(%v, %v) = %v; want %v", tc.src, tc.ident, got, tc.want)
+		}
+	}
+}
+
+func TestSanitizeFunc(t *testing.T) {
+	for _, tc := range []struct {
+		src  string
+		want string
+	}{
+		{},
+		{"foo", "foo"},
+		{"func   f()", "func f()"},
+		{"func f(a int,)", "func f(a int)"},
+		{"func f(a int,\n)", "func f(a int)"},
+		{"func f(\n\ta int,\n\tb int,\n\tc int,\n)", "func f(a int, b int, c int)"},
+		{"  (   a,   b,  c  )  ", "(a, b, c)"},
+		{"(  a,  b, c    int, foo   bar  ,  )", "(a, b, c int, foo bar)"},
+		{"{   a,   b}", "{a, b}"},
+		{"[   a,   b]", "[a, b]"},
+	} {
+		if got := sanitizeFunc(tc.src); got != tc.want {
+			t.Errorf("sanitizeFunc(%v) = %v; want %v", tc.src, got, tc.want)
+		}
+	}
+}
diff --git a/godoc/index.go b/godoc/index.go
new file mode 100644
index 0000000..725121a
--- /dev/null
+++ b/godoc/index.go
@@ -0,0 +1,1590 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file contains the infrastructure to create an
+// identifier and full-text index for a set of Go files.
+//
+// Algorithm for identifier index:
+// - traverse all .go files of the file tree specified by root
+// - for each identifier (word) encountered, collect all occurrences (spots)
+//   into a list; this produces a list of spots for each word
+// - reduce the lists: from a list of spots to a list of FileRuns,
+//   and from a list of FileRuns into a list of PakRuns
+// - make a HitList from the PakRuns
+//
+// Details:
+// - keep two lists per word: one containing package-level declarations
+//   that have snippets, and one containing all other spots
+// - keep the snippets in a separate table indexed by snippet index
+//   and store the snippet index in place of the line number in a SpotInfo
+//   (the line number for spots with snippets is stored in the snippet)
+// - at the end, create lists of alternative spellings for a given
+//   word
+//
+// Algorithm for full text index:
+// - concatenate all source code in a byte buffer (in memory)
+// - add the files to a file set in lockstep as they are added to the byte
+//   buffer such that a byte buffer offset corresponds to the Pos value for
+//   that file location
+// - create a suffix array from the concatenated sources
+//
+// String lookup in full text index:
+// - use the suffix array to lookup a string's offsets - the offsets
+//   correspond to the Pos values relative to the file set
+// - translate the Pos values back into file and line information and
+//   sort the result
+
+package godoc
+
+import (
+	"bufio"
+	"bytes"
+	"encoding/gob"
+	"errors"
+	"fmt"
+	"go/ast"
+	"go/doc"
+	"go/parser"
+	"go/token"
+	"index/suffixarray"
+	"io"
+	"log"
+	"os"
+	pathpkg "path"
+	"path/filepath"
+	"regexp"
+	"runtime"
+	"sort"
+	"strconv"
+	"strings"
+	"sync"
+	"time"
+	"unicode"
+
+	"golang.org/x/tools/godoc/util"
+	"golang.org/x/tools/godoc/vfs"
+)
+
+// ----------------------------------------------------------------------------
+// InterfaceSlice is a helper type for sorting interface
+// slices according to some slice-specific sort criteria.
+
+type comparer func(x, y interface{}) bool
+
+type interfaceSlice struct {
+	slice []interface{}
+	less  comparer
+}
+
+// ----------------------------------------------------------------------------
+// RunList
+
+// A RunList is a list of entries that can be sorted according to some
+// criteria. A RunList may be compressed by grouping "runs" of entries
+// which are equal (according to the sort critera) into a new RunList of
+// runs. For instance, a RunList containing pairs (x, y) may be compressed
+// into a RunList containing pair runs (x, {y}) where each run consists of
+// a list of y's with the same x.
+type RunList []interface{}
+
+func (h RunList) sort(less comparer) {
+	sort.Sort(&interfaceSlice{h, less})
+}
+
+func (p *interfaceSlice) Len() int           { return len(p.slice) }
+func (p *interfaceSlice) Less(i, j int) bool { return p.less(p.slice[i], p.slice[j]) }
+func (p *interfaceSlice) Swap(i, j int)      { p.slice[i], p.slice[j] = p.slice[j], p.slice[i] }
+
+// Compress entries which are the same according to a sort criteria
+// (specified by less) into "runs".
+func (h RunList) reduce(less comparer, newRun func(h RunList) interface{}) RunList {
+	if len(h) == 0 {
+		return nil
+	}
+	// len(h) > 0
+
+	// create runs of entries with equal values
+	h.sort(less)
+
+	// for each run, make a new run object and collect them in a new RunList
+	var hh RunList
+	i, x := 0, h[0]
+	for j, y := range h {
+		if less(x, y) {
+			hh = append(hh, newRun(h[i:j]))
+			i, x = j, h[j] // start a new run
+		}
+	}
+	// add final run, if any
+	if i < len(h) {
+		hh = append(hh, newRun(h[i:]))
+	}
+
+	return hh
+}
+
+// ----------------------------------------------------------------------------
+// KindRun
+
+// Debugging support. Disable to see multiple entries per line.
+const removeDuplicates = true
+
+// A KindRun is a run of SpotInfos of the same kind in a given file.
+// The kind (3 bits) is stored in each SpotInfo element; to find the
+// kind of a KindRun, look at any of its elements.
+type KindRun []SpotInfo
+
+// KindRuns are sorted by line number or index. Since the isIndex bit
+// is always the same for all infos in one list we can compare lori's.
+func (k KindRun) Len() int           { return len(k) }
+func (k KindRun) Less(i, j int) bool { return k[i].Lori() < k[j].Lori() }
+func (k KindRun) Swap(i, j int)      { k[i], k[j] = k[j], k[i] }
+
+// FileRun contents are sorted by Kind for the reduction into KindRuns.
+func lessKind(x, y interface{}) bool { return x.(SpotInfo).Kind() < y.(SpotInfo).Kind() }
+
+// newKindRun allocates a new KindRun from the SpotInfo run h.
+func newKindRun(h RunList) interface{} {
+	run := make(KindRun, len(h))
+	for i, x := range h {
+		run[i] = x.(SpotInfo)
+	}
+
+	// Spots were sorted by file and kind to create this run.
+	// Within this run, sort them by line number or index.
+	sort.Sort(run)
+
+	if removeDuplicates {
+		// Since both the lori and kind field must be
+		// same for duplicates, and since the isIndex
+		// bit is always the same for all infos in one
+		// list we can simply compare the entire info.
+		k := 0
+		prev := SpotInfo(1<<32 - 1) // an unlikely value
+		for _, x := range run {
+			if x != prev {
+				run[k] = x
+				k++
+				prev = x
+			}
+		}
+		run = run[0:k]
+	}
+
+	return run
+}
+
+// ----------------------------------------------------------------------------
+// FileRun
+
+// A Pak describes a Go package.
+type Pak struct {
+	Path string // path of directory containing the package
+	Name string // package name as declared by package clause
+}
+
+// Paks are sorted by name (primary key) and by import path (secondary key).
+func (p *Pak) less(q *Pak) bool {
+	return p.Name < q.Name || p.Name == q.Name && p.Path < q.Path
+}
+
+// A File describes a Go file.
+type File struct {
+	Name string // directory-local file name
+	Pak  *Pak   // the package to which the file belongs
+}
+
+// Path returns the file path of f.
+func (f *File) Path() string {
+	return pathpkg.Join(f.Pak.Path, f.Name)
+}
+
+// A Spot describes a single occurrence of a word.
+type Spot struct {
+	File *File
+	Info SpotInfo
+}
+
+// A FileRun is a list of KindRuns belonging to the same file.
+type FileRun struct {
+	File   *File
+	Groups []KindRun
+}
+
+// Spots are sorted by file path for the reduction into FileRuns.
+func lessSpot(x, y interface{}) bool {
+	fx := x.(Spot).File
+	fy := y.(Spot).File
+	// same as "return fx.Path() < fy.Path()" but w/o computing the file path first
+	px := fx.Pak.Path
+	py := fy.Pak.Path
+	return px < py || px == py && fx.Name < fy.Name
+}
+
+// newFileRun allocates a new FileRun from the Spot run h.
+func newFileRun(h RunList) interface{} {
+	file := h[0].(Spot).File
+
+	// reduce the list of Spots into a list of KindRuns
+	h1 := make(RunList, len(h))
+	for i, x := range h {
+		h1[i] = x.(Spot).Info
+	}
+	h2 := h1.reduce(lessKind, newKindRun)
+
+	// create the FileRun
+	groups := make([]KindRun, len(h2))
+	for i, x := range h2 {
+		groups[i] = x.(KindRun)
+	}
+	return &FileRun{file, groups}
+}
+
+// ----------------------------------------------------------------------------
+// PakRun
+
+// A PakRun describes a run of *FileRuns of a package.
+type PakRun struct {
+	Pak   *Pak
+	Files []*FileRun
+}
+
+// Sorting support for files within a PakRun.
+func (p *PakRun) Len() int           { return len(p.Files) }
+func (p *PakRun) Less(i, j int) bool { return p.Files[i].File.Name < p.Files[j].File.Name }
+func (p *PakRun) Swap(i, j int)      { p.Files[i], p.Files[j] = p.Files[j], p.Files[i] }
+
+// FileRuns are sorted by package for the reduction into PakRuns.
+func lessFileRun(x, y interface{}) bool {
+	return x.(*FileRun).File.Pak.less(y.(*FileRun).File.Pak)
+}
+
+// newPakRun allocates a new PakRun from the *FileRun run h.
+func newPakRun(h RunList) interface{} {
+	pak := h[0].(*FileRun).File.Pak
+	files := make([]*FileRun, len(h))
+	for i, x := range h {
+		files[i] = x.(*FileRun)
+	}
+	run := &PakRun{pak, files}
+	sort.Sort(run) // files were sorted by package; sort them by file now
+	return run
+}
+
+// ----------------------------------------------------------------------------
+// HitList
+
+// A HitList describes a list of PakRuns.
+type HitList []*PakRun
+
+// PakRuns are sorted by package.
+func lessPakRun(x, y interface{}) bool { return x.(*PakRun).Pak.less(y.(*PakRun).Pak) }
+
+func reduce(h0 RunList) HitList {
+	// reduce a list of Spots into a list of FileRuns
+	h1 := h0.reduce(lessSpot, newFileRun)
+	// reduce a list of FileRuns into a list of PakRuns
+	h2 := h1.reduce(lessFileRun, newPakRun)
+	// sort the list of PakRuns by package
+	h2.sort(lessPakRun)
+	// create a HitList
+	h := make(HitList, len(h2))
+	for i, p := range h2 {
+		h[i] = p.(*PakRun)
+	}
+	return h
+}
+
+// filter returns a new HitList created by filtering
+// all PakRuns from h that have a matching pakname.
+func (h HitList) filter(pakname string) HitList {
+	var hh HitList
+	for _, p := range h {
+		if p.Pak.Name == pakname {
+			hh = append(hh, p)
+		}
+	}
+	return hh
+}
+
+// ----------------------------------------------------------------------------
+// AltWords
+
+type wordPair struct {
+	canon string // canonical word spelling (all lowercase)
+	alt   string // alternative spelling
+}
+
+// An AltWords describes a list of alternative spellings for a
+// canonical (all lowercase) spelling of a word.
+type AltWords struct {
+	Canon string   // canonical word spelling (all lowercase)
+	Alts  []string // alternative spelling for the same word
+}
+
+// wordPairs are sorted by their canonical spelling.
+func lessWordPair(x, y interface{}) bool { return x.(*wordPair).canon < y.(*wordPair).canon }
+
+// newAltWords allocates a new AltWords from the *wordPair run h.
+func newAltWords(h RunList) interface{} {
+	canon := h[0].(*wordPair).canon
+	alts := make([]string, len(h))
+	for i, x := range h {
+		alts[i] = x.(*wordPair).alt
+	}
+	return &AltWords{canon, alts}
+}
+
+func (a *AltWords) filter(s string) *AltWords {
+	var alts []string
+	for _, w := range a.Alts {
+		if w != s {
+			alts = append(alts, w)
+		}
+	}
+	if len(alts) > 0 {
+		return &AltWords{a.Canon, alts}
+	}
+	return nil
+}
+
+// Ident stores information about external identifiers in order to create
+// links to package documentation.
+type Ident struct {
+	Path    string // e.g. "net/http"
+	Package string // e.g. "http"
+	Name    string // e.g. "NewRequest"
+	Doc     string // e.g. "NewRequest returns a new Request..."
+}
+
+// byImportCount sorts the given slice of Idents by the import
+// counts of the packages to which they belong.
+type byImportCount struct {
+	Idents      []Ident
+	ImportCount map[string]int
+}
+
+func (ic byImportCount) Len() int {
+	return len(ic.Idents)
+}
+
+func (ic byImportCount) Less(i, j int) bool {
+	ri := ic.ImportCount[ic.Idents[i].Path]
+	rj := ic.ImportCount[ic.Idents[j].Path]
+	if ri == rj {
+		return ic.Idents[i].Path < ic.Idents[j].Path
+	}
+	return ri > rj
+}
+
+func (ic byImportCount) Swap(i, j int) {
+	ic.Idents[i], ic.Idents[j] = ic.Idents[j], ic.Idents[i]
+}
+
+func (ic byImportCount) String() string {
+	buf := bytes.NewBuffer([]byte("["))
+	for _, v := range ic.Idents {
+		buf.WriteString(fmt.Sprintf("\n\t%s, %s (%d)", v.Path, v.Name, ic.ImportCount[v.Path]))
+	}
+	buf.WriteString("\n]")
+	return buf.String()
+}
+
+// filter creates a new Ident list where the results match the given
+// package name.
+func (ic byImportCount) filter(pakname string) []Ident {
+	if ic.Idents == nil {
+		return nil
+	}
+	var res []Ident
+	for _, i := range ic.Idents {
+		if i.Package == pakname {
+			res = append(res, i)
+		}
+	}
+	return res
+}
+
+// top returns the top n identifiers.
+func (ic byImportCount) top(n int) []Ident {
+	if len(ic.Idents) > n {
+		return ic.Idents[:n]
+	}
+	return ic.Idents
+}
+
+// ----------------------------------------------------------------------------
+// Indexer
+
+type IndexResult struct {
+	Decls  RunList // package-level declarations (with snippets)
+	Others RunList // all other occurrences
+}
+
+// Statistics provides statistics information for an index.
+type Statistics struct {
+	Bytes int // total size of indexed source files
+	Files int // number of indexed source files
+	Lines int // number of lines (all files)
+	Words int // number of different identifiers
+	Spots int // number of identifier occurrences
+}
+
+// An Indexer maintains the data structures and provides the machinery
+// for indexing .go files under a file tree. It implements the path.Visitor
+// interface for walking file trees, and the ast.Visitor interface for
+// walking Go ASTs.
+type Indexer struct {
+	c          *Corpus
+	fset       *token.FileSet // file set for all indexed files
+	fsOpenGate chan bool      // send pre fs.Open; receive on close
+
+	mu            sync.Mutex              // guards all the following
+	sources       bytes.Buffer            // concatenated sources
+	strings       map[string]string       // interned string
+	packages      map[Pak]*Pak            // interned *Paks
+	words         map[string]*IndexResult // RunLists of Spots
+	snippets      []*Snippet              // indices are stored in SpotInfos
+	current       *token.File             // last file added to file set
+	file          *File                   // AST for current file
+	decl          ast.Decl                // AST for current decl
+	stats         Statistics
+	throttle      *util.Throttle
+	importCount   map[string]int                 // package path ("net/http") => count
+	packagePath   map[string]map[string]bool     // "template" => "text/template" => true
+	exports       map[string]map[string]SpotKind // "net/http" => "ListenAndServe" => FuncDecl
+	curPkgExports map[string]SpotKind
+	idents        map[SpotKind]map[string][]Ident // kind => name => list of Idents
+}
+
+func (x *Indexer) intern(s string) string {
+	if s, ok := x.strings[s]; ok {
+		return s
+	}
+	x.strings[s] = s
+	return s
+}
+
+func (x *Indexer) lookupPackage(path, name string) *Pak {
+	// In the source directory tree, more than one package may
+	// live in the same directory. For the packages map, construct
+	// a key that includes both the directory path and the package
+	// name.
+	key := Pak{Path: x.intern(path), Name: x.intern(name)}
+	pak := x.packages[key]
+	if pak == nil {
+		pak = &key
+		x.packages[key] = pak
+	}
+	return pak
+}
+
+func (x *Indexer) addSnippet(s *Snippet) int {
+	index := len(x.snippets)
+	x.snippets = append(x.snippets, s)
+	return index
+}
+
+func (x *Indexer) visitIdent(kind SpotKind, id *ast.Ident) {
+	if id == nil {
+		return
+	}
+	name := x.intern(id.Name)
+
+	switch kind {
+	case TypeDecl, FuncDecl, ConstDecl, VarDecl:
+		x.curPkgExports[name] = kind
+	}
+
+	lists, found := x.words[name]
+	if !found {
+		lists = new(IndexResult)
+		x.words[name] = lists
+	}
+
+	if kind == Use || x.decl == nil {
+		if x.c.IndexGoCode {
+			// not a declaration or no snippet required
+			info := makeSpotInfo(kind, x.current.Line(id.Pos()), false)
+			lists.Others = append(lists.Others, Spot{x.file, info})
+		}
+	} else {
+		// a declaration with snippet
+		index := x.addSnippet(NewSnippet(x.fset, x.decl, id))
+		info := makeSpotInfo(kind, index, true)
+		lists.Decls = append(lists.Decls, Spot{x.file, info})
+	}
+
+	x.stats.Spots++
+}
+
+func (x *Indexer) visitFieldList(kind SpotKind, flist *ast.FieldList) {
+	for _, f := range flist.List {
+		x.decl = nil // no snippets for fields
+		for _, name := range f.Names {
+			x.visitIdent(kind, name)
+		}
+		ast.Walk(x, f.Type)
+		// ignore tag - not indexed at the moment
+	}
+}
+
+func (x *Indexer) visitSpec(kind SpotKind, spec ast.Spec) {
+	switch n := spec.(type) {
+	case *ast.ImportSpec:
+		x.visitIdent(ImportDecl, n.Name)
+		if n.Path != nil {
+			if imp, err := strconv.Unquote(n.Path.Value); err == nil {
+				x.importCount[x.intern(imp)]++
+			}
+		}
+
+	case *ast.ValueSpec:
+		for _, n := range n.Names {
+			x.visitIdent(kind, n)
+		}
+		ast.Walk(x, n.Type)
+		for _, v := range n.Values {
+			ast.Walk(x, v)
+		}
+
+	case *ast.TypeSpec:
+		x.visitIdent(TypeDecl, n.Name)
+		ast.Walk(x, n.Type)
+	}
+}
+
+func (x *Indexer) visitGenDecl(decl *ast.GenDecl) {
+	kind := VarDecl
+	if decl.Tok == token.CONST {
+		kind = ConstDecl
+	}
+	x.decl = decl
+	for _, s := range decl.Specs {
+		x.visitSpec(kind, s)
+	}
+}
+
+func (x *Indexer) Visit(node ast.Node) ast.Visitor {
+	switch n := node.(type) {
+	case nil:
+		// nothing to do
+
+	case *ast.Ident:
+		x.visitIdent(Use, n)
+
+	case *ast.FieldList:
+		x.visitFieldList(VarDecl, n)
+
+	case *ast.InterfaceType:
+		x.visitFieldList(MethodDecl, n.Methods)
+
+	case *ast.DeclStmt:
+		// local declarations should only be *ast.GenDecls;
+		// ignore incorrect ASTs
+		if decl, ok := n.Decl.(*ast.GenDecl); ok {
+			x.decl = nil // no snippets for local declarations
+			x.visitGenDecl(decl)
+		}
+
+	case *ast.GenDecl:
+		x.decl = n
+		x.visitGenDecl(n)
+
+	case *ast.FuncDecl:
+		kind := FuncDecl
+		if n.Recv != nil {
+			kind = MethodDecl
+			ast.Walk(x, n.Recv)
+		}
+		x.decl = n
+		x.visitIdent(kind, n.Name)
+		ast.Walk(x, n.Type)
+		if n.Body != nil {
+			ast.Walk(x, n.Body)
+		}
+
+	case *ast.File:
+		x.decl = nil
+		x.visitIdent(PackageClause, n.Name)
+		for _, d := range n.Decls {
+			ast.Walk(x, d)
+		}
+
+	default:
+		return x
+	}
+
+	return nil
+}
+
+// addFile adds a file to the index if possible and returns the file set file
+// and the file's AST if it was successfully parsed as a Go file. If addFile
+// failed (that is, if the file was not added), it returns file == nil.
+func (x *Indexer) addFile(f vfs.ReadSeekCloser, filename string, goFile bool) (file *token.File, ast *ast.File) {
+	defer f.Close()
+
+	// The file set's base offset and x.sources size must be in lock-step;
+	// this permits the direct mapping of suffix array lookup results to
+	// to corresponding Pos values.
+	//
+	// When a file is added to the file set, its offset base increases by
+	// the size of the file + 1; and the initial base offset is 1. Add an
+	// extra byte to the sources here.
+	x.sources.WriteByte(0)
+
+	// If the sources length doesn't match the file set base at this point
+	// the file set implementation changed or we have another error.
+	base := x.fset.Base()
+	if x.sources.Len() != base {
+		panic("internal error: file base incorrect")
+	}
+
+	// append file contents (src) to x.sources
+	if _, err := x.sources.ReadFrom(f); err == nil {
+		src := x.sources.Bytes()[base:]
+
+		if goFile {
+			// parse the file and in the process add it to the file set
+			if ast, err = parser.ParseFile(x.fset, filename, src, parser.ParseComments); err == nil {
+				file = x.fset.File(ast.Pos()) // ast.Pos() is inside the file
+				return
+			}
+			// file has parse errors, and the AST may be incorrect -
+			// set lines information explicitly and index as ordinary
+			// text file (cannot fall through to the text case below
+			// because the file has already been added to the file set
+			// by the parser)
+			file = x.fset.File(token.Pos(base)) // token.Pos(base) is inside the file
+			file.SetLinesForContent(src)
+			ast = nil
+			return
+		}
+
+		if util.IsText(src) {
+			// only add the file to the file set (for the full text index)
+			file = x.fset.AddFile(filename, x.fset.Base(), len(src))
+			file.SetLinesForContent(src)
+			return
+		}
+	}
+
+	// discard possibly added data
+	x.sources.Truncate(base - 1) // -1 to remove added byte 0 since no file was added
+	return
+}
+
+// Design note: Using an explicit white list of permitted files for indexing
+// makes sure that the important files are included and massively reduces the
+// number of files to index. The advantage over a blacklist is that unexpected
+// (non-blacklisted) files won't suddenly explode the index.
+
+// Files are whitelisted if they have a file name or extension
+// present as key in whitelisted.
+var whitelisted = map[string]bool{
+	".bash":        true,
+	".c":           true,
+	".cc":          true,
+	".cpp":         true,
+	".cxx":         true,
+	".css":         true,
+	".go":          true,
+	".goc":         true,
+	".h":           true,
+	".hh":          true,
+	".hpp":         true,
+	".hxx":         true,
+	".html":        true,
+	".js":          true,
+	".out":         true,
+	".py":          true,
+	".s":           true,
+	".sh":          true,
+	".txt":         true,
+	".xml":         true,
+	"AUTHORS":      true,
+	"CONTRIBUTORS": true,
+	"LICENSE":      true,
+	"Makefile":     true,
+	"PATENTS":      true,
+	"README":       true,
+}
+
+// isWhitelisted returns true if a file is on the list
+// of "permitted" files for indexing. The filename must
+// be the directory-local name of the file.
+func isWhitelisted(filename string) bool {
+	key := pathpkg.Ext(filename)
+	if key == "" {
+		// file has no extension - use entire filename
+		key = filename
+	}
+	return whitelisted[key]
+}
+
+func (x *Indexer) indexDocs(dirname string, filename string, astFile *ast.File) {
+	pkgName := x.intern(astFile.Name.Name)
+	if pkgName == "main" {
+		return
+	}
+	pkgPath := x.intern(strings.TrimPrefix(strings.TrimPrefix(dirname, "/src/"), "pkg/"))
+	astPkg := ast.Package{
+		Name: pkgName,
+		Files: map[string]*ast.File{
+			filename: astFile,
+		},
+	}
+	var m doc.Mode
+	docPkg := doc.New(&astPkg, dirname, m)
+	addIdent := func(sk SpotKind, name string, docstr string) {
+		if x.idents[sk] == nil {
+			x.idents[sk] = make(map[string][]Ident)
+		}
+		name = x.intern(name)
+		x.idents[sk][name] = append(x.idents[sk][name], Ident{
+			Path:    pkgPath,
+			Package: pkgName,
+			Name:    name,
+			Doc:     doc.Synopsis(docstr),
+		})
+	}
+
+	if x.idents[PackageClause] == nil {
+		x.idents[PackageClause] = make(map[string][]Ident)
+	}
+	// List of words under which the package identifier will be stored.
+	// This includes the package name and the components of the directory
+	// in which it resides.
+	words := strings.Split(pathpkg.Dir(pkgPath), "/")
+	if words[0] == "." {
+		words = []string{}
+	}
+	name := x.intern(docPkg.Name)
+	synopsis := doc.Synopsis(docPkg.Doc)
+	words = append(words, name)
+	pkgIdent := Ident{
+		Path:    pkgPath,
+		Package: pkgName,
+		Name:    name,
+		Doc:     synopsis,
+	}
+	for _, word := range words {
+		word = x.intern(word)
+		found := false
+		pkgs := x.idents[PackageClause][word]
+		for i, p := range pkgs {
+			if p.Path == pkgPath {
+				if docPkg.Doc != "" {
+					p.Doc = synopsis
+					pkgs[i] = p
+				}
+				found = true
+				break
+			}
+		}
+		if !found {
+			x.idents[PackageClause][word] = append(x.idents[PackageClause][word], pkgIdent)
+		}
+	}
+
+	for _, c := range docPkg.Consts {
+		for _, name := range c.Names {
+			addIdent(ConstDecl, name, c.Doc)
+		}
+	}
+	for _, t := range docPkg.Types {
+		addIdent(TypeDecl, t.Name, t.Doc)
+		for _, c := range t.Consts {
+			for _, name := range c.Names {
+				addIdent(ConstDecl, name, c.Doc)
+			}
+		}
+		for _, v := range t.Vars {
+			for _, name := range v.Names {
+				addIdent(VarDecl, name, v.Doc)
+			}
+		}
+		for _, f := range t.Funcs {
+			addIdent(FuncDecl, f.Name, f.Doc)
+		}
+		for _, f := range t.Methods {
+			addIdent(MethodDecl, f.Name, f.Doc)
+			// Change the name of methods to be "<typename>.<methodname>".
+			// They will still be indexed as <methodname>.
+			idents := x.idents[MethodDecl][f.Name]
+			idents[len(idents)-1].Name = x.intern(t.Name + "." + f.Name)
+		}
+	}
+	for _, v := range docPkg.Vars {
+		for _, name := range v.Names {
+			addIdent(VarDecl, name, v.Doc)
+		}
+	}
+	for _, f := range docPkg.Funcs {
+		addIdent(FuncDecl, f.Name, f.Doc)
+	}
+}
+
+func (x *Indexer) indexGoFile(dirname string, filename string, file *token.File, astFile *ast.File) {
+	pkgName := astFile.Name.Name
+
+	if x.c.IndexGoCode {
+		x.current = file
+		pak := x.lookupPackage(dirname, pkgName)
+		x.file = &File{filename, pak}
+		ast.Walk(x, astFile)
+	}
+
+	if x.c.IndexDocs {
+		// Test files are already filtered out in visitFile if IndexGoCode and
+		// IndexFullText are false.  Otherwise, check here.
+		isTestFile := (x.c.IndexGoCode || x.c.IndexFullText) &&
+			(strings.HasSuffix(filename, "_test.go") || strings.HasPrefix(dirname, "/test/"))
+		if !isTestFile {
+			x.indexDocs(dirname, filename, astFile)
+		}
+	}
+
+	ppKey := x.intern(pkgName)
+	if _, ok := x.packagePath[ppKey]; !ok {
+		x.packagePath[ppKey] = make(map[string]bool)
+	}
+	pkgPath := x.intern(strings.TrimPrefix(strings.TrimPrefix(dirname, "/src/"), "pkg/"))
+	x.packagePath[ppKey][pkgPath] = true
+
+	// Merge in exported symbols found walking this file into
+	// the map for that package.
+	if len(x.curPkgExports) > 0 {
+		dest, ok := x.exports[pkgPath]
+		if !ok {
+			dest = make(map[string]SpotKind)
+			x.exports[pkgPath] = dest
+		}
+		for k, v := range x.curPkgExports {
+			dest[k] = v
+		}
+	}
+}
+
+func (x *Indexer) visitFile(dirname string, fi os.FileInfo) {
+	if fi.IsDir() || !x.c.IndexEnabled {
+		return
+	}
+
+	filename := pathpkg.Join(dirname, fi.Name())
+	goFile := isGoFile(fi)
+
+	switch {
+	case x.c.IndexFullText:
+		if !isWhitelisted(fi.Name()) {
+			return
+		}
+	case x.c.IndexGoCode:
+		if !goFile {
+			return
+		}
+	case x.c.IndexDocs:
+		if !goFile ||
+			strings.HasSuffix(fi.Name(), "_test.go") ||
+			strings.HasPrefix(dirname, "/test/") {
+			return
+		}
+	default:
+		// No indexing turned on.
+		return
+	}
+
+	x.fsOpenGate <- true
+	defer func() { <-x.fsOpenGate }()
+
+	// open file
+	f, err := x.c.fs.Open(filename)
+	if err != nil {
+		return
+	}
+
+	x.mu.Lock()
+	defer x.mu.Unlock()
+
+	x.throttle.Throttle()
+
+	x.curPkgExports = make(map[string]SpotKind)
+	file, fast := x.addFile(f, filename, goFile)
+	if file == nil {
+		return // addFile failed
+	}
+
+	if fast != nil {
+		x.indexGoFile(dirname, fi.Name(), file, fast)
+	}
+
+	// update statistics
+	x.stats.Bytes += file.Size()
+	x.stats.Files++
+	x.stats.Lines += file.LineCount()
+}
+
+// indexOptions contains information that affects the contents of an index.
+type indexOptions struct {
+	// Docs provides documentation search results.
+	// It is only consulted if IndexEnabled is true.
+	// The default values is true.
+	Docs bool
+
+	// GoCode provides Go source code search results.
+	// It is only consulted if IndexEnabled is true.
+	// The default values is true.
+	GoCode bool
+
+	// FullText provides search results from all files.
+	// It is only consulted if IndexEnabled is true.
+	// The default values is true.
+	FullText bool
+
+	// MaxResults optionally specifies the maximum results for indexing.
+	// The default is 1000.
+	MaxResults int
+}
+
+// ----------------------------------------------------------------------------
+// Index
+
+type LookupResult struct {
+	Decls  HitList // package-level declarations (with snippets)
+	Others HitList // all other occurrences
+}
+
+type Index struct {
+	fset        *token.FileSet           // file set used during indexing; nil if no textindex
+	suffixes    *suffixarray.Index       // suffixes for concatenated sources; nil if no textindex
+	words       map[string]*LookupResult // maps words to hit lists
+	alts        map[string]*AltWords     // maps canonical(words) to lists of alternative spellings
+	snippets    []*Snippet               // all snippets, indexed by snippet index
+	stats       Statistics
+	importCount map[string]int                 // package path ("net/http") => count
+	packagePath map[string]map[string]bool     // "template" => "text/template" => true
+	exports     map[string]map[string]SpotKind // "net/http" => "ListenAndServe" => FuncDecl
+	idents      map[SpotKind]map[string][]Ident
+	opts        indexOptions
+}
+
+func canonical(w string) string { return strings.ToLower(w) }
+
+// Somewhat arbitrary, but I figure low enough to not hurt disk-based filesystems
+// consuming file descriptors, where some systems have low 256 or 512 limits.
+// Go should have a built-in way to cap fd usage under the ulimit.
+const (
+	maxOpenFiles = 200
+	maxOpenDirs  = 50
+)
+
+func (c *Corpus) throttle() float64 {
+	if c.IndexThrottle <= 0 {
+		return 0.9
+	}
+	if c.IndexThrottle > 1.0 {
+		return 1.0
+	}
+	return c.IndexThrottle
+}
+
+// NewIndex creates a new index for the .go files provided by the corpus.
+func (c *Corpus) NewIndex() *Index {
+	// initialize Indexer
+	// (use some reasonably sized maps to start)
+	x := &Indexer{
+		c:           c,
+		fset:        token.NewFileSet(),
+		fsOpenGate:  make(chan bool, maxOpenFiles),
+		strings:     make(map[string]string),
+		packages:    make(map[Pak]*Pak, 256),
+		words:       make(map[string]*IndexResult, 8192),
+		throttle:    util.NewThrottle(c.throttle(), 100*time.Millisecond), // run at least 0.1s at a time
+		importCount: make(map[string]int),
+		packagePath: make(map[string]map[string]bool),
+		exports:     make(map[string]map[string]SpotKind),
+		idents:      make(map[SpotKind]map[string][]Ident, 4),
+	}
+
+	// index all files in the directories given by dirnames
+	var wg sync.WaitGroup // outstanding ReadDir + visitFile
+	dirGate := make(chan bool, maxOpenDirs)
+	for dirname := range c.fsDirnames() {
+		if c.IndexDirectory != nil && !c.IndexDirectory(dirname) {
+			continue
+		}
+		dirGate <- true
+		wg.Add(1)
+		go func(dirname string) {
+			defer func() { <-dirGate }()
+			defer wg.Done()
+
+			list, err := c.fs.ReadDir(dirname)
+			if err != nil {
+				log.Printf("ReadDir(%q): %v; skipping directory", dirname, err)
+				return // ignore this directory
+			}
+			for _, fi := range list {
+				wg.Add(1)
+				go func(fi os.FileInfo) {
+					defer wg.Done()
+					x.visitFile(dirname, fi)
+				}(fi)
+			}
+		}(dirname)
+	}
+	wg.Wait()
+
+	if !c.IndexFullText {
+		// the file set, the current file, and the sources are
+		// not needed after indexing if no text index is built -
+		// help GC and clear them
+		x.fset = nil
+		x.sources.Reset()
+		x.current = nil // contains reference to fset!
+	}
+
+	// for each word, reduce the RunLists into a LookupResult;
+	// also collect the word with its canonical spelling in a
+	// word list for later computation of alternative spellings
+	words := make(map[string]*LookupResult)
+	var wlist RunList
+	for w, h := range x.words {
+		decls := reduce(h.Decls)
+		others := reduce(h.Others)
+		words[w] = &LookupResult{
+			Decls:  decls,
+			Others: others,
+		}
+		wlist = append(wlist, &wordPair{canonical(w), w})
+		x.throttle.Throttle()
+	}
+	x.stats.Words = len(words)
+
+	// reduce the word list {canonical(w), w} into
+	// a list of AltWords runs {canonical(w), {w}}
+	alist := wlist.reduce(lessWordPair, newAltWords)
+
+	// convert alist into a map of alternative spellings
+	alts := make(map[string]*AltWords)
+	for i := 0; i < len(alist); i++ {
+		a := alist[i].(*AltWords)
+		alts[a.Canon] = a
+	}
+
+	// create text index
+	var suffixes *suffixarray.Index
+	if c.IndexFullText {
+		suffixes = suffixarray.New(x.sources.Bytes())
+	}
+
+	// sort idents by the number of imports of their respective packages
+	for _, idMap := range x.idents {
+		for _, ir := range idMap {
+			sort.Sort(byImportCount{ir, x.importCount})
+		}
+	}
+
+	return &Index{
+		fset:        x.fset,
+		suffixes:    suffixes,
+		words:       words,
+		alts:        alts,
+		snippets:    x.snippets,
+		stats:       x.stats,
+		importCount: x.importCount,
+		packagePath: x.packagePath,
+		exports:     x.exports,
+		idents:      x.idents,
+		opts: indexOptions{
+			Docs:       x.c.IndexDocs,
+			GoCode:     x.c.IndexGoCode,
+			FullText:   x.c.IndexFullText,
+			MaxResults: x.c.MaxResults,
+		},
+	}
+}
+
+var ErrFileIndexVersion = errors.New("file index version out of date")
+
+const fileIndexVersion = 3
+
+// fileIndex is the subset of Index that's gob-encoded for use by
+// Index.Write and Index.Read.
+type fileIndex struct {
+	Version     int
+	Words       map[string]*LookupResult
+	Alts        map[string]*AltWords
+	Snippets    []*Snippet
+	Fulltext    bool
+	Stats       Statistics
+	ImportCount map[string]int
+	PackagePath map[string]map[string]bool
+	Exports     map[string]map[string]SpotKind
+	Idents      map[SpotKind]map[string][]Ident
+	Opts        indexOptions
+}
+
+func (x *fileIndex) Write(w io.Writer) error {
+	return gob.NewEncoder(w).Encode(x)
+}
+
+func (x *fileIndex) Read(r io.Reader) error {
+	return gob.NewDecoder(r).Decode(x)
+}
+
+// WriteTo writes the index x to w.
+func (x *Index) WriteTo(w io.Writer) (n int64, err error) {
+	w = countingWriter{&n, w}
+	fulltext := false
+	if x.suffixes != nil {
+		fulltext = true
+	}
+	fx := fileIndex{
+		Version:     fileIndexVersion,
+		Words:       x.words,
+		Alts:        x.alts,
+		Snippets:    x.snippets,
+		Fulltext:    fulltext,
+		Stats:       x.stats,
+		ImportCount: x.importCount,
+		PackagePath: x.packagePath,
+		Exports:     x.exports,
+		Idents:      x.idents,
+		Opts:        x.opts,
+	}
+	if err := fx.Write(w); err != nil {
+		return 0, err
+	}
+	if fulltext {
+		encode := func(x interface{}) error {
+			return gob.NewEncoder(w).Encode(x)
+		}
+		if err := x.fset.Write(encode); err != nil {
+			return 0, err
+		}
+		if err := x.suffixes.Write(w); err != nil {
+			return 0, err
+		}
+	}
+	return n, nil
+}
+
+// ReadFrom reads the index from r into x; x must not be nil.
+// If r does not also implement io.ByteReader, it will be wrapped in a bufio.Reader.
+// If the index is from an old version, the error is ErrFileIndexVersion.
+func (x *Index) ReadFrom(r io.Reader) (n int64, err error) {
+	// We use the ability to read bytes as a plausible surrogate for buffering.
+	if _, ok := r.(io.ByteReader); !ok {
+		r = bufio.NewReader(r)
+	}
+	r = countingReader{&n, r.(byteReader)}
+	var fx fileIndex
+	if err := fx.Read(r); err != nil {
+		return n, err
+	}
+	if fx.Version != fileIndexVersion {
+		return 0, ErrFileIndexVersion
+	}
+	x.words = fx.Words
+	x.alts = fx.Alts
+	x.snippets = fx.Snippets
+	x.stats = fx.Stats
+	x.importCount = fx.ImportCount
+	x.packagePath = fx.PackagePath
+	x.exports = fx.Exports
+	x.idents = fx.Idents
+	x.opts = fx.Opts
+	if fx.Fulltext {
+		x.fset = token.NewFileSet()
+		decode := func(x interface{}) error {
+			return gob.NewDecoder(r).Decode(x)
+		}
+		if err := x.fset.Read(decode); err != nil {
+			return n, err
+		}
+		x.suffixes = new(suffixarray.Index)
+		if err := x.suffixes.Read(r); err != nil {
+			return n, err
+		}
+	}
+	return n, nil
+}
+
+// Stats returns index statistics.
+func (x *Index) Stats() Statistics {
+	return x.stats
+}
+
+// ImportCount returns a map from import paths to how many times they were seen.
+func (x *Index) ImportCount() map[string]int {
+	return x.importCount
+}
+
+// PackagePath returns a map from short package name to a set
+// of full package path names that use that short package name.
+func (x *Index) PackagePath() map[string]map[string]bool {
+	return x.packagePath
+}
+
+// Exports returns a map from full package path to exported
+// symbol name to its type.
+func (x *Index) Exports() map[string]map[string]SpotKind {
+	return x.exports
+}
+
+// Idents returns a map from identifier type to exported
+// symbol name to the list of identifiers matching that name.
+func (x *Index) Idents() map[SpotKind]map[string][]Ident {
+	return x.idents
+}
+
+func (x *Index) lookupWord(w string) (match *LookupResult, alt *AltWords) {
+	match = x.words[w]
+	alt = x.alts[canonical(w)]
+	// remove current spelling from alternatives
+	// (if there is no match, the alternatives do
+	// not contain the current spelling)
+	if match != nil && alt != nil {
+		alt = alt.filter(w)
+	}
+	return
+}
+
+// isIdentifier reports whether s is a Go identifier.
+func isIdentifier(s string) bool {
+	for i, ch := range s {
+		if unicode.IsLetter(ch) || ch == '_' || i > 0 && unicode.IsDigit(ch) {
+			continue
+		}
+		return false
+	}
+	return len(s) > 0
+}
+
+// For a given query, which is either a single identifier or a qualified
+// identifier, Lookup returns a SearchResult containing packages, a LookupResult, a
+// list of alternative spellings, and identifiers, if any. Any and all results
+// may be nil.  If the query syntax is wrong, an error is reported.
+func (x *Index) Lookup(query string) (*SearchResult, error) {
+	ss := strings.Split(query, ".")
+
+	// check query syntax
+	for _, s := range ss {
+		if !isIdentifier(s) {
+			return nil, errors.New("all query parts must be identifiers")
+		}
+	}
+	rslt := &SearchResult{
+		Query:  query,
+		Idents: make(map[SpotKind][]Ident, 5),
+	}
+	// handle simple and qualified identifiers
+	switch len(ss) {
+	case 1:
+		ident := ss[0]
+		rslt.Hit, rslt.Alt = x.lookupWord(ident)
+		if rslt.Hit != nil {
+			// found a match - filter packages with same name
+			// for the list of packages called ident, if any
+			rslt.Pak = rslt.Hit.Others.filter(ident)
+		}
+		for k, v := range x.idents {
+			const rsltLimit = 50
+			ids := byImportCount{v[ident], x.importCount}
+			rslt.Idents[k] = ids.top(rsltLimit)
+		}
+
+	case 2:
+		pakname, ident := ss[0], ss[1]
+		rslt.Hit, rslt.Alt = x.lookupWord(ident)
+		if rslt.Hit != nil {
+			// found a match - filter by package name
+			// (no paks - package names are not qualified)
+			decls := rslt.Hit.Decls.filter(pakname)
+			others := rslt.Hit.Others.filter(pakname)
+			rslt.Hit = &LookupResult{decls, others}
+		}
+		for k, v := range x.idents {
+			ids := byImportCount{v[ident], x.importCount}
+			rslt.Idents[k] = ids.filter(pakname)
+		}
+
+	default:
+		return nil, errors.New("query is not a (qualified) identifier")
+	}
+
+	return rslt, nil
+}
+
+func (x *Index) Snippet(i int) *Snippet {
+	// handle illegal snippet indices gracefully
+	if 0 <= i && i < len(x.snippets) {
+		return x.snippets[i]
+	}
+	return nil
+}
+
+type positionList []struct {
+	filename string
+	line     int
+}
+
+func (list positionList) Len() int           { return len(list) }
+func (list positionList) Less(i, j int) bool { return list[i].filename < list[j].filename }
+func (list positionList) Swap(i, j int)      { list[i], list[j] = list[j], list[i] }
+
+// unique returns the list sorted and with duplicate entries removed
+func unique(list []int) []int {
+	sort.Ints(list)
+	var last int
+	i := 0
+	for _, x := range list {
+		if i == 0 || x != last {
+			last = x
+			list[i] = x
+			i++
+		}
+	}
+	return list[0:i]
+}
+
+// A FileLines value specifies a file and line numbers within that file.
+type FileLines struct {
+	Filename string
+	Lines    []int
+}
+
+// LookupRegexp returns the number of matches and the matches where a regular
+// expression r is found in the full text index. At most n matches are
+// returned (thus found <= n).
+//
+func (x *Index) LookupRegexp(r *regexp.Regexp, n int) (found int, result []FileLines) {
+	if x.suffixes == nil || n <= 0 {
+		return
+	}
+	// n > 0
+
+	var list positionList
+	// FindAllIndex may returns matches that span across file boundaries.
+	// Such matches are unlikely, buf after eliminating them we may end up
+	// with fewer than n matches. If we don't have enough at the end, redo
+	// the search with an increased value n1, but only if FindAllIndex
+	// returned all the requested matches in the first place (if it
+	// returned fewer than that there cannot be more).
+	for n1 := n; found < n; n1 += n - found {
+		found = 0
+		matches := x.suffixes.FindAllIndex(r, n1)
+		// compute files, exclude matches that span file boundaries,
+		// and map offsets to file-local offsets
+		list = make(positionList, len(matches))
+		for _, m := range matches {
+			// by construction, an offset corresponds to the Pos value
+			// for the file set - use it to get the file and line
+			p := token.Pos(m[0])
+			if file := x.fset.File(p); file != nil {
+				if base := file.Base(); base <= m[1] && m[1] <= base+file.Size() {
+					// match [m[0], m[1]) is within the file boundaries
+					list[found].filename = file.Name()
+					list[found].line = file.Line(p)
+					found++
+				}
+			}
+		}
+		if found == n || len(matches) < n1 {
+			// found all matches or there's no chance to find more
+			break
+		}
+	}
+	list = list[0:found]
+	sort.Sort(list) // sort by filename
+
+	// collect matches belonging to the same file
+	var last string
+	var lines []int
+	addLines := func() {
+		if len(lines) > 0 {
+			// remove duplicate lines
+			result = append(result, FileLines{last, unique(lines)})
+			lines = nil
+		}
+	}
+	for _, m := range list {
+		if m.filename != last {
+			addLines()
+			last = m.filename
+		}
+		lines = append(lines, m.line)
+	}
+	addLines()
+
+	return
+}
+
+// InvalidateIndex should be called whenever any of the file systems
+// under godoc's observation change so that the indexer is kicked on.
+func (c *Corpus) invalidateIndex() {
+	c.fsModified.Set(nil)
+	c.refreshMetadata()
+}
+
+// indexUpToDate() returns true if the search index is not older
+// than any of the file systems under godoc's observation.
+//
+func (c *Corpus) indexUpToDate() bool {
+	_, fsTime := c.fsModified.Get()
+	_, siTime := c.searchIndex.Get()
+	return !fsTime.After(siTime)
+}
+
+// feedDirnames feeds the directory names of all directories
+// under the file system given by root to channel c.
+//
+func (c *Corpus) feedDirnames(ch chan<- string) {
+	if dir, _ := c.fsTree.Get(); dir != nil {
+		for d := range dir.(*Directory).iter(false) {
+			ch <- d.Path
+		}
+	}
+}
+
+// fsDirnames() returns a channel sending all directory names
+// of all the file systems under godoc's observation.
+//
+func (c *Corpus) fsDirnames() <-chan string {
+	ch := make(chan string, 256) // buffered for fewer context switches
+	go func() {
+		c.feedDirnames(ch)
+		close(ch)
+	}()
+	return ch
+}
+
+// CompatibleWith reports whether the Index x is compatible with the corpus
+// indexing options set in c.
+func (x *Index) CompatibleWith(c *Corpus) bool {
+	return x.opts.Docs == c.IndexDocs &&
+		x.opts.GoCode == c.IndexGoCode &&
+		x.opts.FullText == c.IndexFullText &&
+		x.opts.MaxResults == c.MaxResults
+}
+
+func (c *Corpus) readIndex(filenames string) error {
+	matches, err := filepath.Glob(filenames)
+	if err != nil {
+		return err
+	} else if matches == nil {
+		return fmt.Errorf("no index files match %q", filenames)
+	}
+	sort.Strings(matches) // make sure files are in the right order
+	files := make([]io.Reader, 0, len(matches))
+	for _, filename := range matches {
+		f, err := os.Open(filename)
+		if err != nil {
+			return err
+		}
+		defer f.Close()
+		files = append(files, f)
+	}
+	return c.ReadIndexFrom(io.MultiReader(files...))
+}
+
+// ReadIndexFrom sets the current index from the serialized version found in r.
+func (c *Corpus) ReadIndexFrom(r io.Reader) error {
+	x := new(Index)
+	if _, err := x.ReadFrom(r); err != nil {
+		return err
+	}
+	if !x.CompatibleWith(c) {
+		return fmt.Errorf("index file options are incompatible: %v", x.opts)
+	}
+	c.searchIndex.Set(x)
+	return nil
+}
+
+func (c *Corpus) UpdateIndex() {
+	if c.Verbose {
+		log.Printf("updating index...")
+	}
+	start := time.Now()
+	index := c.NewIndex()
+	stop := time.Now()
+	c.searchIndex.Set(index)
+	if c.Verbose {
+		secs := stop.Sub(start).Seconds()
+		stats := index.Stats()
+		log.Printf("index updated (%gs, %d bytes of source, %d files, %d lines, %d unique words, %d spots)",
+			secs, stats.Bytes, stats.Files, stats.Lines, stats.Words, stats.Spots)
+	}
+	memstats := new(runtime.MemStats)
+	runtime.ReadMemStats(memstats)
+	if c.Verbose {
+		log.Printf("before GC: bytes = %d footprint = %d", memstats.HeapAlloc, memstats.Sys)
+	}
+	runtime.GC()
+	runtime.ReadMemStats(memstats)
+	if c.Verbose {
+		log.Printf("after  GC: bytes = %d footprint = %d", memstats.HeapAlloc, memstats.Sys)
+	}
+}
+
+// RunIndexer runs forever, indexing.
+func (c *Corpus) RunIndexer() {
+	// initialize the index from disk if possible
+	if c.IndexFiles != "" {
+		c.initFSTree()
+		if err := c.readIndex(c.IndexFiles); err != nil {
+			log.Printf("error reading index from file %s: %v", c.IndexFiles, err)
+		}
+		return
+	}
+
+	// Repeatedly update the package directory tree and index.
+	// TODO(bgarcia): Use fsnotify to only update when notified of a filesystem change.
+	for {
+		c.initFSTree()
+		c.UpdateIndex()
+		if c.IndexInterval < 0 {
+			return
+		}
+		delay := 5 * time.Minute // by default, reindex every 5 minutes
+		if c.IndexInterval > 0 {
+			delay = c.IndexInterval
+		}
+		time.Sleep(delay)
+	}
+}
+
+type countingWriter struct {
+	n *int64
+	w io.Writer
+}
+
+func (c countingWriter) Write(p []byte) (n int, err error) {
+	n, err = c.w.Write(p)
+	*c.n += int64(n)
+	return
+}
+
+type byteReader interface {
+	io.Reader
+	io.ByteReader
+}
+
+type countingReader struct {
+	n *int64
+	r byteReader
+}
+
+func (c countingReader) Read(p []byte) (n int, err error) {
+	n, err = c.r.Read(p)
+	*c.n += int64(n)
+	return
+}
+
+func (c countingReader) ReadByte() (b byte, err error) {
+	b, err = c.r.ReadByte()
+	*c.n += 1
+	return
+}
diff --git a/godoc/index_test.go b/godoc/index_test.go
new file mode 100644
index 0000000..a16bdcb
--- /dev/null
+++ b/godoc/index_test.go
@@ -0,0 +1,323 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package godoc
+
+import (
+	"bytes"
+	"reflect"
+	"sort"
+	"strings"
+	"testing"
+
+	"golang.org/x/tools/godoc/vfs/mapfs"
+)
+
+func newCorpus(t *testing.T) *Corpus {
+	c := NewCorpus(mapfs.New(map[string]string{
+		"src/foo/foo.go": `// Package foo is an example.
+package foo
+
+import "bar"
+
+const Pi = 3.1415
+
+var Foos []Foo
+
+// Foo is stuff.
+type Foo struct{}
+
+func New() *Foo {
+   return new(Foo)
+}
+`,
+		"src/bar/bar.go": `// Package bar is another example to test races.
+package bar
+`,
+		"src/other/bar/bar.go": `// Package bar is another bar package.
+package bar
+func X() {}
+`,
+		"src/skip/skip.go": `// Package skip should be skipped.
+package skip
+func Skip() {}
+`,
+		"src/bar/readme.txt": `Whitelisted text file.
+`,
+		"src/bar/baz.zzz": `Text file not whitelisted.
+`,
+	}))
+	c.IndexEnabled = true
+	c.IndexDirectory = func(dir string) bool {
+		return !strings.Contains(dir, "skip")
+	}
+
+	if err := c.Init(); err != nil {
+		t.Fatal(err)
+	}
+	return c
+}
+
+func TestIndex(t *testing.T) {
+	for _, docs := range []bool{true, false} {
+		for _, goCode := range []bool{true, false} {
+			for _, fullText := range []bool{true, false} {
+				c := newCorpus(t)
+				c.IndexDocs = docs
+				c.IndexGoCode = goCode
+				c.IndexFullText = fullText
+				c.UpdateIndex()
+				ix, _ := c.CurrentIndex()
+				if ix == nil {
+					t.Fatal("no index")
+				}
+				t.Logf("docs, goCode, fullText = %v,%v,%v", docs, goCode, fullText)
+				testIndex(t, c, ix)
+			}
+		}
+	}
+}
+
+func TestIndexWriteRead(t *testing.T) {
+	type key struct {
+		docs, goCode, fullText bool
+	}
+	type val struct {
+		buf *bytes.Buffer
+		c   *Corpus
+	}
+	m := map[key]val{}
+
+	for _, docs := range []bool{true, false} {
+		for _, goCode := range []bool{true, false} {
+			for _, fullText := range []bool{true, false} {
+				k := key{docs, goCode, fullText}
+				c := newCorpus(t)
+				c.IndexDocs = docs
+				c.IndexGoCode = goCode
+				c.IndexFullText = fullText
+				c.UpdateIndex()
+				ix, _ := c.CurrentIndex()
+				if ix == nil {
+					t.Fatal("no index")
+				}
+				var buf bytes.Buffer
+				nw, err := ix.WriteTo(&buf)
+				if err != nil {
+					t.Fatalf("Index.WriteTo: %v", err)
+				}
+				m[k] = val{bytes.NewBuffer(buf.Bytes()), c}
+				ix2 := new(Index)
+				nr, err := ix2.ReadFrom(&buf)
+				if err != nil {
+					t.Fatalf("Index.ReadFrom: %v", err)
+				}
+				if nr != nw {
+					t.Errorf("Wrote %d bytes to index but read %d", nw, nr)
+				}
+				testIndex(t, c, ix)
+			}
+		}
+	}
+	// Test CompatibleWith
+	for k1, v1 := range m {
+		ix := new(Index)
+		if _, err := ix.ReadFrom(v1.buf); err != nil {
+			t.Fatalf("Index.ReadFrom: %v", err)
+		}
+		for k2, v2 := range m {
+			if got, want := ix.CompatibleWith(v2.c), k1 == k2; got != want {
+				t.Errorf("CompatibleWith = %v; want %v for %v, %v", got, want, k1, k2)
+			}
+		}
+	}
+}
+
+func testIndex(t *testing.T, c *Corpus, ix *Index) {
+	if _, ok := ix.words["Skip"]; ok {
+		t.Errorf("the word Skip was found; expected it to be skipped")
+	}
+	checkStats(t, c, ix)
+	checkImportCount(t, c, ix)
+	checkPackagePath(t, c, ix)
+	checkExports(t, c, ix)
+	checkIdents(t, c, ix)
+}
+
+// checkStats checks the Index's statistics.
+// Some statistics are only set when we're indexing Go code.
+func checkStats(t *testing.T, c *Corpus, ix *Index) {
+	want := Statistics{}
+	if c.IndexFullText {
+		want.Bytes = 314
+		want.Files = 4
+		want.Lines = 21
+	} else if c.IndexDocs || c.IndexGoCode {
+		want.Bytes = 291
+		want.Files = 3
+		want.Lines = 20
+	}
+	if c.IndexGoCode {
+		want.Words = 8
+		want.Spots = 12
+	}
+	if got := ix.Stats(); !reflect.DeepEqual(got, want) {
+		t.Errorf("Stats = %#v; want %#v", got, want)
+	}
+}
+
+// checkImportCount checks the Index's import count map.
+// It is only set when we're indexing Go code.
+func checkImportCount(t *testing.T, c *Corpus, ix *Index) {
+	want := map[string]int{}
+	if c.IndexGoCode {
+		want = map[string]int{
+			"bar": 1,
+		}
+	}
+	if got := ix.ImportCount(); !reflect.DeepEqual(got, want) {
+		t.Errorf("ImportCount = %v; want %v", got, want)
+	}
+}
+
+// checkPackagePath checks the Index's package path map.
+// It is set if at least one of the indexing options is enabled.
+func checkPackagePath(t *testing.T, c *Corpus, ix *Index) {
+	want := map[string]map[string]bool{}
+	if c.IndexDocs || c.IndexGoCode || c.IndexFullText {
+		want = map[string]map[string]bool{
+			"foo": map[string]bool{
+				"foo": true,
+			},
+			"bar": map[string]bool{
+				"bar":       true,
+				"other/bar": true,
+			},
+		}
+	}
+	if got := ix.PackagePath(); !reflect.DeepEqual(got, want) {
+		t.Errorf("PackagePath = %v; want %v", got, want)
+	}
+}
+
+// checkExports checks the Index's exports map.
+// It is only set when we're indexing Go code.
+func checkExports(t *testing.T, c *Corpus, ix *Index) {
+	want := map[string]map[string]SpotKind{}
+	if c.IndexGoCode {
+		want = map[string]map[string]SpotKind{
+			"foo": map[string]SpotKind{
+				"Pi":   ConstDecl,
+				"Foos": VarDecl,
+				"Foo":  TypeDecl,
+				"New":  FuncDecl,
+			},
+			"other/bar": map[string]SpotKind{
+				"X": FuncDecl,
+			},
+		}
+	}
+	if got := ix.Exports(); !reflect.DeepEqual(got, want) {
+		t.Errorf("Exports = %v; want %v", got, want)
+	}
+}
+
+// checkIdents checks the Index's indents map.
+// It is only set when we're indexing documentation.
+func checkIdents(t *testing.T, c *Corpus, ix *Index) {
+	want := map[SpotKind]map[string][]Ident{}
+	if c.IndexDocs {
+		want = map[SpotKind]map[string][]Ident{
+			PackageClause: map[string][]Ident{
+				"bar": []Ident{
+					{"bar", "bar", "bar", "Package bar is another example to test races."},
+					{"other/bar", "bar", "bar", "Package bar is another bar package."},
+				},
+				"foo":   []Ident{{"foo", "foo", "foo", "Package foo is an example."}},
+				"other": []Ident{{"other/bar", "bar", "bar", "Package bar is another bar package."}},
+			},
+			ConstDecl: map[string][]Ident{
+				"Pi": []Ident{{"foo", "foo", "Pi", ""}},
+			},
+			VarDecl: map[string][]Ident{
+				"Foos": []Ident{{"foo", "foo", "Foos", ""}},
+			},
+			TypeDecl: map[string][]Ident{
+				"Foo": []Ident{{"foo", "foo", "Foo", "Foo is stuff."}},
+			},
+			FuncDecl: map[string][]Ident{
+				"New": []Ident{{"foo", "foo", "New", ""}},
+				"X":   []Ident{{"other/bar", "bar", "X", ""}},
+			},
+		}
+	}
+	if got := ix.Idents(); !reflect.DeepEqual(got, want) {
+		t.Errorf("Idents = %v; want %v", got, want)
+	}
+}
+
+func TestIdentResultSort(t *testing.T) {
+	ic := map[string]int{
+		"/a/b/pkg1": 10,
+		"/a/b/pkg2": 2,
+		"/b/d/pkg3": 20,
+	}
+	for _, tc := range []struct {
+		ir  []Ident
+		exp []Ident
+	}{
+		{
+			ir: []Ident{
+				{"/a/b/pkg2", "pkg2", "MyFunc2", ""},
+				{"/b/d/pkg3", "pkg3", "MyFunc3", ""},
+				{"/a/b/pkg1", "pkg1", "MyFunc1", ""},
+			},
+			exp: []Ident{
+				{"/b/d/pkg3", "pkg3", "MyFunc3", ""},
+				{"/a/b/pkg1", "pkg1", "MyFunc1", ""},
+				{"/a/b/pkg2", "pkg2", "MyFunc2", ""},
+			},
+		},
+		{
+			ir: []Ident{
+				{"/a/a/pkg1", "pkg1", "MyFunc1", ""},
+				{"/a/b/pkg1", "pkg1", "MyFunc1", ""},
+			},
+			exp: []Ident{
+				{"/a/b/pkg1", "pkg1", "MyFunc1", ""},
+				{"/a/a/pkg1", "pkg1", "MyFunc1", ""},
+			},
+		},
+	} {
+		if sort.Sort(byImportCount{tc.ir, ic}); !reflect.DeepEqual(tc.ir, tc.exp) {
+			t.Errorf("got: %v, want %v", tc.ir, tc.exp)
+		}
+	}
+}
+
+func TestIdentFilter(t *testing.T) {
+	ic := map[string]int{}
+	for _, tc := range []struct {
+		ir  []Ident
+		pak string
+		exp []Ident
+	}{
+		{
+			ir: []Ident{
+				{"/a/b/pkg2", "pkg2", "MyFunc2", ""},
+				{"/b/d/pkg3", "pkg3", "MyFunc3", ""},
+				{"/a/b/pkg1", "pkg1", "MyFunc1", ""},
+			},
+			pak: "pkg2",
+			exp: []Ident{
+				{"/a/b/pkg2", "pkg2", "MyFunc2", ""},
+			},
+		},
+	} {
+		res := byImportCount{tc.ir, ic}.filter(tc.pak)
+		if !reflect.DeepEqual(res, tc.exp) {
+			t.Errorf("got: %v, want %v", res, tc.exp)
+		}
+	}
+}
diff --git a/godoc/linkify.go b/godoc/linkify.go
new file mode 100644
index 0000000..0a8fb47
--- /dev/null
+++ b/godoc/linkify.go
@@ -0,0 +1,234 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file implements LinkifyText which introduces
+// links for identifiers pointing to their declarations.
+// The approach does not cover all cases because godoc
+// doesn't have complete type information, but it's
+// reasonably good for browsing.
+
+package godoc
+
+import (
+	"fmt"
+	"go/ast"
+	"go/token"
+	"io"
+	"strconv"
+)
+
+// LinkifyText HTML-escapes source text and writes it to w.
+// Identifiers that are in a "use" position (i.e., that are
+// not being declared), are wrapped with HTML links pointing
+// to the respective declaration, if possible. Comments are
+// formatted the same way as with FormatText.
+//
+func LinkifyText(w io.Writer, text []byte, n ast.Node) {
+	links := linksFor(n)
+
+	i := 0     // links index
+	prev := "" // prev HTML tag
+	linkWriter := func(w io.Writer, _ int, start bool) {
+		// end tag
+		if !start {
+			if prev != "" {
+				fmt.Fprintf(w, `</%s>`, prev)
+				prev = ""
+			}
+			return
+		}
+
+		// start tag
+		prev = ""
+		if i < len(links) {
+			switch info := links[i]; {
+			case info.path != "" && info.name == "":
+				// package path
+				fmt.Fprintf(w, `<a href="/pkg/%s/">`, info.path)
+				prev = "a"
+			case info.path != "" && info.name != "":
+				// qualified identifier
+				fmt.Fprintf(w, `<a href="/pkg/%s/#%s">`, info.path, info.name)
+				prev = "a"
+			case info.path == "" && info.name != "":
+				// local identifier
+				if info.mode == identVal {
+					fmt.Fprintf(w, `<span id="%s">`, info.name)
+					prev = "span"
+				} else if ast.IsExported(info.name) {
+					fmt.Fprintf(w, `<a href="#%s">`, info.name)
+					prev = "a"
+				}
+			}
+			i++
+		}
+	}
+
+	idents := tokenSelection(text, token.IDENT)
+	comments := tokenSelection(text, token.COMMENT)
+	FormatSelections(w, text, linkWriter, idents, selectionTag, comments)
+}
+
+// A link describes the (HTML) link information for an identifier.
+// The zero value of a link represents "no link".
+//
+type link struct {
+	mode       identMode
+	path, name string // package path, identifier name
+}
+
+// linksFor returns the list of links for the identifiers used
+// by node in the same order as they appear in the source.
+//
+func linksFor(node ast.Node) (list []link) {
+	modes := identModesFor(node)
+
+	// NOTE: We are expecting ast.Inspect to call the
+	//       callback function in source text order.
+	ast.Inspect(node, func(node ast.Node) bool {
+		switch n := node.(type) {
+		case *ast.Ident:
+			m := modes[n]
+			info := link{mode: m}
+			switch m {
+			case identUse:
+				if n.Obj == nil && predeclared[n.Name] {
+					info.path = builtinPkgPath
+				}
+				info.name = n.Name
+			case identDef:
+				// any declaration expect const or var - empty link
+			case identVal:
+				// const or var declaration
+				info.name = n.Name
+			}
+			list = append(list, info)
+			return false
+		case *ast.SelectorExpr:
+			// Detect qualified identifiers of the form pkg.ident.
+			// If anything fails we return true and collect individual
+			// identifiers instead.
+			if x, _ := n.X.(*ast.Ident); x != nil {
+				// x must be a package for a qualified identifier
+				if obj := x.Obj; obj != nil && obj.Kind == ast.Pkg {
+					if spec, _ := obj.Decl.(*ast.ImportSpec); spec != nil {
+						// spec.Path.Value is the import path
+						if path, err := strconv.Unquote(spec.Path.Value); err == nil {
+							// Register two links, one for the package
+							// and one for the qualified identifier.
+							info := link{path: path}
+							list = append(list, info)
+							info.name = n.Sel.Name
+							list = append(list, info)
+							return false
+						}
+					}
+				}
+			}
+		}
+		return true
+	})
+
+	return
+}
+
+// The identMode describes how an identifier is "used" at its source location.
+type identMode int
+
+const (
+	identUse identMode = iota // identifier is used (must be zero value for identMode)
+	identDef                  // identifier is defined
+	identVal                  // identifier is defined in a const or var declaration
+)
+
+// identModesFor returns a map providing the identMode for each identifier used by node.
+func identModesFor(node ast.Node) map[*ast.Ident]identMode {
+	m := make(map[*ast.Ident]identMode)
+
+	ast.Inspect(node, func(node ast.Node) bool {
+		switch n := node.(type) {
+		case *ast.Field:
+			for _, n := range n.Names {
+				m[n] = identDef
+			}
+		case *ast.ImportSpec:
+			if name := n.Name; name != nil {
+				m[name] = identDef
+			}
+		case *ast.ValueSpec:
+			for _, n := range n.Names {
+				m[n] = identVal
+			}
+		case *ast.TypeSpec:
+			m[n.Name] = identDef
+		case *ast.FuncDecl:
+			m[n.Name] = identDef
+		case *ast.AssignStmt:
+			// Short variable declarations only show up if we apply
+			// this code to all source code (as opposed to exported
+			// declarations only).
+			if n.Tok == token.DEFINE {
+				// Some of the lhs variables may be re-declared,
+				// so technically they are not defs. We don't
+				// care for now.
+				for _, x := range n.Lhs {
+					// Each lhs expression should be an
+					// ident, but we are conservative and check.
+					if n, _ := x.(*ast.Ident); n != nil {
+						m[n] = identVal
+					}
+				}
+			}
+		}
+		return true
+	})
+
+	return m
+}
+
+// The predeclared map represents the set of all predeclared identifiers.
+// TODO(gri) This information is also encoded in similar maps in go/doc,
+//           but not exported. Consider exporting an accessor and using
+//           it instead.
+var predeclared = map[string]bool{
+	"bool":       true,
+	"byte":       true,
+	"complex64":  true,
+	"complex128": true,
+	"error":      true,
+	"float32":    true,
+	"float64":    true,
+	"int":        true,
+	"int8":       true,
+	"int16":      true,
+	"int32":      true,
+	"int64":      true,
+	"rune":       true,
+	"string":     true,
+	"uint":       true,
+	"uint8":      true,
+	"uint16":     true,
+	"uint32":     true,
+	"uint64":     true,
+	"uintptr":    true,
+	"true":       true,
+	"false":      true,
+	"iota":       true,
+	"nil":        true,
+	"append":     true,
+	"cap":        true,
+	"close":      true,
+	"complex":    true,
+	"copy":       true,
+	"delete":     true,
+	"imag":       true,
+	"len":        true,
+	"make":       true,
+	"new":        true,
+	"panic":      true,
+	"print":      true,
+	"println":    true,
+	"real":       true,
+	"recover":    true,
+}
diff --git a/godoc/meta.go b/godoc/meta.go
new file mode 100644
index 0000000..41ade39
--- /dev/null
+++ b/godoc/meta.go
@@ -0,0 +1,144 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package godoc
+
+import (
+	"bytes"
+	"encoding/json"
+	"log"
+	pathpkg "path"
+	"strings"
+	"time"
+
+	"golang.org/x/tools/godoc/vfs"
+)
+
+var (
+	doctype   = []byte("<!DOCTYPE ")
+	jsonStart = []byte("<!--{")
+	jsonEnd   = []byte("}-->")
+)
+
+// ----------------------------------------------------------------------------
+// Documentation Metadata
+
+// TODO(adg): why are some exported and some aren't? -brad
+type Metadata struct {
+	Title    string
+	Subtitle string
+	Template bool   // execute as template
+	Path     string // canonical path for this page
+	filePath string // filesystem path relative to goroot
+}
+
+func (m *Metadata) FilePath() string { return m.filePath }
+
+// extractMetadata extracts the Metadata from a byte slice.
+// It returns the Metadata value and the remaining data.
+// If no metadata is present the original byte slice is returned.
+//
+func extractMetadata(b []byte) (meta Metadata, tail []byte, err error) {
+	tail = b
+	if !bytes.HasPrefix(b, jsonStart) {
+		return
+	}
+	end := bytes.Index(b, jsonEnd)
+	if end < 0 {
+		return
+	}
+	b = b[len(jsonStart)-1 : end+1] // drop leading <!-- and include trailing }
+	if err = json.Unmarshal(b, &meta); err != nil {
+		return
+	}
+	tail = tail[end+len(jsonEnd):]
+	return
+}
+
+// UpdateMetadata scans $GOROOT/doc for HTML files, reads their metadata,
+// and updates the DocMetadata map.
+func (c *Corpus) updateMetadata() {
+	metadata := make(map[string]*Metadata)
+	var scan func(string) // scan is recursive
+	scan = func(dir string) {
+		fis, err := c.fs.ReadDir(dir)
+		if err != nil {
+			log.Println("updateMetadata:", err)
+			return
+		}
+		for _, fi := range fis {
+			name := pathpkg.Join(dir, fi.Name())
+			if fi.IsDir() {
+				scan(name) // recurse
+				continue
+			}
+			if !strings.HasSuffix(name, ".html") {
+				continue
+			}
+			// Extract metadata from the file.
+			b, err := vfs.ReadFile(c.fs, name)
+			if err != nil {
+				log.Printf("updateMetadata %s: %v", name, err)
+				continue
+			}
+			meta, _, err := extractMetadata(b)
+			if err != nil {
+				log.Printf("updateMetadata: %s: %v", name, err)
+				continue
+			}
+			// Store relative filesystem path in Metadata.
+			meta.filePath = name
+			if meta.Path == "" {
+				// If no Path, canonical path is actual path.
+				meta.Path = meta.filePath
+			}
+			// Store under both paths.
+			metadata[meta.Path] = &meta
+			metadata[meta.filePath] = &meta
+		}
+	}
+	scan("/doc")
+	c.docMetadata.Set(metadata)
+}
+
+// MetadataFor returns the *Metadata for a given relative path or nil if none
+// exists.
+//
+func (c *Corpus) MetadataFor(relpath string) *Metadata {
+	if m, _ := c.docMetadata.Get(); m != nil {
+		meta := m.(map[string]*Metadata)
+		// If metadata for this relpath exists, return it.
+		if p := meta[relpath]; p != nil {
+			return p
+		}
+		// Try with or without trailing slash.
+		if strings.HasSuffix(relpath, "/") {
+			relpath = relpath[:len(relpath)-1]
+		} else {
+			relpath = relpath + "/"
+		}
+		return meta[relpath]
+	}
+	return nil
+}
+
+// refreshMetadata sends a signal to update DocMetadata. If a refresh is in
+// progress the metadata will be refreshed again afterward.
+//
+func (c *Corpus) refreshMetadata() {
+	select {
+	case c.refreshMetadataSignal <- true:
+	default:
+	}
+}
+
+// RefreshMetadataLoop runs forever, updating DocMetadata when the underlying
+// file system changes. It should be launched in a goroutine.
+func (c *Corpus) refreshMetadataLoop() {
+	for {
+		<-c.refreshMetadataSignal
+		c.updateMetadata()
+		time.Sleep(10 * time.Second) // at most once every 10 seconds
+	}
+}
diff --git a/godoc/page.go b/godoc/page.go
new file mode 100644
index 0000000..b296b27
--- /dev/null
+++ b/godoc/page.go
@@ -0,0 +1,43 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package godoc
+
+import (
+	"net/http"
+	"runtime"
+)
+
+// Page describes the contents of the top-level godoc webpage.
+type Page struct {
+	Title    string
+	Tabtitle string
+	Subtitle string
+	Query    string
+	Body     []byte
+
+	// filled in by servePage
+	SearchBox  bool
+	Playground bool
+	Version    string
+}
+
+func (p *Presentation) ServePage(w http.ResponseWriter, page Page) {
+	if page.Tabtitle == "" {
+		page.Tabtitle = page.Title
+	}
+	page.SearchBox = p.Corpus.IndexEnabled
+	page.Playground = p.ShowPlayground
+	page.Version = runtime.Version()
+	applyTemplateToResponseWriter(w, p.GodocHTML, page)
+}
+
+func (p *Presentation) ServeError(w http.ResponseWriter, r *http.Request, relpath string, err error) {
+	w.WriteHeader(http.StatusNotFound)
+	p.ServePage(w, Page{
+		Title:    "File " + relpath,
+		Subtitle: relpath,
+		Body:     applyTemplate(p.ErrorHTML, "errorHTML", err), // err may contain an absolute path!
+	})
+}
diff --git a/godoc/parser.go b/godoc/parser.go
new file mode 100644
index 0000000..4e644d6
--- /dev/null
+++ b/godoc/parser.go
@@ -0,0 +1,74 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file contains support functions for parsing .go files
+// accessed via godoc's file system fs.
+
+package godoc
+
+import (
+	"bytes"
+	"go/ast"
+	"go/parser"
+	"go/token"
+	pathpkg "path"
+
+	"golang.org/x/tools/godoc/vfs"
+)
+
+var linePrefix = []byte("//line ")
+
+// This function replaces source lines starting with "//line " with a blank line.
+// It does this irrespective of whether the line is truly a line comment or not;
+// e.g., the line may be inside a string, or a /*-style comment; however that is
+// rather unlikely (proper testing would require a full Go scan which we want to
+// avoid for performance).
+func replaceLinePrefixCommentsWithBlankLine(src []byte) {
+	for {
+		i := bytes.Index(src, linePrefix)
+		if i < 0 {
+			break // we're done
+		}
+		// 0 <= i && i+len(linePrefix) <= len(src)
+		if i == 0 || src[i-1] == '\n' {
+			// at beginning of line: blank out line
+			for i < len(src) && src[i] != '\n' {
+				src[i] = ' '
+				i++
+			}
+		} else {
+			// not at beginning of line: skip over prefix
+			i += len(linePrefix)
+		}
+		// i <= len(src)
+		src = src[i:]
+	}
+}
+
+func (c *Corpus) parseFile(fset *token.FileSet, filename string, mode parser.Mode) (*ast.File, error) {
+	src, err := vfs.ReadFile(c.fs, filename)
+	if err != nil {
+		return nil, err
+	}
+
+	// Temporary ad-hoc fix for issue 5247.
+	// TODO(gri) Remove this in favor of a better fix, eventually (see issue 7702).
+	replaceLinePrefixCommentsWithBlankLine(src)
+
+	return parser.ParseFile(fset, filename, src, mode)
+}
+
+func (c *Corpus) parseFiles(fset *token.FileSet, relpath string, abspath string, localnames []string) (map[string]*ast.File, error) {
+	files := make(map[string]*ast.File)
+	for _, f := range localnames {
+		absname := pathpkg.Join(abspath, f)
+		file, err := c.parseFile(fset, absname, parser.ParseComments)
+		if err != nil {
+			return nil, err
+		}
+		files[pathpkg.Join(relpath, f)] = file
+	}
+
+	return files, nil
+}
diff --git a/godoc/pres.go b/godoc/pres.go
new file mode 100644
index 0000000..a8f8b2b
--- /dev/null
+++ b/godoc/pres.go
@@ -0,0 +1,165 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package godoc
+
+import (
+	"net/http"
+	"regexp"
+	"sync"
+	"text/template"
+
+	"golang.org/x/tools/godoc/vfs/httpfs"
+)
+
+// SearchResultFunc functions return an HTML body for displaying search results.
+type SearchResultFunc func(p *Presentation, result SearchResult) []byte
+
+// Presentation generates output from a corpus.
+type Presentation struct {
+	Corpus *Corpus
+
+	mux        *http.ServeMux
+	fileServer http.Handler
+	cmdHandler handlerServer
+	pkgHandler handlerServer
+
+	CallGraphHTML,
+	DirlistHTML,
+	ErrorHTML,
+	ExampleHTML,
+	GodocHTML,
+	ImplementsHTML,
+	MethodSetHTML,
+	PackageHTML,
+	PackageText,
+	SearchHTML,
+	SearchDocHTML,
+	SearchCodeHTML,
+	SearchTxtHTML,
+	SearchText,
+	SearchDescXML *template.Template
+
+	// TabWidth optionally specifies the tab width.
+	TabWidth int
+
+	ShowTimestamps bool
+	ShowPlayground bool
+	ShowExamples   bool
+	DeclLinks      bool
+
+	// SrcMode outputs source code instead of documentation in command-line mode.
+	SrcMode bool
+	// HTMLMode outputs HTML instead of plain text in command-line mode.
+	HTMLMode bool
+
+	// NotesRx optionally specifies a regexp to match
+	// notes to render in the output.
+	NotesRx *regexp.Regexp
+
+	// AdjustPageInfoMode optionally specifies a function to
+	// modify the PageInfoMode of a request. The default chosen
+	// value is provided.
+	AdjustPageInfoMode func(req *http.Request, mode PageInfoMode) PageInfoMode
+
+	// URLForSrc optionally specifies a function that takes a source file and
+	// returns a URL for it.
+	// The source file argument has the form /src/<path>/<filename>.
+	URLForSrc func(src string) string
+
+	// URLForSrcPos optionally specifies a function to create a URL given a
+	// source file, a line from the source file (1-based), and low & high offset
+	// positions (0-based, bytes from beginning of file). Ideally, the returned
+	// URL will be for the specified line of the file, while the high & low
+	// positions will be used to highlight a section of the file.
+	// The source file argument has the form /src/<path>/<filename>.
+	URLForSrcPos func(src string, line, low, high int) string
+
+	// URLForSrcQuery optionally specifies a function to create a URL given a
+	// source file, a query string, and a line from the source file (1-based).
+	// The source file argument has the form /src/<path>/<filename>.
+	// The query argument will be escaped for the purposes of embedding in a URL
+	// query parameter.
+	// Ideally, the returned URL will be for the specified line of the file with
+	// the query string highlighted.
+	URLForSrcQuery func(src, query string, line int) string
+
+	// SearchResults optionally specifies a list of functions returning an HTML
+	// body for displaying search results.
+	SearchResults []SearchResultFunc
+
+	initFuncMapOnce sync.Once
+	funcMap         template.FuncMap
+	templateFuncs   template.FuncMap
+}
+
+// NewPresentation returns a new Presentation from a corpus.
+// It sets SearchResults to:
+// [SearchResultDoc SearchResultCode SearchResultTxt].
+func NewPresentation(c *Corpus) *Presentation {
+	if c == nil {
+		panic("nil Corpus")
+	}
+	p := &Presentation{
+		Corpus:     c,
+		mux:        http.NewServeMux(),
+		fileServer: http.FileServer(httpfs.New(c.fs)),
+
+		TabWidth:     4,
+		ShowExamples: true,
+		DeclLinks:    true,
+		SearchResults: []SearchResultFunc{
+			(*Presentation).SearchResultDoc,
+			(*Presentation).SearchResultCode,
+			(*Presentation).SearchResultTxt,
+		},
+	}
+	p.cmdHandler = handlerServer{
+		p:       p,
+		c:       c,
+		pattern: "/cmd/",
+		fsRoot:  "/src/cmd",
+	}
+	p.pkgHandler = handlerServer{
+		p:       p,
+		c:       c,
+		pattern: "/pkg/",
+		fsRoot:  "/src",
+		exclude: []string{"/src/cmd"},
+	}
+	p.cmdHandler.registerWithMux(p.mux)
+	p.pkgHandler.registerWithMux(p.mux)
+	p.mux.HandleFunc("/", p.ServeFile)
+	p.mux.HandleFunc("/search", p.HandleSearch)
+	p.mux.HandleFunc("/opensearch.xml", p.serveSearchDesc)
+	return p
+}
+
+func (p *Presentation) FileServer() http.Handler {
+	return p.fileServer
+}
+
+func (p *Presentation) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+	p.mux.ServeHTTP(w, r)
+}
+
+func (p *Presentation) PkgFSRoot() string {
+	return p.pkgHandler.fsRoot
+}
+
+func (p *Presentation) CmdFSRoot() string {
+	return p.cmdHandler.fsRoot
+}
+
+// TODO(bradfitz): move this to be a method on Corpus. Just moving code around for now,
+// but this doesn't feel right.
+func (p *Presentation) GetPkgPageInfo(abspath, relpath string, mode PageInfoMode) *PageInfo {
+	return p.pkgHandler.GetPageInfo(abspath, relpath, mode)
+}
+
+// TODO(bradfitz): move this to be a method on Corpus. Just moving code around for now,
+// but this doesn't feel right.
+func (p *Presentation) GetCmdPageInfo(abspath, relpath string, mode PageInfoMode) *PageInfo {
+	return p.cmdHandler.GetPageInfo(abspath, relpath, mode)
+}
diff --git a/godoc/redirect/hash.go b/godoc/redirect/hash.go
new file mode 100644
index 0000000..d5a1e3e
--- /dev/null
+++ b/godoc/redirect/hash.go
@@ -0,0 +1,138 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file provides a compact encoding of
+// a map of Mercurial hashes to Git hashes.
+
+package redirect
+
+import (
+	"encoding/binary"
+	"fmt"
+	"io"
+	"os"
+	"sort"
+	"strconv"
+	"strings"
+)
+
+// hashMap is a map of Mercurial hashes to Git hashes.
+type hashMap struct {
+	file    *os.File
+	entries int
+}
+
+// newHashMap takes a file handle that contains a map of Mercurial to Git
+// hashes. The file should be a sequence of pairs of little-endian encoded
+// uint32s, representing a hgHash and a gitHash respectively.
+// The sequence must be sorted by hgHash.
+// The file must remain open for as long as the returned hashMap is used.
+func newHashMap(f *os.File) (*hashMap, error) {
+	fi, err := f.Stat()
+	if err != nil {
+		return nil, err
+	}
+	return &hashMap{file: f, entries: int(fi.Size() / 8)}, nil
+}
+
+// Lookup finds an hgHash in the map that matches the given prefix, and returns
+// its corresponding gitHash. The prefix must be at least 8 characters long.
+func (m *hashMap) Lookup(s string) gitHash {
+	if m == nil {
+		return 0
+	}
+	hg, err := hgHashFromString(s)
+	if err != nil {
+		return 0
+	}
+	var git gitHash
+	b := make([]byte, 8)
+	sort.Search(m.entries, func(i int) bool {
+		n, err := m.file.ReadAt(b, int64(i*8))
+		if err != nil {
+			panic(err)
+		}
+		if n != 8 {
+			panic(io.ErrUnexpectedEOF)
+		}
+		v := hgHash(binary.LittleEndian.Uint32(b[:4]))
+		if v == hg {
+			git = gitHash(binary.LittleEndian.Uint32(b[4:]))
+		}
+		return v >= hg
+	})
+	return git
+}
+
+// hgHash represents the lower (leftmost) 32 bits of a Mercurial hash.
+type hgHash uint32
+
+func (h hgHash) String() string {
+	return intToHash(int64(h))
+}
+
+func hgHashFromString(s string) (hgHash, error) {
+	if len(s) < 8 {
+		return 0, fmt.Errorf("string too small: len(s) = %d", len(s))
+	}
+	hash := s[:8]
+	i, err := strconv.ParseInt(hash, 16, 64)
+	if err != nil {
+		return 0, err
+	}
+	return hgHash(i), nil
+}
+
+// gitHash represents the leftmost 28 bits of a Git hash in its upper 28 bits,
+// and it encodes hash's repository in the lower 4  bits.
+type gitHash uint32
+
+func (h gitHash) Hash() string {
+	return intToHash(int64(h))[:7]
+}
+
+func (h gitHash) Repo() string {
+	return repo(h & 0xF).String()
+}
+
+func intToHash(i int64) string {
+	s := strconv.FormatInt(i, 16)
+	if len(s) < 8 {
+		s = strings.Repeat("0", 8-len(s)) + s
+	}
+	return s
+}
+
+// repo represents a Go Git repository.
+type repo byte
+
+const (
+	repoGo repo = iota
+	repoBlog
+	repoCrypto
+	repoExp
+	repoImage
+	repoMobile
+	repoNet
+	repoSys
+	repoTalks
+	repoText
+	repoTools
+)
+
+func (r repo) String() string {
+	return map[repo]string{
+		repoGo:     "go",
+		repoBlog:   "blog",
+		repoCrypto: "crypto",
+		repoExp:    "exp",
+		repoImage:  "image",
+		repoMobile: "mobile",
+		repoNet:    "net",
+		repoSys:    "sys",
+		repoTalks:  "talks",
+		repoText:   "text",
+		repoTools:  "tools",
+	}[r]
+}
diff --git a/godoc/redirect/redirect.go b/godoc/redirect/redirect.go
new file mode 100644
index 0000000..77d927d
--- /dev/null
+++ b/godoc/redirect/redirect.go
@@ -0,0 +1,232 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package redirect provides hooks to register HTTP handlers that redirect old
+// godoc paths to their new equivalents and assist in accessing the issue
+// tracker, wiki, code review system, etc.
+package redirect // import "golang.org/x/tools/godoc/redirect"
+
+import (
+	"fmt"
+	"net/http"
+	"os"
+	"regexp"
+	"strconv"
+	"strings"
+)
+
+// Register registers HTTP handlers that redirect old godoc paths to their new
+// equivalents and assist in accessing the issue tracker, wiki, code review
+// system, etc. If mux is nil it uses http.DefaultServeMux.
+func Register(mux *http.ServeMux) {
+	if mux == nil {
+		mux = http.DefaultServeMux
+	}
+	handlePathRedirects(mux, pkgRedirects, "/pkg/")
+	handlePathRedirects(mux, cmdRedirects, "/cmd/")
+	for prefix, redirect := range prefixHelpers {
+		p := "/" + prefix + "/"
+		mux.Handle(p, PrefixHandler(p, redirect))
+	}
+	for path, redirect := range redirects {
+		mux.Handle(path, Handler(redirect))
+	}
+	// NB: /src/pkg (sans trailing slash) is the index of packages.
+	mux.HandleFunc("/src/pkg/", srcPkgHandler)
+	mux.HandleFunc("/cl/", clHandler)
+	mux.HandleFunc("/change/", changeHandler)
+}
+
+func handlePathRedirects(mux *http.ServeMux, redirects map[string]string, prefix string) {
+	for source, target := range redirects {
+		h := Handler(prefix + target + "/")
+		p := prefix + source
+		mux.Handle(p, h)
+		mux.Handle(p+"/", h)
+	}
+}
+
+// Packages that were renamed between r60 and go1.
+var pkgRedirects = map[string]string{
+	"asn1":              "encoding/asn1",
+	"big":               "math/big",
+	"cmath":             "math/cmplx",
+	"csv":               "encoding/csv",
+	"exec":              "os/exec",
+	"exp/template/html": "html/template",
+	"gob":               "encoding/gob",
+	"http":              "net/http",
+	"http/cgi":          "net/http/cgi",
+	"http/fcgi":         "net/http/fcgi",
+	"http/httptest":     "net/http/httptest",
+	"http/pprof":        "net/http/pprof",
+	"json":              "encoding/json",
+	"mail":              "net/mail",
+	"rand":              "math/rand",
+	"rpc":               "net/rpc",
+	"rpc/jsonrpc":       "net/rpc/jsonrpc",
+	"scanner":           "text/scanner",
+	"smtp":              "net/smtp",
+	"tabwriter":         "text/tabwriter",
+	"template":          "text/template",
+	"template/parse":    "text/template/parse",
+	"url":               "net/url",
+	"utf16":             "unicode/utf16",
+	"utf8":              "unicode/utf8",
+	"xml":               "encoding/xml",
+}
+
+// Commands that were renamed between r60 and go1.
+var cmdRedirects = map[string]string{
+	"gofix":     "fix",
+	"goinstall": "go",
+	"gopack":    "pack",
+	"gotest":    "go",
+	"govet":     "vet",
+	"goyacc":    "yacc",
+}
+
+var redirects = map[string]string{
+	"/blog":       "/blog/",
+	"/build":      "http://build.golang.org",
+	"/change":     "https://go.googlesource.com/go",
+	"/cl":         "https://go-review.googlesource.com",
+	"/cmd/godoc/": "http://godoc.org/golang.org/x/tools/cmd/godoc/",
+	"/issue":      "https://github.com/golang/go/issues",
+	"/issue/new":  "https://github.com/golang/go/issues/new",
+	"/issues":     "https://github.com/golang/go/issues",
+	"/issues/new": "https://github.com/golang/go/issues/new",
+	"/play":       "http://play.golang.org",
+
+	// In Go 1.2 the references page is part of /doc/.
+	"/ref": "/doc/#references",
+	// This next rule clobbers /ref/spec and /ref/mem.
+	// TODO(adg): figure out what to do here, if anything.
+	// "/ref/": "/doc/#references",
+
+	// Be nice to people who are looking in the wrong place.
+	"/doc/mem":  "/ref/mem",
+	"/doc/spec": "/ref/spec",
+
+	"/talks": "http://talks.golang.org",
+	"/tour":  "http://tour.golang.org",
+	"/wiki":  "https://github.com/golang/go/wiki",
+
+	"/doc/articles/c_go_cgo.html":                    "/blog/c-go-cgo",
+	"/doc/articles/concurrency_patterns.html":        "/blog/go-concurrency-patterns-timing-out-and",
+	"/doc/articles/defer_panic_recover.html":         "/blog/defer-panic-and-recover",
+	"/doc/articles/error_handling.html":              "/blog/error-handling-and-go",
+	"/doc/articles/gobs_of_data.html":                "/blog/gobs-of-data",
+	"/doc/articles/godoc_documenting_go_code.html":   "/blog/godoc-documenting-go-code",
+	"/doc/articles/gos_declaration_syntax.html":      "/blog/gos-declaration-syntax",
+	"/doc/articles/image_draw.html":                  "/blog/go-imagedraw-package",
+	"/doc/articles/image_package.html":               "/blog/go-image-package",
+	"/doc/articles/json_and_go.html":                 "/blog/json-and-go",
+	"/doc/articles/json_rpc_tale_of_interfaces.html": "/blog/json-rpc-tale-of-interfaces",
+	"/doc/articles/laws_of_reflection.html":          "/blog/laws-of-reflection",
+	"/doc/articles/slices_usage_and_internals.html":  "/blog/go-slices-usage-and-internals",
+	"/doc/go_for_cpp_programmers.html":               "/wiki/GoForCPPProgrammers",
+	"/doc/go_tutorial.html":                          "http://tour.golang.org/",
+}
+
+var prefixHelpers = map[string]string{
+	"issue":  "https://github.com/golang/go/issues/",
+	"issues": "https://github.com/golang/go/issues/",
+	"play":   "http://play.golang.org/",
+	"talks":  "http://talks.golang.org/",
+	"wiki":   "https://github.com/golang/go/wiki/",
+}
+
+func Handler(target string) http.Handler {
+	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+		http.Redirect(w, r, target, http.StatusMovedPermanently)
+	})
+}
+
+var validId = regexp.MustCompile(`^[A-Za-z0-9-]*$`)
+
+func PrefixHandler(prefix, baseURL string) http.Handler {
+	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+		if p := r.URL.Path; p == prefix {
+			// redirect /prefix/ to /prefix
+			http.Redirect(w, r, p[:len(p)-1], http.StatusFound)
+			return
+		}
+		id := r.URL.Path[len(prefix):]
+		if !validId.MatchString(id) {
+			http.Error(w, "Not found", http.StatusNotFound)
+			return
+		}
+		target := baseURL + id
+		http.Redirect(w, r, target, http.StatusFound)
+	})
+}
+
+// Redirect requests from the old "/src/pkg/foo" to the new "/src/foo".
+// See http://golang.org/s/go14nopkg
+func srcPkgHandler(w http.ResponseWriter, r *http.Request) {
+	r.URL.Path = "/src/" + r.URL.Path[len("/src/pkg/"):]
+	http.Redirect(w, r, r.URL.String(), http.StatusMovedPermanently)
+}
+
+func clHandler(w http.ResponseWriter, r *http.Request) {
+	const prefix = "/cl/"
+	if p := r.URL.Path; p == prefix {
+		// redirect /prefix/ to /prefix
+		http.Redirect(w, r, p[:len(p)-1], http.StatusFound)
+		return
+	}
+	id := r.URL.Path[len(prefix):]
+	// support /cl/152700045/, which is used in commit 0edafefc36.
+	id = strings.TrimSuffix(id, "/")
+	if !validId.MatchString(id) {
+		http.Error(w, "Not found", http.StatusNotFound)
+		return
+	}
+	target := ""
+	// the first CL in rietveld is about 152046, so only treat the id as
+	// a rietveld CL if it is larger than 150000.
+	if n, err := strconv.Atoi(id); err == nil && n > 150000 {
+		target = "https://codereview.appspot.com/" + id
+	} else {
+		target = "https://go-review.googlesource.com/r/" + id
+	}
+	http.Redirect(w, r, target, http.StatusFound)
+}
+
+var changeMap *hashMap
+
+// LoadChangeMap loads the specified map of Mercurial to Git revisions,
+// which is used by the /change/ handler to intelligently map old hg
+// revisions to their new git equivalents.
+// It should be called before calling Register.
+// The file should remain open as long as the process is running.
+// See the implementation of this package for details.
+func LoadChangeMap(filename string) error {
+	f, err := os.Open(filename)
+	if err != nil {
+		return err
+	}
+	m, err := newHashMap(f)
+	if err != nil {
+		return err
+	}
+	changeMap = m
+	return nil
+}
+
+func changeHandler(w http.ResponseWriter, r *http.Request) {
+	const prefix = "/change/"
+	if p := r.URL.Path; p == prefix {
+		// redirect /prefix/ to /prefix
+		http.Redirect(w, r, p[:len(p)-1], http.StatusFound)
+		return
+	}
+	hash := r.URL.Path[len(prefix):]
+	target := "https://go.googlesource.com/go/+/" + hash
+	if git := changeMap.Lookup(hash); git > 0 {
+		target = fmt.Sprintf("https://go.googlesource.com/%v/+/%v", git.Repo(), git.Hash())
+	}
+	http.Redirect(w, r, target, http.StatusFound)
+}
diff --git a/godoc/search.go b/godoc/search.go
new file mode 100644
index 0000000..e126330
--- /dev/null
+++ b/godoc/search.go
@@ -0,0 +1,138 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package godoc
+
+import (
+	"bytes"
+	"fmt"
+	"net/http"
+	"regexp"
+	"strings"
+)
+
+type SearchResult struct {
+	Query string
+	Alert string // error or warning message
+
+	// identifier matches
+	Pak HitList       // packages matching Query
+	Hit *LookupResult // identifier matches of Query
+	Alt *AltWords     // alternative identifiers to look for
+
+	// textual matches
+	Found    int         // number of textual occurrences found
+	Textual  []FileLines // textual matches of Query
+	Complete bool        // true if all textual occurrences of Query are reported
+	Idents   map[SpotKind][]Ident
+}
+
+func (c *Corpus) Lookup(query string) SearchResult {
+	result := &SearchResult{Query: query}
+
+	index, timestamp := c.CurrentIndex()
+	if index != nil {
+		// identifier search
+		if r, err := index.Lookup(query); err == nil {
+			result = r
+		} else if err != nil && !c.IndexFullText {
+			// ignore the error if full text search is enabled
+			// since the query may be a valid regular expression
+			result.Alert = "Error in query string: " + err.Error()
+			return *result
+		}
+
+		// full text search
+		if c.IndexFullText && query != "" {
+			rx, err := regexp.Compile(query)
+			if err != nil {
+				result.Alert = "Error in query regular expression: " + err.Error()
+				return *result
+			}
+			// If we get maxResults+1 results we know that there are more than
+			// maxResults results and thus the result may be incomplete (to be
+			// precise, we should remove one result from the result set, but
+			// nobody is going to count the results on the result page).
+			result.Found, result.Textual = index.LookupRegexp(rx, c.MaxResults+1)
+			result.Complete = result.Found <= c.MaxResults
+			if !result.Complete {
+				result.Found-- // since we looked for maxResults+1
+			}
+		}
+	}
+
+	// is the result accurate?
+	if c.IndexEnabled {
+		if ts := c.FSModifiedTime(); timestamp.Before(ts) {
+			// The index is older than the latest file system change under godoc's observation.
+			result.Alert = "Indexing in progress: result may be inaccurate"
+		}
+	} else {
+		result.Alert = "Search index disabled: no results available"
+	}
+
+	return *result
+}
+
+// SearchResultDoc optionally specifies a function returning an HTML body
+// displaying search results matching godoc documentation.
+func (p *Presentation) SearchResultDoc(result SearchResult) []byte {
+	return applyTemplate(p.SearchDocHTML, "searchDocHTML", result)
+}
+
+// SearchResultCode optionally specifies a function returning an HTML body
+// displaying search results matching source code.
+func (p *Presentation) SearchResultCode(result SearchResult) []byte {
+	return applyTemplate(p.SearchCodeHTML, "searchCodeHTML", result)
+}
+
+// SearchResultTxt optionally specifies a function returning an HTML body
+// displaying search results of textual matches.
+func (p *Presentation) SearchResultTxt(result SearchResult) []byte {
+	return applyTemplate(p.SearchTxtHTML, "searchTxtHTML", result)
+}
+
+// HandleSearch obtains results for the requested search and returns a page
+// to display them.
+func (p *Presentation) HandleSearch(w http.ResponseWriter, r *http.Request) {
+	query := strings.TrimSpace(r.FormValue("q"))
+	result := p.Corpus.Lookup(query)
+
+	if p.GetPageInfoMode(r)&NoHTML != 0 {
+		p.ServeText(w, applyTemplate(p.SearchText, "searchText", result))
+		return
+	}
+	contents := bytes.Buffer{}
+	for _, f := range p.SearchResults {
+		contents.Write(f(p, result))
+	}
+
+	var title string
+	if haveResults := contents.Len() > 0; haveResults {
+		title = fmt.Sprintf(`Results for query %q`, query)
+		if !p.Corpus.IndexEnabled {
+			result.Alert = ""
+		}
+	} else {
+		title = fmt.Sprintf(`No results found for query %q`, query)
+	}
+
+	body := bytes.NewBuffer(applyTemplate(p.SearchHTML, "searchHTML", result))
+	body.Write(contents.Bytes())
+
+	p.ServePage(w, Page{
+		Title:    title,
+		Tabtitle: query,
+		Query:    query,
+		Body:     body.Bytes(),
+	})
+}
+
+func (p *Presentation) serveSearchDesc(w http.ResponseWriter, r *http.Request) {
+	w.Header().Set("Content-Type", "application/opensearchdescription+xml")
+	data := map[string]interface{}{
+		"BaseURL": fmt.Sprintf("http://%s", r.Host),
+	}
+	applyTemplateToResponseWriter(w, p.SearchDescXML, &data)
+}
diff --git a/godoc/server.go b/godoc/server.go
new file mode 100644
index 0000000..2c18efb
--- /dev/null
+++ b/godoc/server.go
@@ -0,0 +1,750 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package godoc
+
+import (
+	"bytes"
+	"encoding/json"
+	"fmt"
+	"go/ast"
+	"go/build"
+	"go/doc"
+	"go/token"
+	htmlpkg "html"
+	htmltemplate "html/template"
+	"io"
+	"io/ioutil"
+	"log"
+	"net/http"
+	"os"
+	pathpkg "path"
+	"path/filepath"
+	"sort"
+	"strings"
+	"text/template"
+	"time"
+
+	"golang.org/x/tools/godoc/analysis"
+	"golang.org/x/tools/godoc/util"
+	"golang.org/x/tools/godoc/vfs"
+)
+
+// handlerServer is a migration from an old godoc http Handler type.
+// This should probably merge into something else.
+type handlerServer struct {
+	p       *Presentation
+	c       *Corpus  // copy of p.Corpus
+	pattern string   // url pattern; e.g. "/pkg/"
+	fsRoot  string   // file system root to which the pattern is mapped; e.g. "/src"
+	exclude []string // file system paths to exclude; e.g. "/src/cmd"
+}
+
+func (s *handlerServer) registerWithMux(mux *http.ServeMux) {
+	mux.Handle(s.pattern, s)
+}
+
+// getPageInfo returns the PageInfo for a package directory abspath. If the
+// parameter genAST is set, an AST containing only the package exports is
+// computed (PageInfo.PAst), otherwise package documentation (PageInfo.Doc)
+// is extracted from the AST. If there is no corresponding package in the
+// directory, PageInfo.PAst and PageInfo.PDoc are nil. If there are no sub-
+// directories, PageInfo.Dirs is nil. If an error occurred, PageInfo.Err is
+// set to the respective error but the error is not logged.
+//
+func (h *handlerServer) GetPageInfo(abspath, relpath string, mode PageInfoMode) *PageInfo {
+	info := &PageInfo{Dirname: abspath}
+
+	// Restrict to the package files that would be used when building
+	// the package on this system.  This makes sure that if there are
+	// separate implementations for, say, Windows vs Unix, we don't
+	// jumble them all together.
+	// Note: Uses current binary's GOOS/GOARCH.
+	// To use different pair, such as if we allowed the user to choose,
+	// set ctxt.GOOS and ctxt.GOARCH before calling ctxt.ImportDir.
+	ctxt := build.Default
+	ctxt.IsAbsPath = pathpkg.IsAbs
+	ctxt.ReadDir = func(dir string) ([]os.FileInfo, error) {
+		f, err := h.c.fs.ReadDir(filepath.ToSlash(dir))
+		filtered := make([]os.FileInfo, 0, len(f))
+		for _, i := range f {
+			if mode&NoFiltering != 0 || i.Name() != "internal" {
+				filtered = append(filtered, i)
+			}
+		}
+		return filtered, err
+	}
+	ctxt.OpenFile = func(name string) (r io.ReadCloser, err error) {
+		data, err := vfs.ReadFile(h.c.fs, filepath.ToSlash(name))
+		if err != nil {
+			return nil, err
+		}
+		return ioutil.NopCloser(bytes.NewReader(data)), nil
+	}
+
+	pkginfo, err := ctxt.ImportDir(abspath, 0)
+	// continue if there are no Go source files; we still want the directory info
+	if _, nogo := err.(*build.NoGoError); err != nil && !nogo {
+		info.Err = err
+		return info
+	}
+
+	// collect package files
+	pkgname := pkginfo.Name
+	pkgfiles := append(pkginfo.GoFiles, pkginfo.CgoFiles...)
+	if len(pkgfiles) == 0 {
+		// Commands written in C have no .go files in the build.
+		// Instead, documentation may be found in an ignored file.
+		// The file may be ignored via an explicit +build ignore
+		// constraint (recommended), or by defining the package
+		// documentation (historic).
+		pkgname = "main" // assume package main since pkginfo.Name == ""
+		pkgfiles = pkginfo.IgnoredGoFiles
+	}
+
+	// get package information, if any
+	if len(pkgfiles) > 0 {
+		// build package AST
+		fset := token.NewFileSet()
+		files, err := h.c.parseFiles(fset, relpath, abspath, pkgfiles)
+		if err != nil {
+			info.Err = err
+			return info
+		}
+
+		// ignore any errors - they are due to unresolved identifiers
+		pkg, _ := ast.NewPackage(fset, files, poorMansImporter, nil)
+
+		// extract package documentation
+		info.FSet = fset
+		if mode&ShowSource == 0 {
+			// show extracted documentation
+			var m doc.Mode
+			if mode&NoFiltering != 0 {
+				m |= doc.AllDecls
+			}
+			if mode&AllMethods != 0 {
+				m |= doc.AllMethods
+			}
+			info.PDoc = doc.New(pkg, pathpkg.Clean(relpath), m) // no trailing '/' in importpath
+			if mode&NoTypeAssoc != 0 {
+				for _, t := range info.PDoc.Types {
+					info.PDoc.Consts = append(info.PDoc.Consts, t.Consts...)
+					info.PDoc.Vars = append(info.PDoc.Vars, t.Vars...)
+					info.PDoc.Funcs = append(info.PDoc.Funcs, t.Funcs...)
+					t.Consts = nil
+					t.Vars = nil
+					t.Funcs = nil
+				}
+				// for now we cannot easily sort consts and vars since
+				// go/doc.Value doesn't export the order information
+				sort.Sort(funcsByName(info.PDoc.Funcs))
+			}
+
+			// collect examples
+			testfiles := append(pkginfo.TestGoFiles, pkginfo.XTestGoFiles...)
+			files, err = h.c.parseFiles(fset, relpath, abspath, testfiles)
+			if err != nil {
+				log.Println("parsing examples:", err)
+			}
+			info.Examples = collectExamples(h.c, pkg, files)
+
+			// collect any notes that we want to show
+			if info.PDoc.Notes != nil {
+				// could regexp.Compile only once per godoc, but probably not worth it
+				if rx := h.p.NotesRx; rx != nil {
+					for m, n := range info.PDoc.Notes {
+						if rx.MatchString(m) {
+							if info.Notes == nil {
+								info.Notes = make(map[string][]*doc.Note)
+							}
+							info.Notes[m] = n
+						}
+					}
+				}
+			}
+
+		} else {
+			// show source code
+			// TODO(gri) Consider eliminating export filtering in this mode,
+			//           or perhaps eliminating the mode altogether.
+			if mode&NoFiltering == 0 {
+				packageExports(fset, pkg)
+			}
+			info.PAst = files
+		}
+		info.IsMain = pkgname == "main"
+	}
+
+	// get directory information, if any
+	var dir *Directory
+	var timestamp time.Time
+	if tree, ts := h.c.fsTree.Get(); tree != nil && tree.(*Directory) != nil {
+		// directory tree is present; lookup respective directory
+		// (may still fail if the file system was updated and the
+		// new directory tree has not yet been computed)
+		dir = tree.(*Directory).lookup(abspath)
+		timestamp = ts
+	}
+	if dir == nil {
+		// no directory tree present (too early after startup or
+		// command-line mode); compute one level for this page
+		// note: cannot use path filter here because in general
+		//       it doesn't contain the FSTree path
+		dir = h.c.newDirectory(abspath, 1)
+		timestamp = time.Now()
+	}
+	info.Dirs = dir.listing(true, func(path string) bool { return h.includePath(path, mode) })
+	info.DirTime = timestamp
+	info.DirFlat = mode&FlatDir != 0
+
+	return info
+}
+
+func (h *handlerServer) includePath(path string, mode PageInfoMode) (r bool) {
+	// if the path is under one of the exclusion paths, don't list.
+	for _, e := range h.exclude {
+		if strings.HasPrefix(path, e) {
+			return false
+		}
+	}
+
+	// if the path includes 'internal', don't list unless we are in the NoFiltering mode.
+	if mode&NoFiltering != 0 {
+		return true
+	}
+	if strings.Contains(path, "internal") {
+		for _, c := range strings.Split(filepath.Clean(path), string(os.PathSeparator)) {
+			if c == "internal" {
+				return false
+			}
+		}
+	}
+	return true
+}
+
+type funcsByName []*doc.Func
+
+func (s funcsByName) Len() int           { return len(s) }
+func (s funcsByName) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }
+func (s funcsByName) Less(i, j int) bool { return s[i].Name < s[j].Name }
+
+func (h *handlerServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+	if redirect(w, r) {
+		return
+	}
+
+	relpath := pathpkg.Clean(r.URL.Path[len(h.pattern):])
+	abspath := pathpkg.Join(h.fsRoot, relpath)
+	mode := h.p.GetPageInfoMode(r)
+	if relpath == builtinPkgPath {
+		mode = NoFiltering | NoTypeAssoc
+	}
+	info := h.GetPageInfo(abspath, relpath, mode)
+	if info.Err != nil {
+		log.Print(info.Err)
+		h.p.ServeError(w, r, relpath, info.Err)
+		return
+	}
+
+	if mode&NoHTML != 0 {
+		h.p.ServeText(w, applyTemplate(h.p.PackageText, "packageText", info))
+		return
+	}
+
+	var tabtitle, title, subtitle string
+	switch {
+	case info.PAst != nil:
+		for _, ast := range info.PAst {
+			tabtitle = ast.Name.Name
+			break
+		}
+	case info.PDoc != nil:
+		tabtitle = info.PDoc.Name
+	default:
+		tabtitle = info.Dirname
+		title = "Directory "
+		if h.p.ShowTimestamps {
+			subtitle = "Last update: " + info.DirTime.String()
+		}
+	}
+	if title == "" {
+		if info.IsMain {
+			// assume that the directory name is the command name
+			_, tabtitle = pathpkg.Split(relpath)
+			title = "Command "
+		} else {
+			title = "Package "
+		}
+	}
+	title += tabtitle
+
+	// special cases for top-level package/command directories
+	switch tabtitle {
+	case "/src":
+		title = "Packages"
+		tabtitle = "Packages"
+	case "/src/cmd":
+		title = "Commands"
+		tabtitle = "Commands"
+	}
+
+	// Emit JSON array for type information.
+	pi := h.c.Analysis.PackageInfo(relpath)
+	info.CallGraphIndex = pi.CallGraphIndex
+	info.CallGraph = htmltemplate.JS(marshalJSON(pi.CallGraph))
+	info.AnalysisData = htmltemplate.JS(marshalJSON(pi.Types))
+	info.TypeInfoIndex = make(map[string]int)
+	for i, ti := range pi.Types {
+		info.TypeInfoIndex[ti.Name] = i
+	}
+
+	h.p.ServePage(w, Page{
+		Title:    title,
+		Tabtitle: tabtitle,
+		Subtitle: subtitle,
+		Body:     applyTemplate(h.p.PackageHTML, "packageHTML", info),
+	})
+}
+
+type PageInfoMode uint
+
+const (
+	NoFiltering PageInfoMode = 1 << iota // do not filter exports
+	AllMethods                           // show all embedded methods
+	ShowSource                           // show source code, do not extract documentation
+	NoHTML                               // show result in textual form, do not generate HTML
+	FlatDir                              // show directory in a flat (non-indented) manner
+	NoTypeAssoc                          // don't associate consts, vars, and factory functions with types
+)
+
+// modeNames defines names for each PageInfoMode flag.
+var modeNames = map[string]PageInfoMode{
+	"all":     NoFiltering,
+	"methods": AllMethods,
+	"src":     ShowSource,
+	"text":    NoHTML,
+	"flat":    FlatDir,
+}
+
+// GetPageInfoMode computes the PageInfoMode flags by analyzing the request
+// URL form value "m". It is value is a comma-separated list of mode names
+// as defined by modeNames (e.g.: m=src,text).
+func (p *Presentation) GetPageInfoMode(r *http.Request) PageInfoMode {
+	var mode PageInfoMode
+	for _, k := range strings.Split(r.FormValue("m"), ",") {
+		if m, found := modeNames[strings.TrimSpace(k)]; found {
+			mode |= m
+		}
+	}
+	if p.AdjustPageInfoMode != nil {
+		mode = p.AdjustPageInfoMode(r, mode)
+	}
+	return mode
+}
+
+// poorMansImporter returns a (dummy) package object named
+// by the last path component of the provided package path
+// (as is the convention for packages). This is sufficient
+// to resolve package identifiers without doing an actual
+// import. It never returns an error.
+//
+func poorMansImporter(imports map[string]*ast.Object, path string) (*ast.Object, error) {
+	pkg := imports[path]
+	if pkg == nil {
+		// note that strings.LastIndex returns -1 if there is no "/"
+		pkg = ast.NewObj(ast.Pkg, path[strings.LastIndex(path, "/")+1:])
+		pkg.Data = ast.NewScope(nil) // required by ast.NewPackage for dot-import
+		imports[path] = pkg
+	}
+	return pkg, nil
+}
+
+// globalNames returns a set of the names declared by all package-level
+// declarations. Method names are returned in the form Receiver_Method.
+func globalNames(pkg *ast.Package) map[string]bool {
+	names := make(map[string]bool)
+	for _, file := range pkg.Files {
+		for _, decl := range file.Decls {
+			addNames(names, decl)
+		}
+	}
+	return names
+}
+
+// collectExamples collects examples for pkg from testfiles.
+func collectExamples(c *Corpus, pkg *ast.Package, testfiles map[string]*ast.File) []*doc.Example {
+	var files []*ast.File
+	for _, f := range testfiles {
+		files = append(files, f)
+	}
+
+	var examples []*doc.Example
+	globals := globalNames(pkg)
+	for _, e := range doc.Examples(files...) {
+		name := stripExampleSuffix(e.Name)
+		if name == "" || globals[name] {
+			examples = append(examples, e)
+		} else if c.Verbose {
+			log.Printf("skipping example 'Example%s' because '%s' is not a known function or type", e.Name, e.Name)
+		}
+	}
+
+	return examples
+}
+
+// addNames adds the names declared by decl to the names set.
+// Method names are added in the form ReceiverTypeName_Method.
+func addNames(names map[string]bool, decl ast.Decl) {
+	switch d := decl.(type) {
+	case *ast.FuncDecl:
+		name := d.Name.Name
+		if d.Recv != nil {
+			var typeName string
+			switch r := d.Recv.List[0].Type.(type) {
+			case *ast.StarExpr:
+				typeName = r.X.(*ast.Ident).Name
+			case *ast.Ident:
+				typeName = r.Name
+			}
+			name = typeName + "_" + name
+		}
+		names[name] = true
+	case *ast.GenDecl:
+		for _, spec := range d.Specs {
+			switch s := spec.(type) {
+			case *ast.TypeSpec:
+				names[s.Name.Name] = true
+			case *ast.ValueSpec:
+				for _, id := range s.Names {
+					names[id.Name] = true
+				}
+			}
+		}
+	}
+}
+
+// packageExports is a local implementation of ast.PackageExports
+// which correctly updates each package file's comment list.
+// (The ast.PackageExports signature is frozen, hence the local
+// implementation).
+//
+func packageExports(fset *token.FileSet, pkg *ast.Package) {
+	for _, src := range pkg.Files {
+		cmap := ast.NewCommentMap(fset, src, src.Comments)
+		ast.FileExports(src)
+		src.Comments = cmap.Filter(src).Comments()
+	}
+}
+
+func applyTemplate(t *template.Template, name string, data interface{}) []byte {
+	var buf bytes.Buffer
+	if err := t.Execute(&buf, data); err != nil {
+		log.Printf("%s.Execute: %s", name, err)
+	}
+	return buf.Bytes()
+}
+
+type writerCapturesErr struct {
+	w   io.Writer
+	err error
+}
+
+func (w *writerCapturesErr) Write(p []byte) (int, error) {
+	n, err := w.w.Write(p)
+	if err != nil {
+		w.err = err
+	}
+	return n, err
+}
+
+// applyTemplateToResponseWriter uses an http.ResponseWriter as the io.Writer
+// for the call to template.Execute.  It uses an io.Writer wrapper to capture
+// errors from the underlying http.ResponseWriter.  Errors are logged only when
+// they come from the template processing and not the Writer; this avoid
+// polluting log files with error messages due to networking issues, such as
+// client disconnects and http HEAD protocol violations.
+func applyTemplateToResponseWriter(rw http.ResponseWriter, t *template.Template, data interface{}) {
+	w := &writerCapturesErr{w: rw}
+	err := t.Execute(w, data)
+	// There are some cases where template.Execute does not return an error when
+	// rw returns an error, and some where it does.  So check w.err first.
+	if w.err == nil && err != nil {
+		// Log template errors.
+		log.Printf("%s.Execute: %s", t.Name(), err)
+	}
+}
+
+func redirect(w http.ResponseWriter, r *http.Request) (redirected bool) {
+	canonical := pathpkg.Clean(r.URL.Path)
+	if !strings.HasSuffix(canonical, "/") {
+		canonical += "/"
+	}
+	if r.URL.Path != canonical {
+		url := *r.URL
+		url.Path = canonical
+		http.Redirect(w, r, url.String(), http.StatusMovedPermanently)
+		redirected = true
+	}
+	return
+}
+
+func redirectFile(w http.ResponseWriter, r *http.Request) (redirected bool) {
+	c := pathpkg.Clean(r.URL.Path)
+	c = strings.TrimRight(c, "/")
+	if r.URL.Path != c {
+		url := *r.URL
+		url.Path = c
+		http.Redirect(w, r, url.String(), http.StatusMovedPermanently)
+		redirected = true
+	}
+	return
+}
+
+func (p *Presentation) serveTextFile(w http.ResponseWriter, r *http.Request, abspath, relpath, title string) {
+	src, err := vfs.ReadFile(p.Corpus.fs, abspath)
+	if err != nil {
+		log.Printf("ReadFile: %s", err)
+		p.ServeError(w, r, relpath, err)
+		return
+	}
+
+	if r.FormValue("m") == "text" {
+		p.ServeText(w, src)
+		return
+	}
+
+	h := r.FormValue("h")
+	s := RangeSelection(r.FormValue("s"))
+
+	var buf bytes.Buffer
+	if pathpkg.Ext(abspath) == ".go" {
+		// Find markup links for this file (e.g. "/src/fmt/print.go").
+		fi := p.Corpus.Analysis.FileInfo(abspath)
+		buf.WriteString("<script type='text/javascript'>document.ANALYSIS_DATA = ")
+		buf.Write(marshalJSON(fi.Data))
+		buf.WriteString(";</script>\n")
+
+		if status := p.Corpus.Analysis.Status(); status != "" {
+			buf.WriteString("<a href='/lib/godoc/analysis/help.html'>Static analysis features</a> ")
+			// TODO(adonovan): show analysis status at per-file granularity.
+			fmt.Fprintf(&buf, "<span style='color: grey'>[%s]</span><br/>", htmlpkg.EscapeString(status))
+		}
+
+		buf.WriteString("<pre>")
+		formatGoSource(&buf, src, fi.Links, h, s)
+		buf.WriteString("</pre>")
+	} else {
+		buf.WriteString("<pre>")
+		FormatText(&buf, src, 1, false, h, s)
+		buf.WriteString("</pre>")
+	}
+	fmt.Fprintf(&buf, `<p><a href="/%s?m=text">View as plain text</a></p>`, htmlpkg.EscapeString(relpath))
+
+	p.ServePage(w, Page{
+		Title:    title + " " + relpath,
+		Tabtitle: relpath,
+		Body:     buf.Bytes(),
+	})
+}
+
+// formatGoSource HTML-escapes Go source text and writes it to w,
+// decorating it with the specified analysis links.
+//
+func formatGoSource(buf *bytes.Buffer, text []byte, links []analysis.Link, pattern string, selection Selection) {
+	// Emit to a temp buffer so that we can add line anchors at the end.
+	saved, buf := buf, new(bytes.Buffer)
+
+	var i int
+	var link analysis.Link // shared state of the two funcs below
+	segmentIter := func() (seg Segment) {
+		if i < len(links) {
+			link = links[i]
+			i++
+			seg = Segment{link.Start(), link.End()}
+		}
+		return
+	}
+	linkWriter := func(w io.Writer, offs int, start bool) {
+		link.Write(w, offs, start)
+	}
+
+	comments := tokenSelection(text, token.COMMENT)
+	var highlights Selection
+	if pattern != "" {
+		highlights = regexpSelection(text, pattern)
+	}
+
+	FormatSelections(buf, text, linkWriter, segmentIter, selectionTag, comments, highlights, selection)
+
+	// Now copy buf to saved, adding line anchors.
+
+	// The lineSelection mechanism can't be composed with our
+	// linkWriter, so we have to add line spans as another pass.
+	n := 1
+	for _, line := range bytes.Split(buf.Bytes(), []byte("\n")) {
+		fmt.Fprintf(saved, "<span id=\"L%d\" class=\"ln\">%6d</span>\t", n, n)
+		n++
+		saved.Write(line)
+		saved.WriteByte('\n')
+	}
+}
+
+func (p *Presentation) serveDirectory(w http.ResponseWriter, r *http.Request, abspath, relpath string) {
+	if redirect(w, r) {
+		return
+	}
+
+	list, err := p.Corpus.fs.ReadDir(abspath)
+	if err != nil {
+		p.ServeError(w, r, relpath, err)
+		return
+	}
+
+	p.ServePage(w, Page{
+		Title:    "Directory " + relpath,
+		Tabtitle: relpath,
+		Body:     applyTemplate(p.DirlistHTML, "dirlistHTML", list),
+	})
+}
+
+func (p *Presentation) ServeHTMLDoc(w http.ResponseWriter, r *http.Request, abspath, relpath string) {
+	// get HTML body contents
+	src, err := vfs.ReadFile(p.Corpus.fs, abspath)
+	if err != nil {
+		log.Printf("ReadFile: %s", err)
+		p.ServeError(w, r, relpath, err)
+		return
+	}
+
+	// if it begins with "<!DOCTYPE " assume it is standalone
+	// html that doesn't need the template wrapping.
+	if bytes.HasPrefix(src, doctype) {
+		w.Write(src)
+		return
+	}
+
+	// if it begins with a JSON blob, read in the metadata.
+	meta, src, err := extractMetadata(src)
+	if err != nil {
+		log.Printf("decoding metadata %s: %v", relpath, err)
+	}
+
+	// evaluate as template if indicated
+	if meta.Template {
+		tmpl, err := template.New("main").Funcs(p.TemplateFuncs()).Parse(string(src))
+		if err != nil {
+			log.Printf("parsing template %s: %v", relpath, err)
+			p.ServeError(w, r, relpath, err)
+			return
+		}
+		var buf bytes.Buffer
+		if err := tmpl.Execute(&buf, nil); err != nil {
+			log.Printf("executing template %s: %v", relpath, err)
+			p.ServeError(w, r, relpath, err)
+			return
+		}
+		src = buf.Bytes()
+	}
+
+	// if it's the language spec, add tags to EBNF productions
+	if strings.HasSuffix(abspath, "go_spec.html") {
+		var buf bytes.Buffer
+		Linkify(&buf, src)
+		src = buf.Bytes()
+	}
+
+	p.ServePage(w, Page{
+		Title:    meta.Title,
+		Subtitle: meta.Subtitle,
+		Body:     src,
+	})
+}
+
+func (p *Presentation) ServeFile(w http.ResponseWriter, r *http.Request) {
+	p.serveFile(w, r)
+}
+
+func (p *Presentation) serveFile(w http.ResponseWriter, r *http.Request) {
+	relpath := r.URL.Path
+
+	// Check to see if we need to redirect or serve another file.
+	if m := p.Corpus.MetadataFor(relpath); m != nil {
+		if m.Path != relpath {
+			// Redirect to canonical path.
+			http.Redirect(w, r, m.Path, http.StatusMovedPermanently)
+			return
+		}
+		// Serve from the actual filesystem path.
+		relpath = m.filePath
+	}
+
+	abspath := relpath
+	relpath = relpath[1:] // strip leading slash
+
+	switch pathpkg.Ext(relpath) {
+	case ".html":
+		if strings.HasSuffix(relpath, "/index.html") {
+			// We'll show index.html for the directory.
+			// Use the dir/ version as canonical instead of dir/index.html.
+			http.Redirect(w, r, r.URL.Path[0:len(r.URL.Path)-len("index.html")], http.StatusMovedPermanently)
+			return
+		}
+		p.ServeHTMLDoc(w, r, abspath, relpath)
+		return
+
+	case ".go":
+		p.serveTextFile(w, r, abspath, relpath, "Source file")
+		return
+	}
+
+	dir, err := p.Corpus.fs.Lstat(abspath)
+	if err != nil {
+		log.Print(err)
+		p.ServeError(w, r, relpath, err)
+		return
+	}
+
+	if dir != nil && dir.IsDir() {
+		if redirect(w, r) {
+			return
+		}
+		if index := pathpkg.Join(abspath, "index.html"); util.IsTextFile(p.Corpus.fs, index) {
+			p.ServeHTMLDoc(w, r, index, index)
+			return
+		}
+		p.serveDirectory(w, r, abspath, relpath)
+		return
+	}
+
+	if util.IsTextFile(p.Corpus.fs, abspath) {
+		if redirectFile(w, r) {
+			return
+		}
+		p.serveTextFile(w, r, abspath, relpath, "Text file")
+		return
+	}
+
+	p.fileServer.ServeHTTP(w, r)
+}
+
+func (p *Presentation) ServeText(w http.ResponseWriter, text []byte) {
+	w.Header().Set("Content-Type", "text/plain; charset=utf-8")
+	w.Write(text)
+}
+
+func marshalJSON(x interface{}) []byte {
+	var data []byte
+	var err error
+	const indentJSON = false // for easier debugging
+	if indentJSON {
+		data, err = json.MarshalIndent(x, "", "    ")
+	} else {
+		data, err = json.Marshal(x)
+	}
+	if err != nil {
+		panic(fmt.Sprintf("json.Marshal failed: %s", err))
+	}
+	return data
+}
diff --git a/godoc/snippet.go b/godoc/snippet.go
new file mode 100644
index 0000000..dd9c822
--- /dev/null
+++ b/godoc/snippet.go
@@ -0,0 +1,123 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file contains the infrastructure to create a code
+// snippet for search results.
+//
+// Note: At the moment, this only creates HTML snippets.
+
+package godoc
+
+import (
+	"bytes"
+	"fmt"
+	"go/ast"
+	"go/token"
+)
+
+type Snippet struct {
+	Line int
+	Text string // HTML-escaped
+}
+
+func (p *Presentation) newSnippet(fset *token.FileSet, decl ast.Decl, id *ast.Ident) *Snippet {
+	// TODO instead of pretty-printing the node, should use the original source instead
+	var buf1 bytes.Buffer
+	p.writeNode(&buf1, fset, decl)
+	// wrap text with <pre> tag
+	var buf2 bytes.Buffer
+	buf2.WriteString("<pre>")
+	FormatText(&buf2, buf1.Bytes(), -1, true, id.Name, nil)
+	buf2.WriteString("</pre>")
+	return &Snippet{fset.Position(id.Pos()).Line, buf2.String()}
+}
+
+func findSpec(list []ast.Spec, id *ast.Ident) ast.Spec {
+	for _, spec := range list {
+		switch s := spec.(type) {
+		case *ast.ImportSpec:
+			if s.Name == id {
+				return s
+			}
+		case *ast.ValueSpec:
+			for _, n := range s.Names {
+				if n == id {
+					return s
+				}
+			}
+		case *ast.TypeSpec:
+			if s.Name == id {
+				return s
+			}
+		}
+	}
+	return nil
+}
+
+func (p *Presentation) genSnippet(fset *token.FileSet, d *ast.GenDecl, id *ast.Ident) *Snippet {
+	s := findSpec(d.Specs, id)
+	if s == nil {
+		return nil //  declaration doesn't contain id - exit gracefully
+	}
+
+	// only use the spec containing the id for the snippet
+	dd := &ast.GenDecl{
+		Doc:    d.Doc,
+		TokPos: d.Pos(),
+		Tok:    d.Tok,
+		Lparen: d.Lparen,
+		Specs:  []ast.Spec{s},
+		Rparen: d.Rparen,
+	}
+
+	return p.newSnippet(fset, dd, id)
+}
+
+func (p *Presentation) funcSnippet(fset *token.FileSet, d *ast.FuncDecl, id *ast.Ident) *Snippet {
+	if d.Name != id {
+		return nil //  declaration doesn't contain id - exit gracefully
+	}
+
+	// only use the function signature for the snippet
+	dd := &ast.FuncDecl{
+		Doc:  d.Doc,
+		Recv: d.Recv,
+		Name: d.Name,
+		Type: d.Type,
+	}
+
+	return p.newSnippet(fset, dd, id)
+}
+
+// NewSnippet creates a text snippet from a declaration decl containing an
+// identifier id. Parts of the declaration not containing the identifier
+// may be removed for a more compact snippet.
+func NewSnippet(fset *token.FileSet, decl ast.Decl, id *ast.Ident) *Snippet {
+	// TODO(bradfitz, adg): remove this function.  But it's used by indexer, which
+	// doesn't have a *Presentation, and NewSnippet needs a TabWidth.
+	var p Presentation
+	p.TabWidth = 4
+	return p.NewSnippet(fset, decl, id)
+}
+
+// NewSnippet creates a text snippet from a declaration decl containing an
+// identifier id. Parts of the declaration not containing the identifier
+// may be removed for a more compact snippet.
+func (p *Presentation) NewSnippet(fset *token.FileSet, decl ast.Decl, id *ast.Ident) *Snippet {
+	var s *Snippet
+	switch d := decl.(type) {
+	case *ast.GenDecl:
+		s = p.genSnippet(fset, d, id)
+	case *ast.FuncDecl:
+		s = p.funcSnippet(fset, d, id)
+	}
+
+	// handle failure gracefully
+	if s == nil {
+		var buf bytes.Buffer
+		fmt.Fprintf(&buf, `<span class="alert">could not generate a snippet for <span class="highlight">%s</span></span>`, id.Name)
+		s = &Snippet{fset.Position(id.Pos()).Line, buf.String()}
+	}
+	return s
+}
diff --git a/godoc/spec.go b/godoc/spec.go
new file mode 100644
index 0000000..6d6b9c2
--- /dev/null
+++ b/godoc/spec.go
@@ -0,0 +1,179 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package godoc
+
+// This file contains the mechanism to "linkify" html source
+// text containing EBNF sections (as found in go_spec.html).
+// The result is the input source text with the EBNF sections
+// modified such that identifiers are linked to the respective
+// definitions.
+
+import (
+	"bytes"
+	"fmt"
+	"io"
+	"text/scanner"
+)
+
+type ebnfParser struct {
+	out     io.Writer // parser output
+	src     []byte    // parser input
+	scanner scanner.Scanner
+	prev    int    // offset of previous token
+	pos     int    // offset of current token
+	tok     rune   // one token look-ahead
+	lit     string // token literal
+}
+
+func (p *ebnfParser) flush() {
+	p.out.Write(p.src[p.prev:p.pos])
+	p.prev = p.pos
+}
+
+func (p *ebnfParser) next() {
+	p.tok = p.scanner.Scan()
+	p.pos = p.scanner.Position.Offset
+	p.lit = p.scanner.TokenText()
+}
+
+func (p *ebnfParser) printf(format string, args ...interface{}) {
+	p.flush()
+	fmt.Fprintf(p.out, format, args...)
+}
+
+func (p *ebnfParser) errorExpected(msg string) {
+	p.printf(`<span class="highlight">error: expected %s, found %s</span>`, msg, scanner.TokenString(p.tok))
+}
+
+func (p *ebnfParser) expect(tok rune) {
+	if p.tok != tok {
+		p.errorExpected(scanner.TokenString(tok))
+	}
+	p.next() // make progress in any case
+}
+
+func (p *ebnfParser) parseIdentifier(def bool) {
+	if p.tok == scanner.Ident {
+		name := p.lit
+		if def {
+			p.printf(`<a id="%s">%s</a>`, name, name)
+		} else {
+			p.printf(`<a href="#%s" class="noline">%s</a>`, name, name)
+		}
+		p.prev += len(name) // skip identifier when printing next time
+		p.next()
+	} else {
+		p.expect(scanner.Ident)
+	}
+}
+
+func (p *ebnfParser) parseTerm() bool {
+	switch p.tok {
+	case scanner.Ident:
+		p.parseIdentifier(false)
+
+	case scanner.String:
+		p.next()
+		const ellipsis = '…' // U+2026, the horizontal ellipsis character
+		if p.tok == ellipsis {
+			p.next()
+			p.expect(scanner.String)
+		}
+
+	case '(':
+		p.next()
+		p.parseExpression()
+		p.expect(')')
+
+	case '[':
+		p.next()
+		p.parseExpression()
+		p.expect(']')
+
+	case '{':
+		p.next()
+		p.parseExpression()
+		p.expect('}')
+
+	default:
+		return false // no term found
+	}
+
+	return true
+}
+
+func (p *ebnfParser) parseSequence() {
+	if !p.parseTerm() {
+		p.errorExpected("term")
+	}
+	for p.parseTerm() {
+	}
+}
+
+func (p *ebnfParser) parseExpression() {
+	for {
+		p.parseSequence()
+		if p.tok != '|' {
+			break
+		}
+		p.next()
+	}
+}
+
+func (p *ebnfParser) parseProduction() {
+	p.parseIdentifier(true)
+	p.expect('=')
+	if p.tok != '.' {
+		p.parseExpression()
+	}
+	p.expect('.')
+}
+
+func (p *ebnfParser) parse(out io.Writer, src []byte) {
+	// initialize ebnfParser
+	p.out = out
+	p.src = src
+	p.scanner.Init(bytes.NewBuffer(src))
+	p.next() // initializes pos, tok, lit
+
+	// process source
+	for p.tok != scanner.EOF {
+		p.parseProduction()
+	}
+	p.flush()
+}
+
+// Markers around EBNF sections
+var (
+	openTag  = []byte(`<pre class="ebnf">`)
+	closeTag = []byte(`</pre>`)
+)
+
+func Linkify(out io.Writer, src []byte) {
+	for len(src) > 0 {
+		// i: beginning of EBNF text (or end of source)
+		i := bytes.Index(src, openTag)
+		if i < 0 {
+			i = len(src) - len(openTag)
+		}
+		i += len(openTag)
+
+		// j: end of EBNF text (or end of source)
+		j := bytes.Index(src[i:], closeTag) // close marker
+		if j < 0 {
+			j = len(src) - i
+		}
+		j += i
+
+		// write text before EBNF
+		out.Write(src[0:i])
+		// process EBNF
+		var p ebnfParser
+		p.parse(out, src[i:j])
+
+		// advance
+		src = src[j:]
+	}
+}
diff --git a/godoc/spot.go b/godoc/spot.go
new file mode 100644
index 0000000..95ffa4b
--- /dev/null
+++ b/godoc/spot.go
@@ -0,0 +1,83 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package godoc
+
+// ----------------------------------------------------------------------------
+// SpotInfo
+
+// A SpotInfo value describes a particular identifier spot in a given file;
+// It encodes three values: the SpotKind (declaration or use), a line or
+// snippet index "lori", and whether it's a line or index.
+//
+// The following encoding is used:
+//
+//   bits    32   4    1       0
+//   value    [lori|kind|isIndex]
+//
+type SpotInfo uint32
+
+// SpotKind describes whether an identifier is declared (and what kind of
+// declaration) or used.
+type SpotKind uint32
+
+const (
+	PackageClause SpotKind = iota
+	ImportDecl
+	ConstDecl
+	TypeDecl
+	VarDecl
+	FuncDecl
+	MethodDecl
+	Use
+	nKinds
+)
+
+var (
+	// These must match the SpotKind values above.
+	name = []string{
+		"Packages",
+		"Imports",
+		"Constants",
+		"Types",
+		"Variables",
+		"Functions",
+		"Methods",
+		"Uses",
+		"Unknown",
+	}
+)
+
+func (x SpotKind) Name() string { return name[x] }
+
+func init() {
+	// sanity check: if nKinds is too large, the SpotInfo
+	// accessor functions may need to be updated
+	if nKinds > 8 {
+		panic("internal error: nKinds > 8")
+	}
+}
+
+// makeSpotInfo makes a SpotInfo.
+func makeSpotInfo(kind SpotKind, lori int, isIndex bool) SpotInfo {
+	// encode lori: bits [4..32)
+	x := SpotInfo(lori) << 4
+	if int(x>>4) != lori {
+		// lori value doesn't fit - since snippet indices are
+		// most certainly always smaller then 1<<28, this can
+		// only happen for line numbers; give it no line number (= 0)
+		x = 0
+	}
+	// encode kind: bits [1..4)
+	x |= SpotInfo(kind) << 1
+	// encode isIndex: bit 0
+	if isIndex {
+		x |= 1
+	}
+	return x
+}
+
+func (x SpotInfo) Kind() SpotKind { return SpotKind(x >> 1 & 7) }
+func (x SpotInfo) Lori() int      { return int(x >> 4) }
+func (x SpotInfo) IsIndex() bool  { return x&1 != 0 }
diff --git a/godoc/static/analysis/call-eg.png b/godoc/static/analysis/call-eg.png
new file mode 100644
index 0000000..c48bf4d
--- /dev/null
+++ b/godoc/static/analysis/call-eg.png
Binary files differ
diff --git a/godoc/static/analysis/call3.png b/godoc/static/analysis/call3.png
new file mode 100644
index 0000000..387a38c
--- /dev/null
+++ b/godoc/static/analysis/call3.png
Binary files differ
diff --git a/godoc/static/analysis/callers1.png b/godoc/static/analysis/callers1.png
new file mode 100644
index 0000000..80fbc62
--- /dev/null
+++ b/godoc/static/analysis/callers1.png
Binary files differ
diff --git a/godoc/static/analysis/callers2.png b/godoc/static/analysis/callers2.png
new file mode 100644
index 0000000..59a84ed
--- /dev/null
+++ b/godoc/static/analysis/callers2.png
Binary files differ
diff --git a/godoc/static/analysis/chan1.png b/godoc/static/analysis/chan1.png
new file mode 100644
index 0000000..5eb2811
--- /dev/null
+++ b/godoc/static/analysis/chan1.png
Binary files differ
diff --git a/godoc/static/analysis/chan2a.png b/godoc/static/analysis/chan2a.png
new file mode 100644
index 0000000..b757504
--- /dev/null
+++ b/godoc/static/analysis/chan2a.png
Binary files differ
diff --git a/godoc/static/analysis/chan2b.png b/godoc/static/analysis/chan2b.png
new file mode 100644
index 0000000..d197862
--- /dev/null
+++ b/godoc/static/analysis/chan2b.png
Binary files differ
diff --git a/godoc/static/analysis/error1.png b/godoc/static/analysis/error1.png
new file mode 100644
index 0000000..69550b9
--- /dev/null
+++ b/godoc/static/analysis/error1.png
Binary files differ
diff --git a/godoc/static/analysis/help.html b/godoc/static/analysis/help.html
new file mode 100644
index 0000000..023c07d
--- /dev/null
+++ b/godoc/static/analysis/help.html
@@ -0,0 +1,254 @@
+<!--{
+        "Title": "Static analysis features of godoc"
+}-->
+
+<style>
+  span.err { 'font-size:120%; color:darkred; background-color: yellow; }
+  img.ss { margin-left: 1in; } /* screenshot */
+  img.dotted { border: thin dotted; }
+</style>
+
+<!-- Images were grabbed from Chrome/Linux at 150% zoom, and are
+     displayed at 66% of natural size.  This allows users to zoom a
+     little before seeing pixels. -->
+
+<p>
+  When invoked with the <code>-analysis</code> flag, godoc performs
+  static analysis on the Go packages it indexes and displays the
+  results in the source and package views.  This document provides a
+  brief tour of these features.
+</p>
+
+<h2>Type analysis features</h2>
+<p>
+  <code>godoc -analysis=type</code> performs static checking similar
+  to that done by a compiler: it detects ill-formed programs, resolves
+  each identifier to the entity it denotes, computes the type of each
+  expression and the method set of each type, and determines which
+  types are assignable to each interface type.
+
+  <b>Type analysis</b> is relatively quick, requiring about 10 seconds for
+  the &gt;200 packages of the standard library, for example.
+</p>
+
+<h3>Compiler errors</h3>
+<p>
+  If any source file contains a compilation error, the source view
+  will highlight the errant location in red.  Hovering over it
+  displays the error message.
+</p>
+<img class="ss" width='811' src='error1.png'><br/>
+
+<h3>Identifier resolution</h3>
+<p>
+  In the source view, every referring identifier is annotated with
+  information about the language entity it refers to: a package,
+  constant, variable, type, function or statement label.
+
+  Hovering over the identifier reveals the entity's kind and type
+  (e.g. <code>var x int</code> or <code>func f
+  func(int) string</code>).
+</p>
+<img class="ss" width='652' src='ident-field.png'><br/>
+<br/>
+<img class="ss" width='652' src='ident-func.png'>
+<p>
+  Clicking the link takes you to the entity's definition.
+</p>
+<img class="ss" width='652' src='ident-def.png'><br/>
+
+<h3>Type information: size/alignment, method set, interfaces</h3>
+<p>
+  Clicking on the identifier that defines a named type causes a panel
+  to appear, displaying information about the named type, including
+  its size and alignment in bytes, its
+  <a href='http://golang.org/ref/spec#Method_sets'>method set</a>, and its
+  <i>implements</i> relation: the set of types T that are assignable to
+  or from this type U where at least one of T or U is an interface.
+
+  This example shows information about <code>net/rpc.methodType</code>.
+</p>
+<img class="ss" width='470' src='typeinfo-src.png'>
+<p>
+  The method set includes not only the declared methods of the type,
+  but also any methods "promoted" from anonymous fields of structs,
+  such as <code>sync.Mutex</code> in this example.
+
+  In addition, the receiver type is displayed as <code>*T</code> or
+  <code>T</code> depending on whether it requires the address or just
+  a copy of the receiver value.
+</p>
+<p>
+  The method set and <i>implements</i> relation are also available
+  via the package view.
+</p>
+<img class="ss dotted" width='716' src='typeinfo-pkg.png'>
+
+<h2>Pointer analysis features</h2>
+<p>
+  <code>godoc -analysis=pointer</code> additionally performs a precise
+  whole-program <b>pointer analysis</b>.  In other words, it
+  approximates the set of memory locations to which each
+  reference&mdash;not just vars of kind <code>*T</code>, but also
+  <code>[]T</code>, <code>func</code>, <code>map</code>,
+  <code>chan</code>, and <code>interface</code>&mdash;may refer.  This
+  information reveals the possible destinations of each dynamic call
+  (via a <code>func</code> variable or interface method), and the
+  relationship between send and receive operations on the same
+  channel.
+</p>
+<p>
+  Compared to type analysis, pointer analysis requires more time and
+  memory, and is impractical for code bases exceeding a million lines.
+</p>
+
+<h3>Call graph navigation</h3>
+<p>
+  When pointer analysis is complete, the source view annotates the
+  code with <b>callers</b> and <b>callees</b> information: callers
+  information is associated with the <code>func</code> keyword that
+  declares a function, and callees information is associated with the
+  open paren '<span style="color: dark-blue"><code>(</code></span>' of
+  a function call.
+</p>
+<p>
+  In this example, hovering over the declaration of the
+  <code>rot13</code> function (defined in strings/strings_test.go)
+  reveals that it is called in exactly one place.
+</p>
+<img class="ss" width='612' src='callers1.png'>
+<p>
+  Clicking the link navigates to the sole caller.  (If there were
+  multiple callers, a list of choices would be displayed first.)
+</p>
+<img class="ss" width='680' src='callers2.png'>
+<p>
+  Notice that hovering over this call reveals that there are 19
+  possible callees at this site, of which our <code>rot13</code>
+  function was just one: this is a dynamic call through a variable of
+  type <code>func(rune) rune</code>.
+
+  Clicking on the call brings up the list of all 19 potential callees,
+  shown truncated.  Many of them are anonymous functions.
+</p>
+<img class="ss" width='564' src='call3.png'>
+<p>
+  Pointer analysis gives a very precise approximation of the call
+  graph compared to type-based techniques.
+
+  As a case in point, the next example shows the dynamic call inside
+  the <code>testing</code> package responsible for calling all
+  user-defined functions named <code>Example<i>XYZ</i></code>.
+</p>
+<img class="ss" width='361' src='call-eg.png'>
+<p>
+  Recall that all such functions have type <code>func()</code>,
+  i.e. no arguments and no results.  A type-based approximation could
+  only conclude that this call might dispatch to any function matching
+  that type&mdash;and these are very numerous in most
+  programs&mdash;but pointer analysis can track the flow of specific
+  <code>func</code> values through the testing package.
+
+  As an indication of its precision, the result contains only
+  functions whose name starts with <code>Example</code>.
+</p>
+
+<h3>Intra-package call graph</h3>
+<p>
+  The same call graph information is presented in a very different way
+  in the package view.  For each package, an interactive tree view
+  allows exploration of the call graph as it relates to just that
+  package; all functions from other packages are elided.
+
+  The roots of the tree are the external entry points of the package:
+  not only its exported functions, but also any unexported or
+  anonymous functions that are called (dynamically) from outside the
+  package.
+</p>
+<p>
+  This example shows the entry points of the
+  <code>path/filepath</code> package, with the call graph for
+  <code>Glob</code> expanded several levels
+</p>
+<img class="ss dotted" width='501' src='ipcg-pkg.png'>
+<p>
+  Notice that the nodes for Glob and Join appear multiple times: the
+  tree is a partial unrolling of a cyclic graph; the full unrolling
+  is in general infinite.
+</p>
+<p>
+  For each function documented in the package view, another
+  interactive tree view allows exploration of the same graph starting
+  at that function.
+
+  This is a portion of the internal graph of
+  <code>net/http.ListenAndServe</code>.
+</p>
+<img class="ss dotted" width='455' src='ipcg-func.png'>
+
+<h3>Channel peers (send ↔ receive)</h3>
+<p>
+  Because concurrent Go programs use channels to pass not just values
+  but also control between different goroutines, it is natural when
+  reading Go code to want to navigate from a channel send to the
+  corresponding receive so as to understand the sequence of events.
+</p>
+<p>
+  Godoc annotates every channel operation&mdash;make, send, range,
+  receive, close&mdash;with a link to a panel displaying information
+  about other operations that might alias the same channel.
+</p>
+<p>
+  This example, from the tests of <code>net/http</code>, shows a send
+  operation on a <code>chan bool</code>.
+</p>
+<img class="ss" width='811' src='chan1.png'>
+<p>
+  Clicking on the <code>&lt;-</code> send operator reveals that this
+  channel is made at a unique location (line 332) and that there are
+  three receive operations that might read this value.
+
+  It hardly needs pointing out that some channel element types are
+  very widely used (e.g. struct{}, bool, int, interface{}) and that a
+  typical Go program might contain dozens of receive operations on a
+  value of type <code>chan bool</code>; yet the pointer analysis is
+  able to distinguish operations on channels at a much finer precision
+  than based on their type alone.
+</p>
+<p>
+  Notice also that the send occurs in a different (anonymous) function
+  from the outer one containing the <code>make</code> and the receive
+  operations.
+</p>
+<p>
+  Here's another example of send on a different <code>chan
+  bool</code>, also in package <code>net/http</code>:
+</p>
+<img class="ss" width='774' src='chan2a.png'>
+<p>
+  The analysis finds just one receive operation that might receive
+  from this channel, in the test for this feature.
+</p>
+<img class="ss" width='737' src='chan2b.png'>
+
+<h2>Known issues</h2>
+<p>
+  All analysis results pertain to exactly
+  one configuration (e.g. amd64 linux).  Files that are conditionally
+  compiled based on different platforms or build tags are not visible
+  to the analysis.
+</p>
+<p>
+  Files that <code>import "C"</code> require
+  preprocessing by the cgo tool.  The file offsets after preprocessing
+  do not align with the unpreprocessed file, so markup is misaligned.
+</p>
+<p>
+  Files are not periodically re-analyzed.
+  If the files change underneath the running server, the displayed
+  markup is misaligned.
+</p>
+<p>
+  Additional issues are listed at
+  <a href='https://go.googlesource.com/tools/+/master/godoc/analysis/README'>tools/godoc/analysis/README</a>.
+</p>
diff --git a/godoc/static/analysis/ident-def.png b/godoc/static/analysis/ident-def.png
new file mode 100644
index 0000000..b0d9e55
--- /dev/null
+++ b/godoc/static/analysis/ident-def.png
Binary files differ
diff --git a/godoc/static/analysis/ident-field.png b/godoc/static/analysis/ident-field.png
new file mode 100644
index 0000000..76cbe5a
--- /dev/null
+++ b/godoc/static/analysis/ident-field.png
Binary files differ
diff --git a/godoc/static/analysis/ident-func.png b/godoc/static/analysis/ident-func.png
new file mode 100644
index 0000000..69670fa
--- /dev/null
+++ b/godoc/static/analysis/ident-func.png
Binary files differ
diff --git a/godoc/static/analysis/ipcg-func.png b/godoc/static/analysis/ipcg-func.png
new file mode 100644
index 0000000..523318d
--- /dev/null
+++ b/godoc/static/analysis/ipcg-func.png
Binary files differ
diff --git a/godoc/static/analysis/ipcg-pkg.png b/godoc/static/analysis/ipcg-pkg.png
new file mode 100644
index 0000000..e029068
--- /dev/null
+++ b/godoc/static/analysis/ipcg-pkg.png
Binary files differ
diff --git a/godoc/static/analysis/typeinfo-pkg.png b/godoc/static/analysis/typeinfo-pkg.png
new file mode 100644
index 0000000..91bd5f7
--- /dev/null
+++ b/godoc/static/analysis/typeinfo-pkg.png
Binary files differ
diff --git a/godoc/static/analysis/typeinfo-src.png b/godoc/static/analysis/typeinfo-src.png
new file mode 100644
index 0000000..6e5b147
--- /dev/null
+++ b/godoc/static/analysis/typeinfo-src.png
Binary files differ
diff --git a/godoc/static/callgraph.html b/godoc/static/callgraph.html
new file mode 100644
index 0000000..c56b2ef
--- /dev/null
+++ b/godoc/static/callgraph.html
@@ -0,0 +1,15 @@
+<div class="toggle" style="display: none">
+	<div class="collapsed">
+		<p class="exampleHeading toggleButton">▹ <span class="text">Internal call graph</span></p>
+	</div>
+	<div class="expanded">
+		<p class="exampleHeading toggleButton">▾ <span class="text">Internal call graph</span></p>
+		<p>
+		  This viewer shows the portion of the internal call
+		  graph of this package that is reachable from this function.
+		  See the <a href='#pkg-callgraph'>package's call
+		  graph</a> for more information.
+		</p>
+		<ul style="margin-left: 0.5in" id="callgraph-{{.Index}}" class="treeview"></ul>
+	</div>
+</div>
diff --git a/godoc/static/codewalk.html b/godoc/static/codewalk.html
new file mode 100644
index 0000000..0f3d22a
--- /dev/null
+++ b/godoc/static/codewalk.html
@@ -0,0 +1,56 @@
+<!--
+	Copyright 2010 The Go Authors. All rights reserved.
+	Use of this source code is governed by a BSD-style
+	license that can be found in the LICENSE file.
+-->
+
+<style type='text/css'>@import "/doc/codewalk/codewalk.css";</style>
+<script type="text/javascript" src="/doc/codewalk/codewalk.js"></script>
+
+<div id="codewalk-main">
+  <div class="left" id="code-column">
+    <div id='sizer'></div>
+    <div id="code-area">
+      <div id="code-header" align="center">
+        <a id="code-popout-link" href="" target="_blank">
+          <img title="View code in new window" alt="Pop Out Code" src="/doc/codewalk/popout.png" style="display: block; float: right;"/>
+        </a>
+        <select id="code-selector">
+          {{range .File}}
+          <option value="/doc/codewalk/?fileprint=/{{urlquery .}}">{{html .}}</option>
+          {{end}}
+        </select>
+      </div>
+      <div id="code">
+        <iframe class="code-display" name="code-display" id="code-display"></iframe>
+      </div>
+    </div>
+    <div id="code-options" class="setting">
+      <span>code on <a id="set-code-left" class="selected" href="#">left</a> &bull; <a id="set-code-right" href="#">right</a></span>
+      <span>code width <span id="code-column-width">70%</span></span>
+      <span>filepaths <a id="show-filepaths" class="selected" href="#">shown</a> &bull; <a id="hide-filepaths" href="#">hidden</a></span>
+    </div>
+  </div>
+  <div class="right" id="comment-column">
+    <div id="comment-area">
+      {{range .Step}}
+      <div class="comment first last">
+        <a class="comment-link" href="/doc/codewalk/?fileprint=/{{urlquery .File}}&amp;lo={{urlquery .Lo}}&amp;hi={{urlquery .Hi}}#mark" target="code-display"></a>
+        <div class="comment-title">{{html .Title}}</div>
+        <div class="comment-text">
+	{{with .Err}}
+	ERROR LOADING FILE: {{html .}}<br/><br/>
+	{{end}}
+        {{.XML}}
+        </div>
+        <div class="comment-text file-name"><span class="path-file">{{html .}}</span></div>
+      </div>
+      {{end}}
+    </div>
+    <div id="comment-options" class="setting">
+      <a id="prev-comment" href="#"><span class="hotkey">p</span>revious step</a>
+      &bull;
+      <a id="next-comment" href="#"><span class="hotkey">n</span>ext step</a>
+    </div>
+  </div>
+</div>
diff --git a/godoc/static/codewalkdir.html b/godoc/static/codewalkdir.html
new file mode 100644
index 0000000..b7674c6
--- /dev/null
+++ b/godoc/static/codewalkdir.html
@@ -0,0 +1,16 @@
+<!--
+	Copyright 2010 The Go Authors. All rights reserved.
+	Use of this source code is governed by a BSD-style
+	license that can be found in the LICENSE file.
+-->
+
+<table class="layout">
+{{range .}}
+<tr>
+	{{$name_html := html .Name}}
+	<td><a href="{{$name_html}}">{{$name_html}}</a></td>
+	<td width="25">&nbsp;</td>
+	<td>{{html .Title}}</td>
+</tr>
+{{end}}
+</table>
diff --git a/godoc/static/dirlist.html b/godoc/static/dirlist.html
new file mode 100644
index 0000000..a3e1a2f
--- /dev/null
+++ b/godoc/static/dirlist.html
@@ -0,0 +1,31 @@
+<!--
+	Copyright 2009 The Go Authors. All rights reserved.
+	Use of this source code is governed by a BSD-style
+	license that can be found in the LICENSE file.
+-->
+
+<p>
+<table class="layout">
+<tr>
+	<th align="left">File</th>
+	<td width="25">&nbsp;</td>
+	<th align="right">Bytes</th>
+	<td width="25">&nbsp;</td>
+	<th align="left">Modified</th>
+</tr>
+<tr>
+	<td><a href="..">..</a></td>
+</tr>
+{{range .}}
+<tr>
+	{{$name_html := fileInfoName . | html}}
+	<td align="left"><a href="{{$name_html}}">{{$name_html}}</a></td>
+	<td></td>
+	<td align="right">{{html .Size}}</td>
+	<td></td>
+	<td align="left">{{fileInfoTime . | html}}</td>
+</tr>
+{{end}}
+
+</table>
+</p>
diff --git a/godoc/static/doc.go b/godoc/static/doc.go
new file mode 100644
index 0000000..b3d8bcf
--- /dev/null
+++ b/godoc/static/doc.go
@@ -0,0 +1,8 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package static exports a map of static file content that supports the godoc
+// user interface. The map should be used with the mapfs package, see
+// golang.org/x/tools/godoc/vfs/mapfs.
+package static // import "golang.org/x/tools/godoc/static"
diff --git a/godoc/static/error.html b/godoc/static/error.html
new file mode 100644
index 0000000..7573aa2
--- /dev/null
+++ b/godoc/static/error.html
@@ -0,0 +1,9 @@
+<!--
+	Copyright 2009 The Go Authors. All rights reserved.
+	Use of this source code is governed by a BSD-style
+	license that can be found in the LICENSE file.
+-->
+
+<p>
+<span class="alert" style="font-size:120%">{{html .}}</span>
+</p>
diff --git a/godoc/static/example.html b/godoc/static/example.html
new file mode 100644
index 0000000..cda2a84
--- /dev/null
+++ b/godoc/static/example.html
@@ -0,0 +1,28 @@
+<div id="example_{{.Name}}" class="toggle">
+	<div class="collapsed">
+		<p class="exampleHeading toggleButton">▹ <span class="text">Example{{example_suffix .Name}}</span></p>
+	</div>
+	<div class="expanded">
+		<p class="exampleHeading toggleButton">▾ <span class="text">Example{{example_suffix .Name}}</span></p>
+		{{with .Doc}}<p>{{html .}}</p>{{end}}
+		{{$output := .Output}}
+		{{with .Play}}
+			<div class="play">
+				<div class="input"><textarea class="code">{{html .}}</textarea></div>
+				<div class="output"><pre>{{html $output}}</pre></div>
+				<div class="buttons">
+					<a class="run" title="Run this code [shift-enter]">Run</a>
+					<a class="fmt" title="Format this code">Format</a>
+					<a class="share" title="Share this code">Share</a>
+				</div>
+			</div>
+		{{else}}
+			<p>Code:</p>
+			<pre class="code">{{.Code}}</pre>
+			{{with .Output}}
+			<p>Output:</p>
+			<pre class="output">{{html .}}</pre>
+			{{end}}
+		{{end}}
+	</div>
+</div>
diff --git a/godoc/static/gen.go b/godoc/static/gen.go
new file mode 100644
index 0000000..4226821
--- /dev/null
+++ b/godoc/static/gen.go
@@ -0,0 +1,7 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package static
+
+//go:generate go run makestatic.go
diff --git a/godoc/static/godoc.html b/godoc/static/godoc.html
new file mode 100644
index 0000000..6d6d1b6
--- /dev/null
+++ b/godoc/static/godoc.html
@@ -0,0 +1,105 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<meta name="viewport" content="width=device-width, initial-scale=1">
+<meta name="theme-color" content="#375EAB">
+{{with .Tabtitle}}
+  <title>{{html .}} - The Go Programming Language</title>
+{{else}}
+  <title>The Go Programming Language</title>
+{{end}}
+<link type="text/css" rel="stylesheet" href="/lib/godoc/style.css">
+{{if .SearchBox}}
+<link rel="search" type="application/opensearchdescription+xml" title="godoc" href="/opensearch.xml" />
+{{end}}
+<link rel="stylesheet" href="/lib/godoc/jquery.treeview.css">
+<script type="text/javascript">window.initFuncs = [];</script>
+</head>
+<body>
+
+<div id='lowframe' style="position: fixed; bottom: 0; left: 0; height: 0; width: 100%; border-top: thin solid grey; background-color: white; overflow: auto;">
+...
+</div><!-- #lowframe -->
+
+<div id="topbar"{{if .Title}} class="wide"{{end}}><div class="container">
+<div class="top-heading" id="heading-wide"><a href="/">The Go Programming Language</a></div>
+<div class="top-heading" id="heading-narrow"><a href="/">Go</a></div>
+<a href="#" id="menu-button"><span id="menu-button-arrow">&#9661;</span></a>
+<form method="GET" action="/search">
+<div id="menu">
+<a href="/doc/">Documents</a>
+<a href="/pkg/">Packages</a>
+<a href="/project/">The Project</a>
+<a href="/help/">Help</a>
+<a href="/blog/">Blog</a>
+{{if .Playground}}
+<a id="playgroundButton" href="http://play.golang.org/" title="Show Go Playground">Play</a>
+{{end}}
+<input type="text" id="search" name="q" class="inactive" value="Search" placeholder="Search">
+</div>
+</form>
+
+</div></div>
+
+{{if .Playground}}
+<div id="playground" class="play">
+	<div class="input"><textarea class="code">package main
+
+import "fmt"
+
+func main() {
+	fmt.Println("Hello, 世界")
+}</textarea></div>
+	<div class="output"></div>
+	<div class="buttons">
+		<a class="run" title="Run this code [shift-enter]">Run</a>
+		<a class="fmt" title="Format this code">Format</a>
+		<a class="share" title="Share this code">Share</a>
+	</div>
+</div>
+{{end}}
+
+<div id="page"{{if .Title}} class="wide"{{end}}>
+<div class="container">
+
+{{with .Title}}
+  <h1>{{html .}}</h1>
+{{end}}
+{{with .Subtitle}}
+  <h2>{{html .}}</h2>
+{{end}}
+
+{{/* The Table of Contents is automatically inserted in this <div>.
+     Do not delete this <div>. */}}
+<div id="nav"></div>
+
+{{/* Body is HTML-escaped elsewhere */}}
+{{printf "%s" .Body}}
+
+<div id="footer">
+Build version {{html .Version}}.<br>
+Except as <a href="https://developers.google.com/site-policies#restrictions">noted</a>,
+the content of this page is licensed under the
+Creative Commons Attribution 3.0 License,
+and code is licensed under a <a href="/LICENSE">BSD license</a>.<br>
+<a href="/doc/tos.html">Terms of Service</a> | 
+<a href="http://www.google.com/intl/en/policies/privacy/">Privacy Policy</a>
+</div>
+
+</div><!-- .container -->
+</div><!-- #page -->
+
+<!-- TODO(adonovan): load these from <head> using "defer" attribute? -->
+<script type="text/javascript" src="/lib/godoc/jquery.js"></script>
+<script type="text/javascript" src="/lib/godoc/jquery.treeview.js"></script>
+<script type="text/javascript" src="/lib/godoc/jquery.treeview.edit.js"></script>
+
+{{if .Playground}}
+<script type="text/javascript" src="/lib/godoc/playground.js"></script>
+{{end}}
+<script type="text/javascript" src="/lib/godoc/godocs.js"></script>
+
+</body>
+</html>
+
diff --git a/godoc/static/godocs.js b/godoc/static/godocs.js
new file mode 100644
index 0000000..47d1de9
--- /dev/null
+++ b/godoc/static/godocs.js
@@ -0,0 +1,567 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+/* A little code to ease navigation of these documents.
+ *
+ * On window load we:
+ *  + Bind search box hint placeholder show/hide events (bindSearchEvents)
+ *  + Generate a table of contents (generateTOC)
+ *  + Bind foldable sections (bindToggles)
+ *  + Bind links to foldable sections (bindToggleLinks)
+ */
+
+(function() {
+'use strict';
+
+// Mobile-friendly topbar menu
+$(function() {
+  var menu = $('#menu');
+  var menuButton = $('#menu-button');
+  var menuButtonArrow = $('#menu-button-arrow');
+  menuButton.click(function(event) {
+    menu.toggleClass('menu-visible');
+    menuButtonArrow.toggleClass('vertical-flip');
+    event.preventDefault();
+    return false;
+  });
+});
+
+function bindSearchEvents() {
+
+  var search = $('#search');
+  if (search.length === 0) {
+    return; // no search box
+  }
+
+  function clearInactive() {
+    if (search.is('.inactive')) {
+      search.val('');
+      search.removeClass('inactive');
+    }
+  }
+
+  function restoreInactive() {
+    if (search.val() !== '') {
+      return;
+    }
+    search.val(search.attr('placeholder'));
+    search.addClass('inactive');
+  }
+
+  search.on('focus', clearInactive);
+  search.on('blur', restoreInactive);
+
+  restoreInactive();
+}
+
+/* Generates a table of contents: looks for h2 and h3 elements and generates
+ * links. "Decorates" the element with id=="nav" with this table of contents.
+ */
+function generateTOC() {
+  if ($('#manual-nav').length > 0) {
+    return;
+  }
+
+  var nav = $('#nav');
+  if (nav.length === 0) {
+    return;
+  }
+
+  var toc_items = [];
+  $(nav).nextAll('h2, h3').each(function() {
+    var node = this;
+    if (node.id == '')
+      node.id = 'tmp_' + toc_items.length;
+    var link = $('<a/>').attr('href', '#' + node.id).text($(node).text());
+    var item;
+    if ($(node).is('h2')) {
+      item = $('<dt/>');
+    } else { // h3
+      item = $('<dd class="indent"/>');
+    }
+    item.append(link);
+    toc_items.push(item);
+  });
+  if (toc_items.length <= 1) {
+    return;
+  }
+
+  var dl1 = $('<dl/>');
+  var dl2 = $('<dl/>');
+
+  var split_index = (toc_items.length / 2) + 1;
+  if (split_index < 8) {
+    split_index = toc_items.length;
+  }
+  for (var i = 0; i < split_index; i++) {
+    dl1.append(toc_items[i]);
+  }
+  for (/* keep using i */; i < toc_items.length; i++) {
+    dl2.append(toc_items[i]);
+  }
+
+  var tocTable = $('<table class="unruled"/>').appendTo(nav);
+  var tocBody = $('<tbody/>').appendTo(tocTable);
+  var tocRow = $('<tr/>').appendTo(tocBody);
+
+  // 1st column
+  $('<td class="first"/>').appendTo(tocRow).append(dl1);
+  // 2nd column
+  $('<td/>').appendTo(tocRow).append(dl2);
+}
+
+function bindToggle(el) {
+  $('.toggleButton', el).click(function() {
+    if ($(el).is('.toggle')) {
+      $(el).addClass('toggleVisible').removeClass('toggle');
+    } else {
+      $(el).addClass('toggle').removeClass('toggleVisible');
+    }
+  });
+}
+function bindToggles(selector) {
+  $(selector).each(function(i, el) {
+    bindToggle(el);
+  });
+}
+
+function bindToggleLink(el, prefix) {
+  $(el).click(function() {
+    var href = $(el).attr('href');
+    var i = href.indexOf('#'+prefix);
+    if (i < 0) {
+      return;
+    }
+    var id = '#' + prefix + href.slice(i+1+prefix.length);
+    if ($(id).is('.toggle')) {
+      $(id).find('.toggleButton').first().click();
+    }
+  });
+}
+function bindToggleLinks(selector, prefix) {
+  $(selector).each(function(i, el) {
+    bindToggleLink(el, prefix);
+  });
+}
+
+function setupDropdownPlayground() {
+  if (!$('#page').is('.wide')) {
+    return; // don't show on front page
+  }
+  var button = $('#playgroundButton');
+  var div = $('#playground');
+  var setup = false;
+  button.toggle(function() {
+    button.addClass('active');
+    div.show();
+    if (setup) {
+      return;
+    }
+    setup = true;
+    playground({
+      'codeEl': $('.code', div),
+      'outputEl': $('.output', div),
+      'runEl': $('.run', div),
+      'fmtEl': $('.fmt', div),
+      'shareEl': $('.share', div),
+      'shareRedirect': '//play.golang.org/p/'
+    });
+  },
+  function() {
+    button.removeClass('active');
+    div.hide();
+  });
+  button.show();
+  $('#menu').css('min-width', '+=60');
+}
+
+function setupInlinePlayground() {
+	'use strict';
+	// Set up playground when each element is toggled.
+	$('div.play').each(function (i, el) {
+		// Set up playground for this example.
+		var setup = function() {
+			var code = $('.code', el);
+			playground({
+				'codeEl':   code,
+				'outputEl': $('.output', el),
+				'runEl':    $('.run', el),
+				'fmtEl':    $('.fmt', el),
+				'shareEl':  $('.share', el),
+				'shareRedirect': '//play.golang.org/p/'
+			});
+
+			// Make the code textarea resize to fit content.
+			var resize = function() {
+				code.height(0);
+				var h = code[0].scrollHeight;
+				code.height(h+20); // minimize bouncing.
+				code.closest('.input').height(h);
+			};
+			code.on('keydown', resize);
+			code.on('keyup', resize);
+			code.keyup(); // resize now.
+		};
+		
+		// If example already visible, set up playground now.
+		if ($(el).is(':visible')) {
+			setup();
+			return;
+		}
+
+		// Otherwise, set up playground when example is expanded.
+		var built = false;
+		$(el).closest('.toggle').click(function() {
+			// Only set up once.
+			if (!built) {
+				setup();
+				built = true;
+			}
+		});
+	});
+}
+
+// fixFocus tries to put focus to div#page so that keyboard navigation works.
+function fixFocus() {
+  var page = $('div#page');
+  var topbar = $('div#topbar');
+  page.css('outline', 0); // disable outline when focused
+  page.attr('tabindex', -1); // and set tabindex so that it is focusable
+  $(window).resize(function (evt) {
+    // only focus page when the topbar is at fixed position (that is, it's in
+    // front of page, and keyboard event will go to the former by default.)
+    // by focusing page, keyboard event will go to page so that up/down arrow,
+    // space, etc. will work as expected.
+    if (topbar.css('position') == "fixed")
+      page.focus();
+  }).resize();
+}
+
+function toggleHash() {
+    var hash = $(window.location.hash);
+    if (hash.is('.toggle')) {
+      hash.find('.toggleButton').first().click();
+    }
+}
+
+function personalizeInstallInstructions() {
+  var prefix = '?download=';
+  var s = window.location.search;
+  if (!s.startsWith(prefix)) {
+    // No 'download' query string; bail.
+    return;
+  }
+
+  var filename = s.substr(prefix.length);
+  var filenameRE = /^go1\.\d+(\.\d+)?([a-z0-9]+)?\.([a-z0-9]+)(-[a-z0-9]+)?(-osx10\.[68])?\.([a-z.]+)$/;
+  $('.downloadFilename').text(filename);
+  $('.hideFromDownload').hide();
+  var m = filenameRE.exec(filename);
+  if (!m) {
+    // Can't interpret file name; bail.
+    return;
+  }
+
+  var os = m[3];
+  var ext = m[6];
+  if (ext != 'tar.gz') {
+    $('#tarballInstructions').hide();
+  }
+  if (os != 'darwin' || ext != 'pkg') {
+    $('#darwinPackageInstructions').hide();
+  }
+  if (os != 'windows') {
+    $('#windowsInstructions').hide();
+  } else {
+    if (ext != 'msi') {
+      $('#windowsInstallerInstructions').hide();
+    }
+    if (ext != 'zip') {
+      $('#windowsZipInstructions').hide();
+    }
+  }
+
+  var download = "https://storage.googleapis.com/golang/" + filename;
+
+  var message = $('<p class="downloading">'+
+    'Your download should begin shortly. '+
+    'If it does not, click <a>this link</a>.</p>');
+  message.find('a').attr('href', download);
+  message.insertAfter('#nav');
+
+  window.location = download;
+}
+
+$(document).ready(function() {
+  bindSearchEvents();
+  generateTOC();
+  bindToggles(".toggle");
+  bindToggles(".toggleVisible");
+  bindToggleLinks(".exampleLink", "example_");
+  bindToggleLinks(".overviewLink", "");
+  bindToggleLinks(".examplesLink", "");
+  bindToggleLinks(".indexLink", "");
+  setupDropdownPlayground();
+  setupInlinePlayground();
+  fixFocus();
+  setupTypeInfo();
+  setupCallgraphs();
+  toggleHash();
+  personalizeInstallInstructions();
+
+  // godoc.html defines window.initFuncs in the <head> tag, and root.html and
+  // codewalk.js push their on-page-ready functions to the list.
+  // We execute those functions here, to avoid loading jQuery until the page
+  // content is loaded.
+  for (var i = 0; i < window.initFuncs.length; i++) window.initFuncs[i]();
+});
+
+// -- analysis ---------------------------------------------------------
+
+// escapeHTML returns HTML for s, with metacharacters quoted.
+// It is safe for use in both elements and attributes
+// (unlike the "set innerText, read innerHTML" trick).
+function escapeHTML(s) {
+    return s.replace(/&/g, '&amp;').
+             replace(/\"/g, '&quot;').
+             replace(/\'/g, '&#39;').
+             replace(/</g, '&lt;').
+             replace(/>/g, '&gt;');
+}
+
+// makeAnchor returns HTML for an <a> element, given an anchorJSON object.
+function makeAnchor(json) {
+  var html = escapeHTML(json.Text);
+  if (json.Href != "") {
+      html = "<a href='" + escapeHTML(json.Href) + "'>" + html + "</a>";
+  }
+  return html;
+}
+
+function showLowFrame(html) {
+  var lowframe = document.getElementById('lowframe');
+  lowframe.style.height = "200px";
+  lowframe.innerHTML = "<p style='text-align: left;'>" + html + "</p>\n" +
+      "<div onclick='hideLowFrame()' style='position: absolute; top: 0; right: 0; cursor: pointer;'>✘</div>"
+};
+
+document.hideLowFrame = function() {
+  var lowframe = document.getElementById('lowframe');
+  lowframe.style.height = "0px";
+}
+
+// onClickCallers is the onclick action for the 'func' tokens of a
+// function declaration.
+document.onClickCallers = function(index) {
+  var data = document.ANALYSIS_DATA[index]
+  if (data.Callers.length == 1 && data.Callers[0].Sites.length == 1) {
+    document.location = data.Callers[0].Sites[0].Href; // jump to sole caller
+    return;
+  }
+
+  var html = "Callers of <code>" + escapeHTML(data.Callee) + "</code>:<br/>\n";
+  for (var i = 0; i < data.Callers.length; i++) {
+    var caller = data.Callers[i];
+    html += "<code>" + escapeHTML(caller.Func) + "</code>";
+    var sites = caller.Sites;
+    if (sites != null && sites.length > 0) {
+      html += " at line ";
+      for (var j = 0; j < sites.length; j++) {
+        if (j > 0) {
+          html += ", ";
+        }
+        html += "<code>" + makeAnchor(sites[j]) + "</code>";
+      }
+    }
+    html += "<br/>\n";
+  }
+  showLowFrame(html);
+};
+
+// onClickCallees is the onclick action for the '(' token of a function call.
+document.onClickCallees = function(index) {
+  var data = document.ANALYSIS_DATA[index]
+  if (data.Callees.length == 1) {
+    document.location = data.Callees[0].Href; // jump to sole callee
+    return;
+  }
+
+  var html = "Callees of this " + escapeHTML(data.Descr) + ":<br/>\n";
+  for (var i = 0; i < data.Callees.length; i++) {
+    html += "<code>" + makeAnchor(data.Callees[i]) + "</code><br/>\n";
+  }
+  showLowFrame(html);
+};
+
+// onClickTypeInfo is the onclick action for identifiers declaring a named type.
+document.onClickTypeInfo = function(index) {
+  var data = document.ANALYSIS_DATA[index];
+  var html = "Type <code>" + data.Name + "</code>: " +
+  "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<small>(size=" + data.Size + ", align=" + data.Align + ")</small><br/>\n";
+  html += implementsHTML(data);
+  html += methodsetHTML(data);
+  showLowFrame(html);
+};
+
+// implementsHTML returns HTML for the implements relation of the
+// specified TypeInfoJSON value.
+function implementsHTML(info) {
+  var html = "";
+  if (info.ImplGroups != null) {
+    for (var i = 0; i < info.ImplGroups.length; i++) {
+      var group = info.ImplGroups[i];
+      var x = "<code>" + escapeHTML(group.Descr) + "</code> ";
+      for (var j = 0; j < group.Facts.length; j++) {
+        var fact = group.Facts[j];
+        var y = "<code>" + makeAnchor(fact.Other) + "</code>";
+        if (fact.ByKind != null) {
+          html += escapeHTML(fact.ByKind) + " type " + y + " implements " + x;
+        } else {
+          html += x + " implements " + y;
+        }
+        html += "<br/>\n";
+      }
+    }
+  }
+  return html;
+}
+
+
+// methodsetHTML returns HTML for the methodset of the specified
+// TypeInfoJSON value.
+function methodsetHTML(info) {
+  var html = "";
+  if (info.Methods != null) {
+    for (var i = 0; i < info.Methods.length; i++) {
+      html += "<code>" + makeAnchor(info.Methods[i]) + "</code><br/>\n";
+    }
+  }
+  return html;
+}
+
+// onClickComm is the onclick action for channel "make" and "<-"
+// send/receive tokens.
+document.onClickComm = function(index) {
+  var ops = document.ANALYSIS_DATA[index].Ops
+  if (ops.length == 1) {
+    document.location = ops[0].Op.Href; // jump to sole element
+    return;
+  }
+
+  var html = "Operations on this channel:<br/>\n";
+  for (var i = 0; i < ops.length; i++) {
+    html += makeAnchor(ops[i].Op) + " by <code>" + escapeHTML(ops[i].Fn) + "</code><br/>\n";
+  }
+  if (ops.length == 0) {
+    html += "(none)<br/>\n";
+  }
+  showLowFrame(html);
+};
+
+$(window).load(function() {
+    // Scroll window so that first selection is visible.
+    // (This means we don't need to emit id='L%d' spans for each line.)
+    // TODO(adonovan): ideally, scroll it so that it's under the pointer,
+    // but I don't know how to get the pointer y coordinate.
+    var elts = document.getElementsByClassName("selection");
+    if (elts.length > 0) {
+	elts[0].scrollIntoView()
+    }
+});
+
+// setupTypeInfo populates the "Implements" and "Method set" toggle for
+// each type in the package doc.
+function setupTypeInfo() {
+  for (var i in document.ANALYSIS_DATA) {
+    var data = document.ANALYSIS_DATA[i];
+
+    var el = document.getElementById("implements-" + i);
+    if (el != null) {
+      // el != null => data is TypeInfoJSON.
+      if (data.ImplGroups != null) {
+        el.innerHTML = implementsHTML(data);
+        el.parentNode.parentNode.style.display = "block";
+      }
+    }
+
+    var el = document.getElementById("methodset-" + i);
+    if (el != null) {
+      // el != null => data is TypeInfoJSON.
+      if (data.Methods != null) {
+        el.innerHTML = methodsetHTML(data);
+        el.parentNode.parentNode.style.display = "block";
+      }
+    }
+  }
+}
+
+function setupCallgraphs() {
+  if (document.CALLGRAPH == null) {
+    return
+  }
+  document.getElementById("pkg-callgraph").style.display = "block";
+
+  var treeviews = document.getElementsByClassName("treeview");
+  for (var i = 0; i < treeviews.length; i++) {
+    var tree = treeviews[i];
+    if (tree.id == null || tree.id.indexOf("callgraph-") != 0) {
+      continue;
+    }
+    var id = tree.id.substring("callgraph-".length);
+    $(tree).treeview({collapsed: true, animated: "fast"});
+    document.cgAddChildren(tree, tree, [id]);
+    tree.parentNode.parentNode.style.display = "block";
+  }
+}
+
+document.cgAddChildren = function(tree, ul, indices) {
+  if (indices != null) {
+    for (var i = 0; i < indices.length; i++) {
+      var li = cgAddChild(tree, ul, document.CALLGRAPH[indices[i]]);
+      if (i == indices.length - 1) {
+        $(li).addClass("last");
+      }
+    }
+  }
+  $(tree).treeview({animated: "fast", add: ul});
+}
+
+// cgAddChild adds an <li> element for document.CALLGRAPH node cgn to
+// the parent <ul> element ul. tree is the tree's root <ul> element.
+function cgAddChild(tree, ul, cgn) {
+   var li = document.createElement("li");
+   ul.appendChild(li);
+   li.className = "closed";
+
+   var code = document.createElement("code");
+
+   if (cgn.Callees != null) {
+     $(li).addClass("expandable");
+
+     // Event handlers and innerHTML updates don't play nicely together,
+     // hence all this explicit DOM manipulation.
+     var hitarea = document.createElement("div");
+     hitarea.className = "hitarea expandable-hitarea";
+     li.appendChild(hitarea);
+
+     li.appendChild(code);
+
+     var childUL = document.createElement("ul");
+     li.appendChild(childUL);
+     childUL.setAttribute('style', "display: none;");
+
+     var onClick = function() {
+       document.cgAddChildren(tree, childUL, cgn.Callees);
+       hitarea.removeEventListener('click', onClick)
+     };
+     hitarea.addEventListener('click', onClick);
+
+   } else {
+     li.appendChild(code);
+   }
+   code.innerHTML += "&nbsp;" + makeAnchor(cgn.Func);
+   return li
+}
+
+})();
diff --git a/godoc/static/images/minus.gif b/godoc/static/images/minus.gif
new file mode 100644
index 0000000..47fb7b7
--- /dev/null
+++ b/godoc/static/images/minus.gif
Binary files differ
diff --git a/godoc/static/images/plus.gif b/godoc/static/images/plus.gif
new file mode 100644
index 0000000..6906621
--- /dev/null
+++ b/godoc/static/images/plus.gif
Binary files differ
diff --git a/godoc/static/images/treeview-black-line.gif b/godoc/static/images/treeview-black-line.gif
new file mode 100644
index 0000000..e549687
--- /dev/null
+++ b/godoc/static/images/treeview-black-line.gif
Binary files differ
diff --git a/godoc/static/images/treeview-black.gif b/godoc/static/images/treeview-black.gif
new file mode 100644
index 0000000..b718d17
--- /dev/null
+++ b/godoc/static/images/treeview-black.gif
Binary files differ
diff --git a/godoc/static/images/treeview-default-line.gif b/godoc/static/images/treeview-default-line.gif
new file mode 100644
index 0000000..37114d3
--- /dev/null
+++ b/godoc/static/images/treeview-default-line.gif
Binary files differ
diff --git a/godoc/static/images/treeview-default.gif b/godoc/static/images/treeview-default.gif
new file mode 100644
index 0000000..76eee60
--- /dev/null
+++ b/godoc/static/images/treeview-default.gif
Binary files differ
diff --git a/godoc/static/images/treeview-gray-line.gif b/godoc/static/images/treeview-gray-line.gif
new file mode 100644
index 0000000..3760044
--- /dev/null
+++ b/godoc/static/images/treeview-gray-line.gif
Binary files differ
diff --git a/godoc/static/images/treeview-gray.gif b/godoc/static/images/treeview-gray.gif
new file mode 100644
index 0000000..cfdf1ab
--- /dev/null
+++ b/godoc/static/images/treeview-gray.gif
Binary files differ
diff --git a/godoc/static/implements.html b/godoc/static/implements.html
new file mode 100644
index 0000000..5f65b86
--- /dev/null
+++ b/godoc/static/implements.html
@@ -0,0 +1,9 @@
+<div class="toggle" style="display: none">
+	<div class="collapsed">
+		<p class="exampleHeading toggleButton">▹ <span class="text">Implements</span></p>
+	</div>
+	<div class="expanded">
+		<p class="exampleHeading toggleButton">▾ <span class="text">Implements</span></p>
+		<div style="margin-left: 1in" id='implements-{{.Index}}'>...</div>
+	</div>
+</div>
diff --git a/godoc/static/jquery.js b/godoc/static/jquery.js
new file mode 100644
index 0000000..bc3fbc8
--- /dev/null
+++ b/godoc/static/jquery.js
@@ -0,0 +1,2 @@
+/*! jQuery v1.8.2 jquery.com | jquery.org/license */
+(function(a,b){function G(a){var b=F[a]={};return p.each(a.split(s),function(a,c){b[c]=!0}),b}function J(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(I,"-$1").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:+d+""===d?+d:H.test(d)?p.parseJSON(d):d}catch(f){}p.data(a,c,d)}else d=b}return d}function K(a){var b;for(b in a){if(b==="data"&&p.isEmptyObject(a[b]))continue;if(b!=="toJSON")return!1}return!0}function ba(){return!1}function bb(){return!0}function bh(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function bi(a,b){do a=a[b];while(a&&a.nodeType!==1);return a}function bj(a,b,c){b=b||0;if(p.isFunction(b))return p.grep(a,function(a,d){var e=!!b.call(a,d,a);return e===c});if(b.nodeType)return p.grep(a,function(a,d){return a===b===c});if(typeof b=="string"){var d=p.grep(a,function(a){return a.nodeType===1});if(be.test(b))return p.filter(b,d,!c);b=p.filter(b,d)}return p.grep(a,function(a,d){return p.inArray(a,b)>=0===c})}function bk(a){var b=bl.split("|"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}function bC(a,b){return a.getElementsByTagName(b)[0]||a.appendChild(a.ownerDocument.createElement(b))}function bD(a,b){if(b.nodeType!==1||!p.hasData(a))return;var c,d,e,f=p._data(a),g=p._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;d<e;d++)p.event.add(b,c,h[c][d])}g.data&&(g.data=p.extend({},g.data))}function bE(a,b){var c;if(b.nodeType!==1)return;b.clearAttributes&&b.clearAttributes(),b.mergeAttributes&&b.mergeAttributes(a),c=b.nodeName.toLowerCase(),c==="object"?(b.parentNode&&(b.outerHTML=a.outerHTML),p.support.html5Clone&&a.innerHTML&&!p.trim(b.innerHTML)&&(b.innerHTML=a.innerHTML)):c==="input"&&bv.test(a.type)?(b.defaultChecked=b.checked=a.checked,b.value!==a.value&&(b.value=a.value)):c==="option"?b.selected=a.defaultSelected:c==="input"||c==="textarea"?b.defaultValue=a.defaultValue:c==="script"&&b.text!==a.text&&(b.text=a.text),b.removeAttribute(p.expando)}function bF(a){return typeof a.getElementsByTagName!="undefined"?a.getElementsByTagName("*"):typeof a.querySelectorAll!="undefined"?a.querySelectorAll("*"):[]}function bG(a){bv.test(a.type)&&(a.defaultChecked=a.checked)}function bY(a,b){if(b in a)return b;var c=b.charAt(0).toUpperCase()+b.slice(1),d=b,e=bW.length;while(e--){b=bW[e]+c;if(b in a)return b}return d}function bZ(a,b){return a=b||a,p.css(a,"display")==="none"||!p.contains(a.ownerDocument,a)}function b$(a,b){var c,d,e=[],f=0,g=a.length;for(;f<g;f++){c=a[f];if(!c.style)continue;e[f]=p._data(c,"olddisplay"),b?(!e[f]&&c.style.display==="none"&&(c.style.display=""),c.style.display===""&&bZ(c)&&(e[f]=p._data(c,"olddisplay",cc(c.nodeName)))):(d=bH(c,"display"),!e[f]&&d!=="none"&&p._data(c,"olddisplay",d))}for(f=0;f<g;f++){c=a[f];if(!c.style)continue;if(!b||c.style.display==="none"||c.style.display==="")c.style.display=b?e[f]||"":"none"}return a}function b_(a,b,c){var d=bP.exec(b);return d?Math.max(0,d[1]-(c||0))+(d[2]||"px"):b}function ca(a,b,c,d){var e=c===(d?"border":"content")?4:b==="width"?1:0,f=0;for(;e<4;e+=2)c==="margin"&&(f+=p.css(a,c+bV[e],!0)),d?(c==="content"&&(f-=parseFloat(bH(a,"padding"+bV[e]))||0),c!=="margin"&&(f-=parseFloat(bH(a,"border"+bV[e]+"Width"))||0)):(f+=parseFloat(bH(a,"padding"+bV[e]))||0,c!=="padding"&&(f+=parseFloat(bH(a,"border"+bV[e]+"Width"))||0));return f}function cb(a,b,c){var d=b==="width"?a.offsetWidth:a.offsetHeight,e=!0,f=p.support.boxSizing&&p.css(a,"boxSizing")==="border-box";if(d<=0||d==null){d=bH(a,b);if(d<0||d==null)d=a.style[b];if(bQ.test(d))return d;e=f&&(p.support.boxSizingReliable||d===a.style[b]),d=parseFloat(d)||0}return d+ca(a,b,c||(f?"border":"content"),e)+"px"}function cc(a){if(bS[a])return bS[a];var b=p("<"+a+">").appendTo(e.body),c=b.css("display");b.remove();if(c==="none"||c===""){bI=e.body.appendChild(bI||p.extend(e.createElement("iframe"),{frameBorder:0,width:0,height:0}));if(!bJ||!bI.createElement)bJ=(bI.contentWindow||bI.contentDocument).document,bJ.write("<!doctype html><html><body>"),bJ.close();b=bJ.body.appendChild(bJ.createElement(a)),c=bH(b,"display"),e.body.removeChild(bI)}return bS[a]=c,c}function ci(a,b,c,d){var e;if(p.isArray(b))p.each(b,function(b,e){c||ce.test(a)?d(a,e):ci(a+"["+(typeof e=="object"?b:"")+"]",e,c,d)});else if(!c&&p.type(b)==="object")for(e in b)ci(a+"["+e+"]",b[e],c,d);else d(a,b)}function cz(a){return function(b,c){typeof b!="string"&&(c=b,b="*");var d,e,f,g=b.toLowerCase().split(s),h=0,i=g.length;if(p.isFunction(c))for(;h<i;h++)d=g[h],f=/^\+/.test(d),f&&(d=d.substr(1)||"*"),e=a[d]=a[d]||[],e[f?"unshift":"push"](c)}}function cA(a,c,d,e,f,g){f=f||c.dataTypes[0],g=g||{},g[f]=!0;var h,i=a[f],j=0,k=i?i.length:0,l=a===cv;for(;j<k&&(l||!h);j++)h=i[j](c,d,e),typeof h=="string"&&(!l||g[h]?h=b:(c.dataTypes.unshift(h),h=cA(a,c,d,e,h,g)));return(l||!h)&&!g["*"]&&(h=cA(a,c,d,e,"*",g)),h}function cB(a,c){var d,e,f=p.ajaxSettings.flatOptions||{};for(d in c)c[d]!==b&&((f[d]?a:e||(e={}))[d]=c[d]);e&&p.extend(!0,a,e)}function cC(a,c,d){var e,f,g,h,i=a.contents,j=a.dataTypes,k=a.responseFields;for(f in k)f in d&&(c[k[f]]=d[f]);while(j[0]==="*")j.shift(),e===b&&(e=a.mimeType||c.getResponseHeader("content-type"));if(e)for(f in i)if(i[f]&&i[f].test(e)){j.unshift(f);break}if(j[0]in d)g=j[0];else{for(f in d){if(!j[0]||a.converters[f+" "+j[0]]){g=f;break}h||(h=f)}g=g||h}if(g)return g!==j[0]&&j.unshift(g),d[g]}function cD(a,b){var c,d,e,f,g=a.dataTypes.slice(),h=g[0],i={},j=0;a.dataFilter&&(b=a.dataFilter(b,a.dataType));if(g[1])for(c in a.converters)i[c.toLowerCase()]=a.converters[c];for(;e=g[++j];)if(e!=="*"){if(h!=="*"&&h!==e){c=i[h+" "+e]||i["* "+e];if(!c)for(d in i){f=d.split(" ");if(f[1]===e){c=i[h+" "+f[0]]||i["* "+f[0]];if(c){c===!0?c=i[d]:i[d]!==!0&&(e=f[0],g.splice(j--,0,e));break}}}if(c!==!0)if(c&&a["throws"])b=c(b);else try{b=c(b)}catch(k){return{state:"parsererror",error:c?k:"No conversion from "+h+" to "+e}}}h=e}return{state:"success",data:b}}function cL(){try{return new a.XMLHttpRequest}catch(b){}}function cM(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function cU(){return setTimeout(function(){cN=b},0),cN=p.now()}function cV(a,b){p.each(b,function(b,c){var d=(cT[b]||[]).concat(cT["*"]),e=0,f=d.length;for(;e<f;e++)if(d[e].call(a,b,c))return})}function cW(a,b,c){var d,e=0,f=0,g=cS.length,h=p.Deferred().always(function(){delete i.elem}),i=function(){var b=cN||cU(),c=Math.max(0,j.startTime+j.duration-b),d=1-(c/j.duration||0),e=0,f=j.tweens.length;for(;e<f;e++)j.tweens[e].run(d);return h.notifyWith(a,[j,d,c]),d<1&&f?c:(h.resolveWith(a,[j]),!1)},j=h.promise({elem:a,props:p.extend({},b),opts:p.extend(!0,{specialEasing:{}},c),originalProperties:b,originalOptions:c,startTime:cN||cU(),duration:c.duration,tweens:[],createTween:function(b,c,d){var e=p.Tween(a,j.opts,b,c,j.opts.specialEasing[b]||j.opts.easing);return j.tweens.push(e),e},stop:function(b){var c=0,d=b?j.tweens.length:0;for(;c<d;c++)j.tweens[c].run(1);return b?h.resolveWith(a,[j,b]):h.rejectWith(a,[j,b]),this}}),k=j.props;cX(k,j.opts.specialEasing);for(;e<g;e++){d=cS[e].call(j,a,k,j.opts);if(d)return d}return cV(j,k),p.isFunction(j.opts.start)&&j.opts.start.call(a,j),p.fx.timer(p.extend(i,{anim:j,queue:j.opts.queue,elem:a})),j.progress(j.opts.progress).done(j.opts.done,j.opts.complete).fail(j.opts.fail).always(j.opts.always)}function cX(a,b){var c,d,e,f,g;for(c in a){d=p.camelCase(c),e=b[d],f=a[c],p.isArray(f)&&(e=f[1],f=a[c]=f[0]),c!==d&&(a[d]=f,delete a[c]),g=p.cssHooks[d];if(g&&"expand"in g){f=g.expand(f),delete a[d];for(c in f)c in a||(a[c]=f[c],b[c]=e)}else b[d]=e}}function cY(a,b,c){var d,e,f,g,h,i,j,k,l=this,m=a.style,n={},o=[],q=a.nodeType&&bZ(a);c.queue||(j=p._queueHooks(a,"fx"),j.unqueued==null&&(j.unqueued=0,k=j.empty.fire,j.empty.fire=function(){j.unqueued||k()}),j.unqueued++,l.always(function(){l.always(function(){j.unqueued--,p.queue(a,"fx").length||j.empty.fire()})})),a.nodeType===1&&("height"in b||"width"in b)&&(c.overflow=[m.overflow,m.overflowX,m.overflowY],p.css(a,"display")==="inline"&&p.css(a,"float")==="none"&&(!p.support.inlineBlockNeedsLayout||cc(a.nodeName)==="inline"?m.display="inline-block":m.zoom=1)),c.overflow&&(m.overflow="hidden",p.support.shrinkWrapBlocks||l.done(function(){m.overflow=c.overflow[0],m.overflowX=c.overflow[1],m.overflowY=c.overflow[2]}));for(d in b){f=b[d];if(cP.exec(f)){delete b[d];if(f===(q?"hide":"show"))continue;o.push(d)}}g=o.length;if(g){h=p._data(a,"fxshow")||p._data(a,"fxshow",{}),q?p(a).show():l.done(function(){p(a).hide()}),l.done(function(){var b;p.removeData(a,"fxshow",!0);for(b in n)p.style(a,b,n[b])});for(d=0;d<g;d++)e=o[d],i=l.createTween(e,q?h[e]:0),n[e]=h[e]||p.style(a,e),e in h||(h[e]=i.start,q&&(i.end=i.start,i.start=e==="width"||e==="height"?1:0))}}function cZ(a,b,c,d,e){return new cZ.prototype.init(a,b,c,d,e)}function c$(a,b){var c,d={height:a},e=0;b=b?1:0;for(;e<4;e+=2-b)c=bV[e],d["margin"+c]=d["padding"+c]=a;return b&&(d.opacity=d.width=a),d}function da(a){return p.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}var c,d,e=a.document,f=a.location,g=a.navigator,h=a.jQuery,i=a.$,j=Array.prototype.push,k=Array.prototype.slice,l=Array.prototype.indexOf,m=Object.prototype.toString,n=Object.prototype.hasOwnProperty,o=String.prototype.trim,p=function(a,b){return new p.fn.init(a,b,c)},q=/[\-+]?(?:\d*\.|)\d+(?:[eE][\-+]?\d+|)/.source,r=/\S/,s=/\s+/,t=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,u=/^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,v=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,w=/^[\],:{}\s]*$/,x=/(?:^|:|,)(?:\s*\[)+/g,y=/\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,z=/"[^"\\\r\n]*"|true|false|null|-?(?:\d\d*\.|)\d+(?:[eE][\-+]?\d+|)/g,A=/^-ms-/,B=/-([\da-z])/gi,C=function(a,b){return(b+"").toUpperCase()},D=function(){e.addEventListener?(e.removeEventListener("DOMContentLoaded",D,!1),p.ready()):e.readyState==="complete"&&(e.detachEvent("onreadystatechange",D),p.ready())},E={};p.fn=p.prototype={constructor:p,init:function(a,c,d){var f,g,h,i;if(!a)return this;if(a.nodeType)return this.context=this[0]=a,this.length=1,this;if(typeof a=="string"){a.charAt(0)==="<"&&a.charAt(a.length-1)===">"&&a.length>=3?f=[null,a,null]:f=u.exec(a);if(f&&(f[1]||!c)){if(f[1])return c=c instanceof p?c[0]:c,i=c&&c.nodeType?c.ownerDocument||c:e,a=p.parseHTML(f[1],i,!0),v.test(f[1])&&p.isPlainObject(c)&&this.attr.call(a,c,!0),p.merge(this,a);g=e.getElementById(f[2]);if(g&&g.parentNode){if(g.id!==f[2])return d.find(a);this.length=1,this[0]=g}return this.context=e,this.selector=a,this}return!c||c.jquery?(c||d).find(a):this.constructor(c).find(a)}return p.isFunction(a)?d.ready(a):(a.selector!==b&&(this.selector=a.selector,this.context=a.context),p.makeArray(a,this))},selector:"",jquery:"1.8.2",length:0,size:function(){return this.length},toArray:function(){return k.call(this)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=p.merge(this.constructor(),a);return d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")"),d},each:function(a,b){return p.each(this,a,b)},ready:function(a){return p.ready.promise().done(a),this},eq:function(a){return a=+a,a===-1?this.slice(a):this.slice(a,a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(k.apply(this,arguments),"slice",k.call(arguments).join(","))},map:function(a){return this.pushStack(p.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:j,sort:[].sort,splice:[].splice},p.fn.init.prototype=p.fn,p.extend=p.fn.extend=function(){var a,c,d,e,f,g,h=arguments[0]||{},i=1,j=arguments.length,k=!1;typeof h=="boolean"&&(k=h,h=arguments[1]||{},i=2),typeof h!="object"&&!p.isFunction(h)&&(h={}),j===i&&(h=this,--i);for(;i<j;i++)if((a=arguments[i])!=null)for(c in a){d=h[c],e=a[c];if(h===e)continue;k&&e&&(p.isPlainObject(e)||(f=p.isArray(e)))?(f?(f=!1,g=d&&p.isArray(d)?d:[]):g=d&&p.isPlainObject(d)?d:{},h[c]=p.extend(k,g,e)):e!==b&&(h[c]=e)}return h},p.extend({noConflict:function(b){return a.$===p&&(a.$=i),b&&a.jQuery===p&&(a.jQuery=h),p},isReady:!1,readyWait:1,holdReady:function(a){a?p.readyWait++:p.ready(!0)},ready:function(a){if(a===!0?--p.readyWait:p.isReady)return;if(!e.body)return setTimeout(p.ready,1);p.isReady=!0;if(a!==!0&&--p.readyWait>0)return;d.resolveWith(e,[p]),p.fn.trigger&&p(e).trigger("ready").off("ready")},isFunction:function(a){return p.type(a)==="function"},isArray:Array.isArray||function(a){return p.type(a)==="array"},isWindow:function(a){return a!=null&&a==a.window},isNumeric:function(a){return!isNaN(parseFloat(a))&&isFinite(a)},type:function(a){return a==null?String(a):E[m.call(a)]||"object"},isPlainObject:function(a){if(!a||p.type(a)!=="object"||a.nodeType||p.isWindow(a))return!1;try{if(a.constructor&&!n.call(a,"constructor")&&!n.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}var d;for(d in a);return d===b||n.call(a,d)},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},error:function(a){throw new Error(a)},parseHTML:function(a,b,c){var d;return!a||typeof a!="string"?null:(typeof b=="boolean"&&(c=b,b=0),b=b||e,(d=v.exec(a))?[b.createElement(d[1])]:(d=p.buildFragment([a],b,c?null:[]),p.merge([],(d.cacheable?p.clone(d.fragment):d.fragment).childNodes)))},parseJSON:function(b){if(!b||typeof b!="string")return null;b=p.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(w.test(b.replace(y,"@").replace(z,"]").replace(x,"")))return(new Function("return "+b))();p.error("Invalid JSON: "+b)},parseXML:function(c){var d,e;if(!c||typeof c!="string")return null;try{a.DOMParser?(e=new DOMParser,d=e.parseFromString(c,"text/xml")):(d=new ActiveXObject("Microsoft.XMLDOM"),d.async="false",d.loadXML(c))}catch(f){d=b}return(!d||!d.documentElement||d.getElementsByTagName("parsererror").length)&&p.error("Invalid XML: "+c),d},noop:function(){},globalEval:function(b){b&&r.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(A,"ms-").replace(B,C)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,c,d){var e,f=0,g=a.length,h=g===b||p.isFunction(a);if(d){if(h){for(e in a)if(c.apply(a[e],d)===!1)break}else for(;f<g;)if(c.apply(a[f++],d)===!1)break}else if(h){for(e in a)if(c.call(a[e],e,a[e])===!1)break}else for(;f<g;)if(c.call(a[f],f,a[f++])===!1)break;return a},trim:o&&!o.call(" ")?function(a){return a==null?"":o.call(a)}:function(a){return a==null?"":(a+"").replace(t,"")},makeArray:function(a,b){var c,d=b||[];return a!=null&&(c=p.type(a),a.length==null||c==="string"||c==="function"||c==="regexp"||p.isWindow(a)?j.call(d,a):p.merge(d,a)),d},inArray:function(a,b,c){var d;if(b){if(l)return l.call(b,a,c);d=b.length,c=c?c<0?Math.max(0,d+c):c:0;for(;c<d;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,c){var d=c.length,e=a.length,f=0;if(typeof d=="number")for(;f<d;f++)a[e++]=c[f];else while(c[f]!==b)a[e++]=c[f++];return a.length=e,a},grep:function(a,b,c){var d,e=[],f=0,g=a.length;c=!!c;for(;f<g;f++)d=!!b(a[f],f),c!==d&&e.push(a[f]);return e},map:function(a,c,d){var e,f,g=[],h=0,i=a.length,j=a instanceof p||i!==b&&typeof i=="number"&&(i>0&&a[0]&&a[i-1]||i===0||p.isArray(a));if(j)for(;h<i;h++)e=c(a[h],h,d),e!=null&&(g[g.length]=e);else for(f in a)e=c(a[f],f,d),e!=null&&(g[g.length]=e);return g.concat.apply([],g)},guid:1,proxy:function(a,c){var d,e,f;return typeof c=="string"&&(d=a[c],c=a,a=d),p.isFunction(a)?(e=k.call(arguments,2),f=function(){return a.apply(c,e.concat(k.call(arguments)))},f.guid=a.guid=a.guid||p.guid++,f):b},access:function(a,c,d,e,f,g,h){var i,j=d==null,k=0,l=a.length;if(d&&typeof d=="object"){for(k in d)p.access(a,c,k,d[k],1,g,e);f=1}else if(e!==b){i=h===b&&p.isFunction(e),j&&(i?(i=c,c=function(a,b,c){return i.call(p(a),c)}):(c.call(a,e),c=null));if(c)for(;k<l;k++)c(a[k],d,i?e.call(a[k],k,c(a[k],d)):e,h);f=1}return f?a:j?c.call(a):l?c(a[0],d):g},now:function(){return(new Date).getTime()}}),p.ready.promise=function(b){if(!d){d=p.Deferred();if(e.readyState==="complete")setTimeout(p.ready,1);else if(e.addEventListener)e.addEventListener("DOMContentLoaded",D,!1),a.addEventListener("load",p.ready,!1);else{e.attachEvent("onreadystatechange",D),a.attachEvent("onload",p.ready);var c=!1;try{c=a.frameElement==null&&e.documentElement}catch(f){}c&&c.doScroll&&function g(){if(!p.isReady){try{c.doScroll("left")}catch(a){return setTimeout(g,50)}p.ready()}}()}}return d.promise(b)},p.each("Boolean Number String Function Array Date RegExp Object".split(" "),function(a,b){E["[object "+b+"]"]=b.toLowerCase()}),c=p(e);var F={};p.Callbacks=function(a){a=typeof a=="string"?F[a]||G(a):p.extend({},a);var c,d,e,f,g,h,i=[],j=!a.once&&[],k=function(b){c=a.memory&&b,d=!0,h=f||0,f=0,g=i.length,e=!0;for(;i&&h<g;h++)if(i[h].apply(b[0],b[1])===!1&&a.stopOnFalse){c=!1;break}e=!1,i&&(j?j.length&&k(j.shift()):c?i=[]:l.disable())},l={add:function(){if(i){var b=i.length;(function d(b){p.each(b,function(b,c){var e=p.type(c);e==="function"&&(!a.unique||!l.has(c))?i.push(c):c&&c.length&&e!=="string"&&d(c)})})(arguments),e?g=i.length:c&&(f=b,k(c))}return this},remove:function(){return i&&p.each(arguments,function(a,b){var c;while((c=p.inArray(b,i,c))>-1)i.splice(c,1),e&&(c<=g&&g--,c<=h&&h--)}),this},has:function(a){return p.inArray(a,i)>-1},empty:function(){return i=[],this},disable:function(){return i=j=c=b,this},disabled:function(){return!i},lock:function(){return j=b,c||l.disable(),this},locked:function(){return!j},fireWith:function(a,b){return b=b||[],b=[a,b.slice?b.slice():b],i&&(!d||j)&&(e?j.push(b):k(b)),this},fire:function(){return l.fireWith(this,arguments),this},fired:function(){return!!d}};return l},p.extend({Deferred:function(a){var b=[["resolve","done",p.Callbacks("once memory"),"resolved"],["reject","fail",p.Callbacks("once memory"),"rejected"],["notify","progress",p.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return p.Deferred(function(c){p.each(b,function(b,d){var f=d[0],g=a[b];e[d[1]](p.isFunction(g)?function(){var a=g.apply(this,arguments);a&&p.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f+"With"](this===e?c:this,[a])}:c[f])}),a=null}).promise()},promise:function(a){return a!=null?p.extend(a,d):d}},e={};return d.pipe=d.then,p.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[a^1][2].disable,b[2][2].lock),e[f[0]]=g.fire,e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=k.call(arguments),d=c.length,e=d!==1||a&&p.isFunction(a.promise)?d:0,f=e===1?a:p.Deferred(),g=function(a,b,c){return function(d){b[a]=this,c[a]=arguments.length>1?k.call(arguments):d,c===h?f.notifyWith(b,c):--e||f.resolveWith(b,c)}},h,i,j;if(d>1){h=new Array(d),i=new Array(d),j=new Array(d);for(;b<d;b++)c[b]&&p.isFunction(c[b].promise)?c[b].promise().done(g(b,j,c)).fail(f.reject).progress(g(b,i,h)):--e}return e||f.resolveWith(j,c),f.promise()}}),p.support=function(){var b,c,d,f,g,h,i,j,k,l,m,n=e.createElement("div");n.setAttribute("className","t"),n.innerHTML="  <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",c=n.getElementsByTagName("*"),d=n.getElementsByTagName("a")[0],d.style.cssText="top:1px;float:left;opacity:.5";if(!c||!c.length)return{};f=e.createElement("select"),g=f.appendChild(e.createElement("option")),h=n.getElementsByTagName("input")[0],b={leadingWhitespace:n.firstChild.nodeType===3,tbody:!n.getElementsByTagName("tbody").length,htmlSerialize:!!n.getElementsByTagName("link").length,style:/top/.test(d.getAttribute("style")),hrefNormalized:d.getAttribute("href")==="/a",opacity:/^0.5/.test(d.style.opacity),cssFloat:!!d.style.cssFloat,checkOn:h.value==="on",optSelected:g.selected,getSetAttribute:n.className!=="t",enctype:!!e.createElement("form").enctype,html5Clone:e.createElement("nav").cloneNode(!0).outerHTML!=="<:nav></:nav>",boxModel:e.compatMode==="CSS1Compat",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0,boxSizingReliable:!0,pixelPosition:!1},h.checked=!0,b.noCloneChecked=h.cloneNode(!0).checked,f.disabled=!0,b.optDisabled=!g.disabled;try{delete n.test}catch(o){b.deleteExpando=!1}!n.addEventListener&&n.attachEvent&&n.fireEvent&&(n.attachEvent("onclick",m=function(){b.noCloneEvent=!1}),n.cloneNode(!0).fireEvent("onclick"),n.detachEvent("onclick",m)),h=e.createElement("input"),h.value="t",h.setAttribute("type","radio"),b.radioValue=h.value==="t",h.setAttribute("checked","checked"),h.setAttribute("name","t"),n.appendChild(h),i=e.createDocumentFragment(),i.appendChild(n.lastChild),b.checkClone=i.cloneNode(!0).cloneNode(!0).lastChild.checked,b.appendChecked=h.checked,i.removeChild(h),i.appendChild(n);if(n.attachEvent)for(k in{submit:!0,change:!0,focusin:!0})j="on"+k,l=j in n,l||(n.setAttribute(j,"return;"),l=typeof n[j]=="function"),b[k+"Bubbles"]=l;return p(function(){var c,d,f,g,h="padding:0;margin:0;border:0;display:block;overflow:hidden;",i=e.getElementsByTagName("body")[0];if(!i)return;c=e.createElement("div"),c.style.cssText="visibility:hidden;border:0;width:0;height:0;position:static;top:0;margin-top:1px",i.insertBefore(c,i.firstChild),d=e.createElement("div"),c.appendChild(d),d.innerHTML="<table><tr><td></td><td>t</td></tr></table>",f=d.getElementsByTagName("td"),f[0].style.cssText="padding:0;margin:0;border:0;display:none",l=f[0].offsetHeight===0,f[0].style.display="",f[1].style.display="none",b.reliableHiddenOffsets=l&&f[0].offsetHeight===0,d.innerHTML="",d.style.cssText="box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;",b.boxSizing=d.offsetWidth===4,b.doesNotIncludeMarginInBodyOffset=i.offsetTop!==1,a.getComputedStyle&&(b.pixelPosition=(a.getComputedStyle(d,null)||{}).top!=="1%",b.boxSizingReliable=(a.getComputedStyle(d,null)||{width:"4px"}).width==="4px",g=e.createElement("div"),g.style.cssText=d.style.cssText=h,g.style.marginRight=g.style.width="0",d.style.width="1px",d.appendChild(g),b.reliableMarginRight=!parseFloat((a.getComputedStyle(g,null)||{}).marginRight)),typeof d.style.zoom!="undefined"&&(d.innerHTML="",d.style.cssText=h+"width:1px;padding:1px;display:inline;zoom:1",b.inlineBlockNeedsLayout=d.offsetWidth===3,d.style.display="block",d.style.overflow="visible",d.innerHTML="<div></div>",d.firstChild.style.width="5px",b.shrinkWrapBlocks=d.offsetWidth!==3,c.style.zoom=1),i.removeChild(c),c=d=f=g=null}),i.removeChild(n),c=d=f=g=h=i=n=null,b}();var H=/(?:\{[\s\S]*\}|\[[\s\S]*\])$/,I=/([A-Z])/g;p.extend({cache:{},deletedIds:[],uuid:0,expando:"jQuery"+(p.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){return a=a.nodeType?p.cache[a[p.expando]]:a[p.expando],!!a&&!K(a)},data:function(a,c,d,e){if(!p.acceptData(a))return;var f,g,h=p.expando,i=typeof c=="string",j=a.nodeType,k=j?p.cache:a,l=j?a[h]:a[h]&&h;if((!l||!k[l]||!e&&!k[l].data)&&i&&d===b)return;l||(j?a[h]=l=p.deletedIds.pop()||p.guid++:l=h),k[l]||(k[l]={},j||(k[l].toJSON=p.noop));if(typeof c=="object"||typeof c=="function")e?k[l]=p.extend(k[l],c):k[l].data=p.extend(k[l].data,c);return f=k[l],e||(f.data||(f.data={}),f=f.data),d!==b&&(f[p.camelCase(c)]=d),i?(g=f[c],g==null&&(g=f[p.camelCase(c)])):g=f,g},removeData:function(a,b,c){if(!p.acceptData(a))return;var d,e,f,g=a.nodeType,h=g?p.cache:a,i=g?a[p.expando]:p.expando;if(!h[i])return;if(b){d=c?h[i]:h[i].data;if(d){p.isArray(b)||(b in d?b=[b]:(b=p.camelCase(b),b in d?b=[b]:b=b.split(" ")));for(e=0,f=b.length;e<f;e++)delete d[b[e]];if(!(c?K:p.isEmptyObject)(d))return}}if(!c){delete h[i].data;if(!K(h[i]))return}g?p.cleanData([a],!0):p.support.deleteExpando||h!=h.window?delete h[i]:h[i]=null},_data:function(a,b,c){return p.data(a,b,c,!0)},acceptData:function(a){var b=a.nodeName&&p.noData[a.nodeName.toLowerCase()];return!b||b!==!0&&a.getAttribute("classid")===b}}),p.fn.extend({data:function(a,c){var d,e,f,g,h,i=this[0],j=0,k=null;if(a===b){if(this.length){k=p.data(i);if(i.nodeType===1&&!p._data(i,"parsedAttrs")){f=i.attributes;for(h=f.length;j<h;j++)g=f[j].name,g.indexOf("data-")||(g=p.camelCase(g.substring(5)),J(i,g,k[g]));p._data(i,"parsedAttrs",!0)}}return k}return typeof a=="object"?this.each(function(){p.data(this,a)}):(d=a.split(".",2),d[1]=d[1]?"."+d[1]:"",e=d[1]+"!",p.access(this,function(c){if(c===b)return k=this.triggerHandler("getData"+e,[d[0]]),k===b&&i&&(k=p.data(i,a),k=J(i,a,k)),k===b&&d[1]?this.data(d[0]):k;d[1]=c,this.each(function(){var b=p(this);b.triggerHandler("setData"+e,d),p.data(this,a,c),b.triggerHandler("changeData"+e,d)})},null,c,arguments.length>1,null,!1))},removeData:function(a){return this.each(function(){p.removeData(this,a)})}}),p.extend({queue:function(a,b,c){var d;if(a)return b=(b||"fx")+"queue",d=p._data(a,b),c&&(!d||p.isArray(c)?d=p._data(a,b,p.makeArray(c)):d.push(c)),d||[]},dequeue:function(a,b){b=b||"fx";var c=p.queue(a,b),d=c.length,e=c.shift(),f=p._queueHooks(a,b),g=function(){p.dequeue(a,b)};e==="inprogress"&&(e=c.shift(),d--),e&&(b==="fx"&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return p._data(a,c)||p._data(a,c,{empty:p.Callbacks("once memory").add(function(){p.removeData(a,b+"queue",!0),p.removeData(a,c,!0)})})}}),p.fn.extend({queue:function(a,c){var d=2;return typeof a!="string"&&(c=a,a="fx",d--),arguments.length<d?p.queue(this[0],a):c===b?this:this.each(function(){var b=p.queue(this,a,c);p._queueHooks(this,a),a==="fx"&&b[0]!=="inprogress"&&p.dequeue(this,a)})},dequeue:function(a){return this.each(function(){p.dequeue(this,a)})},delay:function(a,b){return a=p.fx?p.fx.speeds[a]||a:a,b=b||"fx",this.queue(b,function(b,c){var d=setTimeout(b,a);c.stop=function(){clearTimeout(d)}})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,c){var d,e=1,f=p.Deferred(),g=this,h=this.length,i=function(){--e||f.resolveWith(g,[g])};typeof a!="string"&&(c=a,a=b),a=a||"fx";while(h--)d=p._data(g[h],a+"queueHooks"),d&&d.empty&&(e++,d.empty.add(i));return i(),f.promise(c)}});var L,M,N,O=/[\t\r\n]/g,P=/\r/g,Q=/^(?:button|input)$/i,R=/^(?:button|input|object|select|textarea)$/i,S=/^a(?:rea|)$/i,T=/^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,U=p.support.getSetAttribute;p.fn.extend({attr:function(a,b){return p.access(this,p.attr,a,b,arguments.length>1)},removeAttr:function(a){return this.each(function(){p.removeAttr(this,a)})},prop:function(a,b){return p.access(this,p.prop,a,b,arguments.length>1)},removeProp:function(a){return a=p.propFix[a]||a,this.each(function(){try{this[a]=b,delete this[a]}catch(c){}})},addClass:function(a){var b,c,d,e,f,g,h;if(p.isFunction(a))return this.each(function(b){p(this).addClass(a.call(this,b,this.className))});if(a&&typeof a=="string"){b=a.split(s);for(c=0,d=this.length;c<d;c++){e=this[c];if(e.nodeType===1)if(!e.className&&b.length===1)e.className=a;else{f=" "+e.className+" ";for(g=0,h=b.length;g<h;g++)f.indexOf(" "+b[g]+" ")<0&&(f+=b[g]+" ");e.className=p.trim(f)}}}return this},removeClass:function(a){var c,d,e,f,g,h,i;if(p.isFunction(a))return this.each(function(b){p(this).removeClass(a.call(this,b,this.className))});if(a&&typeof a=="string"||a===b){c=(a||"").split(s);for(h=0,i=this.length;h<i;h++){e=this[h];if(e.nodeType===1&&e.className){d=(" "+e.className+" ").replace(O," ");for(f=0,g=c.length;f<g;f++)while(d.indexOf(" "+c[f]+" ")>=0)d=d.replace(" "+c[f]+" "," ");e.className=a?p.trim(d):""}}}return this},toggleClass:function(a,b){var c=typeof a,d=typeof b=="boolean";return p.isFunction(a)?this.each(function(c){p(this).toggleClass(a.call(this,c,this.className,b),b)}):this.each(function(){if(c==="string"){var e,f=0,g=p(this),h=b,i=a.split(s);while(e=i[f++])h=d?h:!g.hasClass(e),g[h?"addClass":"removeClass"](e)}else if(c==="undefined"||c==="boolean")this.className&&p._data(this,"__className__",this.className),this.className=this.className||a===!1?"":p._data(this,"__className__")||""})},hasClass:function(a){var b=" "+a+" ",c=0,d=this.length;for(;c<d;c++)if(this[c].nodeType===1&&(" "+this[c].className+" ").replace(O," ").indexOf(b)>=0)return!0;return!1},val:function(a){var c,d,e,f=this[0];if(!arguments.length){if(f)return c=p.valHooks[f.type]||p.valHooks[f.nodeName.toLowerCase()],c&&"get"in c&&(d=c.get(f,"value"))!==b?d:(d=f.value,typeof d=="string"?d.replace(P,""):d==null?"":d);return}return e=p.isFunction(a),this.each(function(d){var f,g=p(this);if(this.nodeType!==1)return;e?f=a.call(this,d,g.val()):f=a,f==null?f="":typeof f=="number"?f+="":p.isArray(f)&&(f=p.map(f,function(a){return a==null?"":a+""})),c=p.valHooks[this.type]||p.valHooks[this.nodeName.toLowerCase()];if(!c||!("set"in c)||c.set(this,f,"value")===b)this.value=f})}}),p.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c,d,e,f=a.selectedIndex,g=[],h=a.options,i=a.type==="select-one";if(f<0)return null;c=i?f:0,d=i?f+1:h.length;for(;c<d;c++){e=h[c];if(e.selected&&(p.support.optDisabled?!e.disabled:e.getAttribute("disabled")===null)&&(!e.parentNode.disabled||!p.nodeName(e.parentNode,"optgroup"))){b=p(e).val();if(i)return b;g.push(b)}}return i&&!g.length&&h.length?p(h[f]).val():g},set:function(a,b){var c=p.makeArray(b);return p(a).find("option").each(function(){this.selected=p.inArray(p(this).val(),c)>=0}),c.length||(a.selectedIndex=-1),c}}},attrFn:{},attr:function(a,c,d,e){var f,g,h,i=a.nodeType;if(!a||i===3||i===8||i===2)return;if(e&&p.isFunction(p.fn[c]))return p(a)[c](d);if(typeof a.getAttribute=="undefined")return p.prop(a,c,d);h=i!==1||!p.isXMLDoc(a),h&&(c=c.toLowerCase(),g=p.attrHooks[c]||(T.test(c)?M:L));if(d!==b){if(d===null){p.removeAttr(a,c);return}return g&&"set"in g&&h&&(f=g.set(a,d,c))!==b?f:(a.setAttribute(c,d+""),d)}return g&&"get"in g&&h&&(f=g.get(a,c))!==null?f:(f=a.getAttribute(c),f===null?b:f)},removeAttr:function(a,b){var c,d,e,f,g=0;if(b&&a.nodeType===1){d=b.split(s);for(;g<d.length;g++)e=d[g],e&&(c=p.propFix[e]||e,f=T.test(e),f||p.attr(a,e,""),a.removeAttribute(U?e:c),f&&c in a&&(a[c]=!1))}},attrHooks:{type:{set:function(a,b){if(Q.test(a.nodeName)&&a.parentNode)p.error("type property can't be changed");else if(!p.support.radioValue&&b==="radio"&&p.nodeName(a,"input")){var c=a.value;return a.setAttribute("type",b),c&&(a.value=c),b}}},value:{get:function(a,b){return L&&p.nodeName(a,"button")?L.get(a,b):b in a?a.value:null},set:function(a,b,c){if(L&&p.nodeName(a,"button"))return L.set(a,b,c);a.value=b}}},propFix:{tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},prop:function(a,c,d){var e,f,g,h=a.nodeType;if(!a||h===3||h===8||h===2)return;return g=h!==1||!p.isXMLDoc(a),g&&(c=p.propFix[c]||c,f=p.propHooks[c]),d!==b?f&&"set"in f&&(e=f.set(a,d,c))!==b?e:a[c]=d:f&&"get"in f&&(e=f.get(a,c))!==null?e:a[c]},propHooks:{tabIndex:{get:function(a){var c=a.getAttributeNode("tabindex");return c&&c.specified?parseInt(c.value,10):R.test(a.nodeName)||S.test(a.nodeName)&&a.href?0:b}}}}),M={get:function(a,c){var d,e=p.prop(a,c);return e===!0||typeof e!="boolean"&&(d=a.getAttributeNode(c))&&d.nodeValue!==!1?c.toLowerCase():b},set:function(a,b,c){var d;return b===!1?p.removeAttr(a,c):(d=p.propFix[c]||c,d in a&&(a[d]=!0),a.setAttribute(c,c.toLowerCase())),c}},U||(N={name:!0,id:!0,coords:!0},L=p.valHooks.button={get:function(a,c){var d;return d=a.getAttributeNode(c),d&&(N[c]?d.value!=="":d.specified)?d.value:b},set:function(a,b,c){var d=a.getAttributeNode(c);return d||(d=e.createAttribute(c),a.setAttributeNode(d)),d.value=b+""}},p.each(["width","height"],function(a,b){p.attrHooks[b]=p.extend(p.attrHooks[b],{set:function(a,c){if(c==="")return a.setAttribute(b,"auto"),c}})}),p.attrHooks.contenteditable={get:L.get,set:function(a,b,c){b===""&&(b="false"),L.set(a,b,c)}}),p.support.hrefNormalized||p.each(["href","src","width","height"],function(a,c){p.attrHooks[c]=p.extend(p.attrHooks[c],{get:function(a){var d=a.getAttribute(c,2);return d===null?b:d}})}),p.support.style||(p.attrHooks.style={get:function(a){return a.style.cssText.toLowerCase()||b},set:function(a,b){return a.style.cssText=b+""}}),p.support.optSelected||(p.propHooks.selected=p.extend(p.propHooks.selected,{get:function(a){var b=a.parentNode;return b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex),null}})),p.support.enctype||(p.propFix.enctype="encoding"),p.support.checkOn||p.each(["radio","checkbox"],function(){p.valHooks[this]={get:function(a){return a.getAttribute("value")===null?"on":a.value}}}),p.each(["radio","checkbox"],function(){p.valHooks[this]=p.extend(p.valHooks[this],{set:function(a,b){if(p.isArray(b))return a.checked=p.inArray(p(a).val(),b)>=0}})});var V=/^(?:textarea|input|select)$/i,W=/^([^\.]*|)(?:\.(.+)|)$/,X=/(?:^|\s)hover(\.\S+|)\b/,Y=/^key/,Z=/^(?:mouse|contextmenu)|click/,$=/^(?:focusinfocus|focusoutblur)$/,_=function(a){return p.event.special.hover?a:a.replace(X,"mouseenter$1 mouseleave$1")};p.event={add:function(a,c,d,e,f){var g,h,i,j,k,l,m,n,o,q,r;if(a.nodeType===3||a.nodeType===8||!c||!d||!(g=p._data(a)))return;d.handler&&(o=d,d=o.handler,f=o.selector),d.guid||(d.guid=p.guid++),i=g.events,i||(g.events=i={}),h=g.handle,h||(g.handle=h=function(a){return typeof p!="undefined"&&(!a||p.event.triggered!==a.type)?p.event.dispatch.apply(h.elem,arguments):b},h.elem=a),c=p.trim(_(c)).split(" ");for(j=0;j<c.length;j++){k=W.exec(c[j])||[],l=k[1],m=(k[2]||"").split(".").sort(),r=p.event.special[l]||{},l=(f?r.delegateType:r.bindType)||l,r=p.event.special[l]||{},n=p.extend({type:l,origType:k[1],data:e,handler:d,guid:d.guid,selector:f,needsContext:f&&p.expr.match.needsContext.test(f),namespace:m.join(".")},o),q=i[l];if(!q){q=i[l]=[],q.delegateCount=0;if(!r.setup||r.setup.call(a,e,m,h)===!1)a.addEventListener?a.addEventListener(l,h,!1):a.attachEvent&&a.attachEvent("on"+l,h)}r.add&&(r.add.call(a,n),n.handler.guid||(n.handler.guid=d.guid)),f?q.splice(q.delegateCount++,0,n):q.push(n),p.event.global[l]=!0}a=null},global:{},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,n,o,q,r=p.hasData(a)&&p._data(a);if(!r||!(m=r.events))return;b=p.trim(_(b||"")).split(" ");for(f=0;f<b.length;f++){g=W.exec(b[f])||[],h=i=g[1],j=g[2];if(!h){for(h in m)p.event.remove(a,h+b[f],c,d,!0);continue}n=p.event.special[h]||{},h=(d?n.delegateType:n.bindType)||h,o=m[h]||[],k=o.length,j=j?new RegExp("(^|\\.)"+j.split(".").sort().join("\\.(?:.*\\.|)")+"(\\.|$)"):null;for(l=0;l<o.length;l++)q=o[l],(e||i===q.origType)&&(!c||c.guid===q.guid)&&(!j||j.test(q.namespace))&&(!d||d===q.selector||d==="**"&&q.selector)&&(o.splice(l--,1),q.selector&&o.delegateCount--,n.remove&&n.remove.call(a,q));o.length===0&&k!==o.length&&((!n.teardown||n.teardown.call(a,j,r.handle)===!1)&&p.removeEvent(a,h,r.handle),delete m[h])}p.isEmptyObject(m)&&(delete r.handle,p.removeData(a,"events",!0))},customEvent:{getData:!0,setData:!0,changeData:!0},trigger:function(c,d,f,g){if(!f||f.nodeType!==3&&f.nodeType!==8){var h,i,j,k,l,m,n,o,q,r,s=c.type||c,t=[];if($.test(s+p.event.triggered))return;s.indexOf("!")>=0&&(s=s.slice(0,-1),i=!0),s.indexOf(".")>=0&&(t=s.split("."),s=t.shift(),t.sort());if((!f||p.event.customEvent[s])&&!p.event.global[s])return;c=typeof c=="object"?c[p.expando]?c:new p.Event(s,c):new p.Event(s),c.type=s,c.isTrigger=!0,c.exclusive=i,c.namespace=t.join("."),c.namespace_re=c.namespace?new RegExp("(^|\\.)"+t.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,m=s.indexOf(":")<0?"on"+s:"";if(!f){h=p.cache;for(j in h)h[j].events&&h[j].events[s]&&p.event.trigger(c,d,h[j].handle.elem,!0);return}c.result=b,c.target||(c.target=f),d=d!=null?p.makeArray(d):[],d.unshift(c),n=p.event.special[s]||{};if(n.trigger&&n.trigger.apply(f,d)===!1)return;q=[[f,n.bindType||s]];if(!g&&!n.noBubble&&!p.isWindow(f)){r=n.delegateType||s,k=$.test(r+s)?f:f.parentNode;for(l=f;k;k=k.parentNode)q.push([k,r]),l=k;l===(f.ownerDocument||e)&&q.push([l.defaultView||l.parentWindow||a,r])}for(j=0;j<q.length&&!c.isPropagationStopped();j++)k=q[j][0],c.type=q[j][1],o=(p._data(k,"events")||{})[c.type]&&p._data(k,"handle"),o&&o.apply(k,d),o=m&&k[m],o&&p.acceptData(k)&&o.apply&&o.apply(k,d)===!1&&c.preventDefault();return c.type=s,!g&&!c.isDefaultPrevented()&&(!n._default||n._default.apply(f.ownerDocument,d)===!1)&&(s!=="click"||!p.nodeName(f,"a"))&&p.acceptData(f)&&m&&f[s]&&(s!=="focus"&&s!=="blur"||c.target.offsetWidth!==0)&&!p.isWindow(f)&&(l=f[m],l&&(f[m]=null),p.event.triggered=s,f[s](),p.event.triggered=b,l&&(f[m]=l)),c.result}return},dispatch:function(c){c=p.event.fix(c||a.event);var d,e,f,g,h,i,j,l,m,n,o=(p._data(this,"events")||{})[c.type]||[],q=o.delegateCount,r=k.call(arguments),s=!c.exclusive&&!c.namespace,t=p.event.special[c.type]||{},u=[];r[0]=c,c.delegateTarget=this;if(t.preDispatch&&t.preDispatch.call(this,c)===!1)return;if(q&&(!c.button||c.type!=="click"))for(f=c.target;f!=this;f=f.parentNode||this)if(f.disabled!==!0||c.type!=="click"){h={},j=[];for(d=0;d<q;d++)l=o[d],m=l.selector,h[m]===b&&(h[m]=l.needsContext?p(m,this).index(f)>=0:p.find(m,this,null,[f]).length),h[m]&&j.push(l);j.length&&u.push({elem:f,matches:j})}o.length>q&&u.push({elem:this,matches:o.slice(q)});for(d=0;d<u.length&&!c.isPropagationStopped();d++){i=u[d],c.currentTarget=i.elem;for(e=0;e<i.matches.length&&!c.isImmediatePropagationStopped();e++){l=i.matches[e];if(s||!c.namespace&&!l.namespace||c.namespace_re&&c.namespace_re.test(l.namespace))c.data=l.data,c.handleObj=l,g=((p.event.special[l.origType]||{}).handle||l.handler).apply(i.elem,r),g!==b&&(c.result=g,g===!1&&(c.preventDefault(),c.stopPropagation()))}}return t.postDispatch&&t.postDispatch.call(this,c),c.result},props:"attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(a,b){return a.which==null&&(a.which=b.charCode!=null?b.charCode:b.keyCode),a}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(a,c){var d,f,g,h=c.button,i=c.fromElement;return a.pageX==null&&c.clientX!=null&&(d=a.target.ownerDocument||e,f=d.documentElement,g=d.body,a.pageX=c.clientX+(f&&f.scrollLeft||g&&g.scrollLeft||0)-(f&&f.clientLeft||g&&g.clientLeft||0),a.pageY=c.clientY+(f&&f.scrollTop||g&&g.scrollTop||0)-(f&&f.clientTop||g&&g.clientTop||0)),!a.relatedTarget&&i&&(a.relatedTarget=i===a.target?c.toElement:i),!a.which&&h!==b&&(a.which=h&1?1:h&2?3:h&4?2:0),a}},fix:function(a){if(a[p.expando])return a;var b,c,d=a,f=p.event.fixHooks[a.type]||{},g=f.props?this.props.concat(f.props):this.props;a=p.Event(d);for(b=g.length;b;)c=g[--b],a[c]=d[c];return a.target||(a.target=d.srcElement||e),a.target.nodeType===3&&(a.target=a.target.parentNode),a.metaKey=!!a.metaKey,f.filter?f.filter(a,d):a},special:{load:{noBubble:!0},focus:{delegateType:"focusin"},blur:{delegateType:"focusout"},beforeunload:{setup:function(a,b,c){p.isWindow(this)&&(this.onbeforeunload=c)},teardown:function(a,b){this.onbeforeunload===b&&(this.onbeforeunload=null)}}},simulate:function(a,b,c,d){var e=p.extend(new p.Event,c,{type:a,isSimulated:!0,originalEvent:{}});d?p.event.trigger(e,null,b):p.event.dispatch.call(b,e),e.isDefaultPrevented()&&c.preventDefault()}},p.event.handle=p.event.dispatch,p.removeEvent=e.removeEventListener?function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c,!1)}:function(a,b,c){var d="on"+b;a.detachEvent&&(typeof a[d]=="undefined"&&(a[d]=null),a.detachEvent(d,c))},p.Event=function(a,b){if(this instanceof p.Event)a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||a.returnValue===!1||a.getPreventDefault&&a.getPreventDefault()?bb:ba):this.type=a,b&&p.extend(this,b),this.timeStamp=a&&a.timeStamp||p.now(),this[p.expando]=!0;else return new p.Event(a,b)},p.Event.prototype={preventDefault:function(){this.isDefaultPrevented=bb;var a=this.originalEvent;if(!a)return;a.preventDefault?a.preventDefault():a.returnValue=!1},stopPropagation:function(){this.isPropagationStopped=bb;var a=this.originalEvent;if(!a)return;a.stopPropagation&&a.stopPropagation(),a.cancelBubble=!0},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=bb,this.stopPropagation()},isDefaultPrevented:ba,isPropagationStopped:ba,isImmediatePropagationStopped:ba},p.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){p.event.special[a]={delegateType:b,bindType:b,handle:function(a){var c,d=this,e=a.relatedTarget,f=a.handleObj,g=f.selector;if(!e||e!==d&&!p.contains(d,e))a.type=f.origType,c=f.handler.apply(this,arguments),a.type=b;return c}}}),p.support.submitBubbles||(p.event.special.submit={setup:function(){if(p.nodeName(this,"form"))return!1;p.event.add(this,"click._submit keypress._submit",function(a){var c=a.target,d=p.nodeName(c,"input")||p.nodeName(c,"button")?c.form:b;d&&!p._data(d,"_submit_attached")&&(p.event.add(d,"submit._submit",function(a){a._submit_bubble=!0}),p._data(d,"_submit_attached",!0))})},postDispatch:function(a){a._submit_bubble&&(delete a._submit_bubble,this.parentNode&&!a.isTrigger&&p.event.simulate("submit",this.parentNode,a,!0))},teardown:function(){if(p.nodeName(this,"form"))return!1;p.event.remove(this,"._submit")}}),p.support.changeBubbles||(p.event.special.change={setup:function(){if(V.test(this.nodeName)){if(this.type==="checkbox"||this.type==="radio")p.event.add(this,"propertychange._change",function(a){a.originalEvent.propertyName==="checked"&&(this._just_changed=!0)}),p.event.add(this,"click._change",function(a){this._just_changed&&!a.isTrigger&&(this._just_changed=!1),p.event.simulate("change",this,a,!0)});return!1}p.event.add(this,"beforeactivate._change",function(a){var b=a.target;V.test(b.nodeName)&&!p._data(b,"_change_attached")&&(p.event.add(b,"change._change",function(a){this.parentNode&&!a.isSimulated&&!a.isTrigger&&p.event.simulate("change",this.parentNode,a,!0)}),p._data(b,"_change_attached",!0))})},handle:function(a){var b=a.target;if(this!==b||a.isSimulated||a.isTrigger||b.type!=="radio"&&b.type!=="checkbox")return a.handleObj.handler.apply(this,arguments)},teardown:function(){return p.event.remove(this,"._change"),!V.test(this.nodeName)}}),p.support.focusinBubbles||p.each({focus:"focusin",blur:"focusout"},function(a,b){var c=0,d=function(a){p.event.simulate(b,a.target,p.event.fix(a),!0)};p.event.special[b]={setup:function(){c++===0&&e.addEventListener(a,d,!0)},teardown:function(){--c===0&&e.removeEventListener(a,d,!0)}}}),p.fn.extend({on:function(a,c,d,e,f){var g,h;if(typeof a=="object"){typeof c!="string"&&(d=d||c,c=b);for(h in a)this.on(h,c,d,a[h],f);return this}d==null&&e==null?(e=c,d=c=b):e==null&&(typeof c=="string"?(e=d,d=b):(e=d,d=c,c=b));if(e===!1)e=ba;else if(!e)return this;return f===1&&(g=e,e=function(a){return p().off(a),g.apply(this,arguments)},e.guid=g.guid||(g.guid=p.guid++)),this.each(function(){p.event.add(this,a,e,d,c)})},one:function(a,b,c,d){return this.on(a,b,c,d,1)},off:function(a,c,d){var e,f;if(a&&a.preventDefault&&a.handleObj)return e=a.handleObj,p(a.delegateTarget).off(e.namespace?e.origType+"."+e.namespace:e.origType,e.selector,e.handler),this;if(typeof a=="object"){for(f in a)this.off(f,c,a[f]);return this}if(c===!1||typeof c=="function")d=c,c=b;return d===!1&&(d=ba),this.each(function(){p.event.remove(this,a,d,c)})},bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},live:function(a,b,c){return p(this.context).on(a,this.selector,b,c),this},die:function(a,b){return p(this.context).off(a,this.selector||"**",b),this},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return arguments.length===1?this.off(a,"**"):this.off(b,a||"**",c)},trigger:function(a,b){return this.each(function(){p.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0])return p.event.trigger(a,b,this[0],!0)},toggle:function(a){var b=arguments,c=a.guid||p.guid++,d=0,e=function(c){var e=(p._data(this,"lastToggle"+a.guid)||0)%d;return p._data(this,"lastToggle"+a.guid,e+1),c.preventDefault(),b[e].apply(this,arguments)||!1};e.guid=c;while(d<b.length)b[d++].guid=c;return this.click(e)},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}}),p.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(a,b){p.fn[b]=function(a,c){return c==null&&(c=a,a=null),arguments.length>0?this.on(b,null,a,c):this.trigger(b)},Y.test(b)&&(p.event.fixHooks[b]=p.event.keyHooks),Z.test(b)&&(p.event.fixHooks[b]=p.event.mouseHooks)}),function(a,b){function bc(a,b,c,d){c=c||[],b=b||r;var e,f,i,j,k=b.nodeType;if(!a||typeof a!="string")return c;if(k!==1&&k!==9)return[];i=g(b);if(!i&&!d)if(e=P.exec(a))if(j=e[1]){if(k===9){f=b.getElementById(j);if(!f||!f.parentNode)return c;if(f.id===j)return c.push(f),c}else if(b.ownerDocument&&(f=b.ownerDocument.getElementById(j))&&h(b,f)&&f.id===j)return c.push(f),c}else{if(e[2])return w.apply(c,x.call(b.getElementsByTagName(a),0)),c;if((j=e[3])&&_&&b.getElementsByClassName)return w.apply(c,x.call(b.getElementsByClassName(j),0)),c}return bp(a.replace(L,"$1"),b,c,d,i)}function bd(a){return function(b){var c=b.nodeName.toLowerCase();return c==="input"&&b.type===a}}function be(a){return function(b){var c=b.nodeName.toLowerCase();return(c==="input"||c==="button")&&b.type===a}}function bf(a){return z(function(b){return b=+b,z(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function bg(a,b,c){if(a===b)return c;var d=a.nextSibling;while(d){if(d===b)return-1;d=d.nextSibling}return 1}function bh(a,b){var c,d,f,g,h,i,j,k=C[o][a];if(k)return b?0:k.slice(0);h=a,i=[],j=e.preFilter;while(h){if(!c||(d=M.exec(h)))d&&(h=h.slice(d[0].length)),i.push(f=[]);c=!1;if(d=N.exec(h))f.push(c=new q(d.shift())),h=h.slice(c.length),c.type=d[0].replace(L," ");for(g in e.filter)(d=W[g].exec(h))&&(!j[g]||(d=j[g](d,r,!0)))&&(f.push(c=new q(d.shift())),h=h.slice(c.length),c.type=g,c.matches=d);if(!c)break}return b?h.length:h?bc.error(a):C(a,i).slice(0)}function bi(a,b,d){var e=b.dir,f=d&&b.dir==="parentNode",g=u++;return b.first?function(b,c,d){while(b=b[e])if(f||b.nodeType===1)return a(b,c,d)}:function(b,d,h){if(!h){var i,j=t+" "+g+" ",k=j+c;while(b=b[e])if(f||b.nodeType===1){if((i=b[o])===k)return b.sizset;if(typeof i=="string"&&i.indexOf(j)===0){if(b.sizset)return b}else{b[o]=k;if(a(b,d,h))return b.sizset=!0,b;b.sizset=!1}}}else while(b=b[e])if(f||b.nodeType===1)if(a(b,d,h))return b}}function bj(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function bk(a,b,c,d,e){var f,g=[],h=0,i=a.length,j=b!=null;for(;h<i;h++)if(f=a[h])if(!c||c(f,d,e))g.push(f),j&&b.push(h);return g}function bl(a,b,c,d,e,f){return d&&!d[o]&&(d=bl(d)),e&&!e[o]&&(e=bl(e,f)),z(function(f,g,h,i){if(f&&e)return;var j,k,l,m=[],n=[],o=g.length,p=f||bo(b||"*",h.nodeType?[h]:h,[],f),q=a&&(f||!b)?bk(p,m,a,h,i):p,r=c?e||(f?a:o||d)?[]:g:q;c&&c(q,r,h,i);if(d){l=bk(r,n),d(l,[],h,i),j=l.length;while(j--)if(k=l[j])r[n[j]]=!(q[n[j]]=k)}if(f){j=a&&r.length;while(j--)if(k=r[j])f[m[j]]=!(g[m[j]]=k)}else r=bk(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):w.apply(g,r)})}function bm(a){var b,c,d,f=a.length,g=e.relative[a[0].type],h=g||e.relative[" "],i=g?1:0,j=bi(function(a){return a===b},h,!0),k=bi(function(a){return y.call(b,a)>-1},h,!0),m=[function(a,c,d){return!g&&(d||c!==l)||((b=c).nodeType?j(a,c,d):k(a,c,d))}];for(;i<f;i++)if(c=e.relative[a[i].type])m=[bi(bj(m),c)];else{c=e.filter[a[i].type].apply(null,a[i].matches);if(c[o]){d=++i;for(;d<f;d++)if(e.relative[a[d].type])break;return bl(i>1&&bj(m),i>1&&a.slice(0,i-1).join("").replace(L,"$1"),c,i<d&&bm(a.slice(i,d)),d<f&&bm(a=a.slice(d)),d<f&&a.join(""))}m.push(c)}return bj(m)}function bn(a,b){var d=b.length>0,f=a.length>0,g=function(h,i,j,k,m){var n,o,p,q=[],s=0,u="0",x=h&&[],y=m!=null,z=l,A=h||f&&e.find.TAG("*",m&&i.parentNode||i),B=t+=z==null?1:Math.E;y&&(l=i!==r&&i,c=g.el);for(;(n=A[u])!=null;u++){if(f&&n){for(o=0;p=a[o];o++)if(p(n,i,j)){k.push(n);break}y&&(t=B,c=++g.el)}d&&((n=!p&&n)&&s--,h&&x.push(n))}s+=u;if(d&&u!==s){for(o=0;p=b[o];o++)p(x,q,i,j);if(h){if(s>0)while(u--)!x[u]&&!q[u]&&(q[u]=v.call(k));q=bk(q)}w.apply(k,q),y&&!h&&q.length>0&&s+b.length>1&&bc.uniqueSort(k)}return y&&(t=B,l=z),x};return g.el=0,d?z(g):g}function bo(a,b,c,d){var e=0,f=b.length;for(;e<f;e++)bc(a,b[e],c,d);return c}function bp(a,b,c,d,f){var g,h,j,k,l,m=bh(a),n=m.length;if(!d&&m.length===1){h=m[0]=m[0].slice(0);if(h.length>2&&(j=h[0]).type==="ID"&&b.nodeType===9&&!f&&e.relative[h[1].type]){b=e.find.ID(j.matches[0].replace(V,""),b,f)[0];if(!b)return c;a=a.slice(h.shift().length)}for(g=W.POS.test(a)?-1:h.length-1;g>=0;g--){j=h[g];if(e.relative[k=j.type])break;if(l=e.find[k])if(d=l(j.matches[0].replace(V,""),R.test(h[0].type)&&b.parentNode||b,f)){h.splice(g,1),a=d.length&&h.join("");if(!a)return w.apply(c,x.call(d,0)),c;break}}}return i(a,m)(d,b,f,c,R.test(a)),c}function bq(){}var c,d,e,f,g,h,i,j,k,l,m=!0,n="undefined",o=("sizcache"+Math.random()).replace(".",""),q=String,r=a.document,s=r.documentElement,t=0,u=0,v=[].pop,w=[].push,x=[].slice,y=[].indexOf||function(a){var b=0,c=this.length;for(;b<c;b++)if(this[b]===a)return b;return-1},z=function(a,b){return a[o]=b==null||b,a},A=function(){var a={},b=[];return z(function(c,d){return b.push(c)>e.cacheLength&&delete a[b.shift()],a[c]=d},a)},B=A(),C=A(),D=A(),E="[\\x20\\t\\r\\n\\f]",F="(?:\\\\.|[-\\w]|[^\\x00-\\xa0])+",G=F.replace("w","w#"),H="([*^$|!~]?=)",I="\\["+E+"*("+F+")"+E+"*(?:"+H+E+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+G+")|)|)"+E+"*\\]",J=":("+F+")(?:\\((?:(['\"])((?:\\\\.|[^\\\\])*?)\\2|([^()[\\]]*|(?:(?:"+I+")|[^:]|\\\\.)*|.*))\\)|)",K=":(even|odd|eq|gt|lt|nth|first|last)(?:\\("+E+"*((?:-\\d)?\\d*)"+E+"*\\)|)(?=[^-]|$)",L=new RegExp("^"+E+"+|((?:^|[^\\\\])(?:\\\\.)*)"+E+"+$","g"),M=new RegExp("^"+E+"*,"+E+"*"),N=new RegExp("^"+E+"*([\\x20\\t\\r\\n\\f>+~])"+E+"*"),O=new RegExp(J),P=/^(?:#([\w\-]+)|(\w+)|\.([\w\-]+))$/,Q=/^:not/,R=/[\x20\t\r\n\f]*[+~]/,S=/:not\($/,T=/h\d/i,U=/input|select|textarea|button/i,V=/\\(?!\\)/g,W={ID:new RegExp("^#("+F+")"),CLASS:new RegExp("^\\.("+F+")"),NAME:new RegExp("^\\[name=['\"]?("+F+")['\"]?\\]"),TAG:new RegExp("^("+F.replace("w","w*")+")"),ATTR:new RegExp("^"+I),PSEUDO:new RegExp("^"+J),POS:new RegExp(K,"i"),CHILD:new RegExp("^:(only|nth|first|last)-child(?:\\("+E+"*(even|odd|(([+-]|)(\\d*)n|)"+E+"*(?:([+-]|)"+E+"*(\\d+)|))"+E+"*\\)|)","i"),needsContext:new RegExp("^"+E+"*[>+~]|"+K,"i")},X=function(a){var b=r.createElement("div");try{return a(b)}catch(c){return!1}finally{b=null}},Y=X(function(a){return a.appendChild(r.createComment("")),!a.getElementsByTagName("*").length}),Z=X(function(a){return a.innerHTML="<a href='#'></a>",a.firstChild&&typeof a.firstChild.getAttribute!==n&&a.firstChild.getAttribute("href")==="#"}),$=X(function(a){a.innerHTML="<select></select>";var b=typeof a.lastChild.getAttribute("multiple");return b!=="boolean"&&b!=="string"}),_=X(function(a){return a.innerHTML="<div class='hidden e'></div><div class='hidden'></div>",!a.getElementsByClassName||!a.getElementsByClassName("e").length?!1:(a.lastChild.className="e",a.getElementsByClassName("e").length===2)}),ba=X(function(a){a.id=o+0,a.innerHTML="<a name='"+o+"'></a><div name='"+o+"'></div>",s.insertBefore(a,s.firstChild);var b=r.getElementsByName&&r.getElementsByName(o).length===2+r.getElementsByName(o+0).length;return d=!r.getElementById(o),s.removeChild(a),b});try{x.call(s.childNodes,0)[0].nodeType}catch(bb){x=function(a){var b,c=[];for(;b=this[a];a++)c.push(b);return c}}bc.matches=function(a,b){return bc(a,null,null,b)},bc.matchesSelector=function(a,b){return bc(b,null,null,[a]).length>0},f=bc.getText=function(a){var b,c="",d=0,e=a.nodeType;if(e){if(e===1||e===9||e===11){if(typeof a.textContent=="string")return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=f(a)}else if(e===3||e===4)return a.nodeValue}else for(;b=a[d];d++)c+=f(b);return c},g=bc.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?b.nodeName!=="HTML":!1},h=bc.contains=s.contains?function(a,b){var c=a.nodeType===9?a.documentElement:a,d=b&&b.parentNode;return a===d||!!(d&&d.nodeType===1&&c.contains&&c.contains(d))}:s.compareDocumentPosition?function(a,b){return b&&!!(a.compareDocumentPosition(b)&16)}:function(a,b){while(b=b.parentNode)if(b===a)return!0;return!1},bc.attr=function(a,b){var c,d=g(a);return d||(b=b.toLowerCase()),(c=e.attrHandle[b])?c(a):d||$?a.getAttribute(b):(c=a.getAttributeNode(b),c?typeof a[b]=="boolean"?a[b]?b:null:c.specified?c.value:null:null)},e=bc.selectors={cacheLength:50,createPseudo:z,match:W,attrHandle:Z?{}:{href:function(a){return a.getAttribute("href",2)},type:function(a){return a.getAttribute("type")}},find:{ID:d?function(a,b,c){if(typeof b.getElementById!==n&&!c){var d=b.getElementById(a);return d&&d.parentNode?[d]:[]}}:function(a,c,d){if(typeof c.getElementById!==n&&!d){var e=c.getElementById(a);return e?e.id===a||typeof e.getAttributeNode!==n&&e.getAttributeNode("id").value===a?[e]:b:[]}},TAG:Y?function(a,b){if(typeof b.getElementsByTagName!==n)return b.getElementsByTagName(a)}:function(a,b){var c=b.getElementsByTagName(a);if(a==="*"){var d,e=[],f=0;for(;d=c[f];f++)d.nodeType===1&&e.push(d);return e}return c},NAME:ba&&function(a,b){if(typeof b.getElementsByName!==n)return b.getElementsByName(name)},CLASS:_&&function(a,b,c){if(typeof b.getElementsByClassName!==n&&!c)return b.getElementsByClassName(a)}},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(V,""),a[3]=(a[4]||a[5]||"").replace(V,""),a[2]==="~="&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),a[1]==="nth"?(a[2]||bc.error(a[0]),a[3]=+(a[3]?a[4]+(a[5]||1):2*(a[2]==="even"||a[2]==="odd")),a[4]=+(a[6]+a[7]||a[2]==="odd")):a[2]&&bc.error(a[0]),a},PSEUDO:function(a){var b,c;if(W.CHILD.test(a[0]))return null;if(a[3])a[2]=a[3];else if(b=a[4])O.test(b)&&(c=bh(b,!0))&&(c=b.indexOf(")",b.length-c)-b.length)&&(b=b.slice(0,c),a[0]=a[0].slice(0,c)),a[2]=b;return a.slice(0,3)}},filter:{ID:d?function(a){return a=a.replace(V,""),function(b){return b.getAttribute("id")===a}}:function(a){return a=a.replace(V,""),function(b){var c=typeof b.getAttributeNode!==n&&b.getAttributeNode("id");return c&&c.value===a}},TAG:function(a){return a==="*"?function(){return!0}:(a=a.replace(V,"").toLowerCase(),function(b){return b.nodeName&&b.nodeName.toLowerCase()===a})},CLASS:function(a){var b=B[o][a];return b||(b=B(a,new RegExp("(^|"+E+")"+a+"("+E+"|$)"))),function(a){return b.test(a.className||typeof a.getAttribute!==n&&a.getAttribute("class")||"")}},ATTR:function(a,b,c){return function(d,e){var f=bc.attr(d,a);return f==null?b==="!=":b?(f+="",b==="="?f===c:b==="!="?f!==c:b==="^="?c&&f.indexOf(c)===0:b==="*="?c&&f.indexOf(c)>-1:b==="$="?c&&f.substr(f.length-c.length)===c:b==="~="?(" "+f+" ").indexOf(c)>-1:b==="|="?f===c||f.substr(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d){return a==="nth"?function(a){var b,e,f=a.parentNode;if(c===1&&d===0)return!0;if(f){e=0;for(b=f.firstChild;b;b=b.nextSibling)if(b.nodeType===1){e++;if(a===b)break}}return e-=d,e===c||e%c===0&&e/c>=0}:function(b){var c=b;switch(a){case"only":case"first":while(c=c.previousSibling)if(c.nodeType===1)return!1;if(a==="first")return!0;c=b;case"last":while(c=c.nextSibling)if(c.nodeType===1)return!1;return!0}}},PSEUDO:function(a,b){var c,d=e.pseudos[a]||e.setFilters[a.toLowerCase()]||bc.error("unsupported pseudo: "+a);return d[o]?d(b):d.length>1?(c=[a,a,"",b],e.setFilters.hasOwnProperty(a.toLowerCase())?z(function(a,c){var e,f=d(a,b),g=f.length;while(g--)e=y.call(a,f[g]),a[e]=!(c[e]=f[g])}):function(a){return d(a,0,c)}):d}},pseudos:{not:z(function(a){var b=[],c=[],d=i(a.replace(L,"$1"));return d[o]?z(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)if(f=g[h])a[h]=!(b[h]=f)}):function(a,e,f){return b[0]=a,d(b,null,f,c),!c.pop()}}),has:z(function(a){return function(b){return bc(a,b).length>0}}),contains:z(function(a){return function(b){return(b.textContent||b.innerText||f(b)).indexOf(a)>-1}}),enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&!!a.checked||b==="option"&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},parent:function(a){return!e.pseudos.empty(a)},empty:function(a){var b;a=a.firstChild;while(a){if(a.nodeName>"@"||(b=a.nodeType)===3||b===4)return!1;a=a.nextSibling}return!0},header:function(a){return T.test(a.nodeName)},text:function(a){var b,c;return a.nodeName.toLowerCase()==="input"&&(b=a.type)==="text"&&((c=a.getAttribute("type"))==null||c.toLowerCase()===b)},radio:bd("radio"),checkbox:bd("checkbox"),file:bd("file"),password:bd("password"),image:bd("image"),submit:be("submit"),reset:be("reset"),button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&a.type==="button"||b==="button"},input:function(a){return U.test(a.nodeName)},focus:function(a){var b=a.ownerDocument;return a===b.activeElement&&(!b.hasFocus||b.hasFocus())&&(!!a.type||!!a.href)},active:function(a){return a===a.ownerDocument.activeElement},first:bf(function(a,b,c){return[0]}),last:bf(function(a,b,c){return[b-1]}),eq:bf(function(a,b,c){return[c<0?c+b:c]}),even:bf(function(a,b,c){for(var d=0;d<b;d+=2)a.push(d);return a}),odd:bf(function(a,b,c){for(var d=1;d<b;d+=2)a.push(d);return a}),lt:bf(function(a,b,c){for(var d=c<0?c+b:c;--d>=0;)a.push(d);return a}),gt:bf(function(a,b,c){for(var d=c<0?c+b:c;++d<b;)a.push(d);return a})}},j=s.compareDocumentPosition?function(a,b){return a===b?(k=!0,0):(!a.compareDocumentPosition||!b.compareDocumentPosition?a.compareDocumentPosition:a.compareDocumentPosition(b)&4)?-1:1}:function(a,b){if(a===b)return k=!0,0;if(a.sourceIndex&&b.sourceIndex)return a.sourceIndex-b.sourceIndex;var c,d,e=[],f=[],g=a.parentNode,h=b.parentNode,i=g;if(g===h)return bg(a,b);if(!g)return-1;if(!h)return 1;while(i)e.unshift(i),i=i.parentNode;i=h;while(i)f.unshift(i),i=i.parentNode;c=e.length,d=f.length;for(var j=0;j<c&&j<d;j++)if(e[j]!==f[j])return bg(e[j],f[j]);return j===c?bg(a,f[j],-1):bg(e[j],b,1)},[0,0].sort(j),m=!k,bc.uniqueSort=function(a){var b,c=1;k=m,a.sort(j);if(k)for(;b=a[c];c++)b===a[c-1]&&a.splice(c--,1);return a},bc.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},i=bc.compile=function(a,b){var c,d=[],e=[],f=D[o][a];if(!f){b||(b=bh(a)),c=b.length;while(c--)f=bm(b[c]),f[o]?d.push(f):e.push(f);f=D(a,bn(e,d))}return f},r.querySelectorAll&&function(){var a,b=bp,c=/'|\\/g,d=/\=[\x20\t\r\n\f]*([^'"\]]*)[\x20\t\r\n\f]*\]/g,e=[":focus"],f=[":active",":focus"],h=s.matchesSelector||s.mozMatchesSelector||s.webkitMatchesSelector||s.oMatchesSelector||s.msMatchesSelector;X(function(a){a.innerHTML="<select><option selected=''></option></select>",a.querySelectorAll("[selected]").length||e.push("\\["+E+"*(?:checked|disabled|ismap|multiple|readonly|selected|value)"),a.querySelectorAll(":checked").length||e.push(":checked")}),X(function(a){a.innerHTML="<p test=''></p>",a.querySelectorAll("[test^='']").length&&e.push("[*^$]="+E+"*(?:\"\"|'')"),a.innerHTML="<input type='hidden'/>",a.querySelectorAll(":enabled").length||e.push(":enabled",":disabled")}),e=new RegExp(e.join("|")),bp=function(a,d,f,g,h){if(!g&&!h&&(!e||!e.test(a))){var i,j,k=!0,l=o,m=d,n=d.nodeType===9&&a;if(d.nodeType===1&&d.nodeName.toLowerCase()!=="object"){i=bh(a),(k=d.getAttribute("id"))?l=k.replace(c,"\\$&"):d.setAttribute("id",l),l="[id='"+l+"'] ",j=i.length;while(j--)i[j]=l+i[j].join("");m=R.test(a)&&d.parentNode||d,n=i.join(",")}if(n)try{return w.apply(f,x.call(m.querySelectorAll(n),0)),f}catch(p){}finally{k||d.removeAttribute("id")}}return b(a,d,f,g,h)},h&&(X(function(b){a=h.call(b,"div");try{h.call(b,"[test!='']:sizzle"),f.push("!=",J)}catch(c){}}),f=new RegExp(f.join("|")),bc.matchesSelector=function(b,c){c=c.replace(d,"='$1']");if(!g(b)&&!f.test(c)&&(!e||!e.test(c)))try{var i=h.call(b,c);if(i||a||b.document&&b.document.nodeType!==11)return i}catch(j){}return bc(c,null,null,[b]).length>0})}(),e.pseudos.nth=e.pseudos.eq,e.filters=bq.prototype=e.pseudos,e.setFilters=new bq,bc.attr=p.attr,p.find=bc,p.expr=bc.selectors,p.expr[":"]=p.expr.pseudos,p.unique=bc.uniqueSort,p.text=bc.getText,p.isXMLDoc=bc.isXML,p.contains=bc.contains}(a);var bc=/Until$/,bd=/^(?:parents|prev(?:Until|All))/,be=/^.[^:#\[\.,]*$/,bf=p.expr.match.needsContext,bg={children:!0,contents:!0,next:!0,prev:!0};p.fn.extend({find:function(a){var b,c,d,e,f,g,h=this;if(typeof a!="string")return p(a).filter(function(){for(b=0,c=h.length;b<c;b++)if(p.contains(h[b],this))return!0});g=this.pushStack("","find",a);for(b=0,c=this.length;b<c;b++){d=g.length,p.find(a,this[b],g);if(b>0)for(e=d;e<g.length;e++)for(f=0;f<d;f++)if(g[f]===g[e]){g.splice(e--,1);break}}return g},has:function(a){var b,c=p(a,this),d=c.length;return this.filter(function(){for(b=0;b<d;b++)if(p.contains(this,c[b]))return!0})},not:function(a){return this.pushStack(bj(this,a,!1),"not",a)},filter:function(a){return this.pushStack(bj(this,a,!0),"filter",a)},is:function(a){return!!a&&(typeof a=="string"?bf.test(a)?p(a,this.context).index(this[0])>=0:p.filter(a,this).length>0:this.filter(a).length>0)},closest:function(a,b){var c,d=0,e=this.length,f=[],g=bf.test(a)||typeof a!="string"?p(a,b||this.context):0;for(;d<e;d++){c=this[d];while(c&&c.ownerDocument&&c!==b&&c.nodeType!==11){if(g?g.index(c)>-1:p.find.matchesSelector(c,a)){f.push(c);break}c=c.parentNode}}return f=f.length>1?p.unique(f):f,this.pushStack(f,"closest",a)},index:function(a){return a?typeof a=="string"?p.inArray(this[0],p(a)):p.inArray(a.jquery?a[0]:a,this):this[0]&&this[0].parentNode?this.prevAll().length:-1},add:function(a,b){var c=typeof a=="string"?p(a,b):p.makeArray(a&&a.nodeType?[a]:a),d=p.merge(this.get(),c);return this.pushStack(bh(c[0])||bh(d[0])?d:p.unique(d))},addBack:function(a){return this.add(a==null?this.prevObject:this.prevObject.filter(a))}}),p.fn.andSelf=p.fn.addBack,p.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return p.dir(a,"parentNode")},parentsUntil:function(a,b,c){return p.dir(a,"parentNode",c)},next:function(a){return bi(a,"nextSibling")},prev:function(a){return bi(a,"previousSibling")},nextAll:function(a){return p.dir(a,"nextSibling")},prevAll:function(a){return p.dir(a,"previousSibling")},nextUntil:function(a,b,c){return p.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return p.dir(a,"previousSibling",c)},siblings:function(a){return p.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return p.sibling(a.firstChild)},contents:function(a){return p.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:p.merge([],a.childNodes)}},function(a,b){p.fn[a]=function(c,d){var e=p.map(this,b,c);return bc.test(a)||(d=c),d&&typeof d=="string"&&(e=p.filter(d,e)),e=this.length>1&&!bg[a]?p.unique(e):e,this.length>1&&bd.test(a)&&(e=e.reverse()),this.pushStack(e,a,k.call(arguments).join(","))}}),p.extend({filter:function(a,b,c){return c&&(a=":not("+a+")"),b.length===1?p.find.matchesSelector(b[0],a)?[b[0]]:[]:p.find.matches(a,b)},dir:function(a,c,d){var e=[],f=a[c];while(f&&f.nodeType!==9&&(d===b||f.nodeType!==1||!p(f).is(d)))f.nodeType===1&&e.push(f),f=f[c];return e},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var bl="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",bm=/ jQuery\d+="(?:null|\d+)"/g,bn=/^\s+/,bo=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,bp=/<([\w:]+)/,bq=/<tbody/i,br=/<|&#?\w+;/,bs=/<(?:script|style|link)/i,bt=/<(?:script|object|embed|option|style)/i,bu=new RegExp("<(?:"+bl+")[\\s/>]","i"),bv=/^(?:checkbox|radio)$/,bw=/checked\s*(?:[^=]|=\s*.checked.)/i,bx=/\/(java|ecma)script/i,by=/^\s*<!(?:\[CDATA\[|\-\-)|[\]\-]{2}>\s*$/g,bz={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]},bA=bk(e),bB=bA.appendChild(e.createElement("div"));bz.optgroup=bz.option,bz.tbody=bz.tfoot=bz.colgroup=bz.caption=bz.thead,bz.th=bz.td,p.support.htmlSerialize||(bz._default=[1,"X<div>","</div>"]),p.fn.extend({text:function(a){return p.access(this,function(a){return a===b?p.text(this):this.empty().append((this[0]&&this[0].ownerDocument||e).createTextNode(a))},null,a,arguments.length)},wrapAll:function(a){if(p.isFunction(a))return this.each(function(b){p(this).wrapAll(a.call(this,b))});if(this[0]){var b=p(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){return p.isFunction(a)?this.each(function(b){p(this).wrapInner(a.call(this,b))}):this.each(function(){var b=p(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=p.isFunction(a);return this.each(function(c){p(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){p.nodeName(this,"body")||p(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){(this.nodeType===1||this.nodeType===11)&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){(this.nodeType===1||this.nodeType===11)&&this.insertBefore(a,this.firstChild)})},before:function(){if(!bh(this[0]))return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=p.clean(arguments);return this.pushStack(p.merge(a,this),"before",this.selector)}},after:function(){if(!bh(this[0]))return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=p.clean(arguments);return this.pushStack(p.merge(this,a),"after",this.selector)}},remove:function(a,b){var c,d=0;for(;(c=this[d])!=null;d++)if(!a||p.filter(a,[c]).length)!b&&c.nodeType===1&&(p.cleanData(c.getElementsByTagName("*")),p.cleanData([c])),c.parentNode&&c.parentNode.removeChild(c);return this},empty:function(){var a,b=0;for(;(a=this[b])!=null;b++){a.nodeType===1&&p.cleanData(a.getElementsByTagName("*"));while(a.firstChild)a.removeChild(a.firstChild)}return this},clone:function(a,b){return a=a==null?!1:a,b=b==null?a:b,this.map(function(){return p.clone(this,a,b)})},html:function(a){return p.access(this,function(a){var c=this[0]||{},d=0,e=this.length;if(a===b)return c.nodeType===1?c.innerHTML.replace(bm,""):b;if(typeof a=="string"&&!bs.test(a)&&(p.support.htmlSerialize||!bu.test(a))&&(p.support.leadingWhitespace||!bn.test(a))&&!bz[(bp.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(bo,"<$1></$2>");try{for(;d<e;d++)c=this[d]||{},c.nodeType===1&&(p.cleanData(c.getElementsByTagName("*")),c.innerHTML=a);c=0}catch(f){}}c&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(a){return bh(this[0])?this.length?this.pushStack(p(p.isFunction(a)?a():a),"replaceWith",a):this:p.isFunction(a)?this.each(function(b){var c=p(this),d=c.html();c.replaceWith(a.call(this,b,d))}):(typeof a!="string"&&(a=p(a).detach()),this.each(function(){var b=this.nextSibling,c=this.parentNode;p(this).remove(),b?p(b).before(a):p(c).append(a)}))},detach:function(a){return this.remove(a,!0)},domManip:function(a,c,d){a=[].concat.apply([],a);var e,f,g,h,i=0,j=a[0],k=[],l=this.length;if(!p.support.checkClone&&l>1&&typeof j=="string"&&bw.test(j))return this.each(function(){p(this).domManip(a,c,d)});if(p.isFunction(j))return this.each(function(e){var f=p(this);a[0]=j.call(this,e,c?f.html():b),f.domManip(a,c,d)});if(this[0]){e=p.buildFragment(a,this,k),g=e.fragment,f=g.firstChild,g.childNodes.length===1&&(g=f);if(f){c=c&&p.nodeName(f,"tr");for(h=e.cacheable||l-1;i<l;i++)d.call(c&&p.nodeName(this[i],"table")?bC(this[i],"tbody"):this[i],i===h?g:p.clone(g,!0,!0))}g=f=null,k.length&&p.each(k,function(a,b){b.src?p.ajax?p.ajax({url:b.src,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0}):p.error("no ajax"):p.globalEval((b.text||b.textContent||b.innerHTML||"").replace(by,"")),b.parentNode&&b.parentNode.removeChild(b)})}return this}}),p.buildFragment=function(a,c,d){var f,g,h,i=a[0];return c=c||e,c=!c.nodeType&&c[0]||c,c=c.ownerDocument||c,a.length===1&&typeof i=="string"&&i.length<512&&c===e&&i.charAt(0)==="<"&&!bt.test(i)&&(p.support.checkClone||!bw.test(i))&&(p.support.html5Clone||!bu.test(i))&&(g=!0,f=p.fragments[i],h=f!==b),f||(f=c.createDocumentFragment(),p.clean(a,c,f,d),g&&(p.fragments[i]=h&&f)),{fragment:f,cacheable:g}},p.fragments={},p.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){p.fn[a]=function(c){var d,e=0,f=[],g=p(c),h=g.length,i=this.length===1&&this[0].parentNode;if((i==null||i&&i.nodeType===11&&i.childNodes.length===1)&&h===1)return g[b](this[0]),this;for(;e<h;e++)d=(e>0?this.clone(!0):this).get(),p(g[e])[b](d),f=f.concat(d);return this.pushStack(f,a,g.selector)}}),p.extend({clone:function(a,b,c){var d,e,f,g;p.support.html5Clone||p.isXMLDoc(a)||!bu.test("<"+a.nodeName+">")?g=a.cloneNode(!0):(bB.innerHTML=a.outerHTML,bB.removeChild(g=bB.firstChild));if((!p.support.noCloneEvent||!p.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!p.isXMLDoc(a)){bE(a,g),d=bF(a),e=bF(g);for(f=0;d[f];++f)e[f]&&bE(d[f],e[f])}if(b){bD(a,g);if(c){d=bF(a),e=bF(g);for(f=0;d[f];++f)bD(d[f],e[f])}}return d=e=null,g},clean:function(a,b,c,d){var f,g,h,i,j,k,l,m,n,o,q,r,s=b===e&&bA,t=[];if(!b||typeof b.createDocumentFragment=="undefined")b=e;for(f=0;(h=a[f])!=null;f++){typeof h=="number"&&(h+="");if(!h)continue;if(typeof h=="string")if(!br.test(h))h=b.createTextNode(h);else{s=s||bk(b),l=b.createElement("div"),s.appendChild(l),h=h.replace(bo,"<$1></$2>"),i=(bp.exec(h)||["",""])[1].toLowerCase(),j=bz[i]||bz._default,k=j[0],l.innerHTML=j[1]+h+j[2];while(k--)l=l.lastChild;if(!p.support.tbody){m=bq.test(h),n=i==="table"&&!m?l.firstChild&&l.firstChild.childNodes:j[1]==="<table>"&&!m?l.childNodes:[];for(g=n.length-1;g>=0;--g)p.nodeName(n[g],"tbody")&&!n[g].childNodes.length&&n[g].parentNode.removeChild(n[g])}!p.support.leadingWhitespace&&bn.test(h)&&l.insertBefore(b.createTextNode(bn.exec(h)[0]),l.firstChild),h=l.childNodes,l.parentNode.removeChild(l)}h.nodeType?t.push(h):p.merge(t,h)}l&&(h=l=s=null);if(!p.support.appendChecked)for(f=0;(h=t[f])!=null;f++)p.nodeName(h,"input")?bG(h):typeof h.getElementsByTagName!="undefined"&&p.grep(h.getElementsByTagName("input"),bG);if(c){q=function(a){if(!a.type||bx.test(a.type))return d?d.push(a.parentNode?a.parentNode.removeChild(a):a):c.appendChild(a)};for(f=0;(h=t[f])!=null;f++)if(!p.nodeName(h,"script")||!q(h))c.appendChild(h),typeof h.getElementsByTagName!="undefined"&&(r=p.grep(p.merge([],h.getElementsByTagName("script")),q),t.splice.apply(t,[f+1,0].concat(r)),f+=r.length)}return t},cleanData:function(a,b){var c,d,e,f,g=0,h=p.expando,i=p.cache,j=p.support.deleteExpando,k=p.event.special;for(;(e=a[g])!=null;g++)if(b||p.acceptData(e)){d=e[h],c=d&&i[d];if(c){if(c.events)for(f in c.events)k[f]?p.event.remove(e,f):p.removeEvent(e,f,c.handle);i[d]&&(delete i[d],j?delete e[h]:e.removeAttribute?e.removeAttribute(h):e[h]=null,p.deletedIds.push(d))}}}}),function(){var a,b;p.uaMatch=function(a){a=a.toLowerCase();var b=/(chrome)[ \/]([\w.]+)/.exec(a)||/(webkit)[ \/]([\w.]+)/.exec(a)||/(opera)(?:.*version|)[ \/]([\w.]+)/.exec(a)||/(msie) ([\w.]+)/.exec(a)||a.indexOf("compatible")<0&&/(mozilla)(?:.*? rv:([\w.]+)|)/.exec(a)||[];return{browser:b[1]||"",version:b[2]||"0"}},a=p.uaMatch(g.userAgent),b={},a.browser&&(b[a.browser]=!0,b.version=a.version),b.chrome?b.webkit=!0:b.webkit&&(b.safari=!0),p.browser=b,p.sub=function(){function a(b,c){return new a.fn.init(b,c)}p.extend(!0,a,this),a.superclass=this,a.fn=a.prototype=this(),a.fn.constructor=a,a.sub=this.sub,a.fn.init=function c(c,d){return d&&d instanceof p&&!(d instanceof a)&&(d=a(d)),p.fn.init.call(this,c,d,b)},a.fn.init.prototype=a.fn;var b=a(e);return a}}();var bH,bI,bJ,bK=/alpha\([^)]*\)/i,bL=/opacity=([^)]*)/,bM=/^(top|right|bottom|left)$/,bN=/^(none|table(?!-c[ea]).+)/,bO=/^margin/,bP=new RegExp("^("+q+")(.*)$","i"),bQ=new RegExp("^("+q+")(?!px)[a-z%]+$","i"),bR=new RegExp("^([-+])=("+q+")","i"),bS={},bT={position:"absolute",visibility:"hidden",display:"block"},bU={letterSpacing:0,fontWeight:400},bV=["Top","Right","Bottom","Left"],bW=["Webkit","O","Moz","ms"],bX=p.fn.toggle;p.fn.extend({css:function(a,c){return p.access(this,function(a,c,d){return d!==b?p.style(a,c,d):p.css(a,c)},a,c,arguments.length>1)},show:function(){return b$(this,!0)},hide:function(){return b$(this)},toggle:function(a,b){var c=typeof a=="boolean";return p.isFunction(a)&&p.isFunction(b)?bX.apply(this,arguments):this.each(function(){(c?a:bZ(this))?p(this).show():p(this).hide()})}}),p.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=bH(a,"opacity");return c===""?"1":c}}}},cssNumber:{fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":p.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,c,d,e){if(!a||a.nodeType===3||a.nodeType===8||!a.style)return;var f,g,h,i=p.camelCase(c),j=a.style;c=p.cssProps[i]||(p.cssProps[i]=bY(j,i)),h=p.cssHooks[c]||p.cssHooks[i];if(d===b)return h&&"get"in h&&(f=h.get(a,!1,e))!==b?f:j[c];g=typeof d,g==="string"&&(f=bR.exec(d))&&(d=(f[1]+1)*f[2]+parseFloat(p.css(a,c)),g="number");if(d==null||g==="number"&&isNaN(d))return;g==="number"&&!p.cssNumber[i]&&(d+="px");if(!h||!("set"in h)||(d=h.set(a,d,e))!==b)try{j[c]=d}catch(k){}},css:function(a,c,d,e){var f,g,h,i=p.camelCase(c);return c=p.cssProps[i]||(p.cssProps[i]=bY(a.style,i)),h=p.cssHooks[c]||p.cssHooks[i],h&&"get"in h&&(f=h.get(a,!0,e)),f===b&&(f=bH(a,c)),f==="normal"&&c in bU&&(f=bU[c]),d||e!==b?(g=parseFloat(f),d||p.isNumeric(g)?g||0:f):f},swap:function(a,b,c){var d,e,f={};for(e in b)f[e]=a.style[e],a.style[e]=b[e];d=c.call(a);for(e in b)a.style[e]=f[e];return d}}),a.getComputedStyle?bH=function(b,c){var d,e,f,g,h=a.getComputedStyle(b,null),i=b.style;return h&&(d=h[c],d===""&&!p.contains(b.ownerDocument,b)&&(d=p.style(b,c)),bQ.test(d)&&bO.test(c)&&(e=i.width,f=i.minWidth,g=i.maxWidth,i.minWidth=i.maxWidth=i.width=d,d=h.width,i.width=e,i.minWidth=f,i.maxWidth=g)),d}:e.documentElement.currentStyle&&(bH=function(a,b){var c,d,e=a.currentStyle&&a.currentStyle[b],f=a.style;return e==null&&f&&f[b]&&(e=f[b]),bQ.test(e)&&!bM.test(b)&&(c=f.left,d=a.runtimeStyle&&a.runtimeStyle.left,d&&(a.runtimeStyle.left=a.currentStyle.left),f.left=b==="fontSize"?"1em":e,e=f.pixelLeft+"px",f.left=c,d&&(a.runtimeStyle.left=d)),e===""?"auto":e}),p.each(["height","width"],function(a,b){p.cssHooks[b]={get:function(a,c,d){if(c)return a.offsetWidth===0&&bN.test(bH(a,"display"))?p.swap(a,bT,function(){return cb(a,b,d)}):cb(a,b,d)},set:function(a,c,d){return b_(a,c,d?ca(a,b,d,p.support.boxSizing&&p.css(a,"boxSizing")==="border-box"):0)}}}),p.support.opacity||(p.cssHooks.opacity={get:function(a,b){return bL.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?.01*parseFloat(RegExp.$1)+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=p.isNumeric(b)?"alpha(opacity="+b*100+")":"",f=d&&d.filter||c.filter||"";c.zoom=1;if(b>=1&&p.trim(f.replace(bK,""))===""&&c.removeAttribute){c.removeAttribute("filter");if(d&&!d.filter)return}c.filter=bK.test(f)?f.replace(bK,e):f+" "+e}}),p(function(){p.support.reliableMarginRight||(p.cssHooks.marginRight={get:function(a,b){return p.swap(a,{display:"inline-block"},function(){if(b)return bH(a,"marginRight")})}}),!p.support.pixelPosition&&p.fn.position&&p.each(["top","left"],function(a,b){p.cssHooks[b]={get:function(a,c){if(c){var d=bH(a,b);return bQ.test(d)?p(a).position()[b]+"px":d}}}})}),p.expr&&p.expr.filters&&(p.expr.filters.hidden=function(a){return a.offsetWidth===0&&a.offsetHeight===0||!p.support.reliableHiddenOffsets&&(a.style&&a.style.display||bH(a,"display"))==="none"},p.expr.filters.visible=function(a){return!p.expr.filters.hidden(a)}),p.each({margin:"",padding:"",border:"Width"},function(a,b){p.cssHooks[a+b]={expand:function(c){var d,e=typeof c=="string"?c.split(" "):[c],f={};for(d=0;d<4;d++)f[a+bV[d]+b]=e[d]||e[d-2]||e[0];return f}},bO.test(a)||(p.cssHooks[a+b].set=b_)});var cd=/%20/g,ce=/\[\]$/,cf=/\r?\n/g,cg=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,ch=/^(?:select|textarea)/i;p.fn.extend({serialize:function(){return p.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?p.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||ch.test(this.nodeName)||cg.test(this.type))}).map(function(a,b){var c=p(this).val();return c==null?null:p.isArray(c)?p.map(c,function(a,c){return{name:b.name,value:a.replace(cf,"\r\n")}}):{name:b.name,value:c.replace(cf,"\r\n")}}).get()}}),p.param=function(a,c){var d,e=[],f=function(a,b){b=p.isFunction(b)?b():b==null?"":b,e[e.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=p.ajaxSettings&&p.ajaxSettings.traditional);if(p.isArray(a)||a.jquery&&!p.isPlainObject(a))p.each(a,function(){f(this.name,this.value)});else for(d in a)ci(d,a[d],c,f);return e.join("&").replace(cd,"+")};var cj,ck,cl=/#.*$/,cm=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,cn=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,co=/^(?:GET|HEAD)$/,cp=/^\/\//,cq=/\?/,cr=/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,cs=/([?&])_=[^&]*/,ct=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/,cu=p.fn.load,cv={},cw={},cx=["*/"]+["*"];try{ck=f.href}catch(cy){ck=e.createElement("a"),ck.href="",ck=ck.href}cj=ct.exec(ck.toLowerCase())||[],p.fn.load=function(a,c,d){if(typeof a!="string"&&cu)return cu.apply(this,arguments);if(!this.length)return this;var e,f,g,h=this,i=a.indexOf(" ");return i>=0&&(e=a.slice(i,a.length),a=a.slice(0,i)),p.isFunction(c)?(d=c,c=b):c&&typeof c=="object"&&(f="POST"),p.ajax({url:a,type:f,dataType:"html",data:c,complete:function(a,b){d&&h.each(d,g||[a.responseText,b,a])}}).done(function(a){g=arguments,h.html(e?p("<div>").append(a.replace(cr,"")).find(e):a)}),this},p.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){p.fn[b]=function(a){return this.on(b,a)}}),p.each(["get","post"],function(a,c){p[c]=function(a,d,e,f){return p.isFunction(d)&&(f=f||e,e=d,d=b),p.ajax({type:c,url:a,data:d,success:e,dataType:f})}}),p.extend({getScript:function(a,c){return p.get(a,b,c,"script")},getJSON:function(a,b,c){return p.get(a,b,c,"json")},ajaxSetup:function(a,b){return b?cB(a,p.ajaxSettings):(b=a,a=p.ajaxSettings),cB(a,b),a},ajaxSettings:{url:ck,isLocal:cn.test(cj[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded; charset=UTF-8",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":cx},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":p.parseJSON,"text xml":p.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:cz(cv),ajaxTransport:cz(cw),ajax:function(a,c){function y(a,c,f,i){var k,s,t,u,w,y=c;if(v===2)return;v=2,h&&clearTimeout(h),g=b,e=i||"",x.readyState=a>0?4:0,f&&(u=cC(l,x,f));if(a>=200&&a<300||a===304)l.ifModified&&(w=x.getResponseHeader("Last-Modified"),w&&(p.lastModified[d]=w),w=x.getResponseHeader("Etag"),w&&(p.etag[d]=w)),a===304?(y="notmodified",k=!0):(k=cD(l,u),y=k.state,s=k.data,t=k.error,k=!t);else{t=y;if(!y||a)y="error",a<0&&(a=0)}x.status=a,x.statusText=(c||y)+"",k?o.resolveWith(m,[s,y,x]):o.rejectWith(m,[x,y,t]),x.statusCode(r),r=b,j&&n.trigger("ajax"+(k?"Success":"Error"),[x,l,k?s:t]),q.fireWith(m,[x,y]),j&&(n.trigger("ajaxComplete",[x,l]),--p.active||p.event.trigger("ajaxStop"))}typeof a=="object"&&(c=a,a=b),c=c||{};var d,e,f,g,h,i,j,k,l=p.ajaxSetup({},c),m=l.context||l,n=m!==l&&(m.nodeType||m instanceof p)?p(m):p.event,o=p.Deferred(),q=p.Callbacks("once memory"),r=l.statusCode||{},t={},u={},v=0,w="canceled",x={readyState:0,setRequestHeader:function(a,b){if(!v){var c=a.toLowerCase();a=u[c]=u[c]||a,t[a]=b}return this},getAllResponseHeaders:function(){return v===2?e:null},getResponseHeader:function(a){var c;if(v===2){if(!f){f={};while(c=cm.exec(e))f[c[1].toLowerCase()]=c[2]}c=f[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){return v||(l.mimeType=a),this},abort:function(a){return a=a||w,g&&g.abort(a),y(0,a),this}};o.promise(x),x.success=x.done,x.error=x.fail,x.complete=q.add,x.statusCode=function(a){if(a){var b;if(v<2)for(b in a)r[b]=[r[b],a[b]];else b=a[x.status],x.always(b)}return this},l.url=((a||l.url)+"").replace(cl,"").replace(cp,cj[1]+"//"),l.dataTypes=p.trim(l.dataType||"*").toLowerCase().split(s),l.crossDomain==null&&(i=ct.exec(l.url.toLowerCase())||!1,l.crossDomain=i&&i.join(":")+(i[3]?"":i[1]==="http:"?80:443)!==cj.join(":")+(cj[3]?"":cj[1]==="http:"?80:443)),l.data&&l.processData&&typeof l.data!="string"&&(l.data=p.param(l.data,l.traditional)),cA(cv,l,c,x);if(v===2)return x;j=l.global,l.type=l.type.toUpperCase(),l.hasContent=!co.test(l.type),j&&p.active++===0&&p.event.trigger("ajaxStart");if(!l.hasContent){l.data&&(l.url+=(cq.test(l.url)?"&":"?")+l.data,delete l.data),d=l.url;if(l.cache===!1){var z=p.now(),A=l.url.replace(cs,"$1_="+z);l.url=A+(A===l.url?(cq.test(l.url)?"&":"?")+"_="+z:"")}}(l.data&&l.hasContent&&l.contentType!==!1||c.contentType)&&x.setRequestHeader("Content-Type",l.contentType),l.ifModified&&(d=d||l.url,p.lastModified[d]&&x.setRequestHeader("If-Modified-Since",p.lastModified[d]),p.etag[d]&&x.setRequestHeader("If-None-Match",p.etag[d])),x.setRequestHeader("Accept",l.dataTypes[0]&&l.accepts[l.dataTypes[0]]?l.accepts[l.dataTypes[0]]+(l.dataTypes[0]!=="*"?", "+cx+"; q=0.01":""):l.accepts["*"]);for(k in l.headers)x.setRequestHeader(k,l.headers[k]);if(!l.beforeSend||l.beforeSend.call(m,x,l)!==!1&&v!==2){w="abort";for(k in{success:1,error:1,complete:1})x[k](l[k]);g=cA(cw,l,c,x);if(!g)y(-1,"No Transport");else{x.readyState=1,j&&n.trigger("ajaxSend",[x,l]),l.async&&l.timeout>0&&(h=setTimeout(function(){x.abort("timeout")},l.timeout));try{v=1,g.send(t,y)}catch(B){if(v<2)y(-1,B);else throw B}}return x}return x.abort()},active:0,lastModified:{},etag:{}});var cE=[],cF=/\?/,cG=/(=)\?(?=&|$)|\?\?/,cH=p.now();p.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var a=cE.pop()||p.expando+"_"+cH++;return this[a]=!0,a}}),p.ajaxPrefilter("json jsonp",function(c,d,e){var f,g,h,i=c.data,j=c.url,k=c.jsonp!==!1,l=k&&cG.test(j),m=k&&!l&&typeof i=="string"&&!(c.contentType||"").indexOf("application/x-www-form-urlencoded")&&cG.test(i);if(c.dataTypes[0]==="jsonp"||l||m)return f=c.jsonpCallback=p.isFunction(c.jsonpCallback)?c.jsonpCallback():c.jsonpCallback,g=a[f],l?c.url=j.replace(cG,"$1"+f):m?c.data=i.replace(cG,"$1"+f):k&&(c.url+=(cF.test(j)?"&":"?")+c.jsonp+"="+f),c.converters["script json"]=function(){return h||p.error(f+" was not called"),h[0]},c.dataTypes[0]="json",a[f]=function(){h=arguments},e.always(function(){a[f]=g,c[f]&&(c.jsonpCallback=d.jsonpCallback,cE.push(f)),h&&p.isFunction(g)&&g(h[0]),h=g=b}),"script"}),p.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){return p.globalEval(a),a}}}),p.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),p.ajaxTransport("script",function(a){if(a.crossDomain){var c,d=e.head||e.getElementsByTagName("head")[0]||e.documentElement;return{send:function(f,g){c=e.createElement("script"),c.async="async",a.scriptCharset&&(c.charset=a.scriptCharset),c.src=a.url,c.onload=c.onreadystatechange=function(a,e){if(e||!c.readyState||/loaded|complete/.test(c.readyState))c.onload=c.onreadystatechange=null,d&&c.parentNode&&d.removeChild(c),c=b,e||g(200,"success")},d.insertBefore(c,d.firstChild)},abort:function(){c&&c.onload(0,1)}}}});var cI,cJ=a.ActiveXObject?function(){for(var a in cI)cI[a](0,1)}:!1,cK=0;p.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&cL()||cM()}:cL,function(a){p.extend(p.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(p.ajaxSettings.xhr()),p.support.ajax&&p.ajaxTransport(function(c){if(!c.crossDomain||p.support.cors){var d;return{send:function(e,f){var g,h,i=c.xhr();c.username?i.open(c.type,c.url,c.async,c.username,c.password):i.open(c.type,c.url,c.async);if(c.xhrFields)for(h in c.xhrFields)i[h]=c.xhrFields[h];c.mimeType&&i.overrideMimeType&&i.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(h in e)i.setRequestHeader(h,e[h])}catch(j){}i.send(c.hasContent&&c.data||null),d=function(a,e){var h,j,k,l,m;try{if(d&&(e||i.readyState===4)){d=b,g&&(i.onreadystatechange=p.noop,cJ&&delete cI[g]);if(e)i.readyState!==4&&i.abort();else{h=i.status,k=i.getAllResponseHeaders(),l={},m=i.responseXML,m&&m.documentElement&&(l.xml=m);try{l.text=i.responseText}catch(a){}try{j=i.statusText}catch(n){j=""}!h&&c.isLocal&&!c.crossDomain?h=l.text?200:404:h===1223&&(h=204)}}}catch(o){e||f(-1,o)}l&&f(h,j,l,k)},c.async?i.readyState===4?setTimeout(d,0):(g=++cK,cJ&&(cI||(cI={},p(a).unload(cJ)),cI[g]=d),i.onreadystatechange=d):d()},abort:function(){d&&d(0,1)}}}});var cN,cO,cP=/^(?:toggle|show|hide)$/,cQ=new RegExp("^(?:([-+])=|)("+q+")([a-z%]*)$","i"),cR=/queueHooks$/,cS=[cY],cT={"*":[function(a,b){var c,d,e=this.createTween(a,b),f=cQ.exec(b),g=e.cur(),h=+g||0,i=1,j=20;if(f){c=+f[2],d=f[3]||(p.cssNumber[a]?"":"px");if(d!=="px"&&h){h=p.css(e.elem,a,!0)||c||1;do i=i||".5",h=h/i,p.style(e.elem,a,h+d);while(i!==(i=e.cur()/g)&&i!==1&&--j)}e.unit=d,e.start=h,e.end=f[1]?h+(f[1]+1)*c:c}return e}]};p.Animation=p.extend(cW,{tweener:function(a,b){p.isFunction(a)?(b=a,a=["*"]):a=a.split(" ");var c,d=0,e=a.length;for(;d<e;d++)c=a[d],cT[c]=cT[c]||[],cT[c].unshift(b)},prefilter:function(a,b){b?cS.unshift(a):cS.push(a)}}),p.Tween=cZ,cZ.prototype={constructor:cZ,init:function(a,b,c,d,e,f){this.elem=a,this.prop=c,this.easing=e||"swing",this.options=b,this.start=this.now=this.cur(),this.end=d,this.unit=f||(p.cssNumber[c]?"":"px")},cur:function(){var a=cZ.propHooks[this.prop];return a&&a.get?a.get(this):cZ.propHooks._default.get(this)},run:function(a){var b,c=cZ.propHooks[this.prop];return this.options.duration?this.pos=b=p.easing[this.easing](a,this.options.duration*a,0,1,this.options.duration):this.pos=b=a,this.now=(this.end-this.start)*b+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),c&&c.set?c.set(this):cZ.propHooks._default.set(this),this}},cZ.prototype.init.prototype=cZ.prototype,cZ.propHooks={_default:{get:function(a){var b;return a.elem[a.prop]==null||!!a.elem.style&&a.elem.style[a.prop]!=null?(b=p.css(a.elem,a.prop,!1,""),!b||b==="auto"?0:b):a.elem[a.prop]},set:function(a){p.fx.step[a.prop]?p.fx.step[a.prop](a):a.elem.style&&(a.elem.style[p.cssProps[a.prop]]!=null||p.cssHooks[a.prop])?p.style(a.elem,a.prop,a.now+a.unit):a.elem[a.prop]=a.now}}},cZ.propHooks.scrollTop=cZ.propHooks.scrollLeft={set:function(a){a.elem.nodeType&&a.elem.parentNode&&(a.elem[a.prop]=a.now)}},p.each(["toggle","show","hide"],function(a,b){var c=p.fn[b];p.fn[b]=function(d,e,f){return d==null||typeof d=="boolean"||!a&&p.isFunction(d)&&p.isFunction(e)?c.apply(this,arguments):this.animate(c$(b,!0),d,e,f)}}),p.fn.extend({fadeTo:function(a,b,c,d){return this.filter(bZ).css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){var e=p.isEmptyObject(a),f=p.speed(b,c,d),g=function(){var b=cW(this,p.extend({},a),f);e&&b.stop(!0)};return e||f.queue===!1?this.each(g):this.queue(f.queue,g)},stop:function(a,c,d){var e=function(a){var b=a.stop;delete a.stop,b(d)};return typeof a!="string"&&(d=c,c=a,a=b),c&&a!==!1&&this.queue(a||"fx",[]),this.each(function(){var b=!0,c=a!=null&&a+"queueHooks",f=p.timers,g=p._data(this);if(c)g[c]&&g[c].stop&&e(g[c]);else for(c in g)g[c]&&g[c].stop&&cR.test(c)&&e(g[c]);for(c=f.length;c--;)f[c].elem===this&&(a==null||f[c].queue===a)&&(f[c].anim.stop(d),b=!1,f.splice(c,1));(b||!d)&&p.dequeue(this,a)})}}),p.each({slideDown:c$("show"),slideUp:c$("hide"),slideToggle:c$("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){p.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),p.speed=function(a,b,c){var d=a&&typeof a=="object"?p.extend({},a):{complete:c||!c&&b||p.isFunction(a)&&a,duration:a,easing:c&&b||b&&!p.isFunction(b)&&b};d.duration=p.fx.off?0:typeof d.duration=="number"?d.duration:d.duration in p.fx.speeds?p.fx.speeds[d.duration]:p.fx.speeds._default;if(d.queue==null||d.queue===!0)d.queue="fx";return d.old=d.complete,d.complete=function(){p.isFunction(d.old)&&d.old.call(this),d.queue&&p.dequeue(this,d.queue)},d},p.easing={linear:function(a){return a},swing:function(a){return.5-Math.cos(a*Math.PI)/2}},p.timers=[],p.fx=cZ.prototype.init,p.fx.tick=function(){var a,b=p.timers,c=0;for(;c<b.length;c++)a=b[c],!a()&&b[c]===a&&b.splice(c--,1);b.length||p.fx.stop()},p.fx.timer=function(a){a()&&p.timers.push(a)&&!cO&&(cO=setInterval(p.fx.tick,p.fx.interval))},p.fx.interval=13,p.fx.stop=function(){clearInterval(cO),cO=null},p.fx.speeds={slow:600,fast:200,_default:400},p.fx.step={},p.expr&&p.expr.filters&&(p.expr.filters.animated=function(a){return p.grep(p.timers,function(b){return a===b.elem}).length});var c_=/^(?:body|html)$/i;p.fn.offset=function(a){if(arguments.length)return a===b?this:this.each(function(b){p.offset.setOffset(this,a,b)});var c,d,e,f,g,h,i,j={top:0,left:0},k=this[0],l=k&&k.ownerDocument;if(!l)return;return(d=l.body)===k?p.offset.bodyOffset(k):(c=l.documentElement,p.contains(c,k)?(typeof k.getBoundingClientRect!="undefined"&&(j=k.getBoundingClientRect()),e=da(l),f=c.clientTop||d.clientTop||0,g=c.clientLeft||d.clientLeft||0,h=e.pageYOffset||c.scrollTop,i=e.pageXOffset||c.scrollLeft,{top:j.top+h-f,left:j.left+i-g}):j)},p.offset={bodyOffset:function(a){var b=a.offsetTop,c=a.offsetLeft;return p.support.doesNotIncludeMarginInBodyOffset&&(b+=parseFloat(p.css(a,"marginTop"))||0,c+=parseFloat(p.css(a,"marginLeft"))||0),{top:b,left:c}},setOffset:function(a,b,c){var d=p.css(a,"position");d==="static"&&(a.style.position="relative");var e=p(a),f=e.offset(),g=p.css(a,"top"),h=p.css(a,"left"),i=(d==="absolute"||d==="fixed")&&p.inArray("auto",[g,h])>-1,j={},k={},l,m;i?(k=e.position(),l=k.top,m=k.left):(l=parseFloat(g)||0,m=parseFloat(h)||0),p.isFunction(b)&&(b=b.call(a,c,f)),b.top!=null&&(j.top=b.top-f.top+l),b.left!=null&&(j.left=b.left-f.left+m),"using"in b?b.using.call(a,j):e.css(j)}},p.fn.extend({position:function(){if(!this[0])return;var a=this[0],b=this.offsetParent(),c=this.offset(),d=c_.test(b[0].nodeName)?{top:0,left:0}:b.offset();return c.top-=parseFloat(p.css(a,"marginTop"))||0,c.left-=parseFloat(p.css(a,"marginLeft"))||0,d.top+=parseFloat(p.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(p.css(b[0],"borderLeftWidth"))||0,{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||e.body;while(a&&!c_.test(a.nodeName)&&p.css(a,"position")==="static")a=a.offsetParent;return a||e.body})}}),p.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(a,c){var d=/Y/.test(c);p.fn[a]=function(e){return p.access(this,function(a,e,f){var g=da(a);if(f===b)return g?c in g?g[c]:g.document.documentElement[e]:a[e];g?g.scrollTo(d?p(g).scrollLeft():f,d?f:p(g).scrollTop()):a[e]=f},a,e,arguments.length,null)}}),p.each({Height:"height",Width:"width"},function(a,c){p.each({padding:"inner"+a,content:c,"":"outer"+a},function(d,e){p.fn[e]=function(e,f){var g=arguments.length&&(d||typeof e!="boolean"),h=d||(e===!0||f===!0?"margin":"border");return p.access(this,function(c,d,e){var f;return p.isWindow(c)?c.document.documentElement["client"+a]:c.nodeType===9?(f=c.documentElement,Math.max(c.body["scroll"+a],f["scroll"+a],c.body["offset"+a],f["offset"+a],f["client"+a])):e===b?p.css(c,d,e,h):p.style(c,d,e,h)},c,g?e:b,g,null)}})}),a.jQuery=a.$=p,typeof define=="function"&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return p})})(window);
\ No newline at end of file
diff --git a/godoc/static/jquery.treeview.css b/godoc/static/jquery.treeview.css
new file mode 100644
index 0000000..ac33361
--- /dev/null
+++ b/godoc/static/jquery.treeview.css
@@ -0,0 +1,76 @@
+/* https://github.com/jzaefferer/jquery-treeview/blob/master/jquery.treeview.css */
+/* License: MIT. */
+.treeview, .treeview ul {
+	padding: 0;
+	margin: 0;
+	list-style: none;
+}
+
+.treeview ul {
+	background-color: white;
+	margin-top: 4px;
+}
+
+.treeview .hitarea {
+	background: url(images/treeview-default.gif) -64px -25px no-repeat;
+	height: 16px;
+	width: 16px;
+	margin-left: -16px;
+	float: left;
+	cursor: pointer;
+}
+/* fix for IE6 */
+* html .hitarea {
+	display: inline;
+	float:none;
+}
+
+.treeview li {
+	margin: 0;
+	padding: 3px 0pt 3px 16px;
+}
+
+.treeview a.selected {
+	background-color: #eee;
+}
+
+#treecontrol { margin: 1em 0; display: none; }
+
+.treeview .hover { color: red; cursor: pointer; }
+
+.treeview li { background: url(images/treeview-default-line.gif) 0 0 no-repeat; }
+.treeview li.collapsable, .treeview li.expandable { background-position: 0 -176px; }
+
+.treeview .expandable-hitarea { background-position: -80px -3px; }
+
+.treeview li.last { background-position: 0 -1766px }
+.treeview li.lastCollapsable, .treeview li.lastExpandable { background-image: url(images/treeview-default.gif); }
+.treeview li.lastCollapsable { background-position: 0 -111px }
+.treeview li.lastExpandable { background-position: -32px -67px }
+
+.treeview div.lastCollapsable-hitarea, .treeview div.lastExpandable-hitarea { background-position: 0; }
+
+.treeview-red li { background-image: url(images/treeview-red-line.gif); }
+.treeview-red .hitarea, .treeview-red li.lastCollapsable, .treeview-red li.lastExpandable { background-image: url(images/treeview-red.gif); }
+
+.treeview-black li { background-image: url(images/treeview-black-line.gif); }
+.treeview-black .hitarea, .treeview-black li.lastCollapsable, .treeview-black li.lastExpandable { background-image: url(images/treeview-black.gif); }
+
+.treeview-gray li { background-image: url(images/treeview-gray-line.gif); }
+.treeview-gray .hitarea, .treeview-gray li.lastCollapsable, .treeview-gray li.lastExpandable { background-image: url(images/treeview-gray.gif); }
+
+.treeview-famfamfam li { background-image: url(images/treeview-famfamfam-line.gif); }
+.treeview-famfamfam .hitarea, .treeview-famfamfam li.lastCollapsable, .treeview-famfamfam li.lastExpandable { background-image: url(images/treeview-famfamfam.gif); }
+
+.treeview .placeholder {
+	background: url(images/ajax-loader.gif) 0 0 no-repeat;
+	height: 16px;
+	width: 16px;
+	display: block;
+}
+
+.filetree li { padding: 3px 0 2px 16px; }
+.filetree span.folder, .filetree span.file { padding: 1px 0 1px 16px; display: block; }
+.filetree span.folder { background: url(images/folder.gif) 0 0 no-repeat; }
+.filetree li.expandable span.folder { background: url(images/folder-closed.gif) 0 0 no-repeat; }
+.filetree span.file { background: url(images/file.gif) 0 0 no-repeat; }
diff --git a/godoc/static/jquery.treeview.edit.js b/godoc/static/jquery.treeview.edit.js
new file mode 100644
index 0000000..9895b02
--- /dev/null
+++ b/godoc/static/jquery.treeview.edit.js
@@ -0,0 +1,39 @@
+/* https://github.com/jzaefferer/jquery-treeview/blob/master/jquery.treeview.edit.js */
+/* License: MIT. */
+(function($) {
+	var CLASSES = $.treeview.classes;
+	var proxied = $.fn.treeview;
+	$.fn.treeview = function(settings) {
+		settings = $.extend({}, settings);
+		if (settings.add) {
+			return this.trigger("add", [settings.add]);
+		}
+		if (settings.remove) {
+			return this.trigger("remove", [settings.remove]);
+		}
+		return proxied.apply(this, arguments).bind("add", function(event, branches) {
+			$(branches).prev()
+				.removeClass(CLASSES.last)
+				.removeClass(CLASSES.lastCollapsable)
+				.removeClass(CLASSES.lastExpandable)
+			.find(">.hitarea")
+				.removeClass(CLASSES.lastCollapsableHitarea)
+				.removeClass(CLASSES.lastExpandableHitarea);
+			$(branches).find("li").andSelf().prepareBranches(settings).applyClasses(settings, $(this).data("toggler"));
+		}).bind("remove", function(event, branches) {
+			var prev = $(branches).prev();
+			var parent = $(branches).parent();
+			$(branches).remove();
+			prev.filter(":last-child").addClass(CLASSES.last)
+				.filter("." + CLASSES.expandable).replaceClass(CLASSES.last, CLASSES.lastExpandable).end()
+				.find(">.hitarea").replaceClass(CLASSES.expandableHitarea, CLASSES.lastExpandableHitarea).end()
+				.filter("." + CLASSES.collapsable).replaceClass(CLASSES.last, CLASSES.lastCollapsable).end()
+				.find(">.hitarea").replaceClass(CLASSES.collapsableHitarea, CLASSES.lastCollapsableHitarea);
+			if (parent.is(":not(:has(>))") && parent[0] != this) {
+				parent.parent().removeClass(CLASSES.collapsable).removeClass(CLASSES.expandable)
+				parent.siblings(".hitarea").andSelf().remove();
+			}
+		});
+	};
+	
+})(jQuery);
diff --git a/godoc/static/jquery.treeview.js b/godoc/static/jquery.treeview.js
new file mode 100644
index 0000000..356af23
--- /dev/null
+++ b/godoc/static/jquery.treeview.js
@@ -0,0 +1,256 @@
+/*
+ * Treeview 1.4.1 - jQuery plugin to hide and show branches of a tree
+ * 
+ * http://bassistance.de/jquery-plugins/jquery-plugin-treeview/
+ * http://docs.jquery.com/Plugins/Treeview
+ *
+ * Copyright (c) 2007 Jörn Zaefferer
+ *
+ * Dual licensed under the MIT and GPL licenses:
+ *   http://www.opensource.org/licenses/mit-license.php
+ *   http://www.gnu.org/licenses/gpl.html
+ *
+ * Revision: $Id: jquery.treeview.js 5759 2008-07-01 07:50:28Z joern.zaefferer $
+ *
+ */
+
+;(function($) {
+
+	// TODO rewrite as a widget, removing all the extra plugins
+	$.extend($.fn, {
+		swapClass: function(c1, c2) {
+			var c1Elements = this.filter('.' + c1);
+			this.filter('.' + c2).removeClass(c2).addClass(c1);
+			c1Elements.removeClass(c1).addClass(c2);
+			return this;
+		},
+		replaceClass: function(c1, c2) {
+			return this.filter('.' + c1).removeClass(c1).addClass(c2).end();
+		},
+		hoverClass: function(className) {
+			className = className || "hover";
+			return this.hover(function() {
+				$(this).addClass(className);
+			}, function() {
+				$(this).removeClass(className);
+			});
+		},
+		heightToggle: function(animated, callback) {
+			animated ?
+				this.animate({ height: "toggle" }, animated, callback) :
+				this.each(function(){
+					jQuery(this)[ jQuery(this).is(":hidden") ? "show" : "hide" ]();
+					if(callback)
+						callback.apply(this, arguments);
+				});
+		},
+		heightHide: function(animated, callback) {
+			if (animated) {
+				this.animate({ height: "hide" }, animated, callback);
+			} else {
+				this.hide();
+				if (callback)
+					this.each(callback);				
+			}
+		},
+		prepareBranches: function(settings) {
+			if (!settings.prerendered) {
+				// mark last tree items
+				this.filter(":last-child:not(ul)").addClass(CLASSES.last);
+				// collapse whole tree, or only those marked as closed, anyway except those marked as open
+				this.filter((settings.collapsed ? "" : "." + CLASSES.closed) + ":not(." + CLASSES.open + ")").find(">ul").hide();
+			}
+			// return all items with sublists
+			return this.filter(":has(>ul)");
+		},
+		applyClasses: function(settings, toggler) {
+			// TODO use event delegation
+			this.filter(":has(>ul):not(:has(>a))").find(">span").unbind("click.treeview").bind("click.treeview", function(event) {
+				// don't handle click events on children, eg. checkboxes
+				if ( this == event.target )
+					toggler.apply($(this).next());
+			}).add( $("a", this) ).hoverClass();
+			
+			if (!settings.prerendered) {
+				// handle closed ones first
+				this.filter(":has(>ul:hidden)")
+						.addClass(CLASSES.expandable)
+						.replaceClass(CLASSES.last, CLASSES.lastExpandable);
+						
+				// handle open ones
+				this.not(":has(>ul:hidden)")
+						.addClass(CLASSES.collapsable)
+						.replaceClass(CLASSES.last, CLASSES.lastCollapsable);
+						
+	            // create hitarea if not present
+				var hitarea = this.find("div." + CLASSES.hitarea);
+				if (!hitarea.length)
+					hitarea = this.prepend("<div class=\"" + CLASSES.hitarea + "\"/>").find("div." + CLASSES.hitarea);
+				hitarea.removeClass().addClass(CLASSES.hitarea).each(function() {
+					var classes = "";
+					$.each($(this).parent().attr("class").split(" "), function() {
+						classes += this + "-hitarea ";
+					});
+					$(this).addClass( classes );
+				})
+			}
+			
+			// apply event to hitarea
+			this.find("div." + CLASSES.hitarea).click( toggler );
+		},
+		treeview: function(settings) {
+			
+			settings = $.extend({
+				cookieId: "treeview"
+			}, settings);
+			
+			if ( settings.toggle ) {
+				var callback = settings.toggle;
+				settings.toggle = function() {
+					return callback.apply($(this).parent()[0], arguments);
+				};
+			}
+		
+			// factory for treecontroller
+			function treeController(tree, control) {
+				// factory for click handlers
+				function handler(filter) {
+					return function() {
+						// reuse toggle event handler, applying the elements to toggle
+						// start searching for all hitareas
+						toggler.apply( $("div." + CLASSES.hitarea, tree).filter(function() {
+							// for plain toggle, no filter is provided, otherwise we need to check the parent element
+							return filter ? $(this).parent("." + filter).length : true;
+						}) );
+						return false;
+					};
+				}
+				// click on first element to collapse tree
+				$("a:eq(0)", control).click( handler(CLASSES.collapsable) );
+				// click on second to expand tree
+				$("a:eq(1)", control).click( handler(CLASSES.expandable) );
+				// click on third to toggle tree
+				$("a:eq(2)", control).click( handler() ); 
+			}
+		
+			// handle toggle event
+			function toggler() {
+				$(this)
+					.parent()
+					// swap classes for hitarea
+					.find(">.hitarea")
+						.swapClass( CLASSES.collapsableHitarea, CLASSES.expandableHitarea )
+						.swapClass( CLASSES.lastCollapsableHitarea, CLASSES.lastExpandableHitarea )
+					.end()
+					// swap classes for parent li
+					.swapClass( CLASSES.collapsable, CLASSES.expandable )
+					.swapClass( CLASSES.lastCollapsable, CLASSES.lastExpandable )
+					// find child lists
+					.find( ">ul" )
+					// toggle them
+					.heightToggle( settings.animated, settings.toggle );
+				if ( settings.unique ) {
+					$(this).parent()
+						.siblings()
+						// swap classes for hitarea
+						.find(">.hitarea")
+							.replaceClass( CLASSES.collapsableHitarea, CLASSES.expandableHitarea )
+							.replaceClass( CLASSES.lastCollapsableHitarea, CLASSES.lastExpandableHitarea )
+						.end()
+						.replaceClass( CLASSES.collapsable, CLASSES.expandable )
+						.replaceClass( CLASSES.lastCollapsable, CLASSES.lastExpandable )
+						.find( ">ul" )
+						.heightHide( settings.animated, settings.toggle );
+				}
+			}
+			this.data("toggler", toggler);
+			
+			function serialize() {
+				function binary(arg) {
+					return arg ? 1 : 0;
+				}
+				var data = [];
+				branches.each(function(i, e) {
+					data[i] = $(e).is(":has(>ul:visible)") ? 1 : 0;
+				});
+				$.cookie(settings.cookieId, data.join(""), settings.cookieOptions );
+			}
+			
+			function deserialize() {
+				var stored = $.cookie(settings.cookieId);
+				if ( stored ) {
+					var data = stored.split("");
+					branches.each(function(i, e) {
+						$(e).find(">ul")[ parseInt(data[i]) ? "show" : "hide" ]();
+					});
+				}
+			}
+			
+			// add treeview class to activate styles
+			this.addClass("treeview");
+			
+			// prepare branches and find all tree items with child lists
+			var branches = this.find("li").prepareBranches(settings);
+			
+			switch(settings.persist) {
+			case "cookie":
+				var toggleCallback = settings.toggle;
+				settings.toggle = function() {
+					serialize();
+					if (toggleCallback) {
+						toggleCallback.apply(this, arguments);
+					}
+				};
+				deserialize();
+				break;
+			case "location":
+				var current = this.find("a").filter(function() {
+					return this.href.toLowerCase() == location.href.toLowerCase();
+				});
+				if ( current.length ) {
+					// TODO update the open/closed classes
+					var items = current.addClass("selected").parents("ul, li").add( current.next() ).show();
+					if (settings.prerendered) {
+						// if prerendered is on, replicate the basic class swapping
+						items.filter("li")
+							.swapClass( CLASSES.collapsable, CLASSES.expandable )
+							.swapClass( CLASSES.lastCollapsable, CLASSES.lastExpandable )
+							.find(">.hitarea")
+								.swapClass( CLASSES.collapsableHitarea, CLASSES.expandableHitarea )
+								.swapClass( CLASSES.lastCollapsableHitarea, CLASSES.lastExpandableHitarea );
+					}
+				}
+				break;
+			}
+			
+			branches.applyClasses(settings, toggler);
+				
+			// if control option is set, create the treecontroller and show it
+			if ( settings.control ) {
+				treeController(this, settings.control);
+				$(settings.control).show();
+			}
+			
+			return this;
+		}
+	});
+	
+	// classes used by the plugin
+	// need to be styled via external stylesheet, see first example
+	$.treeview = {};
+	var CLASSES = ($.treeview.classes = {
+		open: "open",
+		closed: "closed",
+		expandable: "expandable",
+		expandableHitarea: "expandable-hitarea",
+		lastExpandableHitarea: "lastExpandable-hitarea",
+		collapsable: "collapsable",
+		collapsableHitarea: "collapsable-hitarea",
+		lastCollapsableHitarea: "lastCollapsable-hitarea",
+		lastCollapsable: "lastCollapsable",
+		lastExpandable: "lastExpandable",
+		last: "last",
+		hitarea: "hitarea"
+	});
+	
+})(jQuery);
diff --git a/godoc/static/makestatic.go b/godoc/static/makestatic.go
new file mode 100644
index 0000000..f5e3272
--- /dev/null
+++ b/godoc/static/makestatic.go
@@ -0,0 +1,121 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build ignore
+
+// Command makestatic reads a set of files and writes a Go source file to "static.go"
+// that declares a map of string constants containing contents of the input files.
+// It is intended to be invoked via "go generate" (directive in "gen.go").
+package main
+
+import (
+	"bufio"
+	"bytes"
+	"fmt"
+	"io/ioutil"
+	"os"
+	"unicode/utf8"
+)
+
+var files = []string{
+	"analysis/call3.png",
+	"analysis/call-eg.png",
+	"analysis/callers1.png",
+	"analysis/callers2.png",
+	"analysis/chan1.png",
+	"analysis/chan2a.png",
+	"analysis/chan2b.png",
+	"analysis/error1.png",
+	"analysis/help.html",
+	"analysis/ident-def.png",
+	"analysis/ident-field.png",
+	"analysis/ident-func.png",
+	"analysis/ipcg-func.png",
+	"analysis/ipcg-pkg.png",
+	"analysis/typeinfo-pkg.png",
+	"analysis/typeinfo-src.png",
+	"callgraph.html",
+	"codewalk.html",
+	"codewalkdir.html",
+	"dirlist.html",
+	"error.html",
+	"example.html",
+	"godoc.html",
+	"godocs.js",
+	"images/minus.gif",
+	"images/plus.gif",
+	"images/treeview-black-line.gif",
+	"images/treeview-black.gif",
+	"images/treeview-default-line.gif",
+	"images/treeview-default.gif",
+	"images/treeview-gray-line.gif",
+	"images/treeview-gray.gif",
+	"implements.html",
+	"jquery.js",
+	"jquery.treeview.css",
+	"jquery.treeview.edit.js",
+	"jquery.treeview.js",
+	"methodset.html",
+	"opensearch.xml",
+	"package.html",
+	"package.txt",
+	"play.js",
+	"playground.js",
+	"search.html",
+	"search.txt",
+	"searchcode.html",
+	"searchdoc.html",
+	"searchtxt.html",
+	"style.css",
+}
+
+func main() {
+	if err := makestatic(); err != nil {
+		fmt.Fprintln(os.Stderr, err)
+		os.Exit(1)
+	}
+}
+
+func makestatic() error {
+	f, err := os.Create("static.go")
+	if err != nil {
+		return err
+	}
+	defer f.Close()
+	w := bufio.NewWriter(f)
+	fmt.Fprintf(w, "%v\n\npackage static\n\n", warning)
+	fmt.Fprintf(w, "var Files = map[string]string{\n")
+	for _, fn := range files {
+		b, err := ioutil.ReadFile(fn)
+		if err != nil {
+			return err
+		}
+		fmt.Fprintf(w, "\t%q: ", fn)
+		if utf8.Valid(b) {
+			fmt.Fprintf(w, "`%s`", sanitize(b))
+		} else {
+			fmt.Fprintf(w, "%q", b)
+		}
+		fmt.Fprintln(w, ",\n")
+	}
+	fmt.Fprintln(w, "}")
+	if err := w.Flush(); err != nil {
+		return err
+	}
+	return f.Close()
+}
+
+// sanitize prepares a valid UTF-8 string as a raw string constant.
+func sanitize(b []byte) []byte {
+	// Replace ` with `+"`"+`
+	b = bytes.Replace(b, []byte("`"), []byte("`+\"`\"+`"), -1)
+
+	// Replace BOM with `+"\xEF\xBB\xBF"+`
+	// (A BOM is valid UTF-8 but not permitted in Go source files.
+	// I wouldn't bother handling this, but for some insane reason
+	// jquery.js has a BOM somewhere in the middle.)
+	return bytes.Replace(b, []byte("\xEF\xBB\xBF"), []byte("`+\"\\xEF\\xBB\\xBF\"+`"), -1)
+}
+
+const warning = "// DO NOT EDIT ** This file was generated by \"go generate\" ** DO NOT EDIT //"
diff --git a/godoc/static/methodset.html b/godoc/static/methodset.html
new file mode 100644
index 0000000..1b339e3
--- /dev/null
+++ b/godoc/static/methodset.html
@@ -0,0 +1,9 @@
+<div class="toggle" style="display: none">
+	<div class="collapsed">
+		<p class="exampleHeading toggleButton">▹ <span class="text">Method set</span></p>
+	</div>
+	<div class="expanded">
+		<p class="exampleHeading toggleButton">▾ <span class="text">Method set</span></p>
+		<div style="margin-left: 1in" id='methodset-{{.Index}}'>...</div>
+	</div>
+</div>
diff --git a/godoc/static/opensearch.xml b/godoc/static/opensearch.xml
new file mode 100644
index 0000000..1b652db
--- /dev/null
+++ b/godoc/static/opensearch.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/">
+  <ShortName>godoc</ShortName>
+  <Description>The Go Programming Language</Description>
+  <Tags>go golang</Tags>
+  <Contact />
+  <Url type="text/html" template="{{.BaseURL}}/search?q={searchTerms}" />
+  <Image height="15" width="16" type="image/x-icon">/favicon.ico</Image>
+  <OutputEncoding>UTF-8</OutputEncoding>
+  <InputEncoding>UTF-8</InputEncoding>
+</OpenSearchDescription>
diff --git a/godoc/static/package.html b/godoc/static/package.html
new file mode 100644
index 0000000..964ed91
--- /dev/null
+++ b/godoc/static/package.html
@@ -0,0 +1,329 @@
+<!--
+	Copyright 2009 The Go Authors. All rights reserved.
+	Use of this source code is governed by a BSD-style
+	license that can be found in the LICENSE file.
+-->
+<!--
+	Note: Static (i.e., not template-generated) href and id
+	attributes start with "pkg-" to make it impossible for
+	them to conflict with generated attributes (some of which
+	correspond to Go identifiers).
+-->
+{{with .PDoc}}
+	<script type='text/javascript'>
+	document.ANALYSIS_DATA = {{$.AnalysisData}};
+	document.CALLGRAPH = {{$.CallGraph}};
+	</script>
+
+	{{if $.IsMain}}
+		{{/* command documentation */}}
+		{{comment_html .Doc}}
+	{{else}}
+		{{/* package documentation */}}
+		<div id="short-nav">
+			<dl>
+			<dd><code>import "{{html .ImportPath}}"</code></dd>
+			</dl>
+			<dl>
+			<dd><a href="#pkg-overview" class="overviewLink">Overview</a></dd>
+			<dd><a href="#pkg-index" class="indexLink">Index</a></dd>
+			{{if $.Examples}}
+				<dd><a href="#pkg-examples" class="examplesLink">Examples</a></dd>
+			{{end}}
+			{{if $.Dirs}}
+				<dd><a href="#pkg-subdirectories">Subdirectories</a></dd>
+			{{end}}
+			</dl>
+		</div>
+		<!-- The package's Name is printed as title by the top-level template -->
+		<div id="pkg-overview" class="toggleVisible">
+			<div class="collapsed">
+				<h2 class="toggleButton" title="Click to show Overview section">Overview ▹</h2>
+			</div>
+			<div class="expanded">
+				<h2 class="toggleButton" title="Click to hide Overview section">Overview ▾</h2>
+				{{comment_html .Doc}}
+			</div>
+		</div>
+		{{example_html $ ""}}
+
+		<div id="pkg-index" class="toggleVisible">
+		<div class="collapsed">
+			<h2 class="toggleButton" title="Click to show Index section">Index ▹</h2>
+		</div>
+		<div class="expanded">
+			<h2 class="toggleButton" title="Click to hide Index section">Index ▾</h2>
+
+		<!-- Table of contents for API; must be named manual-nav to turn off auto nav. -->
+			<div id="manual-nav">
+			<dl>
+			{{if .Consts}}
+				<dd><a href="#pkg-constants">Constants</a></dd>
+			{{end}}
+			{{if .Vars}}
+				<dd><a href="#pkg-variables">Variables</a></dd>
+			{{end}}
+			{{range .Funcs}}
+				{{$name_html := html .Name}}
+				<dd><a href="#{{$name_html}}">{{node_html $ .Decl false | sanitize}}</a></dd>
+			{{end}}
+			{{range .Types}}
+				{{$tname_html := html .Name}}
+				<dd><a href="#{{$tname_html}}">type {{$tname_html}}</a></dd>
+				{{range .Funcs}}
+					{{$name_html := html .Name}}
+					<dd>&nbsp; &nbsp; <a href="#{{$name_html}}">{{node_html $ .Decl false | sanitize}}</a></dd>
+				{{end}}
+				{{range .Methods}}
+					{{$name_html := html .Name}}
+					<dd>&nbsp; &nbsp; <a href="#{{$tname_html}}.{{$name_html}}">{{node_html $ .Decl false | sanitize}}</a></dd>
+				{{end}}
+			{{end}}
+			{{if $.Notes}}
+				{{range $marker, $item := $.Notes}}
+				<dd><a href="#pkg-note-{{$marker}}">{{noteTitle $marker | html}}s</a></dd>
+				{{end}}
+			{{end}}
+			</dl>
+			</div><!-- #manual-nav -->
+
+		{{if $.Examples}}
+		<div id="pkg-examples">
+			<h4>Examples</h4>
+			<dl>
+			{{range $.Examples}}
+			<dd><a class="exampleLink" href="#example_{{.Name}}">{{example_name .Name}}</a></dd>
+			{{end}}
+			</dl>
+		</div>
+		{{end}}
+
+		{{with .Filenames}}
+			<h4>Package files</h4>
+			<p>
+			<span style="font-size:90%">
+			{{range .}}
+				<a href="{{.|srcLink|html}}">{{.|filename|html}}</a>
+			{{end}}
+			</span>
+			</p>
+		{{end}}
+		</div><!-- .expanded -->
+		</div><!-- #pkg-index -->
+
+		<div id="pkg-callgraph" class="toggle" style="display: none">
+		<div class="collapsed">
+			<h2 class="toggleButton" title="Click to show Internal Call Graph section">Internal call graph ▹</h2>
+		</div> <!-- .expanded -->
+		<div class="expanded">
+			<h2 class="toggleButton" title="Click to hide Internal Call Graph section">Internal call graph ▾</h2>
+			<p>
+			  In the call graph viewer below, each node
+			  is a function belonging to this package
+			  and its children are the functions it
+			  calls&mdash;perhaps dynamically.
+			</p>
+			<p>
+			  The root nodes are the entry points of the
+			  package: functions that may be called from
+			  outside the package.
+			  There may be non-exported or anonymous
+			  functions among them if they are called
+			  dynamically from another package.
+			</p>
+			<p>
+			  Click a node to visit that function's source code.
+			  From there you can visit its callers by
+			  clicking its declaring <code>func</code>
+			  token.
+			</p>
+			<p>
+			  Functions may be omitted if they were
+			  determined to be unreachable in the
+			  particular programs or tests that were
+			  analyzed.
+			</p>
+			<!-- Zero means show all package entry points. -->
+			<ul style="margin-left: 0.5in" id="callgraph-0" class="treeview"></ul>
+		</div>
+		</div> <!-- #pkg-callgraph -->
+
+		{{with .Consts}}
+			<h2 id="pkg-constants">Constants</h2>
+			{{range .}}
+				<pre>{{node_html $ .Decl true}}</pre>
+				{{comment_html .Doc}}
+			{{end}}
+		{{end}}
+		{{with .Vars}}
+			<h2 id="pkg-variables">Variables</h2>
+			{{range .}}
+				<pre>{{node_html $ .Decl true}}</pre>
+				{{comment_html .Doc}}
+			{{end}}
+		{{end}}
+		{{range .Funcs}}
+			{{/* Name is a string - no need for FSet */}}
+			{{$name_html := html .Name}}
+			<h2 id="{{$name_html}}">func <a href="{{posLink_url $ .Decl}}">{{$name_html}}</a></h2>
+			<pre>{{node_html $ .Decl true}}</pre>
+			{{comment_html .Doc}}
+			{{example_html $ .Name}}
+			{{callgraph_html $ "" .Name}}
+
+		{{end}}
+		{{range .Types}}
+			{{$tname := .Name}}
+			{{$tname_html := html .Name}}
+			<h2 id="{{$tname_html}}">type <a href="{{posLink_url $ .Decl}}">{{$tname_html}}</a></h2>
+			<pre>{{node_html $ .Decl true}}</pre>
+			{{comment_html .Doc}}
+
+			{{range .Consts}}
+				<pre>{{node_html $ .Decl true}}</pre>
+				{{comment_html .Doc}}
+			{{end}}
+
+			{{range .Vars}}
+				<pre>{{node_html $ .Decl true}}</pre>
+				{{comment_html .Doc}}
+			{{end}}
+
+			{{example_html $ $tname}}
+			{{implements_html $ $tname}}
+			{{methodset_html $ $tname}}
+
+			{{range .Funcs}}
+				{{$name_html := html .Name}}
+				<h3 id="{{$name_html}}">func <a href="{{posLink_url $ .Decl}}">{{$name_html}}</a></h3>
+				<pre>{{node_html $ .Decl true}}</pre>
+				{{comment_html .Doc}}
+				{{example_html $ .Name}}
+				{{callgraph_html $ "" .Name}}
+			{{end}}
+
+			{{range .Methods}}
+				{{$name_html := html .Name}}
+				<h3 id="{{$tname_html}}.{{$name_html}}">func ({{html .Recv}}) <a href="{{posLink_url $ .Decl}}">{{$name_html}}</a></h3>
+				<pre>{{node_html $ .Decl true}}</pre>
+				{{comment_html .Doc}}
+				{{$name := printf "%s_%s" $tname .Name}}
+				{{example_html $ $name}}
+				{{callgraph_html $ .Recv .Name}}
+			{{end}}
+		{{end}}
+	{{end}}
+
+	{{with $.Notes}}
+		{{range $marker, $content := .}}
+			<h2 id="pkg-note-{{$marker}}">{{noteTitle $marker | html}}s</h2>
+			<ul style="list-style: none; padding: 0;">
+			{{range .}}
+			<li><a href="{{posLink_url $ .}}">&#x261e;</a> {{html .Body}}</li>
+			{{end}}
+			</ul>
+		{{end}}
+	{{end}}
+{{end}}
+
+{{with .PAst}}
+	{{range $filename, $ast := .}}
+		<a href="{{$filename|srcLink|html}}">{{$filename|filename|html}}</a>:<pre>{{node_html $ $ast false}}</pre>
+	{{end}}
+{{end}}
+
+{{with .Dirs}}
+	{{/* DirList entries are numbers and strings - no need for FSet */}}
+	{{if $.PDoc}}
+		<h2 id="pkg-subdirectories">Subdirectories</h2>
+	{{end}}
+	{{if eq $.Dirname "/src"}}
+		<div id="manual-nav">
+			<dl>
+				<dt><a href="#stdlib">Standard library</a></dt>
+				<dt><a href="#other">Other packages</a></dt>
+				<dd><a href="#subrepo">Sub-repositories</a></dd>
+				<dd><a href="#community">Community</a></dd>
+			</dl>
+		</div>
+		<h2 id="stdlib">Standard library</h2>
+		<img class="gopher" src="/doc/gopher/pkg.png"/>
+	{{end}}
+
+
+	<div class="pkg-dir">
+		<table>
+			<tr>
+				<th class="pkg-name">Name</th>
+				<th class="pkg-synopsis">Synopsis</th>
+			</tr>
+
+			{{if not (or (eq $.Dirname "/src") (eq $.Dirname "/src/cmd") $.DirFlat)}}
+			<tr>
+				<td colspan="2"><a href="..">..</a></td>
+			</tr>
+			{{end}}
+
+			{{range .List}}
+				{{if $.DirFlat}}
+					{{if .HasPkg}}
+						<tr>
+							<td class="pkg-name">
+								<a href="{{html .Path}}/">{{html .Path}}</a>
+							</td>
+							<td class="pkg-synopsis">
+								{{html .Synopsis}}
+							</td>
+						</tr>
+					{{end}}
+				{{else}}
+					<tr>
+						<td class="pkg-name" style="padding-left: {{multiply .Depth 20}}px;">
+							<a href="{{html .Path}}/">{{html .Name}}</a>
+						</td>
+						<td class="pkg-synopsis">
+							{{html .Synopsis}}
+						</td>
+					</tr>
+				{{end}}
+			{{end}}
+		</table>
+	</div>
+
+
+	{{if eq $.Dirname "/src"}}
+	<h2 id="other">Other packages</h2>
+
+	<h3 id="subrepo">Sub-repositories</h3>
+	<p>
+	These packages are part of the Go Project but outside the main Go tree.
+	They are developed under looser <a href="/doc/go1compat">compatibility requirements</a> than the Go core.
+	Install them with "<a href="/cmd/go/#hdr-Download_and_install_packages_and_dependencies">go get</a>".
+	</p>
+	<ul>
+		<li><a href="//godoc.org/golang.org/x/benchmarks">benchmarks</a> — benchmarks to measure Go as it is developed.</li>
+		<li><a href="//godoc.org/golang.org/x/blog">blog</a> — <a href="//blog.golang.org">blog.golang.org</a>'s implementation.</li>
+		<li><a href="//godoc.org/golang.org/x/build">build</a> — <a href="//build.golang.org">build.golang.org</a>'s implementation.</li>
+		<li><a href="//godoc.org/golang.org/x/crypto">crypto</a> — additional cryptography packages.</li>
+		<li><a href="//godoc.org/golang.org/x/debug">debug</a> — an experimental debugger for Go.</li>
+		<li><a href="//godoc.org/golang.org/x/image">image</a> — additional imaging packages.</li>
+		<li><a href="//godoc.org/golang.org/x/mobile">mobile</a> — experimental support for Go on mobile platforms.</li>
+		<li><a href="//godoc.org/golang.org/x/net">net</a> — additional networking packages.</li>
+		<li><a href="//godoc.org/golang.org/x/sys">sys</a> — packages for making system calls.</li>
+		<li><a href="//godoc.org/golang.org/x/text">text</a> — packages for working with text.</li>
+		<li><a href="//godoc.org/golang.org/x/tools">tools</a> — godoc, goimports, gorename, and other tools.</li>
+		<li><a href="//godoc.org/golang.org/x/tour">tour</a> — <a href="//tour.golang.org">tour.golang.org</a>'s implementation.</li>
+		<li><a href="//godoc.org/golang.org/x/exp">exp</a> — experimental and deprecated packages (handle with care; may change without warning).</li>
+	</ul>
+
+	<h3 id="community">Community</h3>
+	<p>
+	These services can help you find Open Source packages provided by the community.
+	</p>
+	<ul>
+		<li><a href="//godoc.org">GoDoc</a> - a package index and search engine.</li>
+		<li><a href="http://go-search.org">Go Search</a> - a code search engine.</li>
+		<li><a href="/wiki/Projects">Projects at the Go Wiki</a> - a curated list of Go projects.</li>
+	</ul>
+	{{end}}
+{{end}}
diff --git a/godoc/static/package.txt b/godoc/static/package.txt
new file mode 100644
index 0000000..e53fa6e
--- /dev/null
+++ b/godoc/static/package.txt
@@ -0,0 +1,116 @@
+{{$info := .}}{{$filtered := .IsFiltered}}{{/*
+
+---------------------------------------
+
+*/}}{{if $filtered}}{{range .PAst}}{{range .Decls}}{{node $info .}}
+
+{{end}}{{end}}{{else}}{{with .PAst}}{{range $filename, $ast := .}}{{$filename}}:
+{{node $ $ast}}{{end}}{{end}}{{end}}{{/*
+
+---------------------------------------
+
+*/}}{{if and $filtered (not (or .PDoc .PAst))}}No match found.
+{{end}}{{with .PDoc}}{{if $.IsMain}}COMMAND DOCUMENTATION
+
+{{comment_text .Doc "    " "\t"}}
+{{else}}{{if not $filtered}}PACKAGE DOCUMENTATION
+
+package {{.Name}}
+    import "{{.ImportPath}}"
+
+{{comment_text .Doc "    " "\t"}}
+{{example_text $ "" "    "}}{{end}}{{/*
+
+---------------------------------------
+
+*/}}{{with .Consts}}{{if not $filtered}}CONSTANTS
+
+{{end}}{{range .}}{{node $ .Decl}}
+{{comment_text .Doc "    " "\t"}}
+{{end}}{{end}}{{/*
+
+---------------------------------------
+
+*/}}{{with .Vars}}{{if not $filtered}}VARIABLES
+
+{{end}}{{range .}}{{node $ .Decl}}
+{{comment_text .Doc "    " "\t"}}
+{{end}}{{end}}{{/*
+
+---------------------------------------
+
+*/}}{{with .Funcs}}{{if not $filtered}}FUNCTIONS
+
+{{end}}{{range .}}{{node $ .Decl}}
+{{comment_text .Doc "    " "\t"}}
+{{example_text $ .Name "    "}}{{end}}{{end}}{{/*
+
+---------------------------------------
+
+*/}}{{with .Types}}{{if not $filtered}}TYPES
+
+{{end}}{{range .}}{{$tname := .Name}}{{node $ .Decl}}
+{{comment_text .Doc "    " "\t"}}
+{{/*
+
+---------------------------------------
+
+*/}}{{if .Consts}}{{range .Consts}}{{node $ .Decl}}
+{{comment_text .Doc "    " "\t"}}
+{{end}}{{end}}{{/*
+
+---------------------------------------
+
+*/}}{{if .Vars}}{{range .Vars}}{{node $ .Decl}}
+{{comment_text .Doc "    " "\t"}}
+{{range $name := .Names}}{{example_text $ $name "    "}}{{end}}{{end}}{{end}}{{/*
+
+---------------------------------------
+
+*/}}{{if .Funcs}}{{range .Funcs}}{{node $ .Decl}}
+{{comment_text .Doc "    " "\t"}}
+{{example_text $ .Name "    "}}{{end}}{{end}}{{/*
+
+---------------------------------------
+
+*/}}{{if .Methods}}{{range .Methods}}{{node $ .Decl}}
+{{comment_text .Doc "    " "\t"}}
+{{$name := printf "%s_%s" $tname .Name}}{{example_text $ $name "    "}}{{end}}{{end}}{{/*
+
+---------------------------------------
+
+*/}}{{end}}{{end}}{{/*
+
+---------------------------------------
+
+*/}}{{if and $filtered (not (or .Consts (or .Vars (or .Funcs .Types))))}}No match found.
+{{end}}{{/*
+
+---------------------------------------
+
+*/}}{{end}}{{/*
+
+---------------------------------------
+
+*/}}{{with $.Notes}}
+{{range $marker, $content := .}}
+{{$marker}}S
+
+{{range $content}}{{comment_text .Body "   " "\t"}}
+{{end}}{{end}}{{end}}{{end}}{{/*
+
+---------------------------------------
+
+*/}}{{if not $filtered}}{{with .Dirs}}SUBDIRECTORIES
+{{if $.DirFlat}}{{range .List}}{{if .HasPkg}}
+	{{.Path}}{{end}}{{end}}
+{{else}}{{range .List}}
+	{{repeat `. ` .Depth}}{{.Name}}{{end}}
+{{end}}{{end}}{{/*
+
+---------------------------------------
+
+*/}}{{end}}{{/*
+Make sure there is no newline at the end of this file.
+perl -i -pe 'chomp if eof' package.txt
+*/}}
diff --git a/godoc/static/play.js b/godoc/static/play.js
new file mode 100644
index 0000000..7e87460
--- /dev/null
+++ b/godoc/static/play.js
@@ -0,0 +1,103 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+function initPlayground(transport) {
+	"use strict";
+
+	function text(node) {
+		var s = "";
+		for (var i = 0; i < node.childNodes.length; i++) {
+			var n = node.childNodes[i];
+			if (n.nodeType === 1) {
+				if (n.tagName === "BUTTON") continue
+				if (n.tagName === "SPAN" && n.className === "number") continue;
+				if (n.tagName === "DIV" || n.tagName == "BR") {
+					s += "\n";
+				}
+				s += text(n);
+				continue;
+			}
+			if (n.nodeType === 3) {
+				s += n.nodeValue;
+			}
+		}
+		return s.replace("\xA0", " "); // replace non-breaking spaces
+	}
+
+	function init(code) {
+		var output = document.createElement('div');
+		var outpre = document.createElement('pre');
+		var running;
+
+		if ($ && $(output).resizable) {
+			$(output).resizable({
+				handles: "n,w,nw",
+				minHeight:	27,
+				minWidth:	135,
+				maxHeight: 608,
+				maxWidth:	990
+			});
+		}
+
+		function onKill() {
+			if (running) running.Kill();
+		}
+
+		function onRun(e) {
+			onKill();
+			output.style.display = "block";
+			outpre.innerHTML = "";
+			run1.style.display = "none";
+			var options = {Race: e.shiftKey};
+			running = transport.Run(text(code), PlaygroundOutput(outpre), options);
+		}
+
+		function onClose() {
+			onKill();
+			output.style.display = "none";
+			run1.style.display = "inline-block";
+		}
+
+		var run1 = document.createElement('button');
+		run1.innerHTML = 'Run';
+		run1.className = 'run';
+		run1.addEventListener("click", onRun, false);
+		var run2 = document.createElement('button');
+		run2.className = 'run';
+		run2.innerHTML = 'Run';
+		run2.addEventListener("click", onRun, false);
+		var kill = document.createElement('button');
+		kill.className = 'kill';
+		kill.innerHTML = 'Kill';
+		kill.addEventListener("click", onKill, false);
+		var close = document.createElement('button');
+		close.className = 'close';
+		close.innerHTML = 'Close';
+		close.addEventListener("click", onClose, false);
+
+		var button = document.createElement('div');
+		button.classList.add('buttons');
+		button.appendChild(run1);
+		// Hack to simulate insertAfter
+		code.parentNode.insertBefore(button, code.nextSibling);
+
+		var buttons = document.createElement('div');
+		buttons.classList.add('buttons');
+		buttons.appendChild(run2);
+		buttons.appendChild(kill);
+		buttons.appendChild(close);
+
+		output.classList.add('output');
+		output.appendChild(buttons);
+		output.appendChild(outpre);
+		output.style.display = "none";
+		code.parentNode.insertBefore(output, button.nextSibling);
+	}
+
+	var play = document.querySelectorAll('div.playground');
+	for (var i = 0; i < play.length; i++) {
+		init(play[i]);
+	}
+}
+
diff --git a/godoc/static/playground.js b/godoc/static/playground.js
new file mode 100644
index 0000000..93dea15
--- /dev/null
+++ b/godoc/static/playground.js
@@ -0,0 +1,433 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+/*
+In the absence of any formal way to specify interfaces in JavaScript,
+here's a skeleton implementation of a playground transport.
+
+        function Transport() {
+                // Set up any transport state (eg, make a websocket connection).
+                return {
+                        Run: function(body, output, options) {
+                                // Compile and run the program 'body' with 'options'.
+				// Call the 'output' callback to display program output.
+                                return {
+                                        Kill: function() {
+                                                // Kill the running program.
+                                        }
+                                };
+                        }
+                };
+        }
+
+	// The output callback is called multiple times, and each time it is
+	// passed an object of this form.
+        var write = {
+                Kind: 'string', // 'start', 'stdout', 'stderr', 'end'
+                Body: 'string'  // content of write or end status message
+        }
+
+	// The first call must be of Kind 'start' with no body.
+	// Subsequent calls may be of Kind 'stdout' or 'stderr'
+	// and must have a non-null Body string.
+	// The final call should be of Kind 'end' with an optional
+	// Body string, signifying a failure ("killed", for example).
+
+	// The output callback must be of this form.
+	// See PlaygroundOutput (below) for an implementation.
+        function outputCallback(write) {
+        }
+*/
+
+function HTTPTransport() {
+	'use strict';
+
+	// TODO(adg): support stderr
+
+	function playback(output, events) {
+		var timeout;
+		output({Kind: 'start'});
+		function next() {
+			if (!events || events.length === 0) {
+				output({Kind: 'end'});
+				return;
+			}
+			var e = events.shift();
+			if (e.Delay === 0) {
+				output({Kind: 'stdout', Body: e.Message});
+				next();
+				return;
+			}
+			timeout = setTimeout(function() {
+				output({Kind: 'stdout', Body: e.Message});
+				next();
+			}, e.Delay / 1000000);
+		}
+		next();
+		return {
+			Stop: function() {
+				clearTimeout(timeout);
+			}
+		}
+	}
+
+	function error(output, msg) {
+		output({Kind: 'start'});
+		output({Kind: 'stderr', Body: msg});
+		output({Kind: 'end'});
+	}
+
+	var seq = 0;
+	return {
+		Run: function(body, output, options) {
+			seq++;
+			var cur = seq;
+			var playing;
+			$.ajax('/compile', {
+				type: 'POST',
+				data: {'version': 2, 'body': body},
+				dataType: 'json',
+				success: function(data) {
+					if (seq != cur) return;
+					if (!data) return;
+					if (playing != null) playing.Stop();
+					if (data.Errors) {
+						error(output, data.Errors);
+						return;
+					}
+					playing = playback(output, data.Events);
+				},
+				error: function() {
+					error(output, 'Error communicating with remote server.');
+				}
+			});
+			return {
+				Kill: function() {
+					if (playing != null) playing.Stop();
+					output({Kind: 'end', Body: 'killed'});
+				}
+			};
+		}
+	};
+}
+
+function SocketTransport() {
+	'use strict';
+
+	var id = 0;
+	var outputs = {};
+	var started = {};
+	var websocket = new WebSocket('ws://' + window.location.host + '/socket');
+
+	websocket.onclose = function() {
+		console.log('websocket connection closed');
+	}
+
+	websocket.onmessage = function(e) {
+		var m = JSON.parse(e.data);
+		var output = outputs[m.Id];
+		if (output === null)
+			return;
+		if (!started[m.Id]) {
+			output({Kind: 'start'});
+			started[m.Id] = true;
+		}
+		output({Kind: m.Kind, Body: m.Body});
+	}
+
+	function send(m) {
+		websocket.send(JSON.stringify(m));
+	}
+
+	return {
+		Run: function(body, output, options) {
+			var thisID = id+'';
+			id++;
+			outputs[thisID] = output;
+			send({Id: thisID, Kind: 'run', Body: body, Options: options});
+			return {
+				Kill: function() {
+					send({Id: thisID, Kind: 'kill'});
+				}
+			};
+		}
+	};
+}
+
+function PlaygroundOutput(el) {
+	'use strict';
+
+	return function(write) {
+		if (write.Kind == 'start') {
+			el.innerHTML = '';
+			return;
+		}
+
+		var cl = 'system';
+		if (write.Kind == 'stdout' || write.Kind == 'stderr')
+			cl = write.Kind;
+
+		var m = write.Body;
+		if (write.Kind == 'end') 
+			m = '\nProgram exited' + (m?(': '+m):'.');
+
+		if (m.indexOf('IMAGE:') === 0) {
+			// TODO(adg): buffer all writes before creating image
+			var url = 'data:image/png;base64,' + m.substr(6);
+			var img = document.createElement('img');
+			img.src = url;
+			el.appendChild(img);
+			return;
+		}
+
+		// ^L clears the screen.
+		var s = m.split('\x0c');
+		if (s.length > 1) {
+			el.innerHTML = '';
+			m = s.pop();
+		}
+
+		m = m.replace(/&/g, '&amp;');
+		m = m.replace(/</g, '&lt;');
+		m = m.replace(/>/g, '&gt;');
+
+		var needScroll = (el.scrollTop + el.offsetHeight) == el.scrollHeight;
+
+		var span = document.createElement('span');
+		span.className = cl;
+		span.innerHTML = m;
+		el.appendChild(span);
+
+		if (needScroll)
+			el.scrollTop = el.scrollHeight - el.offsetHeight;
+	}
+}
+
+(function() {
+  function lineHighlight(error) {
+    var regex = /prog.go:([0-9]+)/g;
+    var r = regex.exec(error);
+    while (r) {
+      $(".lines div").eq(r[1]-1).addClass("lineerror");
+      r = regex.exec(error);
+    }
+  }
+  function highlightOutput(wrappedOutput) {
+    return function(write) {
+      if (write.Body) lineHighlight(write.Body);
+      wrappedOutput(write);
+    }
+  }
+  function lineClear() {
+    $(".lineerror").removeClass("lineerror");
+  }
+
+  // opts is an object with these keys
+  //  codeEl - code editor element
+  //  outputEl - program output element
+  //  runEl - run button element
+  //  fmtEl - fmt button element (optional)
+  //  fmtImportEl - fmt "imports" checkbox element (optional)
+  //  shareEl - share button element (optional)
+  //  shareURLEl - share URL text input element (optional)
+  //  shareRedirect - base URL to redirect to on share (optional)
+  //  toysEl - toys select element (optional)
+  //  enableHistory - enable using HTML5 history API (optional)
+  //  transport - playground transport to use (default is HTTPTransport)
+  function playground(opts) {
+    var code = $(opts.codeEl);
+    var transport = opts['transport'] || new HTTPTransport();
+    var running;
+  
+    // autoindent helpers.
+    function insertTabs(n) {
+      // find the selection start and end
+      var start = code[0].selectionStart;
+      var end   = code[0].selectionEnd;
+      // split the textarea content into two, and insert n tabs
+      var v = code[0].value;
+      var u = v.substr(0, start);
+      for (var i=0; i<n; i++) {
+        u += "\t";
+      }
+      u += v.substr(end);
+      // set revised content
+      code[0].value = u;
+      // reset caret position after inserted tabs
+      code[0].selectionStart = start+n;
+      code[0].selectionEnd = start+n;
+    }
+    function autoindent(el) {
+      var curpos = el.selectionStart;
+      var tabs = 0;
+      while (curpos > 0) {
+        curpos--;
+        if (el.value[curpos] == "\t") {
+          tabs++;
+        } else if (tabs > 0 || el.value[curpos] == "\n") {
+          break;
+        }
+      }
+      setTimeout(function() {
+        insertTabs(tabs);
+      }, 1);
+    }
+  
+    function keyHandler(e) {
+      if (e.keyCode == 9 && !e.ctrlKey) { // tab (but not ctrl-tab)
+        insertTabs(1);
+        e.preventDefault();
+        return false;
+      }
+      if (e.keyCode == 13) { // enter
+        if (e.shiftKey) { // +shift
+          run();
+          e.preventDefault();
+          return false;
+        } if (e.ctrlKey) { // +control
+          fmt();
+          e.preventDefault();
+        } else {
+          autoindent(e.target);
+        }
+      }
+      return true;
+    }
+    code.unbind('keydown').bind('keydown', keyHandler);
+    var outdiv = $(opts.outputEl).empty();
+    var output = $('<pre/>').appendTo(outdiv);
+  
+    function body() {
+      return $(opts.codeEl).val();
+    }
+    function setBody(text) {
+      $(opts.codeEl).val(text);
+    }
+    function origin(href) {
+      return (""+href).split("/").slice(0, 3).join("/");
+    }
+  
+    var pushedEmpty = (window.location.pathname == "/");
+    function inputChanged() {
+      if (pushedEmpty) {
+        return;
+      }
+      pushedEmpty = true;
+      $(opts.shareURLEl).hide();
+      window.history.pushState(null, "", "/");
+    }
+    function popState(e) {
+      if (e === null) {
+        return;
+      }
+      if (e && e.state && e.state.code) {
+        setBody(e.state.code);
+      }
+    }
+    var rewriteHistory = false;
+    if (window.history && window.history.pushState && window.addEventListener && opts.enableHistory) {
+      rewriteHistory = true;
+      code[0].addEventListener('input', inputChanged);
+      window.addEventListener('popstate', popState);
+    }
+
+    function setError(error) {
+      if (running) running.Kill();
+      lineClear();
+      lineHighlight(error);
+      output.empty().addClass("error").text(error);
+    }
+    function loading() {
+      lineClear();
+      if (running) running.Kill();
+      output.removeClass("error").text('Waiting for remote server...');
+    }
+    function run() {
+      loading();
+      running = transport.Run(body(), highlightOutput(PlaygroundOutput(output[0])));
+    }
+
+    function fmt() {
+      loading();
+      var data = {"body": body()}; 
+      if ($(opts.fmtImportEl).is(":checked")) {
+        data["imports"] = "true";
+      }
+      $.ajax("/fmt", {
+        data: data,
+        type: "POST",
+        dataType: "json",
+        success: function(data) {
+          if (data.Error) {
+            setError(data.Error);
+          } else {
+            setBody(data.Body);
+            setError("");
+          }
+        }
+      });
+    }
+
+    $(opts.runEl).click(run);
+    $(opts.fmtEl).click(fmt);
+
+    if (opts.shareEl !== null && (opts.shareURLEl !== null || opts.shareRedirect !== null)) {
+      var shareURL;
+      if (opts.shareURLEl) {
+        shareURL = $(opts.shareURLEl).hide();
+      }
+      var sharing = false;
+      $(opts.shareEl).click(function() {
+        if (sharing) return;
+        sharing = true;
+        var sharingData = body();
+        $.ajax("/share", {
+          processData: false,
+          data: sharingData,
+          type: "POST",
+          complete: function(xhr) {
+            sharing = false;
+            if (xhr.status != 200) {
+              alert("Server error; try again.");
+              return;
+            }
+            if (opts.shareRedirect) {
+              window.location = opts.shareRedirect + xhr.responseText;
+            }
+            if (shareURL) {
+              var path = "/p/" + xhr.responseText;
+              var url = origin(window.location) + path;
+              shareURL.show().val(url).focus().select();
+  
+              if (rewriteHistory) {
+                var historyData = {"code": sharingData};
+                window.history.pushState(historyData, "", path);
+                pushedEmpty = false;
+              }
+            }
+          }
+        });
+      });
+    }
+  
+    if (opts.toysEl !== null) {
+      $(opts.toysEl).bind('change', function() {
+        var toy = $(this).val();
+        $.ajax("/doc/play/"+toy, {
+          processData: false,
+          type: "GET",
+          complete: function(xhr) {
+            if (xhr.status != 200) {
+              alert("Server error; try again.");
+              return;
+            }
+            setBody(xhr.responseText);
+          }
+        });
+      });
+    }
+  }
+
+  window.playground = playground;
+})();
diff --git a/godoc/static/search.html b/godoc/static/search.html
new file mode 100644
index 0000000..e0d13b9
--- /dev/null
+++ b/godoc/static/search.html
@@ -0,0 +1,18 @@
+<!--
+	Copyright 2009 The Go Authors. All rights reserved.
+	Use of this source code is governed by a BSD-style
+	license that can be found in the LICENSE file.
+-->
+{{with .Alert}}
+	<p>
+	<span class="alert" style="font-size:120%">{{html .}}</span>
+	</p>
+{{end}}
+{{with .Alt}}
+	<p>
+	<span class="alert" style="font-size:120%">Did you mean: </span>
+	{{range .Alts}}
+		<a href="search?q={{urlquery .}}" style="font-size:120%">{{html .}}</a>
+	{{end}}
+	</p>
+{{end}}
diff --git a/godoc/static/search.txt b/godoc/static/search.txt
new file mode 100644
index 0000000..0ae0c08
--- /dev/null
+++ b/godoc/static/search.txt
@@ -0,0 +1,54 @@
+QUERY
+	{{.Query}}
+
+{{with .Alert}}{{.}}
+{{end}}{{/* .Alert */}}{{/*
+
+---------------------------------------
+
+*/}}{{with .Alt}}DID YOU MEAN
+
+{{range .Alts}}	{{.}}
+{{end}}
+{{end}}{{/* .Alt */}}{{/*
+
+---------------------------------------
+
+*/}}{{with .Pak}}PACKAGE {{$.Query}}
+
+{{range .}}	{{pkgLink .Pak.Path}}
+{{end}}
+{{end}}{{/* .Pak */}}{{/*
+
+---------------------------------------
+
+*/}}{{range $key, $val := .Idents}}{{if $val}}{{$key.Name}}
+{{range $val}}    {{.Path}}.{{.Name}}
+{{end}}
+{{end}}{{end}}{{/* .Idents */}}{{/*
+
+---------------------------------------
+
+*/}}{{with .Hit}}{{with .Decls}}PACKAGE-LEVEL DECLARATIONS
+
+{{range .}}package {{.Pak.Name}}
+{{range $file := .Files}}{{range .Groups}}{{range .}}	{{srcLink $file.File.Path}}:{{infoLine .}}{{end}}
+{{end}}{{end}}{{/* .Files */}}
+{{end}}{{end}}{{/* .Decls */}}{{/*
+
+---------------------------------------
+
+*/}}{{with .Others}}LOCAL DECLARATIONS AND USES
+
+{{range .}}package {{.Pak.Name}}
+{{range $file := .Files}}{{range .Groups}}{{range .}}	{{srcLink $file.File.Path}}:{{infoLine .}}
+{{end}}{{end}}{{end}}{{/* .Files */}}
+{{end}}{{end}}{{/* .Others */}}{{end}}{{/* .Hit */}}{{/*
+
+---------------------------------------
+
+*/}}{{if .Textual}}{{if .Complete}}{{.Found}} TEXTUAL OCCURRENCES{{else}}MORE THAN {{.Found}} TEXTUAL OCCURRENCES{{end}}
+
+{{range .Textual}}{{len .Lines}}	{{srcLink .Filename}}
+{{end}}{{if not .Complete}}...	...
+{{end}}{{end}}
diff --git a/godoc/static/searchcode.html b/godoc/static/searchcode.html
new file mode 100644
index 0000000..a032e64
--- /dev/null
+++ b/godoc/static/searchcode.html
@@ -0,0 +1,64 @@
+<!--
+	Copyright 2009 The Go Authors. All rights reserved.
+	Use of this source code is governed by a BSD-style
+	license that can be found in the LICENSE file.
+-->
+{{$query_url := urlquery .Query}}
+{{if not .Idents}}
+	{{with .Pak}}
+		<h2 id="Packages">Package {{html $.Query}}</h2>
+		<p>
+		<table class="layout">
+		{{range .}}
+			{{$pkg_html := pkgLink .Pak.Path | html}}
+			<tr><td><a href="/{{$pkg_html}}">{{$pkg_html}}</a></td></tr>
+		{{end}}
+		</table>
+		</p>
+	{{end}}
+{{end}}
+{{with .Hit}}
+	{{with .Decls}}
+		<h2 id="Global">Package-level declarations</h2>
+		{{range .}}
+			{{$pkg_html := pkgLink .Pak.Path | html}}
+			<h3 id="Global_{{$pkg_html}}">package <a href="/{{$pkg_html}}">{{html .Pak.Name}}</a></h3>
+			{{range .Files}}
+				{{$file := .File.Path}}
+				{{range .Groups}}
+					{{range .}}
+						{{$line := infoLine .}}
+						<a href="{{queryLink $file $query_url $line | html}}">{{$file}}:{{$line}}</a>
+						{{infoSnippet_html .}}
+					{{end}}
+				{{end}}
+			{{end}}
+		{{end}}
+	{{end}}
+	{{with .Others}}
+		<h2 id="Local">Local declarations and uses</h2>
+		{{range .}}
+			{{$pkg_html := pkgLink .Pak.Path | html}}
+			<h3 id="Local_{{$pkg_html}}">package <a href="/{{$pkg_html}}">{{html .Pak.Name}}</a></h3>
+			{{range .Files}}
+				{{$file := .File.Path}}
+				<a href="{{queryLink $file $query_url 0 | html}}">{{$file}}</a>
+				<table class="layout">
+				{{range .Groups}}
+					<tr>
+					<td width="25"></td>
+					<th align="left" valign="top">{{index . 0 | infoKind_html}}</th>
+					<td align="left" width="4"></td>
+					<td>
+					{{range .}}
+						{{$line := infoLine .}}
+						<a href="{{queryLink $file $query_url $line | html}}">{{$line}}</a>
+					{{end}}
+					</td>
+					</tr>
+				{{end}}
+				</table>
+			{{end}}
+		{{end}}
+	{{end}}
+{{end}}
diff --git a/godoc/static/searchdoc.html b/godoc/static/searchdoc.html
new file mode 100644
index 0000000..679c02c
--- /dev/null
+++ b/godoc/static/searchdoc.html
@@ -0,0 +1,24 @@
+<!--
+	Copyright 2009 The Go Authors. All rights reserved.
+	Use of this source code is governed by a BSD-style
+	license that can be found in the LICENSE file.
+-->
+{{range $key, $val := .Idents}}
+	{{if $val}}
+		<h2 id="{{$key.Name}}">{{$key.Name}}</h2>
+		{{range $val}}
+			{{$pkg_html := pkgLink .Path | html}}
+			{{if eq "Packages" $key.Name}}
+				<a href="/{{$pkg_html}}">{{html .Path}}</a>
+			{{else}}
+				{{$doc_html := docLink .Path .Name| html}}
+				<a href="/{{$pkg_html}}">{{html .Package}}</a>.<a href="{{$doc_html}}">{{.Name}}</a>
+			{{end}}
+			{{if .Doc}}
+				<p>{{comment_html .Doc}}</p>
+			{{else}}
+				<p><em>No documentation available</em></p>
+			{{end}}
+		{{end}}
+	{{end}}
+{{end}}
diff --git a/godoc/static/searchtxt.html b/godoc/static/searchtxt.html
new file mode 100644
index 0000000..7e4a978
--- /dev/null
+++ b/godoc/static/searchtxt.html
@@ -0,0 +1,42 @@
+<!--
+	Copyright 2009 The Go Authors. All rights reserved.
+	Use of this source code is governed by a BSD-style
+	license that can be found in the LICENSE file.
+-->
+{{$query_url := urlquery .Query}}
+{{with .Textual}}
+	{{if $.Complete}}
+		<h2 id="Textual">{{html $.Found}} textual occurrences</h2>
+	{{else}}
+		<h2 id="Textual">More than {{html $.Found}} textual occurrences</h2>
+		<p>
+		<span class="alert" style="font-size:120%">Not all files or lines containing "{{html $.Query}}" are shown.</span>
+		</p>
+	{{end}}
+	<p>
+	<table class="layout">
+	{{range .}}
+		{{$file := .Filename}}
+		<tr>
+		<td align="left" valign="top">
+		<a href="{{queryLink $file $query_url 0}}">{{$file}}</a>:
+		</td>
+		<td align="left" width="4"></td>
+		<th align="left" valign="top">{{len .Lines}}</th>
+		<td align="left" width="4"></td>
+		<td align="left">
+		{{range .Lines}}
+			<a href="{{queryLink $file $query_url .}}">{{html .}}</a>
+		{{end}}
+		{{if not $.Complete}}
+			...
+		{{end}}
+		</td>
+		</tr>
+	{{end}}
+	{{if not $.Complete}}
+		<tr><td align="left">...</td></tr>
+	{{end}}
+	</table>
+	</p>
+{{end}}
diff --git a/godoc/static/static.go b/godoc/static/static.go
new file mode 100644
index 0000000..3009e24
--- /dev/null
+++ b/godoc/static/static.go
@@ -0,0 +1,3544 @@
+// DO NOT EDIT ** This file was generated by "go generate" ** DO NOT EDIT //
+
+package static
+
+var Files = map[string]string{
+	"analysis/call3.png": "\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x03N\x00\x00\x01\xea\b\x03\x00\x00\x00\x04l\xeeb\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x02\xfdPLTE\x00\x01\x00\x04\x06\x03\x06\t\x05\x0e\x10\r\x16\x17\x15$\x18\x0f\x1e\x1d\x17!# #$\"$%#&(%)(\"()'-+\x1f*+),-+-/,41&J-\x1202/241S/\x0e564,7M796<:.:<9!?p=?<B@4@B?DECLH9?JVHIGvD\x13JLIMOLVQ@QRPUWT_ZHY[X,`\xae7]\xaduWG8`\xaa\\^[A`\xa5:b\xab;b\xac<c\xad_a^=d\xae@f\xb0bdaRe\x99lfP\x90^8Ci\xb4egdMj\xafhjgFm\xb1Ol\xb2fj\x90Ip\xb4\xa7c\"}iflnkKr\xb7oqnNu\xba\xb3h\"{s[Xv\xb6tvs\u007fr\u007fZx\xb8ry\x81]{\xbb\\}\xb6y{x_}\xbeX\x80\xbf`\x80\xba\x96xpb\x80\xc0}\u007f|\x89\x80eb\x83\xbd\u007f\x81~\x9a{oe\x85\xc0\x82\x83\x81k\x85\xbb\xa7}fh\x88\xc3m\x88\xbdj\x8aľ~G\x87\x89\x86q\x8c\xc1\x8a\x8c\x89\xbe\x82Y\x96\x8cnt\x8e\xc4z\x8f\xc0\x8f\x91\x8ex\x92\xc8~\x93\xc3x\x95\xc4z\x94ʒ\x94\x91\x80\x95\xc5ӊJz\x98ǂ\x96Ǡ\x96w|\x99ȕ\x97\x94\x83\x98ɂ\x9aė\x99\x96\x86\x9a\xcc\xe4\x8dA\x80\x9d̅\x9dǚ\x9c\x98\x83\xa0Ϝ\x9e\x9b\xa8\x9e\u007f\x88\xa0\xcb\xf3\x915\x8a\xa2̙\xa0\xb5\x9f\xa1\x9e\x8e\xa2Nj\xa3Ρ\xa3\xa0\xfa\x95/\xa2\xa4\xa1\x8e\xa6\xd0\xff\x952\x92\xa6˳\xa6\x82\xa5\xa7\xa4\x91\xa9ԧ\xa9\xa6\x94\xac֙\xacҪ\xac\xa8\xb9\xac\x88\x9e\xaeΛ\xafԭ\xaf\xac\x9d\xb1֢\xb1ѯ\xb1\xae\xa1\xb5ڥ\xb5ճ\xb5\xb2µ\x90\xa3\xb7ݵ\xb7\xb4\xac\xb7Ҫ\xb9ٷ\xb9\xb6\xac\xbcܺ\xbc\xb9\xb1\xbd\u05ef\xbe\xdf˾\x98\xbd\xbf\xbc\xb1\xc0\xe0\xba\xc1\xd6\xc0¾\xb7\xc2\xdd\xc2\xc4\xc1\xb9\xc5\xe0\xbd\xc5\xda\xc4\xc6û\xc7\xe2\xd6ǝ\xbc\xc8\xe3\xbb\xca\xde\xc7\xc9ƿ\xca\xe5\xc6\xca\xda\xc0\xcc\xda\xca\xcc\xc8\xc1\xcc\xe7\xbf\xcf\xe2\xc2\xce\xe9\xcd\xcf\xcc\xc4\xd0\xde\xcb\xcf\xdf\xc8\xd0\xe5\xcf\xd1\xce\xdfѥ\xca\xd1\xe7\xcc\xd3\xe9\xd2\xd4\xd1\xcc\xd5\xdd\xd3\xd3\xde\xce\xd6\xeb\xd6\xd8\xd5\xd0\xd8\xed\xe7ج\xd2\xda\xe2\xcb\xdb\xee\xd5\xd9\xe9\xd9\xd9\xe4\xd7\xdb\xeb\xda\xdc\xd9\xd8\xdc\xec\xd2\xde\xec\xd9\xdd\xed\xdc\xdd\xe7\xdd\xdf\xdc\xd4\xe0\xef\xdb\xdf\xef\xf0\xe0\xb3\xdc\xe1\xe4\xdd\xe1\xf1\xe0\xe2\xdf\xd9\xe5\xf4\xe0\xe5\xe8\xe0\xe4\xf4\xe3\xe5\xe2\xde\xe6\xef\xe7\xe5\xe9\xe5\xe7\xe4\xe6\xe7\xf1\xe0\xe9\xf1\xe4\xe9\xeb\xe7\xe9\xe6\xe3\xec\xf4\xeb\xed\xea\xe6\xee\xf7\xec\xed\xf7\xe8\xf0\xf9\xf0\xf0\xfb\xf0\xf3\xef\xf4\xf2\xf6\xee\xf4\xf6\xf0\xf6\xf8\xf4\xf7\xf3\xf2\xf7\xfa\xf5\xfa\xfd\xf8\xfa\xf7\xfd\xfb\xff\xf7\xfd\xff\xf9\xff\xff\xfe\xff\xfc\x9cx\xeb\xab\x00\x00 \x00IDATx^\xed\x9d\x0fp\x14ׁ\xa7C\x9c\xf3\x83\x89-\x94\x95V\xa7\xb0\x04r\xac8\x14\xd37l\tF\\N\xa0\xd1\xe9N\xb27\xd2q\x0e\x845\xc1+\xbc\xb6N\xb0\x11\xb2\x1d\xd8(K!\x8e\x15\n\xa9S \"\x18\bZ\x82\x10QJ\x12\b,\x84A\x90\n\x10\xe1\"\xe0\x80b\xc9v\xe2\x12Nd\x1bk\x89\xd6\xc4j;\x80\x8d\x8d\xf0\xd4Խ\xd7\xdd3\xf3\xba\xa7{zz\xd4j\x8dF\xbf\xaf\xa8\xa1\xe7\xe9\xbd\xd7\u007f\xa6\xbf\xe9\xee7=\xbf\xf9\x8c?fD\x00\x80\x8aϘIc\x8cY\xd7\x00L4\xa0\x13\x00\xb6\x01\x9d\x00\xb0\r\xe8\x04\x80m@'\x00l\x03:%27\xcc*\x00{\x81N\tKwA\x1aYhV\t\xd8\ntJXfάj|ɬ\x12\xb0\x15Gu\xea\xde_[]w\xa8\x9fM\xde8\xb1\xa7z\xd7\x19m\xa9\xd3\xf4\x15\xa7%͋\xf2\x8c\xa81\xb5ެJ\\q\x82\xec7\xab\x02\xec\xc6I\x9dz\xab\xea\xcft\x9f\xd9U;@\xa7\xebk\x8e_h\xafnה:Mfچ\x82\xa4>\xb3Z2\xf5Sw\x99U\x89+\xdaI\xb3Y\x15`7N\xea\xd4U\xd5M\x1f\a\xaa\xe8A\xe9x5ۉ\xbb\xaa\xfbU\xa5N\xd3G։\xe2\x98\x1c\x16\x1d\xa0\x8d\xb4\x99U\x01v\xe3\xa4N\xa2t\x00\xeae\xfa\xd4\xcb'\"\xb5\xed\xaaR\xa7\xe9\"\xe3\xeb\xfc\xcd\x12\xd0i\fpT'\xca@w\x1dۅw\xc9'\"{\xeaU\xa5\x8e2\x98J$\x96J\xcf6d$el\xa0\xff\x9f\x98BȪ\xae\xdc\xe9I\xf3\x06\xf9\xca}I\x84L\xae\xd5\xeb&H\xd7\xc2TWڼ\xb07\x85\x9a\xb4*\xf6_w\xb2<7\x92\xcc\xd7\xe0\xe7ֿ(\xdd5m\xc1\tZZL\\UKg$=$\xd5\xec\xcdMM_\xba4uj\x1d\x9d\xae\x9d3u\xc6R\xedѴ\xf3\x89|\xf7\xe2\xa7\xf2\x874\xc5b\x13tr\x1egu\uab6a\xaa\xaaa\xfbáZ\xb6\xb7\x0e\xd4\xecR\x95:\xcb\xf1\xe6\xed\xa4\xac\xb9Y\xdai\v\\\xab\xeaW\xb9r\xe9\"\xd5\xd5N\x9b\x91<mi.Q\x0f\x8a\xb577\xbb\xcat\xbbQh\x9a\x9aQ\xd1XF*\xb4\xe5\v\xc9<\xf6\xdf`\xcd:\x99\x1a^S~n\xf5\xe4ᦺ\x05\x93\xa9\x03gj\xa7\x90Բ\x8ad6\xca=83}C\x99+\xa9\xfa!\xdaq\xc1\xe4\xe2\xfau\xa9\x19ꡓ_\xce}\xa6\xa5\xe3\xc0b\xe1]U\xe9`o\xd3\xec\x14\xe77\xe9\x84\xc7Y\x9d\xc4\xde\xeeSu\xb5\xf4e\uebe9\xef\x1d\xe8\xdeSU\xa7*u\x9a\xe0\xc9\xde~i\x14L~\x143Hf\xbf\xde%UR$\x9d\x06\xa6ͣ'\xad\x83ua\xe3\x1a\x17\xd6\\\x90\xfe\xef\xbd ӫ\xf9{pn\x03ul\x96\xb3\xa4O\x8a\\)T\xf2\xdcT:\xb5\x9d\xd0\xe3\xd5\x06r\x8aN֓\x1a\x91\x9d\xc3mW\xb5?\xe0e\"\xed\xcbQ\x1f\x9d\x16\xd2\xe3\xa0\xe3\xc7{\xe0\xb4N\"\xdb\xe5\x1a\xe9c_==$\xb5\xd5\xefQ\x97:LP\xa7\x82Y\xd2\u007f3\v\xd8c\x86K\xffӚ\x88:Փ\xe3\x11\xfeJ\xad\"\x01.\xa8\xff\x10\x9a[\xef\x86yӓ\x89\xb4$.\xb6 e.\xfa\xb0\"Ed\xcbɶӢ郌\xf4\x02U\xfb\u05fc\x85\x1b\x0f\xfcjHs\xae\xf7\xd2\xfe\xaa\x998:9\x8f\x93:)C\xe1'\xaa\xe4g}7\xc4\xdaC\xdaRG\t\xea4g\x81\xf4\u07fc\xd9\xec1c\xb6~\xed\x88:\xad#&\x03\xfd\xcd\xf52\xda\xd1\xeb\xe0\xdc\xdaҦ\xad\xd8՜)\xeb\xc4f%\xe9TAz\xd9a\x93\x1d\x9d2\x14\x1f5w:\\;P^$\xe4\xed\r\xbbvjƵ\x93\xf38\xa9Sm\x93\xf4\xdf\xf1j\xfa ]AHc\xe4|\xa9Ä\x8eNӥ\xff\xa6\xcbG'\x83;s\"\xea\xd4hrt2$8\xb7\x99s\x98\x90\v5:\xbd4y\xdeK'f\xcca\x85\xb9\xd3\xdb%ԧ\x8b\xe7\xb6R\x91\xae\xb5\xcc? j\xc0\xc8\xde\x18\xe0\xa8Nҥ\x89tZw\xa6\x8a\xee\x14\xfd\x92I\\\xa9\xd3\x04u\xaa\x97.H\xb6\xcbO3\x16\xe9\xd7\x0e\xe9t\xa1,̝\xfe\xf4L\xf6\x0eQ\xbcT\xfb\x87\xc0\xb5\x93\x11\xc1\xb9Mc^\xdd\xc8\xd0\xe8\xd4N\xd2\bɔ\x86K\xf6\x13\xe9J\xf3\xf15\xaa\xf6;\x85\x0e\xf6\xdf\xcagE\r\xd0i\fpR\xa7\xae\xaa\xc63\xddg\xea\xd8\xfd\x0f]U\xed\xdd\xc7k\xeb\aԥ\xce\"\x8f\xec\xc9\xfb\\\xee\xe4\x15\xf5+&\xe7R\xadۚgd67k\x15\xa0\xc5ͮ\x82\xe6f\xf9rd\x01\x99\x1a6\xe4\xd0\xf4\xc0\xcc\r\xf5\xc5$\xec\x18\xbb@\x1e\xd9Ӈ\x9f[\x19Y\xb4aM\x06I\xadh릳j\x13\xdb\v\\\xcd\xdd\xe2qWc}\xb32\xb6\xbe\x82,\xaa\xdbS@\xd4\xe3\xf5;\x05\xcf\x0f\x8e\x1cyF\x96\x8a\xa7\x9d\x1c\xd2\x16\x81\xd1\xc6I\x9d\xc4\ue9ba\xea]m\x927\xc7\xebjꏇ\x95:\xc9@\x8at%2E\xbe\x1bcݬ\xa4Y\xd2\xe7N\x93\xa5R\xad\x02\xedr1\x91/\xf0\xaa\xa7\xea\xbc\xf3w-JO\x9e\x1d~\x1fRMj\x84\x8bB~n7*f\xb8R\x17\xd5Lwe\x16\xd3\"ש\xa9\xf4\xb1X<\xe4b\x15\\\x99\xec\xe2Iܟ\x99\x9a2Gs'\xdeO\x97\xef\xccw{W\x86\xd9$\xf6NYt\xa27\xca\xfb\x11\x81M8\xaaS°\x8784j\xd6;\xb5\xb8wp\xb0\xaf}a\f\xc3t{f\x86\r[\x80Q\x06:\xc5@M\xca\xc3fUlbO\x8a2\x11\xd3\xed\xec\xbd'\xc6\xe0έ\t\rt\xb2Nw\xeaR\xa7NM\xdb'Kgy\xe2\xa9\xc91\x0e\x1c\x02G\x81N\xf1MA\xd2\xc3ۛ\xb6?\x9c\xe4\xd4\xe1\x10\x8c\b\xe8\x14\xe7\xd4?\x94\xeeJ\x9f\x17˩\x1ep\x1e\xe8\x04\x80m@\xa7D\xe4G!̪\x02;\x81N\x89\bt\x1a#\xa0S\"\x02\x9d\xc6\b蔈@\xa71\x02:%\"\xd0i\x8c\x80N\x89\bt\x1a#\xa0S\"\x02\x9d\xc6\b蔈(*\xfd\xe3\u007f\xff\xbeJ\xa7\xbe9{D0\x9a8\xaa\x93~\xa82\xe5T\x15>\xf6\xb7H\x87\xf7\x88\xf1\x1fe\x9b\xfeA\xf8{\xcdѩb\xb2\xfa\xbb\x87\xc0f\x9c\xd4I?T\x99\xd2W}(r\x86\x1d\b㈧\xc5\xf8\x8f\xb2M\xee\u007f\f;٫\x9f\xb2N\xbf\x05\xb0\x05'u\xd2\x0fU\xa6\xd47vC'\xab\x84e\xadp0\x9b\xfe\xaf\xfb\xeft\xae\x9dV\xb9\xf0\x9d\x8dQ\xc4I\x9d\fB\x95\xc5S5\x03\xd0\xc9V\x98G\xff\xeb\xbf~\xffG?\xfcяn\f\xaa\xbe\x91ۯ\xc9\x15\x03\xb6\xe2\xa8N\xa2n\xa8r\u007fu\x97\x98@:\x19\xc42\x8b\x91\xf3\x95\xdf\xcdso\xf5z;6欼&\x8a\xd7ʽ\xee\xfc\xa7.\xd2\xe2\u007f\x16\xdc\xfb\xd6{s\x9e\xfa\x8djR\xbc\xe6\x11\x04A:٣\xa5\a6\x16y\x9ex\x9d=\xb9\xb6v\xb1\xf7_\xfee\xb1\xa7\x85\xda\xf4ÿ\xf9\x9f\u007f\xf9\x17\u007f\xf1\xd7\u007f9s\xe6\xd2߬^\xec\xf6>\xf5\xba<\xa3UIN}Wk\"\xe2\xacN\xba\xa1\xca\xf5\x8db\"\xe9d\x14\xcbl\x92\xafܑ-l,\x11\x16\xef\xcc\xdbG\xaf\x8b\x84\xf5\x1d-O\t\xe7D\xf1b\x8b[\xc8߹3\xdfs\x91\x9f\x14\xc5s\x9d\x9d\xf3w\xb2f\xacԻso\xf6j:=T\xe4\xdd\xf7\x83\xf9\x9e\x03O\xec\xa3:\xfd\x93\xfb?L\xce̜\x94\x949{\xd2_}}o\xc7Na\x9f<\x9fC\b8\x1aE\x9c\xd5I/T\xf9\f\xf3+\x81t\x12\rc\x99#\xe7+{\u05ca\x1d\xc2\x11\xf1\x99\xf5\xa2x\xbd\x85\x1e\xa2\x86\x960EĬBv\xb8\xca_\xae\x9e\xa4\xc8:\xd1\xd2\x1cz\xdcY\xeb\xa5S-\x025m\x1f{`\x83\xe4\xee\xfb\xd6\xf8\xfdg>\xf4\u07fb\xef?\xd2\x19\r\xb1.\x19\xddd|\xfdL\xd5\xf8\xc2a\x9dİP\xe5\xfe\xea37n\xdcx\xa96\x912w\x8cb\x99e\f\xf2\x95\xbd-\xe29ᚸu\xadȒ]\x9f(\xcc\x16\x96\xb0⬭\xecq\x1f\xfd\v?)r:=C\x1fvfч\xad9\xf4\xe1e\xaa\xa4\xac\xd3_L\x9a4I\\4i\xd2g\xfe7\x9fb֭\xc98\av\xe2\xa4N\xba\xa1\xca\x17\xaa\x02$ΐ\x93Q,\xb3\x82~\xbe\xb2\xb7C<\xe7\x16%\x9d\xcey\xf3\xb7\x1e\xe9,\x91u\x92\xac\xe9dg~ܤ\xc8\xe9\xc4\xfe\x97t\xda7\x97\x8a֡\x1c\x9d\xfeI\xf8?\u007f\xfd\x97T\xa7\xcf\xfd\xa7\xbf:şT\xb6!~o\x14qR'\xfdP\xe5^Ʃ\x9a^\xedOK\x8cc\x8cb\x99#\xc2tʒu*Z~\x9d\x16\x94\xcb:md\x8f\a\xa4\xa3ShR\xd4\xd3\xe95\xe1\x89\xd7.\x16-\x1f\x92t\xfa\xbe\xfb\xef\xbf\xff?\xa8NS\xfe\x9f\xfb\x1c?\x9b2\x97\xf5\x881\x10-\x8e\xea\xa4\x1b\xaa,\x91`\xd7N\xfa\xb1̑\xf3\x959\x9d\xf2\xcb\xe9\xf3\xa1Ge\x9d\xf2\xd8\x05S\xe1J\xf5\xa4\xa8\xa7\xd39!O\x10J\xd8\b\x9e<P\xfeÿe:\x9d\xf2\xaed\x1fQm\x94\\\x14ǒ\x10J\vF\x8a\x93:\xe9\x87*Snt\x9f\xaa\xe9\x8e\xf2\x17\x9f\xe3\x1e\x83Xf\xd1$_\xf9bξ\xeb-\xee\x8b\xd7\xd7R\x1fv\n\xe5\av>*,\xde\xdbIm\x11\xbe\xder\xa0(\xe7e\x91\x9f\x1c\xea\xec\xec\x9c\xfflg\xe75\xf1\xb5N\xf7\xb3\x9dC\xbf|\xd6\xdd\xf9\x9axn~GG\xe7\xeb\xcc\x1d\xf9c\xdc\u007f\x90t\xea\xea\x98_t\xa0c\xa3 \xff&@\x05i7^\x060R\x9c\xd4\xc9 T\x99\x96\xb3K\xa7D9>\x19\xc42\x8b\x91\xf3\x95\x87聥%[\xf0\xb4\b\xc2jqh_Q\x96w\xed\x81\"\xf7Jv\x86\xf7L\xb6w\xedk\xacNh\xf2\x97\x82\xcc\x01\xf1;\xf4\xd1\xfd+\xf61\xd4w\xc4N7+s/\xbf(\xdfd\xf4\xf7\u007f\xf3\xdf$\x9d\x06_.\xf7f/\x97\xef\xf0kN\n\xfbM\x02`#\x8e\xea\x04\xac\x93\xb5SoR\x8f?x\x9e\xfdû\xef^\xfb\xe5\xea\x9ck\xf2-\xb0\u007f\xf7W\xb2N\xa1*\xdb]\x05\xdaϖ\x81\x9d@\xa78'z\x9d\x8e(?\xe89\xb4\xb8C\xd6\xe9G\xffE\xa3S_:n(\x1f]\xa0S\x9c\x13\xbdN\xe7\xd8\x109\xe5\xa2\xf0+\xe5\\0\xec\xe8\x04F\x19\xe8\x14\u05fc.\x8d4h'\xf5\x19z\xc6\xf3lKG˳\x9e\xf5C\xd0i\x8c\x80Nq\x8d4\xd2\xf0\x9avҀ\xa1#Ox\xdd\xde'\x8e\f\x05\xbe\x8d\xfb\xb7\xd0\xc9a\xa0S\"\x02\x9d\xc6\b蔈@\xa71\x02:%0u\xd0\xc9a\xa0S\xc22\xb8a!\xbb\x05v\xc5!\xf8\xe4\x18\xd0)a\x99\xa3|A㳻\xe0\x93S@\xa7De\x80}}\xf0C\xbf\xff\xde}\v\x13\xe5v\xc8\xf8\a:%*\x03\x84dfޗ\x969{\xd2\xc3\xd0\xc9)\xa0S\xa22\xb8\xe7s\x9f\x9dt\u007fJJJf;\xc2V\x9c\x02:%,3\xa6\x97U\x1f\xba\xd0\xd5\xf5\x12\xbe/\xe8\x18\x8e\xea\xa4\x1b\xaa<P#}\xb5\xbd&\x91\xae\x97\x1bS\x83!\xd1}\xc5iI\xf3TA\x18\xdfQ2\xbdFF`\x16\x05\x84\x90\xa4.\x9d\n'\xc8~\x96\xb1\xa7\xc9\xd9\x03\xa3\x8a\x93:\xe9\x87*\xf7U\x1d\xef\xa6$\xd0w\xdb\xe9\xdaM\r\xc6\x05e\xa6m(HR]\xbc\xbc\xde\xe9\x8e|/kT\x04f\xd1\xddܼA7뫝\xa8\xb3(\x80\x038\xa9\x93~\xa8r_U\xa4؟\xf1N\x1fY\x17\x1e\x11frk\xb8U\xdatu\xd2/\x05\xa3\x8a\x93:\xe9\x87*'\xb6N]D\xe7\xb7A\xa0S\xa2\xe2\xa8N\xa2^\xa8r\xc2\xe9ԗD\xc8d\xe9\xab\xfa\x83\xa9r\x9e\x9e\xf6\v\xe5Y\x1b\x9fQґCpQ˺\xa9\xcbb1qU-\x9d\x91\xf4\x10+\v͂\xa1/N\x13tr\x1egu\xd2\vU\xee\xabj\xdcUUۜ@\x83\xb9\xed\xcdͮ2i\xeax\xf3vR\xd6ܬM\x10d\x19*-K<\x17\xf92.jY?u\xf9L\xed\x14\x92ZV\x91,\x85\x8e\x85f!\xea\xea4\xd8\xdb4;EgDo\x92m\x84\xf7\r\x9c\xd6I/T\xb9\xbf\xaa\xf6D\xf7\x99\xba\xed\t\xe4\x93(&\x05\xf6u\xfd\x93\xbd\xa2\xeb\xa2x\xbdh\xb9\xaa\x90\x8bZ\xd6O]\x16])\xd4\xcb\xdcT\xe5YR$\x9d\x16\xd2c\x9b\xde/\xd0Mz\xdb&\xa0\x93.\x0e\xeb$\x86\x85*\x8b\xe2)&\xd2@MB\x9d\x9a\x98\xe8$\xa5#\a\xf2'e\xb8\xa8e\x83\xd4e\xd1\xc5~K\xa6̥<\x8b\xa8\xd3K\xfb\xabf\xea\x1e\x9d\xcc4\x89\x16褋\x93:\xe9\x86*\ahN\xa8$z\x13\x9dT\xe9\xc8\n\\Բ~\xea\xb2(\x9d\xdeE\xa7\x13\xa5Y\xaf\x14:\x8d.N\xea\xa4\x1f\xaa\xdc(\xefoM\t\xf5\xeb\xb8&:\xa9ґ\xa3ƚN\xba\xa5\xd0itqT'\xddP\xe5z\xe9\xb0\xd4W\x13\f\xb1L\x04Lt\xf2^g\xbfƴ2\xfc/\x11qR\xa7Iҿ\b\u007f\x0f\xef\x1b8\xab\x93~\xa8rw\xd5\xfe\xae\x97ګ\x13\xe7\xe04\xd8\xd6\xdc\xec*hn\xee\x0f\x8c\xec\x85\xed\xd6Y\xc2\x13\xbf\xe8X.\x05%GO7\xed\xb4Ml/p5w\xf3\xb3\x90\xee\x8aX\xd7\xdc\x1c\xf6iC\xbb\xdeOe0E\x9e\xfb\x82,ʫ_\xbb\u007f҃\xdf3\xd2\x05:ł\x93:\x19\x84*\xf76\xd6\xd6ԟ\x8a\xd4n|\xd1.\xa7*\x93*q E\x9a\x98rFS\xa3hgy (9z\x8aiO\xaeSS\xe9c17\v\xe9\x9e=Fد\f\xf4NYt\xa2W{\xbf\x1eS\xe4\x8b\xcfɢ|\xf5\x8bϿ\xfa\xfc\x97~f\xa0\vt\x8a\x05Gu\x02N\xb2g&!\xda_ƙ\x14p\x85\xf2\xb9\x9fӇ\x9f\xffgŏ\xef=8\xe9\xfeo\xbd\xfd\xf6\xf3_\xbe\xef\xbe/\xff:\xa8\xd3\xf7>?\xe9\xfe\xaf\xbd\xcdM<\xff\xe5\xcfMz\xf0\xbb\xd0\xc9\x00\xe8\x94\xc0\xf4\x9e\xd0~\x80\x1c\xae\xd3\xfd\x8aM\x9f\xfbޫ\xcfS\xb5\x1e|\xee\xd5_\u007f\xe5+\x01\x9d\xfe\xf5\xc1\u007f\xa5\a\xb0\xafq\x13\x0f~\xf3\u05ef\xfe\xec\xcb\xd0\xc9\x00\xe84\xa1\xe0u\x92O\xf6\x94S\xba/|\xf7\xed \xbf\xbe?\xa0\xd3\x17\u007f\xa6\x18\x17\x9c\xf8\xec\xcf\xe5:\xd0I\x17\xe84\xa1\xe0ubC\x11\xf7\u007fK\xd1iү\xe5\xff\u007fNO\xe6&M\n\xe8t\x9f|C\x117\xf1\xd5\xfb\xbe\xf2\xad\x9fC'#\xa0ӄ\x82\xd7I\xe2\xb9\xcf\xcb\xffߧ\xe8\xf4ů\xfe\xfc\xedW\x83:MR\x8eE\xa1\x89\xb7\u007f\xf6\xb5/\xdf\xf7M\xe8d\x00t\x9aP\x84\xe9\xf4\xe5\xaf)\x1a)'{\x9f}\x95^(\x05u\xfa\xc27\x95j\xc1\t\xc6\xf3\xf7A'\x03\xa0ӄ\x82\xd7\xe9K?{\xf5\xf9\xaf|\xe1UY\x91\xe7\xeeW\x86\"\xbe\xf9\xea\xcf>\x1f\xd4\xe9\xb9\xfb\xbe\xf5\xebW\x9f\xfb\x127\xf1\xa5\xef\xbd\xfa\xea7\x1f\x84N\x06@\xa7\t\x05\x13I\xb9\nz\xfb\xbb\x9f\xff\xcc\xfd_}5p\xc8\xf9\xee祁\xf2\x9f=8\xe9\xfeo\x06uz\xfb\xb9/~v\xd2\x17\x9f\xe3&\xbe\xf7\xc5I\xf7}\xf9y\xe8d\x00t\x9aPp\xa7y#\x03:\xe9\x02\x9d&\x14\xd0it\x81N\x13\n\xe84\xba@\xa7\t\x05t\x1a]\xa0ӄ\x02:\x8d.\xd0iB\xa1\x1f\xa3\x12\vfs\x9a\x988\xaa\x93n\xa82\xe5\xcc\xfe\x9a\xba\xf6\b\xed\x80Bİf\xdb9A\xf6\x9bU\x01j\x9c\xd4I?TY\x1cl\xacj\xbb\xd0^\xa5\x97\xb3\r\xd4D\fk\xb6\x1d\xc42[\xc6I\x9d\xf4C\x95\xc5\xc6\xean\xa6\x9a\xf6;v \x12\xbaa\xcd6\x83\x1cY\xcb8\xa9\x93~\xa8rw\x95\xf4\xad\xdcQ\xde5\x12\r\xdd\f\n\x9b\x81N\x96qT'Q/T\xb9\xad:\x91~\x8af\x141\vk\xbe\xe8\x16\x84\xad\xbfY[8\xff\x89w\xb9RӰf\xcao\xca\x17\xbb\xbdO\xbd.j@,\xb3e\x9c\xd5I/TyO\xfd\x99]U\xb5\x87\x12*\x04vt0\tk\xbe\xdeҒ_\x94\xedݸv.\x9fBa\x1a\xd6,\x8a\x1d\x9e\xaf\xef\xed\xd8)\xecS\x15\x1a\xc52\x83H8\xab\x93^\xa8r\x9d\x14\xaa\\[\x87cT\x14D\x0e\x1c\x13\x1f\x15J\xae\x89C\xea\xf8>Ӱ\xe6\xeb\xf9O\xb0\x9c\xb2\x16u3\xa3Xf\x10\t\x87u\x12\xc3C\x95\xeb\xa5\xf1\x88\xfe\xc4\nU\x1e-\xcct\xca\n\x8bG2\x0fk\xee\x10~\xa5m$\x1a\xc72\x83H8\xa9\x93~\xa8r\x93<\xf6۴Ǩ\x19\ba\xa6\xd3\xd7\xc3\xcbLÚ\xf7\t\xd7\xc3[I-q\xedd\x15'u\xd2\x0fUn\xaf\x91>\x8clęE\x14\x98\xe9T\xaeShF\x87:+=\x04F\xf6,\xe3\xa8N\xba\xa1\xca}\xd2@y\u007f5n\x8b\x88\x82\xd1\xd0\xe9\x9aw\xe5\x10\xfdo\xe3F\xed\x1f\xa0\x93e\x9c\xd4I?TYl\xafn\xef>U\xbb\vC\x11&\x98\x855\xbf\xfb\x8b\u03a2\x95\x9d\x9d\x16\xc3e)\x1d\xf3\x8b\x0etl\x14\x0eh\xcbuc\x99A$\x9c\xd4\xc9 TY\xec\xdaS\xb3\xab\x1d6\x99a\x16\xd6|Q\x90xʠy\x04^.\xf7f/?\x12V\xac\x1b\xcb\f\"\xe1\xa8N`|\xa1\x17\xcb\f\"\x01\x9d@\x04\xc2c\x99A$\xa0\x13\x00\xb6\x01\x9d\x00\xb0\r\xe8\x04\x80m@'\x00l\x03:\x01`\x1b\xd0\t\x00ۀN\x00\xd8\x06t\x02\xc06\xa0\x13\x00\xb6\x01\x9d\x00\xb0\r\xe8\x04\x80m@'\x00l\xc3Q\x9d\xf4B\x95\ak\xabdjM\x1a\x83\xf8\x80\vv\x06Z\x9c\xd4I7Ty\xa0\xaa\xbd\x9b\xd2^u¬9\x183\x9a\xb8\xafJs\xc1\xce@\x8b\x93:\xe9\x87*\x9fbv\r\xd4⋟q\xcc\xecEf5\x80\x84\x93:\xe9\x87*K\xd4\xe3\xbb\xed\xf1L\x06t\x8a\x0eGu\x12\xf5B\x95\x19R\x12\v\x18+\xba\x16\xa6\xba\xd2\xe6I_\x14ܐ\x91\x94\xb1\x81\xfe_L\\UKg$=\xc4\xde\xfa\x94p\xbe\f\x91\x0fv\xe6*\x14\xb3\xa2\v.2S\xea\xacv\xce\xd4\x19K'j@\x9f\xb3:\xe9\x85*3\xa4$K0F4Mͨh,#\x15t\xb2\xc0\xb5\xaa~\x95+\x97\xbe\xc1\xd5N!\xa9e\x15\xc9\vE\xb1\xffP\xf3\x8c\xcc\xe6\xe6f)\x99\"\x18\xec\xccU薊\xda\n\\\xac\xbc`rq\xfd\xbaԌ\t\x1a1\xe1\xacNz\xa1ʔ\vU\xf8\n\xf5\xd810m\xde\x00\xcbk\xa3W\xb3\xfb\xa5\x1fH\x93\x1f])\xf4E\xc9M\x95\xaa\xa8N\xf6\x02\xe1d\\\x05ɰ2\xa6S=\xa9\x11Y\xa4\xd8vqB\xe2\xb0Nbx\xa82\xa5\xb1.r\x130\x9aԓ@\xa4\x94X0K\xfaof\x01}p\xb1\aI\x11#\x9dB\x15B:-\x9a>\xc8H/\x10'$N\xea\xa4\x1f\xaaL\xa9Ad\xe5\x18\xb2\x8e\x04\u007f\xbdd\xce\x02\xe9\xbfy\xb3E^\x11#\x9dB\x15B\x93\x19ʅ\xd6\x04\r@rR'\xfdPe\x96\x03\xab\x8a\xa0\a\xce\xd2\xc8\x1d\x9d\xa6K\xffM\x97\x8eNZ\x9d\xaa_\x92+\x19鴊M\xe6No\x97\x98\xa0CK\x8e\xea\xa4\x1b\xaa\xcc.\x9dF\xf77^AD\xfa\xd33ٛ[\xf1Rv\xdeǮy\xb6K\x81ͼN\x99\x99\xf4\xb2\x97(\xa7\xe4::%\xad\x10\xc5\x1b\xb3\xd9\xe4~\xb9\xd6\xe3k\xc4\t\x89\x93:\x19\x84*S\xb7\xf0[icI\xd3\x0337\xd4\x17\x13vҐ;yE\xfd\x8aɹ\xd2h]A\x9b\xd8^\xe0\x92~\x93\xad\xccU\xb1'sj7\x1f쬪0'u͚9dJ\xcd\x19Q\\A\x16\xd5\xed) \x13\xf4\x961'u2\nU\xbe\x80\xbbVƖ\xaeE\xe9ɳ\xe5\x17aݬ\xa4Y\xf2\xe7N\x84\xb8NM\xa5\x8f\xc5\xf4\xd9@qJR&\x8bD\x0f\x05;\xab*te&%?\xf4\xb8\\w\u007ffjʜ\xfdF\xb3Jp\x1c\xd5\t\x80\xc4\x06:\x01`\x1b\xd0\t\x00ۀN\x00\xd8\x06t\x02\xc06\xa0\x13\x00\xb6\x01\x9d\x00\xb0\r\xe8\x04\x80m@'\x00l\x03:\x01`\x1b\xd0\t\x00ۀN\x00\xd8\x06t\x1a7,\"\xa9\xb9g\xcc*\x811\x05:\x8d\x1b\xba\x9bjf\xa6NԈ\xa0q\x82\xa3:\xe9\x85*\xb3\xa4\x9c]ջ\x0ea?\x89\x82&\x82\xacܸ\xc6I\x9dtC\x95ž\xda]R)\xbe\x91kN\x1bi3\xab\x02\xc6\x12'u\xd2\x0fUn\xaec_\xad\x1e\xack6i\r\xa0S\xdc\xe3\xa4N\xfa\xa1ʍr8\xd8\x1e$W\x9a\x03\x9d\xe2\x1cGu\x12\xf5B\x95\xfbj\x9b\xfa\x06\xfb\x9aq\xb2\x17\x05'H\x93Y\x150\x968\xab\x93n\xa8\xf2@#-ݏ\xf4\x95(\x18L\x9d}\xa8{\x82\xe6\x15\x8f\v\x9c\xd5I/Ty\xb0\xb1\x8e\xe5\x1b5\xe2'4\xa2`?!d\x81Y%0f8\xac\x93\x18\x1e\xaa\xdc\\7 \x95\xe2\a\x9e\xcc\xe9O\x9d\xbe\xae\t\x19\x9f\xf1\x8b\x93:\xe9\x87*W\xcb\xf9`R6,\x88L\x1b\xc1\x80M\\\xe3\xa4N\xfa\xa1\xca\xd0)z0\xb2\x17\xe78\xaa\x93n\xa8r\x93t\xb27P\x871+s\xa0S\x9c\xe3\xa4N\xfa\xa1\xca\x03\xdb\xebNu\x9f\xaaێ\xa1=s\xa0S\x9c\xe3\xa4N\x06\xa1ʃm\xbbjv\xb5a`ό\xc1\xee\xf6E.\xfc\xae\\\\\xe3\xa8N`$,$d\xda\x1e\xb3J`L\x81N\xe3\x86\xee\xe384\xc5;\xd0\t\x00ۀN\x00\xd8\x06t\x02\xc06\xa0\x13\x00\xb6\x01\x9d\x00\xb0\r\xe8\x04\x80m@'\x00l\x03:\x01`\x1b\xd0\t\x00ۀN@\xcd\xe0\xc0\xc0\xc0`\xf0?`\t\xe8\x04T\x1c\x9aL\bI\xea\xefO\xa2\xffMFX\x9bE\xa0\x13\x90\xd83\xa7W\xfa\xbf\x8eԷ\xb5\x9d\x12\xc5Smm\xf5\xa4Τ\xd1X\xd37'\xce\xee\tvT'\xfdPen\x12\x18\xf3\x1dAh1\xab\x13\x99\rd\xf2v\xa3\xbfU\x902y\xa2\x8e\x04o\xb4\xed\x96u*&\x93G[\xab\x98\u05edb\xf2\x1a\xb3*\x8e\xe2\xa4N\xfa\xa1\xca\xfc$0\xe6\xf5N\xf7N\xb3:\x91\xe9k\x9e]f\xf0\xa7u\x93k\x94\xa9p\x9d\xba\x9b]\xfa͚l{\xcd\f\u05ed\xe3\x9cnq\x88\xfa)\xebLj8\x8a\x93:\xe9\x87*s\x93 \"Y#\xd4I\x14\x17\x18\xe8t\xc1\xb5\"0\x19\xae\x93(\x1a\xe84{\x91nqL\x18\xac\xdb\xf2r\xddb\x8eUq\xf5\x8dJ'u\xd2\x0fU\xe6&ADFO\xa7\x82\xf4\xe0\x9b\x99\x05\x9d2F_\xa7GMu\xeaO/0\xab\xe2 \x8e\xea$\xea\x85*s\x93 \"Y\x1b\x9f\xf1\xe6<\xf5\x1bUYw2\x91I\xe6ޤ\a\xd3\\\x8f\xa7\xa77\x15\xa7d\xb2\x84\xd0E\xe9\xaei\v\xe4\x1f\xb2\xa1:\x15Ӻ\x0f\xb0Q\x87\xda9Sg,\x95-\x1aL\x0e\x1e\x9c\xf4u*~8=eA\x17}룍\x1f\x17\xcb\xe8c]\xbd2\xdf\f\xa9\x06\xd7Y8\xef湷z\xbd\x1d\x1bsV^\x13\xc5k\xe5^w\xfeS\x17i\xf1E\xb7 <5\xe4\x15\x84\x9c\xebܺ\x1d\x11\x04a\xab\xb8\x93>\xb6\xb0I\xc6\xd7Y'C?]\xee)\xdax\x9dMv>\x91\xef^\xfcT\xfe\x90\xdc\xfb\xaa\xa48J\x19qV'\xbdPe>_\x19D\"K\xf8zK\xcb\x12\xcfE\xbel\xb0f\x9dL\r\xff!QS2Y\x9aIRפU0\x05\x1en\xaa[0Y\xcal\xa1:u\xe7N^Ǧ\v&\x17\u05efK͐\x12\x9a۹\xe8s]\x9dH\xc6\xf6\xed\x19I\xa7\xc4\xfeCӊ{\xc5\u07b2\xe4\xe6\xfe\xfeC\xcd32\x9b\x9b\x9b\xa51$\xbe3\x1d:\xb2\x85\x8d%\xc2\xe2\x9dy\xfb\x98.\xeb;Z\x9e\x12\xe85\xd1\xd0/v\n\xbf\x10\u007f:\xf7\xa7\xbf\x12\xb9u\xbbޙ\xff\xec\x1f\xc4?\xfc \xbb\xf3ڵ\xce\u03a2\x95\x9d\x9d\x9d/\xb3>\x9e\x116v\xec\xf3>J\x1d\xfa\xe5\xdcgZ:\x0e,\x16ޕ;?\x14Oq4\xce\xea\xa4\x17\xaa\xccM\x82\x88d\x15\xd17\xe7\xebE\xcbU\x85\xbd\x17dzU\xa5\xe9\xb9T\xa3z\xb1\xe0a\x16\xb9\xc6\u07bff-d\xc5T\xa7\n\x97t\x1aPO\xd8\xd8C\x1b\xd9.?\t%\xcb\xea\xea4\x93\x1e\x00\x06f̡\x93e\xechT \x9f_\x05O\xf6T\x9d\xe9\xe1]+v\bG\xc4g\xd6\xd3\xe5o\xa1\x87\xa8\xa1%\xabY\xf1\xd03˯y\xe5\xb3<n\xddv\xb2\xa3\xd13\xcfH\xc5\xc1\x93\xbd#\xc2\x01\xfax\x8e\r\x00\x1e\xf02\x91\xf6\xe5(G\xa7n\x12Go\xc4\x0e\xeb$\x86\x87*\xf3\x93 \x12Y[\xd9\xe3\x01\xe1\x1aWv\x81\x04Pe-\xa7o\xa7{w\xbf\xb8\x82\xed\xf0\xbd\x1b\xe6MO&\xb3X\xf1\x82\xb2UD>\xa9^4}\x90!_x\xec1\xd3\xe9q\xf6\xb8\x81\xf4\xb1\xb2S\xe2@\xb2\x9cE\x1b\xd4Iՙ\x1e\xde\x16j\xc25q\xebZ:}\xed\xc0\x13\x85\xd9\xc2\x12\xa9\xfc\xfa\xa3yO\xc9Vp\xeb\xf6\xfa\xdc_\x89׳;\xa4\xe2\xa0Nk\v\x87ޥx\xa9e\xafy\v7\x1e\xf8Րb\x13]\"C\x8b\x9d\xc7I\x9d\xf4C\x95Փ\xc0\x18\xf9r\xbdSP\r\x1e7\xd7˨o`H\xdf/\xb6\xb9DI\xa7\xb6\xb4i+v5g\xca:\xa5%ϔ\x0eSb\x86\"\xa1\xf4\x8c\x8f\xef3\x1e\x8ah&l\xb4h\xdeRq\u007f\x8a|b\x19\xd4Iՙ\x1e\xde\x0e\xf1\x9c[\x94t:\xe7\xcd\xdfz\xa4\xb3D\xd6Il\x11:\xe5\t~ݞ\xf8\x17\xb1C9\xf6\x04uZ\xa2\\G=%2!ˋ\x84\xbc\xbd\x8aOm$\x8e\xf6\x1c'u\xd2\x0fU\xe6'A$\xb26\xb2G\xf5\xd1\xc9\x00N\xa7\x99s\xd8\xdb\xd8BY\xa7\xd4S\x17\x92+\xd8T\xee\xf4v\t\xe9\x1c\xb1\x9f\x1b\xba\xd3\xd5i){\xac&쬱>uP9דu\xaa~Iә\x1eL\xa7,Y\xa7\xa2\xe5l8\xa1\\\xd6\xe9u\xef\xd6|\xf9\x12\x88_\xb7#9Cʹ\x9e\xacӁ\xd7\xd8\xd1\xe9\x9c\x04\xfd\xfb\xb9\xadT\xa4k-\xf3\x0f\xc8U\xca\\q\xf4\x11\x8b\xa3:\xe9\x86*s\x93 \"Y^\xba'\x0e\x15\xad4\xab'\xaat\x9aƎ\x1972\x94\x93=Q\xdc\xefb\x87\xa2\xfd\xb2*\x8f\xcb7\x15,\x9a\x1e\x1cE\xd0\xd5)\x9d\x1a983\x93M\x0f\xa6֧(\xafU&-\xe8euԝ](;.j\xe0t\xcag\x82\f=*\xe94\xb4\xfc\a\xe2\xb3%\xd2Q\x86_\xb7\xa1\xc5Gr\xe4s=q%-\xf8\x03\xbb`\xea\x90o\x9b\xd8J\x0fb;\x05\xe9\x8f+\x9f\x95jܘ9O;\xb71\xc4I\x9d\xf4C\x95\xb9I\x10\x91,\xe1\x89_t,\xcfy٬\x1e}\x8bJ\xa9\xe8\xdf\xee:џ\x9b\xd9-\x96\x91E\x1b\xd6d\x90Ԋ\xb6\xfe\xe6\xd9\x05m\x83\xfd\xf3қ\xe8\x1b\xd8\n\xb2\xa8nO\x01\xa9\x95\xeawM\xae\b4\xd5\x1fٛ\xd7\xd64'E\xbe\xc0Z1]9ףDž\x8a=\x99SYuUg\v\xc8T\xcd/I^\xcc\xd9w\xbd\xc5}\xf1\xfaڒש\f\xe5\av>*,\xde\xdby\xbd\xf3;\xde\xd7\xc5\xdfdo켮Y\xb7\xad\x859ʰ\xddά}GJ<\xaf\xb1\xb2\xb9k[\x8e<ä\xda)x~p\x84N\xca\xc6U\x90x\xfa\xc0\xd2I\x9d\fB\x95\xb9I\x10\x89\xa2\x9d\xe5\xd9\u07b5\xaf\x99U\xa3\xef\xd8i\x84\xd4&\x93\xa9u\xecr\xe6F\xc5\fWꢚ\xe9\xae\xcc\r\xec&\xf1\xf6Z\xfa\xb8\x8aVڟ\x99\x9a2g\xbf\xd2b\xd5\x03\x81\v\x90:\xd2\x15\xf8\x82FW@\xa7\x99e\x8b\x92\xd3s\x15ͺ\xc8\xc3JՁ┤L\xf9\xaa\x8b\xef\xacz\xaaf\xe8z(O\x10Z\xb2\x05O\x8b \xac\x16\x87\xf6\x15ey\xd7\x1e(r\xaf젗B\x1bō\x820\xb7C\xb3n/\v땦\xd77\xe6\xcc_)_+v\x94,\xceY\xce\x14\xfa\xe9\xf2\x9d\xf9n\xefJ٦椥b\x1c\xe1\xa8N nY\xeaRԑ>\x9eU\xbe\xa0A\xf4>Z\xefw\x99\x9d\x97\xef!#\xbc\x9a\xb9\x96\xd5aVEa\xbb\xab \xae\xbe\x94\x05\x9d\x80DE\xba<\x900x\xa2-\xf0\x05\x8d\xb6\x13z\xbbj]\xaa\xc9\x0e\\\x93\xf2\xb082Z\x16\xbfkVE\xa6/=\xben(\x87N\xc0\neMb\xa6\xd1]\xe9\nݩKGt\x1d\xbc\xb3c\xa8\xe4\af\x95\xe2\x15\xe8\x04\xa2g\x80d\x14\xa7k\xc6\x19l\xe6\xba\xf0\xf5\u007f\xf6F\xf1Q@|\x02\x9d\x80\x05ʦf\x8e\xf6\x17=\u007f\xe0)y٬N\xdc\x02\x9d\x00\xb0\r\xe8\x04\x80m@'\x00l\x03:\x01`\x1b\xd0\t\x00ۀN\x00\xd8\x06t\x02\x8e\x131\xb0y\\\xa79C'\xe04Jn\xb3\xfe\x1f\xc7w\x9a3t\x02#!\x90\xc5l\x85@n\xb3>\\\x9as\xdce&\x9b\xe2\xb4N\xa7\xaa\x94\xbb\x94\xbb\xf7\xd4\xec\xef\x0e\x9b\x04\xd1\x10s\x06\xb1\xedHY\xccV\x17\x87\xfbJ\x15G\x87\xf7H`2\xf8E\xabx\xcbL6\xc5a\x9d\xfa\xaa\x0f\xc9\xdf1\xeb\xaen\xeej\xae\xee\xd6L\x82\xa8\x88=\x83\xd8f\xe4,f\xabq\xcf\xfa:\x1d\xf1\x04\x9d\f\xea\x14o\x99ɦ8\xacS}c\xb7\xa4\xd3\r)i\xe5P\xed\r\xd5$\x88\x96\x983\x88m%\x98\xc5l-\x9fV_'q(8\x15\xd2)\xce2\x93MqV\xa7S5\x03\xb2Ng\xaa\xd9M\xfc\x03\xd5gT\x93 Zb\xce \xb6\x95`\x16\xb3-:\x85\xe0t\x8a\xaf\xccdS\x1cթ\xbf\xbaK\x94uj\x94\xbf\b]ߤ\x9a\x04\x11\xf8g\xc1}`c\x91\xe7\x89\xd7ٓ\xd83\x88et\xb3\x98\x19]\vS]i\xf3\xa4\xc2\r\x19I\x19\x1bD\xf6\x834Sօ\x87*\x8b|\x16\xb3^ܳ\n\xd52p:դ\xc9)q\xd7<\x02w\x01\xc6\xe9\x14_\x99ɦ8\xaaS}\xa3\xa8\xe8\xb4K\x8e&8\xb4G5\t\"p\xb1\xc5-xw\xee͖\xf2Sc\xcf \x96\xd1\xcfb\x16Ŧ\xa9\x19\x15\x8de\xa4\x82N\x16\xb8Vկr\xe5\xd2Ӈ\xda)dښ\xb2i\xeaPe\x91\xcfb\u058b{\xe6Q/\x03\xa7\xd3B\xa2\xe4\x10\x9d\xeb\xec\x9c\x1f<\xc4\xf1:\xc5Uf\xb2)\x9fy\x1c\x00`\x13#8:\x01\x00\xd4@'\x00l\x03:\x01`\x1b\xd0\t\x00ۀN\x00\xd8\x06t\x02\xc06\xa0\x13\x00\xb6\x01\x9d\x00\xb0\r\xe8\x04\x80m@'\x00l\x03:\x01`\x1b\xd0\t\x00ۀN\x00\xd8\x06t\x02\xc06\xa0\x13\x00\xb6\x01\x9d\x00\xb0\r\xe8\x04\x80m@'\x00l\x03:\x01`\x1b\xd0\t\x00ۀN\x00\xd8\x06t\x02\xc06\xa0\x13\x00\xb6\x01\x9d\x00\xb0\r\xe8\x04\x80m@'\x00l\x03:\x01`\x1b\xd0\t\x00ۀN\x00\xd8\x06t\x02\xc06\xa0\x13\x00\xb6\x01\x9d\x00\xb0\r\xe8\x04\x80m\x98\xeb4\xb0f\xf6TW\xfa\xc2C\xe1\u007f\xd9@\x1eV\x1eF\xc0\xbd\x8ai\xae\xf4\xc6\xe0Ӂ{\xf4\xa1\x96,\nU\xa8#\v\xc3\x1a\xf1\xac#\xc5\x11\xffn\x82a\xf7\x9a\x053AZn\xb3E5\xc1\x96\xed\t\xc6\x12S\x9dj\\ʏ\x12\xcf\xfbP\xfb'[^\xfe\n\xd6w{\xe0ن$6\x97\xb8\xd0I\xbd`&\xc8\xcbm\xb6\xa8&ز=\xc1Xb\xa6\xd3RB\x16\x9e\x10?\xe9]\xe5\"\x99\xf74\u007f\xb3\xe5\xe5\x9fE\x96~r/\xd0\xf3=B\xc2t\xea\xdeЬ\xd7.\xc8\bu2\xec^\xb5`&(\xcbm\xb6\xa8&ز=\xc1Xb\xa2S\x13!\xdb\xe5\xa9\xe3\x84\xd4h\xfeh\xcb˟N\xbaBO\xf4t2c\x84:\x19\xa2Z0\x13\x94\xe5\x1e!\xb6lO0\x96D\xd6\xe9^Zh_-&\xd35\u007f\xb5\xe5\xe5O#ݡ'\xf1\xa4\x93j\xc1L\x80N@\"\xb2Nm\x84\f\x04\xa6\xfb6tIE\x8b\xd2]I3W\x89~\xf5\xcb?\xb0t\xba+e\xe1q\xb9*\xff\xa4\xbfx\x9a+yN\x8dꬩ\x97\x96\xa5,d\xd7%s\xa4˲\x80\x0f+\xa4g\xddL'qi\xbakzY\xe8\x82D\xaf\x9bS\vR\xa7λ\xc0t\xaa%\xb3\xe4\xa2\n\xe9ɺ\x0fX\xebU\x1fHE\xdc\x02ג\r\x83\xc5i\x0fd4\xd2\xc9Y\xae\xb4\x9b\xacD(\x00\x00\x1e\xe5IDAT\xa5\xdc\xf5N\xff\n\xb6\xc8g\x82}\a\x16,\xb0wK\xd2jz\x0e\xb6\t,\xb7\xd2Wh\xf5\xb4-\x14\xf8\x99\xe9o\xcfYd\x85\x1f\x8c?\"봊\xccД\x14\x13\x92\x9e\x91F\x1f>P\xbd\xfcǧ\x12\u05ec鄬\xf1k\x9e\xf4&\x93\x94\xd93\by\x88\xeb\xa3\xdeE\xa6\xb2>\xe8\x1e\xb3&\xd7E\xe6\xe5\xd6)\u007fس\x88^\xa9\xe5\x0e0;\xd2HZ\n!\xb3\xee)\xfb\xbb^7U\x84\xa4\xcdrMɤ;\xfa\a.\xd2+\x95\xcd gh\xeb\xa5\xe9$\x99\xb6\x9e\xf9\x89f\x81kIq*Is\x11\xd2XL\x1e\xa0e\x99\xfe\x80N\x87\x92\xc8\xd4ٴ$x\xed\x13X0\x8dN|ϡ6\x81\xe5\x96\xfb\xe2VO\xd3B\x81\x9f\x99\xc1\xf6\x84N\xe3\x93\xc8:- \x05\xea\x826\x92\xc4\x0e:\xa7\xa6\x92\r\xfc\xcb?\x90LV\xd0\xfd\xe5T\ni\xd4<YHVQ%^J&\x87\x82}\xbc4\x99\xac\xa1e\xfb]\xa4\xd6ot\xb2G\xa6wљ\xb9\xc8\x1ee\u007f\xd7\xeb\x86\x10\xaa\xe1\a\xf3\xa4\x83\xdbBY\xe4\x97\xc84\xa9\xf5\f\xfa\xce\xdf\xec\"\xbb4\vL\xff2\xb3\xd7\u007f/\x97\xb8\x1e\xa8\xbfǮ\v/(\xdd\x0fNe\xfd߫ \x0f\x84\x8e\"\xf2\x82it\xe2z\xe6\xdb(\xcb-\xf5\xa5Z=U\v\x05\xbe\xa1\xc1\xf6\xf4\xd7W\x9d\xf2\x83\xf1Gd\x9d\xe6h\xdf$W\x902\xe5\xffb\xfe\xe5_A\x16H\xc5\xfb\xd9\xd1L\xf5d\x9alKun[\xb0\x8f\x85\xca\x1eZGR\xef\x19\xea$\x1dl\x8a\xd9\\\xa4}T\xa7\x9b\\y\xd9>Le\x95\x9a\xe5\v\xbbǙU\xb4u_\xb0\xb5j\x81\x95~{\t\xa9`e\xb3\xd9>.u_F\xe6I\xb52I\xe0@i\xa4S\xa8g\xbe\r\xaf\x93j\xf5T-\x14\xf8\x86\x06\xdb\x13\x8cS\"\xeb\xf4\x10Y\xaa)Q\x86\x8e+\xd8a+\xf4\xf2O#MR\xf1'\x93I\xbf\xfa\xc9Cd\xce\x19\xf5h\xf3\xbd$e\xc8\xec\xdeTzff\xa0\x93|)T͆$\xa4}4\xbc\x1b\u007f2;\xb6\xf8\x95=\xf1^\n\xeb\xf4^\x1a\xdbyk\xc9\xccPk\xd5\x02\xd7\xca箟\x10y\x9e\xb9\xa4Z\xe9~\xa6\xb2ȃ\x83\xa1\xfeuu\xe2z\xe6\xdbp:\xa9WO\xbd,2\xaa\x99\xe9oO0N\x89\xac\xd3\xc3$W[t\xef̮\xb2Eӈ\xea\xe5\xff\x90^\xe5̑p\x91v\xd5\x13\xff\x19z\xa5\x92\x9c\xbb\x87\xbb\x12\x1f D\xb9\x8e\x98\xc3\xce\xe5\xf4u\x92\x8fo{\xd8\xff\xd2\xfe\x1e\xde\xcd\a\x81n\xf6Ho\xfcKٱ\xaa\x9d\xcc\xe6Z+\x03\x03\xdc\x02\xd7\xca\xc7\x05:\x17v\xe5\xef/ UJ\xad\xc0\xa5\x17\x8f\xaeN\\\xcf|\x1bN'\xf5\xeai\x96EB=3\xbd\xed\t\xc6+\x91u\xaa\xe0\x87\"\x8e\xb3=\xa6:\x8d\rbe\xccQ\xbd\xfc\"\tѨzBϬ\n\x92\xe8Ĕ\xe2\xe0\xa5x7\x99\xa2L-`\x9fdE\x1a(\x0f\xe9\x14\xdeM?!\xf2D\xb3\xa4S\x17I\xbbG\xed\xaf\xe5Z\xcb\r\xf9\x05V\xfe\x12\xa6\x13=\\q\x87%\x05]\x9dB=\xab\xdap:\xa9WO\xbd,\x12\xea\x99\xe9nO0^\x89\xacS7\xf7\xd2\xf7\x93\xc9]\xecΛ\xe2\xfa\v\x1fjNN>T\xae\x10$TO\x18\xf7N\xad\x99EB;I\u007f4G\xa70\x9dº\xf9 \xf0Q\xcf~\xf9\xb2d\x069q/i\xca\a~\x8dN\xaa\x056\xd2ɯ]d\x86Z\xa75Z\x9dTm8\x9d\xfa5G\xa70\x9dT\r\xf5\xb7'\x18\xaf\x98\xdc\x151-t\xf1\xb4\x82^Z\xd3\xeb\x01\xf9Z}\xa9\xfa\xe5Oe\xc7!Ʃ\xfe{\xea'\x03\xf2\xa7+\xb5dJ\xf0F\xa2\a\xa2\xb8v\xd2\xea\x14ލ?E\xe9f\x8d\xacS\x05Y\xd1.\xef\xb3\xfc.\xac^`C\x9df(#\xe4M\x0fU\a\xbaW\x16\xacJ\xe9\xec\xe10\x9d\xf86\xfc\xb5\x93j\xf5\xf4t\xe2\x1a\x1amO0N1\xd1i\x17!\xf5\xf2\xd4!B6\xb0\xb3:\xe9\xbc\xff\xc3tvQ\x15z\xf9\x8b\xc9li7o#\xae\x0fTODe\xcf\xed#\x93\x83\x1e\x04\x86\xbev\x91\xe4O\xa2\xd4I\xaf\x9bb\xb9\x9b{\xd3e\x9d\x06ȴ\x15\xf25>\xbf\v\xab\x17\xd8P\xa7\x15\xca\u07be@\x1e\xf2\x93\x90\x17\xac^>\xdd\xfd0-L'\xbe\x8d\xdeȞ\xb4zz:q\r\x8d\xb6'\x18\xa7\x98\xdd\x02\xbb\x90^$\x9f\xf9\xf0^\xef\xe3\x84̹翗,\x8dNߘG؎\x1ez\xf9\xfb\\\xa4\x98\xeeO])\xec`\xa6z\xf2\x10y\x88\xee\xba\x1f.R\x06\x87\x19\x17\xa6\x90\n*ES\x12\x1bX\xd3\xdc\xcb\xe3\"\x8d\x9f\xdc\xd39:\xe9t\xd3\xef\"\x1b\xee\xf9?\xcc\r\xdcT\x91I\x92\x92\xa5\xd3,\xd5\xd1I\xb5\xc0\x86:\xf5'\xb1E\xba\xb7\x8eL\x15\x83\xfd\xcb\vF\xcf\xdd\xe8_\xfa3I\x98N\xaa6\xf2rK\xe5\xaa\xd5\xd3Ӊkh\xb4=\xf1\xb9\xd38\xc5L\xa7O\n\x02\xc3\n\v\xa4\x91\bB\xa6-\x98=9\xa5\x8c\res/\u007f\x93\x8b<0{:\x91\xef:\xe7\x9f\f\xa4\x10\xd7\xccYI$\xad?\xd4g\xfd\x14\x92<;\x9d\xc8\xe7\x91j\x9df\x13\xf6\xa5\b\x9d\x93=\x9dn\x1a]$mv\x12Y\xa8\xe8\xb4'\xe0\x95j\x17V-\xb0\xa1N\xecs֔\xd9t\x1e\xdc\x1d\xe1ʂ\x15\x13\x92\x9cN\x92*\xc2tR\xb5\x91\x97[.\xe7WOO'\xbe\xa1\xd1\xf6\xc4]\x11\xe3\x133\x9d\xfc\xfe3\xc53\x1ep\xa5/R>?m\xcbLu\xcd,\xfb\xe0C\x17\x19T\x9d\x9c\xf4/\x9d\xeeJ\x9a]-\x9f\x8a\xf1O\x06\x96\xcep=@[\xf0]v?\x9c\xeeJ\x97oj\xd3\xe8ԗ\xf9@\xf2~\xbd\xa1\b\xddnrӒ\xe6\xb45*\x16\xd1E\n\\`\xf1\xbb0\xbf\xc0\xc6:\xf9\xfb\x8aӧ\xa4\xe6\xf2\x8b\xa2,ؽ\xdaY\xae\x94ܾ\x13\xe1:\xf1m\xe4\xe5Vʹ\xd5\xd3Չoh\xb0=\xa1\xd3\xf8\xc4\\\xa7\xf1\xc2\x00\xbb\xc1\b\x80\xb1$qt\xaa\xe0\x86\x11\x00\x18\x13\x12D\xa7\xbe\xc1\xc6\a\\\xa1a\x04\x00Ƅ\x04\xd1)\x97\x10\x1c\x9c\xc0\x98\x93 :U'\xa5\xc1&0\xe6$\x88N\x00\xc4\x03\xd0\t\x00ۀN\x00\xd8\x06t\x02\xc06\xa0\x13\x00\xb6\x01\x9d\x00\xb0\r\xe8\x04\x80m@'\x00l\x03:\x01`\x1bv\xebt\xb6\xe4\xb6Y\x95h\xb8Sr֬\n\x00q\x87\xa9N\x1fm\xc9\xf3\x94\xfb\xccj\x058(4D]7\x12\xbe\x83\xc2A\xb3:V\xb8\xec=oVń\x91\xf7\x10-\x97\xe6\n2^k\x9br3m\xe2yOS\xd8 \xb8\xd9\x1bӋ\x1e\xa1A\xaf\r\xb0\x17S\x9dJ\xbdG7y>6\xab\xa5\xd0*\xbc`V%Z^t\xb7\x9aU\xb1\xc0\xf9쨏vW~\xaf[l\xa1\a\x0e\x83\xce\"V\x18~Ž\xb9\x87\xb2[\xb0v\xa0\xbf\xd9\xd3sX\xf8\x9d\xa6\xf0N\xa5\xa7\x94\xfeWꩼ\xa3\xd7\x06؋\x99Nw\x84V\xbf\xef\xaeI\xa5\x00\xef\xbbw\x9bU\x89\x9e\xbdY7ͪX \xfa7\xfa\x95\xeb\xf5ˣ\xef\x81è\xb3\xc8\x15\xb2\xa4#\xc9\v\x82e\x03\xae\x86\xe9\xe4\xdf]N\xdf\f\xefx\xcam|e\x80!f:\xbd'X8\xc7\xd9\xec\x1d6\xab\x12=\xc3\xde\xcdfUF\x85\xc7\xcc\f\xb0\x82ig\xba\x15d\x9d\xde\xdba\xd9`=\x9d*KO\xfb_X]\t\x9d\x9c \xa2N\xbe\xc5\xf2I\xfc\x0e\xbf\u007f\xab@\xcf\xe3\xdew\vKؤ\xfb؎%\x9e\xd5\xf2\xc1\xe3\xbdo繽\xe5Ҵ/[~\xcd\xder\v\xc2\xde\xf7*\v=\xab?\xe5:\xe3J\x8d:\xf3\xbdP\x92\xbddG@ɽ\x1e\x8d\x9c\x96{P\xf8\xd8C\xd7\xe1$\x9bR/z\x88\x9eՅ\xee\xbc\xf2B\x9f\xff\xbcrٲ\\\xbd\x16\x06=ܩ\\\\\xb8c\xc7\xe2\xec\xd3\\\x0f\x1c\\g\xaa%ӛ\x9b\x8a\xac\xc0u\xce\x1f\xe92\x94\xfb\n\x05!\xc7翻>\xdf]X\xfe\x96\xdf\xffi\x9e\xfbDž\xf9W\xb6\xe5\x94\xdee\x8bӺ%?\xa7\\\xb9d\n\xea\x14\x9a\xdb\xee\xca\xc3O\xfbˏ2\x9d\x82=h\x9b\x01\xbb\x88|tz\xb3\xe7\xa4\xd0\xd0\xd3s\x8b\x9d\x98\xbb\x1b\xfc\xbe\xab\x9b\xb3\xe8k|\xd2-x\x1b\x0e\xe6<\xcdj\\\xc9^~\xf0r\x83 ]\xe7\xbc)\xf4H\xad\x86O\x9f,,\xca.\xdcQ9\xf7\xcf\\_\\\xa9Qg\x9b\x85m/\xb6z\x1fS\xf6\xc9W\x84\xdf\xfaUX\xee!\xc0՞\x9e\xf9\xd2\x1e\xaa\xaa\x1b⍹\x9b\xce^>\x96'|J\xaf[z\x8a\x9e\xa4\xd7-\xff\xaeY\v\xdd\x1e|\x8fz\x0f7\xcc\xf7\x1c[\xdd\xca\xf5\xc0\xc1u\xc6/\x99\xee\xdcTd\xed\x1d\x1e^\xbf\x83\xcd\xe1\xb7\rt#\xbc0\xf7\x857\x99\x9c[\xae\x9c.\x17\xae\xd2m\x9e#\xec(\x15\x16\x1f\xcck\x95\x16\xa7\xb0\xa1\xa1\xd0\xf3\x8e\xd40\xa8Shn\xbb+of\u007f4\xff\x16\xd3)ԃ\xa6\x19\xb0\x8b\xe8O\xf6\xa4\xb7̆,i2\x87\xbe9Wz\xe9\xd4p\xe1j\xfa\x92\xf9NKg\xf9/\n\u007f\n4{L\xa0o\x9da\xd7\\\xa1R\xdd\xce\xceK\x03\x19W\xe5\xc3\x005X\b\xbf\xf8\xb7\xd6\x03\x87Gy\xc3\x0f\xd5\xe58\xece\x1a\x1cΑ,\xe4N\xbfTk\x11\xde\xc3i\x81\xbe\xd3\x1f\x16\xde\xd1\xf6\xc0\x11\xec\x8c[2\xa3\xb9\x85\xc8b\x87\xacriҷ\xa9\xe4N\xa14\xc89|\x92.\x88o\x19\xf3\xd8[I\xb7\xf5y\xff\xa6-\xacn!-\xfe\xb8\xb0D\xaa\x1dЉ\x9b\xdb\xeeJ\xff\xb2-+\xfdL'\xae\au3`\x17\xb1\xe9\xb4)0yIx3T\xf7\xac\xf0~`\xf2\xb1,\xfe\xc0\x14^\xaa\xdb\xd9\xfaG|\x9fR\n7\xcbun\n\xa7G\xd8\x03GP\x86`]\x8e?\xe7\x17n;\xf6\xa6Ov\x81\u05c9_\x8b\xf0\x1ev\xe7Ї?Iҫz\xe0\bv\xc6-\x99\xd1\xdcBdm\xb9zu\x99\xac\x93\u007f\xf8\x1by\xca\xe7\x14w\x0e\xaf~$GXF\xa7\xbc'\xa9*\xc3\xcc\x14ZW:\xc1>,\x0f[\x04t\xe2\xe6F+\xb1\x0f\x1d\xa4k\xa7P\x0f\xeaf\xc0.b\xd3)8\xd9*p\xd7)܅\xf0c\xda\xcb\x01M\xa9ng˔K\t\xe5T\xec\xaa\xf0\xca\b{\xe0\b\xca\x10j\xc6\xf1\xf1\xd1\xf5K\x84\xbc\x83aG'~-\xc2{h\x9d{\x87\xbd\xa1\xbc\xa3\xed\x81#\xd8\x19\xbfd\x06s\v\xc1fq\xe9\xb2\xf2䬲\x19\xaez\vw\x9f\xed)\x95t\xba\xe4\xbf\xea\xf6+:I\x8b\xd5#H\x03\xee\x81W\x80\x9b\x1b\xadtg\xc7mI'\xae\au3`\x17\x16uګ\xd9\u007f/\xf3\xaf\xc7p\xf0\x12\xda\xffط\xfd:\x84Ju;\xab|\xe4\xf7\x12\xca;f\x83;|\x80\xdeZ\x0f\x1c\x11u\xba\xba\x9b\xee\xda\x1f\x9f\xf4\x1cfO\xa4\x1d\xfc\x98tXR\xadEx\x0f\u007f\x16\xca\xff\xfcVQ\x89O\xdb\x03G\xb03nɌ\xe6\x16Bَo\xb1ո\xe9\xdd[\xf8\x11{\xb6\xa4\x84\xbds};\xa0SV@\xa7m\xec\x8f\xc7\x04i[\x05t\xe2\xe6&U\xf2K:q=\xa8\x9b\x01\xbb\x88^'\x0f}A|+5\xfb\xef]o)ۛ\xb6I/\x8e\xff\xdbE\x81wg\xfd\x01\xe2P\xa9ng\x97\xe4k\x9e\xbd\xf2\xfd\x10\xbe%\xe5#\xec\x81'\xa2N\r\xc2%\xf6_\xe9\x16\xe9\xb1\xd4\xef\xbf-\xf7\xa3Z\x8b\xf0\x1e~/\xe4\tB\xe9Ͱ\x1e8\x82\x9dqKf47\xff\xfb\a\xdf\xe7fA\xada\xabX\xb2\u05ffE\xdaƅ\xccm\xdf7\xc2tʣF\f?R*\xb5\b\xe8\xc4͍Ӊ\xebA\xdd\f\xd8E4#{W%IJ\xbc\a\x1bJ\x04\xf7\v\u007f\xbc\xd5\xe3\xde|\xd5\xf7\xe6f7\x1b\xf1\xbb2\xffѣ\x97\xb6\tǤ\xea\xef\xc9w\x06}\xfa[i\xc0*x!%\xa3*\xd5\xefl\xf7\xdcʳg7+wV\xb4\x86\x9d\x88X\xed!\x80\xefw==\xf37\xf7\xf4\xdc\xf5\xab\xea\x86h\x10\xb2\u007fr\x9e6\xbb\"=\xc9j=[\x9a\xfdg\xd5\xdc\xf4{\xf8\xfd\xfc\xcb/\xf6\xdc\xf4\x85\xf5\xc0\xf7\xact\xc6/\x99\xee\xdc\x18O\xcb\xc3\x0f\x81\xbb\"zrv\f\xbf\xb2\xd5{\xd3\xff~ζW|\xb4\xd9\xfa\xc3\r\x8fѓī\u007f\xcci\x1d>\xe9~k\xb8\x92\xa9\x9c%,?y\xac(\xe7O\xf4`\xc9\xee\x8ah\xed\xe9Q\xcd\xed\xa3\xcaR\xb6\xaa\xb7J+?\xe2z\xe0\x9b\x01\x1b\x89\xfc\xb9S\x8et\x06\xee\x96\x06r\xdf+\xf5d\xaf\xfe\xb1 l\xddʊ\xfe-\x9b>n\xa5\xc5\u007fZ_\x98\x1d\xbc_u\xef|v\x9e\xff\x96|\xe2\xae9\xb8\xa8J\r:\xbbT\xba8\xe7I\xe9\xbd\xdb\xdf\xe3\xd9\xe1\xd7`\xb1\x87 o(W\x12G\xfd\xea\xbaA^x\xb2\xa1\xd0\xed-\x95]\xf0m\xcb\xf1<yU=7\xfd\x1e^q\xb32\xf7\x93\xefhz\xe0\bt\xe6\xe7\x96Lwn\x8ccޣRE!@+\x9b\xdc\xe6\xdf&\bs\xaf\xf8}\xadEY\xde\xf5NJ\xdcO\xd2c\xe2\xc9l!\xfb\xa4tm\x94\xb5csN~%Sf\x93\xd2j=?\xb7\x06A\xd8D\x9fn\x11\x84\x86P\x0f\xa5|3`#f'{\xd6\xf0ms\x9f4\xab\x13\x1d\xa7ݛU\x9f\xe1\xc4!\xb7\xb3\xb7\xdc\xfe\xf4ӏ\xdfx:'\xda[\x1aG\x83\xd0\xf5\xaa%bl\x06\"c\xafN\xf4\r\xb0Ж\xa1\xd7;ްA\xb2\xb8\xe3\xac\xf2)\x93/Ou4\x1c~_\xc6\xc6\xfb\xad\"\x11\xa3\x1716\x03\x91\xb1Y\xa7\x89\xc4\xef\xe5!r\xff;\xfcgo~\xff\x93\xca9ד\xba\x8dl'F/bl\x06\"\x03\x9dbƷٳ\xe5\xf4\x95\xd3[<[T\a\xd2?\x9d\x97q\xe4*\xff\xa642bV+\x8c\x18\x9b\x013\xa0S\xec\xf8ί\xcew\xe7\xaf>?\x86\xfb\xa542\xa2\x19B\x8d\x82\x18\x9b\x013\xa0\x13\x00\xb6\x01\x9d\x00\xb0\r\xe8\x04\x80m@'\x00l\x03:\x01`\x1b\xd0\t\x00ۀN\x00\xd8\x06t\x02\xc06\xa0\x13\x00\xb6a\xb7N\xc8(\a\x13\x18S\x9d\x90Q.3\xf2\x1e\xa2\xe5\xa4t\a\xed⧣\xb9\th\xab\xa0\x93\xdad\xc0\xd1P]+\xb3\xb0Rw\xc2'\xa2\x9bꄌr\x19\v=pĒQ~\xf7\xbc\xf0㞞\x17\x96\xe5}\xa4S_\x83\x947\x18%\x1f\xf7\x94\x04\xea\x1a\xce\xc2\xca\xe2\xe8ԝ\xf0\x89\xe8f:!\xa3<@\xf4=pĔQ~K:\x8a\xdc\xf1D%\x8a\x95oZ\x94\a\xeb\x1a\xcd\xc2\xca\xe2\xe8՝\xe8\x89\xe8f:!\xa3|D\x98v\xa6WA\xde\u007f\xfd\xcb\xcc\xdaJ\x8cD\xa7\xf0YXY\x1c\xbd\xba\x13=\x11=rV\x042\xca\xc7\"\xa3\\\xde\u007foK)\xce\xc1fF[=k\x87\\\xca'\x97si\xe4\xaaׂ괍\xcen\xfe\x1dn\x16l\x19~\xcc\"%\x84\xd3\x06\xcbk\xa5\xeeDOD\x8f&\xc9\b\x19\xe5\xcef\x94\xdf\x12\x8e\r\xdf\xfdݲ%w\xf9fF[=KXr\xf2l\xdeӪ\xe4r.\x8d\\\xb5\x16T\xa7\x9b\x95B\xebU~\x16ï\x14n\xb9\xed\xbf\xfd\x93\x9c\x9e\xbb\x06\xcbk\xa5\xeeDOD\x8f\xfed\x8f\x8f]EF\xf9hf\x94ߒ\xde\xf7\x8bn\xaa\x9b\x19l\xf5,\xefG\xec,ۯJ.\xe7\xd3ȹ\xb5\xa0:\xb5f\x9d\xd7\xcc\xc2\xdf\xc0\x8e0\x9b6\xcbuu\x96\xd7J݉\x9e\x88\x1e\x9bN\x9b\x02\x93\xc8(\x1f\x85\x8c\xf2[\xc2O\xae^\xbd\xb4i\xf1\x1b\xea\x15\xd2\xdf\xeaY[\x02\xa5|r9\x97FέEy\xc3^\xe5\xe5\xe4f\xe1\xbf9\xf7\xdf\xfc\xbe\x1c9\xc3Yoy\xadԝ\xe8\x89\xe8\xb1\xe9\x14\x9cDF\xf9(d\x94+\xd7\xfe\xeb\x8b|\xaaf\xfa[=T\xca%\x97\xf3i\xe4\xdcZ\x94{s\x96<\xed\xd3̂\x16\xef\xf0_\xca\xd1\xd8\xcd\xcd\xd8J݉\x9e\x88nQ'd\x94s=\x8cVF\xb9\xb2\xff\x1e\xa3o\xe6\xfc\n\xe9ou\xb5NY\xb2N|\x1a9\xb7\x16\xe5\xdew\xde\xcfi\xd5̂\x9e\xac\xe5\xf9\x94\xf37\xdd\xe5\xb5Rw\xa2'\xa2G\xaf\x132ʵ=\x8cVF\xb9\xb2\xffn\xca\xf6\xa9VH\u007f\xab\xeb\xeaħ\x91sk\xc1\x06\xca/\xb9\xaf\xaag\xc1\x82\x02\xcf+\xe7o\xba\xcbk\xa5\xeeDOD\x8ffd\x0f\x19\xe5\x8ef\x94˷!\x9c\xad\x946f\xb0\x99\xfeV\xe7J\xf9\xe4\xf2P\x1a9\xb7\x16\x1f\xf7\x94l\xfe\x9d\xefn\xb9\xf7\xcam\xd5,\xe8L\x1e\xc9\xf9\xd4py\xadԝ\xf0\x89\xe8\x91?wBF\xf9\x18d\x94\xcb7ɹ\x97\x1d\xf3\xf1\xcd\xf4\xb7z\xa8t\v\x9f\\\x1eJ#\xe7\xd6\xe2(\x9bx\x83\xf5\xbeW=\v\xff\x9f\x84\xc0QUgy\xadԝ\xf0\x89\xe8f'{\xd6@F\xf9\xb8\xe4nV\xd8\xfb\x80!V\xea\x06\t]T'8\xf6ꄌr\xc73\xca\xed\xe0\xf4\xe2\xe8ߺ\xac\xd4\r\x02\x9d\x80\x19\xf1\x91Q>b\x1a\xae\xf8J\u007fbVI\xc1J]\x1e\xe8\x04̈\x87\x8c\xf2\x913,,\xdf\xea\x8d\xf2l\xd5J]\x8e\t\x94\x88\x0e\x9db'\x0e2\xcam\xa0!\xbbTsϠ1Vꆘ@\x89\xe8\xd0\t\x00ۀN\x00\xd8\x06t\x02\xc06\xa0\x13\x00\xb6\x01\x9d\x00\xb0\r\xe8\x04\x80m@'\x00l\x03:\x01`\x1b\xd0\t\x00ۀN\x00\xd8\xc6\xc8ur.\xbc;:\xd6\x1f\x95\xff\xbf\xb2:\xcf]\xb8yb\xdc\xdb\x02\xe2\x04\v:\x8dyx\xb7!|\xdd7\x84\xdd\xd2\xffW\xe7\x96\x1c\xbb|\xb4(o\x02|g\r\xc4\r\x16t\x1a\xfb\xf0n#Bu}=\xf9\x8aNg\x05\x16ipS\xf9\xda=\x00N`A'Ӽm+\x98vfZ\x81#Tw\xbd\xb0\xde#\xeb\xe4\x93\x0eKz\xe1b\x00\x8c\x16&:\xc5Ux\xb7*o\xdbwt\xb9\xe7\x1b\x87}\x9a\xcen\xdf\xf2\xe7\xec\x0e\xd4\xf7ݹT\xf8\x8d\x98\x8e\x9d\x00\xc4Dd\x9d\xe2+\xbc[5\xe3MY{_ܛ\xb5\xd9\x1fV7\xa8ӛԱl\fE\x00\a\x89\xacS\x9c\x85ws3\xbe$\x85\xd5ɏ\xea\xbaA\x9d|W\xaf\xb4\x16z\xe1\x13p\x8e\xc8:\xc5Yx77\xe3\xcdr$㣛\xc3\xea\x86N\xf6(\x1f\xe7\xebd_\x020J\x98\\;\xc5Wx77\xe3\x12Y\x93\U00092c3a\x8aNw\xe496\xb8q\xf1\x04\x1c#\xb2Nq\x16\xde\xcd\xcdx\xf3#\xacw_ᦰ\xba\xb2N\xbe\x1c\xb9f\x83'\x86\x1c+\x00b#\xb2Nq\x16\xde\xcd\xcd\xf8E\xe9O'\x85\x17\xb5u\x03:屟@\xf2\u007f\\\x18\xfec\x1a\x00\x8c\x16f:\xc5Sx\xb7*\xa3\xbcR\xd8}~\xb7P\xa9\xe9\xecNOO\xf6z)T\xfd\x05\xa1\xfc\xe8\xe5\xd6\xc2<;\u007f\xaf\x1a\x80\xc8D\xd6)\xbe»U\x19\xe5\xbe\xd6e\x9ee\x87}\x9a\xba{\xa5\x1an\xf6+\xac\xbf}\xbap\xfe\x92m\xb6d\xd2\x02\x10\x1d\x16\ue288\x9a\xc4\t\xef\x06\xc0\x12\xa3\xa1S\xe2\x84w\x03`\x89\xd1\xd0)A»\x01\xb0\xcah\xe8\x94\x18\xe1\xdd\x00Xf4tJ\x90\xf0n\x00\xac2*:\x0101\x81N\x00\xd8\x06t\x02\xc06\xa0\x13\x00\xb6\x01\x9d\x00\xb0\r\xe8\x04\x80m@'\x00l\x03:\x01`\x1b\xd0\t\x00۰[\xa7\xb3%\xb7ͪ\xa8\xb9S\x12K\x88,\x00\xf1\x88\xa9N\x1fm\xc9\xf3\x94G}\xb7\xd0A\xa1!\xea\xba2\xbe\x83\xc2A\xb3:V\x18yd\xfa\xc8{\x88\x96\xb3n\xe5\xae`\xb7\xf9[J\x83\\\xe9E\x8f\xd0`V\x15\x8c\x19\xa6:\x95z\x8fn\xf2D\xfb\xbd\xa5V)\xe5\xcb\"/\xba[ͪX\xc0Bd\xfa\x98\x87\xae\x1f\x14zz\x0e\v\xad==s\x8d\xdfQ\x02\xcd\xeeTzJ\xe9\u007f\xa5\x9eJ|#2~1\xd3\xe9\x8e\xd0\x1a\f\xd43\xe5}7\x1f\xca\x155{\xb3\xec\xfc\x06z\xf4G\xc71\x0f]ou\xb3\x84\xc1\xdf\xf9\xfd\x1e\xe37\x94`\xb3\xdd\xe5\xf4]펧<\xa6M\f\x9c\xc1L\xa7\xf7\x04\vg>\x9b\xbd1}5pػ٬ʨ`%\x06\xdd\x14\xd3\xcet*\xf8\xdeStz\xcf\xd8\xe0`\xb3ݕ\xa5\xa7\xfd/\xac\xae\x84NqLD\x9d|\x8b\xe5S\xfb\x1d,\x82\x9c\x9eǽ\xef\x16\x96h\xd2\xc8\xfd\xef};\xcf\xed-\x97\xa6}\xd9\xf2K\xcde\x89\x1b5\xe3\x82\xc9){=\x1a\r-\xf7\xa0`\x10\x99\xce\x11W\xa1\xeb\fI\xa7h\x9a\xed\xae<\xfc\xb4\xbf\xfc(\xd3\xe9\xee\xfa|wa\xf9[~i![\xb7\xe4甿\x17\xd6/\x18\v\"\x1f\x9d\xde\xec9)4\xf4\xf4\xdc\xf2\xfbo\xf6\xb8\x1b\xfc\xbe\xab\x9b\xb3\xd4i\xe4\xfe+\xd9\xcb\x0f^n\x10\xa4\x93\x957\x85\x1e\xa9\x15\x97%n\xd4,\x14L\xcexE\xf8\xadz\xbe\x96{\b\xa0\x1b\x99\xce\x11_\xa1댠Nf\xcdvW\xde\xcc\xfeh\xfe-\xa6\xd3ya˕\xd3\xe5\xc2Uy!\v\x1b\x1a\n=\xef\x84u\fƀ\xe8O\xf6B1z\\\x1a\xf9p!\x8b\xb3\xf3\x9d\x96.\x8f_\x14\x82_\xb4\r\x85\x98\xeb6\xe3\x82\xc9\x197\x85\xf0\x8b\u007fk=p\x84G\xa6s\xc4]\xe8zP'\xd3f\xbb+\xfd˶\xac\xf43\x9d\x86O\xd2%\xf5-\x93\xde*\xb2\n\xef\xb28\xc1\x12\xbd\xbe\x81\xd3ĦӦ\xc0\xe4%>\x0e\xe2\xac\x10\xcc\xd7\x0f\x85\x98\xeb6\xe3\x82\xc9\x197\x85\xd3~-\xd6z\xe0\b\x8fL爻\xd0\xf5\xa0N\xa6ͨN\xec3\x05\xe9\xda\xe9\xce\xe1Տ\xe4\bRL{\x96t\x82}X\xc0x_<\x10\x9bN\xc1\xc9V\x81\xbbz\t\x9e\xb7\xf0!\xe6\xba\xcd\xf8`r\xbf\xfe\x8f\x9aY\xeb\x81#<\x94\x96'\xdeB׃\x1bʹ\x19\xd5\xe9ΎےNW\xbd\x85\xbb\xcf\xf6\x94\xca:I\v\xdb#\x98\x8d\xd3\x03'\xb0\xa8\xd3^\xcd^}\x99\u007f\x19\x87\xb3\x1a\x02\x93\xa1\x10s\xddf\\09\xa3\xc1\x1d>\x14o\xad\a\x8e\x88:\xc5]\xe8zP'\xd3f\xbb\xe5\xc4[\xa6Ӓ\x12\xf6&\xf6mY\xa7m\xec\xf1\x98\x10\xed\x87\x19`4\x89^'\xf6#\x99\xbe\x95\x9a\xbd\xfa\xae\xb7\x94\xedcۤ\xd7\xd4\xff\xed\xa2\xc0{v\xe8\xadX\xb7\x19\x17LN\xf1-\xd1\xf9\xd5\x18K=\xf0D\xd4)\xeeB׃:\x996\xe3t*d\xf2\xfb\xbe!\xeb\x94GE\x1a~\xa4\xd4\x0f\xe2\x80hF\xf6\xaeJ\x92\x94x\x0f6\x94\b\xee\x17\xfeȧ\x91\xfb\xaf\xcc\u007f\xf4\xe8\xa5m\xca\x0f:\xbf'\xdf/\xa4\xca\x12\xd7o\x16\n&\xf7\xb33F홊\xd5\x1e\x02\xe8G\xa6s\xc4W\xe8:\xe5\xcd\xc3B\xab\x1c\x1dm\xd2\xec\xa3\xcaR\xb6&\xb7J+?\xa2\x15\xd6\x1fnx\x8c\x9e\x0eҖY\xc2\xf2\x93NJr\x90\xb6\x16\x17D\xfe\xdc)G:\x9dwKû\xef\x95z\xb2W\xffX\x10\xb6\xf2i\xe4\xf4\x02}}av\xf0.ֽ\xf3\xd9E\x90*KܠY0\x98\x9c\x9e\xf7{vhgl\xb1\x87 \xfa\x91\xe9\x1c\xf1\x15\xbaN\x0f+\xac\u007f\xcf\xdd(\x9a5\b\xc2&\xfat\x8b 4\xf8}\xadEY\xde\xf5NJ\xdc\xf4\x98\x94\xb5csN~\xa5\xea=\x03\x8c\x19f'{\xd6\xf0ms\x87\x8f\\\x9bpڽ9\xde\u007f\x82)\x9eC\xd7C\u05eb`\xec\xb1W'\xfa\xbeYhq\xc4\xf6\x8e7l\x90,\xee\x88\xe7\xd0u\xe8\x14OجSb\x12ϡ\xeb\xd0)\x9e\x80NQ\x10\xbf\xa1\xeb7\xa5\xf1\x12\xb3Z\xc0)\xa0S4\xc4m\xe8\xba4^\xf2\xbe\x1f\xc4\t\xd0\t\x00ۀN\x00\xd8\x06t\x02\xc06\xa0\x13\x00\xb6\x01\x9d\x00\xb0\r\xe8\x04\x80m@'\x00l\x03:\x01`\x1b\xd0\t\x00۰['d\x94\x83\t\x8c\xa9N\xc8(\x1f=\x90Q\x9eh\x98ꄌ\xf2\xe8@F90\xd7\t\x19\xe5Q\x82\x8cr`\xae\x132ʣĴ3d\x94O\x00\"gE \xa3\x1c\x19\xe5\xc0\x02\xd1$\x19!\xa3\x1c\x19\xe5 *\xa2?\xd9CF92ʁ\t\xb1\xe9\xb4)0\x89\x8c\xf2`\x0f\x81\xceL\xc3\xc6\xd5 \xa3<\x91\x88M\xa7\xe0$2ʃ=\x04:3\r\x1bW\x83\x8c\xf2D¢N\xc8(GF90&z\x9d\x90Q\x8e\x8cr`B4#{\xc8(GF9\x88\x8aȟ;!\xa3\x1c\x19\xe5\xc0\x02f'{\xd6@F\xb9\xe3 \x056\x9e\xb0W'd\x94;\x0et\x8a'l\xd6)1AF9\x88\x0e\xe8\x14\x05\xc8(\a\xd1\x01\x9d\xa2\x01\x19\xe5 *\xa0\x13\x00\xb6\x01\x9d\x00\xb0\r\xe8\x04\x80m@'\x00l\x03:\x01`\x1b\xd0\t\x00ۀN\x00\xd8\x06t\x02\xc06\xa0\x13\x00\xb6a\xb7N\x963\xca\xf5Ar9\x18\x8f\x98\xea4\xda\x19\xe5\xfa \xb9\\@r\xf98\xc4T\xa7\xd1\xcf(\xd7\a\xc9\xe5H.\x1f\u007f\x98\xe9\xe4DF\xb9>H.Gr\xf9\xb8\xc3L''2\xca\xf5Ar9\x92\xcb\xc7\x1d\x91\xb3\"F\x9cQ\xceuf9w\x1c\xc9\xe5Q4Cry\\\x11M\x92\xd1\b2ʹ\xbe,\xe7\x8e#\xb9<\x8afH.\x8f+\xa2?ً1\xa3\x9c\xc7Z\xee8\x92ˣh\x86\xe4\xf2\xb8\"6\x9d6\x05&\xcd3\xcay\xac\xe5\x8e#\xb9<\x8afH.\x8f+b\xd3)8i\x9eQ\xcec-w\x1c\xc9\xe5Q4Cry\\aQ'\xeb\x19\xe5<\xd6rǑ\\\x1eE3$\x97\xc7\x15\xd1\xeb\x14cF9\x8f\xa5\xdcq$\x97\xfb\xa3h\x86\xe4\xf2\xb8\"\x9a\x91\xbd\x11e\x94\a\xb1\x9a;\x8e\xe4r\xbfy3$\x97\xc7\x17\x91?w\xb2!\xa3<\x88\xc5\xdcq$\x97#\xb9|\xfcav\xb2g\x8dX2\xca\xf5Ar\xf9\x88@6\xec\xd8`\xafN1d\x94\xeb\x83\xe4\xf2\x91\x01\x9d\xc6\x06\x9bu\x9aH \xb9\x1ch\x81N1\x83\xe4r\xa0\x05:\xc5\x0e\x92ˁ\x06\xe8\x04\x80m@'\x00l\x03:\x01`\x1b\xd0\t\x00ۀN\x00\xd8\x06t\x02\xc06\xa0\x13\x00\xb6\x01\x9d\x00\xb0\r\xe8\x04\x80mح\x132\xca\xc1\x04\xc6T'd\x94ˌ\xbc\x87hAF\xf9\xf8\xc5T'd\x94\xcbX\xe8\x81\x03\x19\xe5\x13\v3\x9d\x90Q\x1e \xfa\x1e8\x90Q>\xb10\xd3\t\x19\xe5#´3d\x94'\x14\x91\xb3\"\x90Q\x8e\x8cr`\x81h\x92\x8c\x90Q\x8e\x8cr\x10\x15џ\xec!\xa3\\\xdb\x032ʁ\x86\xd8t\xda\x14\x98DF92\xcaA\x88\xd8t\nN\"\xa3\x1c\x19\xe5 \x84E\x9d\x90Q\x8e\x8cr`L\xf4:!\xa3\\\xdb\x032ʁ\x86hF\xf6\x90Q\x8e\x8cr\x10\x15\x91?wBF92ʁ\x05\xccN\xf6\xac\x81\x8c\xf28\x01)\xb0c\x83\xbd:!\xa3\x1c\x19\xe5\x13\x1a\x9bu\x9aH \xa3\x1ch\x81N1\x83\x8cr\xa0\x05:\xc5\x0e2ʁ\x06\xe8\x04\x80m@'\x00l\x03:\x01`\x1b\xd0\t\x00ۀN\x00\xd8\x06t\x02\xc06\xa0\x13\x00\xb6\x01\x9d\x00\xb0\r\xe8\x04\x80mح\x132\xca\xc1\x04\xc6T'd\x94ˌ\xbc\x87h9)\xddA\xbb\xf8\xe9h\xee\x12\xda*\xe8\xa46\x19p4T\xd74ڼg\xaeP\xe2\xf3\x9f\x15\x84\xb9\x97\xd5\u007fxgu\xb6\xb7\xf2\x8a\xf7\xb6\x95\x19O LuBF\xb9\x8c\x85\x1e8b\xc9(\xbf{^\xf8qO\xcf\v\xcb\xf2>ҩ\xafA\xca\x1b\x8c\x92\x8f{J\x02uM\xa3͇/\v\x9e\x1e\xffݳ\xc2e\xf5\xf7L.e\xaf<vr\x99 \xfc\xbb\x95\x19O \xcctBFy\x80\xe8{\xe0\x88%\xa3\xdc\u007fKz\xe3\xbf\xe3\x89j\u007f\xb5\xf2U\x8c\xf2`]\xd3h\xf3\xbbB\xe5f\xfa\x82j\xb2[\xee\xe4<M7\xc3p\x91\xf0\xef\xd6f<a0\xd3\t\x19\xe5#´3\xbd\n\xb2N\xfeefm%\xac\xec՜Nf\xd1\xe6w\x85\xcb\xd9\xc3a:\xed\xf6Hߗo\x15\u07b36\xe3\tC\xe4\xac\bd\x94\x8fEF\xb9\xac\xd3m)\xc59\xd8\xcch\xabg\xed\x90K?\xcds\xff\xb80\xffʶ\x9cһ|\\\xb9굠:m\xa3\xb3\x9b\u007f\xc7<\xda\xfc\xae\xf0\xfecg\x15\x9d|G\x97{\xbeq\x98\xadZ\xd1&i\xeewZ}\xa1\x19kz\xd0\xdd:z+\x9f\x90D\x93d\x84\x8crg3\xcao\tdž\xef\xfenْ\xbb|3\xa3\xad\x9e%,9y6\x8f\x96^\xc9\x11v\x94\n\x8b\x0f\xe6\xb5\xf2q媵\xa0:ݬ\x942\x92L\xa3ͩN\xad\xe5\x8aN\x9b\xb2\xf6\xbe\xb87k3]a\x81\xbb\x9e\r\xceXӃ\xce\xd6\xd1]\xf9\x84$\xfa\x93=>v\x15\x19壙Q~K:d\x15\xddT73\xd8\xeaYޏ\xd8Y6\x9d\xf2V\xd2W\xe0\xbc\u007f\xd3\x16u\\9\xb7\x16T\xa7\xd6,\xe9\xf54\x8d6\xa7:ݙ\u007fG\xd2\xe9\x92\x14\xf0\xc7\x1e\xdf\xe7_\x91ЌU=\xe8m\x1d\xa3\x95O<b\xd3iS`\x12\x19壐Q~K\xf8\xc9ի\x976-~C\xbdB\xfa[=kK\xa0\xd4{\x92\xee\xb1\xc3r\x90%\x17WέEy\xc3^\xe5\xe54\x8d6\xa7:\xf9\xcb[%\x9d6\xcb\xdd<\xba\xd9\xef\xe3G[C3V\xf5\xa0\xb7u\x8cV>\xf1\x88M\xa7\xe0$2\xcaG!\xa3\\\x19\x8aX_\xe4S5\xd3\xdf\xea\xa1R\xef%\xffU\xb7\x9c\v\xcbǕskQ\xee\xcdY\xf2\xb44[\xd3hs\xa6\xd3\xd9oH:\x95\xc8\xc1\x86\xe5%\xc1k'\xdf%Ռ\xc3z\xd0n\x1d\xa3\x95O<,ꄌr\xae\x87\xd1\xca(Wt:F\x0f\x12\xfc\n\xe9ou\xb5NY\xb2N|\\9\xb7\x16\xe5\xdew\xdeϑ\x0e0\xa6\xd1\xe6L\xa7\xe1\xec\xcb\xd2\xd1\xe9\x11\xb6\x86\xbe\xc2MldOڲ'\x85\xdb\xfc\x8cU=\xe8m\x1d\xa3\x95O<\xa2\xd7\t\x19\xe5\xda\x1eF+\xa3\\\xd1iS\xb6O\xb5B\xfa[]W'>\xae\x9c[\v6P~\xc9\xcd2gM\xa3͙N\xfeM\x95L\xa7\x17\xa5e8)\xbc\x18\xf8\xdc\xc9WZ\xa8\x9a\xb1\xaa\a\xbd\xadc\xb4\xf2\x89G4#{\xc8(w4\xa3\\\xbe+\xe2l\xa5\xb41\x83\xcd\xf4\xb7:W\xfaǜ\xd6\xe1\x93\uedc6+\xe9.\x1c\x8a+\xe7\xd6\xe2㞒Ϳ\xf3\xdd-\xf7^\xb9m\x1am>|Y8{\xd7\xdf\xe3\x91F\xf6*\x85\xdd\xe7w\v\x92\x80\x97<%/\x9c]\xed~E\xb58\xa1\x1e\f\xb6\x8e\xd1\xca'\x1e\x91?wBF\xf9\x18d\x94\xcb\xf7칗\x1d\xf3\xf1\xcd\xf4\xb7z\xa8t\v=\x16\x9c\xcc\x16\xb2O\xb2K\x94P\\9\xb7\x16G\xd9\xc4\x1b\xac\xf7\xbd\xa6\xd1\xe6W\xe6\n\xc2i\xbf\xaf\xc4+\x9d\xe7\xb5.\xf3,;,\x8b\xf1\xcejO\xde\xd3\xff\xa6^\x9cP\x0f\x06[\xc7h\xe5\x13\x0f\xb3\x93=k \xa3||\x13\xba\xf8\x1d1\t\xb8u\xa2\xc0^\x9d\x90Q\x1e'\x19\xe51b\xa3N\x06['\xc1\xb1Y\xa7\x89D<g\x94Lj\x8d:\x19l\x9d\x04\a:\xc5L\xfcf\x94Lj\xad\xd1\xe6\x06['\xc1\x81N\xb1\x13\xb7\x19\xe51bo\xb4y\xa2m\x9d\xa8\x80N\x00\xd8\x06t\x02\xc06\xa0\x13\x00\xb6\x01\x9d\x00\xb0\r\xe8\x04\x80m\xfc\u007f\xe7\xbd\xe7\x84\xdaB\xea\xf4\x00\x00\x00\x00IEND\xaeB`\x82",
+
+	"analysis/call-eg.png": "\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x02\x1e\x00\x00\x01\xc8\b\x03\x00\x00\x006\x92\x13\xd7\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x02\xfdPLTE\x00\x01\x00\x05\a\x03\n\r\t\r\x12\x14\x0e\x12\x1d\x11\x13\x10\x1b\x1a\x14  \x19\x15\"6\x1f#%!# $%#&(&+)\x1e++$*,*0.\"-/,\x1c0Z120463/6B;8-8:7<>;C@4#Cx@B?AFHDFDKH<MH7\x00f\x00IJH\x00i\x01\x00j\x02LNK8P|0R\x95\am\x06PROYTC\x0fp\vTVS/Z\xa3\x0es\x18,`\xae7]\xad\x15v\x1c[]Zb]K9a\xab\x19y\x1e;b\xac_a^=d\xae@f\xb0*{!bdaBh\xb3efdDi\xb4fheMj\xaf.\x81.Fm\xb1qjROl\xb2Ho\xb3kmj0\x859Jq\xb5Kr\xb7npmMs\xb8;\x86:cr\x8fNu\xba|t]Xv\xb6sur?\x8a>Zx\xb8vxu]{\xbb_}\xbez|y\x84|dX\x80\xbfL\x91K`\x81\xbbb\x80\xc0}\u007f|\u007f\x81~c\x83\xbdN\x95Ue\x85\xbf\u007f\x83\x92W\x95V\x82\x84\x81\x8d\x84fg\x88\xc2m\x87\xbci\x89\xc3j\x8a\xc4[\x9aZ\x87\x89\x86q\x8c\xc1\x8a\x8b\x88\\\x9dc\x96\x8cnt\x8e\xc4v\x90\xc6g\xa0g}\x91\u008f\x91\x8ey\x93ɒ\x94\x91\x80\x95\xc6z\x97Ƃ\x96\xc7s\xa4l\xa1\x96x\x95\x97\x94\x83\x98ɂ\x9aė\x99\x96\u007f\x9d\xcct\xa9v\x86\x9b́\x9eΚ\x9c\x99\x82\xa0Ϩ\x9d\u007f\x9c\x9e\x9b\x88\xa0\xca\u007f\xabz\x8a\xa2̟\xa1\x9e\x9e\xa3\xa5\xa1\xa3\xa0\x8d\xa6Ђ\xb1\x85\xa3\xa5\xa2\xb3\xa7\x83\x91\xa9ԧ\xa9\xa6\x8d\xb5\x8a\x94\xac֙\xacѪ\xac\xa9\xa4\xac\xc0\x9e\xad͍\xb8\x93\x9b\xafԻ\xae\x89\x9d\xb1֯\xb1\xae\x97\xbb\x97\x9f\xb3ء\xb5\xdaµ\x90\xb4\xb6\xb3\xa3\xbf\x9d\xac\xb7Ң\xc0\xa4\xa9\xb9ٷ\xb9\xb6\xac\xbcܺ\xbc\xb9\xa6Ũ\xb1\xbd\u05ef\xbe\u07fd\xbf\xbc̿\x9a\xb1\xc0\xe1\xb8\xc0ձȭ\xc0¿\xb7\xc2ݹ\xc5\xe0\xbd\xc5ڲͷ\xc2\xc6ֻ\xc7\xe2\xd6ǝ\xc6\xc8ż\xc8\xe3\xbf\xca\xe5\xbdм\xc6\xcb\xdb\xca\xcc\xc8\xc1\xcc\xe7\xc2\xcd\xe9\xbf\xcf\xe2\xc7\xce\xe4\xca\xcf\xdf\xce\xd0\xcd\xc8\xd3\xc1\xc8\xd0\xe6\xdfѥ\xca\xd1\xe7\xcb\xd3\xe9\xca\xd8\xcc\xd3\xd5\xd1\xce\xd6\xeb\xd3\xd7\xe0\xd6\xd8\xd4\xd0\xd8\xed\xe7ج\xd5\xdb\xd0\xcb\xdb\xee\xd5\xd9\xe9\xd9\xdb\xd8\xd7\xdb\xeb\xd8\xdc\xec\xd2\xde\xec\xd5\xdf\xda\xd9\xdd\xed\xdc\xdd\xe7\xdd\xdf\xdc\xd7\xe1\xdb\xdb\xdf\xef\xd5\xe1\xef\xf0\xe0\xb3\xdd\xe1\xf1\xe0\xe2\xdf\xde\xe3\xe6\xd9\xe5\xf4\xe0\xe4\xf4\xe3\xe5\xe2\xde\xe6\xef\xe8\xe5\xea\xe5\xe7\xe4\xe6\xe7\xf1\xe0\xe9\xf1\xe3\xe9\xeb\xe7\xe9\xe6\xe3\xec\xf4\xeb\xed\xea\xe6\xee\xf7\xec\xed\xf7\xe8\xf0\xf9\xef\xf0\xfb\xf0\xf3\xef\xf4\xf2\xf6\xef\xf4\xf7\xf4\xf7\xf3\xf2\xf7\xfa\xf5\xfa\xfd\xf8\xfa\xf7\xfd\xfb\xff\xf7\xfd\xff\xf9\xfe\xff\xfe\xff\xfcA\x10\x8d\xd1\x00\x00 \x00IDATx^\xed\x9d\x0ft\x14U\xbe\xe7\awqv+\xfd^\xcc&O\x98\xe51\xd3@vaȆ\x82\x89M\"\x98`^\xc0\x13a} \b\x0e\x88\x99l\x1c=A\x98\xe1\xafg2\xcf3YI\x8eA\xf2@$\x98\xacsL\x00\xb3J\x88\x12\x91\x80\xae\xe6\x80ᨼ#\x90LD\x87\x93\x991\x83о\xc9L\xc4RQD\x12\xfb\xd4\xd9{oUu\xdd[\xa9\xbe71\xe9\xaa\xea\xee\xdf\xe7p\x92ە[\xb7nU}\xba\xeaVu\u007f\xa9\xef\xa9#@\x01\xe2\x9c\xef\x89\x14\xe0!j\x1c\x88u@\x0f\x80\x03\xe8\x01p\x00=\x00\x0e\xa0\a\xc0\x01\xf4\x008\xb8\xa7G_kMeM\x9b\xfe\xa2\xad\xaejG\v\xaf6\xe0\n\xee\xe9QW\xd5z\xaa\xa5\xb2\x05\x17{\x1bʛO\xb5\x94\xb7\v\xe6\x00\x1c\xc75=Z+\xbb\xd0\xcf\xf6\xca\x1e\xf4\xb3\xa1\xb2CQ\xbaʍC\t\xe0\x19\\ӣ\xae\x81\xfc\xaanQ\x94\x8e\xf2V\\\xec\xe1U\a\\\xc15=j\x1a\xb5_u\x8a\xd2\\\xd9+\xa8\f\xb8\x84kz4Uc'\x82U\xbb\xb0\"m5\xe5\xd5MA\xd1,\x80㸦GOU]W\xb0\xa3\xa6|\x87\xa2\xec(\xafn\xedh\xab\xde\x01\xc7\x10\xcf\xe1\x9a\x1e\xca\xf9\xba\xf2\xf2\xf2\xe6\xba\x1a4\f!\xe3Ӟ\xaaf\xd1,\x80Ӹ\xa7\a:\xb3\x9c\xefS\xaa\x9b\x14\xa5\xb1\x86\xbc\xd4\u007f\x01\x1e\xc2==ȩ\xa4\xbd\x1c]ҶT\xf5\xe1rC\x1d\u007f\x06\xc0y\\ӣ\xad\xbc\v\x9dP\xaa\xf1\xf5\xcbyraۣ\xdd\"\x03\xbc\x84kz\xb4\x97\xb7t\xb4Vב˕\x96\xca\x1644\xad\x81\xa1\xa9\xe7pM\x0f\xa5uWU]\xab^n\xaf\xa9\xda\xd5\x02vx\x0f\xf7\xf4\x00b\x00\xd0\x03\xe0\x00z\x00\x1c@\x0f\x80\x03\xe8\x01p\x00=\x00\x0e\xa0\a\xc0\x01\xf4\x008\x80\x1e\x00\a\xd0\x03\xe0\x00z\x00\x1c@\x0f\x80\x03\xe8\x01p\x00=\x14e\xcd\x1a\xbb\"\xa0\xb8\xa9G8D\xd9[]\xaeQ-\x9a%:\xfc\x9b\u007f\xa3M\x11\xb3Ǐȼ\xfb\xc4\xe0yF\x8f\x12\xb4\x88\xa9gE\xb5\xdc\xc2==\xc2!\xca`yK\a\xa2\xa5\xbcUq\x85\x92)\xef\xdb\x141=\xbf\xf5?qd\xcf\"\xff\x8b\x83g\x1a5\xce\x1e9\xb2\xc7\u007fDT\xcb-\\Ӄ\nQ\xb6ᯌ\x05\xf1\x97\x92\xdd\xe0\xacy\xc48\xcb\x1e<\x14\xe5\x041cѭJTy\r\xf4\x18\x04\x15\xa2\xd4^\xefr\xe9\xdbb\x91\x0f\x1e\x86\x1eO\xfa\xa3\x9b\xd0\x02=\x06C\x85(1\xe4\x9b\xc9npv\xf2F\x9b\xa2\x8e\xa6G\xc9LE\xf9\x85\u07ff\x17U\xf0ߎ\x8b\x93\xf7l\xbcu\xea݃\x06\f{\x17M\xbdu#2\xe9\xc4d\xbf\u007f\xa52\xd3\xef\x9fޫ\xf4\xac\x9c9y\xe6J4z\xe9˜\xfc\xeb\x993_\xdc8}Q\x10\xb7\xf0䚙\xd3W\xea-\x98z\x18-x\x06\xd7\xf4\xa0B\x94\x98]\r\xdc\xda\xd1c\xcd\xe4\xb36E\x9d\x13\xfe\x17\x82g7\xfa\x9fP\x94\xf7\x8fL~\f\xedȒ)h\xfc\xbaw\xb2?\xf3\xb1'\xa7\xae\xb4T.\xf1o|\xe1\xc9\xcc\xdb\xfb\x94\xbe\xd7\x1e\xf3\xbf\xa6\xfcֿ\x17Y\xf1\x82\u007f͋{W\xa2\x97ʋ\xd3\xfd\x1b\xef\xf6g>\x91\xf9$ia\xe6\x13\x8f͜\xaa\rz\xc3z\x84[\xf0\f\xae\xe9A\x85(\x11\xa7p\xde\xc5\r\xceN^cS48\x81/]\xfc%\xa4<\x05\xe9\xa1<6\x85\x14\xa7#\x8fJ2ٺ/\xf8\u007f\xab\xe0]\xbd\x17\xbf(\xb9\xe3\x8f3\x9f\xc0\x85\xe0^|0\xb8\x1d\xab\x94Y\x82\xea\xfc_\xa5\x04/e\xca-h\xcc\xf5\xe7\x99w\x909\r=\x98\x16\xbc\x81kzP!JD\xc3.A\xedh\xf1\v\xf3\x88\xf1\x8bA\a\x0f\xa4Ǔ\xaf\xbd\xb0h\n\x99N\xebQ\x12.\x9a\xac\xbc\xa5\xb7\x0f1\x93\xc8\x14\xbc=S?\xb8\xfcq\xcfݷL\xc7\xe7$%s/\xda\xf5Ae\xe3\xcfp\v\xe44\xb6\xc7\xffg\xfc\xcbЃi\xc1\x1b\xb8\xa7\x87\x19\xa2DT\xb5\xf0\xabF\x8b\xf7\xa7\xac\xb1)\x86!c\x8f?\xfb\xf7\xe02\xad\x87Y4\xb9ݯ\xa1i\xb1W\xdf\xe5\xafe\xceܸ\xf7\xc8\xddD\x8f\x17\x95\xd7&+\xba\x1e\xb8\x05刟\x9c]\f=\xd8\x16<\x81{z\x98!J\xfc?\x03\x9d\xe2W\x8e\x16\x1b\xfdgm\x8aa\xb4\xa1\xe9t\xb2/Ez\x94\xdcr\x82\xf0G\xfc\xe2\xfd\xcc\xc7f\x92\xc2\xedw\xe0\x93\xcbJC\x8f)\n{\xf4 \xff卡\aӂ7pM\x0f*D\x89\x87\x1e\xe7\x05գ\xc3\xfbSJl\x8a&\x9a\x1e\x99\x1bO\xa0q\xc4T\xb4G\xfb\ue22cNjژ\xe11<\xe4\xe8\xbd\xe31e\xcd\xddx\x889\x13\x1f\n\xfan\x1f\xa4G&\xb2&x\xcb\"2\xa7\xa1\a\xdd\x02\x1a\n=\xe1\x81{\xa9\xae\xe9A\x87(\x91+\xee\\\xcd\t\x0e\x1e\xf8\xca\x05\xfd\xbc{e\tڽ\x8b2\x9fx\xe2\x0e\xff\xe4ߞ@\x171%\xaf)'J&\x1fa\xef\x92l\xf4\xffl\xef\xde\x12\xb4\x8b\x83G\xd6d\x9eU\xceN\xdfx\xa4Wy̿r\xcf\x13\xb7\xa3\v\x96\xd7NL\u007f2\xb8w\xf2\x89\xe0\xcf\xf0\x15\xf1\x14\xff\xed{\xf7܊G\xb8\xe4\xae\xe9\x93G\x8e\x9c\xa5[\xc0\xac\xf4\xc2I\xc65=\x98\x10\xe5)wF\xa6\xefO-\xb1)\x9a\xecE\x03\x01\xf4V>qk&\xb2\xe4\xec\xa2)S\xef\xfe\xb5\u07fff\r\x9a:\xf9\xc4T\xf4\xd32Xy\xf1\xee\xcc\xe9\x8b^\xc0G\x01\xbf\u007f#\xda\xd7~t\xec\xe9{\xf2\xd6)\x99+\xf7\xdc:yQ\xa6\u07ffw\xaa\u007f\xea^2\xb6\x98\xb2\xb1d\xfa\xcc\x12\xacW\t=\xe00Z\xc0\xec\xc9ܣ\xb8\x8e{zx\x80_\xfb\xffͦ\xe8\x04\xda\xd0\xd4\xfb$\xb4\x1e\xee}\x92\x0fz\x00\x1c@\x0f \"\xda\xe06\x16\x00=\\\x80\fn=p\xd9*\x06\xf4\x008\x80\x1e\x00\a\xd0\x03\xe0\x00z\x00\x1c@\x0f\x80\x03\xe8\x01p\x00=\x00\x0e\xa0\a\xc0\x01\xf4\x18\x16/\xad\xfaPQ\xceOK\x98\x87\x03\xb8\xa7\a\xf5$ʞ\xa6]\x95\xbb\x9a\xbc\xf7\xb0\xb0Wg\xc8\x1a\x81w\xb4\t\xb5r\xed\xa7\xe8\xd7\xe6\xa4u\xdc\xf9\xe2\a\xf7\xf40\x9fDy\xbe\xba\xa6\xad\xa3mW\xb5;\xdf\x18\xe3\xf0\xf1\xab\xf9\x0f\xbd\x8a8 \xbfB^?#\x1f\xd0\xfeP\x97\xf4\bg\xb68\xc25=\xa8\x10e#y\x0eT\xef\x0e\x97R\x94<\n\u007f\x85\u007f\xfeN\xd3\xe3wY\xbf\xe9\xeb\xeb\xeb\xc5\xdf\x11|\xc0\xe7R\xf0\xc2a\\Ӄ\nQ6h\xa7\xf2\x1a\xb7\x92P\x1c4=>}\xe6c\xf4\xb3\xfd\x1f\xfe\xd3?Κ4q\xe2\ndtϸ;\x05s\xc6\a\xae\xe9A\x85(\xcfW7v\xf5v5V;\x1f\xa3\xfc\xf4\xc0\xaa\xecſ\xc1\xfb^\xf9xӼ\xf9\xbf\xf9ͼ\xec\xe7\x99\n\x9a\x1e\x84^\xdf\u007f\xce\xc8\x18\x93\x9c\x91>\xe6\x81 :|$\xbb\xf3\xedX\x87qM\x0f:D\x19l(//opa{o\x92\u007f\xf3\xca3\xf9\xf7\xa0\xe1構\xf3\x9f\xa9\rd?\xf3\xd03L\x85\xc2M\x1f\u007f\xfc\xcc*R\f\xfe\x87u\xaa\xdavU\x1d\xb8a6\xf2\xb8IJ\x88'߹\xa6\a\x15\xa2\xecm\u0601\x86\xa6;\x1a\x1c\x8f\xe8\xbfD\x86\x9ao\xca\xe8\x88\xf1\xbc\xfc\x0e\x1ez\xbec\xa9Q\x88\xaf[\xf2I1\xf8\x0fcƌQ\xf2ƌ\xb9a\x1d\x1aCwH\xee|{\xdaa\\Ӄ\nQ6\xed\xc0\a\x0e\x17\x86\xa6\x9b\n?\xfd\x1bb\xfe&E\xd96W\xc1CЗ,5\n\x1fz\xf3\xcdM\x9a\x1e\xca\xff\xf9/\xff\x88\xf4\x18;g]{/\xd6c\x87\xb5\xb5x\xc4==\xcc\x10e\xa5\x96gh\xad\x14\xd4\x1fu\x96\xea\xb75\x1eB\a\x8e\x19h\x04\xf2\xca\xe0\xa3\a\x1a{\xbc\xa3\x9fo\xfe\xdf\xff\xf8_H\x8f\xa4\xd6.|\x94k\x96\x1c\x97\xd9\r\xdc\xd3\xc3\fQ\xba\xa6Ǧ\xc27\t\x1f\xe3\x03\xc7C\xbf{g\xf1\xaaO-5\xa8\xa1\xa9\xf2q\xe0\u007fb=\xdaI\xc7\xd7\xf9\xbcw\x17/\n\xb8\xa6\a\x15\xa2l '\x97\xe0\x0e\xc7/l_\x91\xc9uʶZ<\x00)\x90\xe5\xa2\x0f\xf5?\x9cZ\u05ee\x15h=\x94\xf5\xff-\xacG\xdf\xc4YJ\"\xe0\x9a\x1eT\x882\xb8\x83\fMw8\u007f\xe9\xb2mƦ\xe7_ڄ%y3\xf0\xca+\xaf~h\x1c<fKd\uf4fb\xa6\x1f\x87k\xff\uefc6\xf5\xd8,\xb5\fn-\x0eqM\x0f:D\xd9ۼ\xab\xaa\xa6\xd9\xf1\v\x17\xc4+E\xf3\xe6\x16\xe1[\xa2\xaff\xe1AHV\x916\xf8\xa8J+ǿ\xc8g.ԍ\x90\xf0ɥ)y\x85]k\xf1\x87{zx\x8a\x0f\xb3\u007f\xf5\xe1\xdf\xfe\xf6\xf1\x9bks̓\xc5`\xfeU\xd7c\x87\xefN7\\v\x01Ѓ\xf0\xd2\\\xed\xbc\xf2\xe9\xbcW8\xb5vhz\x9c\x1f\x97(\x1f\u0602\x1e\x1aoꗴ\xef\f\xba\xb4\xd5!\x17\xc0x\xec\xf1\x1f\xff{\x82\x1c8\b\xa0\a\xe1\xd3Mٿz\xfe\xd5\xe7\u007f\x95]f\xbd\xb4\xd5\x01=\x86\x8f\xa8\xf1\x18\xe2ӗ\x1e\xca\xcf\xca\u007f\xe8\xa5\bvh\xec0\xef{$\b\xa0\xc70\x00=\x86\x85\xa8\xf1x\x03\xf4\x18\x16\xa2\xc6\xe3\x8b\xdeGoCzܸ\xba)\x81\xfc\x00=\x86\xcc4\xe3\x03}\xb7\x1e\x0e\xe0\x02\xa0\xc7P\t\x8e]\xa7\xaaWUu`\xec\x1c\xcf}g:j\x80\x1eC%(I\x19\x19c\xd32\xd2\xc7\xdc\xe9\xfc\xb7\x1e\xdd\x02\xf4\x18*\xbdM\xe3RS'\xa4\xa6\xa6f\xb48\xff١[\x80\x1eC\xa6\xb7\xa3\xbd\xbd\xfd\x14\xfa\x97\x10\xdf\xf4\xd0\x00=\x86\x01θh9\x97D\xc1==\xa8\x10%U\x04<\x85{z\x98!J\xba\xe8\t\x1a[D5\x12\x05\xd7\xf4\xa0B\x94T\xd1\x1b\xa4\xe7\x89j\xe8\x8c\x19}D\x8bt\x16\xd7\xf4\xa0B\x94ևR\xbaN\xfam\xa2\x1a:c.\x8e6\xa0\x87\x06\x15\xa2\xb4<\x94\xd21Z\x93$\xe9\x81\xf6\x05\xe3\x93g\xe1۠\xd5Ӓ'\xe0\xf8l\x9d\xa4\x91\xae(K\xa4\xa4j\xe5\x94O\x9a\xc8\xd4ES˗MH\x9e\xd5\x01z\xf0\x115\u0383\nQZ\x1eJ\xe9\x18\xc1\x1d\xd5\xe3'\xa4\x8c[\x96'\x9dR\x94;\x93\x96\xd5=\x92\x96ާ\xf445N\xc8hllDC\xe5\x8eƤ\x87\x15\xa5y\x81\x8f\xa9\xdbV\x9d$\xa5=\xbc9e\x0e\xe8\xc1G\xd48\x0f*D\xc9>\x94\xd2Qҥ\f\x9c\xb7\xc7nj*\x05\x87\x9bH\x1f̓\x8b\x0f\xe9\xa1<\xecc\xeb*\xbeTt\xe4X\x90\x06z\xf0\x115΅z\x12%\xf3PJGI\xf7\xe9\x0f\xb1\xcb\x1bߋ\xd1\xfe_\x86\bz\x18u\x15\xdf\x02}\xea\xf0\xf5\x18C\xfeq\xfe\xaex\n\xf7\xf4`\x9eDI\x15\x1d%=]/L\xd2G\x1cs\xc8T{=\x8c\xba\xe6T\xbc\xa7\x9f\xbaI\xdb\xdfڅ\xc7X\xaa`\xbb\xfbA\x8f\xa1A=\x89\x92~(\xa5\xb3\x84E\xc8\x1b\xdfB\xe8\nO\xad\xc4\xc7\n\"\xc2\x03>\xb6.\xab\xc7\xcdOQ\xfb\xfb'\xf7Z\v\x16@\x8f\xa1A\x85(\x99\x87R:Kx\x977h\xa3\x8e\xfbID!#CQ\xbaȄ\xe4Պҗ\xceՃ\xde\xdf/\xdfx\xceR\xb8\xf8\xf8Mcn\xfc%\x9a\xf0\xa3\xb17\xfc\xe8ݰ\x1e\x8f\xff\xfd\x98\xef\xff\xf3E\xaa\x80\xfe>\xe6\xa6\u007f\x01=\f\xa8\x10%\xf3PJ\a\xe9m&\xd7(ڈb\xb5\x94\xb7\xab\xe6N\xa9\x1a\x97\x1f\xf6m\xae\xc9H\xc6\a\xb3ii\xeb\xd6M\x93\x92\xaaڨ\xba\xe8zfA\xb3Ҳ \xa9\xb1êǏ\xef\xb5\x16\x1e\x1f\xfb\xf8\xb9\x97\u007f|\xf1\xe2\xdf=u\xeeݟ\xfc\xd8\xd0\xe3ٿ{\xf6\xdc\xcb?\xf8g\xaapӽ\xef\x9e{\xf6\x87\xa0G\x18*DI?\x94\xd2A\xf0\xbd\f\x84\x1e\xa6n\xc8HM\xcd\xd0n\xbd\x04\x97\xa5&g\x90\xff\xfd\xa7=#9e\xd6\xfd\x92\xb4\x84\xaa\xbb\x04\xfdNjKF?\x97X\xf4\xb09x\xe0#\x82\xc1\xbb7\x1az\xdc\xfc\x1cz\xf9\xc6\xf7\xa9\xc2\rohu@\x8f8¢Ǐ~n-\\\x1c\xf3\xae\xf6\xfb\x8d\x1f\x8eE\xe3UC\x8f\xb1\xda\xf0\x95*\xfc\xd3؟\xfc\xf2\r\xd0#\xbe`\xf5x\xce8f\x84\vh\xff\xebz\xdc\xfcOo\\<\x17\xd6c\xcc\x1b\x86=F\xe1\xe2s\xf7\xfe\xe8\x86{A\x8f\xb8\x82\xd5\xe3\a\xbf\xb4\x16\x90\x16\xfa\xc9\xe5\x06$̳a=n6\x8e.\xe1\x02\xe6\xe5\x1b@\x8f\xb8\x82\xd1\xe3\xd9\xef_\xb4\x14\x10Oݨ\rMo\xba\xf7\xdcs\xdf\x0f\xeb\xf1\xd4\xd8_\xbe{\xee\xa9\x1fP\x85\x1f<~\xee\xdc\xcfo\x02=\xe2\n,\x86>x@G\x02\xe3\x98q\xb3y\xf0\xb8x\xf1_\xfe\x9e\\\xd8>\x87\xaeo\u007f\x1e\xd6\xe3\xe2S7\xdf0\xe6槨\xc2\xe37\x8f\x19\xfb×A\x8f\xb8\"<(\x1d5@\x8f8\x02\xf4\xe0!j<\xee\x01=x\x88\x1a\x8f{@\x0f\x1e\xa2\xc6\xe3\x1eЃ\x87\xa8\xf1\xb8g\xcc\xe8#Z\xa4\xb3\x80\x1e\x00\x87\x98\xd0#OJ]\x00))7\x88\t=:\x1a\xab&\xa6z&\x05\x93H8\xafG\xa3q\x1c訩j\xe8\x18T\x8c@\xa3\xe4\xc2'\xfe\x80\xe3zt\x95\xb7h\x85\x8e\xca\xc6\xf6\xc6\xca\x0eK1\x12͉\xf1\xf4%\xaf\xe1\xb4\x1e\x1d;t=\xfa\xc87\x8f\x9b\xaa\xfb\x98bD@\x0fWpX\x8f\xc6\xf2F=j\xddVI\x1e\xc6P\xd9\xc6\x14#\x02z\xb8\x82\xc3z\x04\x83F\x94\xb6A\xfb\xde^]#S\x8cH\xab\xe4\xc67\x95\x13\x1e\x87\xf5P\xc2I\xeb\x1a-\xd5\xd2T\xc3\x14#қ:\xad\xa9#\x91\xfe\xe3\x15o\xe0\x9a\x1e\xfa\xaf\x96j\xa6\x18\x19\x9c\x8c\x9eͫ\x00D\x01\xd7\xf4\xd0c\xf9\x8d5L1\"=i\xe3\x1fi8\xa5\x00\xce\xe2\x9a\x1e\xfa\x80\x03?\x19\x9d*F\xa4Yr\xfcIs\x80\x8bz\xb4\x95\xe3۠=\xe5mL1\"p\xe5\xe2\n\xae\xe9\xd1GB\x93\x8d\xda}\x8fp1\"\xa0\x87+8\xacG\xb0\xa3\xa3\xaa\xb1\x83\xe4\x9c\xe1\xaei\f\xe0\xb0\x1e-\xe5\x04\xf2\xf1ZGCe\x8d\xf1\x99\x8bY\xb4\xa3\xb7\xa3%\xcf\xe7B~\x1fpX\x8f\xef\xc6\x1cI\x1a\xef\xc2\xff\r\x03Ć\x1e\x1d\xadp\xe8p\x87\x98\xd0\x03p\v\xd0\x03\xe0\x00z\x00\x1c@\x0f\x80\x03\xe8\x01p\x00=\x00\x0e\xa0\a\xc0\x01\xf4\x008\x80\x1e\x00\a\xd0\x03\xe0\x00z\x00\x1c@\x0f\x80\x83\xf3z\u0605(\xa9\xa9\x80\x97p\\\x0f\xbb\x10%5\x15\xf0\x14N\xeba\x17\xa2\xa4\xa6\x02\xde\xc2a=lC\x94\xd4T\xc0[8\xac\x87m\x88\x92\x9a\nx\v\x87\xf5P\xecB\x94\xd4T\xc0[\xb8\xa6\x87%9\tzx\x12\xd7\xf4\xb0$'A\x0fO\xe2\x9a\x1e\x96\xe4$\xe8\xe1I\\\xd3Ò\x9c\x04=<\x89kzX\x92\x93\xa0\x87'qX\x0f\xfb\x10%5\x15\xf0\x14\x0e\xeba\x1f\xa2\xa4\xa7\x02^\xc2a=\x80\xd8\x02\xf4\x008\x80\x1e\x00\a\xd0\x03\xe0\x00z\x00\x1c@\x0f\x80\x03\xe8\x01p\x00=\x00\x0e\xa0\a\xc0\x01\xf4\x008\x80\x1e\x00\a\xd0\x03\xe0\x00z\x00\x1c@\x0f\x80\xc3\xf7\xee\a\x80\x88\x8c\xe8\xe8\x01\xc4;\xa0\a\xc0\x01\xf4\x008\x80\x1e\x00\a\xd0\x03\xe0\x00z\x00\x1c@\x0f\x80\x03\xe8\x01p\x00=\x00\x0e\xa0\a\xc0\x01\xf4\x008\x80\x1e\x00\a\xd0\x03\xe0\x00z\x00\x1c@\x0f\x80\x03\xe8\x01p\x00=\x00\x0e\xa0\a\xc0\x01\xf4\x008\x80\x1e\x00\a\xd0\x03\xe0\x00z\x00\x1c@\x0f\x80\x03\xe8\x01p\x00=\x00\x0e\xa0\a\xc0\x01\xf4\x008\x80\x1e\x00\a\xd0\x03\xe0\x00z\x00\x1c@\x0f\x80\x03\xe8\x01p\x00=\x00\x0eC\xd1#\xb8.=%)\xed\xb6\xa6\xc1\u007fyT\xbaS\xff1\x02\x066\x8f\xf7\x8dk\b\xbf\f\x0e\xa0\x1f\xd5\xd2mf\x85]Ҝ\xc1sQ<\"-\xe3\xfe]@\xc4\xe6-\x1d\x13@\xfa-ꪀQٞ\xa3\xc9\x10\xf4\xa8J\x924f]\xb5\xfeiTVg3n\xbb\xc5x\xf5h2^\x8a'\xf4`;&@뷨\xab\x02Fe{\x8e&b=VHҜV囮\a|Rƀ\xe5o\xa3\xb2:\x93\xa4\x15\xdf\f\x18-\x0fH\xd2 =:\x1em\xb4\x9b/\xcc\b\xf5\x88\xd8<\xd31\x01z\xbfE]\x150*\xdbs4\x11\xea\xd1(I;\xb4R\xab$UY\xfe8*\xab3Nj7_\xd8\xe9!b\x84zD\x84\xe9\x98\x00\xbd\xdf#dT\xb6\xe7h\"\xd2c \xcd\xdc\xf6ˤ\U00056fce\xca\xea\xa4I\x1d\xe6\v/\xe9\xc1tL@\x82\xea\xd1,IA\xa3|\xfeQ\xf2nj\xce\x1b\xe7K\x9e\xf8\x80\xa2\xb2\xab\x13\\1ޗ:\xa7U\xabJ\xbf\xe8Y2>)eZ\x15s\x94\xeeZ2.)u\x0e>\xafO#\xc3\x1ac\xff\xae&\xaf:\xb0\x1eʊq\xbe\xf1\x0f\x98't\xbbf\xdaf\xa7\xa6\xccj\xc7zTK\x13\xb5I\x9bɋG>'s\u007fN&Q\x1d\xae\x96\x1e\xed]\x92曄\x06\x9c\xd5\x13}i+\xa8\xf1B\xcfj\xdc\xe5\xb6p\xdbFnj\xbd\xf5\x88\xb4D\xb5\xb6\x1c\x9e\xc7\xe8\xb7ޖ\xb9z\xd69t\xe8\x85\xd9oω\xd2j\xd5}Dz< M\xb0LY&I\xe3&\xa5\xa1\x1f\x9f3\xabӚ,\xf9&\x8d\x97\xa4u\xaa\xe5EW\x8a\x94\x9a>\x01\rl\xa96꒤\x94t\xd4\x06\xda\x02\xeb\xf2|Ҭ\xbc]\xfa\x1fj\xf2$鶼 ڨh\x11i\xa9\x924q@\xdf\u007fv͔KR\xda$_R\x06ډ\x9f'I]d\xda\x04\xa9\rͽb\x9c\x94\x82\xe7\xfe\xc6\xd2\xe1jiY\xaa\x94擤\x86%\x92\x0fM\xcbP\r=\x9a\x92\xb5.\x85\xafό\x8eY\xf4\xa0[6\xe71\xfa\xad\xb5E\xad\x9ee\x0e\x1dza\x11\xb6gl\xe81[Z\xc0Nh\x96\x92\xf1A\xa1-Ez\x94^\x9d`\x8a\xb4\x1a\xad\u007f[\xaa\xd4`y1Gz\x00\xed\xe2S)\xe6\x86WO%I\xebд\x06\x9fT\xadF:\xb9H\xe3ѡ\xaa9I\xaa\xd1\xf7\x9f]3\x92\x84\xb4\xfa|\x169\xf8ܦ\x89y\n\x9f\x00\xd1\xdc\x13\xd0;\xb3ɇ\xff\xcet\x18\xfdeb\x97:\x90'\xf9|u\x03j\x83$\x9dқ\xefM\xc1\xed\x0fl\x96|\xe6\xbb\\\xeb\x98E\x0f\xaaez\x1e\xbdߤ-f\xf5\x989t\xe8\x19#lO\xb5\xae\xdc<\x90\xb9\x87H\x8fiV\x89WK\x0f뿗ѫ\xb3Z\x9aM&\xd7\xe1\xa3\r\xf3b\xbc\xb6\xf7+\xf3\x9a\xc3mܦo\xf1]R\xea@D=\xc8\xc1`\t^\n\xd9\xe66\xcd,\xd0\xfav\x95\f\x8f\x9a\xb4\x81\xd1\xfd\xd8\x124\xf7ym\xee%\x96\x0e\xeb\xedvI\xd2f<m\x1a\xdeg\xa4\xf9\x87\xf5\xc3R\x06\xb5\x17\xed\xf50[\xa6\xe7\xa1\xf5`V\x8f\x99C\x87\x9e1\xc2\xf6\xf4\b\"=fI+,S\xf4K\xbd\xcd\xe15!?\xc6I\xda\x15\xdd7IR\x0f\xfbb\x964\xad\x8d\xbd:\x1cH\xd6/\t\x06RЙ \x82\x1e\xdaP\xa2\x12\x0fQ\xc96\x1f܌\x9a\x82\xdf\xfb\xaa\xbeeQ[\xedd$}\x9e\x9e;Oe;\\\xad\x9d+\xbf\x91\xb4e\xe6I\x95z\xf3\x13%\xed\xfeWo\xafپ\xad\x1eT\xcb\xf4<\x94\x1e\xec\xea\xb1}\xd1`\x16f\xbf==\x82H\x8f;\xa9\xb5\xd2\x19h۵.\x0f\r,\x16P\xabsU\x92&M#$I-\xcc\v\xb5\r\x9d\xe9S\xf2j\xa8\x91YP\x92\xf4\xf3p\x06>w\xd8\xeb\xa1\x1d\u007fj\xf0o\xb2\xff\x067\xf3\xb9\xd1L\r\x19ٮ\xc0ǒ\x16)\x9d\x9a[\x1f(R\x1d\xae\xd6\u07b7h)x$\x88\x8e?\xe5z-\x9f>t\xa1\xb1Ճj\x99\x9e\x87҃]=K_\b\xec\xc2춧W\x10鱙\x1e\x9a\xb6\xe2-P\x99\x86\a铦1\xab\xa3H&\r\xcc\vt$_\x90\x8c\nI\xcb\xc2C\xb3\x0e)I/\xcd\xc6wRx\x17\xb6\xa6\x1e\x83\x9b\xe9\x91$\xad\xd0H\xf4h\x97\xd2\x06\x90\xcd\xd5\xd4\xdcڌt\x87\xf5\xbf\f\xd2\x03\x1dN\xa8Æ\x8e\xad\x1ef\xcb\xcc<\x94\x1e\xec\xea\xb1}!\xb0\v\xb3ݞ^A\xa4G\a\xb5*=RR;\xbeӼ\xa4\xee\xd4U\xf4\xdbr\xf48\x1f\x9e\x87y\x81\x19h[7I2W\xba'\xfc\xf6\x9a\x16\xf9\xe81H\x8fA\xcd|n\xdcj\xa8Ӯ\x8b'H\xad\x03\xc9I\x9f\xab\x16=\x98\x0eG\xd2C\x95\x84G\x8fuV=\x98y(=\xd8ճу\x99\xd1~{z\x05\x91\x1ehH\x18\xbe\xe7\xb4\x1a\r\xb5\xd0\xf9T\x1b\xbb\xad`W'M?\x9d\xaam=\x03신6\x02\xaf\x96\x92\x8c\xa1Ào\bc\x0f\xab\x1e\x83\x9bQS\xf5f\xd6i]\xdc,\xadn\xd1\xf6\x01\xbdK\xd8\x0eG\xd4c\x82>\\j\x98Ui4\xafw\xac\\?\xbd.\x19\xa4\a=\x0f\xa5\a\xbbzvzP3Fڞ\x1eA\xa8G\x8d$\xd5i\xa5&\t]{)\xba\xf9W\xc7\xe1\xadf\xae\xce\x12)\x9d\xec\xb6f|\xb1F\xbfP\xf4=\xd1E\xedWch_#\xa5|3D=\xec\x9a\xd1/\x06\x06t\x83\x83\xd2\xf8՚\x97\xf4.a;\x1cQ\x8f\xd5\xfaޛ\xad]\xd2\x10\xb4\x8e\xd5i\xa7Wt}dՃ\x9e\x87҃]=;=\xa8\x19#mO\x8f \xd4C\x9d\x83\x06MmW\a\xba\xee\x97\xf0Gr\xc8v|5\xd97K\xc2;\xce\\\x9d.\x9f\xb4\fm\x9f\xf6T|\xa5ü\x98%\xcdB\xbb\xe2j\x1euC\xebT\x92\xb4\x19\xed\xe4\xc6d|\xe1`\xb9w\x9d$5|3`s\xf4\xb0i\xa6\xc7'=:\x80'\xe9\a\xb8\f)9\x85\x1c\xd6-G\x0f\xaa\xc3\x11\xf5\xe8I\xc6]\x1axDJV\xc2\xedk\x1dC\xe7\n\xf4\x97\x9e\fi\x90\x1e\xcc<Z\xbf\xc9tf\xf5\xec\xf4\xa0f\x8c\xb4=c\xe4\xbe\a\x1aH-0\x86\x99\xb3\xc9\xc8T\x92\xc6\xcfNOJyX\x9aĬN\xa3O\xf2Ớ\xe4S]\xfaE0U\xf2M\x9c\x94,\xa5\xf5\x98m\x92ۊ\xe3$\xed\xa2\x99\xd5#]\xc2\x1f\xa2ۜ\\l\x9aiH\x92\xd2ғ\xa5\xdbt=j\fO\x98]\xc2t8\xa2\x1e\xf8\xbeUJz\xaa\x94D}\xabE\xef\xd8\x12t\xc94NJ\xde<H\x0ff\x1e\xad\xdf\xdatz\xf5\xec\xf4\xa0g\x8c\xb4=c\xe3\xae)\xa6m\xc9\x04_\xd28\xe3~TsF\x9ao\xe2ß_\xf5\xa11+}0\xecY6ޗ\x9c^\xa9\x1d\xfa\xe9\x17\xc1\x15\x13|x\x0e\xbaɎ;\xc7\xf9\xd2nӾK\xc1\xeaѕ\xe1K\xa9\xb3\xd1þ\x99\xbc\xb4\xe4i\xcd\r\xba\x15\xa8K\xda;\x8e\xdd%t\x87#\xebA>'I[@wE\xef\xd8@\xf5$_j\xde\xf9\xd6\xc1z\xd0\xf3h\xfd֧S\xabg\xab\a=c\x84\xed\x19;z\xc4\n\xc1A\x9f(\x03#$\x9e\xf4\xd8L\r+\x81Q!n\xf48\xdf\xdb\xe0\xf3\x99\xc3J`T\x88\x1b=\xf0\x00\x1a\x0e\x1e\xa3M\xdc\xe8Q\x99\x9c\x06v\x8c:q\xa3\a\x10\r@\x0f\x80\x03\xe8\x01p\x00=\x00\x0e\xa0\a\xc0\x01\xf4\x008\x80\x1e\x00\a\xd0\x03\xe0\x00z\x00\x1c\xdcУ\xa2BT\x03\xf0\b#\xd5c\x9b,\x1f\xa3^\x9e\xce?\x19\xb1\xaa\xc1_\xe5ݢ*\xa3\xc1\xdb3d\x8d\xfc\x90\xa8*C\x05\x9a%\xfb\xb2\xa8V\x820R=\xaetf\xd5S/O\xe6\x1c\x8fX\u0560,p\x05\xff:\xf3'QE\x13a]\x9b\n\xfd\xefeUt\"v\xcb_\xd9\xcc\x10\x99+\x9d\x9d\a\xe5ߋj%\b#\xd5CU\x03\xb4\x1e\xaa\xf8\x9dzy\xc6N\xf2\xbb\xa8LP\x91BX\u05f6\x82ֳ\xa3\xf25\x9b\xbfq\xe9\x06=tF[\x0f1[\x03_\x92\xdf\xf7\x89v9\x85\xb0\xaem\x05\xadg\x97w\x8a\x95\xb5\x00z\x18\x88\xf4\xb8^V\x98U\xb8\xe1\x02*]Ȓ\xe5\xda\xcbe\v\xb3\xd7~\x8b^]\xdeR\x90\x95\xbf\x1e\x9f%\x02\xbbw.\xcd^\x8bKײe}$\xf2:*ԫ\xf5\xe8\xe7\xeb\xe8\x80r\xb48g\xe9\xce~\xbd\xc1ϲ\xb6\xa3\x9f'\xf5q\xc1*\xce\"\f\xe8\xbatc\x9dk\v\xb3\n\xd6/\f\xb1\x15(\xc2\xe2\xfe\x05\xb5\xbb!T(˹!si\xdf\x16d=]Xxf{n\xe9u4\x82\xca:XQ\x98\xbbA\x1fr\x84\xf5`\xbb\x9e\x80\x88\xf48)W\x9cy}\x83܍\xce\xe5\xaf\x1f[\xb88\xa7pgٌ/й>g\xd5\xfe\xd3\xf5\xf2\x01T# /=v\xbc`\v\xae\xdc\xdd٩\xed\x92\xeb\x9dsk\xbfR\xbf\xaa\xcd\xed\xbc\x8e\xc7z\xdb\xdf:\x98\u007f\x9f\xfe\x1e\xae\xc8\xc2&\xf5\xbf\u05f9\xf8A40\xf8k\xe4E\x84\xa1\xebR\x8d\xfda\xc6\xd6\xe3\xa7\x0f\x15\xc8߲\x15(\x02\xb5\xfd\xfde\xf8L\x16\xfa\xa0^\xfe@=:\xe3\xe8G\xf4\xd2\xce̕w\x96\xca\xf3\xf6\x15\x1cP\xffr,K^\xb8\xaf~a\xf6%2cX\x0f\xb6\xeb\t\x88H\x8f\xfech\a\x87\x96o /\xee\x93\xd1;-\x84&\xf4\x17\xaeE\x9b,\xf4:>\xab\a\xf2\xbfF\xdb1_\xaf\x9f\xad\xbfc+\xf0Ѿl\xab\x8a\xf7\xc7Q\x15oq\xed\x02糬mz\xcd\xf0\xf9\xc0~\x11\f\xe1\xbaTc\a\xf3\xf1!\xe6`n\x88\xa9@\x13\xc0\x87\x94\xf5\xa4\x18\xdaZt\xadp\x1f.QK\x9b_\xa6\xbe%\x9fT\xb7\xe2\xeb\xec\xc0B4\xf9Za\x11\xa9m\xe8\xc1v=\x11\x11\xe9\xa1^;\xb8\xf6\xae\xb9\xf2rR\xbe/\xa0\xbf\xabߖ?\nW\b\xe0\xad[\x1f\xd0_\x19z\x9c\xc9\xeeW\xfb\xb3;Q\xa9\xec\xaeз\x88B\xedfǶ\xac\xcf\xf4\x9a\xe6\x1e\xb5]\x04C\xb8.\xd5\xd8\x17\x85\v\xb7\x1f\xfa(\x14b+\xd0\x04*\xba\xbbu\xeb\xd4\xfe\x9f\x16\xacת\x9aK\x9b\u007f\f\xed\xfa~u7\x9e7@.\xb6\x0fj\xc3XC\x0f\xb6뉈H\x8f\xee\xfc\xc2\xdd\xc7;K\xf5}W\xa4O= \x9b\xe7cr:\x19\xa4Ƿ\x05\xc7\xd5\xe3\x05x\x87,\xd7G\x06d?]\tl5\xe6\v\xefQ\xfbE0\x84\xebҍ];T\xb6T.\xd8\xcf9z\xa0\xbe\xbc}Z\u007fq\\~\x8f\xfc\xa6\x966\xff\xb4ڝ\xa5\xeaz\x90~w\xca\xe4\x02\xd9Ѓ\xe9zB\"\xd2ci\x11\x16a\x8b\xbe\xef\xb6\xe8SO\xcb\xe6}\x06{=\xd4\xed\x1b\xd4-x\x10\x8aނ\u007f\"\x90\xf7\xe5N\xd98xh{\xf4\xf0\x17\x91\x16\xc1\x10\xaeK5ֽ\x1b\x89q\xedX\xf6A\xa6\x02\x8d>4\xbd\x80\x97|e~\xed¯\xf1+jiX\x8f\x80\xa1\a\xb9\xda>$\x93Ӛy\xf4\xa0\xba\x9e\x90\x88\xf4(Ļ+\xf4S}\xdf\x19\xef\xd1\xeb\xf3K\xf1\x9bv;ަ\x11\xf4\xf8 \xf0e\xe0\x03\\8\xad\x9d\xbak\xf1\x99\xffK\xf3ࡖ\x96\xa2\x9d\x86\xfff\xbf\b\x86p]\xaa\xb1z\x99\x1c\x18J+\x98\n\x88\xcf\xf6\xe9\n\xeaz\xccG\xe7\x8dPQ\xadZA\xfaL-\x8dѣ\x00\x0f\xa9\xee*%s\x18z\xd0]OLDz\xd4\xcbe\a\xf7݇\x8e\xe1\xdd\xdf~@\xae\x0f\xb4M\u007f&pϡ\xb7\xb7ˇ\xd5/;\xb3*\xbaC\x1fUdu~\xa9\x86~\x8f\xae\\*:;\xc9;0T\xb8\xb6P;\xd9\xef\x9eQv\xfcx\x05\x19\xe5\xed\x9caޭ\xae\x0f\x1c8^\x9a\xf3E\xc4E0\xbd0\xeaR\x8d\xd5\xcb9\xb5'Q\xf1\f[AU7h\xc3Q\xe3\xaei\xe7ܝ\xfd\xefm˿\xa2~6w\xfb{!ji\u007f\xc9=\xd0\u007f,\xebB\u007fY\xe9\x15<\x8c]u\xec\xf0\xe2\xdcOИ\x06\xdf5=\xd0\xd9\xc9.-A\x11\xe9\x11:\xb08\x90_vxqV\xe9\x05\xed<\xac]\t\xa8\x9f\x94\x15\xe6\x14\x1d'\x9f\xb9\xc8Y\xff\x9e\x83~nS\xff\xa0\x9f\xaa\x0f\x91\x1a\a\x02\a\xf46N\x97\xce\xcb-~[\xc57F\xa8cCh{n\xf6\x83ݜEP\x84\xebR\x8d\x1d}\xb0\xbe0k~\xe9\x19k\x05\xf5p>\xe9\xc0۲\xc1\x81\xd3\xe8\xc7Nu\xbb,\xcf8c.\xad\xb8@\x96\x8f\xe5\xc89\xc7\xc8\xd8\"\xb0\xb3bna\x19\xbea\xb7U\x9f\xab\x8cYZ\x82\"\xd2cTyZ\xb6ޚ\xf0\fý\xf7\x9b 8\xaa\xc7\xd6a\\!\xf6\u007f\xa6\xe1\xd0-K\xd0\xc3\x16G\xf5\x18\x0e\x0f\xea\xc7\xf8\aE\x15G\a\xd0\xc3\x16\xcf\xea\xf1\xc9I\x8dOD\x15G\x83+d\x80-\xaa\x95\x80xV\x0fG!\x03\xec\xc1\x17L\x00\xe8\x01p\x00=\x00\x0e\xa0\a\xc0\x01\xf4\x008\x80\x1e\x00\a\xd0\x03\xe0\x00z\x00\x1c@\x0f\x80\x03\xe8\x01ppC\x0f\xc8\xd8\xc6\f#\xd5ct2\xb6C\x99m\xb8\x8cj\xc6\x16M\xc4\xdf^9 \xcbV\xb5\xa3\xd1u\xef0R=\xbe{ƖF4\x9b\xeb\x19\xdb/r\xf6\xe3/\x9c^۟c\xfd\"\xbd\xd9ua'c\x90\x91\xea\xf1\xdd3\xb6\f\x82\xd9\xdc\xcf\xd8.?L~\x1d^>\xa8r\xb8\xeb\xc2N\xc6 \xa3\xad\x87\x18#c;\x1c\xdc\xcf\xd8n\xa9%\xbfjm\xbfH\xaf!\xecd\f\"\xd2#J\x19[u\xa9>0(\xa6g\xb3D]u<\x91\xb1ݭ\xed\xfb\xb2\xdd\xccv0\xbbn\xdfI\xfb\xd0p\f!\xd2#J\x19[5@\xc6\x05E\xf2~z6K\xd4U\xc7\x13\x19\xdb\xc3Ejw\xe1\xef\xd5\xfb\x0e\xb1\xdb!\xdcu\xfbNڇ\x86c\b\x91\x1e\xd1\xca\xd8֣q\\\xa8B>h\x99\x8d\x89\xba\x9a\xb8\x9f\xb1\xed,Pwg\xedV\vp,\x94\r\x02\x87\x93=v\x9d\x8c\x14\x1a\x8e\x15DzD/c\xab\x86\xcaf\x84\x03$a=訫\x89\xfb\x19\xdb/\xe4\xfe\a\xb7\x16_\xd7B~L\x10x\xb0\x1e\xcc\x1aۇ\x86c\x05\x91\x1e\xd1\xcb\xd8\xf6\xaf\xcf2\xaff\xc3z\x90ߝ\xb2\xe5\x1a\xd1\xfd\x8cm(p)\xe7O9\x97\xb2\xb4\xa5\x15QK\x19\xac\a\xb3\xc6LݘC\xa4G\xd42\xb6\xd7\x1f\fP\xf1\xa2\xb0\x1et\xd4\xd5\xc4\x03\x19\xdb\xc5\xfb\v\xd5\xc2\x03\x8b\xc9t&\b\xcc\xeaa\xe9d\xa4\xd0p\xac \xd2#Z\x19\xdbkE\xe4\xccs\xb2\x94\x9d\x8d\x89\xba\x9ax c\xbb\xbex\x8b\xba\xa5x-\x99\xce\x1c\xab\xc2kl\xd7\xc9X\xbf\xdc\x15\xe9\x11\xa5\x8c\xed\xb5\xe5\xf2>|\xe9\xb2\x15\xed\x1ez63\xea\xca\xf6\xc2\xfd\x8c\xed\xce\x19\xfb\xd5\xfd3\xd0\xf1\x90\xde\x0e\xcc\x1a\xdbt2bh8V\x10\xe9\x11\xa5\x8c\xedGYz݅*3\x9b\x19ue\xf0@\xc6\xf6\xad\xec\v\xea%|\x03\x9d\xde\x0e\xcc\x1a\xdbt2bh8V\x10\xe91\xaa\x883\xb6ý\x05;j\xb8\xb6`o\xe3\xa8\x1e⌭\xb9\x97 c\xeb\x05\x1c\xd5C\x8c\xb9\x97 c\xeb\x05<\xa5\a\x1du\x85\x8c\xad\x17\xf0\x94\x1e\xaeE]][\xb0\xd7\xf1\x94\x1e\x80\xd7\x00=\x00\x0e\xa0\a\xc0\x01\xf4\x008\x80\x1e\x00\a\xd0\x03\xe0\x00z\x00\x1c@\x0f\x80\x03\xe8\x01ppC\x0f\xc8\xd8\xc6\f#\xd5#A2\xb6\x87qC\x05k\xcd/`\xdb\xf2Y\x96\xbc\x94_#\xd6\x18\xa9\x1e\t\x92\xb1\xbd~T\xde\xd7y\xb8x\xc6\x19\xdbY\fB\xdd\x15\x015\xae\x18\xa9\x1e֏\xc2\xc5\xef\xd4\xd8\xcc\xd8^\xc2\xdfl\r\x15/\xb6\xabNQ\x0fzX\x18\xee7%b3cK\xf4P\x0fʂo'%\x9a\x1e\x90\xb1Ֆ\xa6\xe9QV\xc8N5\xb7\x0e:)\x95\x15\xe6n\xd1N.\x90\xb1M\xb4\x8c\xed%\xf9\xad\xfe\xbf\xee\x96\xf7\xb1S\xcd\xc6\xd4\xcbs\x97\x1e>\xbeV\x0e0\x15 c\x9b \x19\xdbK\xe4\xf8T\x16b\xa7R\x8d\x15/\xee\xc7ŀjYc\xc8ت\t\x90\xb1\xbd$\xef\xef>Y\x9c\xfd\x19;\xd5l\xec\x9a\x16f\xa8\rX*@\xc6\x16\xefٸ\xcfؒ\xb1\x87\xe6\x005\xd5l\xac[&\xd9}\xb2\x1d c\x9bp\x19[mh:\xb7\x96\x9dj6\xf6\xb5v\x9e\xdc\x1aP-k\f\x19[5\x012\xb6\x9a\x1e\xf9;/죧R\x8d\x15\x15\"\x1b>\t\x04\xd8نpM\xeeiDz@\xc6V[\xda\x05\x19\x1f\xebJ\xd7W,g\xfb`4\xa6^\xca.\xac\xaf͕\xb3\x8e\xfe\x052\xb6\t\x97\xb1E\x95\xf05\xf8\x85\xc5\x05'\xe9>\x98[\a]\xd9n\xc8]\xb8\xfbh\x96\xbc\x8d\xaa\x00\x19\xdb\xe1\x00\x19\xdbX\xc3Q= c\x1bk8\xaa>o5\x06\x00\x00\t\x1cIDAT\x87\x18\xc8\xd8z\vO\xe9\x01\x19[\xaf\xe1)=\\\x8b\xba\xba\xb6`\xaf\xe3)=\x00\xaf\x01z\x00\x1c@\x0f\x80\x03\xe8\x01p\x00=\x00\x0e\xa0\a\xc0\x01\xf4\x008\x80\x1e\x00\a\xd0\x03\xe0\x00z\x00\x1c\x04zX\"\xb4\x14_W\x14d\xeb_\xee\xf5|B6Q\x9fB;r\x04zX\"\xb4\x14\xa5\xf9\x87\xb6fk_(\xf7|B6Q\x9fB;r\x84'\x97\b\x9ft_\x93\x0f\x9a\xe9\r\xc1\x1b\xdc\xfd\x84l\x82>\x85v\xe4|W=.\xcbC?*\v\xbf\x8d\x1b\xf5\x84l\x82>\x85v\xe4\x88\xf5ؾU\v\x9f\xa2a\xc8Q\xfd\u007f\xb0\b\xcd\xd3\xc6\x05\xf8\x8b\xeafB\x16M?\xb4*\xfb\xa7\a\xd9\xfd鉄l\x82>\x85v\xe4\x88\xf5\x90W\xbd~ly\xf6%m\x18\xa2\xff\x0f\x16\x1fu\x1e\x93\xeb;;\xc9W\x86\xc3\tY\x9c\xf2\xa8}\xab6\xf0\xbf\x99\xf9=\x91\x90MЧЎ\x1c\xb1\x1eK\xd1\xfb\xa8\u007fq\x91\xca&Z\x98\x93\x8b\x9eR9M\xb2 \xa7e*\xdeDp?!\x9b\xa0O\xa1\x1d9b=\x9e\xc6?\x0f\xe1\x11\xa2H\x8f\nm\xe4w\x8f\xf5\xea\xd1\xfd\x84l\x82>\x85v\xe4\x88\xf5 ۏ\x84OEz\x14k\xef\xf5\xf5E*\x8b\xfb\t\xd9\x04}\n\xed\xc8\x11\xebA§\x87q\xf8\x94\xec\x84Z\xce\xd1\xe3.\xbc\xf9C\v\xc3)k\x1d\xf7\x13\xb2\t\xfa\x14ڑ#\xd6\x03G!C\xf7\xe0\xf0i6\t\xabF\xd6\xe3-r\xbe>&\xbfei\xc2\xfd\x84l\x82>\x85v\xe4\x88\xf5\x90\xd7~p\xba\x98\xa4^\x8b\xf3\xf7\xef+\")R\xedʅ|\xf5\x9fNȖɻO\xee\x96\amQ\xf7\x13\xb2\t\xfa\x14ڑ#\xd4\xe3\x9e\xfa\xb2\x1c=\xf5z\xb94;g\xedӲ\xbc-\x94K\xce\xceY\xf8:\x90NȆ\x0e.\xcf^n\xb9\xef\xa1z !\x9b\xa8O\xa1\x1d9B=b\x02ȸE\x89(\xe9\x01\t\xd9\xf8 Jz@B6>\x88\x92\x1e\x90\x90\x8d\x0f\xa2\xa4\x87\xa3@B6jă\x1e@\xd4\x00=\x00\x0e\xa0\a\xc0\x01\xf4\x008\x80\x1e\x00\a\xd0\x03\xe0\x00z\x00\x1c@\x0f\x80\x03\xe8\x01p\x00=\x00\x0e\x02=\xe2#c\xab\xaa\x17\xd6\x17\xcc}\xf0\xcc\xf2\xf7l\xe6\x18\t\xecҢ\xb1\x1d\\F\xa0G|dl\xd5?e\xad?~t\vy\xf0\xe1\xa8\xc2.M\xb4\x1db\x10\xe1\xc9%.2\xb6k\xf1\x17UC\x15\xa3\xae\x87\xca.mx\a\xbaX\xe0\xbb\xea\x11[\x19ۅ$c{A\x8e»\xdbfiq\x84X\x8fx\xc8ؖ\xcd\xc7\xf9\xca\xd0[\xe4p\x17~\x04\xaf\xf9\x14Z\xd4\xc2!\xfdi\xbcTqHq[ci\xcc\xd3xmZ\xa0\xd68\x86\x10\xeb\x11\x0f\x19\xdb\xcf\n\xe5\xb5\xf5\x1fh;\xc6|\x04\xaf\xd9\x18n!\xbf~\xff\xdc-LqHq\xdb\xf0Ҙ\xa7\xf1\x0en\x81Z\xe3\x18B\xacG<dl\xd5k\xfb\x8a\xb2\xe4\\\\\xa2\x1e\xc1K?\xa37\x90\x8b\xde\xece\xf9lq(q[\xfa\xe4\x12~\"\x9e]\v\xcc\x1a\xc7\nb=\x9e\xc6?c<c\x8b\t\x9d^\x8f\x03Z\xf4#x\xa9g\xf4\x92g j\xebf\x16\x87\x12\xb7\xb5\xd5î\x05f\x8dc\x05\xb1\x1ed\x95c<cۭ\x8d\x03\x8a70\x8fय़\xd1K\xad\x9bY\x1cJ\xdc\xd6V\x0f\xdb\x16\xe85\x8e\x15\xc4z\xc4C\xc6v>y\xa2\xaeZ\xbb\x98y\x04/\xfd\x8c^[=\x86\x12\xb7\xe5\xeb\x11i\x8dc\x05\xb1\x1e\xf1\x90\xb1-\xc0\x0f\x99UCx\x0fS\x8fय़\xd1k\xab\xc7P\xe2\xb6|=\"\xadq\xac \xd6#\x1e2\xb6\x05\xf2\xfc\xfa\xd3\xc7K\xb3\xf1Z\x84\x1f\xc1K5F=\x8d\x97~0\xaf0nK-\xcd\xdc\x0e\xf6-\xb0k\x1c+\b\xf5\x88\x8b\x8cm\xd1\xe1ڥ9\xf9\x1b\xb4ԍ\xf1\b^\xea)\xb4\xd4\xd3x\xe9\a\xf3\n\xe3\xb6\xd4\xd2\xcc\xed`\xdf\x02\xbbƱ\x82P\x8f\x98\x00RrQ\"Jz\xc4s\xc6\xd6\xe1us\x95(\xe9\x11\xcf\x19[\x87\xd7\xcdU\xa2\xa4G<gl\x1d]7\x97\x89\x92\x1e\x8e\x02\x19ۨ\x11\x0fz\x00Q\x03\xf4\x008\x80\x1e\x00\a\xd0\x03\xe0\x00z\x00\x1c@\x0f\x80\x03\xe8\x01p\x00=\x00\x0e\xa0\a\xc0\x01\xf4\x008\b\xf4\x80\x8c\xed\xc8ѲA\xb1\x89@\x0f\xc8؎\x1c=\x1b\x14\x93\bO.\x90\xb1\x1d9\xf5\t\xa7\adl\x87A<\xeb\x01\x19ۈ\x19\xdbZ\xb2\xea\xc7\xd0\xcfZj噺W\xca\ns\xb7h'\x17\xc8\xd8&X\xc6\xf6\xab\xb2\xe2\xce\xeb\xea\xf5\xf7\x8aˮQ+O\u05fd<w\xe9\xe1\xe3ke\xbc\xcd c\x9bp\x19ۣ\xda%\xc9\U000a3595\x0f\xd7-^\u070f\x17\x81\xb7\x19dlI\xa0(\x912\xb6\x17\xe4P\xff\xd1k\xdf\x06.XVި{M{\x10\x19I\x16B\xc66\xe12\xb6\xa1\xac\v\a\xe4ڿ\xca!\xcb\xca\x1bu\xbbe\xf2\xdcm\xad]\xc8\xd8\xe2UO\xa8\x8c\xed\xd2c\xa5\xc5K\x8f\xe3S\f\xb3\xf2Fݯe\xb2~[qc\x90\xb1M\xbc\x8cm\xd9\xf6\xac\xd3\xf26\xfc\x17f\xe5\xc3u\x8b\xf0\x82?\t\xe0\xc6 c\x9bp\x19[u_\xf6\xdc\xd0\xe2l\xa2Ox\xe5麗\xb2\v\xebks\xc96\x83\x8cm\xc2el\xd5\xee\xdcZu\u007f\x0e\xe9zx噺\x977\xe4.\xdc}4\v5\x06\x19[\xd7p4%\x97HDI\x0f\x87s\xa8\x8e\xea\xe1\xf0\xba\xb9J\x94\xf4p8\x87\xea\xa8\x1e\x0e\xaf\x9b\xabDI\x0fGs\xa8\x90\xb1\x8d\x1aQ\xd2\xc3Q c\x1b5\xe2A\x0f j\x80\x1e\x00\a\xd0\x03\xe0\x00z\x00\x1c@\x0f\x80\x03\xe8\x01p\x00=\x00\x0e\xa0\a\xc0\x01\xf4\x008\x80\x1e\x00\a\x81\x1e\x90\xb1Ml\x04z@\xc6v\xa4\bW\xde\xd3\bO.\x90\xb1\x1d\x19\u0095\xf74\xdfU\x0f\xc8\xd8\x0e\x11\xe1\xca{\x1a\xb1\x1e\x90\xb1\xe5=\xc7\xd6h\x8c\xda:\x91\xd6\xcd\xd8:t\u05fd\x8eX\x0f\xc8\xd8r\x9ec\x1bn\x8c\xde:\x11\xd6-\xbcu\xa8\xae{\x1d\xb1\x1e\x90\xb1\x8d\x9c\xb1\xa5\x1a\xa3\xb6\x8e\xfd\xbaQ[\x87\ueeb7\x11\xeb\x01\x19\xdb\xc8\x19[\xba1s\xebد\x1b\xb5u\xe8\xae{\x1b\xb1\x1ed\xd7C\xc6\xd66cK5F\xb7`\xbbn\xd4֡\xbb\xeem\xc4z@\xc66rƖj\x8c\xda:\xf6\xebFm\x1d\xba\xeb\xdeF\xac\adl#gl\xa9ƨ\xadc\xbfn\xd4։'= c\xcb\xc9ؚ\x8dQ['º\x85\xb7\x0e\xd3uo#\xd4\x032\xb6\xbc\x8c\xad٘\xb9u\"\xad\x9b\xb1uBL\u05fd\x8dP\x8f\x98\xc0є\\\"\x11%=\x1cΡ:\xaa\x87\xc3\xeb\xe6*Q\xd2\xc3\xe1\x1c\xaa\xa3z8\xbcn\xae\x12%=\x1c͡B\xc66jDI\x0fG\x81\x8cmԈ\a=\x80\xa8\x01z\x00\x1c@\x0f\x80\x03\xe8\x01p\x00=\x00\x0e\xa0\a\xc0\x01\xf4\x008\x80\x1e\x00\a\xd0\x03\xe0\x00z\x00\x1c\x04zD\xce\xd8F\x99Q\xcd\xd8\x1e#-\xcd\xdb0\xf8\xc6;\x95\x14\xa6\x8a\x80\x81@\x8f\x88\x19\xdb\xe1DG\x85u\xa3\x9d\xb1\xbd~R~\xba\xb3\xf3\xe8\U00082bedթ\xa40U\x04\f\x84'\x97\b\x9f\x95\x0f':*\xac\x1b\xf5\x8c\xed\x97Z\xd8%ۺ.TR\x98\t\r\x03:\xdfU\x8f\xe1DG\x85u\xa3\x9e\xb1\xd5\xf4P\x97[\x97C}\xa1z8\xa1\xe1\xc4A\xac\x87\x91\xb1\xc5yѧ\xd5z\xf4\xf3uan\x96BX\u05c9\x8c\xad\xa6Ǖ\xc0\xbe\bIa:4<\x84`m\xe2 \xd6\xc3\xc8\xd8\xf6\xbfWXqE\xfd\xaavn\xe7uan\x96BX\u05c9\x8c\xed\x97\xf2\xe1\xfe\xeb\xbf_\xbe\xf4z\xa4\xa40\x1d\x1a\x16\x06k\x13\b\xb1\x1efƶ\x1e\xbf\xc1\xf5`\xa807K!\xac\x1b\xf5\x8c\xed\x97\xe4ذ\x98\xe4\x06\"d\xfd\xc2Ea\xb06\x91\x10\xebafl\xaf\xcc\xf8w54W\xcb5\ns\xb3\x14ºQ\xcf\xd8~)\xd7vw\x9f\xde:\xef\x0f\xaaX\x0fa\xb06\x91\x10\xebA\x86\x00Z|u\xfdN\xf5t\xaee\x8fF\xca\xcdR\b\xebF=c\xab\x0fM\xcb\x16\x87\xc4z\b\x83\xb5\x89\x84X\x0f3c\xab\x9e,\b\x19\xff\xe9\x8007K!\xac\x1b\xf5\x8c\xad\xae\xc7\xe1\xf0\xff308)L\x1d=D\x0f\xafM \xc4z\x98\x19[5Tp2W\u007f?\vs\xb3\x14ºQ\xcf\xd8\xeazl\xcd\tEL\n\x87\x8b\xc2`m\"!\xd6\xc3\xccآ}qW\xae~Y\"\xcc\xcdR\b\xebF;c\xab\xdd5=^&\xefW#$\x85\xa9\xa28X\x9b@\b\xf5\xa02\xb6\xaa\xfa\x89l\x1c\x19\x84\xb9Y\na\xddhgl\xb5\xcf\\\xb2\x96\x1f»\xdf.)L\x87\x86\x87\x10\xacM\x1c\x84z0\\\x0fx\xf3)\xbd\x8e\xa6\xe4\x12\x89\xe1\xe9\xf1\xfa\xbc!\xde?t8\x87\nzD\x89a\xe8Q\u007f&TZ+\xaa\xa4\xe3p\x0e\x15\xf4\x88\x12Cף_^\xb5m\xfeP?>u4\x87\xeap\xc66\x91\x18\xba\x1ej}N\xa9\xf5s\x11o\x00\x19ۨ1\f=\x80\xc4\x03\xf4\x008\x80\x1e\x00\a\xd0\x03\xe0\x00z\x00\x1c@\x0f\x80\xc3\xff\a'\xa7c\x12\x8d\x96\rF\x00\x00\x00\x00IEND\xaeB`\x82",
+
+	"analysis/callers1.png": "\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x03\xa2\x00\x00\x01.\b\x03\x00\x00\x00\xa3\xcb_?\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x02\xfdPLTE\x00\x01\x00\x04\a\x03\x06\f\x0f\n\r\t\x10\x12\x0f\x17\x17\x13\x1a\x1a\x14 \x1f\x19!# #$\"%$\x1d$%#&'%'(&+)\x1e()'++$*+)+-*/-!,-+-.,02/52'241574796<9-9;8:;C;=:=?<B@4?@>#CxAB@CDBDFCKH<MH7HIG\x00f\x00\x00h\x00\x00i\x01JLI\x00j\x02MOL\x05m\x05PRO\fo\t\x0fq\vTVSZVD\fr\x17WXV\x11t\x19,`\xae7]\xad\x15v\x1c[]Z\x19y\x1e]_\\d_M:b\xac_`^<c\xad>e\xafac`*{!Ag\xb2ceb)|*dfcfgeghfLi\xafDl\xb0hjgqjR\\k\x88/\x82/jkiHo\xb3/\x858Jq\xb5mol;\x86:pqoUt\xb4>\x89=|t]tvs@\x8b?swzB\x8c@vxu@\x8dG\\{\xbbxzw]~\xb7K\x8fJ{}z\x85}d}\u007f|O\x93N\u007f\x81~c\x83\xbdN\x95Uu\x84\x96\x81\x83\x80W\x95V\x8e\x85gm\x87\xbcZ\x98Y\x87\x89\x86]\x9c\\\x89\x8b\x88\x95\x8bm\\\x9dcs\x8d\xc3d\x9dd\x8c\x8e\x8bf\x9fg{\x90\xc0\x8e\x90\x8d\x90\x92\x8f\u007f\x93\xc4j\xa3jz\x97Ɠ\x95\x92s\xa4l\xa1\x96xq\xa5s\x81\x9a×\x99\x96\x84\x9cƙ\x9b\x98u\xaaw\x9b\x9d\x99~\xaay\x9c\x9e\x9b\xa8\x9e\u007f\x88\xa0˞\xa0\x9d\x80\xad|\xa0\xa2\x9f\xa1\xa3\xa0\xa2\xa4\xa1\x92\xa5ʮ\xa4\x85\x82\xb1\x86\xa4\xa6\xa3\xa5\xa7\xa4\xb4\xa7\x82\xa6\xa8\xa5\x8b\xb3\x88\x95\xa9Ψ\xaa\xa7\x8d\xb5\x8a\x98\xabѩ\xab\xa8\x8e\xb6\x8c\x8d\xb8\x93\xab\xad\xaa\xb9\xad\x88\x9f\xaeέ\xaf\xac\x96\xba\x96\xaf\xb1\xae\xa3\xb2Ҙ\xbc\x98\xb1\xb3\xaf\xb2\xb4\xb1\x9b\xbe\x9bµ\x90\xb4\xb6\xb3\xb5\xb7\xb4\xa3\xbf\x9d\xac\xb7Ң\xc0\xa4\xb7\xb9\xb6\xb8\xba\xb7\xb9\xbb\xb8\xa5ħ\xb1\xbc\u05fb\xbd\xba\xbc\xbe\xbb\xbd\xbf\xbc\xafƫ\xa9ȫ\xb8\xc0տ\xc1\xbe\xce\xc1\x9b\xc1ÿ\xb2ʮ\xc2\xc4\xc1\xbc\xc4ٲ̷\xc4\xc6ú\u0379\xd7Ȝ\xc1\xc8\u07bb\xca\xde\xc7\xc9Ƽϻ\xc9\xcb\xc8\xc0\xcc\xda\xc7\xcb\xdb\xca\xccɿҾ\xcc\xce\xcb\xc4\xcf\xdd\xca\xce\xde\xce\xd0\xcc\xc8\xd3\xc1\xe0Ф\xcf\xd2\xce\xc8\xd6\xc9\xd1\xd3\xd0\xd1\xd2\xdc\xd2\xd4\xd1\xdeէ\xca\xd8\xcc\xd3\xd5\xd2\xcd\xd6\xde\xcc\xda\xce\xd5\xd7\xd4\xe7\u05eb\xd6\xd8\xd5\xd1\xd9\xe1\xd5\xdb\xd1\xd8\xda\xd6\xd8\xd9\xe3\xd3\xdc\xe4\xda\xdc\xd9\xe6ݯ\xd5\xdf\xda\xdc\xdf\xdb\xd7\xe1\xdc\xde\xe0\xdd\xf0\xe0\xb3\xdc\xe1\xe4\xdf\xe1\xde\xe1\xe3\xe0\xe3\xe5\xe1\xe1\xe6\xe8\xe4\xe6\xe3\xe8\xe5\xea\xe5\xe7\xe4\xe6\xe8\xe5\xe4\xe9\xec\xe7\xe9\xe6\xef\xf2\xee\xf7\xf9\xf6\xfe\xff\xfc\xbd\bi5\x00\x00 \x00IDATx^\xed\x9d\x0fp\x13\u05fd\xef\xe1%\xb7\xf7\xf8Y\xba\xbdvjW&\xbevs=n\xb1\xc7\xf6\x98\xa8@\x84\xc3s\x80\x90\xe0\x10\xee\x03'J\xe19\xaf\xb9\x81\xa4\x80\xfb\x9cb\x87ۄ\xbf\xc1m\xd0\x00Uq\xc1<BL\x9d\xa7)\xc5@\xf0\xad\x15p\x9c8&\xb8Ԏi\xeb\xe4\xc6!\xb85\x93\xb9Q\xe2LP:\xb7ʄ\x99e2\xe2ܛy{ή\xa4]\xedY\xadd죕\xfc\xfb\f#\xfdt\xf6\xecٳF\xdf=\u007fvu\xbe3\xbe\x9a8\x18\x00\x80\xa9f\x86\x91\x0ec`T6\x00\x007\rH\x14\x00L\rH\x14\x00L\rH\x14\x00L\rH\x14\x00L\rH\x14\x00L\rH\x14\x00L\rH\x14\x00L\rH\x14\x00LM\nI\xb4\xb1\x91\x15\x02@z\xc3]\xa2C.\x8f\x14\xf8\xda\xdd\x1d\xbePjװ^\xfe0\u007f*y\x8e\x11\x12\x1e)))9\x81O\x88\xaf\x8fhw3\xe0\xc3Ғ\xfb5\x89\u007f}zn\xf9?\ai\xf8\xda\xdcW4\x9b\xd50K`\xd0(֯\xfcJ\xe8\x93\xe2\x10\n\x8c\x8f6\xf5$R\a\xf6Y\x18\x92\xc8!\x00\xde\x12\r\xecy\xb5\x85\x06c\xfb\xbc\x97\xbc\xfbƤ\xd4q\xd7\x1b1\xf6\x91x\xaa\xfc*#$\\\xd9Z\U000a6005s%[\xaf\xe0\x84y\xab\xb1\\\x93\xb6f\xee\xd1\xc6\xf2\xcfix\xb6\xfce\xcd\xe6(X%0\xf8\xf8ܹ\xa3%\xbf\v}R\x1cBA\x1cG\x9br\x12\xa9\x03\xfb,\x98\xbcy1\x12'r\b\x80\xb7D=\xa7ǨD\x83\a^\x15__=@/\xc1\xbeVc\x89^)\xdd\xca\b%\x0e\x97\b\xe2k\xb0\xe40\x9e\x00{5\x02\xfb\\,((\xc8\x1f\xe2h#\xb4%\xe8\xf0VX\xa2\xaaC(\x88\xe3hSN\xfcu\xd0;\v\x16+7(>\xc4\u007f\b\x80\xb7D\x87\xdc\x01\x1f\x95\xe8\xf0\x1e\xf2_\x1b\xd8C:\xb8]\xae\xae}\x86\x12m\x8c\xb4\x9c\x8d\xeaFt\xd2%z\xa5$\xb1~\xd8\x04$\x9a\xe8!\xccI\"g\xa1\x92(\x90\x00|%\x1a\xd87\x82%\x89\x9e>F\x13\x8eu\x8a/B\x00\xb7\x18I\xf4\xc3\xd2g\x19\xa1\x8cR\xa2\xe7\x1e]P:\xf7\x9f\x17\xd0\xf4\x13\x8f\x94\u07fbU\xdc\xf4viI\xc9\xf3W\x9e\xba\xbb\xfc\xfb\xea\xcb\xf7է\xe6\xcf\xd9 wSCy\x85\xb9%\x14\xd2P\u007f^^RRz\x82l\xfdqI\xe9K[\xef-\u007f\xf4cU^u\t\x11Xu \xc8\x12U\x1eB\x01\xf3hd\x84\xbd\x17北m\x9d\x13\xd2;\x9aDpn\xe9O\x16\xcc\u007f\xf3\xd99k\x02\xe2\xdf\u007f\xc3\xfc\xd2\x05O\xbc-\x1d\xe2p\xe3\x82;\x9f\xb8\xa2\n\xf5\xce\xf8\xafO\xcd]\xb0u\xeb\xdc9'\x14\x05+\xce\xe2\xc7d\x1fiL\xae\xfeC]\xd90W\xac\xdaU\xfc\x8a\x94\xb5d\xa5\xea\x10\"GW\x96\xaf<\x1a}4@\x05_\x89zNbY\xa2m\xaf҄\xee6i\x83\xa1D\x1bK?f\x842\n\x89^,}\xea\xe5\xd7^\x9a[\x12\xa4\x19\x9f={x\xee\xca \x16N\x9cXp\xef\x9c\x05[\x9f*\xfd\x10\v\x1fJ\x88{\\\x99s\xefK\xaf<ZR\x8e\x95y\xf1\xdb\xe7N\x94\xec=w\x8e6\xd4\x17ϝ+\xdfK\x82?\x9d(-\x99\xbb\xf7\xf0\x9c\r\xea\xbc\xca\x12\"0\xeb@\b\xb5\xa2\x8aC(\xaa\xc3<\x9apn\xce\xf3W\xf1\xd5\xe7\xe7\x9c\x13tNH\xf7h2o\xce)ٺ\xa6d\xee\xcf\xe6\x8a\u007f\x9d\xb3%\x8do\x9ex\xa2\xf4-\xe9\x10\v~\xb6wA\xf9{\xcaP猅\xfb\xe7\x1f}\xbe\xbc\xfc\xa5GUݔ\xc8Y\\=W\xbaW\x1e\x93\xab\xfePo\xceY\xf9\x8b\xd7\xf6\x8a\xff-\x81ߝ\xbbw\u0379s\xe7\xe8\\A\xf8\x10\xa4?\xf4\xfc\xd9\xe7˟\x8a\xda\rP\xc1U\xa2\xc3\xee@H\xa2\xb2&ߐ\xe6\x8e\f%\xfaa\xe9ӌ0\x84B\xa2G\xe7\x92\xef\xe7\xd19A\xf2}\xfc\x15&\xb2\xa0W\xec\x95%\xb4\x15\xc1x\x8d|A\u007f\x04\xe3G\xee\x15w\v\xae$\x02S\xe5U\xf5\xdfBߦ\xf29\xe2\x85᩹꼊\x12\x14\xe8Ձ\xd5\xd1UT\x87\x1eEs4\xdcH\xbe\xb6?$w\x99\xd8'\xa4{\xb4\x10\xf3\x9f\x127\xbcBoT\t'\xc8\x1fj\xe5\x13\xf4\x10w\x8b;\u007f\xbe\xe0!uȬÉ\x12\xb1\xe1=Z\xf2\x1e\x8e\"\xf2\x87\xa2\xfbH\x1d\xfe\xc8n\u0082\xef\x93n\xc9\t:\x9f\xa4\xea\xe8ʇx\xad\xe45\xfazV\xb5\x1b\xa0\x86\xa7D\x03\xfb\x86\x83\xc1\xe0XKP\xfc6\xb5yiRW\x9c\xad\xe8\x8f\xc5\xe6B\x1b\x86PH\xf4\xe3\xf9w\xff\xf8\xa5\xb7\xe9\x1cƆ\xbb\x05\xf1p\xc1\x05\xf4\x1e\xea\xcary\xaf+\xafH\\\xc1\x9f\x97\xbcD\x12\x9e/\x8f\xce˖(ٴW\x9dWY\x82\x02\xbd:\xb0$\x1a\xa9\x0eE{4\xfcf\xb9\x80\x85\xf2sх\x85OH\xf7h!\xe6\x9f\x10\x0f\x1c\xc0\xcf\xfdP\x8c\xffz\xf4\xfbwϡ\xfdM\\No\\\x1d-\xf9\\\x15bV\x1d\x9e\x9b\x83I\x95\xff\x15G\xc1\x96hx\xb7\xb3D\xd9!X\x12m\x94\xeeV\xddߨ\xda\rP\xc3S\xa2\xa3\xae\x10>|Z\xba;\xda\xde)m2\x90\xe8\xd5\xf2FF\x18F\xfar\t%G\xc5\xd7\xcf_\xdap\u007f\xc9\xdc_`\xd2\xceH\xd06c\xe5J\xcd^\x17K\xc8\xf7^\xfaZ\xa8\xf2\xb2%\x1a\xfe\x12F\xf2*KP\xa2S\x878\xa6\x8b\xb4G\x13\a\x93/\xe3\x97iK\xa9sBzG\v1\xff5\xfcV)\xa6\x12}k\xee\x82\xe7^>\xb7fe\xe4P\xe7J.\xaaB̪\xc3\xe1ҿ\x92\xc6.\xceV4\xb2[\x89bT̒\xe8#RE\x9fxH]\x02\xa0\x82\xa7D\x83~\u0090\xdb\xef\x0f\xe2a\x97ط\xc2\x01\x97\xfcȂ\x81D\x9f-\xbd\xc2\b\xc3H_.*\x98\x8b\xa4A\xf8\xfcD\xf9Q\xb1\xd7t\xf7E\xca_I\x16Ƅ\xe2_\xa9\xa41\x9d\xecQ\xe55\x90h$\xaf\xb2\x04\x05zu\x98\x98D\xf1\xb3O\xe0'\xe8\x04\x19\xfb\x84t\x8f\x16\x82H\xb4\\\x92\xe8\xfd\x0f\xd1\xc6V\x92(-\xf3%\xb1}U\x86\x98U\x87\x0fK\xbf\xff\xe1\xdb\xf7>\xa2\xb9U\x12%\xd1\xe7\xa3$\xfa\x9a\xa6\x15}\xe9CEv\xf1\x0fw7}\xbb\xbb\x11\xab\xcf\x18P\xc2S\xa2\x12>\xf9\xbeh\x97\xf8\xday@\xfeo\x8f-Q\x83F\x14\a\xee$\x89\x8dw\x8a_\xb1\xbdtx\x83\xd7<M\xbe!tL\xf6\xfc\xcf\xc8+k\xce\xff\xa1\x05b\xe3{\xa5\\\xfa6)\xf2\x1aHT\x91WQ\x82\x02\xbd:LP\xa2o\x95_-\u007f\x8b\x04\xec\x13\xd2=Z\b\x85D\x17\x90\x9d\x82R\x03\\>W\x94k\xe0\xee5\xea\x10\xb3\xeap\xb1dnIɚ\xa8;]X%Q\xf1:\x11|(J\xa2\xc2\xfc5\xe4\x8a\xf0,\xbd\x00\xac\x11K\xbf\x1a\x1a%ˇ8+MSKcQ\x90\xa8\x0e\xbc%\x1a\xf4\r\xb9}~1\x18\xdb\xd3y\xa9Kz\xbaH\xf0\xf9ܝ\xbeq\xfd\x9d\xb6FZέ\x8cF\x94\xfc/?}\xf6i\xfa\xff\xbd\xb7d\xce\xf3g_n,yS\x8c\x9f+\xfd\xe1\xcb\xff\xda(&\aߢ\x13\x8a\xd1c\xd8\xf7\xca\x17\xec}\xfe\xce\xd2\xd2_\xbd\xa7\xc8+OT\xbeE\xae\x1d\xc2\xefΝ+o<w.@\xe6,\x1b\xdf\xc2\x17\x1bK\xc9\x04f$\xaf\xb2\x84\b\xcc:HO\x17\x1d\xa6\xb5P\x1cB\x81\xce\xd1pp\xfe\xa3\xf3\xa5\xac\xcc\x13b\x1f-\xc2{w\x1e\x16N\x94\xbe'\xfcp\xcd\xc7b\xde\rG\u007f\xb6R\xec\x15\x8b\x92//Yy\xe2\xa5{\xe7\x90?g$d\xd7\xe1\xed\xf2\xd7Ξ\xbb\x1a݈*\xcf⑹\xbf\xf8\xd9C%\xe2\xdfAU\xf57\xcb\xef?z\xf6Yi\xc0\xbe\xb7\xfc\xf0\xcbk\xca?V\x1eBl\xf6K\x9f;\xfb\\\xe9S8\xea\x8c\x01%\xbc%\xea#C\xd1\x034\xea\xd8\xd7.=\xa3\xdb'\rP\x03z\xfb\\%\xd3\xf2\x9aP\xc5ٕ\xe5+ɵ\x18\x9fxd\xef\x82\xd2\xf9kޤ\xa9\xaf\xad\x99;瑳\xd2mD\xcd\x10M\xe4\xca\x13w\u07bd\xf5W\xa5%O+\xf2\nsh^z%\xb8(\xed'~Ǟ&I\uf54b\xafʼ\xea\x12\xc20\xeb@\x9f\xd1%lP\x1dB\x81\xde\xd1\xf0\xe1\xf2\xd0\xcd\x0e\xd6\t\xb1\x8f\x16&(6\x80'攔\x9f ك\x87\xef-\x9f\xbb\xe1\xa5{K\xc5&\xad|k\xe3\x9c\xf9OQEDBv\x1d~GSK\x1fQ]\x88TgqeM\xf9\x9cG\u007f\"\xe6UW\xfdʆ\x05s\x1e\x92\x1e\xf6\x13\x9e\xbd\xb3|\xcd[\xaaC\x88\x95;L\ue2ca\"\x8f:c@\x01o\x89N\x84\x9f\x94\xfc\x89\x11\x027G\xa8?\xab\x0eY\\\x9d\xf3\xf4\xd5`\xf0\xf3\x8b\x1b\xee\x8c\xefq\\`RI\x05\x89¯Ц\x82\xf8%\xfa\xf2\x1c\xa9\x8f\x1b\x9c\xabj\x9f\x01>\xa4\x82D\x81\xa9 ~\x89^,\x95z\xb8\xef\x95*fh\x01^\x80D\xa7'\xd2\xfcLt\xc8&\xd8X\xdex\xe2\xcd\x13\x8d\xac\xc9t`\xca\x01\x89NO\xe8\xfċѡ\x1e\xaf<:\xbft\xfe\xf7\xa1\x9b\x9b\x14@\xa2\x00`j@\xa2\x00`j@\xa2\x00`j@\xa2\x00`j@\xa2\x00`j@\xa2\x00`j@\xa2)\x87\xe67a@Z\x03\x12M-|\xce<\xb4\xc4(\x13\x90N\x80DٴW\xfa\x8d\xb2ă\xbf\xb2\xdd(KB\x04\x8b\x8b]\xa7njr\x01\xe9\x04w\x892\f#\x02\xde\xd6}\xed\x031\x97L\xfer\xd7\xf2E\x9bn\xc4\xca1A\x965K\xef\x9dUy\x96\x02\xe7h(y\vj\xd2\xdb#1\xb6dl1ʒ\b\x03\xa8\xc3(\v\x90f\xf0\x96(\xc30\"\xe0n\x1f\x1a\xeds\xb7\xc5\xd2h\xfd\x83\xc7w.\xba\x16#\x83H0H\x16\xd7\x12\f\x87j\x9d\xfd\x91\xf8\r\xb4\x9e\xbe\xf7\xa2J\xf7IWQ\x9el2Ӝ\xe1f\xec8!<\x99\xcdFY\x12\xe0\r\xe45\xca\x02\xa4\x19\xbc%\xca0\x8c\xe8l%\xaa\xf2\xef\xeb\xd3\xdf\xeb\x9a\xe38\xbea\xa0\xd0w*\x8a\x8b\x17\xce..^\xab\xfb\xd3p\x99\x8a\x9ap\xe8͗%\xfa\x02:)\xbe\xfa\x90\x8b~\xbadY\xcf\xdaqb4X'\xb1cڋz\x8c\xb2\x00i\x06g\x89\xb2\f#\xdaZ\xe9\xa6N\x8f\xfen\x1f9^\xd7\xdf(!X\x90\xdd>3\xdb^1\xa3\xc1\xc0e\xa4lY(Z\x86\x1eȖ\xc5H\x97e\xe9C\xdd\xf4\x83s\x96\x91\xcc\x13 0\xcbi\x94%~@\xa2\xd3\x0f\xbe\x12e\x1aF\xf8\xa4V\xa6\xfb\x05\x9d\x9d\xae/wPvc\xbc\xcb\xe18\x83?\xadv\xac&a\xf5\xa9ݫ\x17m\xfa\x8c\xe6\xf9\xf4\x99\xe5\xffm\xf3W_\r\xff\xe7W\xffu\xcb=\xd2D\xcf@&B\r#\xab\n\xb2\xaa\x88d\x9b˲\xcbH\x8fӃ$\xcaH\x96q\x1f\xce\r\xb7\x97A\u007fGA\x19U\xb7\x90\xf3$\xa3\x84\x10\x8a\xd4:\x94тG-\xa8\x18\xe3:dq\xad-ʮ\x92Υ\xa52\xbb(ܚ7dE]3\x12.!B\x17Ht\xda\xc1W\xa2\xba\x86\x11\xa4\xe7\xab;\xcaz\u007f\xf0\x8c\xe3\xd0\xe0\xe0_0\xfel\xb0\xfa\x10\xbe\xf1\x87]\xd5\x18_>S\xedx\xf0\xd0\xff[\xfa\f\xc91\xb8xݡ\u007f\x981cF\xb0fƌ[\x9a\xa4o\xb6\xd0z\xa0\xa0('\u007f\xed\n$~\xe9\x9d\xd6\x06O\x83u\x95x\x91\xe8\xf6\x16ٽ^o\xc8\xcf4,\xd1\v\xa2n\xbfq\x89\x86\xfd\xa8K[B\x18E\xaa\xcfki¸\xc7i\x15{\x05\a2\x91\xadi{\xce}$\x8b3\xa3\xce\xd3l+\x93G\xc5\xddѲJ\xb8\x84\xd0~\xe3]\x15\xb9\x93ؾ\x03)\x01W\x89\xea\x1bF\x88_dw\x8c\xbb\x1c\x91\x8e\xae(Q\x8c\x0fU\xd3p\xa9\u0602n{P\x8c\xae\xd7n\xba\x1e\xf4\xfd\xef\u007f\x10%\xfa7K\xb6\xbc\x13n\xb4\xcaм\x005U\xe8\xa0\x13\xa1\x1d\x886ݑ\x8e.VH4\xd8۵=?\x8fjԃ.iJP\x11I\xb5\x92\x89\xdf&+I\xb4\xe6\x8aB^e\xa3\xfb\x93ɦ^tP\xca=\x86\xb4\xfd\x83\xc4J\x90Y\"^Eb\x8c\x06\x80\xf4\x84\xa7Dc\x18F\xe0\x1eW\xf8\x86\a\x03\xb6Dw\x86\xc2\xf3\x8e\xf7E\x8d\x05\\\xa2D3\xfb\xfd\x91neYh\xa6\xc6YLߊ騐-QB \xbf\x8a\xbc\xb5\xa1p]ʘs=\x91T\xa5\xc0\x9c\xa1\xf0\x81B\x81\x90/\x8fAǢ\x94\x96x\t2c\x1d\xaebhE\xa7\x1d<%\xaao\x18!t\x86\x96\xa5gÖh8<\xee\xb8N\x12Z\x89DG\x14\x03\xbf\xb2\n9\xa8\xbc\x87\xbe-\xac\xa4\xa9\f\x89ʺn\xca$\xef=\x91\x9ei\xb8\x04\x15\x91T\xa5\xc0\xc2a\x99<ޕ\x9f\x02\xea\x95'\xa1&^B\x04/\xea\x8dN\x02\xd2\x1c\x9e\x12\xd55\x8c\bxZ|1\xf7\x8c\x92\xe8\xfe(\x89\x9ew\xbcK\x12\xb4\x12\r\x89\xd1YH\xdf\n#\xad\xe8>\xb9\x15\x93$*\xe4J9\x9b\xe8\xccN\xc0\x1a~nA%\xe70\x91T\x9a\xb3!J`+\n\xfb)rϽɢm\xf9\x12+!\x02\xcc\xe8N?xJTBk\x18\xe1?xD\xfc\x12\xc7rd\x8fHt\xd1~\x8co\xd4GI\xf4ڃ\xf5\xa4\x19\xfd\x9f\xba\x12\xf5о\xe6Ai$g\xb7c<\x8e\xa4;=\xa1V4\xaf\x8a\xbc\x06\xf2\xa5f\xab\xe6\x8e\xd0<\x8d\x91D\xb3\x9f\x14+^\x11%\xb0\x0e\xa9\xf0\x8d\x9bi\x96`\xf1\u009b,A\x01Ht\xfa\xc1[\xa2\fÈ\xb1}\aG}>_w\xab\xde>Ҍ\xee\x1f\xe8\xf3\u007f\xf5\x0f\xfe\xf2\xd0:G\xf5\xa9\xcb\u007f\x19\xac\xde\xf5\x87\x1b\xef\xef\xaa&3\xbd\x83\x8bV\x1f?\xbf\xfb\x1fU\x12\x15z\xe8ܭ4\xac\\\x91\xb1\u07b3>c\x05\x8d\x9b\xac\xdb\xdb\xe6e\x93#\x8f{\xbdߨ\xf1\xf6\x88zlAU\xae\x93\xcd\xf9\xf2\xd3E\xefdlה\x10F\x95Zi۲\xb9\x12e\xba\x87}^\x8b\xb3\a\xf7;-^\xb1\x88\xf5\xe8\x81\xd6v'\x92\xa6\xc2v \xc5\xd3L\x13*AA\x1f\xa3\xd3\f\xa47\xbc%\xca0\x8c8&\x0fP\xf5&+\xaf/\xa5\xb7E\xab? \x1f>\xaa_\xb4x\xd3~\x87c\xd7.\x92\xf4\xfeb\xf1u\x97\x98\xfc\xc13\xb5\x8b\xd7\xfd\x1f\x95D\a2\xe8pNj\u0082ͳ\xb3g7Km\xa3P\x97\x9be\xa7C\xba\x06\x9a#sD\f{\x96\xe4[\x8b\x1f\vu,\x1b\xbe\xde\x1d]B\x18U\xea\x88=+\xa7j#Buub\x92e([|\xad\x13\x93;\xec\xb6\\\xbbt\xe7כ\xf5$\x8e\"\xc1\x12\x94\x8cg.\x1b\x187|\xc4\x11H'xKt*ьE'\xcec\x16\xdd6=1\x0eZ\x9c\x93R\xa1\x10mŌI$ \x9d\x01\x89\xb2ّ\x1fé-~\xfc\xb3&\xf5\x87.\x84\xf1\x81\xd8Sk@\x9a\x91\x02\x12u\xc4\xcb?N\xa2D\x01\xc0$\x80D\x01\xc0Ԥ\x80D\xe3f2;\xba\x00`\x12@\xa2\x00`j\xd2G\xa2B\xf32\xf2\x18\xfd\xfan\xd0(\x90N\xa4\x8dD\x83\x95\xa1\x1f\xa3\x1d\x01\x8d\x02iD\xdaHT\xb8u\xf3W_\xfd\xe7W_\xfd\u05edK\xe0\xc7 @\x1a\x916\x12\r d\xb7ߚg\xaf\x98᜔\xe55\x01\xc0\x1c\xa4\x8dD\x05o~n\xee\x1d\xb9\xb9\xb9\xf3ހ\x8e.\x90F\xa4\x8dD\xb1\xe0\xbbt\xe9\xd2\xe8\xa5Kc\xd0\xcf\x05҉\xf4\x91h\xdc\xeb\xe8\x02@*\x91F\x12Mab\xd8SL\xb6\xe5\x04\x90jp\x97(\xc30\xc2\xd7q`Ok\xf74\xee\x9fF\xec)\x18\xfe\x15\x93l9\x01\xa4\x1a\xbc%\xca0\x8c\x18wy\x86dž\x8f\x1c\x98|\x8dθ\x19\x8c\n\x9f<\"\xf6\x14L\xff\x8aɵ\x9c\x00R\r\xde\x12e\x18F\\rQg\x97\xd8\v\x8cM\x88\x19_L\x1c~\x12\x8d\xd8S\xe8\xf8WL\xaa\xe5\x04\x90jp\x96(\xcb0BZ\xa6\xd6\xef\x9a\xfc\x9fA\xa6\x86D\xc3\xf6\x14z\xfe\x15\x93j9\x01\xa4\x1a|%\xca4\x8c \bc\xad\x9eɟ\x8a\xbdI\x89֡\xcc\xe6\xef\xe5\xe7\xde3\xa2)\u061dG۷\xb1\x1cy1\xcd\x1ce3\x97\xa0\x1fDȞB\u05ff\x82a9\x01L#\xf8JT\xc70\xc2\xefr\xb9ܓ?\x14\xbd9\x89\x06\xa9\x85C\xc1概\xec\xa1肗\xa0*\xf2&\xb8\x9b%\xdcJ\t%\xe8\a\x11\xb2\xa7\xa0\xb0\xfc+\x18\x96\x13\xc04\x82\xabDu\r#\xfc\xbe\xa1֩\x98.2\x92!\xfd\xa7\xb3\x8d,\xebi-\b\x90\xa5;+\xa3\v\x1e\xdd,\xa9g|T\"z\x11\x95D\xfc \x14\xf6\x14l\xff\n\xb6\xe5\x040]\xe0)\xd1X\x86\x11b\xdbsRwljB\xf4\xf7\xe27\xf5\x85\x1aS\xa2d\xfcg\xddH\x8aiF:w-GQ\x88\xa8\x85<\x13\xf1\x83hS\xee\xcc\xf2\xaf`[N\x00\xd3\x05\x9e\x12\xd51\x8c\x90\x9f\a\x1apM\xfa`\x94\xe8\xef\xf6\x17'(Q\xb2Ξ\xb4,}\x97f%\xdc\x10^\x8fD\xb4\xa9[\"~\x10=\xca^,˿\x82m9\x01L\x17xJ\x94m\x18\x11l\x91\xa6\x8c.\xec\x9b\x12\x89\xaaT\xf8\xf3\xdbf~\xed_\xbe\xf8\xe2\xb7߹\xf5\x96\xef\xfc9,џ\xff\xfd̿\xfd_$\xe3\x0f\xbe6\x93l\x9by\xdbO\xc5\x0f\xa4\xe5\xb4>F\x8aq\xa1D\xfb\xe0\x89\xf8A(\xec)\xd8\xfe\x15l\xcb\t`\xba\xc0S\xa2\x12\x1aÈ\x03\xc4XP\xec螎\xb9\xdbD\x88\x96\xe8\xcf\xff\xe6\xe7\x9f\xfc\xf6\xbb_|\xf1w/~\xf2\xef\xff\xe3\xbb!\x89\xfe\xfa\xef~\xfd\xc9o\xbf%jt\xc6\xed\xbf\xff\xe2\x8b\xdb~\xf0\xe7\xff\xf8\xf5\xb7\xc5\x0fĬ\xc1\x9aG\x86\x94\x85\xf6\xe8\x82G\xb7(Ə\f\x12\xf2\x83\x88\xd8S\xe8\xf8W0-'\x80\xe9\x02o\x892\f#\xdeq\x9d\x1c\x1e\x1b\x9e\xba颈D\xbf\xf9\xd3H\x83\xfa\xef_\vI\xf4\xf6߈\x1f\u007f\xff\xb7bL\x82[~/m\x9fA\xae$VTֺ\xe7\x8e\\\x8d\x1e\xe5\x19]6\x89\xfaA\xc8\xf6\x14\xfa\xfe\x15Z\xcb\t`\x1a\xc1[\xa2\f\xc3\b\xec\xebl\xdd\xd7\xd63\x05\xb7\xfe\xa2%:\xf3\xcf\xd2\xfb\xef\xbf}\xeb\x8c\x193C\x12\xbdu\xa6\b\xfd\xf8\x1f\xe2\xb6\u007f\xba\xf5\xbb\xffBTJ\x1f]\xb0\xaeu\xe6\xccZ\xa5}\xa6\xc2msi\xd2\xc2$\xec\a!\xd9S\xe8\xfaW0,'\x80i\x04o\x89r%Z\xa2\xb7\xca\x12\xbd\xfd\x9f~\xff\xc5'3B\x12\x9d)\xb7\x9br\xc6\xdf\xfc\xe0;\xb7\xfc $Q\xc50q\n\x89iO1ٖ\x13@\x8a1\xad$z\xbb\xdcѽ\xe5\x93/\xbex1,\xd1o\xfeH%Q\x91\xdf\xde\xc2W\xa2\xb1\xec)\xa6\xc0r\x02H)\xa6\x95D_\xfc\x9a4]t\xdb\x0f>\xf9\xcd\u007f\x0fK\xf4\xc5[\xff\xe5ϟ\xbc\xf8-9\xe3\xb7\xfe\xef'\x9f\xfc\xe86\xce\x12\x05\x00]\xd2^\xa2\xf4\x87e!\x8d\xfe\xf4\xef\xe9M\x97\xdf\xdc6\xf3k?\nK\xf4\x8b\x17o\xbfe\xe6\xed/\xca\x12\xfd\xf9\xed3o\xfd\xf6o\xa9D\xa5\x19\x1e\x00H*i/щB\x1f\xa3G\xc8\x12\xf5\xdc\x10\x00p\x06$\xaa\x03\xbf\x1f\xa3\x01@,@\xa2:\x80D\x01s\x00\x12\xd5\x01$\n\x98\x03\x90\xa8\x0e Q\xc0\x1c\xa4\xb7Do\x06\xa3\xc2\x01\x80\vi-Q\x00H}@\xa2\x80̤\xff\x16\x10\x98\x14@\xa2\x00\xc1\xe7̓~a\x0e\x98\r\x90(\x80\xc9OR\x8b]\xa7a\xb5^S\xc2]\xa2\f\xc3\be*gN\xda\xc2\xc7\xf5\xd7\xe5eUMVg\xefU[_\x9c\xa9\xfey\xb9[\xb4\xe1d\x10\u007f\x1d0\x1e@\x1d\x8cT\xc0\f\xf0\x96(\xc30B\x99\xca\x1bOvxm\xbdyy.gV<?+\xf7őɅX?(e\xa5>Y\xb8%ï\t\xe3$\x10ky\xf0\xf8\xeb@\x9c*\xa2\x97_\x02\xcc\x02o\x892\f#\x14\xa9\xfc\t7\x9b~Ԍ\x83q\x88O\xd4r\xae\xf1Bh/0\x97\xd5d\xa5Vl\xc6\xd9^M\x18\x17AW\xee\xbc\x18\x9b\xe3\xaf\x03Y\xc0\f~/`V8K\x94i\x18\x11IM\"#(ޮ\xf6\xd8\x12T1`\x90\xa7\x13uƙ:\xdb=\x86F4a<\fT\xa0{b\r\x1f\xe3\xaf\x03H\xd4\xcc\xf0\x95(\xdb0\"\x92ʗ@\x16B\x19t\x91\x16\xc1&\xad\x9a\xb9V\xb5\xfdr\xb5ñ\xff\xa3m\x0f/\xda\xf4\xa5z\xc7c\xf9\x19\xd4\xed\x81m\x18A\xe8C}\xf4=\xb0l\x96%\xff\x9e\x90\xa0C\xa9J\xaa\x1a\x96\xcc\x1e\xc8D\x99ê0\x8cn\x1d\x02k3\xf2\xc9EŸ\x0e\xc5r\x06\xbb*UM\x17HԴ\xf0\x95(\xdb0\"\x92ʙ>\xafW\xfe\xd1\xf6\x05\xefA\xd4\xe4\xf5\xaa\x87v\xd7Ϝ\xa9]\xbd\xb8v\xf7\xb6\xbb>\x8d\xda1\xb0>3\uf21ea\x04\xc1g\x93\x8a\xf2\xa0\xefu\xb5ޓѫNU\xb29\xc7\xda'T\xd9ɢb\x8a0\x8c^\x1d\xda\xf22\xd7\xd3n\xb9q\x1d\xacN\xaf\xd7\xdbU\x89\xb6\xa8R\x15\b\xe3]\x15\xb9q\xf5\xf1\x81$\xc0U\xa2l\xc3\bE*\u007f\xb2B\xeb*\xb0;\xba\x8f;\xea\xaf\xe1\x1b״\x1b\x86\xca\xd0c\xfa\x86\x11a\x02\xad\xe4\xab?;\xc6\x1d\xc7-ȅ\x03\xd9ǢB%\xac:ԡ\xb2\x90ьa\x1d\x9a\xfa\xc5a\xab\x13雔.\x11\x9b\xd8x{\xf9\x00wxJ\x94m\x18\xa1L发D\xab\xa3\x1bP\x19wn\x96K\xdf0\"\x82\xbf\xb9\xaa0\a\xcd\xd6ی[Q\xeeZ\xbcc\x96\xa0\x0eU\xb0\xea\xe0\xb6\xe6ʶ\xc1q\xd4Al'\x97!7\xd6e\xac\xc3U\f\xad\xa8i\xe1)Q\xb6a\x842\x95?F\x12]\xc7H\x14\xdb\xd0J\xb4\x90(B\xcf0\"Lo^\xfe\x93m^\xbb\xaeDdz\xd7v~}\xb4\xb0I\x1d\xaaa\xd6\xe1R\x15\xaa\x94\xdaQ\xc3:\x88\n\xad\xb2\x1c\xd1\xdfJ\xf0\xa2\xde\xd8\x19\x80\xa4\xc1S\xa2:\x86\x11\x8aT\xfe\x18I\xf4\x19F\xa28\x12͏\xb3cX\\INs\x99\xaeD\xdbŶツ\x9c\x80:Tì\x03\x1d\x8d>\x19_\xd3\x17\xb0[5\xbd\xe7(`F\u05fc\U00014a04\xc60B\x91ʟ\tH\xb43?^m`\x9cO\x9c#\x82e\xba\x12mC#\xf8\x02Z\x81\x83\x05\x97\x14\xa1:\x8f\x8eDɜ\xee\xacx\xdc\xe4\xfc\x15\xf4n\xabGc{\xa1\x00$j^xK\x94a\x18\xa1L\xe5\x8a\xd0\xe3\xf5\x92\xe9\xce@hF\xb7Gݎ\u007f\xf9\xc7\xc1\xd5\xf5\x83\x83\xd1#\xc1ev\x8d%\xb0.MhY\xf3\xe62dۢ\xa3\x80\xf1욶\x82\"K\xddf\x8b_\x11*2\xe8\xd4AbȾ\f\x1b\x12(F[\xbc\"Nk\x8cL}\xe0\xbdfZxK\x94e\x18\xa1L\xe5\xc9\x1b\x92\xb3\x03ra!\x97\x06\xaa;\x92\x18_vP6\xe9\xec\x1e\x0f\xc1\x1dEV\xdb\x03\xee;,zM\xd8\xe9;lu\x81\x93E\xb9ͪ0\xc2\xcd\xd7\xe1B\xa6<\x9dT\x10#\xd3x沁\xf1d\f4\x00CxK\x140'm\xc5\b~\x8cfN@\xa2\x80\xc4\xf8@2f\xd4\x01C@\xa2\x00`j@\xa2\x00`j@\xa2\x00`j@\xa2\x00`j@\xa2\x00`j@\xa2\x00`j@\xa2\x00`j@\xa2\x00`j@\xa2\x00`j@\xa2\x00`j@\xa2\x00\a\\\xd9\r\xe2kO.\xf7_3\xa5\x01 є\xa0\xbd\xd2\xcf\b͈\xbf\xb2]\x9b\x18\xc8^\x8b\xc60\xbeϦY\xf5\x85\x01\xb3\x84i\fw\x89j\r#\x047]\x16E\xb3\x82\x1d\x10f\vjb\x84\xf1\x93\x88w\xc4Ͳ%C\xebzџ)\xccj\xc7㖍Q\xe9\xa3+\xf2\xb3go\x96\u007f\x1f\xef\xb2\xe7\xe4o$?\x88c\x95\xa0\x0f\xcfsK\n\xbc%\xca0\x8c\b\xb8.\xf8DL\xdd6L\n\x9d\xfdF9th\xcep3\xc2\x04H\xc4;\x02\x1b\xac\xb6=\xf8n\xec\xedؓ\xa9Yl\xb0\xd7\x1a,h\x15\xaf.Q\xebI\x8c|c\xf6v\xcfƜ\xd9t\x8d\x9c\x85\x19u\xed\r\xa8U\xa7\x04)?+1\xa1sKExK\x94a\x18\x11pM\x13K\xae\x8a\x1a\xa3\x1cl.Y\xd63\xc2DH\xc4;b\b\xc5^Tb\x9d\xce:-\x11\x1a\xac\xd1\xff\xa1\xfe\xcc=h(X\x18mo\xb1\xa4\x80\xf4\x9c\x86\xb3I\xe3\xba\xc4\xdaM\xd6gi\xd6)\x81\xc0\xaeY\"疒p\x96(\xcb0b\xdaH\xb4,\x8eeLX8g\x05\x18a\"$\xe2\x1d\xd1c\xb0\x8c\x91\xdeRJ\x11\x02\xb3\x9c\xd1I\x8f\xa1\x85\xe2\xe1\xa2ǘ\xc5\xd2B\x10\xf7U\x90\xa3\xd2\xfe\xfb\x88\xb4\xf2\x03\xa3\x04\xacW\xb3D\xce-%\xe1+Q\xa6aD\xbaIt \x13\xa1\x86\x91U\x05YU\xe4*\xd4R\x99]D\xdc%<\xf2\xf2$ed\x9d\xea\x8c\x16<jAŪ\xbcu\xc8\xe2Z[\x94]\xa5\xf9c\b9OF\x87\xba6\x12:\xc4\xef_\xc1\x16\xc2\xe0\xa6\xda\xea\xe5\x9bjo\xe0ץuZ\x1ct\xdd\xd0\x1b\xa7\xd6-^\xbd\xfb:ƻ\x1c\xd5\xc7w\xd6.\xdd\xf4\x91\x9c\xbd!+z^!8,\xe0e\x9aɢnIF\xceB\xf1ob\t`\xc5fm\tXO\xa2\x89\x9c[J\xc2W\xa2LÈ\x80\xeb\xe4\v\xae\x03\u07b4\x99-\x12Z\x0f\x14\x14\xe5\xe4\xaf]A&1\x9d\x19u\x9ef[Y\x10\a\xba\xbdEv\xaf\xd7+v\x1b|^\x8b\xd8d\xf4\x90\xf5\xbe\x14y\x87\x0fd\"[\xd3\xf6\x9c\xfb\xa2\xcb\xebG]ѡ\x8e\x8d\x84 /L\xaf\xf9S\xc6\xed_\xe1\x1f\x1d=\x82\x8e\x8c\x8e\xaa'\x06\xfe\xed\xae\x9dgΟZ\xee\xf8\x12_\x1b\xa4\xab\x9d\r~@\x92w:v\x9f?\xfe\xe0\xe37\xf0\xe53Վ\xdaC\x87j\x17]\x96\xf2w\xb3\xb4\xa4\x9d,\x92\x11\xf2V\x89=\x8c\x8a=\xc5\x19y\xceВ\xfa\xda\x12\xd85\xc3\t\x9c[\xaa\xc2U\xa2lÈ\x80\xabe`l\xb8\xf5`\xdahT\xfc¡y\xe2\x99Ҷ\x93\xcc\xee\xf4\xa2\x8345\xdcѥN2MVu^l\xcd\x155\xbd\xca\x16]\x98'2ˢ\bY6\x12v\xb9\xa5\xd6]\x8e\xd3ȿBgi\xfb\xe3\x0f\x92\xc6\xfa\xf8\xd2\x1b\xe4C\xb8\xa3\xfb\xba\xe3\x94\xf8\xfa\xae\xe3\x8c\xf8Z\xfd\xb0X\x93k\xb5\xf2\xa2\xdcc\xac\x81\xa0f\xb2H&\xe8\xcc\x12/[\xf9\x19\xb6-\x1d\xcdy\xf9r?^S\x82\xf1\xa2\xfbF疲\xf0\x94(\xdb0\x02\a\x87\x888\x05w\x1a\xad\xe4Z\x16\x9a\xeex\xa0P \xe4ӡ\x95\x8eD\xc3S#Vg$UA[\xe4[\xa9\bY6\x12#\xf2\xc2\xf4\xfas\xb2\x06\xfe\x15\xc1N\x8f\xa7\t5y<\xea\x81ܧ\xb5\x0f\xef>\xf5\xfe\x8d\xeb\xf4CX\xa2\xdb\x1e\xbe\xfe\xa5H\xedN1\xae\xdeOR\x8e;\xa4KƘtIRS\xa8sᨣ\v\x18\x97Y\x89\x80Dz\xe5>\xbd\xa6\x04\x9d\x9a)1\xf2\xe6HUxJ\x94m\x18\x11\xc2ۦ\xb7_\xeaQV\x11\n\xe4K?\xbd\xb6\xebH4\x94W\x95\xaa@1\x04S\x84:V\x16\xb11\xf2\xaf \xb0F|\xd7N=\xb3ڱ\xfc\x97\xeaV\xf4qGd\x01\xd1\xeaC$e\xd0!ݐ\xe9e\xac\xca\xebEm\n\xc3\xe50\x81\x9aLz\x17\xa9\xa6\x98~\\V&%\xb3J0\x98Ȋ\xe7\xdcR\x12\x9e\x12e\x1bF\x84\xd4\xda\x19\xa7\aC*\x10\x16\xe3\x8a\xc2~\x8a?\x9cJo\x05S16X\xd5y\xf5$\x1a\xb061B\xe3\x89U\x06F\xfe\x15\x04\x86\x10\xde\xdd/\x8a\xf3ڙE\xc7\xc9\az\xe0S\x9f\x92V\xf4]\ni9\xabw\x93M\xa7\xe4V\xb4ɢ\x9dw\xae\xb1\t\xd8\x19\xa9\xbe\x8c\xaf,W\xeaN5\xe4\xd0q\xce\x12\xf9z\xc5*\xc1@\xa2\xf1\x9c[J\xc2S\xa2\x12\x1a\xc3\b\x0f\xb5\x04\xf2\xbb/\xc4\xdc-\xa5\bˮC\xba\x17\xbfq3y\xb5\x8b]\xbdq\x9a@\xfas\xc1\x8a8%\x8ak\xee\bj\xc3\tI\xd4ȿ\x82p)G3f<\xe48O\xde\xeaw\xd1\xd7z\x8c?#\x03\xd0\xf3t\x14\x8a\xf7\xffR|\xa9^NƢ\x0f\xd7\xd3\xec\xc1\xe2\x85\xd1%`\xbfe=\xeeGM\x19j\x8bŁYE\x97\x88\xbf)\xb9\xe7IN\xfe\x12}\x94\x97]\x02\xb3f\n\xe29\xb7\x94\x84\xb7D\x19\x86\x11c\xae\x8e\x91\xb1\xbe}\x9etY\f]\xe8\xa1s\xb7Ҩq=z\xa0\xb5݉\xe8e\xa9ɺ\xbdm^69\xe5J͕ۖ(\xd3=\xac\xc8\xeb\xf3Z\x9c=\xb8\xdfi\xf1F\xcfE\xbe\x93\xb1=*\x8ci#\x11\x03#\xff\n\x1d\x0e9\x16\x1fz\xfd\xf5\x9d\x8eA\xfa\xa1\xfa\xf8\xeb\xf5\x8bɡ\xf7ߵ팘J\xa7\x8b\x1c\xebΜZ\xbd\xf4\x03\x9a}\a\xd2>F\xb5\x1d\x8d\xe0\x03\x85A\xab\xea\xc0Dzfy\x88\x95E\xbe\x18o\xb44tl\xb7\x15\atK0b\x82\xe7f~xK\x94e\x181~\xf2\x80\xdb3\x94.\n\xc5\x03\x92\x0f\x85\xdc\x0et\xd8m\xb9v\xe9&\xb0P\x97\x9be\xa77\x05F\xecY9U\x1b\x11\xaaS\xe4\xad\x13\xdf-C\xd9\xe2k]t\x89\r_\xefV\x87\x13\xb5\x910\xf4\xaf`s\xaa\xfePm\xf5\x83\xf5T\xa1\xf8\xfa\ue94b\xea\xa51\xe7\xf9\xfa\xe5K\xebi\x03[\xbd{\xe7\xd2\xdam\u007f\xa1\xa9ެ\xf0}\xdc\bw\x88G\xf4Z<\xea\xf9\xd8\xd0\f4\xedݶ\xce\xce*j\b\xe8\x97`\xc4\x04\xcf\xcd\xfc\xf0\x96(0\x11\x1e\xb3\xb42B\x13!M\x17Q\x0eZ\x9c\xda\xdbg\xe3H\x1c\xcd\x04+\xd1\n\xcd\x16\x06\xcc\x12\xa6/ є`G\xfe8#4\x0f\x11\x89\xfag1\u007f\xa6Bo,\t\xef\xc4\xd3U\xd2)a\xda\x02\x12\x05&\x01E+\nL2 Q\xe0\xa6\xf9l\xb0z\xd7\x1fn\x18\xe5\x02&\x06H\x14\xb8iv9\x1c\x0e\xc6\xc3N\xc0\xa4\x00\x12\x05\x00S\x03\x12\x05\x00S\x03\x12\x05\x00S\x03\x12\x05\x00S\x03\x12\x05\x00S\x03\x12\x05\x00S\x03\x12\x05\x00S3\x9d%Z\x83l\xab\x86\x8d2\x01@r\x99\xce\x12\xf5u\xba\x8bm\x13Z\xf4\x12\x00\xb8\xc1]\xa2Z\xc3\b\x91\xe1c\xee\xd6>\xbd=\xa6\x92.4\x80\x01\xc0\xcc\xf0\x96(\xc30\x02\v']=\xa3\xfd\xaeX?\xa9\x9f*z\r\xd6u\x06\x80d\xc3[\xa2\f\xc3\b|z\x8fؚ\xfa]\xc9\x18\x16\x82D\x01\xb3\xc3Y\xa2,\xc3\b\x9f\x8b\xaeZ\x94\x94A!H\x140;|%\xca4\x8c\xe8\x11\xd5\x1a\xcfO}\xa7\x82\x81\xc8J\xef\x00`J\xf8J\x94i\x18\xd1\xee\x19ns\x1d\xe8N\xcaZ\x18\x82\xad\xb2{,Y\xd7\a\x00\x88\x03\xae\x12e\x1bF\xb4RÈ\x03\xadI\xd1\xe81\x84\xd0=F\x99\x00 y\U00014a0ea\x84g\x0f]\xf5\xda\xdd\x1b{\xef)!`+\xdcѩ\xe7\x12\x02\x00&\x80\xa7Du\f#\xba$\xa7\x88\xaeh\xf7I\x1e\xf4\xa2\x93FY\x00 \xa9\U00014a0eaD\xbf\x9b\x0e\x06O'\xc30\x02ft\x01\xb3\xc3S\xa2\x12\x1a\xc3\b?\xbd\xe9\x12\xd8\xd7\x17s\xb7\xa9\x01$\n\x98\x1d\xde\x12e\x18F\xe0\xbe=}cC-mɘ.2r\x8d\a\x80d\xc3[\xa2,\xc3\b|\xa9\xdd}\xa4\x8f\xbfB\x05_\u007f\x8d5m̜\x814\x85\xb7D\xcd\xc4\x12\x84\n\x921G\x05\x00\t0\x9d%\xea\xeb\x1f\xc3\x00`r\xa6\xb3D\x01 \x05\x00\x89\x02\x80\xa9\x01\x89\x02\x80\xa9\x01\x89\x02\x80\xa9\x01\x89\x02\x80\xa9\x01\x89\x02\x80\xa9\x01\x89\x02\x80\xa9\x01\x89\x02\x80\xa9\x01\x89\x02\x80\xa9\x01\x89\x022\xb0>\x8c9\x01\x89\x02\x04\x9f3\x0f-1\xca\x04$\x03\x90( \x12,.v\x9d\x86'\x96M\tw\x89j\f#\x84\x16y\xb5\x94\x031\xf7\x9b\x1aN\xda\xc2k=\xf8\xeb\xf2\xb2\xaa&\xab\xb3\xf7\xaa\xad/\x14n\xb7ng\xa4\x86\xf1\xcf\xcbݢ\r'\x83\xd0Ѿ\x87$\nU\xa9j\x06P\a#\x150\x03\xbc%\xaa5\x8c\x10\\\xfd>\x91>W2\xdcU<\xd9/\x84\xc2yy.gV<\xebm\xfb\xe2\xc8\xe4B\xaePXf\x99\xcdH\r\xf3d\xe1\x96\f\xbf&\x8c\x93@\xac_\xbb\x86\x8ef\xaf\xf0\x8a\x1c\x94\x17:d\xd5\x01\xe37\x90\x97\x91\n\x98\x01\xde\x12e\x18F\xd0\xe3\xf1\xd4\x00\x00\x0f\xb1IDAT\f\xd1U\x8cZ\xbac\xef8E\x84\x9bM?j\xc6\xc18\xc4'j9\xd7e\xd8ؾ\x80B\xd2\x0fd\xac\xc8\b\x15\x1bI\x8dP\xb1\x19g{5a\\\x04]\xb9\xf3bl\x0e\x1d\xad\x8a\x8e1\xabr\xc6T\xa9j`\x81\x18\xf3\xc2Y\xa2,\xc3\bʱ\x17\xf8\xaf\xba\xa0b\x04Ż\xbc\xd9\xd8\x12Ta\xd4\xe2w\xa2\xcep\xd4\x1f^\xf1>\x92\x1aa\xb6{\f\x8dh\xc2x\x18\xa8@\xf7\xc4\x1a>\x86\x8e6NZf7r\xabSՀD\xcd\v_\x892\r#\bîqݝ\xa6\x8c@\x16B\x19t\x04,ؤ\xe1\xdaZ\xd5\xf6\xcb\xd5\x0e\xc7\xfe\x8f\xb6=\xbchӗ\xea\x1d\x8f\xe5g\xac%-\xe3X\x8e<\xccˉ\x96J\x1fꓣ\xa6|\x9cߤI\x8dPհd\xf6@&\xca\x1cV\x85at\xeb\x10X\x9b\x91O.*\xf1ԁ\xe4\xaab\xa4F\xe8\x02\x89\x9a\x16\xbe\x12e\x1aF\x10ZO\xeb\xee3\x85\xf4y\xbdVI>\x17ıZ\x93\u05eb\x1e\xda]?s\xa6v\xf5\xe2\xda\xdd\xdb\xee\xfa4j\xc7\xc0\xfa̼#\xa2\xb2\xdd\xcd\x12\xee\xe8.\x80\xcf\x16*j^\r^fפF\u061cc\xed\x13\xaa\xec=AU\x18F\xaf\x0emy\x99\xebi\xff9\x9e:D\xba\xb9\xcc:\b\xe3]\x15\xb9q\xf5\xf1\x81$\xc0U\xa2l\xc3\bL\x16\xc1Nք\u007fV\xa8\x85cwt\x1fw\xd4_\xc37\xaei7\f\x95\xa1\xc7\xc4>䨄~\x17 \x98\xbd\x1d\xefȎ1v݂\\8\x90},*TªC\x1d*\x1b\x92C\xe3:(\xba\xb9L\x96\x88mp\xbc\xbd|\x80;<%\xaac\x18!r\xb25\xd6~S\x89\x91D\xab\xa3\x1bP\x19wn\x96\v\x8f\xa2\x10\xba\x9e\x13\x03\xa8[\xe8\x8ea\x05ފr\xd7\xe2\x1d\xb3\x04u\xa8\x82U\a\xb75W\x16]\x1cuPtsٛ;\\\xc5Њ\x9a\x16\x9e\x12\xd51\x8c\x10q\xf7\xc5\xd8mJ1\x92\xe8:F\xa2؆V\xa2\x85D\x11^\x8f\x84\xfe<l3UO\xb3\xde\xe6\xf1쵝_\x1f-lR\x87j\x98u\xb8T\x85*\xa5vԸ\x0e\x8an\xae\x1e^\x94\fG\x1d \x1exJT\xc70\x82\xacG\x9f4\xe7##\x89>\xc3H\x14G\xa2\xf9\xf1v\fk\xcaz{{\xcbj\xf46\xb7\x8bm\xdf}\x059\x01u\xa8\x86Y\a:\x1a}2\xbe\xa6O\xea掮\x8d1g\x0e3\xba慧D%4\x86\x11\xa4y\x8d\xef\xbb6\x05L@\xa2\x9d\xf9\xf1jCd\x16\x99$^;Kos\x1b\x1a\xc1\x17\xd0\n\x1c,\xb8\xa4\b\xd5yt$J\xe6tg\xc5c\x1a%ws[Q\x8c\xe7\x1c@\xa2慷DY\x86\x11b\x93\x9a\x94\x9b\xa2B\x8f\xd7kuz\xbd\x81Ќn\x8fzZ\xe7\xcb?\x0e\xae\xae\x1f\x1c\x8c\x1e\t.\xb3\x0f\xe18\x11\x8e\xa1\x8d\x01\x1c؈\x8e\xe9\x9c\xe0xvM[A\x91\xa5n\xb3ů\b\x15\x19t\xea 1d_\xc6LWs\x0f:H\x1e/j\x88%\xd1>\x94\x9c'G\x00cxK\x94i\x181\xcaz\xe0e\xeay#C\x9agqa!\x97\x06\xaa;\x92\x18_vP6\xe9\xec\x1e\a'\xc5B[\xf1\x11\xf1U\xef\xa6\xd2\xe9;lu\x81\x93E\xb9ͪ0\xc2\xcd\xd7\x01\x17\xc9\xd3I\xb1f\x84\xc63\x97\r\x8c\x1b>3\x05$\x03\xde\x12\x05\xccI[1\x82\x1f\xa3\x99\x13\x90( 1>\x00\x0eT\xa6\x04$\n\x00\xa6\x06$\n\x00\xa6\x06$\n\x00\xa6\x06$\n\x00\xa6\x06$\n\x00\xa6\x06$\n\x00\xa6\x06$\n\x00\xa6\x06$\n\x00\xa6\x06$\n\x00\xa6\x06$\n\x00\xa6\x06$\np\xc0\x95\xdd \xbe\xf6\xe4&\xb6L0@\x00\x89\xa6\x04\xed\x95~FhF\xfc\x95\xed\xda\xc4@\xf6Z4\x86\xf1}\xb6x~t\xc8,a\x1a\xc3]\xa2\x1a\xc3\b\xf1?\xf0\xd5\x17\xf6\xbd\xf0jܿ\x92\x9e\x86lAM\x8c0~\xe2\xf7\xaf\xb8y\xb6dh]/\xfa3\x85Y\xedxܲ1*}tE~\xf6\xec\xcd\xf2\xff\xbc˞\x93\xbf\x91\xfc \x8eU\x82><\xcf-)\xf0\x96\xa8\xd60\x02\aZچdž\x8f\xb4\xa4\xbdF;\xfb\x8dr\xe8М\xe1f\x84\t\x10\xbf\u007f\x85\x88\xc1jۃ\xef\xc6ގ=\x99\x9a\xa5\x9az\xad\xc1\x82V\xf1\xea\x12\xb5\x9e\xc4\xc87fo\xf7l̙M\xd7\xc8Y\x98Q\xd7ހZuJ\x90\xf2\xb3\x12\x13:\xb7T\x84\xb7D\x19\x86\x11\xdeV\xd2\xfd\x11Z\x13\xf1JHI*t\x970\x8a\xcd%\xcbzF\x98\b\xf1\xfbW\x88\xdd\x1c\x14{Q\x89u:\xeb\xb4Dh\xb0F\xaff\xe6\xcf܃\x86\x82\x85\xd1\xf6\x16K\n\xc8\xff\xfcp6i\\\x97X\xbb\xc9\xfa,\xcd:%\x10\xd85K\xe4\xdcR\x12\xce\x12e\x19F\x9c\x96\x16\xealO\xcaj\xd7<)\x8bg\x19\x13\x06\xceY\x01F\x98\b\xf1\xfbW`\xdcc\xb0\x8c\x91\xdeRJ\x11\x02\xb3\x9c\xd1I\x8f\xa1\x85\xe2\xe1\xa2ǘ\xc5\x05\xf4\xed\xbe\nrT\xda\u007f\x1f\x91V~`\x94\x80\xf5j\x96ȹ\xa5$|%\xca4\x8c\xf0\xb7t\xf9\x05\xbf\xb7\xc5Գ \t0\x90\x89P\xc3Ȫ\x82\xac*r\x15j\xa9\xcc.\"\xee\x12\x1eyy\x922\xb2NuF\v\x1e\xb5\xa0bU\xde:dq\xad-ʮҴ\x1fBΓѡ\xae\x8d\x84\x0e\xf1\xfbW\xb0\x850\xb8\xa9\xb6z\xf9\xa6\xda\x1b\xf8ui\x9d\x16\a]7\xf4Ʃu\x8bWホ\xf1.G\xf5\xf1\x9d\xb5K7}$goȊ\x9e\x16\n\x0e\vx\x99f\xb2\xa8[\x92\x91\xb3P\xfc\x9bX\x02X\xb1Y[\x02֓h\"疒\xf0\x95(\xdb0B8\xe9r\xb9:\xe2\x99\xecK\t\x84\xd6\x03\x05E9\xf9kW\x90ILgF\x9d\xa7\xd9V\x16āno\x91\xdd\xeb\xf5\x8a\xdd\x06\x9f\xd7\"~\x93z\x9cVU\xde\xe1\x03\x99\xc8ִ=\xe7\xbe\xe8\xf2\"MC8Ա\x91\x10\xe4\x85\xe95\u007fʸ\xfd+\xfc\xa3\xa3GБ\xd1Q\xf5\xe5\xf2\xdf\xee\xday\xe6\xfc\xa9\xe5\x8e/\xf1\xb5A\xba\xda\xd9\xe0\a$y\xa7c\xf7\xf9\xe3\x0f>~\x03_>S\xed\xa8=t\xa8v\xd1e)\u007f7KK\xda\xc9\"\x19!o\x95\xd8è\xd8S\x9c\x91\xe7\f-\xa9\xaf-\x81]3\x9c\xc0\xb9\xa5*\\%\xca6\x8c\x10N\xb6\x0e\xfb\x86[O\xa6\x8dF\xc5/\x1c\x9a'\x9e)m;\xc9\xecN/:HS\xc3\x1d]\xea$\xd3dU\xe7\xc5\xd6\\Qӫlхy\"\xb3,\x8a\x90e#a\x97[j;\xd6\xc3\xc0\xbfBgi\xfb\xe3\x0f\x92\xc6\xfa\xf8\xd2\x1b\xe4C\xb8\xa3\xfb\xba\xe3\x94\xf8\xfa\xae\xe3\x8c\xf8Z\xfd\xb0X\x93k\xb5\xf2\xa2\xdcc\xac\x81\xa0f\xb2H&\xe8\xcc\x12/[\xf9\x19\xb6-\x1d\xcdy\xf9r?^SB\x1c\x8b\xee\x1bzs\xa4(<%\xaac\x18\x11\x9a.J\xa3e\"\xcbB\xd3\x1d\x0f\x14\n\x84|:\xb4ґhxj\xc4ꌤ*h\x8b|+\x15!\xcbFbD^\x98^\u007fN\xd6\xc0\xbf\"\xd8\xe9\xf14\xa1&\x8fG=\x90\xfb\xb4\xf6\xe1ݧ\u07bfq\x9d~\bKt\xdb\xc3\u05ff\x14\xa9\xdd)\xc6\xd5\xfbI\xcaq\x87t\xc9\x18\x93.Ij\nu.\x1cut\x01\xe32+\x11\xf0X\xb6ܧה\xa0S3%F\xde\x1c\xa9\nO\x89\xb2\r#\x82{.\xd0\xf0¾\xf4\xb9\x00\x96U\x84\x02\xf9\xd2O\x17\xd7ӑh(\xaf*U\x81b\b\xa6\bu\xac,\f0\xf0\xaf \xb0F|\xd7N=\xb3ڱ\xfc\x97\xeaV\xf4qGd\x01\xd1\xeaC$e\xd0!ݐ\xe9e\xac\xca\xebEm\n\xc3\xe50\x81\x9aLz\x17\xa9\xa6\x98~\\V&%\xb3J0\x9aȊ\xe3\xdcR\x12\x9e\x12e\x1bF\x04\xf7I\x12\xedO'\x89\x86ĸ\xa2\xb0\x9f\xe2\x0f\xa7\xd2[\xc1T\x8c\rVu^=\x89\x06\xacM\x8c\xd0xb\x95\x85\x81\u007f\x05\x81!\x84w\xf7\x8b\xe2\xbcvf\xd1q\xf2\x81\x1e\xf8ԧ\xa4\x15}\x97BZ\xce\xea\xddd\xd3)\xb9\x15m\xb2h\xe7\x9dkl\x02vF\xaa/\xe3+˕\xbaS\r9t\x9c\xb3D\xbe^\xb1J0\x92h\x1c疒\U00014a04\xc60\xa2S\xee\xe8\xa6\xcd,\xb9Bv\x1dҽ\xf8\x8d\x9bɫ]\xec\xea\x8d\xd3\x04ҟ\vV\xc4)Q\\sGP\x1bNL\xa2\x06\xfe\x15\x84K9\x9a1\xe3!\xc7y\xf2V\xbf\x8b\xbe\xd6c\xfc\x19\x19\x80\x9e\xa7\xa3P\xbc\xff\x97\xe2K\xf5r2\x16}\xb8\x9ef\x0f\x16/\x8c.\x01\xfb-\xebq?j\xcaP[,\x0e\xcc*\xbaD\xfcM\xc9=Or\xf2\x97裼\xec\x12\x985S\x12ǹ\xa5$\xbc%\xca0\x8c\x10\x0e\xb6\x0e\x8d\r\xb5\x1eL\x97\xe9\"\xa1\x87\xce\xddJ\xa3\xc6\xf5\xe8\x81\xd6v'\xa2\x97\xa5&\xeb\xf6\xb6y\xd9\xe4\x94+m[6W\xa2L\xf7\xb0\"\xaf\xcfkq\xf6\xe0~\xa7\xc5\x1b=\x17\xf9N\xc6\xf6\xa80\xa6\x8d\x84>\x86\xfe\x15:\x1cr,>\xf4\xfa\xeb;\x1d\x83\xf4C\xf5\xf1\xd7\xeb\x17\x93C\xef\xbfk\xdb\x191\x95N\x179֝9\xb5z\xe9\a4\xfb\x0e\xa4}\x8cj;\x1a\xc1\a\n\x83VU;x,k\x96\xc7\xeb\xf5:\xf3\xc5x\xa3\xa5\xa1c\xbb\xad8\xa0[\x82\x01\x13=7\xf3\xc3[\xa2,\xc3\b\xa1\xf7\x88\xbb\xad7m\xfe\xb2\x03\x92\x0f\x85\xdc\x0et\xd8m\xb9v\xe9&\xb0P\x97\x9be\xa7&\x81#\xf6\xac\x9c\xaa\x8d\b\xd5)\xf2։\uf5a1l\xf1\xb5.\xbaĆ\xafw\xab\xc3\t\xdaH\x9cDF\xfe\x15lN\xd5\x1f\xaa\xad~\xb0\x9e*\x14_\u07fdtQ\xbd4\xe6<_\xbf|i=m`\xabw\xef\\Z\xbb\xed/4՛\x15\xbe\x8f\x1b\xe1\x0e\xb1\a\xe1\xb5x\xd4\xf3\xb1\xa1\x19hڻm\x9d\x9dU\xd4\x10\xd0/\xc1\x80\x89\x9e\x9b\xf9\xe1-Q`\"<fie\x84&B\x9a.\xa2\x1c\xb48\xb5W\xdbqtD\xecAU\xa2\x15\x9a-\f\x98%L_@\xa2)\xc1\x8e\xfcqFh\x1e\"\x12\xf5\xcfb\xfeL\x85\xdeX\x12މgFP\xa7\x84i\vH\x14\x98\x04\x14\xad(0ɀD\x81\x9b\xe6\xb3\xc1\xea]\u007f\xb8a\x94\v\x98\x18 Q\xe0\xa6\xd9\xe5p8\x18\x0f;\x01\x93\x02H\x14\x00L\rH\x14\x00L\rH\x14\x00L\rH\x14\x00L\rH\x14\x00L\rH\x14\x00L\rH\x14\x00L\xcdt\x96h\r\xb2\xad\x1a6\xca\x04\x00\xc9e:K\xd4\xd7\xe9.\xb6Mh\xd1K\x00\xe0\x06w\x892\f#\x82\x03m\xfbڒӜu\xa5\xe1Z7@z\xc1[\xa2\fÈ\xa0\xc7\xdd?ڷ\xa7/\xe6~SD\xaf\xc1\xba\xce\x00\x90lxK\x94a\x18qa\x0fY\x85\xe1\x9d=\xc9\xe8r\x82D\x01\xb3\xc3Y\xa2,\xc3\bO\a\xdd\xd4\xd2\x17c\xbf\xa9\x02$\n\x98\x1d\xbe\x12e\x1aF\xc8K\xea\xb6\x1f\xd3\xdfo\xca\x18\x88\xac\xf4\x0e\x00\xa6\x84\xafD\x99\x86\x11\xdd-t\x05@\xf7\x91X{N\x11\x82\xad\xb2{,\x9e\xa5\x00\x00 Ip\x95(\xdb0\"\xe0\xf6\xf8\x05_\xbb+)k\xf2\x1cC\b\xddc\x94\t\x00\x92\aO\x89\xea\x18F`\xbf\xc7\xe5r\xf5x\x92a\x9f\x1e\xb0\x15\xee\xe8\xd4u\t\x01\x80\xe4\xc3S\xa2l\xc3\b\x82\xe0\x0f\xe2\x96Wc\xed;E\xf4\xa2\x93FY\x00 \xa9\xf0\x94(\xdb0\x02K\xbe\x92#\xaed\xb8\xcd\xc1\x8c.`vxJTBc\x181\xec\xf2\x8bb=\x90\x94\xa9U\x90(`vxK\x94a\x18\xf1\x8e덱\v-\x9ed<\xb9`\xe4\xe4\x03\x00I\x87\xb7DY\x86\x11\xfd\xadnO\u007f\x12\xee|\b\xbe\xfe\x1ak2\xba\xd7\x00\x10?\xbc%j&\x96 T\x90\x8cid\x00H\x80\xe9,Q_\xff\x18\x06\x00\x933\x9d%\n\x00)\x00H\x14\x00L\rH\x14\x00L\rH\x14\x00L\rH\x14\x00L\rH\x14\x00L\rH\x14\x00L\rH\x14\x00L\rH\x14\x00L\rH\x14\x00L\rH\x14\x00L\rH\x14\x00L\rw\x89\x86\r#0\xee\n\x99DD\xbc#\x00\x00P\xc3[\xa2a\xc3\b\x8c\xc7]\xd2*\x80\n\xef\bs\xd0\xd9o\x94\x03\x00\xb8\xc1[\xa2!\xc3\b\xb1\xe9l\x95%\xaa\xf0\x8e0\a\x155F9\x00\x80\x1b\x9c%\x1a6\x8c\xc0]\xae\xae}\x92D\x15\xde\x11\xe6\xa0l\x99Q\x0e\x00\xe0\x06_\x89F\f#\xb0\x10\b-w\xad\xf0\x8e\xe0\xca@&B\r#\xab\n\xb2\xaa\xc8%\xa2\xa52\xbbhm@l\xe6\x91D\x19\xc6u(\xa3\x05\x8fZP\xb1*o\x1d\xb2\xb8\xd6\x16eW\xa9;旫\x1d\x8e\xfd\x1fm{xѦ/\xd9G\x03\x80\x89\xc1W\xa2\x11\xc3\b\x82,Q\x85w\x04W\x84\xd6\x03\x05E9\xf9kW QmΌ:O\xb3\xad,\x88\x03\xdd\xde\"\xbb\xd7\xeb\x15\xdbt\x9f\xd7҄q\x8fӪ\xca;| \x13ٚ\xb6\xe7ܧ*\xec\xfa\x993\xb5\xab\x17\xd7\xee\xdevק:\x87\x03\x80\t\xc1U\xa2\n\xc3\b\x82,Q\x85w\x04o\xca\xd0<\xb1F\xb4\xedtc\xb2d\xe7A\x9a\x1a\xee\xe8ZE\x89\xe2&\xab:/\xb6抚^e\x8b.\xecqG\xfd5|\xe3Zt2\x00\xdc\x14<%\xaa4\x8c \x84ZQ\x85w\x04gʬrw\xf5\x81B\x81\x90朗l\x89\x86\xf2b\xab3\x92\xaa\xe0\xf1jh@\x81ɇ\xa7D\x95\x86\x11\x84\xd0XT\xe5\x1d\xc1\x95\xb2\x8aP \x8f@\x97\xd0\x0fl\x89\x86\xf2\xaaR\x15<\xbe.:\x05\x00n\x1e\x9e\x12U\x1aF\x10d\x89*\xbd#8\x13\x16\xe3\x8a\xc2~\x8a?\x9cJ\xef\xd3R16X\xd5yu%\xfaLt\n\x00\xdc<<%*\xa1\x19\x8b*\xbc#x\x13\x96]\a\xa2։\x1b7\x93W\xbb\x1d\xe3q\x9a\x90\xfd\xa4X\xbd\n\x90(\x90DxK4l\x18!\xf8|\xeeN\xdf8I\x8bxGpE\xe8\xa1s\xb7\x92u\xe1z\xf4@k\xbb\x13\xd1\xcbG\x93u{ۼlR\x9fJ͕ۖ(\xd3=\xac\xc8\xeb\xf3Z\x9c=\xb8\xdfi\xf1*\x9fY\xfc\U0008f0eb\xeb\a\aa4\nL6\xbc%\x1a6\x8c\xe8\x93F\xa5\xd4\xc9%\xe2\x1d\xc1\x93\x81\f:\xfc\\(}\xea\xb0\xdbr\xed\xd2\x1dZ\xa1.7\xcb\xdeK\xa2\x11{VN\xd5F\x84\xea\x14y\xeb\xc4w\xcbP\xb6\xf8Z\xa7(첃\xb2\t\x03\xc0\xe4\xc2[\xa2\x00\x00$\x04H\x14\x00L\rH\x14\x00L\rH\x14\x00L\rH\x14\x00L\rH\x14\x00L\rH\x14\x00L\rH\x14\x00L\rH\x14\x00L\rH\x14\x00L\rH\x14\x00L\rH\x14\x00LM*H\xb4\x06\xd9V%\xe1Ǥ\x00`\x06RA\xa2\xbeNw\xb1-`\x94\v\x00\xd2\x12\xee\x12e\x19F\xa8B&]h v\x06\x00HSxK\x94e\x18\xa1\n\xd9\xf4\xa2\x9e\xd8\x19\x00 M\xe1-Q\x86a\x84*\xd4\x01$\nLW8K\x94e\x18\xa1\f\xf5\x00\x89\x02\xd3\x15\xbe\x12e\x1aF(C=\x06PW\xec\f\x00\x90\xa6\xf0\x95(\xd30\"*d\"\xd8*\xbbǒ\xb0D \x00$\x1b\xae\x12e\x1bFD\x85l\x8e!\x84\xee1\xc8\x03\x00i\bO\x89\xea\x18FD\x85L\x02\xb6\xc2\x1d\x9d\xa3\xb1\xf3\x00@:\xc2S\xa2:\x86\x11Q!\x93^t2v\x06\x00HSxJT\xc70\"*d\x023\xba\xc0t\x85\xa7D%&4\x16\x05\x89\x02\xd3\x15\xde\x12e\x19F(B=z@\xa2\xc04\x85\xb7DY\x86\x11J\xef\b\x16\x82\xaf\xbf\xc6\xca\xdfP\x02\x00\xcc\x00o\x89N\x84%\b\x15\xb4\x1be\x02\x80\xf4$\x15$\xea\xeb\xe7\xee\x9a\x06\x00f!\x15$\n\x00\xd3\x18\x90(\x00\x98\x1a\x90(\x00\x98\x1a\x90(\x00\x98\x1a\x90(\x00\x98\x1a\x90(\x00\x98\x9a\xff\x0f5\x16\x1d\x16\xa8\xc9g\xc2\x00\x00\x00\x00IEND\xaeB`\x82",
+
+	"analysis/callers2.png": "\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x03\xfc\x00\x00\x01\xb0\b\x03\x00\x00\x00#z\x9e\xf7\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x02\xfdPLTE\x00\x01\x00\x04\x06\x02\a\t\x05\n\v\x15\a\x0e\x10\x0f\x11\x0e\x0e\x12\x1d\x15\x16\x15%\x19\x10'\x1a\f\x1e\x1d\x17\x16\x1e.!# #$\"$%#%'%'(&)(\"()'-+ *+),-+-.,12053'O.\x0f352786<:.9;8=?<B@4#Cxb<\x1aAB@j=\x11DFCLH9\x00f\x00\x00g\x00\x00h\x00\x00i\x01JLI\x00j\x02\x02k\x03\x04l\x050R\x95OPNVQ@\tn\a\fo\tRTQ\x83L\x1d\x0fq\v\vr\x17UVT\x0fs\x18WYV\x11t\x19_ZH,`\xae\x14v\x1b7]\xad>]\xa1Z\\Y\x16w\x1d\\^[\x19y\x1e:b\xac_a^Ya\x8bac`\x9aZ\x1d*{!@f\xb1Ke\x9e(|*dfclfP+\u007f,fheMj\xaf.\x81.Fm\xb1ikh0\x8301\x841/\x859Jq\xb5mol\x89j_oqn;\x86:>\x88<\xb3h\"{s[Vu\xb5sur?\x8a>@\x8b?uwtB\x8c@@\x8dG\\z\xba\xadq?y{xJ\x8fI^~\xb8L\x90K\x94wq\x85}d~\x80}O\x93Nb\x83\xbdN\x95U\x81\x83\x80W\x95V\xa7|e\x8e\x85gm\x87\xbcZ\x98Y[\x9aZ\x87\x89\x86]\x9b\\^\x9d]\xba\x82Z\\\x9ddr\x8d\u008a\x8c\x89\x96\x8cnd\x9ddf\x9ff{\x90\xc0\x8f\x91\x8eh\xa1h\xe3\x83+ЇK\u007f\x93\xc4j\xa3jz\x97Ɠ\x95\x92s\xa4l\xa0\x96wq\xa5s\x81\x9aė\x99\x96\xe4\x8b@u\xa9w\x9a\x9c\x99\x86\x9eȜ\x9e\x9b\xef\x904~\xaby\xa8\x9e\u007f\x9e\xa0\x9d\x80\xad|\xa0\xa2\x9f\xf9\x94.\xa1\xa3\xa0\xa2\xa4\xa1\x81\xb1\x85\xff\x952\x92\xa6ˤ\xa6\xa3\xb3\xa6\x82\xa5\xa7\xa4\x8b\xb2\x88\xa7\xa9\xa6\x8d\xb5\x8a\x8e\xb6\x8c\xaa\xac\xa8\xb9\xac\x88\x8d\xb8\x93\x9e\xaeΕ\xb8\x95\xad\xaf\xac\x97\xba\x96\xaf\xb1\xae\x98\xbb\x98\xa3\xb2қ\xbe\x9a\xb3\xb5\xb2µ\x90\xb5\xb7\xb4\xa3\xbf\x9d\xac\xb7Ң\xc0\xa4\xb7\xb9\xb6\xb9\xbb\xb8\xa5ħ\xb1\xbc\u05fb\xbd\xba\xa7Ʃ˾\x98\xbd\xbf\xbc\xa9ȫ\xb8\xc0կǫ\xbf\xc1\xbe\xc1ÿ\xb2ʮ\xc2\xc4\xc1\xbd\xc5\xda\xc4\xc6òͷ\xb9̸\xd6ǝ\xc7\xc9ƻκ\xbcϻ\xc4\xca\xd9\xc9\xccȾѽ\xc0ӿ\xca\xce\xde\xcd\xcf\xcc\xc4\xd0\xde\xc8\xd3\xc1\xcf\xd1\xce\xdfѥ\xc7\xd6\xc9\xd1\xd4\xd0\xd2\xd3\xdd\xca\xd8\xcb\xd3\xd5\xd2\xce\xd6\xdf\xcc\xda\xce\xe7\u05eb\xd6\xd8\xd4\xd4\xdb\xd0\xd8\xd8\xe3\xd8\xda\xd6\xd3\xdb\xe4\xda\xdc\xd9\xe6ݯ\xd7\xde\xd3\xd5\xdf\xda\xdd\xdd\xe5\xdc\xdf\xdb\xd7\xe1\xdc\xde\xe0\xdd\xf0\xe0\xb3\xdc\xe1\xe4\xdf\xe1\xde\xe1\xe3\xe0\xe3\xe5\xe1\xe1\xe6\xe9\xe4\xe6\xe3\xe8\xe5\xea\xe5\xe7\xe4\xe6\xe8\xe5\xe4\xe9\xeb\xe7\xe9\xe6\xef\xf2\xee\xfe\xff\xfc(t:\\\x00\x00 \x00IDATx^\xed\xbd\x0fp\x14G\x9e\xe7\xbb\xcc{\xbe}ϯ\x84zf$\xf5\xae4b\xef8M\xb4BB\xc7\x19\x9e%`\xd7z\b\x8b\xf3\xc2C\x1b\x02\xc1\x03\x9d\xe1\x16\xc6\xd8\xf3\b\xb3+0\xecB\x888\x9be,\xeel\xe4\x85~\x92\xb5\x1e\x99\x91X\xd9 \xa2ό\xa4\xc0\x9a6 ,\x06#\xd9H0\xd8\xc6\v\xde\x18\xf5\x10\xb6\xc5ȱ\xf66a\"\xda1\xd1\xe4M\xbcʪ\xee\xaa\xcc\xea\xcc\xca\xeeVw\xb6\xd4\xf5\xfb\x04!\x15\xa9\xac\xac\xac\xac\xfev\xfd\xe9\xea\xfa\xfc\xc1\xef\x93\a\x01\x000{\xf9\x03Q\xc2m\x10\xb5\r\x00\xc0\f\x06\xc2\x0f\x00\x0e\x05\xc2\x0f\x00\x0e\x05\xc2\x0fd+aQ\x05\xa7\x03\xe1\a\xb2\x92@c\xa1\U00084a12Á\xf0\xf7.\x9e\x14U\x91I\xc2ݙZ\xdc+\xaa2\xa3\x90\xd3\xdfpI\x89w  \xaa\xe5p\xe4\x86?\xd0w\xbc\xbd\xfbB\x10O\x06/\xbc\xd1\xfe\x86>I\x94\xf2\xf8\xd7#kk\xf7=\xb0\xab\x11C\xb3\x92\x8b_e\xbe<\xa5ٮZ\x8b\xfd\x9f\xd9\f\x14\xfaDU\f\xa6\xb6\x15歈\xfb\b4\x89\xee\xb4\xe4\x1c\x14U\x91\x8b`t\x92\xeeo\"\xa3~U\xe9\x13U\x01\xa4\x86\u007f\xd2\xeb\xbb\x11\xb8q\xf2\xb8\x9a\xf3`\xe7I<\xd9\x19\xa4J\xb9\xecn8\xfbR\xed}\x9b\n\xb1L\xd5\xe7-U\u007f-ͫ\x9f\xb2\xa9՚\xd3a\xf3W\x1e\xbe\xfc7DU\f\x96\x16z\x1b\xf3l\xdf\xd9\b\x92\xea\x8eon\xab\xa8Jz\x18\x1ce\x16\x8bFG\xd8\xdf$\xdb%\x19V\xfc\xa2*\x80\xd4\xf0\xdf\xf6\xe2\x03\xb1\xa0\xf7\x06B\xfe\xee\x90:\x19\xea\xf6S\xa5<\xeeW\x9fA\x0f\x12\xcb>BM+\xd4\xccM\xe5\xadh\xb2\xa9s\xdbe\xf7W>q\xef\xc9єҊ\xc2\xf1f?\xc9\xee\xecqe\xe6\x00wa=\xbb\\4:\xa2\xfe&\xdb.\xc1\xb02$\xaa\x02H\r?\xd2B0\x89\xc3>\xa0\x9f\xf8\xf5\x0eP\xa5<>\xab~\x97\xffG\x1eM\xf5K\xbbP\xe7\xf2z\xbb<5\x16ś\xcbd\xb9\xa9\xc4\u007f\xac\x9alw\x82E\x8d\xa2*i\xa1\xacNT\x83\x8d\xa8\xbfɶK\x00\xe1\x8f\x03\xb9\xe1W\t\x05\xba}\xea;\xf8T\xe7\xe0Th\xca\xdf9E\x952\xf9vm\xb5\xc61\x84\x8eTW\x9fC\x9f\xd5Voœ\xb5g\x8fm\xad\xdd\xf7[\xad\xceg/\xac\xadm\x88LGi\xaao\xadC+\xbc8\xfc\xc1\xba\"W\xf1ʫj\xe16en\xeb\x93\xc5\xee\x957\xb5*\xa1\x02\xed\x9d!T\x98\xdbT\\4\xb8\xdd]\x15\xe4\xd4%g\v\xe6)J\xceq\xa4U\xc8\xf5\ue61f\xb7\\{ۚZ\xef.ޱÝ\xdfMt!\xe4V4v\xe0\xba9\x9d\xea\x9e])\xb1̆n\u05f9s\vW\x04\x88\ue82bs\x15e\xcf\xcd\xf5\xf3\U000961f8\xb3u.Ο\xbf#\xfaV\xb1'/\x84(\x12n\x81\x81\u007fyq\xae{E1\xafԧ\xaf\x9aRF--\xbeщ\xe9o\x8a\xda5\x19\x84\xf0\x8b\x91\x1c\xfe)\xaf\xd7ۡ\xbd\xe0B\x03\xead_\xc8R\xca\xe4ӱs\xd5=cc_\"\xf4۱\xda\x1e\xf4`\xecH-B\xb7\xce\xd5V7\xf4\xf4\xac~\x01\xd7\x18\xab}\xb6\xe7J\x8fzn@\xd2T\x1fȟ\xfa^\x00\x87ߧ<9ؽ2g\x18\xa1\x1b\xc7\xe7*\xc5\a\x9b\x8b\xf3\xc6q\x95QeP\xab:X\xa0\xecX\xaa\xb8\x0f\x16\xb6p\xeaR\xb3]\xf6\xfb]\xdae9\\Z\xd8\xdcR\x80wT\xa1\x92\xa2\xd6fW^\xfb\xf2\x16\xb2\x0f\xef\xfb\xbb\x94f\xbf_}\x9d\x06\xfc\xb9\xea<C\x8d.z64\x98_\xd62Ь\xb4\x90\xdd\tu\x1f/\x9e_P\xbcc\xbd\x12\xe0\xcd֘\xb3\xdd\xd7ZX\x16yü`}\xa9'\xdcB,\xc3\xca\xfa7\x06\xbcn\x85\x8e\xa9Y\x1a\xbc\xe0\x9f_\xe5\xf7\xfboPK\x8botb\xfa\x9b\xa2v#\x84&\a\x17\xba\x93:\x86r\x16\x92Ï&\x03\xe3\xdd\xf8\xd2^h\xa0\xfbF\xe0F\xf7@\x88*\xe5a\x1e\xf6\xab\xe1G\xa8\xa7V\x9b\\\xad\xee\xe9_lP\xa7\xbeݴ\xef[\xf5\xe79\xfa\xaa@S=*۶\x10i{\xfen\xdcx\x99\xf6\xb9\xafk\x1e\u07bd\x17/\xc6\xd3>\xe5\xb6^\xb7h\xbd:\xedC\x8dOr뒳!\x94\x17\xb9&\xefr\xab/\xcb\xf5\x85\xeaT\x97\xa2\x1e,\xb4*\xe3Ȃyد\xbdt\x9b]\xf4l\xa1bu\xaf\xa6\xbeʵ# \xa3;\xea\xf2\x95\xa5A\xfd\x84\x889\x9bO\xc1\x17\x06\x87\x95.\xbdv@\x89\xbd\x14\x96X\v\xb1\xb4\x16\xe2m\xd3\xea\xa6\xdf\x1d\xa8R\xe2\xf0\xdc\\\x1a\x8actb\xfb\x9b\x9av#<\xa1\x1e8$p\xb2\xe5Xd\x87\x1f\xe1W\xfa\x80y\xc1\xef\x02Uʃ\x1d\xfe\x97\xa2\x93W\xaa?e̤\x86\xbfE9\xa8\x85\x1fM\xb5.\x9fW\x80\x8f$\xd5W\x8evhݪ\xe0\xb8\xf5\x1a\xe1\xefBCJ\x10\xcf«K\xceF\xbc\f\xf1ɫ\x96\xab&7\xc2I\x8f\xf9\f\x9b\x1d~c6\x9f\xf2\xbeY\xb7\x97\b\xbfqM\x8c9[\xfd\xbc\x10\xa68r\xee\x1c`d8\xb1\x16b\t\x14\xcd\xdb\xe6}?l9>\xa7Jɐ\x92\xd7\xf0\x84\xa3\x13\xdb\xdfԴ\x1b!\xd0\xe7-\x81=\xbf\x18\xa9\xe1\x0f\xe9{\x91\xab\xdep\xb8]\u007fͿ\xdf\x1e&J\xb93\xb2\xc3oL\x9e\xa9\xfe\x961\x93\x9a\xe4\xa9\x1d\x93Z\xf8\x87\v\x8b\x9bN\xfa\xab\xf4@k\xaf\xa0A\x05\u007f\x9c4\x14=\xfc,\xeaC\xc3.m\x16^]r6\xe2eh\xe4\xaa\x05\xbf-\xf4Ż\xe7'f#\xd2etG}їE\xa7\x98\xb3\x95EN\x8c#\xf7\xb0\r+ƛ\xa8Ab-0\bz\xebJ\x94B\xeax\xdaRJ\x86\xd4X\x1a\x8act\x18\xfdMI\xbb&~e8\xa6\f\xb0 3\xfc\xe1N\xfd\x94VM|4\xfc\xa3\xea\xa4Yʝ\xd3\x12\xfeW-\xe1\xbfR}\x8b1S\x93\xfe\x81\x11\x0e\u007f\xc9b\xbc\x1f\xa8\xd3\x03\xbd\x1d\xff\xf4*\xb8$芼\x9c\x88\xf0s꒳\xb1^\x86\x81\x9c\x15\x81\xab\xf3\x17Ǭ\x83%\xfc{,\x19\x1cP\x88ϴ\x8d\ue42f\u007f\xe6l\xeb\xe7\x8djD\xae\x976\xbbb\xf7s\x89\xb5\x10\xcbe|\xa8\x13\xecʣ?\x93\xa7J\xb5E\xb4\a\x8c\xc9(\xc2щ\xedoj\xda5\x81\xab\xfdq 3\xfc\xe8\xb8vוv\x80?\x189\xec\x1f\xa4Jy\x10\xe1\u007f\x15\xa1\a\xcfZ\xc2\u007f\xbfa7\xde\xf5\x1f;F\xcdD\x84\xbf\x18\xbf\x84\xc2\xfa^\xc4U\x88O\"\xe7U\xe9\u007f\x9c\xa7\xbfn\x88\xf0s\xeaR\xb31^\x86\xa3J\xa1\xa2T\xc5~\\i\x86?O\xedHx\xa1%\x83\xc1\xa2*<\x10۵\xb7\x16\xa3;䋞9[\x9f\xa2]\xdeޣ\xdf+\x17.Y\x81bH\xa8\x85\xdb\xcd1\xf7\xd54\xeb\xf7\xc8Um\xe3\x97V\xa9\xa31\xa9\xb7#\b)=:\x8c\xfe\xa6\xa4]\x02\b\u007f\x1cH\r\xffM\xef\x00\xbeʧ]\xf0\xeb\xea\x1e\x0f\x8cww\x85\xa8R6\x91\xab\xfd\xdaݽ\xbb\x1bzz\x9e\xad\xae={\xeb˱\xda#c\x0f>=R\x8b?\x05\x18\xab\xddz\xf6ʱ\xea\xb3\xe4\\S\xf5ڋ\"PU?\xa5\xbe\xb4\xeaZ\x0f\x96)\xee\x96!\xf5\x95\xa3\x94u\xb7\xcfw\xebg\xd77s\xb4\x03\xcd\x1b\xee\x96`W\xee\xd5 \x9e\x85Sל\f\r\xf9\xfd\xaeF\xbf?\x88\xaf\xe07\x0e\xa1\xd1\xc6\\\u007f\x00\x8d\xba\x06|\xfe\x80u\x17\xa4_\xed\x1fҊ\x17\x17\x1e<\xb8X\x99\xdbq\x83\x9c\r\r~\xaf\xc4\xebۮ\xb4\x93\xddQ\x97\x80/x\xeb]d\xcf֤\xd4w\xf76*\x9dZ\x95\x16\xc5\x1a\xddD[X\xa9\xe4[\x87\xbfY\xc9o\xf6\x9dl\x8c|\x00\xc1,mv\xb5\xf4.\xcd\x0fPK\x8bgtb\xfb\x9b\x9av\t.3N\x84\x00\vRÏ\x02\x83\xdd\xed'\x87\xb4\xb3\xdc\xd0\xf0Ɏ\x93\xc3!K)\x8boWk\x1f\xf3\xd7\xfe\x06\xff\xe7\xb3ݵ\xab\xf7\xbdZ]}\xe4\b.\xfa\xb4V\xfdyD-\xfe\xcd\v\r\xab\x9f\xa5o\x04jV\x14|]h\x9b\xa24\xa3p\xcb|Wa}\xc7<\x97\xbaKq\xedh,(Z\x1f\xddY\xec\xf9\x9e\xfa\"\t\xab\xbb\x8f\xe3\x05J~7>\x05\xe6\xd45'\x87s\xf4\xb3e/n[\xc9\x1d\xcfW\u007fnC\x17\\\xb8,\xb7\x8a:\xfd\x8c|\xce?W\xbby\xf1fU^\xc1\xf2&\xb5.9\x9bZ\\W\\\xb0\xf0$\xd9\x1dtU_\x82\xbe{\xe4\xcc\xd6W\xe5v/\xd6\xf6\x96ȟ\xb7\x03YH\xb0\x05Ԟ\x1fs\x8e\xdcY\xd5\\\x9c[TEg\x9f.\rmw\xe7U\r\xd3K\x8bct\x18\xfdMI\xbb$\x93s\xeb\xaeN2\xde\x14\x00\x02\xb9\xe1\x9f\t\x98\xe7\xd5\x1a\xdb]\xd6\xfbC\b\x88\xba\x96٬L\xe6o\x9b\f\x85\x82\xc3uӼ\xcal\xdb\x1d6]\xaeF\xee\x1bg\xdc\xf4*\xd3\xeb\xb7=\xd4褤\xbf:6\xa3\xde[bw1\x13\xc08>\xfc\xa8\xa5\x98\xff\x1d\xda\xf8\xc3\xdf\x1b\xf9<<\xec\x9e\xe6\a\xccv\xdda2U\x94\xe4\x97\xe4\b\xc2\x1d\xee'Eu\xa6\x039:\xa9\xe8o\x14\xdbQ\x9f\xbcʸ\x16\x00\x10@\xf8\xed\x88?\xfc\xa39\xfa\x91\xe7x\x0e\xf1\xb9\xfd\xac!\xe0ޑ\xaa\x9d1\x93t\x8dN\xba\xdau\bN\v\xbf~\xb5(>\x88\xba\xc2\xd9\u008dyOv\rv=\x99\x97\xd6=\xe8l%]\xa3\x93\xaev\x1d\x82\xd3¯]-\xba\x8d₨\x1b\xc7l\xbe\xe5E\xae\xa2\xe5\xd3<\xe8\xcfZ\xd25:\xe9j\xd7\x118-\xfc\x00\x00D\x80\xf0\x03\x80C\x81\xf0\x03\x80C\x81\xf0\x03\x80C\x81\xf0\x03\x80C\x81\xf0\x03\x80C\x81\xf0\x03\x80C\x81\xf0\x03\x80C\x81\xf0\xa3\x03\aX\x93\x00\x90\xed\xc8\r?[ץ2\xee\xcd\xd8MZ\xff\xecy\x991\xa9\xf1\x91G\xe7z\xccL1\x1c\xf0x\xfaEuf\x12\xa9\xe9\xef\xc5\xcawDU2@j\xd6M̝R\xcf\x1aQ\x1d\x9aSt\xcf2=|R\xc3\xcf\xd6u\xa9\x04\xdb/t\n\xe6M\x1b{\x17\xdceLj\x84?\x189\xe591\xf2\x81͗^.}\xa8\xff\xbe;R\xdaƯ\x958\xd1vSM\x92\xfd\xe5t\xe7|\x85\x94\x94%H\x82\xeb\x96<\xd7\xf6\x97\x8b\xaa\xd0\xdc\x1b\xd9H\xf6,\xd3\xc3'5\xfcl]\x97\x8ao \x90\xa9\xf0Ox~\u00984\xb8\xe6\xf9 \xa6\x8c\xe4\xff\xd9\x15\x9d*O\xe9\v\xcel7\xb5$\xd9_^wf\xe8\xe32\x12Z\xb7iЖ`\xf8\x11\xdaI\xf5,\xc3\xc3'5\xfc\x1c]\x17\x1a\xef\bf,\xfc\xfb\xcb\xef2&\rD\xe1ߐ\\\x98\x84lHS\xf8\x93\xeco\xba\xba\x93&\x12Z\xb7i0\xdd\xf0g\x18\xb9\xe1Wa躂\xed7Q\xa6\xc2\u007f\xa7\xf4\x10c\xd2$\x12\xfe\xe7=\xa5\xa7\u007f\xb2\xaa\xe2\xa9ϩ?\xbe\x13\xb9&\xb0\x01\xff\xa7\xfc\xb0Y\xe1\xe7\x9b+V\xfd\x84>Yh\xf3\xe0\xf3\xbd~\xf5\xe7Q\xf5\u007f\xa76T\xac;\xa5\xfe\xfe\xa8T\xfd\xff\xc4ޚ\x05O\xabc2\xf2TMi\xe535\x96vI&vU\x96.yF}\x8b\n\xeeZVZ\xb3\xf3#\xadИ\r1\x17L\x90H\u007f\xd9\xdd!\xfb{\xaf\xc2\x139\x85\xa5F\xe7뽕\x8f\x1d>\\i=\xa2et\x9d=\xa8D\v\xd4\xe8\x18cF\x8fd\x14\xaa\x94\xb5n̥\x85\x97\x94\xbe\xf2زK\x87\x16m\tZzv\xe2\xc0c\x8f\ue720&\x119Pw\xf7.[\xb4\x8b{\xd8\xcfiW\v\xff!\xb5\x8f\v\xbeNp\xf8҂\xe4\xf03u]>u\xf7\x9f\xa9\xf0\x1f(\xfd\x9c1i\x12\t\xff?\xf7\x97z*\xdbN<B\xef\x00\x83\x1f\x8c\xac\xda2222\x81\xffS\xeeY\xd3\xff\xce\x12\xad\xc2~ϡ\xf3'*7P\au_=\xb7y$\xa8α\xf9\xb9\xaf\xf01\xc6\xd1\xf3G\xcb\xf7\xaa\xa3\xd0\xdf_\xb3\xea\x91\xc7~\xb2\xd7s\a]\xf7\xec\xed\xbfx\xba\xd2\x13\xa6\xdb%x\xafb\xc3\xeb\x17\xdb<'ԳEρ\xf7\xfawz\xae\xa9\x85\xe6l\xec\x05\x13$\xd2_vw\xc8\xfe\xa2\xeb##\xfa.\x96\x1c\x9dКe\xa7\xda\xca+N?u\x82j\x8d\xd5u\xf6\xa0\x12-PK3ƌ\x1aI\x03\xaa\x94\xb5n쥽\xb7\xc8\xf3\x93\x1fy*_[\x12ӳ\x9a\xd7\xdaj*>!'Ɂ\x9aX\xb4\xea\xf4;Oy\xb8{~v\xbbZ\xf8\xef\xee\xf5\x9c\xd06\\\x02×\x1e$\x87\x9f\xa5뺁\xdf\r2\x14\xfe;\xa5\a\x18\x93\x04\xc6a\u007f\xf9\"\xf5\xadao\xa5\xf5\xef\xc4a\xf4\x92\xaf\xd5W\a\xaep\xde\xf3\x966'\xfd\xe6\xfd\x96~ex\xdd\xcf\x11\xba蹈\xf0\xcf\xf3Z\v\x9e\x1f\x05\xb5\x13\xa2S\x95\xda\xfemQ\x98n\xd7$T\xf3t\b\xe7\xef\x1e\xfe\x81\xdf6\xd7\xedD\xd4l\xec\x05S\xc4\xdf_^w\x8c\xfeb\x16D\x8eb\xcd\xd1\xe9\xf7|\x84\xafj\u007fB\xb5\xc5\xe9:{P\xa9\x16\x8c\xa5\x11cF\x8c$\x01Y\xca^7\xe6Җ\xedU뼃\xf6\x1f\xb0\xf4\xacF]潚\x8d\xd4$\xd1\xd8\xe6Uj\xdd\xf0:\xfea?\xa7]5\xfc'\xca\xcfG+\xc5;|iBv\xf8\x11\xb2꺂\xed7\xc2\xe1p\xa03\x9c\x89\xab\x1fϗ\xdeaL\x12\x98\xe1ߏX\xe7xD\x98\x0eD+\xecz<\xa4\xaeQ\xf8\xb1\xfdT͏<\xa1\xd0[\xf7\xc2\xe5\xea\xc6ݿN+Y\xa3U\xd8P\x1eY\xee\xe7\xcbj\x9e?\xfdQ\xc4X\xc5\n\xffy\xcfG\xc6\xf4ק\x9e~|\x91g\x1d=\x1b{\xc1\x14\xf1\xf7\x97\xd7\x1d\xa3\xbf\x18\xe3\xd5k\x8c\xceˋ\x10\xbet\xfa6\xa2`w\x9d=\xa8T\v\xc6҈1#F\x92\x80,e\xaf\x1bsi\xcb\xfa\xd5m\x1cD\x87\x9fCtϴ\x0f}Oy\ue453fc\xf7<\xa7q\xe1Q\x9b\xf0\xb3\xdb\xdd\xd9v\xd4c~\xbe\x17\xef\xf0\xa5\t\xa9\xe1g\xea\xban{\xa3\xc8\u007f\xde\xe2\xdd\xf2\x03\x8cI\x123\xfcx;نߨ\xb0.r\x8e\xbc\x93\xaa\x19*\xfd\xe4\x84z\x06\xebQӴY\xff\xcb\u038dZ\vƙ\xfd\xbdӻ\xd6x\x96\xbc\xaeM\xb3\xc2\u007f\xc2c\x9c\x96_[Rs\xf8\xed\x91-\xeb\xe8\xd9\xd8\v\xa6\x88\xbf\xbf\xbc\xee\x98\xfdEī\xd7h\xec\x84\xe7k\xbc\x83\xb6\xec\xba8]g\x0e*Ղ\xb14b̈\x91$ K\xd9\xeb\xc6\\ڲ\x8b\xe8Z\xa9\x1a\xba\xe7\x18=C#\x9e\x0f\xc9I\xb3\xb1\xeb\x9e\x11\xc4hL\xdc\xee\xce%\x8f\xac1\xc72\xde\xe1K\x132\xc3\xcf\xd1uMM\xaa\x8cwLf\xe01\xeb\x87<\x13\x8cI\x92\xb8\xc2\u007f\xfa\x0eUa\xef\xe3\x1fj|MW]ӿe\xf3\x9a\xb7\xf1\xc1\xe9\xfeǵ\x82\x9a\xfdF\v\x98\xebx\x0fs\xaf\u007f\xc1)\xba]\x93K\xe6\xees\xcdFmO\xbf\x8e\x9e\x8d\xb3`\x92\xf8\xfb\xcb\xeb\x0e\xf5\xb6\x14\xfb\xea\xbd\xe3y\xfa\xceG\xab6[\xb6%\xbb\xeb\xecA\xa5Z0\x96F\x8e\x999\x92$D){ݸ\xe1/\xd7CJ\xf5L\xbb\xf8{Z\xddw\x13\x93fc_{\xb4a\xb1\xf9\x9c\x9f\xd3\xee\xce\xcaO\xee,2\xce\xe7\xe3\x1d\xbe4!3\xfc\x1c]\x97FF\xce\xf9\xef\x96\xefgLR\x88¿e\x8b:\xaf~FiT\xb8\xa8\x9f=\x1f}\x8d\xae\xfa\xdc\xf3\xa5\x17=\a\xf0\x8b\xf9\xbcV\xa1?r\xce\x1f}y\xb7ig\xb5h\xcb\x01\xba]\x93в-x\xd0\x0e\xa9/\xc6\x1a<Sx\xdd:z6z\xc1w\xda\xe8\xe3b\x8d\xf8\xfb\xcb\xeb\x8e \xfc\x1fz\x96x<[\xac\x9f\x99\xb2\xbb\xce\x1eT\xaa\x05ci䘙#IB\x94\xb2\xd7M\x14~\xaagK\xd4\xfe\x06\x1f\xdfBM\x12\x8dm\xacQO\b&\x16D\x1ac\f5\xa7]\xfcQ\xdf\xf9\xd2k\x91J\xf1\x0e_\x9a\x90\x1a~\xb6\xaeK%\x1c\x18\xef\bp\x95\x91i㰹\xb7?\xcc\xda\xf1G\xee\xf0\xbb\x16\xc27\x8d\xed\xbf\x86>\xdc_:b\xd9.m\xe5'\xde\xfeQ\xc5\xe7t\x85\x97=\xcf\xf5\xbf\xbd\xdfC_\x90B\xafU,\n\xafZ\xa0%l\xaf\xe7\xe5\xf3/{\xf6\xaaK\xb8\xa6]H\xd7v\xa9m\x9e\x8a\xb6\xf3\xeal\xef\x91\xedR\\Z\xb0\xe6\xd4\xf9C\xf8t\xb3ͳ\xeb\xd4k\x1b<\x95\xaf_\xa3f\xa3\x16\xbc\xd3Sq\x0fY\x89\xbf\xbf\xcc\xee\x90\xfd\r}02R\xbe\u007fd$H5\xf6Q\xf9\xa5\xf3#wc\xf6\\\xac\xaes\x06\xd5l\x81\\\x9a9f\xd4H\x12\x18\xa5\xecuc/\xed\x9f\x1e=\x11\xea/\xfd$\xf4ܖ\xcf\xc9AE\xe5\x9e\r\xfd\xa7W-\x9a@Ԥ9P\x9fT<\xd6v\xf4QO\xe9[\xff\x84[\x89\x1djv\xbb\xf7F6\xee\xff \x14ڹ\xec\xd2W\x89\r_z\x90\x1a~\x8e\xaeK-ǧ\xfc\xc7mfL\v_U\xeceL\x12\x98\xf7\xf6\x1fP\u007f\x96~\x82?\x99\xb5\\\x19\b\x1dzt\xc1\x96k\xc8R\xe1\xe2\x96\xcaE\x9b\x8dk\xba\x11\xae/:\x8a^\xaf\xd0\xde\xf4\xc3'\xd6U\xac;\x156\x96\xa0\x9d\xcf\xfe|s[M\xe9\xb2-\xefQ\xed\xd2L\xecz쑍ok\r\xac*\xaf\xdcuzU\xe9\x16z6r\xc1\xa7+<1\r$\xd0_fw\xc8\xfe^\x8f\x8c\xcei\xaa\xb1\x0fJqY\xe9f\xebY+\xa3\xeb\x9cA5[ \x97f\x8e\x195\x92\x04F){ݘK\v\xab\xfb\xd9\xfeG<\x15\xfdx)Ġ\xa2\xf2\x9f\xec_\xb4l\xaf\xf66AL\x12\x035\xb1\xf3њ\xc3o\x95\xea\x8d\xc5\f5\xa7\xddSxu\xae\xeb7#$6|iAn\xf8g\x16\xafx\xfe\x991\x99=\xbc\xed\x89\xdd\U000e76ef*\x0e|\x15\x0e\u07fb\xbe\xeb\xd1d\x97=\xfd\x16R\x01q\x8f`<\xb7\v\xa6j\xa8宼\x93ß\xdd\xdf\xe5\r\xbf\xb5(\x03+\xf5\xb6~_\x00\nWZ\x0f|\xe2e\xfa-\xa4\x82\x84\u009f\xba\xa1\x96\xbb\xf2N\x0e\u007fvs\xb7\x92\u007f\x9fo\xfa\xf80\xf2)\xd5'\x1e\xc6\xd5Ƹ\x98~\v\xa9 \xa1\xf0\xa7n\xa8\xe5\xae<\x84\x1fH%\xe1\xfd\x15\a\xfa\xdf\xeb?P\x91\xf4\xaep\xfa-L\x1f\xfd\x12\x9cuR\x02rW\x1e\xc2\x0f\xa4\x96w\x9eZV\xba\xec\xe9\xe9\x1c\xb5N\xbf\x85\xe9\xa2]\x82\xbbc\x9d\x94\x82̕\x87\xf0\x03\x80C\x81\xf0\x03\x80C\x81\xf0\x03\x80C\x81\xf0\x03\x80C\x81\xf0\x03\x80C\x81\xf0\x03\x80C\x81\xf0\x03\x80C\x81\xf0\x03\x80C\x81\xf0g\xf9-\xfe\x00\xc0Cn\xf8\x99\xba\xaeP\x87\xf6\x10\xaf\x8e\x14\xdd\x1e\x9d(6\xba.\x93\x03\x12<K\xfb=\x1eOń\xa8V\x8a\xe8\u05feNZ\xb93\xde{\xd7\xd8k\xfcAe\x1c&3\xe9\xa4Fו\x96m\x8c\x12k7ͣ.5\xfcl]W\xd0\xfb~@eR4w\x9a\xb0\xd1uq\xedVi\xf1,}>2rJ\xa0\b\x11\x12\xb7\xe5+\xf8\x8e畑\x91\x9f\xaf\xab\xb4>\xf2K(\xe6\"+\x9c֟c9\xc3H\x8d\xae+-\xdb\x18%\xd6n\x9aG]j\xf8ٺ\xae`\x06\x9e\xdcib\xaf\xeb\xe2٭\xd2\xf4\xa8\x15\x91\x1fHH\xfc\x96/\xfd\xa1\\_WXc\"\x14s\x91\x15\xfaS\xb1\x8bM\x03\xe2/\xe2\xc5A\x9a\xb6qB\xed\xa6wԥ\x86\x9f\xad\xeb\xcal\xf8\xedu]Iڭ\x92e\xda\xe1\x8f_\xab\x15y\"\xdf:\xeb\f\xc2\x16\xc8\n\x97<\x97\xf8\x153\x88\x94\x8d%\x95\xb4\x8c\xba\xdc\xf0\xab\xc4\xea\xba2\x1a~;]\x17\xc7n%\xf6,\x91\x02\xad(\xcf{<?\x8fH\x9d\x89\xd9h\x19\x14\x11~\xc3\v\xc5\x16s1\x9dW\\\xcb\x17\v=\xfcw\x17\xbcF\xf6\x8cӂ\xb9Ɩ\nף\xf6r\xd6\x1aӥQ\xd9\x16\x01i\xe32W\x88vt\t\xc5gL\xd3X\xf9\xa1\x03\xcb\xf4A\xe5\xb4KJ\xb1X-p\xb6\xb1\tǗfL\x9a\x83J\x99\xbbį\x1d\x93dG=~$\x87\x9f\xa5\xeb\nz\a\xde\xf0\x1e\xf7g\xe6z\x9f\x9d\xae\x8bg\xb7\x12y\x96H\x81\x96\x81~\"\xaaI\x9d\x89\xd9(\x19\x14\x11~\xd3\v\xc5\x16s1\x9dW<\xcb\x17\x93\xbb\x9eӡ\xe0\a\xeb\xd6\x04ɞ\xf1Z0\xd6\xd8R\xe1n\xa5~\xac\xc4\\cZ$\x16\x95m\x11\x906.s\x85hG\x97P|\xc6\x14\x94\xe1gn\xf6\xafÃ\xcan\x97\x94b\xb1[`nc\x02\xf6f1'\x89A%\xcd]\xc2\xd7\x0e\xb3\x0f\t\x8dz\x02H\x0e?K\xd7\x15\xf4v^U'\xbb2\x91~\x91\xae\x8be\xb7\xc2\xd8z\x96(ѕ\t\xf1\xe4hB\x1cEx\xa1\xcc\xf0\x13^(\xb6\x98\x8b\xe7\xbc\x12\x1e\xb4\x1b\xdc\xd5\xf6%\xab\xb4\xf7;\xf2\x99ּ\x16\xa2k̬\xc0^c\xa2\x94\x12\x94\x11\x186.r\x85\xccR\xa1\xf8\x8c#(+_\xa3\xb6\x16Z\xb5\x91\xd7.\xb1\xb1\xf8\x8a\xb3\xd8mL\xc0\xde,\xe48\x98\x83J\x98\xbb\xd8\xed\xf2\x1d]I\x8cz\x02\xc8\x0e?BV]\x17\n\x8fk\x93\x1dC\x82\xf9ҁH\xd7Ų[al=K\x94\xe8ʄ\f\xbf)\x8e\"\xbcPf\xf8I\xc9\x14S\xcc\xc5s^%\x12\xfe\xa3\u05ee]<\xa0}j4\xed\xf0\xb3ט(\xa5\x04e\x04\xa6\xfb\x8bX!\xb3T(>\xe3\b\xca\xca_\xc1?\xb5Ae\xb6Kl,\xbe\xe2,v\x1b\x9307\v9\x0eD\xf8\ts\x17\xb3]\xbe\xa3+\x89QO\x00\xa9\xe1g꺢\u007f\xf4\x9fdϔN\x84\xba.\x96\xdd\nc\xefY\"EW&d\xf8-\x93\xba\x17\xca\f?!\x99b\x8b\xb9xΫD¯\xed\xebv\xadB\xf1\xb5`\xfb2䬱YJ\t\xca\b\f\x1b\x17\xb9Bf\xa9P|\xc61\x8d\x99\x83\xcan\x97\xd8X|\xc5Y\xec6&`o\x16r\x92\b\xbfi\xeeb\xb7\xcbwt%3\xea\xf1#3\xfcl]\x17\x1a\xf0i\x93\x83>\xee\x8ciC\xa8\xebb٭0\xb6\x9e%Jte\xa2\xd5=\x1a\x13~\xd3\ve\x86\x9f\x90L\xb1\xc5\\<\xe7\x15\xcb\xf2\xc5&\x12\xfe\xd3\xf8uG\xf4\x8c\xdb\x02\xfd2\xb4T`\xaf1QJ\t\xca\b\x8c\xd74\xb9Bf\xa9P|ƩP\xae}f\x8b\a\x95\xdd.\xb1\xb1\xf8\x8a3\xdb\xf0\xb37\v9\x0e\xe6\xa0\x12\xf2\x1ev\xbb|GW\x12\xa3\x9e\x002\xc3\xcf\xd1u\xf9\xb4]\xfeT\xc7\xfb\xb6\xf3\xa6\x03\xb1\xae\x8be\xb7\xc2\xd8z\x96(ѕI\xc5a\xf5\xfdocL\xf8M/\x94\x19~\xc2\v\xc5\x16s\xf1\x9cW\xa4\xe5\xeb\xcek\x13\x88O\xa4\xd6\xdeG\xc2TϘ\x9e0\x8c\xf12dU`\xaf1QJ\t\xca\b\x8c8\x92+d\x96\n\xc5g\x9c\n\xe5\x8f\xe1s\xfe5[x\xed\x12\x1b\x8b\xd3\x02\x12\x84\x9f\xbdY\xc8q0\aU\x18~\xbe\xa3+\x89QO\x00\xa9\xe1g\xeb\xba\x02\u07be\x9b\x81\xcb\xed\xbe\xa4\xaf[$\x8dHׅ\xb7M\xac\xddJ\xe8Y\xa2DW&\x9b+_\u007fm#\x16<Q\xe2(S\x06\xa5\xdd\xe1wB\xb7S\x99^(\xb6\x98\x8b\xe7\xbc\"-_;=\xcf .!\xed\x0e\xbf\xb7\x9f\xf3\xbcN\xf6\xcc҂Q\xd9XcN\x05\xf6\x1a\x93\xa5\x84lˀv\x95EW\x88rt\t\xc5g\xec\n垧\xaf]ڌ\a\x95\xdd.)\xc5b\xb6\xc0\xde\xc6\x04\xbc\xcdb\xae\xb11\xa8\xa4\xb9K\xf8\xdaa\xf6\x01%2\xea\t 5\xfc\x1c]\xd7\xe4\xc0\xf1\x0e߸\xfc\xec\vu]l\xbb\x95гD\x89\xaeL&\xb6,x\xe4\xa9WԺ\x948ʔA폴\xab\xed\x9e\f/\x14[\xcc\xc5s^\x91\x96\xafӕ6w\x81\xea\xf7\xf6\x97\xaeӪ\x18=\xb3\xb4\x10\xc5\\cN\x05\xf6\x1a\x93\xa5\x84lˀ\xb4q\x99+D9\xba\x84\xe23v\x855m\xbb\x1e\xd1\a\x95\xdd.%\xc5b\xb5\xc0\xde\xc6\x04\xec\xcdB\xae\xb11\xa8\xa4\xb9K\xf8\xdaa\xf6\x01%2\xea\t 7\xfc3\x8bT꺒\xf6,\x95\xb7!@2Io\xac\xf4\x90\xb1\xee89\xfc\xa9\xfc.oҞ%\b\xbf|\x92\xdeX\xe9!c\xddqr\xf8SIҞ%\b\xbf|\x92\xdeX\xe9!c݁\xf0\xa7\x86$=KreP\x80N\x92\x1b+]d\xac;\x10\xfeT\x91\x94gI\xb6\f\n\xd0Ijc\xa5\x8f\fu\a\xc2\x0f\x00\x0e\x05\xc2\x0f\x00\x0e\x05\xc2\x0f\x00\x0e\x05\xc2\x0f\x00\x0e\x05\xc2\x0f\x00\x0e\x05\xc2\x0f\x00\x0e\x05\xc2\x0f\x00\x0e\x05\xc2\x0f\x00\x0e\x05\u009f\xd2[\xfc\x01`\xf6 7\xfcL]\x97ʍ\xbe\x8e\xee\xcbv3\xa6\x11{]\xd7\xd7\a\x96,xF\xff\xdeE\"\x9e%\x06\x91\xaf\x94z\x92W-Y|^\xfaӶ\xe3\xab\x1b'|\xd1U\xecʟb\xd6MR\x95\x95\xe8l\xc4f\x89B\xacqr+\x9f6flϤ\x86\x9f\xad\xeb\xc2O\xf1\x1e\xba=\xea\xbd-\x9a==\xd8\xea\xbaЏ\x96\x9c\xda_\xa1\u007f\xd32\x11\xcf\x12\x83\xf0\aڳ:>\xd0\x1ea\x10\xb7V\x8b\xc4\xea\xf3\xd2\x1e\f\x1dg\xdd\xf8\xe0\x8b\xaebW\xfe\xde\xc8FF]n\v\xec5\xe6\xe8\xd0b+X 6K\x14b\x8d\x93[y\x94\xd8f\x89\xbfn*z\x96\x16\xa4\x86\x9f\xad\xebB\x03\xed\x01\xfc\xc6pC0wz\xb0\xd7u\xdd\xf3\x9c@\xc6\xe3Q\xa7\xfd\xb8\x11\xd3\xc9\x11\xbfV\x8b\x86V\xfa\xc4<R\x96\")\xfd\x0f\xf7K\x86\x8c\x95\xdfɬ\xcbi\x81\xbd\xc6<\x1d\x1a\xa3\x02\t\xb5YL\x885Nj\xe5\x13\xda,\x89ԝ~\xcf҂\xd4\xf0\xb3u]\x01\xef\xfb\xc6\xdf\xe4c\xaf\xeb\x9a\xf0L\xebP߂\xb9\xdd\xe3\u007f\xca.M\xe6\xc2\xcf \xa1\xf0\xb3\xd7x\x83(\xfc\xec\xd98\x9be\xda\x11Kd\xb3$Rw\xfa=K\vrï\x12\xab\xeb\x1aj\x0fM\u007f\xa7\x9a,v\xba\xaeP\xa5~\x96\x8e\x8f\ax\xfe&\xa6-\x8aGd\xbbs\xb5Z\x13\xbb*K\x97<\xa3\xbd\x03E\xedV\x84K\x8bhA=N\u07bbl\xd1.\xeba?\xe9\x90\"\xea\n\xacYT\x05\xc3JFڭ8+\xaf\x86\xff\x90\xfa\x87\x05\xf4\x83o\rU\x96P\x03\xc6ѡ\x99k\xc1\x9e\x8d\xdc,\x9c5\xe6\xac<\x01c|\xd9K#ט\xd93\xa2\x05\xb6\u007f\f\x13۳\xf3\xeaܯD\xd4c\x99Br\xf8Y\xba\xae^ߍ\x93\xde\xe3\x17\xe2MPj\xb1\xd3u\xa1\x8fF\xfa=m#\xfa\x93\x1b\xd9\xfe&\xb6\xeb\x89Gd\xbb\xf3\xa4X\xefUlx\xfdb\x9b\a;\x9b\f\xbb\x15\xa1}\"Z@\x13\x8bV\x9d~\xe7)\x8f%\xfc\x84C\x8a\xa8+\xb2fQ\x15\f+\x19e\xcdb\xaf\xbc\x1a\xfe\xbb{=',\xcf#0TYB\r\x18G\x87f\xae\x05g\xa0\x88\xcd\xc2^c\xc4^y\x02\xd6\xf8\xb2\x97F\xae1\xb3gD\vl\xff\x18&\xb6g\xa1\x0fj\x0e\xdcE_\xb5-\x1a\xc9\xcc\v\x1f#9\xfc,]W\xb7\xa6\xeb:ޝ\x89A\x10麨\xe3\xcbX\xcf\x12\xdf\xf5\xc4\xc4\xfe\xb0?T\xf34~\xe0t\xff=\xdanE=9:\xda\xc2\xe6U!\xfc\xe4hK\xf8)7\x95QWh͢$S\x84\x95̰[a\x18\xf2*5\xfc'\xcac\xbe\x84n\xaa\xb2␁\x10\x87\xfdƂiÖ\xfda?{\x8d\x11s\xe5\tx\xe3\xcb\\\x9a\xb9Ɯ\x9eQ-0\xfdc\xccc\x926|\x88\xb1\x97\xf9\xc4xI\xc8\x0e?B1\xba._;~}\x05;\x86E3\xa6\x01\x91\xae\x8b\x1d~ó\xc4w=1\xb1\x0f\xffy\xf3)N\xa4݊\x15\xfe{\xfa#]\x8fZ\xcf\xf9I7\x95\xb14\xa15\x8b\x92L\x11V2ӥ\x85\x98\xf2\xaa\x9dmG\x19\xe7ބ*K\x98+2A\xe6\x82)Ö\xe0\x9c\x9f\xb9ƈ\xb9\xf2\x04\xbc\xf1e\x87\xdf\\cvϨ\x16\x98\xfe1f\xf8?\xf7|\x82B\x8f\xa4ȶ\x9d\x14R\xc3\xcf\xd6u\r\ua7ae\xc1^\xee|iC\xa8\xebb\x87\xdf\xd8\xd8|\xd7\x13\x13\xfb\xf0\x9f\xf0\x18/Q\xd2n\xc5\n\xffu\xcf\b\"J\xa3Pn*siBk\x16S2\x85L\xbb\x15\x86\xa1\xb0ع\xe4\x915\xb1롟\x1fh\xfe1a\xae\x98\t\xa2\r[\xf6\xe1\xe7\xac1s\xe5\tx\xe3\xcb\x0e\xbf\xa8g\xcc1\x13\xf7\f=}\x18]\\\x94\x89\xe3\xdd(2\xc3\xcf\xd1u\x8dvh\xef\t\x033Q\xd7%\b?\xdf\xf5\xc4\xc4\x12~\x8b}\xe9\x12\xb1\xe7'\xecV\xdaҢ\xfb\xf8H\v_{\xb4\x8bv\xd6\v~\x94\x9b\xca<\xed\x15Y\xb3b$S\xac(\xb0\xc2_\xf9ɝE\xb4U\x1aW0TYT\xd7YkL\x96\x9a\xed\xc6\x1a\xb6bf36\v{\x8d\x11s\xe5\tx\xe3\xcb\\\x9a\xb0g1- k]v\xf8ߩ\f\xed\x8f\xf3\x981=\xc8\f?G\xd75\xa5}\xd4\x17l\x97\u007f\x8b\x9fX\xd7%\b?\xedz\xb2\xf7c!r\xbb\xb3\xecK\xa1e[\xf0\x98\x1c:DۭH\x97\x96\xd1\xc2\xc6\x1a\xf5\xa8zb\x81%\xfc\x94\x9bʨ+\xb4f\x91ڧ\x84¯N\x9e/\xb5>\u007f\xd4Teš\x01c\xe9Ш\xb5`\xcffl\x16\xf6\x1a#\xe6\xca\x13\xf0Ɨ\xb94a\xcf\xc8\x16\x8c1\x13\xf6\f\u007fl\xf1Σѣ~\xe1k'\x1dH\r?[ׅ.\xb7_\x0e\x8cw\x9e\x94\u007f\x00$\xd2u闕\xaf\xe1\x03\x13\x8e\xbf\x89r=\xd9\xfa\xb1\xa2w\xf8]\xd3V\x93e_B\x97\x16\xac9u\xfe\x90v:OحL\x97\x16\xe1\xf3\xfa\xa4ⱶ\xa3\x8fF\f[\x06\x84C\x8a\xa8+\xb2f\x11\x15\x88u#\xedV̕\xbf7\xb2q\xff\a\xa1\xd0\xcee\x97\xbe\xa2Z3UYB\r\x98YJ\x0e*\xb1\x16\xecو\xcd\xc2^c\xce\xca\x130Ǘ\xb9\xb48zf\xb4\xc0\xf6\x8fqz\xa6\xf2\xf2\xe3ƅH\xfb\xd7N\x9a\x90\x1a~\x8e\xae\v\xdd\xee\xed8yY~\xf6E\xba\xae\xd0\"턾t\x02\xf1\xfdM\xa4\xeb\xc9֏E\xdf\xdbϲ/\xe1\xcf\xf9\x1f{d\xa3fi'\xecV\xa6K\x8b\xf4yM\xec|\xb4\xe6\xf0[\xa5\\\x87\x14QWd\xcd\"*\x10\xebFڭ\x98+\u007fJ[\x19\xac\xfd:J\xb5f\xaa\xb2\x84\x1a0\xc4ԡ\x11k\xc1\x9c\x8d\xdc,\xec5\xe6\xac<\x01s|\x99K\x8b\xa3gF\vl\xff\x18\xa7gxFs\xf3ٿv҄\xdc\xf0\xcf,R\xa9\xeb\x02\x80\x84\t\x95'\xef\xd9K\x05N\x0e?|\x97\x17\xc8(\xfd\x95q\xde\x1d\x96&\x9c\x1c~\x00\xc8\x1cm\xef\xa1\x1f\xb5\x89*\xa5\x17\b?\x00d\x80\x90g\xc3\xf3\xcb$[y\xad@\xf8\x01 \x13\xb4Ul\x99\x10\xd5I3\x10~\x00p(\x10~\x00p(\x10~\x00p(\x10~\x00p(\x10~\x00p(\x10~\x00p(\x10~\x00p(\x10~\x00p(\x10\xfeYA\xef\xe2I\xea\xffS\x8bm\x9e{\x04\xdfY\x00\xe2Bn\xf8Y\xba\xaeP\xa7W\xe7\xb8`f\xe9lSr\xbaEu\xa6K\xa3\xa2(y7E\xb5Z\x94fkI\xceAfMd\xeb\x1fK\xce\x16\x15\x97K+V\xa0\x15\xd7l@\x06\x91\x1a~\xa6\xae+\xe4\x1d\r\xa8\\\xf6^\x15\xcd.\x9b\x80?ך9\x9d\xc1Qfq2\x04\xfc\xfeVeHP\xa95\xa7#\xa6\xcc7\xb7\x95Q\x13c\xe3\x1fK\xcc\x16%ti\x91\xc4\n\xb4\xe2\x9a\r\xc8 R\xc3\xcf\xd6u\x8dk\x0f\xef\xed\xbc \x989\x13\xb8\xd8\xe1_X\xcf,N\x92aQ\xf8o\xbb\x9a\x18\xa5{\\\x01F\xa9\xc8?F>PJ\x84ХE\xc0\x14h\x89g\x032\x89\xd4\xf0\xb3u]\x1a\xbe7\xe4?\xc9G\f'\xfceu\xcc\xe2$\x11\x86\xbf\xb1\x88\xa52\v\x1652JE\xfe\xb1D\xc2/ti\x110\x05Z\xe2ـL\"7\xfc*\xb1\xba.\xcc\r/}AK\x02\xa1\xc2ܦ\xe2\xa2\xc1\xed\xee*|\x16RW\xe4*^\x89O<n\xccU\x94\x95\xa8XQ\xdc껑k{c\x91{\xa5zJ\xeeSO͛P\xb3\xfa\xb3\x1bObʴV:\x17\xe7\xcfߡeӿ\xbc8\u05fd\xa28f9\x1d\x85^\xfc+P\x10\x99\xaf\xc0\xba\xc36\xc3\x1fml\x9b\x92\xeb\xdd1?o\xb9^3T\x10\xdd\xf1\x8f\xed\xdbT\xbbvߦ\a\xfa\xff\xf6\xe4\xb1\xde\xfbI\xf1\xdf\x00\x00 \x00IDAT/\xed\xfcc\x183\xfcQ\xd3\x18\xa5\xe0\xfazo\xe5c\x87\x0fWV\xf4s\\Z\x14Q\xe7\x15)\xd0\"1\xcc]\xc0\x8cDr\xf8Y\xba.Lw\xf4\b@\"\x83\x05ʎ\xa5\x8a\xfb`a\v\x0e\xf7\x93\x83\xdd+s\x86\x11\n\x0f5\xe7\f\xa1\x0e\xa5\x13?Rإ\x94uu\x95卣\xe0\x85\xe2m\x93h\xb2\xb9\xc0\x1f\f^\xf0ϯ\xf2\xfb\xfd\x9aT\xb81g\xbb\xaf\xb5\xb0,\x8c#\xbc\xfe\x8d\x01\xaf[\x89\t\xe4\x13\xcar\xfc+\xd4Ѫ\xd3a\xada\x84\xdfh\xec\xc6\xf1\xb9JasK\x81~\x801\xaa\xe8O<G\x1f\xff\xd9K箜][\xfd;\xfd\xbf\x17\x98G\f\xb6\xfe1D\x84\xdf0\x8d\x91B\xaaКe\xa7\xda\xca+N?u\x82\xe3\xd2\"1\xdd_\xa4\u05cc\xc00w\x013\x12\xc9\xe1g\xe9\xbaP\xf4b\x80l\x8a֫\xa1\xf7\xa1\xc6'\xd5=\u007f7~G*{B+o\\8U\xac_Kw\x95\xe0\xc7P\xcf_\xacN6\xe3=\xfdz\xfdH\xdb8\xec\xf7)\xf8Jܰ҅Pk!^\x95Vw̃\x99n\x1f\xbc\xad\xfd\x9e\xbc\xad\x13s\x88\x13\r?\xd1\x18r\xb9\xd5\x01Y_\x18)\xd7\x1b@g\x1ap\xecϬ\x8e\xec\xf9\x03\xca\x1b֦\xc4\xfe1#\xfc\xa4i\xcc\x14R\xf5cw\xc0)\x8f\x1eW\x96K\x8b\x80r\u007f\xb1\x0f\xfbMs\x170\x03\x91\x1d~\x84bt]*\x03i\xffH\x8dEQ\x17\x1aR\x82\xa8\t_\xbe\x9bj]>\xaf r(\x1f*+\\\xa9\xd7Я\xb4y\x95)\x1c\xb5q\xf5\x00\\?@1\xc2_?/\x84)V\xdf\x13\x02E\xf3\xb6y\xdfgH\xe3#\xdcV\xa2ܶ\xfc%\x1a~\xa21\xe4\xc2?\x9a]Zyot\x8e/\x1b6\x1d;\xfb\xe9\x83o#\xf3\x05\xb4\xb7\t\v\"\xff\x98\x11~\xd24f\n\xa9^^\x84p\x90\xb5'\b\xb3]Z&\x94\xfb\x8b\x1d~\xd3\xdc\x05\xcc@\xa4\x86\x9f\xad\xebR\xe9\x90/\xecP)\xeaC\xc3j\xbep\xf8\x87\v\x8b\x9bN\xfa\xab\xf4\xf0\xa37\x94\xc8G\x0f\xfa\x05?\xbf\x82?\xda[\xb1\x03\xf5\xb9\xf5l\x1b\xe1/\x8b\xe4\x19\x1f1\x04\xbdu%\n>\x85\xe0\xe0\xf7\xe9\xf8\xad\u007f\x88\x86\x9flL[p$\xfcC\xc6\xe1\xfd\xfd\xb3/l\xad^\xdb\xf3 :_\xec\a$B\xff\x98\x11~\xd24fj)Nx\xbe\xc6;\xf3\x98=?\xa1\xf20\xa0\xdc_6\x17\xfc4s\x170\x03\x91\x19~\x8e\xae\v_\t\xb0\xee\r\xa5@\x84\xbfd1>\xec\xaf\xd3\xc3\x1f(\xdaS\xac_\x88t\xed\xc0?\xdb\x15\xfcG\x9f;\xd4\x18\xb9\xbe\xae\x85\xbf\x1d\x1f\x98\xcf\x1b\xd5Pk_\xc6\a\t\xc1\xae<ާ\xef|\xa2\xe1'\x1a\xa3\xc2\x1f\x8c~\xe6p\xebU5\xf6\xf7\xcf՞\xd1\xff\xdb\xec\x8a\xfd\x10@\xe8\x1f3\xc2O\x9a\xc6\xccl\xdf\xf1<}\xe7\xa3U\x9b\xf57i\x96K\x8b\x80r\u007f\xb1\xc3o\x9a\xbb\x80\x19\x88\xcc\xf0st]\xf8\x94?#/\x0f\"\xfc\xc58\xce\xe12-\xfc\xa1\xc5{ГK\xb5\u05ff\xab\x18\x9f\xb4\x96Ti\xc5n\x9f;r\xe5\xadJ-\x98T\xd4S\x95>E;_\xd9sP\x8d\xa2\xa2\xad\\\xd56\xebR\xa2\xe7\xfc\\\xa2\xe1'\x1a\xa3¯\x9e\x0f\xe8a쩾\x82\u007f\xed>\xa2\xfd/\\\xb2\x02Y\x11\xfbnj\xf0\x93\xa613\xdb\x1fz\x96x<[\"\x17\xeeX.-\x02\xca\xfd\xc5\x0e\xbfi\xee\x02f R\xc3\xcf\xd1u\xa1\x1b\xdeL|\xc8\u007f\xc3\xdd\x12\xecʽ\x1a\xac\xaf\n\xa8ѭk=X\xa6\xb8[\x86B\x17\xb6\x15\x06\xd0\xed\x82\xed\x17\xf0G}\xca\xf2\xa1\xc1\xc5n=\xbdM\xf3\"G\xfdj*[z\x97\xe6\xe3k\x94MJ}wo\xa3҉ß\xdf\xec;\xd9\x18\xbd2o\xb2R\x89\r\xa9\x89v\x87_\x8b\xdfO5\x16\xf0\xe76\x0e\xa1\xd1\xc6\\\xad\x18\xdd\xcc\xd1O&z\xaak{\xde}\xf7\xa5\xea1\xed\u007f-J\xec}\x86\"\xff\x18i\x8b2Lc\xa4\x90\xea\xa3\xf2K\xe7G\xeeF.Z\xb2\\Z$\xa6\xf3\x8a\x10h\x91\x10\xe6.`\x06\"5\xfc\\]\x17\xe3\xb2u\xda\t\x17*\xca\xf1\x02%\xbf\x1b\x9fe\x87[\xe6\xbb\n\xeb;湪\xfaԳ\xee\x1dh\xbb\xfaS\x8dqIs]A\xd1\xfa\xc8'\x117\x95'#\xb3\x86\xb6\xbb\U000ea1b5ɾ*\xb7{1\xde\xe7wV5\x17\xe7\x16U\xc5d?\xfa9?\x87\xc6ȉ\xbev\xcf`\xb4\xb1mjA\xeex\xbe\xfaS?\x8e\xd8\xf3=\xed\xec\xfe\xec\xee\x9eM\xb5\r\xbb\xf5\xec\xfb\xf3v\xc44&\xf2\x8fѶ\xa8\xa8i\x8c\x14R}P\x8a\xff\\\xbaY;\xe9g\xb9\xb4H\f\xe7\x15)\xd0\"!\xcc]\xc0\fDn\xf8g5AWl\xb2%\xb1\xdde\xfd8\xa4\xcb\xd5\x18{\xb44m\xff\xd8W\x15\a\xbe\n\x87\xef]\xdf\xf5(\\\xa0w\x00\x10\xfe\xb8\xe9v\xc7\xc6M\x16-Ŗ\xaf\xf4\x16\xb1\xbe\xd47\xed\xef\xf2\xbe\x1d\xb1Ɔ+\xcf\vj\x02Y\x00\x84?>\x9a\a\xd1R\xf6\x8d\xfe\xd9ć\x91\x0f\xf9>\xc1\xf7\xfa\x00\xd9\x0e\x84?.\x82J\xd96\xe6\xd7k\xb2\x8b\xf0\xfe\x8a\x03\xfd\xef\xf5\x1f\xa8H\xea\xb8\x01\x98e@\xf8\xe3\xa39\xbfꆨN6\xf0\xceS\xcbJ\x97=\r\a\xfd\x8e\x00\xc2\x0f\x00\x0e\x05\xc2\x0f\x00\x0e\x05\xc2\x0f\x00\x0e\x05\xc2\x0f\x00\x0e\x05\xc2\x0f\x00\x0e\x05\xc2\x0f\x00\x0e\x05\xc2\x0f\x00\x0e\x05\xc2\x0f\x00\x0e\x05\u009f}L\xfb\x16\u007f\xc0\x19\xc8\r?K\xd7EMf\b\x19b.\x84.\x94\xe5/\x1f\x12U\x9a>6\xba.\x11\xd30l\xcd\b]םRϚ8K/V2\x9e>\x12%\x03]\xcf\x04R\xc3\xcf\xd4u\x91\x93\x99B\x86\x98\v\r\xb8ֿQ\xefJ\xff3\xcamt]\"\xa6a\xd8J@\xd7\x15Հ\xa5\x81k\xfb-\x8f\x1b▞\xaf\xb0\x89\xf74\xc6a6!5\xfcl]\x171\x999\xd2/\xe6\n\x15\xe2's<Y\x94\xee\xef\x05\vt]\x02\x92\x95\xec$\xa2\xeb25`\xa9\xc7\xfa\xac1~i\xcc3\xd6)\x92\x1d\x87Y\x85\xd4\xf0\xb3u]VsWFH\xbf\x98\xcb\xeb\xc2_\xc9\x0f\xe4\xda=\xd7'\x15\bt]\x02\x92}\xd1'\xa2\xeb\xda0#\xc2oO\xb2\xe30\xab\x90\x1b~\xc4\xd2uY\xcc]Ҡ\xa4X\xe9\x17s=\xa1=\x06\x14U\xa5\xee턉\x9d\xae\x8b\x10s=\xef\xf1\xfc\\?\x19\x0e/)}\xe5\xb1e\x97\x0e-ڂW\x8e4lE}^\x1f\x95z<G'\xf6\xd6,xڲ\xb7\x8c[\xd7u^\xfd\xe3+\xa8M\xfdIk\xc0\x8cE 4\xf2TMi\xe535\x96\x16\xd8N14\xb1\xab\xb2t\xc93\xda;[\xb4\x0f\xea\xb1\xfa\xdee\x8bvE\x0e\xf0\xcdv\xc9R\x83{\xf8\x99d\xdaa?ݮ\x89#Lc\x92\xc3\xcf\xd4u\xd1\xe6.iPR\xac\xf4\x8b\xb9J\xf4'\x006\x96XgK-v\xba.B̥\x9f\xd5j'\xc3\xef-\xf2\xfc\xe4G\x9e\xcaז\x9c@\x94a\xcb\xf0y\x85\xfa\xfbkV=\xf2\xd8O\xf6zh\vH\xfc\xba\xae\xd0\a5\a\ue8af\xda\x16\x8d\x84(\r\x98\xb1\btݳ\xb7\xff\xe2\xe9J\x8f\xe5\xed\x85\xe9\x14C\xefUlx\xfdb\x9b\xe7\x04Շ\x89E\xabN\xbf\U000d49dcn\x97,%\xb8>2\xa2\xef۩v\t\x1ca\x1a\x93\x1c~\x96\xae\x8b6wɄ\x90b\xa5_\xcc\xe5\xd6u\x9bMn\xebl)E\xa0\xeb2\xc5\\\xc4㸗\xedUw\xcd\xef\xa0\xfd\xb8\xbai\xd8\"}^h\x83\xe7G\xc1\xc8Y\x9bAB\xba\xae6\xbc\xa7߫?M\xdc8\xec'\x16q\xaa\x12\x0f\xe7\xa9E\xf4\xa0\xb2\x9db\xa1\x9a\xa7q\xbb\xfd\xf7\xa8>l^\xa5\x16\x86וӳ\x11\xa5\x16\x16D\x0e\xec\x89!!p\x84iLv\xf8Q\xac\xae\x8b6wɄ\x90b\xa5_\xccU\xb2^\xfbU\x9f\xde=\xbf@\xd7e\x8a\xb9\xc8\xf0\xf7\xabA\t\xa2\xc3\xcf!ҰE\xfa\xbcІ\xf2ض\x12\xd2u}\xeeQ\xf7\xff\x8f\\Ҋ\x8d\xf0\x13\x8b\xf8|Y\xcd\xf3\xa7?\xb2\x0e*\xdb)v\xde|Șه{\x9e\xd3x\xeah95\x1bYj\xc1\b\xbf9$\x04\x8e0\x8dI\r?S\xd7e1wɄPc\xa4_\xcc\xf5\x84~\xe9 \"\x03M\x13\"]\x17a\xdf \xc2\u007f\x11]+E\xe8\xe5碥\x9aa\x8b\xf4y\xa1\r\x1bb\xdbJL\xd7\xf5\xf4atq\x91>\xa8F\xf8\xc9E\xdc;\xbdk\x8dg\xc9\xebt\x03<\xa7\x98\xf1\x1ea\xf6\xe1\xbag\x04E+\x98\xb3\x91\xa5\x16\x8c\xf0\xb3\x84$\xce0\x8d\xc9\f?[\xd7E\x9b\xbb\xa4B\x86?\xedb.\xafv pSI\xeb\xd5~\x91\xae\xcb\x1a\xfe\xa3\xd1\xf0\x97G\xc3o\x18\xb6H\x9f\x17\xf3\x02}b\xba\xaew*C\xfb#\x0e!C\x03F,\xe2:\xbe\x1b\xe9^\xff\x82ST\x03l\xa7\xd8%b\xcfo\xf4\xe1k\x8f6\xabviϜ\x8d,\xb5 \b\xbf\x13Lc2\xc3\xcf\xd1uQ\xe6.\xa9\x90\xe1O\xbb\x98+T\x88\xdfH\xea\n\xd3yiC\xa8\xeb\"^\xe9\x15\x87շ\xe3\x8d1\xe17\f[\xa4ϋ\x19\xfe\xc4t]\xa1\xcaw\x1eՏ\xfaM\r\x18\xb1\x886\xed\xe4\x1dm\xa1\x8fV\xd8N\xb1в-x\x10\x0f\x1d\xa2\xfa\xb0\xb1F=D\x9fXPN\xcfF\x94Z\x10\x84\xdf\t\xa61\xa9\xe1g\xeb\xba(s\x97D()V\xfa\xc5\\\xa8\xcfU\u007f\xb2\xde\xd5gWe\xba\bt]\x94wks\xe5\xeb\xafm\xf4\x94\xbe\xf5O\xff\xf4\xe8\x89P\u007f\xe9'\xa1\xe7\xb6|\x8eHÖ\xe1\xf3\n_\xd3.\xd0ǜ\xf5'\xa6\xebz\xf9\xf1\xe8ռ\xa8\x06\x8cX\x84\x1a\xfe\x8a\xb6\xf3\xea\xe4{t\vL\xa7\x18\xba\xb4`ͩ\xf3\x87\xb4\xd3y\xb3\x0f\x9fT<\xd6v\xf4Q\xbcBd\xbbd\xa9I胑\x91\xf2\xfd##A\xae\x8a\xcc\x11\xa61\xa9\xe1\xe7\xe8\xbaHs\x97D()V\xfa\xc5\\\b]X\x9aW\x96\xd6\xdb\x18E\xba.ʻ5\xb1e\xc1#O\xbd\xa2N.\xf1x\xfa\x1f\xf1T\xf4k\xa7֤a+\xea\xf3\xfa\x888\xf9'IL\xd75aȾ\xa2\x1a0d.\x02\xfd|s[M\xe9\xb2-\x96쳝b\xf8s\xfe\xc7\x1e\xd9\xf86\xfe\xbb\xd1\a\xb5p\xe7\xa35\x87\xdf*\xd5*\x18\xedR\xa5\x06\xd7#\x17\x05NsUd\x8e0\x8d\xc9\r\xff,!\x83b\xaei1m]W:\t\x95\xc7$\x1b\xc8,\x10~\x06\x99\x14sM\x87\x19\xfd]\xde\xfeJ\xe9\x17t\x01{ \xfcV\x9c!\xe6\x92L\xdb{\xe8GN\xb8[~v\x01\xe1\xb7\xe0\x101\x97\\B\x9e\r\xcf/\xcb\xea\xfbef%\x10~+N\x11sI\xa5\xadb˄\xa8\x0e \x1b\b?\x008\x14\b?\x008\x14\b?\x008\x14\b?\x008\x14\b?\x008\x14\b?\x008\x14\b?\x008\x14\b?\x008\x14\b\xff̾#\x1e\x00҆\xdc\xf0\xb3u]\u1afd\xed'3vW\x1d\xdfn\xf5vi䛟\xa5o\xcb\xf57\xf1\x97FH\xb1b\xfdXl\xf8\x8d\xd9\x1a\xab\xf8\x15\xe2.ݯ\x0e]ńM\x05\vlٖ\x90\xf4\xce\x16ז'\xb6\x85x5g\x0eR\xc3\xcf\xd6u\x85}\x1d\xa3\xb7/\xb7_\x16͝&\xf8v\xab\xd7=##\xa7<'FF<\xaf'\xefo\x12\xba\xa9\x18\x15\xf8K#\xa4X\xb1~,6\xfc\xc6l\x8dU\xfc\nf)\xd9uF\xdd\xcf\xf1\xf0}`S\xc1\n[\xb6%$-\xb3E\xd7-\xae-Ol\v\xd1j\n_\x0f\x12\x91\x1a~\xb6\xae\xeb\xfdv\xac\xeb\xb8ٞ\x99o\xd3\xd8حN\x94\xe2\xe7?\xab\xafފ\x13\xd1':&\x8e\xd0MŬ\xc0Y\x1a!\xc5b\xfa\xb1\xd8p\xbb.<n`W0J\xa9\xae3\xeb^3\xc3/^Z2f\x1d\x8dt\xccf\xae\x9bx\xcbS\xdbB\xb0\x9a\xc2׃D\xa4\x86\x9f\xad\xeb\xf2\xe9O\xb6\xea\xcc̮\xdf\xc6n\x15\x9a\x88\xbcz'B\xf1\xbc\x04\xd8\b\xddT\xcc\n\x9c\xa5\x11O\xcac>4\x8fM\xb2]\x17\"\\7*\xfcq\x90\x8e\x14\xf3\xb1\x9dmC\x02\xe1O`[\xc41f\xf2\x90\x1b~\x95X]\xd7I\xfd\xd1V\xbd>\xc1\x9ci\xc1\xcen\x851^\xbd\xe5\x87M\xab\x93)\x83\"\x89\x8a\xa3L\x13\x16\"\xdcT\xcf{JO\x1cxL3@\xb1+P\x18\xb6(\xa2.!Ţ\xfdX\"\xad\x16S=e\x1a\xab8\xaa,\xb6\xd2\xca,%\xbbN4\x16ܵ\xac\xb4fg\xf4\xf1\xba\xd1\xe1#*\xac\x89̷\x19\xffG\xa0\xd5\"\a\x95\xad\xd5b8\xba(\xff\x98\xd9\x1d\xaa\x05\xceҢP\x9bE\xb0\xe5\xc9ma\xae&\xb5-\x8c\xf1\xe5m\xee\f!9\xfc,]ׅN\xed\f\xa0\xe3\xa4\xfd\xac\xe9\xc1\xcen\x851\xc3\xefY\xd3\xff\xce\x12\xedm۔A\x91\x18\xe2(\u0084E\xb8\xa9\xb0\x17\xaa浶\x9a\x8aO8\x15(\f[\x14Q\x97\x94b\x91~,\xa1V\x8b\xad\x9e2\x8cU<U\x16[ie\x94R]7\x1b;\xef9\xf0^\xffN\x8f\xfe\x88>s\xf8\xcc\n\xf8\xc1\x99##\x1b=\xf8\x11\xfdB\xad\x961\xa8\x1c\xad\x16\xd3\xd1E\xfa\xc7\xcc\xee\x90-p\x96f@\xad\x9bh˓\xdb\xc2XMr[\x98\xe3\xcb\xdb\xdc\x19Br\xf8Y\xba\xae`\x87o2\x14\xe8\xf5v\x8b\xe6M\x03\x02\xbb\x15\x19\xfe%_\xab\x1b\x1f[\x9d(\x8f\x95\x01)\xaf\"\x9f\x06M\x1c>֨\xeb}\xaff#\xb7\x02\x01a\x8b\"\xeb\xb2\x0e\xfb\x85Z-\xbez*\xf2\xf4j\xb6*\x8b\xa8`QZEK\xe9\xaeGJC\xfd\xf8\xad|]\xe4i\x9f\xe4a\u007f\xa4B\x9b\xba\x1b\x0e\xef\xd7D{B\xad\x165\xa8,\xad\x16\xdb\xd1E\xf8\xc7\xc8\xee\x98-\xf0%^\x06\xc4v\x13ly\xcba\xbf9:\xd1mA\x8d\xaf\xa3\x0f\xfbQ\x8c\xae\vM\xf9ԃ\x80!_\xafh\xc64 \xb0[\x91\xe1\xc7o\rZ\x06)\x8f\x95\x01)\xaf\xe2\x84_\xfb\x1cQ3@\x89\xc3oڢD\xe1\x17j\xb5\xf8\xea\xa9\xc8딭\xca\"*X\x94V\xb6\xe1G_\x9fz\xfa\xf1E\x1e}4X\xe1W\t\xed\xd2R$\xd6jQ\x83\xca\xd0j\xb1\x1d]\x94\u007f\x8c\xe8\x8eт\x8d\xc4ˀ\xd8n\x82-\xcf\r\u007ft[P\xe3\xeb\xd8\xf03u]\xda\x1f\xa6¨S\xbe\xabOh\xb7\"\xc3od\x90\xf2X\x19\x90\xf2*N\xf8\xb5W\x85f\x80\x12\x87\x9f]\x97\x15~\xa1V\x8b\xaf\x9e\x8a\xbeN\x99\xaa,\xb2\x02-\xb6\xb0\r\xff\xb5%5\x87\xdf\x1e\xd9b\x17\xfe\xd03\xa5\xdac\xb7\xc5Z-ޠFa;\xbaH\xff\x18\xd9\x1d\xa3\x05\x1b\x89\x97\x81e\xbb\xd9lyn\xf8\x8dmA\x8e\xafS\xc3\xcf\xd6u\xa9/\x06<u\xd3K\xd9\xec\xe5 \xb2[1\xc3Oy\xac\fHy\x95V\xf7(\x91m\xec\xa6B\xe5\xda\xf5D\xcd\x00Ů@@آȺ\xac\xf0\v\xb5Z|\xf5T\xe4u\xcaVe\x11\x15l\xc3\x1f\xedz\xa4t\xcdF\xbc9wل?\xb4\xb9\xfc\xbc>%\xd4j\xc5\f\xaa%\xaflG\x17\xa9 \"\xbbc\xb4`#\xf12 \xb6\x9b`\xcbs\xc3\x1f\xdd\x16\xd4\xf827w\x86\x90\x19~\x8e\xae\xeb\x86wR=5:>(\x989\r\b\xedV\xcc\xf0S\x1e+\x03R^e\x9a\xb0\b7\x95z\xee\x88/p<\xbe\x85[\x81\x80\xb0E\x91uY\xe1\x17j\xb5\xf8\xea\xa9\xe8Y8S\x95ET\xe0\x85\x9f\xeaz\xa4\xb4\x06\xf7 \xbc\x8e\x1f\xfe{\x1b*\xf0~\xf7<m\x04ck\xb5\xc8Ae\x85\x9f\xe3\xe8\"\xc2Ov\xc7l\x81^ڝ6\xc3\xfdgBl7\xc1\x96\x17\x86\x9f\x1a_\xe6\xe6\xce\x10R\xc3\xcf\xd6u\xdd\xf4\x0e\a\xde\xef\xf4e\xe0\x1e\x1f\x81\xddJ\xe5\xc3S\x9e\x13בEteʠHLq\x94i\xc2B\xf8U\x13uS\xe1\x8b\xee\xa7W-\x9a\xe0V  lQf]B\x8aE\xfa\xb1\x84Z-\xa6z\xca4VqTYl\xa5\x151\x1b\xd1u\xaa\xb1]\xa7^\xdb\xe0\xa9|\xfd\x9a~\x87\xdf\t\xadCf\x85{\xeb<\xaf\xe1\xcb\xfd\ap\x9aDZ-sP9Z-\xa6\xa3\x8b\xf4\x8f\x99\xdd![\xa0\x97\xb6\xd3øS2\xban\xe2-Ol\vs5\xc9mA\x8d/ssg\b\xa9\xe1\xe7\xe8\xbaF\xbb;|\xa3q\xdc\xff\x95jDv+\xb5\x93\xf8sۊ\xa0\xd5\x16eʠ\bHqTԄ\x85\x9b0\xdcT\xe5?ٿ(b\x80bW  lQF]B\x8aE\xfb\xb1DZ-\xa6z\xca4VqTYl\xa5\x151\x1b\xd1u\xa24|bUy\xe5\xaeӫJ\xb7h\xf7\xf6cv\x91\x15>\x8a~aB\xbb\xad@\xa0\xd52\a\x95\xa7\xd5b8\xba¤\u007f\xcc\xec\x0e\xed*#\x97v\xba\xc2c\x1d\u007fs݄[\x9e\xdc\x16\xc4j\xea\x13ڶ\xa0Ɨ\xb9\xb93\x84\xdc\xf0\xcf,$ۭ\xca\xdb\x100#y;\xf6\x83\x10G\xe0\xe4\xf0K\xfe./\x84\u007ff\x12~k\x91\x84\xad?\x13qr\xf8%\x03៙ܭ\x8c\xbdU\xdb\x19@\xf8%\xa1_8\x02\x80\x99\x03\x84_\x12څ\xa3\x99\xf1\xf1.\x00h@\xf8\x01\xc0\xa1@\xf8\x01\xc0\xa1@\xf8\x01\xc0\xa1@\xf8\x01\xc0\xa1@\xf8\x01\xc0\xa1@\xf8\x01\xc0\xa1@\xf8\x01\xc0\xa1@\xf8\x01\xc0\xa1@\xf8e\xdf\xe2\x0f\x003\x04\xb9\xe1't]\xa4\xa3+\xd0\xdbї\x81\xe7\xf8\xe8\xf0u]\x16R&b\x8a\xcb\x00\x95\x02L!\x15\xd1\xf5$\x84_@\x96\"5\xfc\x84\xae\x8btt\x05\xda\xfd\xb7\xfd\xed\x99J?_ׅ\x84B\xaa\xe4\x88\xcb\x00\xc5$Aד!\xa4\"\xba\x9e\x84\xf0\v\xc8R\xa4\x86\x9f\xd0u\x11\x8e\xae\xf0q\xfc\xe8\xce\v\xc73\xb3\x0f\xb2\xd1u\xa1x\x84TI\x91\xec\x17\xfc\x12u=\x19O\xbd2\xba\x9e\x9c\xf0\v\xc8J\xa4\x86\x9f\xd0u\x11\x8e\xae\x1b\xed\xf8\x15\x18lό\xa7\xd7Fׅ\xd2\xf6\xac\xd5dßhwb\x9fO\x9b\x9c\xf0\v\xc8J\xe4\x86_%\xa2\xeb\"\x1c]\x03\xfa\xfb\x80/\x03O\xf0\xb4\xd7u1\x85T\x94\f\x8am\ue88dU&\x13\xbb*K\x97<\x83\xdf`L\x03\x94Y\x97\x14<Q-Dg\xa3]O\"G\x97)\xa42\x1dR\x89\t\xbf\x98\x12/ \x8b\x90\x1c~C\xd7E8\xbaN\xea\x0f쿐\ti\x87\xad\xae\x8b-\xa4\"ePl\u007f\x13m\xac2x\xafb\xc3\xeb\x17\xdb4U\x8di\x802뒂'\xb2\x05c6\xaa;\"G\x17)\xa42UY\x89\b\xbf8\x12/ {\x90\x1c~C\xd7E8\xba:\x87\xb5\xbf\fw\nfM\a\"]\x17KKAȠ\xd8\xfe&\xdaXe\x94\xd6<\x8d\x9f\xa0ݏ\xaf\xb0\x99\x06(\xaa\xae!x\"J\xc9\xd9\xcc\xee\b\x1d]\x16!\x95\xf1<\xe9\xf8\x85_|\x89\x17\x90%\xc8\x0e?\x8a<\xb7\x9fptE\xce\x00\x063!\xea\x14麘\xe17eP\x1c\u007f\x13e\xac\x8ar\xdec\x9e\b\x98\x06(\xaa\xae)\xdb2K\xc9\xd9\xcc\xee\x88\x1c]V!\x95m\xf8ٍ\xf1%^@\x96 5\xfc\xa6\xaeK\xfb_\xc4\xd15\xa0\xbb\xb9{3p\xce/\xd4u1\xc3oʠ\xd8\xfe&\xdaX\x15\xe5\x84\xc7̑遠\xea\x1a\x82'\xa2\x94\x9c\xcd\xec\x8e\xc8\xd1e\x15Rن\x9f\xd3\x18W\xe2\x05d\t2\xc3O\xe8\xba\x10\xe1\xe8\xba\xe1\xc5G\xac\xda\a\x80\xb2\x11\xea\xbaXB*\xc2\a\xc3\xf67\xd1ƪ(\x97\xc8=\xbf\x11~\xaa\xae\x91m\xa2\xf4R̞\x1fwG\xe4\xe8\xb2\n\xa9l\xc3\xcfn\x8c/\xf1\x02\xb2\x04\x99\xe1'u]\x84\xa3+\xac\xfd\x1c\xcc\xc0\xe7\xfcb]\x17KHE\x84\x9f\xedo\xa2\x8dUQB˶\xe0D\x1f\xc2\x1f)\x98\xe1\xa7\xea\x1a\xc1#J\xc9\xd9\xcc\xee\b\x1d]\x16\xfd\x95m\xf8ٍ\xd1\x12\xaf;\xafM  ː\x1a~B\xd7E:\xba\x02탷\a3q\x87\x9fX\xd7\xc5\x10R\x912(\xb6\xbf\x890V\x91\\Z\xb0\xe6\xd4\xf9C\xea\xc98i\x802\xeb҂'\xb3\x05c6\xb2;BG\x17!\xa4\"\\Z\x89\b\xbfh\x89\xd7N\xcf3\b\xc82\xa4\x86\x9f\xd4u\x91\x8e\xae@_{o\x06\xb2/\xd6u1\x84T\x94\f\x8am\xee\"\x8cU\x14\x13\xbb\x1e{d\xe3۴\x01ʬK\n\x9e\xa8\x16\xa2\xb3\x91\xdd\x11;\xbaL!\x95\xe9\x90JH\xf8EK\xbcNW\x9e\xb6.\x01\x98\xed\xc8\r\xff\xccB\xb2\xae\v\x00f\x16N\x0e?|\x97\x17p4N\x0e?\x008\x1a\b?\x008\x14\b?\x008\x14\b?\x008\x14\b?\x008\x14\b?\x008\x14\b?\x008\x14\b?\x008\x14\b?\x008\x14\b\xfft\ta\x8c_\x000k\x80\xf0O\x93\v9\x8a\xa2\xe4\x05\x83y\xea\xaf\x1c\xbf\xa86\x00\xcc\x1c \xfcӤ[\xf1\r\x0f\x8f#4><\xecS\xbaE\xb5\x01`\xe6 7\xfc\x1c]\x17B\x83\x19x\x8cO\"lSr8\xc1\xeeV\x8c/#\a\xf4\xf0\xf3\xeb\x02\xc0LBj\xf89\xba.\xfc\x87a\xfb93M\xc0\x9f\xdb\xcc\xfeKl\xf8\xb9u\aG\x99\xc5\x00\x90\x19\xa4\x86\x9f\xad\xebR\xe3\xd2=\xd3Ï\x90+\xee\xf0s\xeb.\xacg\x16\x03@f\x90\x1a~\xb6\xae\v\rz\a\u06dd\x10\xfe\xb2:f1\x00d\x06\xb9\xe1G,]\x17\n\x05\xa3\xe2\x0e\xa9t+\x8aҌ\x9a՟\xdd(XW\xe4*^yU-\xbd:WQ\xf6\xdc\\?/o9\xfd\xc1\x9dk{c\x91{\xe5MF+\x8c\xf0G\xeb\xfa\xd4ƛ\xf4E\xe0IL\x99V\xa3sq\xfe\xfc\x1d\xb4f\x03\x00$#9\xfc,]\x17&\x13\xe1\x0f\xfa\v\xf6L\xa2\xc9=n\u007fPM铃\xdd+s\x86\U0007314f\x17\xcf/(ޱ\xde\f\xb5\x86K)\xeb\xea*\xcb\x1b\xb7\xb6\xc2\f\u007f\xb4n\xf0B\xf16u\x11\xcd\x05\xfe`\xf0\x82\u007f~\x95\xdf\xef\u05eel6\xe6l\xf7\xb5\x16\x96\xc9\u007f^1\x00\x98H\x0e?Kׅ\xc9D\xf8\xd5\f\xe2\x93\xf0\xfaF\xf5G\xb0\x1b\xbf#\x95=\xa1\x15\x97)Kc\xf4W\xc8U\x82\xef䙿\xd8\xda\x063\xfcf\xddf\xbc\xa7_ߨ\x15\x1b\x87\xfd>\xa5C\xfd9\xact!\x00\xc8\x1c\xb2Ïbu]\x98̄\u007f0/\x88\x82y\x9aId\xaau\xf9\xbc\x82\xc81y\x99\x8b\xf1(aW\x13\xfe\xe9U\xa6,\xe5\xcc\xf0\x9bu\x03\xca8\n\x15\fh\xc5F\xf8\xeb\xe7i\xf7\x03\x167\"\x00\xc8\x1cR\xc3\xcf\xd6ua2\x13\xfe\x90\xfb$\xeau\xe3\xce\f\x17\x167\x9d\xf4WE\xc2_ƨ\xab_\xc4\xf3+֏\xeb\xf8\x17\xfc\xf4\xba+v\xa0>\xb7~\xf9\xc0\b\u007fY\xe4\xfc\xff\t\x04\x00\x99Cf\xf89\xba.Lf\u008f\xb6?\x81\x9e؎'J\x16\xe3\xa3\xfc\xbaH\xf8YW\xe5];\xf0\xcfv\xc5z\x95\x8e\x19~\xa2\xae\xcf\x1dj\x8c\xec\xe1\xb5v\xb1\x9cd\xfd\xbcQ\r\xebQ\x04\x00\xc8Df\xf89\xba.L\x86\xc2?\xe4\n\xb8\x86\xf0D1\xcee\xb8\xcc.\xfc\xc5\xf8<\xbe\xa4\xcaZ\xce\f?Q7\xe4\xf6\xb9#kY\xa5\x16L\xe2:}z\xc5=\a\xad\x8d\x01\x80D\xa4\x86\x9f\xa3\xeb\n\x05\x02\x1d\x83\x81I\xd1\xdci \\\xb4\xbcH;\x05iV\xeaZ\x0f\x96)\ue5a1АvU\xfe\xb6\xb5\xaaKY>4\xb8\xd8\x1dSξ\xdaO\xd4m\x9a\x179\xeaGͮ\x96ޥ\xf9\xb8z\x93R\xdf\xddۨtZ\x1b\x03\x00\x89H\r?G\xd7u٫\x91\x89\x8f\xbd[\\-\xda\xefp\xcb|Wa}\xc7<W\xd5\xd5\x1c\xedt|\x85\xb5fIs]A\xd1\xfa\xd8+\x81\xdd\xca\xcd\xe8WzoF\xc3Oս\xa9<\x19\xa9\x1a\xda\xeeΫ\xd2\x0fq\xfa\xaa\xdc\xee\xc5}1\x8d\x01\x80D\xe4\x86?\v\xd1nމ|\xa5W\xf11*\x04]\x83\b\x00f \x10\xfei\x12\xba:\x1c\xfdJ\xef\xf0U\xd6\xd3<\xbaݬR\x00\xc88\x10\xfe\xb4\xd2<\x88\x96r\xbe\x14\x00\x00\x19\x06\u009fN\x82Jٶ\xa2L\\\xcb\x00\x001\x10\xfe\xb4Ҝ_5\xc3\x1fS\x028\x17\b?\x008\x14\b?\x008\x14\b?\x008\x14\b?\x008\x14\b?\x008\x14\b?\x008\x14\b?\x008\x14\b?\x008\x14\b?\x008\x14\xb9\xe1g뺂\xfe\xee\xf6^\xe6\x97b\x00\x00H\x1bR\xc3\xcf\xd6u\x05;z\xc7o_\xee\xe8\x85\xf4\x03\x80L\xa4\x86\x9f\xad\xeb\x1a\xec\xc6\xcf\xf4\x98\x8az\xfb\x00\x00\x90\x82\xd4\xf0\xb3u]'\xf5\xe7\xdf\f\xb2\x9e\x84\x01\x00@\xba\x90\x1b~\xc4\xd2u\x05\xf4\xe7]]x\xc3n6\x00\x00R\x8c\xe4\xf0\xf3t]\b\x85\x8f\xfb\xf9\xb3\x01\x00\x90r$\x87\x9f\xa7\xebR\xdf\r:\xe0)\xf6\x00 \x13\xd9\xe1Gl]\x17\x1a\xf2\xc6<\x14\x1b\x00\x80t\"5\xfc\\]Wh\xd0\v\x0f\xbc\x01\x00\xb9\xc8\f?W\xd7\x15\xf4u2Ԙ\x00\x00\xa4\x13\x99\xe1\xe7麦\xbaN\xe2\xdb~\xe0&\x1f\x00\x90\x89\xd4\xf0\xb3u]\x81\xf6\xaeہ@\xe0\x82q\xed\x0f\x00\x00\tH\r?[\xd7էۺ\xbcp\x93\x0f\x00\xc8Dn\xf8\x01\x00\x981@\xf8\x01\xc0\xa1@\xf8\x01\xc0\xa1@\xf8\x01\xc0\xa1@\xf8\x01\xc0\xa1@\xf8\x01\xc0\xa1@\xf8\x01\xc0\xa1@\xf8\x01\xc0\xa1@\xf8\x01\xc0\xa1@\xf8\x01\xc0\xa1@\xf8\x01\xc0\xa1@\xf8\xb3\x9a\xb0\xa8\x02\xe0` \xfc\xd9K\xa0\xb1PyBT\tp.\x10\xfe\xac%\\R\xe2\x1d\x80\x87\xa4\x00\\䆟\xad\xeb\"Je3\xb5\xad0oE\x9c\xc7\xc6\x03\x85\xb3\xebK\xc7W\x95>Q\x15\xc0\xd1H\r?[\xd7E\x94Jgi\xa1\xb71/\xce\x05\xfb\xf2g\x97Y`X\x81\x87\xa1\x03vH\r?[\xd7E\x94\xcafJiE\xe18\xb3?뮞\r+C\xa2*\x80\xa3\x91\x1a~\xb6\xae\x8b(\x95\xcdMev\x1d\xc9'\x04\x84\x1f\xb0Gn\xf8\x11K\xd7E\x94J%\xe4V4vh\xffk-\xcb+kU\u007f_\x9d\xab({n\xae\x9f\x97\xb7\x9cz\xa0h0OQr\x8e3Z1\xb9]\xe7\xce-\\\x11\xf3\x16\xd6Q\xe8ſ\x02\x05\xfaҔ\x02\xb2\x06\xb9\xb4`]\x91\xabx\xe5U\xb5t\x9b\x92\xeb\xdd1?o\xb9Vsj\xbd\xbbx\xc7\x0ew>~\xc4a\xe7\xe2\xfc\xf9;\xacG*c\xfb6ծݷ遥\x18\rB\xf8\x01[$\x87\x9f\xad\xeb2J\xe5\xf2\xbe\xbfKi\xf6\xfb\xb5\x885\xba\xf6\xf8\xf6\xb8\xd6\xe3g\v\x1f/\x9e_P\xbcc\xbdB\xc7\xf8\xb2\xdf\xefjf6\x13a0\xbf\xace\xa0Yi\xb1\x96?\xa1,ǿB\x1d\xad:\x1d\xe4\x9b\n\xb94\x9f\xf2\xe4`\xf7ʜa\x84n\x1c\x9f\xab\x146\xb7\x14\xd4\xe1\x1a%E\xadͮ\xbc\xf6\xe5jÍ9\xdb}\xad\x85e\xf4\xbb\xe4\xc7\u007f\xf6ҹ+g\xd7V\xff\x8e*\rM\x0e.t\xcb\x1fR`6!9\xfc\x1c]W\xb4T6\xc6a\u007f\x9fve\\\xff\x89ʔ\xa5\xc1\xc8\xc9\bE\x9e]\xf8C\xc5\xf8P!\xd4\x1d#\x1d\xbb}Pw\x11M\xde֙\xb4\xfc\xddXZ\xb0\x1b/\xb2L\xfbd\xde\xe5V\xdfz\xd6\x17\xaaS]\x8az,Ъ\x8c\xab\x93>\xa5\x03\xe1\xa3\xf9.j\xfe3\r8\xf6gV\xd3{\xfe'\xd4c\x8c,>\xa5\x01R\x81\xec\xf0#\x8e\xae+R*\x19#\xfc\x8d%گ\x92F\xfc\xb3\xccž\xfc`\x1b~\x9f\xf2\xbe\xcd_\xd5\xf7\x00%\x8a\xc5Kf.m\xaau\xf9\xbc\x02\xa5\fO\xbapG\x9a]\xea\x8f&7\xc2\xfd\xc4\xe3T?/\x84)n\xa4\xe6\xff\xb2aӱ\xb3\x9f>\xf8\x96*D\x81>o\t\xec\xf9\x01[\xa4\x86\x9f\xad\xeb\xa2K\xa5b\x84\u007f\xf1J\xed\u05ca\x85\xf8gY\x19\xbb\xb6m\xf8[\x14\x81t\xc4\xefӱ~\xfef,m\xb8\xb0\xb8餿J\x0f?^\x94\x16\xfe\x16e\n\x1f\x92\xe0=\u007fY\xe4\xdd\xc3r\xd7\xde\xfd\xb3/l\xad^\xdb\x13s\xce\xefW\x86\xadE\x00@ 3\xfcl]\x17U*\x19s\xcf?O\xfb5O\xdf\xf3ױkۆ\u007f@\x19\xb5\xf9\xab\r\xc6\xd2J\x16\xe3=u\x9d%\xfc\x81\x9c\x15\x81\xab\xf3\x17\xe3\xb1Y?oT\x83>\xb3\xb8\xf5\xaa\x1a\xfb\xfb\xe7j\xcf \vp\xb5\x1f\xb0Gf\xf89\xba.\xa2T6F\xf8}ډt\x97\xfe_q\xf8o7\xc7$=XT\x85\xdf϶o\xb7\xfe!z\xce\xcf\xc3XZ1\x9e\b\x97Y\xc2?\xaa\x14*J\x95vfЧhWH\xf6\x1c\xa4\xe6奄\x82\u007f\xed>\x82,@\xf8\x01{\xa4\x86\x9f\xad\xeb\"J\xe5\xa2_\xed\x1f\xd2\x0e8\xd6\xe74\xf9\x9ar\xf0\xd5\xfe!\xff\xfc*\xbf\xdf\x1aX\xb5\xd8\xefj\xf4\xfb\xf5N\xaeT\xf2cz;\xf8\xbd\x12\xafo\xbb\xd2n-_\xa9\xac\xb0\x16\x99\x90KkV\xeaZ\x0f\x96)\ue5a1\x80?\xb7q\b\x8d6\xe6\xfa\x03h\xd45\xe0\xf3\a\xf4\x83\xa2&\xa5\xbe\xbb\xb7Q餚詮\xedy\xf7ݗ\xaaǬm_V.X\x8b\x00\x80@j\xf8ٺ.\xb2T&\x91\xcf\xf9\xe7jw\x16\x86\xb5\xcf\xf9\xd5\xfe\\\xcd\xd1J\xad\x81\x1d\u058b\x15\xed3{Ԟ\xcf8\x9f\xbeYW\\\xb0\xf0dLq\xe4s~6\xe4\xd2\xc2-\xf3]\x85\xf5\x1d\xf3\\U\xdbԢ\xdc\xf1|\xf5\xe76t\xc1\x85+\xe4V\xe1\x93~\xd4W\xe5v/\xb6ܱ\u007fvwϦچ\xdd1\xd9G\x93s\xeb\xaeN\xca?\x95\x02f\rrß5\xf4*\x92\x8eS&\xf3\xb7M\x86B\xc1\xe1\xba$.\xdd\xf7\x96\xc4\\\x1c\x04\x00\x13\b\u007f\x12\x84;\xdcO\x8a꤈^\xb7\xbe\xef\x0e\xbb\x93\xf9\xd4~\xf2j\x06\xee\x99\x06f\v\x10\xfe$\b\xb8w\xc8:I\x19\xcdю\xf7\xd1x\x8e\xfdm\x04\x00\x900\x10\xfe\x99M\xb81\xefɮ\xc1\xae'\xf3d\x1dj\x00\xce\x01\xc2?\xd3\xf1-/r\x15-O\xe6\xa0\x1f\x00l\x81\xf0\x03\x80C\x81\xf0g%\xffh\"\xaa\n8\x16\b\u007fV\x02\xe1\a\xc4@\xf8\xb3\x12\b? \x06\u009f\x95@\xf8\x011\x10\xfe\xac\x04\xc2\x0f\x88\x81\xf0g%\x10~@\f\x84?+\x81\xf0\x03b \xfcYI$\xf8\xff\xf5?\xfd\x03\x15\xfe\xa9Ž\b\x00\"\xc8\r?[ץ2\xee\x85[\xd8\x12\xe4Jû\xfc?\xea\xd9\xff\x9b꿲\xec\xf9[r\xe8'\x81\x00NFj\xf8ٺ.\x95`\xfb\x05\xfa\t\x15\x80\x90wk\xcf\xf1\xff\xa8g\xbf\xf6\xbf\xc6\x1c\xf6\xfb液\xe7\x00\x9c\x87\xd4\xf0\xb3u]*\xbe\x81\x00\x84?Qb\x9e\xd8i\x12\xfeǟ\xfd\xe3?\xfe\u007f\xb5\u007f\xc58\xe7\xdf\xc3y41\xe0<\xa4\x86\x9f\xa3\xebB\xe3\x1dA\b\u007f\n\xb9Y\xf6\xc7\u007f\xfc\xef\xff8\xe7\xff\xf8?\u007f\x16\x1b\xfe`\x11\xfd\xe4o\xc0\xb9\xc8\r?b꺂\xed7Q\x16\x85\x9f#\xfcB\xf6\xe6\xae߭\xad}\xb5\xa1a\xec\xd8\xea\xdd\xf7\x11\xba\xffBC\xed\xa6}\xb7\xd4\xe2#յg^jX\xbd\xef3j\x12ݯ\xad\xae\xae\xd6\x0e\xfb\xd5ҳǶ\xd6\xee\xfb-\xfe\xcf\xfd\x17\xd76\xbc\xfa\xea\xda\u007f\xa3TU\xcdɫZ8\xe7\xcf\u007f\xa6\x85\xff\xb3\x17\xd6\xd66\xe85\xd4]\u007f\x9e\xacg\x11\x003\x1c\xc9\xe1g\xea\xba|\x03(\x9b\xc2\xcf\x13~\t\xcc]c\xab\xab\x8f\xed\xae^۳\xf6\x8cz>_\xfd\xd2ع}\xd5\x1f#t\xeb\\m\xf5\xa6\x9e\x9eM\xb5\xb7\xc8I\xb5|l\xac\xb6\aφK\x1bzzV\xbf\xa0N\u007f\xbb\xb5\xe1LOm\xed\x99\xff\xf5\xe0\xef\u007f\u007f\xe3\u007f\xfe\xfe\xf7\x0f\xfd\xfb\u007f\xc0\xe1\x1f\xab}\xb6\xe7JOu\xe4\xd9\xde\x17\u087e\x80\x8e\xe4\xf0\xb3t]7\xf0\xbbA\x16\x85\x1fq\x85_\xf6殆\x17ѕ\xeaw\xd1K/\xe1\xc7\xf0\xab\xbb\xff\a?ƁF\xb5\x9b\xf0\xa1\xc0\xa6g\xe9I\xfc\xbf\x9e\xc8\xef\xd5\xea>\xfd\xc5\x06u\xea\\\xb5\xfa\xbep\xa6\xfa\xe3\x929s\xe6\x84\xeb\xe7\xcc\xf9Ο\xe3\xf0\u007f\xbbi߷\xea\x1b\x03n\x12\x13P\xde@\x00\x80\xe4\x87\x1f\xc5躂\xed7\xc2\xe1\xf5殛\x00\x00\r\xefIDATp\xa03\x9cE\x0f\x9a\xe5\t\xbft8殆s\xe8\xe3\xea\xfb\xe8\xd5\x17\xd5\xe9\xfbg\xf6mZ]\xfdc\\\\\xfb*\xfeyF\xfd\v9\x89\x88\xf0\xab\xef\x16\xa8\xa7V\xfd\xf1\xeaj\xf5\xc7o\xaa\xdf\rl\xffc5\xfc\xff˿\xfb\xf3\xff\x86\x0f\xfb\xafT\u007fJ.&`q\xfd\x01\x8eEj\xf8\x99\xba\xae\xdb\xde(\xd9s\x19\x9a'\xfc\x8a\xc06w5\\A\x1f\xab\x11\xc6\xe1\xff\xb8aӫ\xef\x8e\xed\xd6ïe|\f\xefԉID\x84\x1f\xff\xd6\xc2\u007f\xe6\xcfԷ\x85+շ\xc2\xc1?W\xc3\xffo\xfe\xdf\u007f\xd0.\xf8\x9d\xa9\xa6<~\xc3\xf08\u007f@Gf\xf89\xba\xae\xa9I\x95\xf1\x8e\xc9,z\xc6<\xcf\xf9c\v\x11\xfe\xad\xcf\xe2\x9d\xfb\vz\xf8\x8f\xe1\x9fg\xb5=\xbf9\x89X\xe1\xff\xb2zߗ\xb7\xb6\xee~\x80\xd0\u007f\xc1\xe1\xff\xcf?\xd3>\xea\xbb\x12y\xb3\x88\xd0\xecJ\xfc!\xe0@V\"3\xfc\x1c]\x97F\x96\x9d\xf3\xb3\xc3oo\xee\"¿\t\x9f\xed?\xf8\xb1\x1e\xfe\xb5ډ\xfenz\x12\xb1\xc2\u007f\xabzmu\xf5n|U\x1f\x87\xff\x0f\xff\x93\x1e\xfe\xfb\r\xbb\xf1\xae\xff\x98\xf6\u0381\xc2%6\x02!\xc0QH\r?[ץ\x12\x0e\x8cw\x04b\xcc\xf6\xb3\x14\x8e\xf0\v\t\xcc]\xb7V\x9f\xb9\u007f\xae\xf6\xd6\xfd\x17\xd5\xf4\xf6T\xbfp\xa6\xe7\xc7\xd5k{\xc6\xd4lW?{\xee\xec\xd6տA\xe4\xe4\xb7ccc\xb5G\xc6\xc6\xee\xa3/\xf1\xef\a\x9f\x1e\xa9\x1d\xfb\x12ݪ\xbdre\xec\xb7\xf8\xe6\x1f\x1c\xfe\xff\xed?\xfc\x8d~\x93\xcfX\xedֳW\x8eU\x9f\xd5\x16Ӓ\xacP\x14\xc8:\xa4\x86\x9f\xa3\xebR\xcb\xf1)\xffq\xfe|\xb3\n\x8e\xf0\vٛ\xbb\x1e\xa8;\xeds\xab\xabk\xcfUW\xbf\x80\x1e\x9c\xd9Z\xdb\xf0\xe2٭\xb5\xbb\xf1\xb1\xfeK\xab\x1b^\xfc\x12\xd71'?\xae\xd69\x8b\x8e\xa8?k?\xc5\x1f\xfb\x1fQS\x8e\xcbjw\xdf\xd2\xc2\xff\xbf\xff\xe7\xff\xeb\xbf\xeb7\xf9\xfc慆\xd5\xcf\xea\xdf\x04\xf0\xe7\xed\xe0v\x01p\x18r\xc3\x0f$N\xf4螞d\xf1\xaf\xb5G\xfe\xf5w\xbf\xbb\xff\xf1\v\xab\xefk\xe1\xffo\u007f\x85o\ue9eat\xb9\x1a\xe1\x16\x1f \x02\x84\u007f\xa6\x13\u007f\xf8\xdf]\xad\xdf\xee\xff`\xed\x15=\xfc?\xfb\x9b\xff\xdb\xf2\x95\xde\"\xf8R\x1f`\x00\xe1\x9f\xe9\xc4\x1f\xfe[\x91\xcb\xfa\xb7\xaa?\xfd\xb7\xf8j\xff\u007f\xd0\xce\x02lg\x01\x9c\f\x84\u007ff\xf3[\xedz\x9eu\x92̓\x97j\x8f\x9c\x1b;w\xa4\xf6\xa5\a\x10~@\f\x84\u007ff\xa3]\xcf\xfb\xcc:\xc9\xe1\xc1\xbb\xfb\x1aj\x1b\xf6\xbd\xfb\x00E\x0e\xfb\xe11^\x80\r\x10\xfe\xac\x04\xc2\x0f\x88\x81\xf0g%\x10~@\f\x84?\v\t\xb5\xd6\xe1;\xfc\x9a.\xc0\xc7z\x80\r\x10\xfe\xec#\xbc8\xfa\x95ޓ\x90~\x80\x0f\x84?\xfb\b=t\xf0\xf7\xbf\xff\x9f\xea\x06z\xe8\t\xf8\x0e\x0f\xc0\a\u009f}\x04\x15\xa5\xaa\xea\xa1ª\x85s\x1a\xb3\xe5\xfb\x12@:\x80\xf0g\x1f!\u007f\xb1\xdb=\xdf\xedv/\x1d\x86=?\xc0\a\u009f\x85\x84\x02\xdaS\u0086\xea\n\x95'Du\x01\xe7\x02\xe1\xcfF\xc2\xe1\x90\xfao\xfe|\xef@\xf6<\x1d\tH9r\xc3\xcf\xd4u\x85:\xb4\x87xudӕ\xe9\x81BC?6\xb5\xad0o\x05\xf5\x90\xa2#\x91\xa7nO\x8f\xe8\"\x1a\x15EɻɨpU\xe9c\x94\x02@\x14\xa9\xe1g뺂\xde\xf7\x03*\xf4\xa3lg9\xbe|\xe3\x11\xb9K\v\xbd\x8dyԹ\xf7o\xc7\x04\xdfЉ\x8b\xe8\"\x02~\u007f+\xf3i\xdc\xc3\n\xfd\x8c@\x00\xa0\x91\x1a~\xb6\xae+\x98EO\xee40v\xf5SJ+\n[\xaf\xbb\xa5\"\xfc\xe6\"Ԙ\x0f1\xfe\xce,\x9d\x932b\xdb\x06f\x19R\xc3\xcf\xd6uee\xf8\rn*\f\xffpJ\xc2o\x92H\xf8\xbfI\x11\x10\xfeُ\xdc\xf0#\x96\xae+\xeb\xc2\x1f\xccS\x94\x9c\xe3x*\xe4֟\xcfo}tV\xed\xb1\xa8w˄\x90x1}^h\x9b\x92\xeb\xdd1?o\xb9v\xf4d,\x02\xc3\x0e\xff \x84\x1f\xb0Er\xf8Y\xba\xae\xa0w\xe0\r\xefq\u007f\x16]\xef\xbb\xec\xf7\xbb\x9a\xb5\xa9\xf7\xfd]J\xb3\xdfo}w\xc3O\xe2<\xf7\xe3Z\xea\x91ڄċ\xed\xf3\xbaq|\xaeR\xd8\xdcR\xa0=\x19\xd8\\\x04b\x86?49\xb8\xd0\xcd\xf8\x94\x1f\xc2\x0f\x18H\x0e?K\xd7\x15\xf4v^\r\xdc\xe8\xeeʢ\xf4#\x94\x17M&\xfb\xb0\u007f+\x16hm}\x96*$$^l\x9f\x17r\xb9\xd5w\x91\xf5\x85\x91\xff\xe5م\xff\t\xf5\xb8\x81\xb1`\b?`\";\xfc(Fׅ\xc2\xe3\xfaA\xc0\x90`\xbeY\x85 \xfc\x9aw+j\xdf\xd0!$^\x1c\x9f\x17ra\xbbv\xb3+\xf2?\xdb\xf0\a\xfa\xbc%\xd3\xda\xf3\xcf\xd1\xfe\xd9\xfc=\xb6m`\x96!5\xfcL]W\x14\xffI\xf6L\xb3\x13A\xf8)\xefV\x04B\xe2\xc5\xf6y!\xed@?\xbe\xf0\xab\xf8\x95\xe1\xd8B\x1c\xe87\xffH\x8f\xf5\xbf\xfc\xe5\xc3s\xbe\xffS^\xb8!\xfcY\x8f\xcc\xf0\xb3u]h@O\xc7 \xeb(u\xd6\"\b?\xe5݊\x9b\xc4\xc2Ͻ\xda\xff\x837\xf5X\xff\xc5\x0f~\xf9\xc5/\xff\xe4\x17\x9cpC\xf8\xb3\x1e\x99\xe1\xe7\xe8\xba|\xda.\u007f\xaa\xe3}\xdbyg\x19\x82\xf07h\xe7\xfc\xbbc\xffbK\x8a\xc2\x1f\x8d\xf5\x1f\xfeJ\xfd\xf1\xab\xff\x18I\xf3O\xbf?\xe7\xe1\xbf\xfb\xe6\x9b_\xfe\xf0\xa1\xef\xfc\xf0\xd7F\xf8\u007f\xfa\xdd9\x0f\xff\xe57Ą\xfa\xf79\xdf\xff{\b\u007f6 5\xfcl]W\xc0\xdbw3p\xb9ݗ5\x9e\xceА\xdf\xefj\xf4\xfb\x83ѫ\xfdC\xd6U\xab\xad\xde76\xf6\xac\xa6\xe0\x8a\x9f\x80?\xb7q\b\x8d6\xe6\xfa\x03\xe4\"\xb4;\xfcZb?Q@\x97Y:\xde\xd8\xf0?\x1c\xc9\xfe\x1f\xfe\xf4\x8b_\xaao\x04\xdf\u007f\xf3\x8b_\xff\xe9\x9fF\xc3\xff?\xbe\xff?ԃ\x83\xbf$&\xbe\xff\u05ff\xfe\x97_\xfc\x10\u009f\rH\r?G\xd759p\xbc\xc37\x9e5\xd9Gú\xafK\xf1F?\xe7\x9f{\xc3Rck\xcf\vQ\x05W\xfclS[\xca\x1d\xcfW\u007fn#\x16\xa1\xddۏ\xa9\xb7֟\x9c[w5\xc6|L\x86_?\xec\x8f\x1c\xdc\xff\xd1\xdf\u007fc\xf0뇣\xe1\xff\xc1/\"\xef\x0f\xc6\xc4w~\xa5ׁ\xf0\xcf~\xe4\x86\x1f\x90Io\x89\x12\xf3\x95^2\xfc\xf8\x82\xdf\xc3\u007f\x17\t\xff\x9c_\xeb\xbf\u007f\xa5\x1e\xd6ϙ\x13\r\xffC\xfa\xad\xbc\xc4\xc4_<\xf4\xa7\u007f\xf7+\b\u007fV\x00\xe1\xcff&\xafZO\x06\xc8\xf0k\xbc\xf9]\xfd\xf7C\x91\xf0\xff\xe0/~\xf5\xcd\x17F\xf8\xe7D\xf6\xf3\xe6\xc47\xbf\xf8\xeb\x1f>\xf4\xd7\x10\xfel\x00\xc2\xef,b\xc2\xffÿ\x8c\x84>r\xd8\xff\x9d/\xd4\x13|#\xfc\u007f\xf4\xb7\x91j\xc6\x04\xe6\x97߁\xf0g\x03\x10~gA\x86\xffO~\xf1/\xbf\xfc\xd3?\xfa\x17=\xd0o>\x1c\xb9\xe0\xf7\xd7_\xfc\xe2\xbbF\xf8\xdf|\xe8\xef~\xfdś\u007fBL\xfc\xc9O\xbf\xf8\xe2o\xbf\x0f\xe1\xcf\x06 \xfc\xce\x02\xc7>r\xf6\xfe\xcd\xdf\u007f\xf7\x0f\x1e\xfe\x8b/\xa2\xbb\xf3\xbf\xff\xae\xf6Q\xdf/\xbe?\xe7\xe1\xbf5\xc2\xff͛?\xf8Μ\x1f\xbcIL\xfc\xf4\as\x1e\xfa\xe1/!\xfc\xd9\x00\x84\xdfY\x10\a\xfc\xd3\x03\xc2?\xfb\x81\xf0;\v\b?`\x00\xe1w\x16\x10~\xc0\x00\xc2\xef, \xfc\x80\x01\x84\xdfY@\xf8\x01\x03\b\xbf\xb3`?\x8c3\x19DK\x02f<\x10~\xc0\x96\xec\xf9\xca\x05`\x05\xc2\x0f\xf0\t4\x82\xf0+\x8b\x81\xf0\x03\\\xc2%% \xfc\xcab䆟\xa9\xebR\xb9\xd1\xd7\xd1}\xd9f> \x82\xad\x06,\xe5\x80\xf0+\xbb\x91\x1a~\xb6\xae\v\x85\x06\xbcC\xb7G\xbd\xf4\xc3*\x01\x16\xb6\x1a\xb0\x94\x03¯\xecFj\xf8ٺ.4\xd0\x1e\xc0o\f\xd6'^\x00\f\xec5`)\x86\xfdx0 [\x90\x1a~\xb6\xae+\xe0}\xdf\xf8\x1b\x10/\xccg\x03\xa6\x18\b\u007fv#7\xfc\x88\xa5\xeb\x1aj\x0f\xc1\aJ\xf1 Ҁݪ\xad\xae~\xf5\xb3\x177\xd5\xee\xfb\x1dQ*Ԁ\xa9|\xf6\xc2\xdaچ}\xbfE\x16\x98\xc2/ k\x90\x1c~\x96\xae\xab\xd7w\xe3\xa4\xf7\xf8\x85\xac\x12\xf6\xa4\a\x81\x06\xec\xdbs\xe76m]\xddp\xec\xc5?#\x9f\x0e(Ԁ!4V\xfblϕ\x9e\xea3T!O\xf8\x05d\r\x92\xc3\xcf\xd2uuk\xba\xae\xe3ݐ\xfe8\xb0\u007f$8\xfaq\xf5\xee\xfb\xe8\x01\xad\x03\x10j\xc0\xbeݴ\x0f?I\xfc\x1c=\x1bO\xf8\x05d\r\xb2Ïbu]>\xed\xaa_\xb0\x83\xe1\x97\x01\xac\x88\xc2_\x1b\xf3H`\xb1\x06\xecJ\xf5\xa7֙\x10_\xf8\x05d\rR\xc3\xcf\xd6u\r\ua7ae\xc1^\xfe\x8c@\x14Q\xf8i\xf7\xa7\x86P\x03v\xa6\xfa\xdbع\xb49Y\xc2/ k\x90\x19~\x8e\xaek\xb4C{/\x18\x80c\xcc8\x10\x85\xff\x05F\xa1\x88+\xb43\xd0\x04\xae\xf6g72\xc3\xcf\xd1uMi\x1f\xf5\x05\xdb\xe1\x16\xbf8HG\xf8\xef7\xecƻ\xfecǬ\u007f\x80\xf0g7R\xc3\xcf\xd6u\xa1\xcb\xed\x97\x03\xe3\x9d'႟\x00\x91\x06\xecwcc[w\x8f\x8d}ƙ\x9d\xcfX\xedֳW\x8eU\x9f\xb5\x963\x85_@\xd6 5\xfc\x1c]\x17\xba\xdd\xdbq\xf22d_\x84H\x03v\xabZc\x1fgv\x1b~\xf3B\xc3\xeagߍ)f\n\xbf\x80\xacAn\xf8\x81\xd9\x05K\xf8\x05d\r\x10~\xc0\x8eX\xe1\x17\x905@\xf8\x01\xc0\xa1@\xf8\x01\xc0\xa1@\xf8\x01\xc0\xa1@\xf8\x01\xc0\xa1@\xf8\x01\xc0\xa1@\xf8\x01\xc0\xa1@\xf8\x01\xc0\xa1@\xf8\x01\xc0\xa1@\xf8\x01\xc0\xa1@\xf8\x01\xc0\xa1@\xf8\x01\xc0\xa1@\xf8\x01\xc0\xa1\xc8\r?K\xd7\x15\xea\xf4\xea\x1c\xb7\x9f\x17\x98!\x10\xca0`V#5\xfcL]W\xc8;\x1aP\xb9\xec\xbd*\x9a\x1d\xc8\x18\x83\xa3\xe64\xa1\f\x03f5R\xc3\xcf\xd6u\x8dk\x0f\xef턇\xc6\xcc`\x16\xd6\x13\xff\x81\xc7{d\tR\xc3\xcf\xd6ui\xf8ހ'\xf9\xcc`\xca\xeaD5\x80ه\xdc\xf0#\x96\xae\v\xa3=\xcf\x13\xc8\x14\xb7\xebܹ\x85+\xb4\xc7v\xb4\x96啵\xaa\xbf\xb7)\xb9\xde\x1d\xf3\xf3\x96\xe37\xea\xc8\xc3\xfe\xcb\x10\xa9\f#*lSr:\xd1m\x97R\xa25ֹ8\u007f\xfe\x0ex\xe0\xff,@r\xf8Y\xba.\x8c\xe6\xf1\x002\xc4`~Y\xcb@\xb3ҢN6\xba\xf6\xf8\xf6\xb8֫o\xc7\xc7\xe7*\x85\xcd-\x05\xea.?x\xc1?\xbf\xca\xef\xf7kO\f4\x94aD\x85\x80?W-\x1ajt\xe1\xf2Ɯ\xed\xbe\xd6\xc2287\x98\xf9H\x0e?Kׅ\xa2\x17\x03\x80\xcc\x10*^\x1e\xc2OT\x9fB\xa8O\xc1\xa7c\xfaO\x97[\xdd(\xeb\v\xb5*\xd4a\u007f\xf4\xf1\xe1D\x05\xed\xfd\xa0\x19\x87ߧt \xfc\xd0\xef.\x04\xcctd\x87\x1f\xc5\xea\xbaT\x06\xba\xedg\x01҉Oy?:٨\x1f\xb9\x974\xaa?\\\xf8\x87\x16h^\xf8\xcd\nf\xf8\xeb\xe7\x850ō\b\x98\xe9H\r?[ץ\xd2\x01\u008e\fҢ\x18\x17[\x17\xaf\xd4~\xadX\x88\xc8@\xf3\xc2oV0'\xcb\"\x17\b\u087f3\x1f\x99\xe1\xe7\xe8\xba\xf0\x95\x00J\x1c\t\xc8e@1>\xc5o\x9c\xa7\xfd\x9a\xa7\xed\xf9\xad\xe1o\x8f\x9c\x9b\xf1¿\aO\xae\x9f7\xaa1\x85\x80\x99\x8e\xcc\xf0st]\xf8\x94\x1f.\x0eg\x90`Q\x15~+\u07be\x1d\x9f\x01\xe0s\xf5.M\x05F\x86\xbf\xaa\n\xa1I%rr\xc6\b\u007f^\x93\xfa\u07be\x10O\xf6\xe9\xb5\xf6\x1cD\xc0LGj\xf89\xba.\xf5\x9d\x00>\xe4\xcf$\x83\xdf+\xf1\xfa\xb6+\xed\xea\xe4\xfa\x9c&_S\xcez\xed\n~\xe3\x10\x1am\xcc\xf5\xe3\xfd}\xb3\xab\xa5wi~\x80T\x86Q\x15\x16\x17\x1e<\xb8X\x99\xdbq\x03\xa1&\xa5\xbe\xbb\xb7Q\xe9\x14-\x14\xc88R\xc3\xcf\xd5u\xc1\xfd\xa2\x99\xe5f]q\xc1B\xedSװ\xf69\u007f\x18\u007fv\xaf(\xb9\xe3\xf9\xea\xcfmjqh\xbb;\xaf\n\xfb\xbaMe\x18U\xe1fU^\xc1\xf2&\xbdn_\x95۽\xb8\xcfvy\xc0\x8c@n\xf8\x01\x00\x981@\xf8\x01\xc0\xa1@\xf8\x01\xc0\xa1@\xf8\x01\xc0\xa1@\xf8\x01\xc0\xa1@\xf8\x01\xc0\xa1@\xf8\x01\xc0\xa1@\xf8\x01\xc0\xa1@\xf8\x01\xc0\xa1@\xf8\x01\xc0\xa1@\xf8\x01\xc0\xa1@\xf8\x01\xc0\xa1@\xf8g\x0f\xf5\x8a{\xfd\rQ%\x00\x88\x17\b\xff\xec!0\xd8Q\xe2\x86'\x1f\x00\xa9Bn\xf8Y\xba.\xfct\xd87\xda߸\x00\xaf\xea8\x18T\xc0k\x04\xa4\n\xa9\xe1g\xea\xbaP\xb0\xf3$.\xed\x84\xf4\x8b\x19V\x86DU\x00 N\xa4\x86\x9f\xad\xeb\xf2wk\x8f\xf0\xef\xf6\v\xe6\x06 \xfc@*\x91\x1a~\xb6\xaek@\u007f|w/x;\xc4@\xf8\x81\xd4!7\xfc\x88\xa5\xeb\x9a\xea\x1c\x9c\nM\xf9;\xe1y\xafb\xae*\x83\xa2*\x00\x10'\x92\xc3\xcf\xd4u\x85\x06\xd4\xd2>x\x86g\x1c\x84\xdc\v/\x04\xc0\x84\x05\xa4\x04\xc9\xe1g\xe9\xbaB\x03\xdd\xf8\x99\xbe\x03\x90\xfe8\xe8S\x14e\xa5\xa8\x12\x00ă\xec\xf0\xa3X]W\xf4\x82\xdf\x05ь\x00\n\x16\xcek\x19\x04\xc3\t\x90\x12\xa4\x86\x9f\xa9\xeb\n\xb7\xeb\xa68\xcd\xe3\x03\xd83\xac\xc0eQ U\xc8\f?[\xd7\x15\r\xff(\x84_\f\\\xed\aR\x87\xcc\xf0st]\x83\x91\xc3~\xb8\x8e-\x06\xc2\x0f\xa4\x0e\xa9\xe1g\xeb\xbaB]\xdd\xe3\x81\xf1\xee.\xb8\xe0'f\b\xc2\x0f\xa4\f\xa9\xe1\xe7\xe8\xbaB\xc3';N\x0eC\xf6E\x84\x02\xa3\xf5\xae\x80\xa8\x16\x00ĉ\xdc\xf0\x03\xd3\xe1\tE)\xee\x15U\x02\x80x\x81\xf0\xcf\x1e\x02\xa3\xb0\xdb\aR\b\x84\x1f\x00\x1c\n\x84\x1f\x00\x1c\n\x84\x1f\x00\x1c\n\x84\x1f\x00\x1c\n\x84\x1f\x00\x1c\xca\xff\x0fL\f\x1em+\xfdz{\x00\x00\x00\x00IEND\xaeB`\x82",
+
+	"analysis/chan1.png": "\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x04\xc0\x00\x00\x02n\b\x03\x00\x00\x00aR\x8e\x00\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x02\xfdPLTE\x00\x01\x00\a\n\a\x0f\x11\x0e\x1a\x1a\x14\x1f\x1f\x18!# #$\"\x15%D$%#%'%'(&+)\x1e()'*+)/,!+-*,-+-/,02/63(241564796<9.9;8#?r@=2<>;>@=C@4DA5AB@DFCFHELH:IKHKLJNOMUP?PRORTQTVSVWU]XGWYV_ZI,`\xaeZ[Y7]\xad[]Z\\^[9a\xab;b\xac<c\xad_a^faO>e\xafac`hcQcdbAg\xb2efdCi\xb4fheDl\xb0Mj\xafqjRikhGn\xb2Ip\xb4lmkKr\xb7npmUt\xb4{s\\rtqWv\xb6tvsuwt[y\xb9\\{\xbbxzw]~\xb8e|\xb8\x84|dX\x80\xbf{}za\u007f\xbf|~{~\x80}b\x82\xbc\u007f\x81~d\x84\xbf\x81\x83\x80|\x83\x97\x83\x85\x82l\x86\xbch\x88Ð\x86hn\x88\xbej\x8ać\x88\x86q\x8b\xc1\x89\x8a\x87t\x8e×\x8doz\x8e\xbf\x8c\x8e\x8b|\x90\xc1\x8e\x90\x8dx\x92Ȑ\x92\x8f~\x93ĝ\x93ux\x96Œ\x94\x90\x81\x95Ɠ\x95\x92{\x98Ȕ\x96\x94\xa2\x97y\x96\x98\x95\x81\x9aė\x99\x96\x84\x9cƇ\x9b̙\x9b\x98\x80\x9eͦ\x9c}\x87\x9fɜ\x9e\x9b\x89\xa1˞\xa0\x9d\xa0\xa2\x9f\xa1\xa3\xa0\xa2\xa4\xa1\x91\xa5ʏ\xa7Ѥ\xa6\xa3\x94\xa7̥\xa7\xa4\xb3\xa7\x83\x92\xaaԧ\xa9\xa6\x97\xaaϩ\xab\xa8\x9d\xac̫\xad\xaa\x9b\xaeӟ\xafλ\xae\x89\xad\xaf\xac\x9e\xb1ע\xb1ѯ\xb1\xae\xb1\xb3\xaf\xa5\xb4Ԣ\xb5۳\xb5\xb2ö\x91\xab\xb7ѵ\xb7\xb4\xa8\xb8ح\xb9ӷ\xb9\xb6\xb9\xbb\xb8\xb0\xbc\u05ed\xbdݻ\xbd\xba\xb3\xbeٽ\xbf\xbc\xb7\xbf\xd4\xcd\xc0\x9a\xbf\xc1\xbe\xb6\xc1ܹ\xc1\xd6\xc1ÿ\xbb\xc3\xd8\xc2\xc4\xc1\xbd\xc4ں\xc5\xe0\xc4\xc6\xc3\xc6\xc8\xc5\xc0\xc8\xdd\xd7ȝ\xbb\xca\u07bd\xc9\xe4\xc5\xc9\xd9\xc0\xcb\xe6\xca\xcc\xc8\xc7\xcb\xdb\xc2\xceܿ\xcf\xe2\xc9\xcd\xdd\xcd\xcf\xcc\xc9\xd0\xe6\xcc\xd0\xe0\xc6\xd2\xe0\xdfѤ\xcf\xd2\xce\xd1\xd3\xd0\xd2\xd3\xdd\xd3\xd5\xd2\xcd\xd5\xea\xce\xd7\xdf\xd5\xd7\xd4\xe6ת\xd6\xd8\xd5\xd1\xda\xe2\xd8\xda\xd6\xd9\xd9\xe4\xd3\xdc\xe4\xd5\xdb\xea\xda\xdc\xd9\xd8\xdd\xe0\xdc\xdd\xe7\xdc\xdf\xdb\xda\xdf\xe2\xe0\xde\xe2\xde\xe0\xdd\xf0\xe0\xb3\xd6\xe2\xf0\xdc\xe2\xe4\xe0\xe2\xdf\xde\xe3\xe6\xde\xe2\xf2\xe2\xe4\xe1\xe1\xe6\xe9\xe4\xe6\xe3\xde\xe7\xef\xe8\xe5\xea\xe5\xe7\xe4\xe6\xe8\xe5\xe4\xe9\xeb\xe7\xe9\xe6\xe8\xe8\xf3\xe8\xea\xe7\xe2\xeb\xf3\xe9\xeb\xe8\xec\xee\xeb\xe6\xef\xf7\xe8\xf1\xf9\xef\xf1\xee\xf0\xf0\xfb\xf1\xf3\xf0\xf1\xf6\xf9\xf4\xf6\xf3\xf7\xfa\xf6\xf5\xfa\xfd\xf9\xfb\xf8\xfa\xfc\xf9\xfd\xfb\xff\xf9\xfe\xff\xfc\xfe\xfb\xfe\xff\xfc\xc5\xe5[\xa2\x00\x00 \x00IDATx^\xec\xbdqLS[\xda\xef\xef93\x8b\xab}\x87Ax+\xc3}\xf5^8#\xbe\x1c\xbc^gk\xa9\x17\u007f\xe2A.U\xe1u^\x05މ9\xf6\xe8}\xc9\x18\xc5\x174z\x8fg<W\xb7i\x86\x1e\xa0D\x99`1\xbcD0\f\rp\x022\x04\xa5i\x99\x89\xa9F\xc2;\x8d\x8d\x9c\xd83\x89\xf6L\x8c\x90BL\xbb\xfe\xfc\xe5\x97\xdc\xff&\xbf\xb5\xd6\xdem\xf7nw[@\xd9Px>\t\xddk\xaf\xfd\xac\xb5\xf7j\xd9߮\xf5\xec\xd5\xf5l\xf8\xdb{\x80\x01\x00\x00V\x8e\xbfmH&R\x89HV;\x00\x00\xc02\x02\x02\x06\x00@\xca\x02\x02\x06\x00@\xca\x02\x02\x06\x00@\xca\x02\x02\x06\x00@\xca\x02\x02\x06\x00@\xca\x02\x02\x06\x00@\xca\x02\x02\x06\x00@\xca\x02\x02\x06\xac\v\x02\xc9\f\x80\x94\x04\x04\fX\xfbx*\xb6\xa0\xfdɌ\x80T\x04\x04\fxO\xda\v\xbc\xc9L\xd4\xc1[Ю| \x90\x97\xc7\xf7\xb8\x95\x8f\x01\xa9\x8d\xda\x02\xe6\xe9j6Y\x06|\xb2\xe4|\x13/М\xa0\xe0_\xaf\x95\xe9k\x83\t\fbiۈ\x046\xb6%3]\x94\xed\x12\xa9C\x9b\xe8\rf\xcd@u\xca\x06w\xd9\x05d\xeds)\x1f\xc6\xd8L\x0eבz\x102\xc53\x890\x9aƪK{ \xecNnByds\x84de(\x9c\xc0\xb1'#\xbb\xb47{:\xf6H2\x1aйd&K`\xec\xd0p2\x13F\xbf\x8e\x13\xd0\xf5\x93KIkP4\x1aG]\x8a\xf9@ꣲ\x80M\xf3V\xa7\xdb\xd9\xd6\xec\x93&g\xf8Q\x0f\xe1\x01?\x9e\xa0\xe4\xe9C\x9d\x17\xf5o\x13\x18\xc4Ҁl\xb6\xaf\xd1e\x9b\r)\xff_SzG\x17n\xbbDB\xa7\xf0\x96f\xec\"\x9b]\xe9\xa5qz,\xbe\x81MGl\xbd\xbfٖ\xeeT>\x8e}f\xd4\xe0\xc5\xde\x06d\xf6ű\x88\x9c\r\xcf\x0f\xb2\x06\r\xfa\xc5\xfd\xc1#\x1a\xf2\xea\xa6\xcd\x1c\x8c)Օ\xb1\x83oَP\xbc3\xc7\xe77if!\x11>q<\x1e=Y\x84\xc1pq\u007f|C\tw8\xbb\xbd\x93\xeb\xb0\xdbw\xdf!{֍W\x95\x8c\x86\x90M)\x1bX\x03\xa8,`.\x9e\xf6\xe4}\xbcS\x96t\xd0\xfb\xd1\xd74\x90\xa0\xe0\x0f\\'\x0e\xce&0Pಆ\xfe\uf4bb5\xfdr\\\x9b\x1d\xa5\v\xb7]\"\xa1S\xe0S{3|؛\xbe\xf7T\\S\r\xed\x9b\xf9r\xf6\xc4;\xee`]\x89^\xe4\x88g 9\x1b\x16\x1b\x14\xa6N\xa3\x94\xcb\xf0f\xee':\xe7۶x\x01\x9bԄZ#=\xb1\x04oaH\xaek.(\x1aD\x90\x19,\xb0\xb3ݡ\xc3\xf817\x81\xb1\xbe\x83\xee\x9e\xd1(\x8d\x14\x15Z\f\xac\x11T\x160̺\x0e^\xde#OR\xeeޚW.\xc2x\xc1-lH!\xc5\xef\x12\xffw]~\x1c\x8f\xfc\x83\v\xb7]\"\xa1S\xe0S\xa5\xbbZp\xd3/J\x93\b\x18>\x97\x1e\xef\x91\xd9\x02\x04,|6\xbc\b\x01;\x95\xceƎ\x97P\xdc\xd1k<*\xb2C\x9dA\xe9\x89%8\xc2\x17[\x95L\xc0\x92\x1a(0\xf7B\x14\xb0\x17stח]\xa1`\x04\x02\xb6vQ[\xc0\b3n\x8b5\x10\x93t\xf2\xf1\xfd/se\x82\x9f\xe3&\xc6\xd78\xae\x0f\xbf\xd0q\xbf\xa4Iݽ\x9b\x95\xfa\xda\xef\x99͋\ve\xbaCbZB\xe4\u007f\xb7\xa9 #\xb7\x9a\xddm\xb6=9\x9b\xb4{\xb7\x92\x11\x87\xe8\xf7ʗَoD茫|k\xfa\x9ey\xec;\x98\xad\xc9\xd9G\x87\xb6\xc7\xd0&\xbe:7c\x8f[V\xc31\xb4\xf1jEN\xc8mu=?c\xfbuy\r\xd2S\x9c*\xbd~\x00\xef\xbdN\x05,R\xaf\x93\xd8\xee\xc39\be\xf9C\x02ְ\xd1/\xb9^\xe9\xe5\xc8\x04,t\xb6\xa4\r\xc2\xd8S\x9e\x9du\x80\r!\xb1\xe2[\xb2M\xb8\xed\xbd\x97\xfc\x92z%-Vn<\xc1\x9f\xf99\xdbF\x9d8\xc4\xd5\\\xab\x139\xad\xb9\xd7\xf1\xb0說\xa1\xd9\xc1\xfb5ŕ7Y\u007f\xda^{XWV{8(3x\xab\xe7\xe8nj\xa3>\xe3W\x17\xcb\f7o\x96\x15\xf7\xc9O\"\b\x98ș\xf4\x19\x1cC/\bؚEu\x01\xf3\xf2</\xbap$I\x8c-=\xf1\xcb\xe0\xa7\xf6>\xae\xd5n\xff\v\xc6\xdf\xdbu\xad88\xf1e\x11\xc6S}:\xeeP띒\xf3\xd4\xe2Qq͝\xb1V\xae#\xbad\xf8n\xadH;n\xbd\xaa\xcd\x0fЬ#\xb7\xbay-\"\xf24`\xcb-\xb4\xd9lN\x99팥yknfNu9r\x93\x1b\xb3\xa2ײ/m\x88\bM\xf3F\xa4\xad\xbb\x94y\x00Kk\xa0\xb9[\xeb\xea\xb6fPI9\xa29c=\xa3)\x97\xd5 =ũRw\x86\xf7'\x1e*`\x91z\x03\x83ui\x83،\x9a\x1ebQ\xc0\x02\xf9ۥ\xd7+\xbd\x1c\a\xb2\xce\xcc\xcc\xdcE\xb2\xb3%m\x10ve\xe6\x9a\xdb\u007f\x814\xf1\xde\x12\u007f\x9ad\xdc\x1c\xaeW\xd2b\xe5\xc6\x13FQ/+\x14u\xe2\x10\x9er\x94\x87>A\xa5n<;a\xaf4\xda\xed\xf6\xe74\xfb\nwc\xa4\xf3P\x15\x19%>\xdd}\xb1\u007f\xec^\x19\xf7Nn\xf0\xd8n\u05f7҄\xf43\x9e;a\xe8l\xd5\xeb\xef\xd5F\u007f\xc8R\x01\x1b\x88Ѫ\xf9\xe9\xde\x1dY\xf1}\x86@j\xa3\xba\x80a\xaf\xc7ai\xf6E'\xdd|\xe2\xc7ܑ!d\x11\xfd\xcfn-b\xc9\x12\xf2\xcd|\xf1\x10I\xcd\x1d\xae%C\x88\xb9\xbe\x1f\xa2˅\xeeV+2\xb3\xbd\x16\xd2\xc3\xd0\xd2{\xef\xeb,\xd6\xf5S\x1eq\xe5\xa3]>6\xc6\xf5Y\xe8\xe5}\xc2\xe6\x10i\xb2\xc8%\x96k\xb1\xbc\x06\xcdVj\x96S\x80q\x17\xeb\x1eu\xa1\xbb\xb2\x1adCH\xfcɱ\x1d\x98\xf5\xc0$\xf5\xe2#\x05\xde\x1c\xe1с\xe6_g|\xe3\aP\x8f\xecz%\x959Ď\x8eCv\xb6\xa4\r\xfat\x1b)\x1bخ\x91\xe7FN\xe1F\x91\xf9\a\xd2VDZ\x1c\xa7\xf1\xa4\x8e\xc9PA\xe5!d\xd7&\xb4鮐\f\x8f\x10\x87\xb9\xfb\x98\xca\x0e\xe9Iu\x1ezG\x92\x9d%A\x99\x01E\x100\xe9g\xdc\xc7=#\xa6\xdc\x14\x8eF*`nt+\xea\xe8~\xf2~Y1\xb0FQ_\xc0\b~Kwt\xb2\xdb\x12ך\xa1,`\x17C\xc9\x11\xee\xa9r\xb9\xd0\xddZ\xba\xcd?O\xc8!c%w\xf6\xd6\u007f\xe6\x1f\x06\x04_W\x1c\x01\v\xfb\x82\xbd\xd7\xf7l\xcbD\xb4K\x845G\xc8\xcb9\r\x96נ\xf9\x82\xbe~\x8d\xbc\xb8\xe2\x13V\"\uf23c\x06\x99\x805\xa0\x06&`\xd2z\xf1\xcc\xf6-\xfb\x04\v\rU'-U\x13\xc9\xf5J*s\xa0KCCC\x97\xa9\x80IΖ\xacA>\xc4\xd3\xcd\x19\x8d,Wr\n\xff\xc6H\x0fLڊH\x8b\xe34\x1e\xb7'\x160o\xb5&\aekN2?~X\x9f\xea\x8fν#\x18\xae`\xfc\xd2p\xf4ƽ\xa7A濊#`\xe1ϸ\xb1\x84\xbc<\xe7\xbe\xc5\xd1\xc8\x05\xac%\uaa3b\x8bσ\x1eؚEe\x01\xf3\v\x1e\xafq> M\x12\xcc\x0f\xe2\x96a(\vX8\xd9\xc1\xcd)\x97\vݭ\xdbž\v\xed\xf3\xf8\xf8\x83yh\x8b\xd0\xe7\x89#`;BY[r>o\xb3\xed\x14\x04\xec\x1c\x0ey\xc2%5\bn\xab^4\x8a?\x15Tho\x81\xac\x06\xb9\x80yɽL\x05LZ/Ʒ\x90\xf8\x00VS14$\xb8Ӥ\xd7\x1b\xa9L\xe2\x03\x93\x9e-I\x83\x1e\b\xb3\b\x04%R|KD\x1f\x98\xbfK^\xaf\xa4\xc5ʍǃ\x91\x11\x9b\x92\x805hy'r\xfeF\xcbޣ\xb0>\x9d\x10\xdd]gI\xfa\xed\xbd\v\x95\\ٝ\x04=\xb0\xc8g\xbc\xfb\x15\xfd\xa6J\xdc\x03\x1b\n\xbd\x95Rlh(6\x13X\x13\xa8+`\x81&\xc1e\xf2\xd0\x14\x90$1u\x87%\x99(\x1d%`\xdfD\t\xd8\x18\x1d^(\x11\xba[˷\x8d2H_\xe0\x01\xed\x01\xf9Zҙ\x03\x9c\xddv&\xb7̖\xe4\x1e\x10\x13y\x05\xf4\xbb\xfb\x80 `\xf46d\xf7\xb0\xb4\x06M5=\xc6#\x1f\xae\xd8Ɗl=\"\xabAr\x8aS\xc2D\x03*`\xd2z\xb1'\xfb\x8b\xad\xc2\\\x03Mx\x8a\xab\xe4z%\x95I\x04Lr\xb6d\r\xf2\"v$ډ/9\x85\xf8\x14\xd2B\xfb\x91\x92VDZ\x1c\xa7\xf1\xd8DŽ\x8d!=q\x18?{\n)\xf4֘>\xdd{I{`O\x18D\x8f\x1e7\x12\xe9zۧ\xef\x94\x19Pb\x05\xec%W\xfb\xf2Y\xa51v~\x85T\xc0\xea4\n\x9d-x\n\xb9vQW\xc0p3\x9b\x12\xed\xa7\x1e{I\x12\xe3I>I'?\"`\xfaF\x8c\x83\xff\x12%`\xb3\x06#\xed\x82ݸ\x11].\xf4\xbfۅ\xd8\x18\xf5\x8b::#\x9e\x9d\xb9\xf0\x18{-\xc4xZ8&\x15\xb0Po\"\x87JG`{\x94\x80Ik\xd0l\xa1\xee\xa9m\x85\xd4\x1fDG/-\x82\xc3E\xd2\x1f\t\x9fB\"`\xd2z\xfd\x05g\xf0\xb1]\x81\xf0)\x18\x92\xeb\x95T&\x110\xc9ْ6\xa8 \x87\x88\x94\xeb'\x1a,˕\x9c\u009by\x80\x88L\xa0p\xab\xbc\x15\x8a\x02&;\x1b\x19\x87\n\x1di\xf9\x89%\xb8\xb3B\x9af4b\xfc\x9a:\xbeƄ'\x8c\x8d\xb7ɇǍ\xb0C\xd7d\x06\x94X\x01{\u0095q\xdc\xe9\xd0sfwCx\xf0*\x11\xb0@\xde^\x1c\v\b\xd8\xdaEe\x01s\xf1\xddN\xb7\x93y\xee%I:\x89\"\xe1\xf4+\xe1)\xe4\x04\xfb\xf25\x1e\xbas\xbb\x86\xd3ݟ\xfa\x8b]\xf7\xe5D\xf0\xe9\x97:\xfat\xf2\x91\xfeD\xe7\xc8\r\xee^T\xc1ѯ\xd1\xe5\a,u\n\x95Z\xda+P\x13\xbd\x037\x9f\xb3\xb6U\b\xcf\xcf\xcei.\xb5\xef\xcapKm\xe7\a\xd9\x135v\u007fԡ\x83\xd7\xeb\xf2\x91\xb6a\xd0c\xdbtd\x10\x8f\x1e\xd9d\xf3\xc8jР|\x8b)7\x8bZ\x97\xa7\x9d\xb2\x9eJ+\x97\xd7\x109\x85\xb7t\xa7\x87\xeczv\x96z%\xf5\xce\f\x1cӺ\xf1df\xf5\x80\x9f\xce\xc4\x0f?\xc6\v_\xaf\xa42\xd9L\xfc\xf0\xd9\xe24H2\x13ߑ\x91Sw&+m\xa3\xd9)\xccĿl\xb3\xb9eo\t\xee\xca(0\xb7\xffb〴\x15\x92\x16\xc7k<\xf9\x14\xd3.ay3\xe3\xd2Z\xd4\xd1\u007f\xba\x98v\xb0\x1aw\xd7\xf7\u007f{\x85JU+W\xdc:\xdc\u007f\x85{$3\x98\x9b\xb0\xdb\xf5_\xda\xedo\xb1\xf43~\xa6\x1f\x1b\xb1\u007f\x1f\xea\x80\xedC!\xa9z\xda\xc9u<\x16ӗ\x91\xd2\xef\x01\x1e(\x8d+\x815\x81\xca\x02\x86==\x16S\x9b\xf0\xf3\x16I\x12\xbbo%*4W\"\xfc܍=b\u007fa\xd4\x17\xd7~\xc3q\u05eeѬ\xff(&\xaf\xf4\xfb\xfb\xf9\x05CqM\xf4\xcfO|\x9b\x11B\xe9B\xe7\xaek\xa76\xebS\xfa@\xac\xa9\xb0.gSv\xa1p\x03\xfa\x8fg\xa5\x17\x0e\xc9lDž\x1f\x11\xb2\xfb#p9W\xa3-5o\xd3\x14\x1e#Y\x9b\x1c\x19\xe4\xf5\x98\xac\x06MuEfv\xb9\x87\x19\xfff{\xc6\xf6\xaf\x03\xf2\x1a\"\xa7\xa8C\x88\xba\x9a\x8e\xd1\xdf3F\xea\xed\"\x86\xd5\xf88y\xed\xa5\xbf\x85\xcc\v_{\xe8z%\x95E~\v\xc9K\xce\x16\xa7A\x0f%\xbf\x85t\xed\xcb\xdazҼ\x91\\\xfa\x11\xd1\xf1U*=\x05\xc1\xf1\x8b\x8c-\xfb\x1c\xb2VHZ\x1c\xaf\xf1\x843?\x19\x9073.s7>\xd3\x1b\x05\xa5\x19;]Vb\xa4}\xaf\xfb\xc6ۇu\x06\xe3#\xb9\xc1S\xd1Iv\x0fK?\xe3\t\xf6\xb3G\x9dQp\x82\x99\xb5\xbcP\xed,=*\xfe\xc8̖~2\xfa\xac\x94\xe9\x8d\aǧ\x03\x18X\x83\xa8-`k\x8eȨo\x9dR\xad\x89\x196.\v\xaf\x8b\xaf\xbd~\xf7\xee\xed\xd3\xf3\x9f\xc5\xfdEl\x8b\xa6B\xf9\xd7\x1c\xedy\b\x96\xd3Y\x9b\x80\x80\xbd'\xeb^\xc0\xf0\xe5\x9c%\xaca\xb1x\xfa\x85\xc9b8X6\x12\xc7\u009b\x1d\xff\x87\xf8\xd3㞸ǀ\x14\x06\x04\xec=\x01\x01S\x89'\xe2\x04\x8a\xa9xS\xfe\x80\xf5\b\b\xd8{!x\xb7\x01\x15\b^\xd1_\xeb{\xd4wM\xff\xd5\x02\x17\xaa\x00\xd6\x03 `\xef\x05\xf3nOb@\x05\x82õ\x06\x9d\xa1v\x18\xf4\v\x88\x00\x02\x06\x00@\xca\x02\x02\x06\x00@\xca\x02\x02\x06\x00@\xca\x02\x02\x06\x00@\xca\x02\x02\x06\x00@\xca\x02\x02\x06\x00@\xca\x02\x02\x06\x00@\xca\x02\x02\x06\x00@\xca\x02\x02\x96\"\f\u05fc\x96\xed{\v\"\xeb\xd8\x03\xc0zEm\x01\xf3t5\x9b,\x03\xbe\xa8\xa4o\xe0\x96\xe9\xd6\xc0\xca,\\>\xb9I\xb2\x86M\b\xef\xb1-\xe9{\x17\xbf\x00\xcb_\xaf\x95\xe9k\x170S\xbc_'.\x18\xa3[X\xfci\x1a\x81\xba5\xaaކ\xb4\x0f\x1eC\x1c\x00R\r\x95\x05l\x9a\xb7:\xdd\xce6\xba\x8a\xa1$\xe9kj\xa3ɦ\x95Q\xb0\xc1\xd0Z\xcb\x12vm\xb9~$}\xf1\x97s\xfaP\xe7Eai\xaaGO\x12\xd9\xdd\xe1\xec\xf6N\xae\xc3n\xdf}'\xae\x8d\xac\x86N\x16\xc8G\x9ek\xddx\x15\x03\xc0\xfaFe\x01s\xb1\xb5\xef}\xbcS\x96\xb4Y\xe82N\xf3\x16[\x92\xd2\xcbD(du\x04/\xba\x8a\x03\x8b\u05ef\x1f\xb8N\x1cd\xf1Zq\x8d4@E\f\x1d:q!d}L \xcb0\xd2\x1a^\xe8\x1a\x15r\xcfh\x12\xac\u007f\n\x00\xeb\x01\x95\x05L\x88\x94\xe8\xe5=\xb2d\x8f\xe0\xceiO\x14\xdbv\x19\x89\x150\xd7\xd2\"\tF\x16\xee\x97G؉a\xee\x85(`/\xe2\x04S\xc2\xf2\x1a\xae\x18f\x15r}\xd9\x15\x18\x00\xd65j\v\x18a\xc6m\xb1\x06dIoS\xaf\xd7\xef\xb55y\x13\x17\\\x06<\xe5\xd9Y\a\xc4!dSAFn5QU\xbfVXu\xb9Z\x96;\xbe\x11\xa13\xae\xf2\xad\xe9{d\x8b~\xbe\xbd`\xd0\x1d>KC\"͕\tn\xad\x9b4r\xab@\r\xb5\bޯ)\xae\xbcI\x04虎\xe3\xbeyq\U00068f96\x06s\x8d\x84\xa2\b\x1b`l\xaf=\xac+\xab=\x1c\x94׀犅\x0e\x98<\x97t\xc1\xd2g0\x00\xacgT\x170/\xcf\xf3f_Tr\xa6\x9b$\xbbԿ\x1b]\x99\xb9\xe6\xf6_ \rMW\xa4\x1d\xb7^\xd5\xe6\x13=}hkAu6\x9bG\x96;ciޚ\x9b\x99S]\x8ed\xe3\xb6a\xee\xabG}g9\xb6\x92;\x8b<B#\x8c\xccN\xd8+\x8dv\xbb\x9d\xad\xe1\u007f\x85\xbb1\xd2y\xa8*\x88\xe7\xfa\xfa\x0eW\x16\x1bn\xd6\xeff\x91\xc3\xc2\x02\x166\xc0Ow_\xec\x1f\xbbWƽ\x93׀\x9frv\xb6\x95\xe7b<\x00\xd1v\x80u\x8e\xea\x02\x86\xbd\x1e\x87\x18\x8a(\x9c\xf4w[\x9c\x1e\xa7\xa5[yA\xf3e\xe4\xd3m>\x1a\xddL\x83i813\xa6\x01\xb8X`\xe7\xf0\x10R\x96\x9b\x8fv\xf9đo\x98\xd9>\xd2u\n\x9e8\xcfv\x94\x86\x90\xc3\xcc\xfd\xfeX\x88\x16Vŝ~\x8b\x83\u009a\xee!\x01\x93\x18t\x1e\xa2}\xb3Β\xe80\xaf#\\H\xb2\xe4CS7\xba\x85\x01`=\xa3\xbe\x80a\x1a\f\xb2[\x96\xb4Y\xfc,\xa9v\xf0+\x1fb\x91m\xceh0\rp\xe8\x9f'\xe40\xb7RX\xc0d\xb9\xf9JN\xf3W\x9d\xb5GK\xb8\x13,\xad$`\xf5G\xe7\xde\x11\fWXn\xd1\xcbp\xc1\x90\x80I\f^\x1a\x8e\u07b8\xf748'\xaf\x01\xe3~\xeeE(\x19%`-\x18\x00\xd63*\v\x98_p~\x8d\xf3\x01I2`zȒB\x90n\x15y\x80\xd8s\xcfs\x1a\xf2\xb2]\x8c7Ƃׄ\x05L\x96\x9b\xbf#\xb6\x8aLJ\x0e7\xf6\xdbO\xc7\x17\xb0\x13\xa2\xdf\xea,\xcb\ry\xafpD\xc0\xa4\x06o\xef]\xa8\xe4\xca\xeeD\xf7\xc0&\"\x91[e\x026\x04\xf1\x0e\x81u\x8e\xba\x02\x16h\x12\xc2\t\x12\xa9\x92&E\x01\x1bU[\xc0\xbc\xe8:\xdd0'~\xf9\xb6Q\x06{\x90\x10\x160Yn\xfe\x81\xd8**k\xa8\xf7\xfd\x82\xb2\x80\xdd{I;XO\x18\xaf¹\"\x91\x1eX\xd8\xe0q#\x91\xae\xb7}\xfaNY\rd\x9c\xca\xc2S\xcb\xeb\xa5\xd4i\x16?\xd5\x03\x00\xd6\x12\xea\n\x18nfa\xe9\xfd\x96\x1eY\xb2G\x1cB\xaa>\x8d\xa2 \x87(\x93\xeb'\x1a\x92\xecB,\xbc\xe1\x17,\xc8PX\xc0d\xb9\xf9\ack8L\x05%X\x15#`F#Ư\xa9_kL\xf0~5ަ\xafJ\x02&1h\xe5X\xc40\xe35Y\r\x84\v\x95\xa1i\xf8\xd2\xdc@^(85\x00\xacST\x160\x17\xdf\xedt;\x99\xe7^\x92\x9ci\xb18\xdc\x0eK\x8b\xea\x8f!\x1d\x199ug\xb2\xd26\x9a\x9d\x18\x9fB\xa5\x96\xf6\n\xd4\x14z\n9Ⱥ\x83\xe1\xdc\xf9A[n\xa1\xcd\x16\x1d\xc0\xa3\x95\xbb\xd0y\xbb\x8a\f\xfb&ħ\x90\x13\x82Դ\x16u\xf4\x9f.\xa6=\xa5\xc6\xdd\xf5\xfd\xdf^!\x9a\xf3\xeeO\xec\x19\xa2\xe8\xcez\xda\xc9u\ba\xaa\xc3\x06\xa4\xb2\xe2\xd6\xe1\xfe+\xdc#y\r\x18?\xe7B3\xf6\xa5\xb9\x97\xd1(\x06\x80u\x8d\xca\x02\x86==\x16S۠?*\xe9\x1fj3\xb7\r\xf9\x13\x17]\x0e\\\xfb\xb2\xb6\x9e4oD\xc7H\xbak\xa76\xebӻ\xe4b\xb2\x98\xdbk\xa3\x93Y\x84r\xc7\xd3Xnt\x9f'\xd8QYt\xa8\xfe~\xa5\xce8W\"\xfc\xbaQx`8w\xe33\xbdQ\x10\xa8\xb1\xd3e%Fҵz&\xf8\xbajY\xe6l1I\n\xbf:\n\x1b\xe0\xfb\xc6ۇu\x06\xe3\xa3\xe8\x1a\x88n\xe9E/\x98$ז~\x12\x03\xc0\xfaFm\x01\x03\x96D\xf0\x86\xae/*\xabES\xa1\xfa\xb4\x13\x00Xe\x80\x80\xa5\x06\xc1\x0e\xc3+Y\x867\x1b\x16\xa3\x00\x00\x100\x00\x00R\x16\x100\x00\x00R\x16\x100\x00\x00R\x16\x100\x00\x00R\x16\x100\x00\x00R\x16\x100\x00\x00R\x16\x100\x00\x00R\x16\x100\x00\x00R\x16\x100\x00\x00R\x16\x100\x00\x00R\x16\x100\x00\x00R\x16\x10\xb0UG{\x81\xfaљ\"x\vړ\x99\x00\xc0\xaaAm\x01\xf3t5\x9b,\x03\xbe\xa8d`\xbc\xdd\xd4\xe6L\\r\x859\x86\xd2,\xc9l\x16L'\xc7E/.\x11\xa6\x01\x9d\x93\xed\u007f\xd0\x13S\xba\xb5\t\x83^6\xa4\xc1\xafā\x94Ae\x01\x9b\xe6\xadN\xb7\xb3\x8d\xaeb(I\x06\xac\xe6Q\xf7\x03Ӄd\xa5W\x12\x8fmS]2\x9b\x05\xf3\xd6^ӊ\x95\xf9M\x9aY\x9e\xb1\xf4\x13\xf7*\xafwh\u0378\xa5\x98\x1f>\xbe\xf1j\xc2\xe3\x00\xb0zPY\xc0\\<\r\xec\xe3㝲\xe4C\x13\x1d4\xb9L\xab{\x85w\xcd\x12uD\x91\xb3q\x04lRs*&o\xa9'\xdeQ\xaa\x9c\x9f,\xf2\xc0\x19\xa5\xe8K\x00\xb0\x1aQY\xc0\x84\xa8\x8a^\xde#KZ\xd9\xf2\xf8\xb8\xe9A\x9cB\xab\x83\xa5\xea\x88\"\xf1\x04\xac\";Vŗzb\xa55\xfc\x17\x82/\xbb\"\x99\t\x00\xac\x0e\xd4\x160\u008c\xdbb\rȒm,\xba\x19n\xbf\x9b\xa0\xd4r0\xbe\x11\xa13\xae\xf2\xad\xe9{\xe8ڦM\x05\x19\xb9\xd5L>l{r6i\xf7ne6\xae\x03\xdaM[\xf6zHJs\xb2:7cOl\xe7ļ\x85E\x97tg\x8a!\xd82%&\xef\xcat\x8d\x06ã\x1b%\xc6Y2p\xbc`\xd0\x1d>\xfb\x8c\x1d \x02v\x83.*\xfd\n\xe3\xe0\xfd\x9a\xe2ʛ\xb3,۟\xf9y\xa8\xa8҉}\a\xb359\xfb\xc61\xf5\x8cm\xe2\x95.'|\xe9V\xf1j\xf2\xe5\xcd\xf4\xa5#\x94\u058c\xa3k\xf0\x96ksN\x9e\xd4n\x16\xbcmg\xd2U\x8fN\x00\x00KBu\x01\xf3\xf2<o\xf6ɓ\x03M,*\x91\xb9-a\xc9\x0fό\xa5yknfNu9\"wqE\xdaq\xebUm~\x80\x86[<r\xab\x9b\xd7\"\xaaj\xbd\x9b\xf3\x1b\xbaϡ\xcb$\xa9Ay\xcd\xed[bC\xab\xedG{\xe8\xc6o\xbe*`\x96\xae\xed\xff\xa8\x84\xbby\x9a+\xbb]\xd6Acp\u007f\xf5\xa8\xef,\xc7V\xb4'\x02\xf6}\xbd\x10\xd6\xe3\nwc\xa4\xf3P\x15\v\x062\x8azł\x8a'\xb6\xa2\x8a^˾\xb4!\x8c\x9d\xcd\x1b\x91\xb6\xeeRf\xd4\xe5D.\xdd7\xc0\x82\x90\u061cQ\xcd|`\xb3\t=:i\r\xfe\xbc\xec\xaf\xcfi\xd2M\xbf\xb8\xccj\x19@\x83\x18\x00R\x01\xd5\x05\f{=\x0e\x16\x8aH\x92\xf4\x99\xad\xde\x19O;\xffa\x9f\xb6-\x88|\xb4\xcb\xc7F\xb3VD\x9d\xe7C4\xd6\xf5u-\x95\xae\xaf\xb3\x88\x96\xcd\xe4\xec\xf1Ӏo\xd4G\xa7\xd9B^+\xb41UL\xd6\t\xa1\x8a\xa6'\x05\xa6eG\r\x17\xf1\b7\x8c/~\x85\xf1l\x1f\xe9f\x05O\x9c\xa7\xd9D\xc0:\x8aX\x10\xb6a\xee>\xa6A\xd6\xd8cI+\x12\xc3\x1e)\x9f\xd8g\xa1o\xdc',̮&\x8b\xc8Qy\xd4\xe5H.]6\x84\f7\x93\x92.\x0eI#5\xb4 ҫ\xfb\x1a9Dk7\xba\x85\x01 \x15P_\xc00\xbd/\xbb\xe5I\xaf\x95t\xc6\x06\xad+0\x03)?\xe4\xb0.\xdd\xe6\x9f'\xe4T\x90\xfb7{\xeb?\xf3\x0f\x03\xb4#u\x17=\f\x9bj\xa8g\x88E\xf1Vd\x12\x85\x90\r\xeb\f}D\x9cfqc=I\xbf\xea\xac=Z±\x18\x92g[[\xc5 \x92\xf5G\xe7\xde\x11\fW\xe8N{H\xc0\xe2\x9c\xd8{}϶L\xb4\x9d\xe5\x1e\xc1\xb1\x97#\xb9t\xb9\x80I\xfd\xf2a\x01\v\xd7p*\v\xd3`\x98\xa1\xf7\xdfMe\x1c\x00R\x00\x95\x05\xcc/8\xbf\xc6\xf9\x804I\x98\xf1\x06p\xd3@\xfc\x82\xcbE\xfe\x0e1\xb1]T\x1fڻ\xf1\xf1\a\xf3\xd0\x16:\x1d\xea2\x8ax\x834t~V\x9d&\xb6\x0e\x11\x9bU\xc0&\xcb5\x8c\xe0\xc7:\xcc\x04\xec\xf1\xa1Í\xfd\xf6ӂ\x80\x1d*\xa9<\xcfF\x8d'\x84hk\xdcY\xba3\x18\x1a\xbc)\x9fxhK\xce\xe7m\xb6\x9d\xdb\xe5\xb9R\"\x97.\x17\xb0\x1d8BX\xc0\xc25\\F^\x1a\xc47\xd4\x03\x1bB+\xf0I\x00\xc0\x12PW\xc0\x02M\x82\x8b\xe7\xa1) Ib\xcc\u20f9سI\x95\xc9\x0f9\x91ʷ\x8d2ȝ\xfc\x80\xced\xf0\xb5\xa4_ǸG\x12;\x96\xb9\x8e\x12\b\x982\x861\xfc\xb8H\x10\xb0\xca\x1aꩿ \n\xd8ԋ\x92\x0e\x9a\xaa?\xfa\x84\xc1\x82\x0e\xf94\xe2,V\xe5\x13\xe7\x15\xd0Q\xe0\x81\xed\xf2\\\t\x92K\x17\x05\xccĺ^\xf9R_YX\xc0\xc25\xb8\xd3\xf6\xba\xc7s\vB\xf3+\xea4\xab{B\v\x00\x84PW\xc0p3\x9b0\xe1\xb7\xf4ȒN\x9eȆ\xaf9\xe4\xbfV\x93p/\xa5\v1\x0f\xdc\x17䦮C\xec\xd2\n\x8f\xd1\x19\x05\x85t8v\xbc\x1a\xc7\x170wCt\xb8n)\x12\x01;|\x81\xec\a\xab\xc4!$\xc6#:\xea\xc3\x1f\x13\xbc_\x8d\xb7\x99y\xe96AE\x94O\x9cCu(\xb0=\xbe\x80I.\x9d\xbc\x16b<-4K6\xa3\"V\xc0F\xd1\x16\x84vz\xc4ぼ\xe8\xf0\xbd\x00\xb0JQY\xc0\\|\xb7\xd3\xedd\x9e{Yr\xc8\xfd\xb0ɪ\xfa\xd7\xfe\xfc {R'\xe8\xcf)Tji\xaf@MT\x056\x9f\xb3\xb6U\xb0\a\x82\xbd?ɻ~\xf782\xd1\t\xf1G\x06\xf1\xe8\x91M6OT-\xfbb\xc2uK\x98\xfa\xacc\xb6O75[\u007f\xfa{\xdc\xca]\xe8\xbc]ŕݙxk\xaf\xf9rbn\xb6\xd6\xf0\xe85\x91\xae\xdd\xf5\xfd\xdf^\x11\u007f[\xe4J\xbb$\x14T<q\x1d:x\xbd.\x1fi\x1b\x06\xe3\\\x8e\xf4\xd2\xf19ͥ\xf6]\x19nY3\xfd\x836\x9b\xe6\x88\xcd\xe6\x93\xd5;\xaa\xe9\xb1\xda<\xa1\x0e\xd8e\xa4<\x85\x1f\x00V\x1d*\v\x18\xf6\xf4XLm\x83\xfe\xa8\xe4\xa8\xc5l\x1dM6A\xfc\xc33\x9e\xc6\xdc^\xa2\xfet\xed\xd4f}J\xa7\xa25\x15\xd6\xe5l\xca.\x14:\x84\xae\x839\x99\x05mt\xda\x14B\x9b\x1c\x19\xe4\xf5XT-f-\x8f\xe3\x11,㸾b\xae\xb8\x8f\xe3\xce\xe3`Geѡ\xfa\xfb\x95:c'uz=%\x99\x1c\x9d\xcf:v\xba\xac\xc48\"\x968\xf3\x13\xd1\xff\xa4t\xe2\xc0\xe5\\\x8d\xb6ԼMS\x18\xe7rd\x97\xee?\x9e\x95^8$o搐F\xbc\xac\xde\x01\r\xcd\xdbTȜ`\xb6\xf4\x93\x18\x00R\x03\xb5\x05\fHF\xb5F\xf5\xd9$\xde\xcdǼ\xf3\xf3\xbe\xa1\x03Y\xa4\x13ܢ\xa9\x98OV\x00\x00V\t `\xab\x8e\xcb9\xf2\x99d\xcbO\xbb0o\f\a\xb4w\xb17\x1b\x16\xa3\x00R\a\x100\x00\x8f\xa6\t\x13(\x1ci\x91\xc9g\x00\x90\n\x80\x80\x018P\x91~\xac\xa5\xb7\xe5X:\xfc\x88\x1bH1@\xc0\x00\x82uO\xb6&{O\u0085\x0e\x01`\x15\x02\x02\x06\x00@\xca\x02\x02\x06\x00@\xca\x02\x02\x06\x00@\xca\x02\x02\x06\x00@\xca\x02\x02\x06\x00@\xca\x02\x02\x06\x00@\xca\x02\x02\x06\x00@\xca\x02\x02\x06\x00@\xca\x02\x02\xb6\x9ai/\xf0&3\xf9 x\vV`5o\x00x\u007f\xd4\x160OW\xb3\xc92\x10Z\xf9\xcb\xc1\x8b\x93\xbf=\xed\xe6.O\xbc2+\x87\x99\xae2\xa3ݳ\x9c\xcbcur\xe2J`\n4\xa0s\xb2\xfdc(m\xc1+U$\xb7=Bږ\xe1\x12\xd2\ri\xf0\x13n \x15QY\xc0\xa6y\xab\xd3\xedl\x13\xa3\x12\xf9L\x03M,\xe16\xd9\\6\x93,\x18Ɗ\xd2+J\x96ό\x1az\xcd\x05\xe1Xg\xcb\xc0[{M\x9c\x18\xb7\xf87ify\x86Ƕ\xa9N\xd94\x96\xe4\xb6n\x9b\xed\xebp\xfc4\xebƫ\t\x8d\x01`U\xa2\xb2\x80\xb9x\xaaR>\xde\xc9\xf6\xac=n&`\x81f\xba\x88\xdf@\xb3\xfaK\x1a\xc6aG\xa9\x98p\xd0%\x9a\x03\x9f\xe6&\xb4~O\xe2\x05\xe9\x9eԜ\x8a\xc9[L\x90\xee\x05\xd8\x0eE\x02@\x9eѬ\x9e\xef\x0f\x00X(*\v\x98\x10\x9a\xd0+\x84\xefp\x98}\x1e&`N\x13\r\xc1\xe339\xe3\x97S\x97\xf0\x12\xf2L\xc0\xf0o\xd0r\xaev\x1dO\xc0*\xb2cϺ\x00Q\n\xb3\x00[\x89\x80\xf9\xb2a)\n \xf5P[\xc0\b3n\x8b\x95\xf6\xb5|&\x17\x16\x04\xac\xe7.;pw\x19Gjq\xf0\x96ksN\x9e\xd4n\xa6\xee\xa2\xeb\xf9\x19\xdbi4\x1f\xab\x18`-\x1f\x87\x04\xac<\x87\x197\x15d\xe4V3Q\xf1}\x9e\xb7\xb9p0\xe7ntu\xe6-luiw\xa6XE\xa6\xa4W\xf3\xaeL\xd7h0<\xbaQb\x9c%\x03\xc7\v\x06\xdd\xe1\xb3\xcf\xd8\x01\"`78\x8eӿ\xc28x\xbf\xa6\xb8\xf2\xe6,\xcb\xf6g~\x1e*\xea:\xa0ݴe\xaf\x87\xa44'\xabs3\xf6\xb0^\xec\xc1lMξqL\xbd]\x9b\xf8P\xae\x14\xcd\xf1\x8a\xec\xac}\x82\x93+\xd46yR*`\xf8Lz$\x90\x1b\x00\xa4\b\xaa\v\x98\x97\xe7y3S\x01k7\x16\x05\xacMX\x06~@\xf5Ga\xfe\xbc\xec\xaf\xcfi\xd2M\xbf\xb8\x8c\xf1\x11\xcd\x19\xeb\x19M9\x91\x86\x01\x16\x03\xc3F\xfb\x83\x0ed\xf59?G\xac/S\x91v\xdczU\x9bO\xb4\u05f7M{\xe9\xee1\x84B:\x10f?\xdaê5_\x150\xfb%\a\x1f\x95p7Ose\xb7\xcb:h8\xee\xaf\x1e\xf5\x9d\xe5hT\"*`\xdf\xd7s\x1d4}\x85\xbb1\xd2y\xa8\x8aŋ\x1c\r{\xdez7\xe77t\x9fC\xe4\x1a\xb1\x06\xe55\xb7o\xa1\xb1\x89\xac\xa8\xa2ײ/m\x88\xf4_\x9b7\"mݥLi\xe44\xccl\xf3[Z\xb6gе\n\xc3m\x93%\xe5\x026 I\x03@\x8a\xa0\xba\x80a\xaf\xc7\xc1B\x119\xa9\x8c\t\x02\xd64Ď\f5%,\xb8\f\xb4 ҅\xf9\x9a\x05t\xedb}\xad.\xc4zU\x92!$\x85\xdd\xeeVD]\xeaC4huy\x96\x87$\xabc\x05l\xb2N\x88p4=) _\x1b\xdap\x11\x8fp\xc3\xf8\xe2W\x18\xcf\xf6\x91nV\xf0\xc4y\x9aM\x04\xac\xa3\x88E\xe9\x1e\xe6\xee\x93\xd7\xc7\xc2cIk(H\xf7L\xce\x1e?\x8d?GgTh\xb6\x90\xd7\n-I\xf9,\xf4[\xe0\x13\x1a\x87\x17k\xb2H\xef\xab\\\x8b\xe5h\xf2H\x97j&\xb7@\xd66Y3e\x02\xe6F\xb70\x00\xa4\x18\xea\v\x18\xa67c7\xf5x\x05\x02\x01wS\x80\xf4hڄ`ֽmI\xca}pNe\x91\x17\x17\xa2=\xbf\x8aOXN\xde\x11\xfa*\x11\xb0K\x83ւt*%\xa5\xdb\xfc\xf3\x84\x9c\n\x1c\xc8`\xb3\x1b\x9c\xb1\x02&2\x89BȆu\x86>\"N\xb3,D$~\xd5Y{\xb4\x84\x13CD\xb6rL\xbfp\xfdѹw\x04\xc3\x15\xba\xd3\x1e\x12\xb0\xbb(\xb2г\x86:\xaa\xceih\xd2{}϶L$\x84\x88<\x12Ε\xa0\xf9\x82\xbe^G^i\xdbd͌\x12\xb0\x16\f\x00)\x86\xca\x02\xe6\x17\x1e4\x8e\xf3\x81I>\x84\a\xf7\b\xb3\xc1\xda{\x12\x15]\x0e.\x93\xbb\x9btGh\x0f\xec\xd3},go\x01}\x95;\xf1}iԳ\xb5]Ԥ\xfd\xe4VgJ\xeb\x8b+`\xd8f\x15\xb0\xc9r\r#\xf8\xb1N\x88q\xfb\xf8\xd0\xe1\xc6~\xfbi1HwI\xe5y6j<\xc1\t\x9c\xa5;\x83!q\xb9\x8c\"\xce)\x16\xb8\x9bŢ\x1dڒ\xf3y\x9bm\xe7vy\xae\x14\xc1\x89oC\xa3Ҷɚ)\x13\xb0!4\x80\x01 \xc5PW\xc0\x02M\x82_\xe7\xa1)\x10\xf0R\x1cf\xaf7\x80\x9d<\x1d\x0e\x85&W\xa8\x88;m\xaf{<\xb7\x80\xaaj\xc56\x96\xb35\xd2\x03\xa3\xf3\xd2\x04'~&\x15\x88\xf2m\xa3\f/\x0e\b\xa1\xad\x1d\xf1\x05L\x19I\x90\xee\xca\x1aꩿ \n\xd8ԋ\x92\x0e\x9a\xaa?\xfa\x84\xf1\x8a\xee\xf84\xe2,\xd6\x1eI\x9c\xd9H0\xed\xbc\x02\xfa\x9e\x1d\x88\x1f\xa4\x1bkhTolB>i\xdbd͔\tX\x9df9\x1f\xb5\x02\xc0\xb2\xa0\xae\x80\xe1f\xaa\ad\b\x19\xeaky\xc4y`T\xd7z՟\a6\x8a\xb6 \xb4\xd3C\x93V6\x82jA\xac3XX\x88\xf14\xb2\x84\x04lK\xf5x\x1d騱\x99\xed_\x10\xb1(\xd5R\u007fTy\xac\x80\xb9\x1b&\xa3\xb3$H\x04\xec\xf0\x05\xb2\x1f\xac\x12\x87\x90\x18\x8f\xe8\xa8\x0f\u007fL\xf0~5\xdef\xe6\xa5ۄ\xf7×]H\x9f\x05\x1c\xa7z\x14\x91\xaa\x1c\xea\xb3\x0flO$`9\xd4u\x96W(k\x9b\xac\x99R\x01\v\xe4%\x88/\x0e\x00\xab\x14\x95\x05\xcc\xc5w;\xddN\x8b8\x13?\xe0q\x98=T\vܦ\xde\xc9\xde\x15\x98\x89?\xaa\xe9\xb1\xda<\x82N\x94\xa7\x9d\xb2\x9eJ\x13\x1eϝ\xd3\\jߕA\xaeg\x9cy\xbbw\xee=\xf2\tƧP\xa9\xa5\xbd\x02\x11\xc9\xf5d\xe7\\oۯ\x89\x15\xb0}(\x81\nL}\xd61ۧ\x9b\x9a\xad?\xfd=n\xe5.tޮ\xe2\xca\xeeL\xbc\xb5\xd7|917[kx\xf4\x9aH\xd7\xee\xfa\xfeo\xaf\x88\xbf-r\xa5]\x12\n\xf6\xfe$\xef\xfa\xdd\xe3\xc8Dg\xd7\x1f\x19ģG6\xd9<\xb8\x0e\x1d\xbc^\x97\x8f\xb4\r\x83\xd2\\)\x1a\xb4g\xb0\xa7 \x8bJ\xaa\xa4m\x91$\x9b\x89\u007f\xd9f\x13\xde\xf6\xcbh9\u007f0\x05\x00˃\xca\x02\x86==\x16S۠8\xbb\xc0C]`\xcd,\xd5ej\xf7$(\xb6L\fh\xa8WkS!u\x82\x05~\xb3=c\xfbׂ\x98\xf9\x8fg\xa5\x17\x0eal!G\x1b\x88\x8c\xe5ji\x8f\xa5k\xa76\xebS\xf6\xf8\xce[\x91\x93\xbe\xebA\xac\x80\x99\xb5|tV\x98`\x19\xc7\xf5\x15s\xc5}\x1cw\x1e\a;*\x8b\x0e\xd5߯\xd4\x19;\xa9\xd3\xeb)\xc9\xe4\xe8|ֱ\xd3e%\xc6\x11\xb1ę\x9f\x88^)\xd7\xc1\x9ĉ6:\xe3\x8b\\\xac#\x83\xbc\x1eÁ˹\x1am\xa9y\x9b\xa6P\x9a+%\xaf\xee`fv\xb9\x87&%m\x8b$\x8f\x88N=\xf6\xab\x03[\xfaI\f\x00)\x87\xda\x02\xb6\xaa\xf0n>束\xf7\r\x1d\xc8Z\x8a\xfb'\x81\x13\xff\x03Q\xad\xb1$3\xf9@\xb4h*\xe6\x93\xd9\x00\xc0\xeac]\vX{\x96\xd0\xe1\nhc\xe6\xd4/\x80\xe5\x170|9G>\x93l\xb9\xf0f\xc3b\x14@J\xb2\xae\x05l4\xcd\xc1\xb6\x8e\xb4\xc8L\xab\x85\xa3\x82\x80\x01\x00\x90q~\xef\xa6\x00\x00 \x00IDAT\x90u-`\x81\x8a\xf4c-\xbd-\xc7җ\xf2;fW\x17\xaa\x1eT\xfd\xb9)\x00\x00\x12ֵ\x80alݓ\xad\xc9\xdecMf\xa6ħ\b\xa1\x8d\xaedV\x00\x00,#\xeb\\\xc0\x00\x00He@\xc0\x00\x00HY@\xc0\x00\x00HY@\xc0\x00\x00HY@\xc0\x00\x00HY@\xc0\x00\x00HY@\xc0\x00\x00P$\x15f9\x82\x80\x01\x00\x10\x8b\xa7b\vڟ\xcch\xe5\x01\x01\x03B\f\u05fcNf\xb2\xec\xb4\x17x\x93\x99(\xb1\xc4b\x80\xb7 N$\x9d@^\x1eߣ\xfe\x02W\x8bFm\x01\xf3t5\x9b,\x03\xa1\xc5\x1f\x1c|x\x12|\xaf\xea˱~\b\xaeq\xe2\xe2]\xcbǣݜ1\x88\xfb9n\xf7\xa3x&S\xb5\x9f\x95\x18\x1f\x9d\x98\x88w|a\xdc\xe1Z\x83\xf8>\xc7q\xb7\xf1m\xf2z/\x81\xe9\v\x1d\xf7K\xb2\xf9\x92F\x83{\x11\xdf̾[\\#[\xff,\xbe\x91\x8c\x06$.C\xfb\xd7ke\xfa\xda`b\xe3\b\xe1b\xb1\xd0\x06q\x9f\xd5>\x8dw|\xa9|\xc5qt\x15\xdd\x0e\x8e\xfb*\xea\xc8ءa\xa5\x02\x1f\x8a\x0fܠ\x864\xe5\xdf\U0004fce5<W?*\v\xd84ou\xba\x9dm₆>\xd3@S\xf8\xc0P\xfcR\xcbH\xef\xfb-\xe3\xf7\xbd]'\tK\xfb\xe8\x89RR\x82rnb\x83\xb91Nodz\xfd\xdc\u061cB\x01\xca\x13\xdd\xd9\xfe\xbe\xf3\xef+\xa5\x9d,$\xd2\xdb\xfb\xdc\xed\xd7\xf8\xf5\x1d\xee\xfe\xdb\x04\xb6\xc1\x89/\x8b0m\xbd\xbd\x93K \x9bs\x13\x87j\xed\x84\xfb\xdc\b^\x10\xbfI3\x8b\xa9Ӈ:/\xea\x13]\x82\x94H\xb1Xh\x83\x1eݯ\x89\xaf\xfeK\xe4e\xf1\x9d\x1f\xc8\xe6\x87;\xc5/\xa3\x8e\f\x17\xf7\x8b\xa9\xa4\x1f\xf7R\xf8 \r\x92\\\x99u\xe3U%\x8b!$\x0f\xe8\xb0ZQY\xc0\\<\v\xca*\xae~o\xedq\x8b\x02汬\x90\x80\xed(Mf\x91\x84\"\x89\x80\xd5\\PJJP\xceMb0\xcb]\xfc\x92tz\xb8\xd9\xd8C\x02\xb5\xa7IW%\xf8\xe5\xfb\t\xd8\v]#\xdbNqc\xe4\xf5\x117\x95ؼ\xb5H\xd8>N$`\x18\x1f\xbdF_\x9f/P\xc0&5\xa7\xc4\xd4\x0f\\'\x0e\xc6mp\x14\x91bJ\xb0\x06\x05\x8d\x95\tL\x96\xc4\t\xa1\x8bz\xefD̑p\xc71\xe9ǽ(\xbc\x85\xc20\xf9C4Hzeg4J#š\x14\t\x13\xaa\xb2\x80a\xd6\xf5\xf2\xf2\x1e\xbaq\x98}\u009a\xf8\xb8\x97\xef5\xad\x8c\x80\x85\xe3\x0f-\x15\xa9\x80U]PJJP\xceMb0\xcb=*\x9eM$`G\x99\xf4Lq\xa1/\xfe%q\xc5 Կ\x1c\x026\u05f9\xb0\xbeTEvȷ\xf0\x82[\xc40,RL\t\xa1A\x9d\xf1\u07fe%r\xfe\x1b\xb6i<\x1f\xdf$\xe9ǽ(\x1cHX\xfc\xe9C4Hze\xbel\xa5\xc5X@\xc0\xe22\xe3\xb6X\xe9\x03Z\x9f\xc9%\x06\xf5\xc03\xbePp[U\xb1\x8a\x8b*\xe7\xd3\x1d۞\x9cMڽ[c\x8c\xcc[\xd82\xd1\xeeL\xd18S\xfe}U\xd4x\xb3R_\xfb=\x8dJ+P#K^\xe3t\x9d_\x19>;\xfbB\x96K\xbeA\xef\xd7\x14W\xded\xff\x83\xf6\xdaú\xb2\xda\xc3A\xb9A\x84Y\xeeEU\xbf(`\xe1b\xad\x1c\x1d2\n+Q\xd7\x1b\xa8\xda\x04Gd\x06\xcft\x1c\xf7͋\x8bG\xf5\xb5凞\xe0\xd7\xeaS6 \xe5抅\x0e\x98T\xc0\xde^0\xe8\x0e\x9f\xa5\xee+Ҋ{b3\xc9\xc0\xb1\xdePr\xe1\xcbh\x01S\xaeW\x100,:\v\x05י\xac2\xfc\xe2B\x99\ue410\xf6g~β\xe6ʄ\xf7\xe1\xe6⊝#\x1fN3n&\xafg\xb0\x04\xa1A\xf5\x06\x9aVz\xd7%\x9f\x101\xe8\xac\xd1Wu\x06\xa3\xce\x16\xb6\x95\xd6\xc0\xc2{b|\xa1Q\xd6\xe2\xb7zN\x1c\xcb+\u007f\xdc\xf2w]\x81\xf1\x8d\xe4\xfa]\xe5[\xd3\xf7ȖȽ\x9aku\"\xa75\xf7z\xdc\x06\xcd6\xfe\xb2\xd88a\x18\x91\xbeg\v\xfb?;\x93\x1e\x89\xdb\x17\xa6\x17\x04L\x19/\xcf\xf3f\xf6\x8di\xed\x0eE%\xa2\xac\x84\x80\xf9\x06l\xb9\x856\x9b\x8d\x0eh\x87Б[ݼ\x16Ŭ\xac\xbc\x1f\xed\xa1\x1b\xbf\xf9\xaa\x80\xd9/;\\\xc4U\xf6\r\x97\x91\xaf\xe1\xd9\t{\xa5\xd1n\xb7?\x97%\xa7\xfat\xdc\xe1۷\x0f매\xb9\xa4\xc3\xc3\xdd\x18\xe9<TE\ue267\xbb/\xf6\x8f\xdd+\xe3\xde\xc9\r\"\x10\x01\xeb\xac\x15\x05,\\\xecu}\x8d}\x96\x940ֿ\xc2/\x0fs\xb5\xb7\xff$x\xc8\xc2\x06s}}\x87+\x8b\r7\xebw\xbf\x9c\xb5\x97\xb4\xbeƯ[KH\tE\x03R\xee)g\x17\xce6ō\xcc\xcd͍P\x01\x1b\xe6\xbez\xd4w\x96{,\xb4\xe2P\xeb\x9d\x12\xda\xdbxQRy\u007f\xb8\x96\x8b\x160\xe5z\x8f^\x99\x9b\xeb0b\xd1Y(\xb8Τ\x95\xe1G\xc55w\xc6Z\x99?\x1c\x8f\xa2^\xa1\xae\xa7\xf6>\xae\xd5n\xff\xcb\xe2\x8ayK\vl>\xf2\x99~Z*[Ɩ4h\xf6y#w[v\x91\x92w]\xf2\ta|\xb1蛑o\x8a.\xca\xcf\x16\xb1\x95\xd6p\xaf\x06O\x18&p\xd5=y\x8b\x1f\xdb\xedz\xd6)W\xfe\xb8\xe5\xef\xba\x023\x96歹\x999\xd5\xe5\xf2\xa0Ȟr\x94\x87>A\xa5\xeex\rz{\xf4\xb3\x8e\x11\xa2]\x9d\xd2\xf7la\xffg\x031Z5?ݻcIˬ\xab\x8f\xea\x02\x86\xbd\x1e\a\x8bJ\xe4\xa42\xb6\xb2\x02\x86%C\xc8\xebZ*]_g\xc5Lޛ\xac\x13B\xa5MO\nD-\xf2\\t\xe8\xaf\xe4\xdf\xe4\x10K+\x0e!\x8b\x8e\x92\xf1\xd3\xdb\xc35\xb2\xdca\xe61\u007fL\xbf\xab;\x0f\xd1\x1b\xa3\xb3$\x18UC\x18\"`\xaf\xf4\xaf\x98\x80I\x8a\xddg_\xb0\xf8\x04\xcd\xf8\xe1\xf6\xbf踒>y\xbd\xa42\xee\xf4[\x1c\xa4\xa3\xb7+\xf5\xe4\xa5\xfeJ|\x03<\u0089\xff\xceS\xe2\xd73\xb9\x9dg\xfb\xc8)\x83'\x98b\x14\x95\x90\xbe\xc8E\xdaLc%ˍ\x12\xb08\xf5\x1e\xa5U\xb1\xbe\x820\xd6\x16F\x9e\x91\xca\xe6\x0e\xd7\x12\xe1\x9d\xeb\xa3\xfep\xd2!\x0e\a\xa5\x8b\f!\x17Q̜\xc76\x9f\x84\xff\xa7\x18B\x83.ҷ7λ\x1e\xf9\x84FX\xe7f\x8c\xb9\xec\"g\x93\xd8Jj\xb0\x97\xe1F]#\xfe\x8c\t\xbf\xe4\x9d\xc4X\x1f\xf2*(}\xdcQ\xb6J\xe4\xa3]>\xd1\xd9\"\xa1k\x13\xda\xc4V>Wn\xd0Ez\xb9\xf8\x06\x110\xe9{\xb6\xa0\xff37\xba\x85\xe5\xec'\xdd\xd8%-\x92\xa7>\xea\v\x18\xa6q!\xbb\xc9\x00\xd2\x19\b\x04\xdcM\x01Q1VZ\xc0\xdc\xd9[\xff\x99\u007f\x18\x90w\xaf$L\xa2\x10QCH\xfa\x14]\xf4\b)\v\x18\x1b\x9bur?Hs\xeb\x8fν#\x18\x88\xa6\xbc4\x1c\xbdq\xefip.\xba\x860D\xc0pm\a\x130I\xb1g\xdc\xdc\xec\xfd\xb7\xef\x8a\xc4\t\nsc\xb5\xf4\xb6\x93\x18\x90ʊB\xdf\xf2\x8f\xf4\xa4\xb7\xa6\u007f\x84\xe3\x1a\xe0~N\x9c\x0e1\xc5\xddy\xfc\xf8q\a\xf3\x81\xbd\xea\xac=Z\xc21/5핰f\xbe\x15\xe6W|\x13%`q\xea=z\xf6\xf1㋱\x02\x16\xaa\x8c(\x86d:@{2\x01KRl<\xcd\xef3\xfb\xe65\xe3X\nm\xd0p\r\x9b\xed\x11\xe7]\x8f|BW\x04\x8f\xfc\x89/\xb1\xf4l\x12[i\rܬ\xf1\xa2q\x96cM\x95\xbc\x93J\x02\x16\xef]W&_\xc1\xab\xee\xad\xd6\xe4\xa0l\xcdIo\x9c\x06\x05\x85\x93NE\t\u0602\xfe\xcf\xdc,V\xa8\x14w\x17\x9f\a=0%\xfc\x82\\\x8d\xf3\x81I>\x84\x87e\xad\xb4\x80a\x1f\u007f0\x0fm\x89\x1f\xdc\xc2f\x15\x88z\xba,\xb9\xc1\xe2\b\x18\xfbϲsO\xa4\xb9'\xc4~\xceY\x92~{\xefB%Wv'Q\x0f\f\xf7W1\x01\x93\x14\x9b\xd3Mup\xad\xcf9\xf2\x0f\xf9\x989j\x82Ƴ\xf2zqUؙ\xf6\xee\xb3~\xdc_\x16\xc4q\r\xf0Dh((\xf1\x81=>t\xb8\xb1\xdf~Z\x10\xb0P3\x1f\vc\xcdh'~\x9cz\xa9\x0flJx\\'U\xa2p\xb2\x83\x93\xcc\r\x19\x8c\fe\x94\x05,I1\xff\xc6\xf1\xcb\xe8_\x9di\xf2/!\xd6 Av\xe3\xbc\xeb\x91O\xc8\xc8.\x1f\xd7\xd6`ى#\xb6\x92\x1a\x82ES\xc5ϊ\xa7t\xc2\xe7&\xf5[\xc6\nX\xbcw]\x99\xfc\x1d\xb1y\rZމ\x9c\xbf\xd1\xd6\xc5i\xd0\xf7\xc2#\x9c\xd9(\x01[\xd0\xff\xd9\x10\x1a\x88>\x1d\xf9wG+sC.\x16u\x05,\xd0$\xb8+\x1e\x9a\x02\x01/\xc5a\xf6z\x05M[I\x01\xa3!u\x1f\xd0G\xf1\xbe\x96\xf4\xc5\x06\xea\x88\x11\xb0{/\xe5ɢ\x1bt\xff\x1e\xf7V\x9a[\u007f\xf4\t\xe3\x15\x91\x80F\xea\xc1\xe8\xd3wF\xd5\x10\x86\n\xd8l\xf1\x98\xd0\x03\v\x17Õ}\xa7\x8d\x95\xfdt i`g\xc0\x8d\x95r\x03\xe9\u007f\xe9\x8d\xf3\xf8<\xb3\x8ag0\x1bz\x9a*\x11\xb0\xca\x1a\xeav\xbb \x17\xb0\xbf\xb2[\x04_\x8c\xe9\x81)\xd6\x1bv\xe2\x8b5|\x13\xa5Dc\x9cd\x8a\xabO\x13\x9e\x8e\x1a%`\v,\x96\u05fc\xf3Ӽ\xf6<,ChP\t-\x1b\xe7]\x8f|BW\x8e2G\xfdQ\xda\xf9\x8a\x9cMb+\xfb\x00\xee\x18\xb0\xa1\xa3\x92\x9dD&\br\x01\x8b\xfa\xb8\x95\xbf\xa4d\xe4\x1fP\xc8\xf4\xb3\xa7\x90T\x9b\x15\x1b\x14\xd43\x9f\xd8\u007fD\x04\xec\x9b\"\x1c\xb7\xc5\xf2\xff\xb3:\x8dBg\v\x9eB*\xd2̦\xf7\xfa-=\xe2\xfe\x8a\xfb\xc0\n\v1\x9eF\x16\xf2)\n3\x8f\v\xe5\xc1a\t\xee\x86I\x9c\x00\xa9\x80\x19\x8d\x18\xbf\x16\x1c\x1d\x91dQ\x19\x91\x81٣FY\xee\x98`\xd5x\x9b>Od\x93\xa4\x8cעj\b\x9f\x98\n\x18\xbeXO\x05LR\f\xd7\xdfЍp\xd7\xe8?b\x99\x81\x0eO\x83\xf4\x9fRj \xbdS\xfe\xa4\xff\x8b\xfeO4\x11\xcf\x00_\xa8d_\xcdR\x01;|\x81U+\x170\\s\x98\x9c\xed\xb9>J\xc0\xe2\xd4+\x110=\x19\xa8\x05\xff%J\x89f\rFڗ\xba!Hp鶀h\x1c\x11\xb0\xc5\x14+\xfdgM\x17:\x165\xb3OhС\x1bS\xb7\xe3\xbd\xeb\x91Oh\x84\x19\xf4\t>\xb0\xf0\xd9$\xb6\xd2f\xd6\u0590o\x05c-;\x89\xb2\x80)}\xdcr\xdb\xc9:\x85\x89\xd4q\xa6\xf6\xb8\xb3\x84\x91\xa5r\x83.\x94\x11\x91\n^d\x02\x16y\xcf\x16\xf2\u007f\x16\xc8\xdb\x1bs.\x10\xb08\xb8\xf8n\xa7\xdbi\x11g\xe2\a<\x0e\xb3\x87\xceΛ\xf1x̽\x1eub \xca9\xa7\xb9Ծ+\xc3M\x05l\xf39k[E\xe8AX\x84}H\xe9\xf3\x15\xf9\x8b]\xf7\xe5D\xf0\xe9\x97:\xfaȌ\xfc\xbbw\xf4\x9f\x16ffG\x92E\\M\u07fdʒ\xe7\xf2\xdc\xc6\xdd\xf5\xfd\xdf^\xa1\xffB\xad\\q\xebp\xff\x15\xee\x91\xdc |\xe2\xb91\xae\u007f\x16?ҳ\xa7\x90\x91b\xf8\xb6\xbe$Xɾw\xcb8C\xebH\xffi\xfds\xa9\xc1\xbb?\xb1GM\xa2g+h\xa85\b\x02\x15\xc7\x00?\xe7\xeeЍt&~+w\xa1\xf3v\x15\x19uLH\x9b9\xa57\xdc\xfe\xe63Nw\u007f\n\xbf\xa43\xf1;\xec\xf6\x97q\xea\xa53\xf1'f\xc5\x13\x18\x0fݹ]C\x8b\xc9\u07b3G\xfa\x13\x9d#7\xc4\xdf-\xb9\xd2.\xb1\xad\xf0\x14r\"\xb8\xc8b\xb8!#3\x90\x9b^\x87eL\xb1\x1b\xf7t\xed\x97'\xe2\xbd\xeb\x92O\xa8\x9ek\x1cn\xe4\xea\xe5\x1f\xac\xd4V\xf2\x01\xdc\xd8}\a\xdf\xd9M4T\xfaN\xceM\xd8\xed\xfa/\xedv\xe6\xa3W\xf8\xb8\xa3\xde\xf5}hsT\xefg~\x90=\x19O\xf0\xa5\xa9ܠ\xbf\x18\x0ew\xf6\x9f\xd73\x01\v\xbfg\v\xfa?\xbb\x8c\x94~\x8d\xf2@i\\\xb9\nQY\xc0\xb0\xa7\xc7bj\x1b\x14\xbd\x14\x1e\xea\x02k&\x89\a\x827l\x05܆\xfe\xe3Y酴\xf3\xd7TX\x97\xb3)\xbb0F\xbf\xb0Y\xcb\xc7\x16\vq\x8d\xe38\xdd\u007f\x14\x93W\xfa\xc56w\xe33\xbd\xf11;\x10I\x16ݼRb\xb8\xf8\x97\xa8\\<v\xba\xac\xc4H\xff\x13\xef\x1bo\x1f\xd6\x19\x8c\x8f\xa2\rB'~\xb4\x9b\xce\xeb\t\xd6\b\x02\x14.\x86\x1f\x93Aĝbj\xfb/\xf7\x1a\u007fY|\xe8\xecsY\xbd\xcf\x04\xe7\x87\xd0A\xc0\xb8\xa3\xa8CL\xc51\xc0\xadzڗ\x12~\vIg\x99\xdd\xc3\xc1\x8eʢC\xf5\xf7+uFY3_\x9c\xfd\xech\xe3}\x1dI^\x14=,\x17\xe2\xd4\xcb~\v\xd9'\xd6\xff¨/\xae\xfd\x86\xd4 \u007fϞ_0\x14ׄ\xa6\xe0\x9e\xf9\t\xbdk\xe6JX\r\xba\xe7\x8b+F\xfe\x8d\xb2\xfe\x157l\x96w\xe5\xe9$8\"\xcdS\x95e\xb4O\xa7\xf8\xaeK>\xa1`\xe7\t\"\x8dA\xf9\a+\xfb\x84\"\x1f\xc0\x88\xfe\x19\x9e*\x1e\x96\xbf\x93Oŷ\x84I\xab\xc2\xc7\x1d\xf5\xae\x9b6G\xbb\x9a\xc6\xd3ؓ\xa2\xf8_\x9aq\x1a\x84_]9\xac?\xfd\x98\tX\xf8=\xc3qZ,\xbd2[\xfaI\xa5\xd3Lo<8>\x1d\xc0\xab\x1e\xb5\x05l\xfd!\x9d\xaa\xbf\x9a\t\xde\xd0\xf5ᕦZcIf\xa2\xc4\x12\x8b\x89\xac\xe4'Ԏ>跶\xe0\xc4_\f-\x9a\x8a\x98\xa9\x8f\x8c\xf6<\x04\xcb\xe9\x00+{{,\x8a`\x87\xe1U2\x9be\xe7rΒ\x1c\tK,&\xb0r\x9fP\xc0\x9c\x15\xe3s}/\x16-`\xde\xec\xf8\xcfݧ\xc7=q\x8f\xad\x1a@\xc0\x96\x9b\x95\xbb=\x80\x85\xb1r\x9f\x90G[\x1dw\xe2\xe1\x92X\xb4\x80\xa5< `\xcb\xcb\xf7\xcc\x19\x9c\xcc\nX9\xd6\xd2'\xf4b\x84\xbb\xf9\xa75Җ\x05\x02\x02\xb6\xbc0gp\x825\xff\x80\x95f-}B\xc65Ԗ\x05\x02\x02\x06\x00@\xca\x02\x02\x06\x00@\xca\x02\x02\x06\x00@\xca\x02\x02\x06\x00@\xca\x02\x02\x06\x00@\xca\x02\x02\x06\x00@\xca\x02\x02\x96j\x04\x02\xf3\x01\xfa\x97\xcc\x0e\x00\xd6\x01 `)\x86kG^\xde\xdeO\xf2\xf2\xaa?\xe8o\xe8\x00 5\x01\x01K-\xe65hg\xe1G\x19;wl\xf8W\x85P2\x00\xb0\xceP[\xc0<]\xcd&\xcb@\xa8\xf7\xe0\xe0\x85\xd0\x01>\x9b\xc5\xd4>\xae\xfc\xab\xf8\xb5\xc8\xd2\xc3\xc3\xfb>\xae\xfb\xdbߜ\xff\xdf\xdf\xfe\xef\xc7\xfb\xbc\xc9l\x01`ͣ\xb2\x80M\xf3V\xa7\xdb\xd9&.h\xe83\r\xb0\x15Y}\xe6v\x87\xfb\x81\xb9}\xcd+X(\xa2\xfbR\xc2ÿe\vV\xcd|\xb2aÆ@\xe9\x86\r\x1f\xd5IƐ\xbdJK\xd2\x01\xc0\xdaGe\x01s\xf1tY\\\x1f\xefd{\xd6\x1e7\x13\xb0\x1e\vuI{M\x0f\xe2\x17\\\x1b\x84#\xba/:<|\xf0^\xc9i\xba\rx\xaa\xf3\x89\x80\xfdh\u007f\x83K\xb2\x8e\xc1\x8e\xa8e\x94\x01`\x9d\xa0\xb2\x80\t\xd1\xee\xbcB$\"\x87\xd9'\xac\x89\xdf&,Gכ\"\xa1\xe8\x96N\x95L\xc0\x16\x11\x1e~\xaa\x86;+\x84\xa4\x0e\xf8x\"`\x1bG\xbd\xd2uX⬢\x0e\x00k\x1d\xb5\x05\x8c0\xe3\xb6Xi\x8f\xcbgr\x89A=<B\xb4\x82\x81[\tJ\xa5\x16\xaf.\x96\x19n\xde,+\xee\x93D\xab\x97FtO\x16\x1e^\xce\xecM\xce0\x1c\u07b3P\x01sE\x86\xdbV1^e\xbe,.\xfd1\x94ք'5(\x8f\xd94\x15d\xe4\xc2sK`\xed\xa1\xba\x80yy\x9e7\xb3[\xc9\xda-\x8dJD\xfa\x16\xcdQ!\x17S\x97\xb9\x13\x86\xceV\xbd\xfe^m\x87$Z\xbd4\xa2{\xb2\xf0\xf0R\x82\xfd\x06]\xa3\xd0U\x9b{A\xf8:J\xc0|\x03,\f\x84\xcd)\x8bK\xef\xb1m\xaa\xc3x\xf0\x88\x86\x9aT\xa4\x1d\xb7^\xd5\xe6\xc3\xdc1`\xad\xa1\xba\x80a\xaf\xc7\xc1\xa2\x129\xa9\x8cI\x05l\xc0\xbcf\x9e\xab\xf5Ѹ\x85\x9d,\xba\xb54Z\xbdt\bII\x14\x1e>\xc25\xaejJL\xd2\xf5\x9e\xb8\xff\x1c%`X6\x84\x8cĥ\xd7\xd0\xf0<u\x1aL\xfbhfL\x03eE\a`\x06\x80TG}\x01\xc34.d7\x19@:\x03\x81\x80\xbb)\x10\xea\x16\f\xf2\xb1\x01\xd5S\x95\xc6\x12L\x03\x95}K^\xa5\xd1\xea\xa5\x02\x96,<|\x84\xfbE\x9f\xdd\x17W\xd9|>L\xf8_\x89\x05,\x1c\x97>\"`\xa5\xdb\xfc\xf3\x84\x9c\n\f\x00k\v\x95\x05\xcc/\xc8\xd58\x1f\x98\xe4Cxh\xce|\xaf\xf8drMб\xfb\x15\xed{ю\x934Z}\x94\x13?axx\t/j\xb9\x9a\xa9\xc8n\xb4\x0f\f\xcb\x05,\x1c\x97>\"`\xdbE/Y\n\x04\x99\x01\x80E\xa1\xae\x80\x05\x9a\x84\xb8\x8b\x0fM\x81\x80\x97\xe20{\xbd̡om\xf2$,\x99Z\xbc\xe4j_>\xab4\xd2~\x934Z}$\xa2{\xf2\xf0\xf0R$^0\x1c_\xc0L\xac\xeb\x15\x89K\xcf\x04쌆\xbc\x94o\x1be\xac\x99!:\x00\x88\xa8+`\xb8\xb9\x8b\xbe\xfa-=\xe2\xbe\xe8\x03\xf3\xb6\xb4\xf9\x88\xbc\xad\x99\x1f\xc7<\xe1\xca8\xee4\x9b\xf7 \x8dV\x1f\x89\xe8\x9e<<\xbc\x1c\xfa\x1crLL+\bXa!\xc6ӈMF\x89t\xc62>'o\xe9\x0e\rIu\t\x87\xbe\x88\x8aY\r\x00)\x8f\xca\x02\xe6⻝n\xa7E\x9c\x89\x1f\xf08\xcc\x1e\xd2-p\x9bZ\xdc\x1e\x8fg\xe0}\xa2\x93\xae*\x9e\xe9\xc7F\xec\xdf\v\x8e\xabp\xb4z,\x89\xe8\x9e<<|4S\xc6\xd0\xf0SA\xc0\xcei.\xb5\xef\xcap\xcb\xe3\xd2\u007f\xaam\xa8+@\x1b\xcddh~\n\x95Z\xda+\x90\xe4\x89\t\x00\xac\tT\x160\xec鱘\xda\x06\xc5I\x98\x1e\xea\x02k\xc6\xf8\xae\xe8\r[3\x13Y'tԫ\xa53R\xcfU8Z=\x8eDt_@x\xf8\xf8(\b\x98\xffxVz\xe1PT\\zWaz\xe6\x9e/\x10\xa2\xa1S\xbbvj\xb3>\xbd\xabT\x1b\x00\xa42j\vغ\xe0u\xf1\xb5\xd7\xef\u07bd}z\xfe\xb3\xb7\xc9L\x15H\x16\x9cTA\xc0\x00`\x9d\x02\x02\xb6\f\xf4\x97\b\x1d\xae`Y\xf4\x9c\xfa\x85\x00\x02\x06\x00\v\x05\x04l\x19x\xc2\t\xb3\x1e\xa6\xb8%,\x98\x13-`\\\x14\xff\xf9?\xd1\xd5(>\x1f\xf8\xb01\xe9\x01 %\x01\x01[\x06\x82W\xf4\xd7\xfa\x1e\xf5]\xd3\u007f\xb5\x840\xef\xd1\xe1\xe1\xa3\xf4\xeb?\x85\x96\xd3i\x03\x05\x03\x00\x10\xb0\xe5 8\\k\xd0\x19j\x87\x97\xa0_I\xc2\xc3\xcf\xd0\x05\r\xff\u07ff\xfd\xed\xff~\xbc\x1f~\x9b\r\x00 `\xa9\x85\x0f\xa1\x9d;?\u07b2sdž\n\x98\x96\n\x00 `\xa9ż-'++7++k\xd7К\x99\xf6\v\x00K\x06\x04,\xc5\xf0{&]\x93\x93.\x97\x1bF\x90\x00\x00\x02\x96r@\\H\x00\b\x03\x02\x06\x00@\xca\x02\x02\x06\x00@\xca\x02\x02\x96\xfalXq\x92]!\x00,\x13 `\xa9φ7+\f\b\x18\xb0R\x80\x80\xa5> `\xc0\xbaEm\x01\xf3t5\x9b,\x03\xa1)\x00\x0eq\x05\x1dy.\xb08@\xc0\x80u\x8b\xca\x026\xcd[\x9dng\x9b\xb8\xa0\xa1\xcf4\xd0\x14\x9b\v(\xf2\xf6/\U0004e000\x01\xeb\x16\x95\x05\xcc\xc5B\x0f\xf9\xc4\x00\x1e\xd6\x1ewSl.\xa0@\xf0^\xc9\xe9x\xc7$\x02\xb6`-[\xb0\xe1\x9b\x05\u0602\x80\x01+\x85\xca\x02\xc6\x02\x16b\xaf\x10\x89\xc8a\xf6\x89k\xe2Ks\x01\x05\xa6j\xb8\xb3\xdf\xc7;\b\x02\x06\xac[\xd4\x160\u008c\xdbbe\x91\x88L.I`\xdbP\xee\x1a`~˦/r\xb2{\x8fg\x15Ra\xb6\xed\xc9٤ݻ\x95\x1e\xf0\x96ksN\x9e\xd4n\x8e^\xfb\u07fc\x85\xa7\x1bw\xa6\x18\xfe,3*B&\r\xe91,\xcfz\xa6\xe3\xb8o^\\<\xaa\xaf}\a\x02\x06\xac_T\x170/\xcf\xf3f\xd6\xe3\xb2vG\"sGr\xd7\x02\xbd\x99\xa8z\x17\xd26l\xb9L\xe3a\x1f\xb9\xd5\xcdk\xd1<\xc6\xfe\xbc\xec\xaf\xcfi\xd2M\xbf\xb8\x1ce\xbf\x1f\xed\xa1\x1b\xbf\xf9\xaa\x80Y\xb6ԗ$\xa8\xda\xdc\v\x819<\xd7\xd7w\xb8\xb2\xd8p\xb3~\xf7K*`\u007f\xf8\xf9\xc7\x1f\xfd\xf4\u007f\x13)\xf9\xdf?\xfd\xe8\xe3\u007f\xfc3\x11\x95_\xffxÏ\u007fM\x0e|L\xd2\xffH\xfe>\xfe\xa3 6\xbf\xfd\xe9G?\xfa7\x89!)\xf9\xf1\xcf\xff,ɈT\xf1ۿ\xfb\xe8\xc7\xff\xf4&\"`b\x95o6\xd0\x04\xa9#rV\f\x00+\x83\xea\x02\x86\xbd\x1e\a\x8bJ䤂\x15\ue045r\xd7\x06\xd9\xe5؊\xac\xf8H\x05\xc6\u05f5t\xf1篳H\xef\xb2\x05\x8d\x93\x14rĘO\xd6\tq\x84\xa6'\x05\xa6eG\xafqU\xa1\xb0\xb6FqUC#ݩ\xe2N\xbf\xc5\xc1\xb7l\b\xf9\xd3_\xfd\xf9\xbb\u007f\xff9\x91\x92\xbf\xfb\xddw\u007f\xfcG\"X\xff\xe7G\xbf\xfb\xf3\xef~\xf4\xdb7o~\xfc\xfb7\u007f\xd8\xf0\xc77\xff\xfecQ\xbf>\xfe\xedw\u007f\xf8G\x89!\xd9\xfe\xf9\u007f\xfc7IF8\xf1\xef\u007f\xf7\xef\xdf\xfd\xe1\xbf\xfcSX\xc0\xc2Un\xf8\xd1\xef\xbec\x89\xf0Y1\x00\xac\f\xea\v\x18\xa6q!\xbb\xc9\x00\xd2\x19\b\x04\xdcM\x81\x804w\x8d\x90݂\a\x91\x0f\u007f^Jƅ\xd9[\xff\x99\u007f\x18\xa0}\xaaSY\xe4Ņ\xda㕚D!dC\xc8\xfbE\x9f\xdd\x17WF|>,\xf0\x9c\xeeT\x15\xbd\x14r\x89\xc0|$\xf6\xaf6\xfc\x9e\xbc\xfc\x99\xf4\xba\xfe\xfe\xffP\xc9\xf9\xfb7o\xfeǯ\xde\xfcjÿ\xbd\xf9\xa7\xffG0`\xf9RCʟ\u007f$\xc9\b'\xfe\x81&\xfe\xf8㰀\x85\xab\xdc\xf0[\x9a\xf8\x99\xe4\xac\x18\x00V\x06\x95\x05\xcc/\xc8\xd58\x1f\x98\xe4Cx$\xb9\x89ʦ\x10\xd9]xHC\x14\x8b\b\x18\xf6\xf1\a\xf3Ж\x06\x92\xba\x8c\xbc4\xc8ll\x0f,\x84\xcd*`\x93g\xbf\xa8\xe5j\xa6p\fU5b\x82\b\xcc\xff\xfc\xf8\xbf\xff\x1bU\x13Ak\xc8\xeb\xc7\u007f\x16e\xe8\xb7\xff\xf5\xcd\xcf\xfe\xdb\xcf\xdf\xfc\xfdo\x05\xad\xf9\xe8\xcfoB&\xc2\xeb\x1f\u007f\xfe\xf1\x86\r\x1fI2\"U|\xf4\x11\xfd\x99PX\xc0\xc2Un\b%\xc2g\x8d\xbd8\x00P\x05u\x05,\xd0\xd4˶\x0fM\x81\x80\x97\xe20{\xbd\x01In\xa2\xc2)\x84D\xc0\x1e\x9c\"\xfb\xbe\x96\xf4\xeb\xa43\x96\xb6\xd7=\x9e[\xb0\xf8FJ\xbc`\x12\xaaB\x91n\xa9\xc0\xfc\xfeW?\xff\xf8WJ\x02\xf6\xdd\xc7\u007f\xfc\xe8\x8f\xe4\xef;\x89\nI\x05\xecg\xff\xf3\x8fo\xbe\x93\xeaV8\x11\xea_\xc5\x17\xb0\xf0Y\xa3/\r\x00TB]\x01\xc3\xcd]\xf4\xd5o\xe9\x11\xf7\x05\x1fXtn\xca#\x11\xb0:\xc4\x1aWx\f\xe3Q\xb4\x05\xa1\x9d\x9eXsw\xc3dl\xa6\f\xfa\x1cr,*O&`o\x04\u007f}X}X\x8f\x8b\x8e\xf7\xde\xfc\xc3\u007f\xff\a\xf6'\xf0\xb3\xd0\x102\xf4J\x95\xed\xdf\x15\x05\xec\xef\u007f\xfdFj\x1b\xa92<\x84\xa4\xb0\xb3F_.\x00\xa8\x84\xca\x02\xe6⻝ng\xc8]\x1f\xf08\xcc\x1eotn\xea\xe3̺\xeck\xd94\xee+\xdd\xe9&\x02\xb6\xf9\x9c\xb5\xad\x02\x91N樦\xc7j\xf3(t\xc0\xf6\x89\xb1\xb4\x131e\xbc\x80%\xbc\xfb\x93\xbd\xd2h\xb7\xb3\xe0\x1fD`\xfe\xcb\xef\xbe\xfb\xee\xd7?\x95\xa8\xcf\xff\t9\xda\xdf\xfcjï؟\x00\xc9\x13\x9c\xf8!ß\xfe\xea\xbb\xdf\xffXQ\xc0~\xf7\xf1\xbf\xfd\xf9\xbb\xdf\xfdװ\x80\x85\xab\f;\xf1\xc3gU\xbed\x00XvT\x160\xec鱘\xda\x06\xc5i\x02\x1e\xea\x02k\x8e\xceMy\x02\xa4\xa3՜\x892,\b\xed\xc7M\x85u9\x9b\xb2\v\xe9 y@C\x1d\xf4\x9b\nc\x9c`f-\xafPMB\x9e\t\x8f#ki\x9a\b\xcco\u007f\xf6\xd1\xc7?\xff\x83D}\xde\xfc\xfa\xc7\x1f\xb19\x0fo~\xbf\xe1\x0fo\xfe\xc0<\xf3\x82\f\xfd\xddGt\nD\xd8\xf0\xf7?\xfd\xe8G\xbfV\x14\xb07\xbf\xfb\xd9G\x1f\xfd\xecwa\x01\vW\xb9\x81&\xe84\x8a\xf0Y\x93]-\x00,\x13j\v\xd8:ƻ\xf9\x98w~\xde7t \xeb\x03\xf74C\x02\xa3\x161\xe7\x03\x01\x03V\n\x100\xd5h\xcf\x12F\x8f\x01\xed\xdd$\x96\x8b\x04\x04\fX\xb7\x80\x80\xa9\xc6h\x9a0vt\xa4=Lb\xb9H@\xc0\x80u\v\b\x98j\x04*ҏ\xb5\xf4\xb6\x1cK\xafHf\xb9H\xd4\x16\xb0\x18@\xc0\x80\x95\x02\x04LE\xac{\xb25\xd9{\xac\xc9\xcc\x16\v\b\x18\xb0n\x01\x01K}\x92\x85\xdcX~\x92]!\x00,\x13 `\x00\x00\xa4, `\x00\x00\xa4, `\x00\x00\xa4, `\x00\x00\xa4, `\x00\x00\xa4, `@\"\xfc333\xf3\x18ϓ\xcdZ\xf9\xa9*\xb0\x96\x00\x01\x03\x120\x90\x86\x10J\xf7\xf9\xd2\xc9&-j\x9dE\x00Xy@\xc0\x00\x05\x86k^\xb3\xad\x05Y\x87\x86\x1c\x18;\x86\x86\xac(:\x98\xd2Bi/\xf0&3!x\v\xda\x15\x92\x00\x90\x10\xb5\x05\xcc\xd3\xd5l\xb2\f\x84\x96cp\xf0\xe1i\xe9\x92$\xf0\x01\xf8\x8a\xe3:Ȧ\x83㾊:2v(*D[,w\xb8Va\x15~Kdy~\xb7 `\xc7P\xda\"\x85\xac\x01\x9dKf\xc2hHkPH\x02@\"T\x16\xb0i\xde\xeat;\xdbĥ\v}\xa6\x81PT\"I\x12\xf8\x10\xbc,\xbe\xf3\x03\xd9\xfcp\xa7\xf8eԑ\xe1\xe2~1\xf5\xe8\tV\xa4\x93\xbb/\xa6b\x05\xccc\xdbT\xa7X\xa8wT1\x1b\xff&ͬ| \x06\xebƫ\nI\x00H\x80\xca\x02\xe6\xe2\xe9\r\xe1\xe3\x9dl\xcf\xda\xe3\x0e\xa9\x96$\t|\x10N\xdcc\x9b{'b\x8e\x04C\x89\x1a\xd9\"\xafa^\xe8\x1aC\xc9X\x01\xc3X\xa3,`;J\x15\xb3'5\xa7\x14\xf3\x958\xa3q+$\x01 >*\v\x18f]//\xef\xa1\x1b\x87\xd9\x17\x8a\v)I\x02\x1f\x86\xf3߰M\xe3\xf9\xf8&U\xca\x02v\xc5\x10\x0e \xb2\b\x01\xcb?\xa8\x98]\x91\xbd\xf0\xe5\x1b}\xd9\x15\nI\x00\x88\x8f\xda\x02F\x98q[\xacti?\x9f\xc9\x15\nl+I\xae\x17\x9a\n2r\xabɽ=\xbe\x11\xa13\xae\xf2\xad\xe9{\xe6%\xc9(c\xf3\x16\xb6\xe6\xb4;S\x8c\x1b\x99)ힴr\x1cׇ\xfb\xc8k\xab\xb4Lc=\xdb\\h\xc4\xcft\x1c\xf7͋\x8bG\xf5\xb5\xef\xf0[=\xb3&\f\x8bArYp\xb6\xe0\xfd\x9a\xe2ʛb\xf8\xef\xe2p\aLY\xc0\x8eWdg\xeds\x91^3\xb9\x92/p\x1dy\xb5X\xc5\v\xcbg\x16\xa1\xb6\x11\xfc\x99\x9f\xd3ͻ2]\xa3\xc1\xf0\xe8F\x89\x91\x9e\xc3^{XWV{\x98\xf6\x04_],3ܼYV\xcc.\t\x9fI\x9f\t\x9dN\x92\x04\x80\xb8\xa8.`^\x9e\xe7\xcd\xec\x9f\xdb\xda\x1d\x8e\xcc-I\xae\x13*Ҏ[\xafj\xf3\x03x\xc6Ҽ573\xa7\xba\x1c\xb9%\xc9(\xeb\xfdh\x0f\xdd\xf8\xcdW\x05\xcc\xd29Y\xaf\xebk\xec\xb3xv\xc2X\xffJZ\xe6^\r\x9e0L\xe0\xaa{x\xae\xaf\xefpe\xb1\xe1f\xfd\xee\x97\x18?\xb6\xdb\xf5L\xe8f'XX\x10;\v\x92{\x85\xbb1\xd2y\xa8\x8a\r.\x9fr\xf6p%\x8a\x02\x86\xf2[Z\xb6g8\xb0o \xe7\xd84\xf6\x9e˴\xf9|\x03\xb6\xdcB\x9b\xcd\xc6\\\x03\xe1\xb6a\x1a\x89I\b\x99\xf7\xa8\x84\xbby\x9a+\xbb]\xd6AN\xb0\xfbb\xffؽ2\xee\x1d\x11\xcb\x13\x86\xceV\xbd\xfe^m\a\xb3\x1a@\x83\xa1\xd3I\x92\x00\x10\x17\xd5\x05\f{=\x0e\x16\u007f\xc8IeLP-Ir\x9d`EԳ=\x84Z\xe8N>\xda\xe5\x13\aג\xa4\x94\xc9:!\xee\xda\xf4\xa4\xc0\xb4\xec\xe8\xfd_\xb2͉\x90\xe7]\xc0^\x86\x1bu\x8d\xf83\xa6FU\xdc\xe9\xb78\xf8V8\xa2\x0f\xf5\xd4\xc2C\xc8a\xe6\xb5\u007f,t\xcdF\xb8\xe7\xe1J\x14\x05,\x8f\xf4\x8dfr\vH\xb2\x8e\xf6\xb8\x8e\b\x83\xbd\xf0\x10R\xd66+\x12#\xc6\x19.\x92\x8a\x87\xf1ů0\xee<D\xa4\vw\x96\x10\xb9\xec\xe3\x9e\xd1g\x06\xa1\xb0\xbdnt\v\xc7&\x01 .\xea\v\x18\xa6\x11 \xbbɨ\xd1\x19\b\x04\xdcM\x81\x804\xb9^(\xdd\xe6\x9f'\xe4\xb0{??\xe2\xb0\xceO軞D!dVϸ\xb9\xd9\xfbo\xdf\x15=\x93\x19\xbf\xe4f\x8d\x17\x8d\xb3\x1c{\bYU$y\x16\x19+`\xf5G\xe7\xde\x11\fW\xe8N?\xf7\"l\xaa(`_\xd0\xd7\xeb4̸\x1b9\xc8 Q\b\xe7\x19\x160Y\xdb\xda\xc3\x02\xd6G\x04r\x96\rl_\x1a\x8e\u07b8\xf748Gr\x1bK\xc8\xcbs\xee\xdb\xf09Zpl\x12\x00⢲\x80\xf9\x05\x8d\x1a\xe7\x03\x93|\b\x8f$\x99\xb8\xf4\xdaa\xbb(D\xfb\xe9N\xfe\x8ep\xbe$\xa9\x84\xcd* \x9f\x13?\xa7\x9b\xea\xe0Z\x9fss\xb2\xdc`\xd1T\xf1\xb3\xe2)\x1d\x1b\x16V\xd5H\x8e\xc4\n\xd8\t\xd1\x1fv\x96\xeeLp\x13a\xd3\xf8N|\x1b\xa2\xd3&\xf6\x9e\xc4]Y\xc2x6,`\xb2\xb6\r\x86F\x82\x86\x11\xfcX'z\xe6\xde\u07bbPɕ\xdd!Wֱ\xfb\x15\xed\xf2\x85z`Ch\x00\xc7&\x01 .\xea\nX\xa0I\xf0\x88<4\x05\x02^\x8a\xc3\xec\xf5J\x93Iʯ\x19ʷ\x8d2\xd8\x14\xf5\xfc\x03\xe1|Ir\x11T\xf6\x9d6V\xf6\xff2:\xf7\x8e\x01\x1b:*YZ\xf6\xbcQ.`\xf7^\xd2\x1e\xd8\x13\x06s\xa2\xcd\x16E\x1e\x06(\nX5}5!:еj\xfd\xe2\bR\x100\x93;\xaam>\x8d8\x8b\xd50\x86\x1f\x17\t\x02\xf6\xb8\x91H\xd7\xdb>}'\xed&־|Vi\fM\xec\xa8ӄGϒ$\x00\xc4E]\x01\xc3\xcd]\xf4\xd5o\xe9\x11\xf7%\x8e\xaf\xb5\xeb\x03\x9b\xac\x8b\x99\xe3\xd9%\xa8\xc1\x17\xac3#\x99\x80\x10g.\x82\xbbaR1_\xa4\xfe\x86n\x84\xbbv!ʶ\xb6\xe6<>od\xa1o\xe3\b\x98ш\xf1k\xea\xf8\x1a\x13\xbc_\x8d\xb7Y\xf6\x85\xca\xf0L1E\x01\xcb!].\u007f^!M\xfb\xb5\xd6,\xf1\xb3,$\x19\xd3\xd4F\xd662\xa0\x14\xbe\x95$\x02\xd6ʍ\xd0\x1c\xe35\x8c\x9fpe\x1cw\xfa{\xf1\x14\x81\xbcp\x84rI\x12\x00⣲\x80\xb9\xf8n\xa7\xdbi\x11g\xe2\a<\x0e\xb3\xc7\x1b\x9d\\s\xecC\x9bcz\x13\xa7P\xa9\xa5\xbd\x025\xe1\xf9A\xf6\xfc\x8e\x8a\x8e$\x19SC\xc2\xdb\xf9\xb6\xbe$X\xa9\xbf\x1de{c\xf7\x1d|g\xf7\r\x8c\xdf\xfd\x89=od\x9e\xad\xb9\t\xbb]\xff\xa5\xdd\xce\xfc\xf9\xadE\x1d\xfd\xa7\xd9L\xfd\xc6\xdd\xf5\xfd\xdf^\x11d\f?\xe7\xee\x84jV~\n\xb9g\xb0\xa7 K\xb8\xccS۲\xc49\x1f\xe74\x97\xdaweP\xf3p\xdb(\xae\xb4Kt3\xf5Y\xc7l\x9fnj\xb6\x9e\xa8U+W\xdc:\xdc\u007f\x85{\x84\xf13\xfd؈\xfd\xfb\x90^^Fa\xa5\x97$\x01 >*\v\x18\xf6\xf4XLm\x83\xe2,\x00\x0f\xf5{5G'\xd7\x1c\xa6\xcdh(&\xb3k\xa76\xebӻ\x18\x8f\xa71\x87\x11\x15\x1dI2\n\xb3\x96\x8f͌\xf0\xb8\xa4\x15\xdf)~\x1ce;\xa2\u007f\x86\xa7\x8a\x87\xa9\x93\x9f\xc1\xfabOEo\x17\x9b\xa6?w\xe33\xbdQ(6v\xba\xac\xc48\"\xd6ת\x0fy\xc1,\xc8\x15ZN\xc7\x15\x12\xb0\xbc\xba\x83\x99\xd9\xe5\x1eaDžB\x13N\xfddz\xd2\v\x85v\x86\xda\xc68\xf3\x93\x01\x8c\x83\xa4\xa3\xd5W\xcc\x15\xf7q\xdcy|\xdfx\xfb\xb0\xce`$\xfa\x85't\xf4btF\xe6\x04\xb3\xa5\x9f\x14\xcbH\x93\x00\x90\x00\xb5\x05l]ҎR˟\x13\xbc\xa1\x13\xfabl\xaejh9\x1d\xa4\x14Pܧ\xe9UȕQ\xad\xb1\xc4;\xf4\xba\xf8\xda\xebw\xef\xde>=\xff\x19\xe9\x11\xb6h*B\x13x%I\x00H\x04\b\xd8r0#\xce\xd7b\x93\xc9\x03\xe6\xacc\xc9\n\xac2\x82\x1d\x06aR\xec\xfc\xf8Ph9\x9d\xa1q%M\xb1h\x93+\xcd\xe5\x1c\xf9\xbc\xb5\b\xfd%\xc2\xe81X6\x82\xbd\xd9\xe1\x15($I\x00H\b\b\xd8rP(\xce$`\x8en\x8f\xb6z\x8d.fZ\u05cbw-l\xa9\x9c\x89'\xb4\x8b\x00\x00 \x00IDAT8<\x11'PLqO\x93X\x02\x80\" `ˁK\x9c\xaf\xe5Jf\x98\xd2\xf8P\xfe\xb1E\xfcT[\x81\xe0\x15\xfd\xb5\xbeG}\xd7\xf4_\x051\x00,\x01\x100`ɜۼә\xcc&1\xc1\xe1Z\x83\xceP;\f\xfa\x05,\r\x100\x00\x00R\x16\x100\x00\x00R\x16\x100\x00\x00R\x16\x100\x00\x00R\x16\x100\x00\x00R\x16\x100\x00\x00R\x16\x10\xb0uɺY\xb7\bX\u3000\xad?<\x15[\x84\xd5\x06\x01 \xd5\x01\x01[w\x04\xf2\xf2\xf8\x9eD+W\x03@ʠ\xb6\x80y\xba\x9aM\x96\x81\xd0\xefO\x1c\xbc\x95nf\xcclAi\xf3Z\xfa\xc9`\xb7\xd6\x1aJz\x8fmI\xdf\xfb^\x836k\x96\x15/\x94Љ\x8f \x842\x94~\xcb4\x8e\xba\x14r\x01 \x15QY\xc0\xa6y\xab\xd3\xedl\x13\x174\xf4\x99\x06تw>\xfe\xa1\x87\xb0\xa6\xd63\xb4f\xdc\n%wm\xb9~$\xfd\xbd~3\xf89\xfa<\x99I\x98Љ\xdd6\xdb\u05ca\xa1Ɇ\x90|I}\x00H]T\x160\x17O\xc7.>^\xf8\t\x9d\xb5\xc7-\n\xd8\x1a\x1cф\xbb\\^t\x15\a\xdeK\xbf\xf0\x19t&\x99I\x84H_o(\x8e\x80A\xc4E`\xad\xa0\xb2\x80\t!\x0f\xbdB\xf8!\x87\xd9\xe7Y\xbb\x02\x16ƅ\x16>\xfe\x8bC\x1d\xaaKf\xa2\x04\b\x18\xb0\xd6Q[\xc0\b3n\x8b\x95\xf6\x12|&\x17^\xa3\x02FW0Mc\vd\xfb\xb5\xc2\xca`\xd5Q\x16\xc1\xfb5ŕ7g1~\xa6\xe3\xb8o^\\<\xaa\xaf}'IFY7 \xb6\u009f;S\\g,S\xfa~\x1dC\x9b\xf8\xea܌=\xaco\x1b>1EY\xaazA\xc0\x805\x83\xea\x02\xe6\xa5\xdez\xd6\x0f\xb3v㰀u\xdf\xe2\x9bm3\x89K\xa6\x12\x0fl6!|\"~hkAu6\x9b'\xca\xe0\nwc\xa4\xf3PU\x10\xcf\xf5\xf5\x1d\xae,6ܬ\xdf\xfdR\x92\x8c\xb2\xbe\x8a.Ӎ\xdf|U@\xf6\xb8\xc3ټ\x11i\xeb.e\xb2\x88l\x91\x13cE\x01\x9b\x9f\xeeݑ\xf5~\xe3Y\x00X=\xa8.`\xd8\xebq\xb0\xa8DN*c!\x01k\x1aw;--k\xe9)$N\x0f\xe9\x88\xd2\x10r\x98\xbbO^\x1f\va\x80\xaa\xb8\xd3oq\xf0mTR\n\x8f\x84@\x1d\xd3\xe2R\xd5QK4k\xb2h8F\xad\xb8\x97\x9eH\xc0\xf6\x93\xfe\xdb{\x8fh\x01`\xb5\xa0\xbe\x80a\x1a\x17\xb2\x9b\f \x9d\x81@\xc0\xdd\x14 \xa3ɀ\x83v\xbef\xcckjh\x93P\xc0\xea\x8fν#\x18\xaeН\xaa\xa2p\x8fK\x92\x94bFf\xba\x99D!\xe4Cn\xcd\x11LÚ\x89{\t\x05\xcc\xdd\xc5\xe7A\x0f\fX3\xa8,`~\xe1\x11\xd98\x1f\x98\xe4CxB\amm\xf1\x8a\xa5\"\t\x05\xec\x84\x18\xdd\xec,ݩ\xaa\t\xe7K\x92R\x06\xb2\x04%\xb2\x89KUG̓`ѯ\xeb4\xe2^B\x01#\xd8\x14\x82\xbc\x01@j\xa2\xae\x80\x05\x9a\x84 \\\x0fM\x81\x80\x97\xe20{\xbd\x01\xdc#\xdc\xe1\xbdkjl\x93\xa4\a\xf6\x84\xc1b\xffH\xc2f\xcb\"h/\x18\xe6\xf5Z\xb0\x80\xc1SH`\xed\xa0\xae\x80\xe1f6\t\xdco\x11\xc3ы>0+\xebzy\xcd\x0f\xe3\x94JI\x12\nؘ\xe0\xfdjdѴ\x17 `\x89\xe7\xf1\x83\x80\x01\xeb\x15\x95\x05\xcc\xc5w;\xddN\x8b8\x13?\xe0q\x98\xe9\xfc{7\xdf\xe5r?0Y\xdf\xeb\xe76\xab\t\xff\xa0ͦ9b\xb3\xf9BO!\a\xa3\x9bָ\xbb\xbe\xff\xdb+D\xc6\xde\xfd\xc9^i\xb4\xdb_\x90<I2\n\xeb\xe6\x04\x9dS\x8fmӑA<zd\x93\xcd#=1\x9b\x89\u007f\xd9f\x8b\x99\xa1\xf2\x00\r(U\x03\x00)\x88\xca\x02\x86==\x16S۠\xf8\xb8\xd1C]`t\xd6\xd2tw\xb3\xd9\xeaX3\xfa\x85\x87\xd2\x04_;\x8f\xfdY,\xb11&z\xcf\xd8\xe9\xb2\x12\xe3\b\xc6\xcf\x04gX-\x96%\xa3\xb8\xabU\x8a\x8a-r\x8cԿɑA^\x8fIN\xcc~\vI)\x8d\xb6\x9f\xdexp|z\xed\xbc\xd7\xc0\xbaFm\x01\x03V\x9e\xf6<\x04\xcb\xe9\x00k\x03\x10\xb0\xf5\xc8\xf4\xb8'\x99\t\x00\xa4\x02 `\x00\x00\xa4, `\x00\x00\xa4, `\x00\x00\xa4, `\x00\x00\xa4, `\x00\x00\xa4, `\x00\x00\xa4, `\x00\x00\xa4, `\x00\x00\xa4, `\x00\x00\xa4, `\x00\x00\xa4, `\x80*\\Ϡ\x91\xe1\x06\xb3\xd6T\xf0O`\xc5\x01\x01\x03B\f\u05fcNf\xb2d|\x19\xd5t\x1d\xec\x03\xda\xf9d\x96\x8b\xc4[О\xcc\x04Xè-`\x9e\xaef\x93e \xb4(\xbb\x83\x0f\xads\xe5\xbck\xb6<\x88S\x06H\x88}\xb7\xb8>\xb5\xfeY2S\x8c\xbf\xa4v\xe1\x15\xc7\xfez\xadL_\x1b\x14w\xeep\xad4\xe9Ԛ\xb1I\xeb¸\x02\xa1Kd\xff\x12B\x15Q\x95tk\x17\xbdv\xee\xe8F\u007fv;\x9e\xde\xf4ET~\xf8lK\xa6!\xad!\x99\t\xb0vQY\xc0\xa6y\xab\xd3\xedl\x13\x174\xf4\x99\x06؊\xac\xd8\xdf\xcd\x0fN\x8e\xf2\xef\xf3\u007f\xbcNx\xf4$&kn\xe2P\xad\x9dp\x9f\x1bIj\x8b\xbf\xb7\xdb;\xb9\x89\xd0\xde\xe9C\x9d\x17\xf5b\f\xa4N\x16(\t\xe3\x1eT\x8d\xabQ\x0f\xc6\xee\xcd\rt\xbc\xe7mȌ^\x13њqKL\xf5\x8e\xe2\x851\xa4\tl\xb5\xe0\x064\x19\x95\x1f>\xdbұn\xbc\x9a\xcc\x04X\xb3\xa8,`.\x16\xc2\xd6\xc7\v\xeb\xfbY{܂\x80\xf5\x98<4bd̪\u007f@45JkN\x1f\xbdF_\x9fG\v\x98\xa2-\r\xe6\x16\x12\xb0\x1f\xb8N\x1c\x9c\x15\xd2/t\x8dB\xe2\x01:\x87\xcf!*L\x9f\x98X\x86i{L\x15\xe1\xe5\x10w\xc4,\x97\x18\a\xefF\x13r\x04\xb6\xee\x8aΏ\x9cm\xe9\x9cѬ\xb1\xb8\xc8\xc0\xc2QY\xc00\xebzy\x85HD\x0e\xb3OX\x13\xdf\xc3?\f\x1f\x03\x12\xa2\xb8h\xbe `s\x9dQ\xf1$\xe3,\xb0\x1f\x11\xb0\x17\xdcp8\xf7\x8aAT2\x17\xba\x8c\xaf\"\xda\x19>p\x86e|q\x00\xc7%\xff`\xfccr\x8e\xa3\xbd\xb8\x17\xc5\xf8\xab\"g[:\xbe\xec\xe81.\xb0nP[\xc0\b3n\v[\xfd\xdegr\x89A=\x06M\xf3I\xc2V\x00\x94a\xd1\xd9\x15\x1d{M\x100\xca\xdb\v\x06\xdd\xe1\xb3Ϣl#\xb9\x14Q\xc0\xe6\xca\x04\x83\x9b,s\xaeX\xec\x80a/j\xc2\x16D\a\x8f_\bݫ\xd2/\xf0\xf8F\x84θʷ\xa6\xef\x99Ǿt\x84\xd2\xe8:\xe0\xd8*.Z\x9d\xcf̚\n2r\xab\xc5\xef \xf3\x16\x1eG\x11p\xce\xe3\x83Z\xba\x96\xb8\x85\x14\xa9\xc3u\xe4\xd5\"=[\x1c\x82\xf7k\x8a+o\x12q}\xa6\xe3\xb8o^\\<\xaa\xaf}'I2\x9b3\xe9k(\xa8;\xb0(T\x170/\xcf\xf3f\xf6\u007fn\xed\x0eE%j\xb7:\xdb\xf8\xe6\x01\xf8/L\xc2\xec\x04\x8b\xfaa\u007f\x1e\x95\u007f\xf4\xca\xdc\\\x87\x91\xa6\x86\xb9\xaf\x1e\xf5\x9d\xe5\x1e\xcbm#\xb9\x94P\x0f쩽\x8fk\xb5\xdb\xff\"\xecpv\xb1\xb2@\xce \x1eʡ\xdf'\xa6\x1dx\x90\xec\xe4\xf3x\xc6Ҽ573\xa7\xba\x9c>I|`\xb3\xb10H\xd87`\xcb-\xb4\xd9ll\xe4_\x91v\xdczU\x9b/|\x0f\xedG{p,\xa2\v\xdfg\xcb<\xe3\xc5\xde\u007f͢\xa1G\"g\x8b\xc3\x15\xee\xc6H硪 \x9e\xeb\xeb;\\Yl\xb8Y\xbf\xfb\xa5$\xc9l\x06 \xceҺEu\x01\xc3^\x8f\x83E%rR\x19\x13\x04\xcc\xc27\x8d\xbb\x9d\xcd\x16\u007f\xb2\xb2\x80\xf2\x10\x92\xf6\xa4\f45\xdbG\xfa*\xc1\x13\xe7嶲\\\xe5!\xe4\b\x17\xad\x8a\x18۴\xf8s\xcdI\xace\xb1<\xf3\xd1._x\x94\x1f\x8e\xdc\x16\x1eBZY\xec\xf0!\xd4\xc2\xf6&뢝\xf5\x94\xb0\v\xbf\x82v\xedJ\x174\xee\x1bf\x8f\x16\x1e\vQ誸\xd3oq\xf0mT\x12c7\xba\x15\xaf<\xb0\xc6Q_\xc00\x8d\v\xd9M\x06\x90\xce@ \xe0n\n\x90o_\xab\x89\xde\x18>3D\x8cN\x8a\xb2\x80\x9d}\xfc\xf8\"\x130\xfc\xaa\xb3\xf6h\tw\"\xcaV\x9a\xab,`\xfd\\l477\xf2\x15\x1e\xf9ԇ\x98\x8b<_\xea)\x8f\x15\xb0\xd2m\xfeyBN\"UڶSL\xf4\xa6\xfb\xb0/\xa37\x81i\x98\xfa\xa3s\xef\b\x86+t\xa7\xaa\xe8e(_\x92\xa4\x17\xda\x12[\x12X\x17\xa8,`~a\xb00\xce\a&\xf9\x10\x1e\xdc\xcb\x02\xdb\xe2^\x98\x92\x98\x94\xb8N\xfc\xa9{4\xf5\xf8\xd0\xe1\xc6~\xfb\xe9(\x01\x93\xe5*\v\xd8DdnE\x98\x80Ʊyt\xb3c\x13\xfb\xcc\xf2wH\x8e\xc4\n\xd8v\xd1\x1f\x96 ڑ\r\xb5\x89\xcf/\xe7\xb5m\xb8]\xbb \xaf\xe7\tѕw\x96\xeeTE\x9c\u007fUR?\xe0\x10D\xba\\\xb7\xa8+`\x81&\xe1k\xf7\xa1)\x10\xf0R\x1cf\xaf7\x80G\xcd쟹g\xd1\xd3#\xd7\x1fL\x94\xeeIz\x1f\x94\x88\x13\xbf\xb2\x86>K\xbc \x110j+\xcbU\x16\xb0٢V\x1cCnC6ι\xb4\x8d\xa5\xf3\xa5\xcf\"\xe5\x02f\"}\xb3\xf2m\xa3\x8c\x04\xee\xf8R\xad\x1fW\b\u07b3\xe3\xfb\xf1\xfe\xe3\xf1-%\xd4\x1f}\xc2xEw\xe2\x850\xaf\xd3\xc0\x03\xec\xf5\x8a\xba\x02\x86\x9b\xbb\xe8\xab\xdf\x12\x9a\xb9(\xf8\xc0\xbcl\x1a\x85\xcf\xf4 N) \x8cш\xf1k\xc1#\x84\xdd\r\xa2O)\"`\x87\xe9}\x1d\xac:!\xb7\x95\xe5ƙFq\xa12\x88\xa3\xd9[\xb0\x1f\x1f(\x10\xfc\xf1\xb2\t\x13a\x01+,\xc4x\x9a>M\xec\xa2/\x18\u007f!\x1c\b_\x99\x04\xaf\xe6s<\x8aΥM\x93\xf4\xa0ƣQ\xf0\xbbO\xd6\xc5L\b\x1b\x13\xda\xdax\x9b\xbe\xc6\x11\xb0@\xde^\f\xacST\x160\x17\xdf\xedt;-\xe2L\xfc\x80\xc7a\xf6\xd0\xef\xec\a\xa6\anGSۇ\xfe\x9d\xdc\x1a\xa4\xb5\xa8\xa3\xfft\xb1\xd0\x03ۇ؍Kg\xe2O\x88\x93\xb8Z\xb9\v\x9d\xb7\xab\xb8\xb2;\x13R[I\xeeK:\x13\xbf\xc3n\u007f\x19z\n9!\xea\xd6s\xeeN\xccɪQ\x03n@\xa4\xab4?Ȟ72U\xf2\x0f\xdal\x9a#6\x1b\xfb\b\xcfi.\xb5\xefʠޱS\xa8\xd4\xd2^\x81\x84\x89\xc9\xe2\x95ɸ\x84\\\xb8yk\x80\tW {O\xb6\xc2\br\x1f\xda\x1cӕj\xdc]\xdf\xff\xed\x15\"c\xef\xfe\xc4\x1e\xabRW\x9d$I\xb9\xfc\x9e\x13a\x81\x14Fe\x01Þ\x1e\x8b\xa9mP|\xdc\xe8\xa1.06\xa5\xc8\xd5nn{\x00\xfa\x95\x9c\xb9\x1b\x9f\xe9\x8d\xe2|\b\xb3\x96Ͷb\xbf\x85\x14\xfad8\xd8QYt\xa8\xfe~\xa5\xce(\xb5\x95\xe4^\x14}J\x17\xf0\\\tK\xe8BO\x1f[\xf51^0k\xc68vd\xb4c<\x9e\xc6\x1c\\L\x95\x86\x844b\xe7\xf6\x1f\xcfJ/\x14\x9e\xbdt\xed\xd4f}zW((^\x99\x8cm\xa4\xb3f\xd3X\x85G\x02\x975\x97c\f\xc8Xt3\x8a}\x8e3v\xba\xac\xc48\x82\xf13\xe1\xc2k\xb1,I\xb0\xa5\x9f\x8c)\x04\xac\x17\xd4\x160`\xb5\x12\xbc\xa1\xebKf\xf3\x1eL3\x17~\x01J\xf8ۣv\xb4xgV\x8b\xa6\x02\xbe\xf9\xd6/ `\x80H\xb0\xc3\xf0*\x99\xcd{\xc0z^~W\x82g\x8f\x01sֱ\xf8G\xe3\xe0͆\xc5(\xd63 `\xc0j\xc1\xa3\xad\x86\xa9\xcc\xc0\xe2\x00\x01\x03\x00 e\x01\x01\x03\x00 e\x01\x01\x03\x00 e\x01\x01\x03\x00 e\x01\x01\x03\x00 e\x01\x01\x03\x00 e\x01\x01\x03\x00 e\x01\x01\x03\x00 e\x01\x01\x03\x00 e\x01\x01[\x0eJ\x91\xb6\x1cb\xc4\x01\xc0\xb2\x03\x02\xb6\x1cxz\xcdy\xda\xc5\xff.\x19\x00\x80š\xb6\x80y\xba\x9aM\x96\x81н\xed\xe0\xe9\"\xac\xf3M\xe2\xe2\xd2͉J\xa6\x18\xbdh<\x99\t\x00\x00\xef\x89\xca\x026\xcd[\x9dng\x9b\xb8\xa0\xa1\xcf4@\x17\xc0\x9b\xe1G=\x84\a\xfcZ\xba\xe5\x87 \xd4\x17\x00,;*\v\x98\x8b\xa7\xab\xaa\xf8x\xc1Ad\xedq\xb3\x15<\x1d,(QӚ\x8a\xcc\x00\x02\x06\x00ˏ\xca\x02&\x04\x16\xf4\xf2\x1e\xbaq\x98}\u009a\xf8\x8c\xbb\xb7\xd6Ժt `\x00\xb0\xfc\xa8-`\x84\x19\xb7\xc5J\x97\xb5\xf3\x99\\8\"`N~:A\x99\xd4c\x1c-(\xee!\x00\x00\xef\x81\xea\x02\xe6\xe5y\xde\xcc\xfaa\xd6n,\x11\xb0p\xa0\xa25\x82_[0\xe0^P\xe8C\x00\x00\x96\x8a\xea\x02\x86\xbd\x1e\a\x8bJ\xe4\xa42\x16\x1607/\t\xfc\xbc&\xb8\x8b\x10ڗ\xcc\b\x00\x80\xf7A}\x01\xc34.d7\x19@:\x03\x81\x80\xbb) \xf4R\xba-Iʤ\x1a>\xed\xd6\xcb=kM\x94\x01`\x95\xa1\xb2\x80\xf9\x05\xb9\x1a\xe7\x03\x93|\b\x0f\xcd1?HP*\x15\x19B\xdd\xc9L\x00\x00xO\xd4\x15\xb0@\x93\xe0\xd9~h\n\x04\xbc\x14\x87\xd9륚\xe6]s#Hx\n\t\x00ˏ\xba\x02\x86\x9b\xbb\xe8\xab?\xec\xb1\x0f\xf9\xc0&\xf9\xb5\xf6\xc3\x1b\x100\x00X~T\x160\x17\xdf\xedt;-\xe2L\xfc\x80\xc7a\xf6xi\xcaɯ\xb5\x80Z\x83 `\x00\xb0\xec\xa8,`\xd8\xd3c1\xb5\r\x8aj\xe5\t\xff\x00\xd2}+A\x99\xd4\xc3\xef\x19-\xd5x\x92Y\x01\x00\xf0\x9e\xa8-`\xeb\x83\xfd\bmmOf\x04\x00\xc0\xfb\x02\x02\xb6\x1cxF\xd7\xda3\t\x00X\x95\x80\x80\x01\x00\x90\xb2\x80\x80\x01\x00\x90\xb2\x80\x80\x01\x00\x90\xb2\x80\x80\x01\x00\x90\xb2\x80\x80\x01\x00\x90\xb2\x80\x80\x01\x00\x90\xb2\x80\x80\x01\x00\x90\xb2\x80\x80\x01\x00\x90\xb2\x80\x80\x01\x00\x90\xb2\x80\x80\x01\x00\x90\xb2\xaco\x01+E\xdarg2#\x00\x00V+\xeb[\xc0<\xbd\xe6<\xad\xb0\xb4\x8f\xb7 \xfc\xebkI\x12\x00\x80Ռ\xda\x02\xe6\xe9j6Y\x06B\xab\x17:x+\xdb\xfa\x06n\x99n\r\xacȚ\x86\xbdH\x8c\aސ\xd6\x10ʓ$\x01\x00XŨ,`Ӽ\xd5\xe9v\xb6\x89\v\x1a\xfaL\x03lEV_S\x1b\xcdmZ\t\x05\x8b\xac\x9cj\xddx\x15\xc7&\x01\x00X\xbd\xa8,`.\xb6\xf6\xbd\x8f\x17\x1cO\xd6\x1e7\x130\x9b\x85\x06垷\xd8\x12\x94\\.$K?\x9fѸ\x15\x92\x00\x00\xacZT\x160\xcc:Y^!\x12\x91\xc3\xec\x13\xd6\xc4\xef\x11|N\xed+\x11\xdbV\"`\xbe\xec\n\x85$\x00\x00\xab\x16\xb5\x05\x8c0\xe3\xb6Xi$\"\x9f\xc9%\x06\xf5\xf06\xf5z\xfd^[\x937I\xc9\xe5`\x1c\xf5\x86\xd3g\xd2g\x14\x92\x00\x00\xacVT\x170/\xcf\xf3f\xd6\x0f\xb3v\x87\xa3\x12\xcdt\x93ܮ\x15\x91\f\xbf\xb6`\xc0-D\xab\xc4\x03\x91\xde\xd8\x00\xc4\xe4\x00\x80Տ\xea\x02\x86\xbd\x1e\a\x8bJ\xe4\xa42&\b\x98\xbf\xdb\xe2\xf48-\xdd\xf3\xc9\xca.\aw\x11B\xfb\x84\xa4\x1b\xdd\n\xe5J\x92\x00\x00\xacV\xd4\x170L\xe3Bv\x93\x01\xa43\x10\b\xb8\x9b\x02\x01\xea\xc4\xf7\xb3܁d\x05\x97\x01\x9fv\xeb\xe5\x1e\xd1c\xefF-\xa1lI\x12\x00\x80Պ\xca\x02\xe6\x17\x06k\xe3|`\x92\x0f\xe1\t\x98\x1e\xb2܇\xa6@\xa2\xb2\xcb\xc3\x10ꖤ\a\x14\x92\x00\x00\xacV\xd4\x15\xb0@\x93\xe01'R\x15\xf0R\x1cf\xaf7\x10\x12\xb0ѕ\x11\xb0\x88\xb3\xabN\xe3SH\x02\x00\xb0ZQW\xc0ps\x17}\xf5[B\x13&\xc4i\x14\xe2\x10r\x85\xa7Q\x04\xf2\xf6*$\x01\x00X\xb5\xa8,`.\xbe\xdb\xe9vZę\xf8\x01\x8f\xc3\xec\xf1b<\xd3bq\xb8\x1d\x96\x96\x95x\f9\x18\x11\xb0\xcbhT!\t\x00\xc0\xaaEe\x01Þ\x1e\x8b\xa9m\xd0/\xeeP\x17X3I\xf8\x87\xda\xccmC\xfe\x84%\x97\x03\xbfg\xb4T\xe3\x11wl\xe9'ql\x12\x00\x80Ջ\xda\x02\xb6\xba؏\xd0\xd6\xd0\xca\x13-\x9a\x8a\xf9\xd8$\x00\x00\xab\x98\xf5-`\x9e\xd1\xf0O\x1e\xbd\xd9\r\nI\x00\x00V3\xeb[\xc0\x00\x00Hi@\xc0\x00\x00HY@\xc0\x00\x00HY@\xc0\x00\x00HY@\xc0\x00\x00HY@\xc0\x00\x00HY@\xc0\x00\x00HY@\xc0\x00\x00HY@\xc0\x00\x00HY@\xc0\x00\x00HY@\xc0\x00\x00HY@\xc0V3\xc35\xaf1\xf6\x16\xb4c\x00\x00\x94P[\xc0<]\xcd&\xcb@h\xb5S\aoe\xdb\xc0x\xbb\xa9\xcd\x19\xbf\xd4r2\xb9\t\xe5\xc5dz\x8fmI\xdf\xfb\x81և\x9d\xaa-6\xd4?2\xbc\xc6_r\x1c\xa7\u007f\x91\xcc\\\xc2\x1d\xae5H6\ri\xf0\xe3r\x00PDe\x01\x9b\xe6\xadN\xb7\xb3M\\\xd0\xd0g\x1a`+\xb2\x06\xac\xe6Q\xf7\x03ӃD%\x97\x8f\xc1#\x9a\x98\xbc][\xae\x1fI_آҏ\x9e$>>V\xfc/\xf7\xfaNp\xdc\u007f\xe0\xef\xed\xf6Nn\"\xb1\xb5\x94N\uef90\xb0n\xbc\x9a\xd8\x12\x00\xd6)*\v\x98\x8b\xa7\xeb\xd7\xf8x\xa1\xb7e\xedq3\x01{h\xa2!m]\xa6\x85)\xc6\a\xa7N\x13\x9d\xe3EWq`\x81WSs!\xe1\xe1\x1fJ\xce\xcea<[I\x04\x8c\xf0x\x11\x02\xf6B\xd7\x18J\x9eф\x97\xfd\x01\x00 \x82\xca\x02\x86\x99*xy\x0f\xdd8\xcc>aM|+[)\x1f7=\x88Sh\x99\x89\x150\x17\xb2*\xd8)S\x95X\xc0\x1a\xf5\u007f\xa1\x9b\x0e\xee9\xdd,F\xc0\xae\x18fCI_vE\"K\x00X\xaf\xa8-`\x84\x19\xb7\xc5J\xddK>\x93K\f\xea\xd1fc\a\xda\xef&*\xb6,xʳ\xb3\x0e\x88CȦ\x82\x8c\xdcj\x1f\x8dՍ\x18ղ\xdc\xf1\x8d\b\x9dq\x95oM\xdf#]\xacu\x98\x13\xa8\xa1;\xf6\xdaú\xb2\xda\xc3A\xd9\x19*\xaf\xb0ͫ\x8e9\xba\t\vX\xb0\xb3F_\xd5\x19\x8c*\x16\xbc_S\\ySЭ\xb9\xe2p\a\x8ct\xc1\xd2W\"^\x00\x00\xacvT\x170/\xcf\xf3f\xd6\x0f\xb3v\x87\xa2\x12\r4\xb1\xa8D涄%\x97\x01Wf\xae\xb9\xfd\x17HC\xd3\x15iǭW\xb5\xf9DZ\x1f\xdaZP\x9d\xcd\xe6\x91\xe5\xceX\x9a\xb7\xe6f\xe6T\x97#\xe9hnv\xc2^i\xb4\xdb\xed\xb4{\xf5t\xf7\xc5\xfe\xb1{e\xdc;\xe9\x19\xe6\xb8\x0e\xe9nX\xc0.\x16}3\xf2M\xd1ŨbW\xb8\x1b#\x9d\x87\xaa\x98\xae=\xe5\xec\x91r\x03\x92\xe0o\x00\x00\x84P]\xc0\xb0\xd7\xe3`Q\x89\x9cT\xc6\x04\x01\xf3\x99\xad\xde\x19O;oIV\xf6C\xf3\xe96r\r\x81\xed\x1a\x92\xb4\"3\xa6A\xd6X@\xee\xf0\x10R\x96\x9b\x8fv\xf9\xc4A\xb0\x84\xf0\x10\xb2\xf3\x10\u0560\xce\x12Y\x0f\xec\x05\xf7\xadt7$`#\xdc\x18y\x1d\xe3Fdņ\x99\xd7\xfe1\xd7'\x98<\x8f\x94s\xa3[\x18\x00\x80h\xd4\x170L#@v\x93\x01\xa43\x10\b\xb8\x9b\x02t4鵒~٠U\xed\xf9N>\xc4\xd3\xcd\x19\ry)\xdd\xe6\x9f'\xe40gSX\xc0d\xb9\xf9\x8a\xae\xf4\xb0\x80\xbd4\x1c\xbdq\xefipNvtN\xa7\xd8\x03\xbbr\x82mN|)+V\u007ft\xee\x1d\xc1\xc0F\x9d\xfd\x9cdƅ[\x90P\x00\x00d\xa8,`~an\xd58\x1f\x98\xe4CxhΌ7\x80\x9b\x06\x12\x15]\x06\x1e \xe6|;\xa7!/\xdb\x05\xc7\x17\xdaOs\xc2\x02&\xcb\xcdߡTIĉ\xff\xf6ޅJ\xae쎢\x0fln\x8cmB\x02f<\xcb6\xb55\xb2b'D\x8f\x1a;8!\xf5\xf7\x0f!\xb5\xdf\x1b\x00H\x05\xd4\x15\xb0@S/\xdb>4\x05\x02^\x8a\xc3\xec%ʅ\x99_\xdc%H\x99\x8ax\xd1u\xbaaN\xfc\xf2m\xa3\f:\xa1#\"`\xb2\xdc\xfc\x03J\x950\x01\xbb\xf7\x92\x88S#Ѡ\xb7}\xfaN\xd9\xe1F\xfd+\xba\xe9\xe3^\xd3M\xb8\av\x94\xf9\xec\x8f^\x94\x15\xab?\xfa\x84\xc1J\xcc\x16\xb5Fj\xa9\xd3,pR\a\x00\xac+\xd4\x150\xdc\xcc&L\xf8-=\xe2\xbe\xe0\x03s\xf2D |ͽq\x8b-\x17\x059\xe4Į\x9fhH\xb2\v1\x0f\xdc\x17u\xf45,`\xb2\xdc\xfc\x83Ju\x18\x8d\x18\xbf\xa6n\xabV\xea\xd1\"\xfb\xd7X\xb6\xbba\x92m\u007f(9OF\x87A\xe3Q\xb6\x17\xf1\x81Q?W\x1f-!)6&x\xbf\x1ao3\x9b\v\x95\xe1\xbe\\ o/\x06\x00 \x06\x95\x05\xcc\xc5w;\xddN\x8b8\x13?\xe0q\x98=TB\xf8!\xf7\xc3&\xab\xfa\x9d\fGFNݙ\xac\xb4\x8df'ƧP\xa9\xa5\xbd\x025\x85\x9eB\x0e\xb2\xd1n8w~Ж[h\xb3M\xc6\xd4\xd1Z\xd4\xd1\u007f\xba\xf8%U\xa2\xe2\xd6\xe1\xfe+\xdc#\x96\xbd\x0f\x89\x9a3\xa27\xde\x1f\xae\xd5\x11\xe1zIg\xe2w\xd8\xed\xc4\x16\xd7s\x8dÍ\\=\x96\x17k\xdc]\xdf\xff\xed\x15A\xc6\xf0s\xeeN\xe8\x1c\x97\xd1(\x06\x00 \x06\x95\x05\f{z,\xa6\xb6A\xbf\xb8C]`\xcd$1j1[G?\xd0O\x0f\x17\x85k_\xd6֓\xe6\x8d\xe8\x18Iw\xed\xd4f}z\x97\xf4\x0f\xb3\x98\xdbk\xa3\xf0k\x81P\xeex\x1aˍ\xed\t\xcd\xdd\xf8Lo|L\x12\xf7\x8d\xb7\x0f\xeb\fFA\xbf\xb0Yˋ\x06S\xb5\xfa\xb2\xb3t\x1e\xfeE\xd1\xc5Eǜ\xc1\xce\x13\xfa\x13l\x1e\x98\xac\xd8\xd8\xe9\xb2\x12\xe3\x88X\xb0U/z\xc1l\xe9'1\x00\x00\xb1\xa8-`\xc0\xc2\t\xdeб\xbeX\x8b\xa6B:y\x16\x00\x80\x10 `\xab\x98`\x87\xe1\x15\xc6\xdelX\x8c\x02\x00\x94\x01\x01\x03\x00 e\x01\x01\x03\x00 e\x01\x01\x03\x00 e\x01\x01\x03\x00 e\x01\x01\x03\x00 e\x01\x01\x03\x00 e\x01\x01\x03\x00 e\x01\x01\x03\x00 e\x01\x01\x03\x00 e\x01\x01\x03\x00 e\x01\x01\x03\x00 e\x01\x01\x03\x00 eQ[\xc0<]\xcd&\xcb\x00]\xf9k\xc6\xcc\x16\x946\xb3\xa5u<\xed\xe6.O\xe2\x92+¨\xb0\x88N\xda\x03awr\x13\xca#\x9b#$+\xc3\x15k\xedؓ\x91]ڛ=\x1d{\xe4C\xe1.\xcf\xc9\xf8\xa4N\xfd\x85\xd3\x00`u\xa2\xb2\x80M\xf3V\xa7\xdb\xd9F\x174\xf4\xf1\x0f=\x04\xb6X\xb3\xdbds\xd9L\xab0\xfa\xf4\xfc\xa0\xedkt\xd9\x16Z\xc0\f\x0f\xb2\xe5\xa7\xdd6\x92\x1b\x1b\xe7\xac+c\a߲\x1d!g̑\x0f\x85k\xf3'\x97\xac_d~\x02\n\x06\x00\f\x95\x05\xcc\xc5S\x95\xf2\xf1N\xfa\x12\x16\xac@3\rY1м\x12K\x1a&eH&U\xa1(\xdeC\xb1\x02\xe6\xcd\xdcOtηm\x19\x05l\xffV\x1a\xdf֙\xf1E2C\x00X\x1f\xa8,`BTE/\r\xdf!\x110\xa7\x89ޗ>\xd3\xf2\xdd\xf9\xef\xc1\x82\x05\xecT:\x1b;^B\n\x83\xcb\x0fD\xdeV\xb69\xa0\x18\x1e\t\x00\xd6\x1fj\v\x18a\xc6m\xb1\x06d\x02\xd6s\x97m\xee\xaa\x1c\xd5c~˦/r\xb2{\x8fg\x15\xd2\x11\xed\xc1lMξq\x92\xed܈\xd0>\x9c\x83P\x16\x1b8\x86\xa5\xcaS\x9e\x9du\x80\r!\xa5\xb9\xb8\xa9 #\xf7\xffo\xef\xfcc\xe28\xee\xfe\xff\xfdg\x10\xac\x8c\x0eN\x1cB:\xa4\x039\b\x13Y\xc9`|',\x1cS\x041\x17\xd1`\x93\xafj\xe3\x1f(\xa9\x12\xfb,\x13\x9b\xa8NS94D\xc6`\xf2\x03\xc5%ND\x83c\x14\x1axL\x1d\x91\x1fv\xb8\xa8\x8ay\xda\xe2|\x85\x1e\x92HϵV{\xcf#5\x8e\xb1]\xe1m\x1cR\x82}\x86Z\xa3\xef\xce쯙\xe5\x8e=(\x06\xce\xf9\xbc\x12\xf9\xf6n?\xf3\x99\x99ݝ73\xb3\xb3\xfb\xa9\xa1\xba\x9c͂Gʡ\x034\xd9\xe1\xfb\x1c\xabiȣ*\x94\xd2X\xe3q\x14\x8e\b\x9b\xb2\xdcS\x98\x95\x92\xb1\xce-[iv\xb17Q\x8f\xa4k\xf1\xdc҅qu\xaf\x1a\fes\xf6\xact\x00\xf0\x83d\xc9\x05,D'\xeei{\x0f7v\xbd\xd2\xd8\xdaC\xfb^\xedj\xd0\xc3ޥ\x0el\u06dd\x8ej֢\x8czW\x03\x8d\xc1\xed\xefn\xf3%\xf5+\x03ھ@R\x9f܌Z>dF\xbaT\r\xa5{\x9a\x8f?\x88$Y\xf8U\xf6'Uw\x1cʸo\\\x1eKj0=o\x96\xea:\xea\xa4rE\r[\x93QF\xe0@z\x89\xb0\xa9$\xdf\xfcJWc\x06\x9a\xf5\xaa\xe8\r\xa8\x90~\x8c5\x1fRi\xd6g\xdf8.\xb9\xcag\xff\b\x00?D\x96\\\xc0\xe4\xd0\xe8`\x9b:\x89\xdfrv$\xd8vLi\xa1-\xfdlO\u007f\x8bM\xd2E'\xb3\\\x11\xae\x0ey\xb3\xd2w\n\xb7QU\xcde\x11l\xe5\xcd\xf9\xa1,\xfd=κT\xad\xc9V\f\xc6WK\xe2\xaf\x1d\xa8\x99};&\x8f S\u007f;Q'\xfb\x97\xf6,%\xa7҉*ϐ\x85\xcd\xc3\x19T\xba~\xe1\x9c5\xeb7\x1cP\xe3\x1e}9\xac\x12\xe5\x8e\xe6\xf8\xe6\xd4\x159\xd6\x06\x80\xa5g\xe9\x05L\xa6q!\xbb\x94v8H;_\x97\x9a\x15!hg\x01\xb2\xe5\xee\xf6\xb9\x93->\x99\xc7\xe4>\x14\x96kK\x95\xed\xd0\xe1\xc2\xect\xb4\x9a\xfd~i\xb5˧\xdbhR\x15FllW'\t\xbfʥ\xd9cW\x15\xb2\xfc\xf2X\xb2\xd9\x03\xf3粏\x9c\xcd\xca?\x12\xfd\x87\x05\xff\xe66G2ݏ6~8\x1e\xa5{\xa52\x8ctfߚ}T\x0fZ\t\x00?x\x96X\xc0\xc6\xd4.\xc7\xd9F\xa3\xebѣ\xa8\xd6I\xb5E\x1e\xd7\xc3\xdd.\x19\x99\x9dr\xbf$\xcb;\x14\x01\xebweն\xf7ܯ\n\x98\xfc\n\xea\xd5m4\xa9:\x83\x98ʪJd\n\xd8jMg6\x18s`cJ\xe7k\x8d*\u007f\xeb\xf2\x95\u007f\xa4=\xb2>\xf7\xcfm\x86\x1b\x1f\xcaA\xae\xd8\xd1:z:Tz\xac;¥\xc9\xcd\xd1\x12\x00\xc0\x0f\x91\xa5\x15\xb0\xf1\x16u\x9e\xfeæq]\xb5\xba;hdnuRl\xc9GF\x9c\x80\xe5\xe4\xd32\x94\xa8\x026\x9a\xb9\xcb\x1d\xd2l4\xa9\n!:'/['\xf1˳\a\x18!\xe3.d\x1b\n\xc9~u\x96\xdd\xcdz`4\xaa\xb7&`\xc6\xe6\x99\x1d\xca?\xe1c\xa9\x87\xe5y2z\x9fs\x96\xa6\x01\xc0\x0f\x96\xa5\x150\xb9\x95\xce\r)CH\xa5\xaf\xd5\xc1\x06\x8c\xa1\xe6\x0f\xe9:0\xaak\xddK\xbf\x0e\x8c\x13\xb0,:\xb7>\xbe\x9a\t\xd8X~\x9d\\\xb5V+\x8d.U\xf9Y4\x86\xf8*I\xfc\xb5\x13\xb5я]\x01\xba\x0e\xacD\x19\x12\x8e\x17\xb8\xe9\xcc\xd81\xe5\xc7cl\xac\x17U\xc0\x02l\x92L.\xa8\x92-\x8c\xd4ώ\xfd\xcdq6\xd33\xa4\x94\xef.\xae\xf5\a\x80Db\x89\x05l\xa8\xb1+8\x12d\x93\xf8#\x8d\x9dC#g\x9a\xe8\x8a\ny\xa4\xa9{\xb8{\xe9W\xe2\a\x9d\r\xe1c)gå\xf7\x8f(\x92\xf2\xd0\xe1\xc0}(\xa3\xbe\xefRoUƈ<\x9c^\xd3;Ư\xc4\x1ftd\x05\xea\x9cI\xc9\xcdAu%~CO\x0f-\xf0\x0eT\xdav\u070f\xe8\xfd\x87NG~\xf3\xf1\a\x93\xe9\xe0\xb3<iGǎ\xa4r\xa5\xc7ԓ\xb2\xb9O\x1e\u061c\xd23\xcam*\xb9\xa5\xed\xe9h\xf7\xa3Y\vG|Qb\u007f\x9b\x9cH\xcd\xec\xe8\xe9\xe9\xf1g\xcda\x03\x00? \x96X\xc0\xe4ѓmM\xed\xea\x939_v\xb56w\f\xaa\xfd\x9c\xd1Φ\xe3\xa3s\xa5\xbb\x1b\x8c\xbb\x10jMG\x8e6:\x855\xde\xe0\x912J\x9b\xb3\xa5\x82N\x84P\x8d\\\xad\xfc\xdb-\u007f\xc8=\v9\xe4s\xba\xb75'\xa3*\xf6,$\x85\xce\xfd˝\xf7g8ר\v\xd9\x06\x1ft\xb8|\x83\xcc\xf5\xcfW;V\xffb\x9c.\xfeB(eС\xfc[\xc5m\xca-\x05\x81\xac\x94̂\xd9\vߚ3\x1ag\xfdfR\xa0e\f\vY\x01\x80\xb1\xd4\x02\x06\x00\x00\xb0h\x80\x80\x01\x00\x90\xb0\x80\x80\x01\x00\x90\xb0\x80\x80\x01\x00\x90\xb0\x80\x80\x01\x00\x90\xb0\x80\x80\x01\x00\x90\xb0\x80\x80\x01\x00\x90\xb0\x80\x80\x01\x00\x90\xb0\x80\x80\x01\x00\x90\xb0\x80\x80\x01\x00\x90\xb0\x80\x80\x01\x00\x90\xb0\x80\x80% K\xfe\xd6\x0e\x00X\xa1\x80\x80%\x1a\xa3~\x17\xda`g\x04\x00KD)\xca(_\xf2\x17\xf9\x99\x80\x80%\x18\xe399\x8d'\x97\xfc\xc5C\x00\x10\x83\xd1\xee朌勴\xbc\xd4\x026\xda\xd9\xda\xd4\xd6K\xeb{\xa9\xb9\x91\xa2\x87\xdd\xe9^F\x15\xffw\b\xadu\xaa/\x86~\xb7\b\xab\x14\xbdk\x93\xe4\xdf\xe2\xac\xfa*\xc4\xd7iN\x0f<\xf2\xd6u\xf5\xd7\x0f~\xf4\xdb\xd8I\x9e\xc3\xf8\x1d}\xfbgJ2\xef\x17\x16\x83\xf7\x1e\xc0\xf8S\xf9\x13e\xcfWr<\xbc\xee\xfd\x15\xfb\x14\x9d\xcdY\x86\xb8\bU\xb9R\u05c9\xe3c\xfa\xe6\"Ǽ\x03m\xbe\x8a\x8bhY\xde\xf3\xe2WcX\xfcQ;Y\x9f\xaa_\xbf(\xc2?\x96c\x1c\x1d\x85Ϟ(\xae\xd8\xffQ\xc5_g\xef\x89\r=\xa8\x18oz\xf2\xbfb\x19\xbc\xad\xec~U)*\xc6o\xc52\xf9\xb7\xb9\xfbդt\xa3\xb3v&w\x8d%\x16\xb0/\x1b;\x82#\xc1v5*ч\xa3\n!}G\xff\xdc)\xef\x12\xdd\x03v\x166lˮObu\xf8\x15>w\xeeM\xfc\xfa\xb9s\x0f\xfc\xca.\xcd|\xf9\xe8?\xcd\xed~\xf5\xdd\xfc\xff\xf3+\xfc\xf6\xb9\xf7\xf6\xe3\x97\xd4_\u007f[<\x87j\xfe\xe9\\\xd1K\xe6\xb6R\xc8O,\x06_\xbf\x8b?\xba\"_y\xe4\xb1?\xcaq\xb1\xa5h\v\xfb\x14\x9d\xcdY\x86\xb8X\xeb:\xbc9U\xfcc\xce\xde\x1d9+\x86\xb0\x1d\u007f\xd9\xefݭ|\xec\xf6\xee\xffK\f\x8b\xbf\u007f\xc2N\xd6'Wԯ\xd7?\xf9\xd9z9\xc6\xd1Q\xa4\xb9\xf8\xff\xbe\xf5\xce\x16\x8c\xff߬=s\xf0\xf5'E?;\xf7ћ\x8fx?\x8ba\xf0\xd5\xdb\xf8տ\xca\u007fUNd\xec?\x1b\xfc\x99_\bw\xbf\x9a\x94(Q\x9e\x97\x8c%\x16\xb0!\x16͖\xbd\xfd\x9e\vl\xabt\xccږI\xc0\xf2J\xed,l\xc8\v\xc8\x0e&)\xaf\x17\xc9\xf2\xa7\xf4\xb2\xf0\xben\x97f\xbe<\xb6\xcf\xdc\xd6/\x96\x0f\xb0\xd20\xae?\x87\xb5?\xf0ף$3Y\xff\x92\xb9\xad\x16R\xe4\v\xfc\xb5,\xbfT\xf6\xdf\xd6ߣ\xf35\xdeO\xed\x19\xbc\xb3\xb9\xcb`O\b\x1d\x92\xc7g\x0fF\x16\xd2<\x8e<\xa1t&\xff\xc7\xfbđ9l\xc4\xe3\xf0\xd2\xfah\xbf2\xfeg㓊\x00|\xfd\xc8|[6;\xea_W<\x11k\xffg\xf8\x03\xe5ߏp,\x85\x93\xc53\xbf@\xeez5\x17v\x86\x16\x8b%\x160\x99]\x9f\xa1\xc6QQ\xc0\xba\x1b\xbb\x9b\x96G\xc0\xee{\xc8\xce\u0086\xdc\xe6\x11Ć8W\xbe\xd0.\x8b/\xaeإ\x99/[c\t\x98|e\xe3sѓ\x88\xc4#`\x1f\x14}d\xfd9\x06\x1f\xe1?b\xdd6\x8a\xb3\x053\x14=^\xdcB\x9aǑ\xfd\xbbߑ\xdf~b\xff\xa2\b\xd8\x11\xef\x9f\xe9\xc7\xeb8\xe6h0:\xeaQ\u007f\xc9\x1bK\xd8\xe3\x10\xb0\xadK(`\v\xad\xe6\xc2\xce\xd0b\xb1\xd4\x02\xa6pi\xa4\x8d\xbe\b\x9f\x17\xb0Ka=\xb8\xed\x92ҡ\xbd\xa1\xf9>Y>\x9b\x8cP\xddP\xb9;\xb5\xd0\x1a,\xbb\xd9\xc5^\xf2<\x92\xae\x19\xa7\x8b3\xe8\xeb\xea6\xe4*\x89\x93\xd9\x14\x9evY\xfc\xb1\b\xe3\xa3_<]\xe9}\xe2\xef\xf2W\xfb*\x8a\x1e~\x92\x8e͞\xc3Eo\xfd\xf2\x11\xef\x13\u007f\xa2&\xe7\x9ex\xb8\xa8쉇\xaf\xd3_\xdf|\xb6bӓlJ\xe2\xfa\x9b\x8fy\xb7\xbey]\xf0\xf0[m\x1a\xe315\xbfnA\xc0\xe4\xe7ʔ\xb1\x88\x17\x1b\xb3\\\x86_.c\xa5)=\xff\x8c\x9e\x05w\xed^\u007f\xfb\xb1\xe2G~I\xfbR\x8a\x80}\xb1\xf1U\xeb\xaf\xe6\xa6PH\xf9\xa5\n\xb9BWDݙY\x86w\x8c\xa9\x9dw\x04gf\xc9d\xe3\xa0r\x8ce\xa8\x87\xb7F\xd9\x0e?\x94)e\xf9\xf4y\x15\xa3y\xf4\x14f\xa5d\xacs\xb3\xed\x96|\x87\xa7&\xf6\xd4\xf1\x91\xfdo\ue55fx\x93\n\x98y\x1c>S\x0e\xea\x93\xd7+0\xde\xc8\xfe\xc4\x18\xc7\xe1O\xfb+6\xee\xfb\x99\xb5e\x9bE\u007f\xe4\x19\xf6\xc3_^\xbf\u009d!\xeelF?\xb1\xba\x80\xfd\xaa\xe8\n猿4x\x013\xfcr\x1e\xaa6\xf9\v\x00\x00 \x00IDAT,g~\xd61\xfb{Yё\x8a\x8a\x8f\x9e߸\xf3\xeb\xe5\xac&\x9d\x97\x9d\xfdn\xf4\xa5b\xc9\x05,D'\xee\xd5(j]\xaf4\xb6\xf6\\\xd2~_\x0e\x01\v\xf7\xf6x\nzzz\x14\xf1\xb9\xd4\xd6\xea\xf6\xa4gՔϊ$\xbb\x01\x15ҏ\xb1\xe6C*\xcdb4\xda@\xbat\xe6꺂>6\xf7\xac]\x16W\xdey\xe7\xe1G\x8a+~\xb9\xff\x81\xffV\xae\xc2g?z\xe7I:\x8b\xfa\xd9;E\xf8G/\xfdj\xe3^\xc5\xe2\xf7\x0f<\xfd\xee\ao\x95ῳ_\x1f~\xf5Շ\xd9T\xc9\xd3돾wt\xfdӂ\x87\xaf?9\xf7\xc8\xces\xe7\xceѿ\x8bW\xbf\xec\xces\xaa\xcdV\x13\xb0\xb7\xe8`\xee\xd3s缪\xa2\x98~\xb9\x8c\x95\xa6\x84\x1f{\xe7\x9d-\xdal\x8cq\xed>\x83\x9f\u007f\xef\xcd\x1fm\xbdN\x05\xec\xaf[\x8a\xafX\u007f57\x85Bʻ\xf7\xc9\xfbv\xabƦ3\xa3\f_\x9f\xdb\xf8\xd2_忾\xb4\xf1\xdc\u05fc3\xaed\xb2qPy>\xec9\x86\x02==\xa32\xfd\xc3\xe2\xefn\xf3%iW\x84.`\xfdh\xf3+]\x8d\x19\x88\xfe\x85\xf1'Uw\x1cʸ/悸#\xfb\xffT\xfc\xbf\xde?S\x013\x8f\xc3\xf5\u07fd\x84\u007f'\xbf\xfd\xc0ۿg6zѿ\xd8\xf8\xc8ۿ}\x02[[\xb6Q\xf4+\x98\x9b\x130\xce\x10w6\xa3\x9fXM\xc0\xae?\xb6Ep\xc6]\x1a\x9f\xe1\xf7\xae\\\xb9\xf2\x1e\x16\xce<\xe7\x81?\xf3r\xb4c\xf6\xd1F\xfc\xcbݸ\xecղח\xb3\x9a\xf4\x8fO~\xef\xc82-N\\r\x01\x93C\xa3\x83m\xea$~\xcbّ`\xdb1M\x0f\x96C\xc0da\by\x1fZ\x1b\xd6Ƹ<\xc3\x015\xd0ٗ\xc3*\x96\x90f\xf5\xa8Q\x0e;Ԡ\x1e\\\xc7|+\xde\xfd\x95|\xfd+\xa5=\xbf\xa3\xb4\xe3\xeb[\xe8Y\x97\xd7oT\xfez=\xfd#e\xeb\xcd\x1f\xd1S\xff\xe6F\xf6\x87\xbaR1\xfb\xeaa\xe5\xef\xec{\xecO\xf2\a\xf8=\xc1\x037\x90ؠtQ\xb4a\x96&`\xefi\x1d~M\xc08\xbfB\xc6?V\xd4\xe9\xca#\xea\x9fr\xbd\x90\xbf\xc5o\xb3o\xefP\x01\xdb\xffȏ\u07b4\xfe\xcamr\x85\x94\xaf\x17\xbf.\xbf^\xac\x8d\x8b\xf8\xa1\x88V\x06\xf9\x99\xfd\xca?\xfb\x9f\x11\x9d\xf156\x0f\xaa\x801\x84\f\xb7ѳ\x90\xab\xadv\xd3\x05\xecp\x06\x95\xae_8ǩ\xc25\xb3\x1d\xc7f;Q9\xb2_\xde\xf2\xdcc2\x150\xfe8\\\u007f\xfa\xb1\xbfT\xe87&\xf5\xa2\xef|\x84\x19XZ\xb6Y\xf4/\xf0\u007f\x18~\xf93d\x9e\xcdX'\xf6\xa5+_\xffq/M\xc1\x1fI\xf3\xc4~\xa6\xf5\xb0>\x13\xfc\n\a\x8a\x1fBF9f\x15O+)\u007f+?\xfd\xecrVS\xe1\x84r]\x1a\xa1엖\xa5\x170\x99ƅ\xec\x92\xe5\xf1A\xda\xf9\xbaԬ\x8d\x0fV\x80\x80Is-\xaf\x1aF:\x82U\x1br\xd6\xc8\r\x99ڸ\x93\x13\xb0\xf5\xfa\x8c\xf8_\xde|\xa2r#f\xb7\xed\xd8_X6\v\xf1\xdf\x15\x95Ͽ\xf5\xfb\xeb\xacӳ\x9eMԼ\x89\xffG~F\xbd\xb9\xb7\xe5g\xa2\a\xf32\x1e\xe9l\xcc\x11{`o+\xc9(\x9ax\xf0~\xf9\x8c\x8f\xd2\u007f\xdfTm\xf5B\uebfc\xf2w\x85\x8ag\xa8\x80y?{\xab\xec+˯\xdc&WH\xf9\x8f\xf8\x93+\x9f`\xed\x86e4\x01\xfb\xc8\xfb\xb5\xfc\xb5\xf7#\xd1\x19_\xb2\x18\x98s`\xa1Å\xd9\xe9H\x8b\x92\xae\v\xd8H\xa6\xfb\xd1\xc6\x0f\xc7\xe9\x1f\xbc\xd2챫\nY\xfe\xa8~d&`\xbf¿b\x02\xc6\x1f\a\xf9\xcaֲ'\xf5))\xad\xe8_\xa9\xab\x18\x8eZZ\xb6Y\xf4+Efׄ?C\xe6ٌub\xd9:\x8a\xff\x90\xc5#i\x9e\xd8\xcf\xf0\xaf>\xfd\xf4\xd3\xd7\xe9\x89\xe4\xfc\n\a\xcaf\x0e\xac\xe2\x1d\xa5\xbc_\xd3\xda.c5\x95?8\x19\xee\x86\xe5Z\x9b\xb8\xc4\x026\xa6v4\xcf6\x1a\x1dΞv\xf5s\x05\b\xd8\xdc\xc1\xcaz:T\x84\xc0\xd8_:j\xbaW\rg\a\xb4\xaf\x9c\x80=\xa6\xff\xf4\xa3\x87\x8f\xbc{n\xb7\xaa#\xb4\x85\xab\xd7\xc2Wo\xed{\x04\x97\xfdʜ*9\x87\xffS\xde\xf9$K\xf2\xc4c\x82\a\xf12\xeeA\xea\x81\xd2\x04\xec\xc8F\xf5g]<L\xbf\xb32fY\xc8f!\xb7h\x1d\x80'\xa9\x80\xbd#\xff\xfd\x91#\x96_\xb9M\xdeÛ\xecG\xb5\xbf\x16U\xc0\xfe\xbe\xe9]\xf9ݲ\xeb\xa23\xbe\xc610\x04\xacߕU\xdb\xdes\xbfE\xc0\x94>\xfbC9\xc8EWݭ\xd6\xfe\x96\xc4|\"Ai\xd2\u007f9\xf2W&`\xfcq\x90\xe5w\xcd\xf2jE\xff\x14\x9f\xa3\x1f\xd6\xd9m\xae\xe8\xda\xe4\xd0\x15\xa5W\u009f!\xeel\xc68\xb1\xcf~\xfa\xe9\x17\xd7-θ\x13\xcb́\xf1~\xf9\x03e'`\xefɟ\x16\xb1\xda.c5\xe9\x19꒗\x8b\xa5\x15\xb0\xf1\x16u\xb6\xefæq\xf9\xa4z\xb5vk\x17\xedr\n\x98\x1aR\xf7\xbe\x12\x1b\xdb(\x1cG\xc3r\x89;]\x1fwr\x02\xa6_y\x8f<F'H\xf7Y\x04\xec\xd3#t\x9a\xfd\x1d/\x95\x81\xf5\xcf\xd3}o\xe1\xaf\xe4g*\xe9\x05q\xbd\xf2i\xc1\x83\xb6\xf9\x96\xfaw\xdbr\x17\xf2G\x9a\x95&\x1e\x9c_!c#\v\x99\xff\xe3\xfb\x9f\x8c\xbfh\xcb(\xde\xf3\xfe\xb7\xf8+\xb7\xc9{\xd8\xf7\x98\xd2o\xd0\xef\xefG\x130\xf9\xf9\xbd\xf2\xde\xe7-Y\xf05\x8e\x81!`9\xf9\xf4\x80\x96X\x04\xec\xcc\x0e\xe5\x9f\xf0\xb1\xd4ò\\\x9e=\xc0\bE\xf5#\xabMZ\x81\n\x18\u007f\x1c\xe4?U\x1cy\xf8\u007f5\x1b\xad\xe8\xff\xabj\xf1ӳ\xba&Fяx\xd9j\xb2w\xf0_\x853\x14\xb5e\v'V?\x1e\u00914O,'`\x9c_\xe1@\xf1g>\n\x15\x1fȟ\xaeWk\xbb|\xd5\xfcA݅l\xed\xa4\xff\x8e\xb5\x9d\x94\xe5\x0e\xd6\xf5\n5\u007f\xa8\xeeY&\x01+(P\xbaQ\xa8\x8dn\xc6XQ1R\x1fe\xbaF\xa7\x1d\r\xc9\x1f\xa2Ry\xdc͌\xa2\b\xd8\xc3t\xe3\xfaV\x8b\x80\xbd\xa4\xces\xed\xa4\x8b ֗)\x97\xdeו;\xe9\xd4\x03\x9d$yG\x9b\x033\x05l\xa7\xb2\xef\xaf\xda}FQ\xc0\x8e\xe8C9M<8\xbfB\xc6\x15t\x0el\xcbNf\xa3\x17\xf2\x03\xd5\xe3\x91W5\x01\xbb\xbe\xf3g\xe2\xaf\xdc&WH\xb9\xe2\x97\xca?\xbf\xac\x90\x05g\x14C\xc0~\xe7\xfd\xb3\xf7w\x96,\xf8\x1a\xc78\xa8\x86\x80e\xd1?%\xe3\xab-\x02\x16P\x9fA(\xa8\x92\xe5N\xf5\x8c\xedR{\xbeÁY\xab\x919\x01\xe3\x8fÕ\xc7^\x92\x9f\xdbm\x99\xbe{\xecae\\\xfc_^K\xcb\xe6\x8a\xfe?\x1b\xf7\xd2\x1bs;+\xc53\x14\xb5e\v'\xd6\x100\xfeHF\x150ίp\xa0\xf83\x1f\xe5\x98q\x02\xb6|\xd5\xfcA\t\xd8PcWp$\xc8&\xf1G\x1a;\x87F\xce4\xd1\x15\x15\xf2\xa5\xd1\xd1\xe6\xeeQ\xcb\xf4\xf8\x92\xb0G:p|\xadcD\xbe\xda\xc7nHFiV>\xb4n\xf6\x8f:_:J\xdb\xdd\x1e\xa9:\x90B;\x03\xbf\u007f\x13\xbfN\xef\xfa\xfd\xfdw\xec\xf6\x11[t\xf0\x12\xde\xf7\xe6\xab[\x95\xde\xf6'\u007f>W\xf4\xb3O\xae\xff\xfegE\xe7\xfe\xac\xfcZ\xfc\xd2o\xdf}\x86-\xa7\xa2\xb7\b\xdfzd#\x9d\x8cߏ\x8f\xfc\xf6\b\xde/z\xa0\xd7\xcc\xeb\xef\xee.V\xff\x0e\x9fA\xbd\xf4C]\x89\xff4[\x89\u007f\xe5\x93s\xe7\xbc?;w\xee+\x99\xf7kfL\xb3x\xe2w\x1f=F\xb3\xf8o\xedq\x01\xea\xec\xc8\x03\xfb\xdf\xfd\x8fg\x94kU]\x89/\xbf\xfb\xc0{W\xb8_\x85M\xa3\x90W\xde\xc3G\xbe\x96\xbf>\x82\x15[\xce\x19W\x06\xa5\x11T<Q\xa16\x1f\xd3\x03_\xe3\xa8\aU\xbd\v\xc9\xee\xe6\x06\xd0C\x87\x03\xf7\xa1\x8c\xfa>u%~CO\xcf\b\xfd5mOG\xbb\x9fݲ߁Jێ\xfbQ\x8b\xe6,\xcdr\xeb\xe5\u007f\xf7\xef\xa6k\x9a\xfe\xbc{\xff\xffr\xc7\xe1\xca'\xcf\xfd\xe8O\xf2\x17\x1b\x9f\xff䊾D\xfdwJ\x85?\xf3V\xbczt\x13.z\xfb\xb3\xe8G\x87\xf6Mw\xbe\xfd\xdb'\x8ah\x937\xce\x10w6\xa3\x9fX\xba\x12\xff\xbf\xf4\x02\x19θ\x13+\xac\xc47\xfc\x8a\a\x8a?\xf3\xb3\x8f\xd9g\x9b^\xff\xfa\x9d\xa2Ͼ\u07bf\xfbO\xcbVMJ\xdf\x0fG\xc0\xe4ѓmM\xed}\xec\xce\xe3\x97]\xad\xcd\x1d\x83\xf4\x82\x95ϰ\xc7\"\x1b\x97\xe1\x91бjgj\x81\xd2\xf9;\x9b\xc4&U\xa2hUs\x86u\xc9\x12\xcf\xc9쌪p\x97ǩ\x8ck䯋\xb1\xfa8\xa1\xf6\x04\xda\x13\xd4\xe0\xfa돬\xff\xd1\xfe\xb7\x1f)\xda\xf9\x9c\xf2S\xd1\xff\xa36\xcf\xc9o\xef|\xf5ᢊ\x9d\xec\xfc\xaf\xff\xe53\x1b+\x9ef\x8b\b\xaf\xbf\xb9Ż\x85\xad\x03\xe3<(\xea\xf0\xfc&\xefN\xedq\xb6/\x93\x1f:\xfb\xe5\xb8\xfa,$\xaed\x13\xb3\xbf\xd7\xe61\x94/\x9c_3cY\xde\xf2\xea\xbeb5\x8b\xa75[\xd6\v\xf8`w\xd9Ɲ\xef\xd1?\xb8\xeci\xb9\x9d\xf8\x81O\xb8_\x85M\xa3\x90\x1f<@\x17x\xbd\x8b\xf1\x03\x1f\xf0θ2(\xbc\xbe^\x9f\x106<\xf05\x8evPǜ\xec\x04\xb0\xf5t\xe3\r\x1e)\xa3\xb49[*`\xcfBRJ\x95>zA +%\xb3@\x9d\x84\xe8\xbc?ùF\xbb\xf7۔\x86,\xdd\xf7\x970\xa6\x13:\xcf\xd1\x15i\xe6q\xf8@)\xdf\xf3\xf2\xf3J\xd1?2\xcaK\x8f\xea\x17On\xaa<\xf2v\x91rZ\xa2\x1e\x1d\x99>$\xe8-{\x92-P7\xce\x10w6\xa3\x9fXzP\xb7\x18%ҝq'V}\x16\xf2%\xf5\xa0\x19~\xc5\x03ş\xf9Y\xc7\xecz\x99r*\x8aq\xf1;\x18\xef]\xb6j\xcac\xa3\x03\xa5Ҩ\xbc\\,\xb5\x80\x01\xb3\x10\x96\xc9\xdbs<g\x8e\xc9\xeb\xbb\xc6<\v\xb9\xb4\x1cG\xcb\xf0\xa7\x0fPـ\x90\xfb\xb8\x9d\xd1\xdd\x03\x04lٙ\xb76|yv\xd4\xcedљw!\x97\x8e\xf1fg\x95\x9d\rp\xd7\x18\x1dX\xa6\x05\x14* `\xcb\xce\n\xd6\x06\x93\x15\\\xc8ь\x1a\xf1\xe1\b\xe0\a\x04\b\xd82\xf3'65jg\xb5\xcc$D!\x81\x1f\" `\xcb\f\x9b\x1a\x8d\xf2r\xb9\x15EB\x14\x12\xf8!\x02\x02\x06\x00@\xc2\x02\x02\x06\x00@\xc2\x02\x02\x06\x00@\xc2\x02\x02\x06\x00@\xc2\x02\x02\x06\x00@\xc2\x02\x02\x06\x00@\xc2\x02\x02\xb6B\x18\xb73\x00\x00`\x16\xe4\xff\xec\x02\x00\x00HP\xfe\xad\x1e\x18\x00\x00\xc0r\x02\x02\x06\x00@\xc2\x02\x02\x06\x00@\xc2\x02\x02\x06\x00@\xc2\x02\x02\x06\x00@\xc2\x02\x02\x06\x00@\xc2\x02\x02\x06\x00@\xc2\x02\x02\x06\x00@\xc2\x02\x02\x06\x00@\xc2\x02\x02\x06\x00@\xc2\x02\x02\x06\x00@\xc2\x02\x02\x06\x00@\xc2\x02\x02\x06\x00@\xc2\x02\x02\x06\x00@\xc2\x02\x02\x06\x00@\xc2\x02\x02\x06\x00@\xc2\x02\x02\x06\x00@\xc2\x02\x02\x06\x00@\xc2\x02\x02\x06\x00@\xc2\x02\x02\x06\x00@\xc2\x02\x02\x06\x00@\xc2\x02\x02\x06\x00@\xc2\x02\x02\x06\x00@\xc2\x02\x02\x06\x00@\xc2\x02\x02\x06\x00@\xc2\x02\x02\x06\x00@\xc2\x02\x02\x06\x00@\xc2\x02\x02\x06\x00@\xc2\x02\x02\x06\x00@\xc2\x02\x02\x06\x00@\xc2\x02\x02\x06\x00@\xc2\x02\x02\x06\x00@\xc2\x02\x02\x06\x00@\xc2\x12\x8f\x80\xc9\xf5\xf9\x19)\xaeu\xafD\xec\fc0F\x13\xb6\xa1\rvv\xf3\x87ynE\x0f\x99\xbfē\x8d\x90`!\x1cF~;\x13\x00\x00\x96\x808\x04\xac9\x15\xa9\xb8G\xecL\xa3r8u\x92ħ,\xf3E\xf5\f\x02\x06\x00?T\xec\x05l\x0fB\x05\xbd\xdfF\xc2\xcdYH\xea\xb73\x8eB\x04!*3\xa3\x87{\xec,\xe7\x8b\xe6YУx\xb2\x01\x01\x03\x80{\x04[\x01\xebA\xe8\x17\xea\xd6\xe4\xfd\xc8\xf9\xed\xdc\xc6\xd1\xd0d\xe6.\x10M\xc0\xe2a\xde\t\xac\x80\x80\x01\xc0\xca\xc0V\xc0\xb2Q\x8d\xbe9\xe9B\xd5s\x99F\a\x04\f\x00\x80\xbb\x84\x9d\x80\x9dAIW\x8d/-(-B\xdb\xff\x81P\x893=\xff\x84\xfa\xe3\xd86\xb7\xe4\xdc0@7\x9bQ\xe3@vj^\x98\x90\xbe\xd2LɑS\xf7\r!\xb5l\xfalT\x9f\x9c\nUe\xa587\xb0\xa1h+j\xf8v[\x96䮛\xa0\xdf\u008f\xbaS\xd2\xd74\v7\nb\x1a3tϊ\x1e}\xb3-Sr?>E\xf49\xb0h\xceµ\xd9J9\x83\xcc\x17\x97\x80/\xab\x98\x8b%K\xae\x9e\xaa\x80\xe5\xa2Z\x02\x00\xc0rb'`{\xd0}\xe6\x97q\x84\xfai\xc3.M\x93\n\v\x92P\x15\xfdm\xc0\x81\xa4\xd5n\x84\x02\x84\nضU\b9\"\xa4\x1a\xa1\xcc\xd5.\xe5\x9f\tr\xbc\x14\xa1\x92\xd21MY:RP\xda}\xca\x0e\xda\xf4[QM&Jw\"\x94\xa3\b͗\xe9ș\xe7A\xe8A.\xef\x98\xc6*\xba\xe7V\x94\xebB.eWnD\x13\xb0h\xcezSQZ\x9e⬇\x88\t\xf8\xb2\x8a\xb9\x88Y\xf2\xf5\x04\x01\x03\x80\x95\x81\x9d\x80\xad\x13F\x8dY\xa8\x996l\xe4Q:Y#Nt\\闤\xa3\xda[\x84\f:Q\x17\x15\xb0$Ow\xff+\xa4\x1f\xa5~\xa8X\x0f\xa6\xa1\xc3\xc6@\x8f)\xcbH\x12\n(j\xd0)\xa1\x16Տ\xd2!\xea\x91P;!\x1bPݴ\xb2?\x1d\xf5\x1a\x99\xc56\xd60\x86\x90({H\xe9H\xa5\xd0\xf2\xb0l\xa28\xbb\x9a\x86\xea\"d\xe6\x00Z5!&\x10\xca*\xe4\"|\x11\xea\xa9\nXG\xe3 \x01\x00`9\xb1\x13\xb0<\xb4\xc7\xfa\xad\x95\x8e\xdb\x14N 7\x1d\xc7\xf9\x88\xfa\xc5C\x05\f\x85\xe8\x97\x1dZ\xa2\x1dT\xfdx\x01+\xd1&\x8f\xdaPF\x84\xfaa\xd6U\xb4+\xe7V}6\x95\xf7\x19\x99\xc56\xd60\x05L\xdbU\xade\x13\xc5\xd9\x1e\xb4\x8e}\x16\xa061\x81PV!\x17\xe1\x8bPO\x98\x03\x03\x80\x95\x81\x9d\x80\xadF\xf5ܷ|\xb4\x8b6\xec5\xecKDR\x1ax\x16\xeaV\xbf$\xa1\xb0\"`n\xd5.\xa2\x8e\xf3\xeaiC\xe7\x04,\x92\x8a\x86\xd4\xfdi(\xa8\xf8\xc9a_\x9aP)!\x85(?8Mx\xe60\xd6-t\x01\xcb\xd5v=\xa4\t\xd8lg$\a\x9dd\x9fcW-\t\x84\xb2\n\xb9\b_\x84z\x82\x80\x01\xc0\xca\xc0N\xc06\b\x13=٨\x816\xec]\xea\xb7\\\xd47\x85Pn>#\x05\xf5+\x02\xb6N3\x8c\x04\xdb\x03\xa5n\x846\v\x02\x16FH\x9b\xc1Z\xa3\x8c\xdeZ\xb5N\rӜ\xa0\x84Pz\xe9qn\x99\xc6\x1c\xc6z&\xba\x80\xa9\xbb\x8e\xd3\xcf\x18Έ\xa4\xf6\xa6\x18B\x02\xa1\xacB.\xfc\x17\xb1\x9e `\x00\xb02\xb0\x13\xb0:\x94o~\x99DtV\xa9U\xef\x94\xe5\xa3\x13\xe3ȤK\x110\xad{\xd4\xe4\xa2?\xac^c\x11\xb0Q\x94\xacy\xf2\xa1f\xa2\xaffP5)\xb4١$I\xae\xbe\xa5g6\x97\xb1\x8ae\x19\x85)`\xb3\x9d\xddBh\xccH'$\x10\xca*\xe4\xc2\u007f\x11\xeb\t\x02\x06\x00+\x03;\x01\x1bBIf\xcb?\x8eR&iîS\xbf\xe6\xa03\x8a\xa4\x85Mc]\xc0\x0e \xf4h\xc7\xf0\x14i\x88\xd9\x03\xcbg\x9d*Q\x93\"\x83\x81\\dJ\xc3\xdc\xc6,AL\x01\x9b\xe5\x8c \xa1\a\xc6%\x10\xca\x1aS\xc0\xc4z\x82\x80\x01\xc0\xca\xc0N\xc0\x88\xc7l\xacS\xd9l\xbbU\x1b(\xdeJQz5\x19\xf4\xae\x1ce0<\xad\v\xd8t\x1ajc\xbfm\xb3\b\xd8\xf4*qZ\x8bS\x8bp\x90m\xb7\xa0d}\xf2j\x0ec\x8d\x98\x026ۙR\r\xf5\x11\xa3\x93\x85MB\x02\xb1\xac1\x05L\xac'\b\x18\x00\xac\fl\x05l\x10\xa1\x03\xea\xd6-\x1fJ\xbdDh\xc3Na\x9d\xb2ct\x89X\x15ʛ\xa1_\xfa\x904\xa1\v\x98\xacuw\xa62\xe9\xf7hw!\xdbQzD\x10\b%\x89L\xb7C(\xc9X\xe7\x15\xd3X'\x96\x80EsV\x8bJاO\xa9\r\x9f@,kl\x01\x13\xea\t\x02\x06\x00+\x03[\x01\xa3c\xac\a\xfb'\xc9\xf8\xf1l\x94\xd4M\u007fhE\xe8>E\xc1\xfaR\xe9\xaa\u0590\x84\xaa\xa7\x94\x91\xa6\x13m3\x86\x90\xd3\xe9l\xe6\u007f\xbc\x10\xb1I\xa6\x14\xd4ukZ\x95\x81\x91dT\xafhJw*j\xb2\bă\xa8P\x11\x9d\xa9R\xe36\xc0\\\xc6:\xaa\xe7\xd9=\xb0(\xce©\xa8~\x9a\xcc\x1cB\x8eq\xb1\a&\x945\xb6\x80\t\xf5\x84u`\x00\xb02\xb0\x170ҡ\xbfN'\x93=G\xa34\xec\xecU\xc9\xf7ek=\xb3n\t\xad\xcaS\xbe\xdc\x1f1\xe7\xc0\x9a\x10r\xfb\xf2\x92\x9c\x01\xb6^!OI:\xa0)OG2J\xcf\xcbDT\x05D\x81\xb8\xe4DR\xce\xeaT\xe4⦚b\x1a먞g\vX4g=\x12r\xe69QJ\x8f\xa5\xcb&\x945\xb6\x80\t\xf5\x84\x95\xf8\x00\xb02\x88C\xc0\x88| ?=)c]\x9bvOOiأ\xbe4\xa7\xef\xac\xfa5\\\xe3\x96R\xf3\x9a\xe8`\u0378\v\xd9\u007f\u007f\x86\x94\xb3\xe7\xdb)\x89\xde\xfb\v\x15\xacJ?\xa1+Ϩ?S\xca,\x19\xd0\xfc0cu\xcf\xd86\x8f\xb4JI\xc3g\x1c\xd3XC\xf5\x1ce\x12?\x9a\xb3PUfrF\xf9(\xb1\b\x98P\xd69\x04\x8c\xaf'\b\x18\x00\xac\f\xe2\x110\vz\xc3\x06\x00\x00X^@\xc0\x00\x00HX@\xc0\x00\x00HX@\xc0\x00\x00HX@\xc0\x00\x00HX\x16 `\x00\x00\x00+\x03\x100\x00\x00\x12\x16\x100\x00\x00\x12\x16\x100\x00\x00\x12\x16\x100\x00\x00\x12\x96E\x13\xb07\xf0\x8b\xd1w\xc0MK\x00\x00\xee\x12 `\x00\x00$, `\x00\x00$, `\x00\x00$, `\x00\x00$,v\x02v\x1a\xff\xfa\xbb\xe7ʼ[?&wNoY_\xf1\xe2M\xf6\xeb\x1f\x0eV\x14y\xb7\xbc\xfcO\xf6\xe5\U000fd6ca\x9f\xba\xa8\t؍\x17+\x8b6\xed\xbd\xc0yP\x04,\\\xeet\xe4w\x10\xfa\x96z5\"#9`\x04\xfc\xeeI\xd6^\x97\x98\xdcM옏\xed\x029\x84Rh8\xef>\a:\x14ݠ\x9f\x15 \xe3!\xee]\x89\"\x1d\xca\xeeC\x8a\x1fD\xe3~\xdb1\x92\xc4\xdc%\x8d\xa8_\xc7R\xd8\x01\xaaV~rD\xc9 \xe4K\xcb\xf4\x0ff\n\xaf9\x03\x80\x1f2\xf6\x02\xf6\xe2&\\\xb6\x1e㏟\xc5\xde2\x8cw\xd3\x1f_ĸbk\x85\xf2\x0f\x95\xb3S\xf4KQ\xd1n&`\x17\x8a\xb1wk%Ư\x99\x1eZQ\xae\x13\xe5z\x10*'d\"E\v\x0e\xe4AAmw#\n\x06\xdbPK0\x88\x1aI,Ύ\xc4o\xbb@\xf4,&\xfc\x0e\xfa\x96C\x9f\xc3?\x11\xdd0\x12L\xa9\x0e\x0e\x1e\xf38\xcc(G\"S\x1d\xe8\xf0\x04\x99hB\x1dS1,\xcc\xdc\xc8\xf4\x10\xabА\x1e|d\xa8ZR\xfe\x1d\xa7\xd5\x1c\x9a\x95j m\xcd\xf1\xce<!>\x12\x00\xfc\xb0\xb1\x170\xbc\xe52\xb9}\x10{\xbd\xa7\uf40f1\xbe\xa8\xa8\x14\xf6~\xae\xec\xfa\xbc\x18\x9f\"\xe4\"~@\xd9\xf1\xfdS\x98\n؍b|\xf4\xb6\xb2g\x13\xfe\xd8\xf0ЊP\xb6\xd2\xd8\a\x1c4\xfcO\t\n\xd0\xdfF\xf4\x10\xdeJ\xa7Li\xb1ô\xb5\xa6\xb6\xcc\xce]c\x8d?~\xdb\x05\xa2gA\x02%\x8e)2\xe9(\t\xc44\x95\x1a\x94\u007f\xa6\xdcܛaEB\x88\xbeC\xf6,\x8a\xa5p\x84ˍh\x152h\x90\xa2\xfdʘL/\x8d\x10r\xcb\x03\x02\x06\x00:q\b\xd8e\xe5\xe32\xc6oЯ;\xf1iB\x8e>\xf02\xdbw\x14\xbf@\xc8A|\x94n\xdf,\xa3\x02v\x14\xefe{\xde\xc7?6<\xb4jq\u007f\x8e\xa1le\x10\xa8*\xd7.d\xe8C$\xac\xb5ְ\x11Ah\x16\xf9\x9b\xe3\xb7] z\x16$\xe0\xf7u\x91\x13>\xbf\x8d\x80\x91\x86ԙ\x18\xfb\xe3\x100#72\x0f\x01\v\xa4\xb2\xb1c3\b\x18\x00\xe8\xd8\vX%\xfd\xb8\x8d\xf1\xdf\xe8\xe7A\xda\xe9\"\xb7o\xb3}o\xe0gɝ\x8d\xb4OF\xa8v)\x02\xf6\xb0\xd6\xf3R̯\xe9\x1eZ\xd1Z\xf69\x95\xa4\xb4\xbc\x88\x936\xcc\x19\x97\xd8\b\xcd\xd6z\xa2 -\xe7q\xf6\xee\xfd\xa0ϝ\xe2*Q4\xafW\x9b\xf7\xca\x17lG\x93\x11\xaa\x0fWe;6L\x93\xa9\xcdY\x92\xbb\x94\xbe\xed\xbe\x16\xa5\xb4\xd7\xe58|ょZ\x94\xdcZ\xe3\xce(U\xf3l\xcbw䵉\x1e\xf8,\x02\xfe\xb6rR\xf2\n\x150\xd3oH\xb1-%n\x84\x9c\x11]\xc0\x1a\x93#\\y\xf9\xe2\b\x02\xa6\xe7f[!B\xe4\xaa,gy\xf5,\x013\x0e\x89\xa7\x86}\x9fh\x8ep~\xb9\x1aG\xaf<\x00\xdc\xcb\xd8\v\xd8S\xf4\xe3_\x18\u007fO?\x9fe\x02Fn\u007f~\xfa\xb5\x83\x95X\x11\xb0\xef1\xbe\xad\x19\xbeHn*\xe3\xcd\xed\x8c\"l\xcc\xe3\x1b\x81\xbc\xb3i\x18\xb6mh\x872\x9cDyB&Fk\xadI\xda\xd1\xd7\xeaʟ\xa1\x83\xccG\xbb\a\xda]h\x9a\xdc\n\x06s\x1e\f\x06\x83a\xc16r\xb23;'\xdd]W\x85\xae\x92>T3x\xb24iX\x11\x9a\xced\xe4jhN/'\xbc\a\xfak\xf6\xe1\x9fg\xb3i\xabj\xa9\xbe\xaf^\xaa\x12<\xf0Y\x04\xfc\xe3i\x93\xabd*`\xa6ߙ\xa1\x86\xa4!ҁNP5S\x05,?\x8f//_\x9c\x10\xea\x8bD\"\xfdH\xc8ͶB$\xec\xcc\xe9\xe8\xf5!\xab\x80\x99Y$q\xe3f\xc3/W\xe3\xe8\x95\a\x80{\x19{\x01\xdbG?\x14\x01c\xb7\x1c\x99\x80\xdd9U\x861~`\xebNE\xc0\xaea\xac\x1a\x9eW\x04\xec;lbL\x82\xb5\xa2zuc5\xea&d\b\xb9f\x88\x1f\x89sXzk\xedC\x1d\xec[\xa7\xd2\xc3pѶ\xd7\xe6d\xbfG\x1fq\xe5#ߔ\xd2MR\xa4\xa8\x8bN\x97籈H\x92S\xe9\x80T\xb9\x88\xe8A\xcaV,&\xdd\x05\x84\x9caݣ\x01\xaa\xa5\x9c\aa\bI\xf2\xb6\xad!T\xc0x\xbf\xa4\xba`\xc2}\x98mI\xf5\x91[\xa3\xe5\xe8C\xa1\xbc\x9c\xb3\x90\xd6\xc3\n\t\xb9\xd9Vh\xadG\xe9f\xcd\xe4Y\x04\xcc\xccb\f\xf5\x1ai\xf8Z\x985\x8eQy\x00\xb8wY\x88\x80\xbd\x81\x1fx\xe1\xf4śl\b\xa9t\xbaԕ\x15\xef\xab=0c\xe4hЊ\x1eW7ܴ\xcd\x13\x0f:\x1bq$\x8b+\x01\xf4\xd6\xea\xf7LS\xdcՄ\x8cgyj\x8f\x8f\x12\xb5\a\x11C\xc0\xa4\xab\xda\xd6D\xdb\x06\x8fS\xed\xd5Ity\x06\x9bH\xe2=HlF\xab\rM\x92\x9a\xd5,\xc5\xeajу `M\xa8\x91\t\x18\xef\x97D\xf22\x1fR-$\xaaN.\xaa&\\y9g!\xd4<<<\xdcB\x05\x8c\xcbͮB\x93ꪋz\x8b\x80\x99YL'\x9b\xaa\xcf\xd7¬q\x8c\xca\x03\xc0\xbd\xcb\x02\x04\xecv1\x9d\xc9't5ų\xe4\xce&\xfc9\xfb\xf2\x1a\x9d\x03+\xd3;^\x9f\xff\xe3_\xba\x87V-\x92\xe3$Btv\xa6\x01\xd5\xf6\xf3\xb1\x1d)zk\xcd\xd3\xfa.\xb4\xcf3پ9\x17e\xaa\xcb%b\bX\xbe\xfeS\xa6{OOp\x9d*`t|\xa76g\u0383:\xea\x1bD#d\xad\xaaB%\x05\x82\aQ\xc0&\xf6L0\x01\xe3\xfd\x12ҭ\xaf\xfc\x90j\x86\x87\xd5\xe1\x1f_^\xd3\x197\a\xc6\xe7fS\xa1\x11սu\x12\x9f\xcbB\x9b\x03\x9b\x1e\x10\xfdr5\x8e^y\x00\xb8wY\x80\x80\xfdS\xbd1InV\xe0\x83\x84\xbc\xa0\xa8\x98\xc2\xedJ*`\xcf\xe1\xedw\xe8\xb7?`\xef\xf7\xba\x87V\xb4\x8aM+\xff\x02\xb1n\xc3\x18rע\x93b&zk\xad\xf2\x8c0&\x94\xf6L{@S\x9d\x0e6\x01\xce\xda{\xc7U\xc1V\xf9\xb5\\\xdb\xc8-\xa0\xd3\xda\xe5\x16\x01\xe3=Hl\x1a\xae\x1dM\x91j\x0fK\xe2\xa9\x16<pY\x04\xd4\x15\x0eT\xc0x\xbfDάϞ$F\x16\f\xae\xbc\x9c3N\xc0\xb8\xdc\xec*4\x89\xd8\x1e\xeb$>\x97E\xc0\xc1\xfa\xad]hB\xa8ET\x01\x13r\x03\x80{\x96\x05\bؿ6⣊Lѥ_{\t\xb9\xb6\x1e\xff\xfa\x0e\xb9y\x90\xad\x03\xbb\xec\xc5/(#ʋ\x9b\xb8\xe7\x8aZ\x11\xcaS\x14줤\xcd\xe1\u070f\x1c\xe9\x96U\x10zk\x1d@]\xf4\xa3\xfe0\xed\xa8\x9d\xa1\x9b\x85\xdbؿ\x85\x84|\xab\xee\xe3\x05L\xefƸ\xa9t\xcc\xe4Y\x04\x8c\xf7 eN\xd1\x15T\x85tN\x89NXu\xa2>\xc1\x03\x97\x05'`\xbc\xdf\xe9\x82z\xb2\xcd7cd\xc1\xe0\xca\xcb9\xe3\x04\x8c\xcbͶB\x05nE\x1fë,\x02\xc6e1\x99^\xae\f\tg\n=b-\xa2\n\x98\x90\x1b\x00ܳ,@\xc0\xc8\xdb\x18W>\xf5\x13\xbc\xf1e\xbcU\xf9\xe9\xe3\"\\\xf6\x13/\xde\xc74\xeb\xfcz\xec\xdd^\x89\xf1\xeeۆ\x87V\xe4KM\xb9ύ\xf4\xb9\xfc\xe3\xc8x\x8cHc\xa4\r\xb5\x8c\xb0\xad\x00\xf2\x9f\xec\xadF'h\vL?\xd0\xd7S\x8d\x06\xe9\xcf\rRs\x8f/m\x9c\xb7\x9d\x1eb\xb7\xf2\xc6\xd8n\xb4\xb9\xedp>r5\r\xc9\xc1\x94\xea!2R\x9d\x12\x94\x05\x0f\x12\xca\xef:\x9e\xe3\xa4\x03\xbf\xaa\xa4@_ \xa9J\xf4`f1\xe9_\xf7\x8d\xf2\xf5\x9bu\xfeI\xceo$X\xeb\x1a'\x97\x9c\xbb\x82\x11\xba\x12\xdfX\x03b\x94\x97s&\xac\xc47r\x8bQ!n%~\xc8\xe1>T\x9f\x91\x94\xdc\x11RW\xe2\xb7\x04\x83W\x85CB\xce8\xee\xef\xe8\xf5%\a\xf9Zp5\x8eUy\x00\xb8wY\x88\x80\x91\v\xbb˼[^\xfe\xfef\xd1\x037\x94o\u007f;X\xe6\xdd~\xe1c\xb5\xd3u\xed\x85\xca\"\xef\xf6S\xa6~)\x02\x16\x18\xf5\xa59\xd6\xf6kߧ$\xe31\"\x95[\xe9\b\xa1T\xf5\xb9\x9b\x81u\x19Nfy\xa2\xf0\x90;%\xb3Pm\x80\x91\x1d\x19\x8e\a\x87\x05\xdbQ\xf5!\xc2\x12\xfa\xe3LK\x8e\xe4\xf2wx\xa4\xc2Z委P\x9a\xf2o\xad\xe0Az\xbcڙU%3g\xc7\xf2\xb4u`\x9c\a3\x8b\x06\x84\xe8T\xd36\xfa<\xa3\xe9w@1\xac#;\x94\u007f\xcf\xd2g!W\x1be\xd7\xcb\xcb9S\x9f\x85T\xfc\xb0Yy=\xb7\x18\x15\x1a垅\f\x97fd\xef\xe9HV\x8a^\xadM|\xf9\xf9,\b}\x16ґY\x1a\x12j\xc1\xd58V\xe5\x01\xe0\xde\xc5N\xc0\x16\x9fK\xe6cDK\x869\xea\x03\x00\xe0\x1eb\xe9\x05\xac\x1e\x1d\xb03Yt@\xc0\x00\xe0\x9ed\x89\x05,4ֵJ\x92\xed\xac\x16\x1d\x100\x00\xb8'Yb\x01+G\b-\xb9\x98\xa8\xb3\xdb\x00\x00\xdcs,\xb1\x805\xa5\xba\x96~\x00\xc9f\xb7\xc7\xec\xac\x00\x00H8\x96X\xc0\x00\x00\x00\x16\x0f\x100\x00\x00\x12\x16\x100\x00\x00\x12\x16\x100\x00\x00\x12\x16\x100\x00\x00\x12\x96\xc5\x12\xb0\x1b\xc2\xc3C\x0f\xc56\x04\x00\x00X,\x16G\xc0\xee\x9c\xf2\xde4\xbf\x81\x80\x01\x00\xb0$,\x8e\x80\xdd\xd6\xdf\xcb\xca\x00\x01\x03\x00`I\x00\x01\x03\x00 aI\f\x01\xeb-\x88\x11';~\xb6\xd5\xd8Y\x00VV\xca1\x9b\xbcߌgr\x17X)\xd5\x04\x16\x80\xad\x80]{\xe1ᢍ;\u007f\xa3\xce\xd1\xdfx\xb1\xb2h\xd3^\x161\xed4~\xe3\xfb\x17+\x8a*_\xfe\x9eƄ\xa4\\֓(\x02\x16.w:\xf2i<\x9d\x16\x94\xab\xfex@x\x8d\xe1\xe4\xb6LGI\xacȰ\xb3h\xfc\xf7\x9f\x9f\f\xa3\x00\xa9EI]vvQ\xa0/\xf8B\xae\r#vv\xf3\xa5\x06\xa1fB\x03\xd5\"k\x03\x1ap\xdd\xd5\x06\x1b/+\xe7\x985%\x1d\x8e\xfa\xfb\xa2\x1c\xa8\u007f\xa3\x9a\v\xa4'Y{\xe1[r\xb7\x9d\xe9\xbcl\x17\xc8!\x94B\x0fc\x9f\x03\x1d\x8an\xd0\xcf\n\x90\xf1P̈\xca\xea;\xf0\x0e!\xf5\x1dx6\x8cp\xef\xc0S\x18Ka\x12A߁爒Aȗ\x96\xe9\x1f\xcc\x14\xa3\x00q\xd8\t\xd8\xe5b\xbci\xfb\x8f1\xfe)}\xd7\xfd\x85b\xec\xddZ\x89\xf1k\x84Ł\xac\xc0ś0\xder\x9b\x9c>\x88\xf1\xbe\x837\xf44\xad(\u05c9r=\b\x95\x132\x91\xa2E\xa8\xf6\b\xaf1\xf4e\xbeR\x9d:I\xe2\xe3XR\x87\x9d\xc9lΊ\x8d\xa7jշ\xf4\xa1nN\b9\x83\xb3s64\xfa\x8a\xd5\xc1\x8e\x82E\u007f\xbb\xe9xz\x13=\x02\x93M\xe9\xe3\x96=}i\xdd\xda\xd6\xdc%[lV\xd81\xe3\xb2\xe8Kn\x8dfa\x1e\xa8\xf9\xb0x\xd5\\\xa0A#\xd2^\xb9\x8bbG]ѓ\xc5c\xbb@\xf4,&\xfc\x0e\x9f\xf2\xe1s\xf8c\x8cs\xe8[\x88\x83\x83\xc7<\x8eP\xf4\xfd\xe2[\x88c`\x1c\a\xee-Č!\x16\a\x82\xbd\x85x\xf6+\x17\x06\xd2\xd6\x1c\xef\xccC\xb1\xa3\xd1\xdb\t\xd8>\xfc\xb2\xd2\xf9\xba\xb8\x11\x9fW\xfa_\xc5\xf8\xa8\xf2\xe5\xf3M4\xf6\xd0i\x8c\u007f\xfc9!\xe7\x8bh\x88\"\xeb\x10\x12e+U\x1dp\xd08\x15%\x88Ɨ #\xc2k\f'Q\xab\x16\x8f1\x0e.\xa9A\xd1\xe6\xc9\x1a?\xff-\xacF\xd7\xe5_\xab\xc3\x19\x88\xb6\xb3P_r\xbf6gN\xa3\x05\x90\xa7\xea\xf2q1ʯ\x80M\xc9\xe6\xc9D\xe1\xdc#\xf1\x15v\xcc\xf8,\xea%\xab\xca/\x9cE\xac\xe6\xc2\fZ$-\xe8A\xaa\x18\x1f\x95GO\x16\x8f\xed\x021J\x16(qL\x91IGI\xecvƎΔ\xdb\x12M\xccD\x88F\x1f\x1d\xfe8\f\vRe\x8d\xc4\xc51\x99^\x1a\xa1\xd1,\x16.`\x95\xea\xc8\xf0\xed\x83\u007f\xa0#Ž\xec\xb7\xf7\U0004f640\xb1=\xcf\xe1\xe7\xa2\b\x18\xab\xc81\x94\xadt\x81U\xe5څ\xf8\xa3\x13F\xf3\xe8\xfaWgݲ3\x89\x02\x1f\xb9\x8c\x06\xfba/!\xe3\xafR\xce@\xb4\x9d\x85zv\x8e\xa1\x85\x14c.\xca\xd5(\x01\xf5fl\xa4Yؔl\x9e|9\xd7\x05FV\xdc1㳸\x95e\t\xa4\xf0o\xb0\x88\xd5\\\x98A$\xac\xb5ְ%\xba\r\x87\x9e,\x1e\xdb\x05\u0085\x12\xf4u\x91\x13>\xbf\x8d\x80\x91\x86\xd4X\xb3>q\bX\xf4؈\x949\x04,\x90\xcaƎ\xcd\v\x17\xb0\x9f❟\xeb!\x1e\x1f֢>ަ\xf1kO\xe3-\xec\xcb)\xfa\xd2|\xab\x80\xade\x9fSIJ\xbe\x11'-\u058c\xcb,\xc2t\x86:\xa8\xaf\xa3/\xbaI:A\xc6$:\b\xaeE)\xedu9\x0e\x9f\xfa\x876\\\xeeJ\xc9\xdc\xc0\xae\xac\xe9\xf4=\xec\xa7\x03J\x92N҉\x8c\xe8 \f1ى\x82\xb4\x9cǕ6ӫ\xcd\x1b\xe4kVcɻا\xb4G\xb3\xe5\f\xb8\xcdZ\x94\xdcZ\xe3\xce(\xb5\x1c-\xf5\xecT\xb9\x85,\b\t\xfa\xdc)\xae\x92lk\xb2\xb6|\xfdm\xf5\\\xc9\f[ރ\x19\x00i4Y\xa9U\xb8*۱a\x9aL\xa6\"\x94\xc4b}\x8b\xb5Г\xf1\xb6Q\x89aК\xd3\x17Fᾜ\xb6\xe5<fS{r\xd3\x1f\x1cr\xf7\xf3g\x9eD=\xa8\xd6\xe2ԧZ\x1b\xb0y\xa0\xc4\n\xe9,A5\xa3\x9f\xa19jab\xb6V\xfbd\x9a-\u007fb\xa76gI\xee\xd2Q\x12\xeb:\x8b~Mr\x1e\xf8,\x02\xfe\xb6rR\xf2\n\x150\xd3o(\x99F#u#\xe4\x8c\xe8\x02֘\x1c!\xd1/DA\xc0\xf4\xdcl+D\x88\\\x95\xe5,\xb7\x86\x12\xe4\x0e\x89\x16\vu\xa29B\xa2\xb6\xacZd'`\x9f\x17a\xbc\xf1\xe0i*O71\u07b2\x9dQ\x84/(\x02\xa6v\xc7NG\x13\xb0:u#\x1b\xf5\xd3\xf8\x18;ht0n\x9c4\x1a\xecD\r\xc1\xe07D\x9bz`\x83\xe0Pg2r54\xa7\xb3\xee\xc8`z~\xd3@\x03b\x9d\xe6\x11m\"e\xc2_\x10\x9c\"S\xc1\xb5~~BOHV\x93\xb4\xa3\xafՕ?Cn\x05Y\x90\xa0\xa0~\xb9\xd5h\x03\x10\xa5\xc1t\xf6f*\xb6\x9c\x01\xb7I\x9de\x1f\xfey\xb6e\xac\x1fB}\x91\xf0\x1etX\xc8B)ף\xdd\x03\xed.4-&\xab\x96\xea\xfb\xea\xa5*\xb1d\xa6-\xef\xe1\xf8\x1a2\xe4\x1e\"\xf9\xc7I\xe4dgvN\xba\xbb\xae\n]U\x8c\x83A\xf5z\x11ja$\x13l\xa3\x11\xc3@\xaeB\xab\x95\xff6\x8f/\xe31\x9b\xf4\xb8\x9a\xfak\x11j\xe3\xcf|\xf4\x97\xdcG\xa5\x00\x00 \x00IDAT\x83j-Np\xf6\x9fg\xe3@\t\x152X\x82jF?Cs\xd4\xc2\xc4h\xadq$\xd3l\xf9\x13ۇj\x06O\x96&\rǺ\u03a2_\x93\x9c\a>\x8b\x80\u007f<mr\x95L\x05\xcc\xf4;3Ԑ4D:\xd0\t\xaaf\xeaq\xce\xcf\xe3\xcb\xcb\x17\x87\x9e\xeeH\xa4\x1f\t\xb9\xd9V\x88\x84\x9d9\x1d\xbd>d\x1503\x8b$n\xdc\x1c\xade\x85:\xed\x04\x8c\\>\xe8\xc5\x18\x17\xbdx\x9b|\x87M>\xd6\xc3\x15E\x170\xad\x8f\xb4\x1au+\x17)r\xcd\x10?\x12F\xf0\xe6\x10\x92\x8fj\xe8T.\xa5*\x97\xb2\x15qoP\x14w\xfa$\x9b\xe5\xef\xd3\xfbn\x1d\xea_\xeb\xd5'\x88\x80\x99\xac\x0f\xd1I\xa5a\x163Q\xe8\xb1^M\xa9\xd5l3\x15\x975.b107\xa5\xec)\xa5\x99\xb9\v\bO\x88\xfd\xf1\xa0g\x84Ϣ\xcdE\xe5\xa8\xcd)&;\xc3\xfe\x14\rP\xe5\xe6J\xc6\xd9r\x1e\x82.\xb2G\xdaC\\L\xa0\xf3\x91oʘ\x17t\xe8\xe3\x19\xa3db\xddx\xdbhD78\x93\x82R\xfa\xd9\xd6r\x1d\xb3*'\xedTױ\x18\xbe晏qP\xc5\xc1\xd78\xbd\x96f\xa1\x1f(\xb3B<w\xbf\x9a\xd1\xcfP\xecZ\x98\xe8\xad5\x9ed\\,T\xfd\xc4F\xba\xe8\xd9\xcdc1\xe1\xa3^g1\xaeI\xfe\xd2\xe0\x86\x90$o\xdb\x1a\x16\v\x95\xf7K\xaa\v&\xdc\xea\xed_\xa9>rk\xb4\x1c}\x18\xebB\fi=\xac\x90\x90\x9bm\x85\xd6zn\xd1ȫ\x16\x013\xb3\x18㦚\xa2\xb7,\xdb!\xa4\xc2\xed\xcf_ۊ\xf1\xb3\xb4\av\xcd\xfcuN\x01{\\\xddp\xd3\x1a\x13\x0f:\x1bq$\v\xf7A\xa3\vX\xb5\xbeُFM\xdb\x1e\xa4\xbdLu4)r\xabcrZ\xe2\xf6\x89\xc9\xfc\x9ei\x8a[\x8d\xba\xcd\x1d\xafZ\xfd}\xacR\r1\x86\xdcѯR6\rІ\x84\x1b\xa4!\xd4<\xd4W\xe0\xa0>\xb8,Ƴ<\xb5\xc7Gɴ\x98\xacF\r\xb9\xb6\x9a\xc5\xcc6J\xc6\xd9r\x1e\xae\xa2[\x0f>\xbavJ\xed(\xe5K\\\u007fi\xb6\x80\x89u\x93\x84\xbe\xd5l\xa2\x19L\xd6In\x94%\xed\xa1U[\xaec\xe68\xa0\xee\x13\x05,\xc6A\xb5\nX\xb4u\x0e\x86\x80\x19\x15\xe2\xb9\xfbՌ~\x86b\xd7\xc2Do\xad\xf1$\xe3\x04\xcc8\xb1\x13m\x1b<Nu\\\x13\xf5:\x8bqM\xf2\x97\x06/`M\xa8\x91\t\x18\xef\x97D\xf22\xb5\x15\x9d\x12U'\xb6f%\xfa\x85\xa8\x9c\xee\xe1\xe1\xe1\x16*`\\nv\x15\x9aTW]\xd4[\x04\xcc\xccb:\xd9\xec\xf7DoYv\x02v\xe7\x1f\x9f\xb3\xcf\xdf\xe0\xa2\u007f\x912m\x0e\x8c|\xfe\x8f\u007f\xcd-`\xea݊I\x84h\xf7\xbc\x01\xd5\xf6#\xf1\xfeEt\x0136[\x107\xdf1\xa4\x9f\xbdH\xf2h\xb32\xe8N\xb2̅\x98\xc9\xf2\xb4?\x03\xec\xcf\aw\xbcd\xa9f\x96m\xac\xab\x945\x88A4B8\xd8\x00\u007f2\xa9\x9d\x88YL\xb6o\xceE\x99\x8db\xb2\xb5\xea\x19/) Bn\xa6-\xefA\n\xa5\x8f\xa4\x87R\xd8\xcch>?M2[\xc0ĺ͞R\x11\x89f\xd0\xe8j\x0f\xa1\xd01\x17\xfd\x93\xbaL\xc7l\x1c\xf5\xd0}S\x16\x01\x8bqPŦ?l\x89&\xaab\b\x18WH\x93\xbb_\xcd\x18g(f-L\xf4\xd6\x1aO2N\xc0\xf4\x13;\x9c\xe9\xde\xd3\x13\\g\x89Fo\u007fM\xf2\x97\x06/`\x13{&\x98\x80\xf1~\t\xe9\xd6\x0f\xbaT3<\xac\x0e\x84\xc4#\xa9;\xe3\xe6\xc0\xf8\xdcl*4\xa2\xba\xb7N\xe2sYhs`\xd3\x03$V˲\x11\xb0\xef\xf1\x03\xff\xa4\x9f\x971\xbeM\x9e\xc3\xdb\xe9j0\xf2\a\xec\xfd~n\x01[\xc5\xe6\x15~\xa1F\x80\x1dC\xeeZtRpk\x11\xb0z\x8b\x80}\xc8_%\xb7\x8c\xfbC\xb9\x9d\xeb\xd6\xe6\xf6\xe4\x12\x113Y\x95g\x841A\u007ffǫ\x83\xfd\x81\xa8K\xba4\xcbV007%6{\u05ce\x84їzv\x9c\xb4\xf7\xc0e1B\xff^Mu:ڄd\xd5\x1e\x96\xc4S-\xe4\xc6\xd9\xf2\x85\xcci\xca\"\xeef5E>?\x81#\n\x18-\x99X\xb79\xee[\x92\x98\x06t\xaa5\xa4\xfdu^\x9ec6\x93\xfasu\x9f!`\xf5\x962\xf0\a\x95ύ\x90CR\xb4!s\xbc\x02v\xb7\xaa\x19\xfd\fŮ\x85\x89\xdeZ\xe3I\xc6\t\x98~bs\v\xe8\xdf\xf1r\x8b\x80\xd9_\x93\xfc\xa5ada\xdeM\x12\xfc\x129\xb3>[\xedp\x1am0ƅ\xc8\t\x18\x97\x9b]\x85&م@\xac\x93\xf8\\\x16\x01\a\x1b\xb9u\xa1\x89\x18-\xcbN\xc0\xc8O\xf1O\x15\x05\xbby\x10?\xa5\xa8\x98\x17\xbf\xa0\xe8\xd4\xc5M4\b\xb7 `\xa4\b\u007f|[\xbfYI\x97Q\xe4)\nvR\xd2d\xea~\xe4H\x17\xbbM\xa6\x809\xf6(\x83\xe05\x16\x01\x9b\xca,\xa4\xedl\x17;\x05d\xb3G\xbby믕ΠZ?\x111\x93\r\xa8\xa3\x8cz6l/,$\xe4[\xf6\xc37\x92q\a\x9e\xbfJM\x03nSʜ\xa2\xcbN\n\x99\xc5\xd8a\xf5\xeaV\xcfNf\xdd\xe8/\xf8,\x1a\xd0\x19\x96v\x9b\x90\xac\x8fM\x0et\xa2>!7Ζ/䆂rR~\xbf\x8fe\"\xfc\xa16\x04\xcc(\x99P7\xdev\xac\xc1\xd2%\xb0\x1ap\x8c;\xd5\t\xebe;f\x9b]\xf4\xba\xafb\u05edy\xe6c\x1cT>72\x93\xab\x85P\x17\x89W\xc0\x16\xbb\x9a&\xd1\xceP\xccZ\xe8G\x87\x98\xad5\x9ed\x9c\x80\xe9'\xd6M\xa5c&\xcf\"`\xf6\xd7$\u007fi\x18Yp\x02\xc6\xfb\x9d.\xa8'\xdb|3F\x16\x8c\xe8\x17\"'`\\n\xb6\x15*p+\xfa\x18^e\x110.\x8b\xc9\xf4rE\tf\n=\xb1Z\x96\xad\x80\xdd\u0604\x8b\xb6l\xf5\xe22:\xfdu~=\xf6n\xaf\xc4x\xf7m\xab\x80m\xc7\x18_\xd0Ӵ\"_j\xca}nc\xbd\xc3q$<F\xa4݅Ԧ\xf1\\\x8d\x87\vPrGH\x8d}6R\x9d\x12\x94\x95#\xb1j\xf5+\xfd;\xb4\xe7\x12\xc2I\xcdj\xba\xc3\x0e\xe7L\x8e\xe30\xef\x8a\b\xc9\x02\xc8\u007f\xb2\xb7\x1a\xb1Y\xfe\x06\xa9\xb9ǗF\x1b\xec\xe3\xfa]\x00\xc1\x963\xe06%\x94\xdfu<ǩ&(\xd5\x06\xbe\xa3l\xe2p݆\xea\xfb\xf8,\x1aP\xfa\x81\xbe\x9ejv\x8f\x94KV\x95\x14\xe8\v$U\x89\xb9\xf1\xb6\\!\xebP#i\xa27i\xa7\x87\xd8M\x1a6\x1d\xa3l\a\xa5\xea`pJ,\x99\x91\x8c\xb7e\x85L\xb7\xcc\xcaX\ff\xb3|\xc7\xec\x9bLw[w\xa9\xc4\x04\xcc8\xf3\xb1\x0e*\x9f\x1bi\xb1\x0e\xdd\xf8\x03%\x16R\xe7nV\xd3$\xca\x19\x8a]\x8bRc*e\xa4\r\xb5\xa85\xb2O\xa6\xdb\xf2'\xb6\x01mn;\x9c\x8f\\MC\xb1\xae\xb3hפxi\xe8YL\xfa\xd7}\xa3|\xfdf\x9d\u007f\x92\xf3\x1b\tֺ\xc6\xc9%\xe7\xae`\x84\xae\xc47\xea\x1d\xedB\x14V\xe2\x1b\xb9Ũ\x10\xb7\x12?\xe4p\x1f\xaa\xcfH\xa2\x17\xc1\xb8\xf6\xc0\xc1Uᐐ3\x8e\xfb;z}\xc9A\x12\xbde\xc9A;\x01c\x8f?z\xb7\xbc\xac\x8e\x10\xaf\xbd\xa0|\xd9~J\xd1/\x8b\x80]\xde\xed\xdd\xf8\xbe\x9e\xa4\x15\x05F}i\x8e\xb5\xfd\xda\xf7)I\x98\xbf\x888\xd9\b7\x99\x1d\x92p\xa1#\xdd\x17@\xa8\x96\xc5>\v\xa5)\xff\xd2\xdbB\xe1\xcd\xee\xf4\x82\x1e-A\xfd*5\xf9\x882\"iL\x1f&<b\xb2\x81u\x19N-\xdbȎ\fǃ\xd4\xf6\xdbԪ\xa8\xb6\x86\x01\xbf)=^\xed̪ҚA\x87\x8bN\xe1(\xfdW\x84\x9a\x94&\x99\xe3\xea\xe3\xb38Qxȝ\x92Y8hMv,O_\xadb\xe6\xc6\xdbr\x85\xecs\x8c\x92PZ/\xbd?\xc1\x0e\t\xebdh\x8f\x8a\xa1v\xb1dF2ޖ\x162\x1d\x89G\xc4j0\x9b\xe5;fd\xa2\xda\xed\xf0\x8d0\x013\xce<\x89qP\xf9܂\x8e=Ċy\xa0\xc4B\xea\xdc\xcdj\x9aD9C1k\xa1\x1f\x1d\xa5g\x94\xaed\x95:\x15W2Ö?\xb13-9\x92\xcb\xdf\xe1\x91\nc]gѮI\xf1\xd2гhP\x9f\xc6\xddF\x9fg4\xfd\x0e \xbaTs\x87\xf2\xefY\xfa,\xa4:\x85Η\x97s\xa6>\v\xa9\xf8a}\x0e=\xb7\x18\x15\x1a垅\f\x97fd\xef\xe9HV\x8a^\xad\x9eL\xe4\xe7\xb3P\b\xf9\x1c\x99\xa5!\xa1\x16\\\x8d\xedׁ-\x06\x97\x84Lj\x16\xc0.)\xda\x1d\xa88\t\xc4^\xc5;\x1b\xb3\xab</\x16\x98lQ\xe8\xb1\xce\xca,\x02w\xf7\x98\xa9\x93\xf8\xf3\xa1K\xaa\x9e\xb6\xb3Y\x00w\xb7\x9a\xcbL\xa2\x95w\x81,\x85\x80գ\u007f7\x98m\x8b\xfb[;\x93\x98\xd4Ԑ\xf8Y\xe0Y_`\xb2Šù\xcd\xced\xfe\xdc\xddc6o\x01\x9b\xcc\x12\xe7\r\x16\x8b\x05V32\xa6\xb2\xe8\xcf\xf6,*\xf3>-\x89\xc9]\x17\xb0\xd0X\xd7*iV\xc7{\xa5\xb2\xc0\xb3\xbe\xc0d\x8b\x80\xec\xaa[\xeev4\xef\xca\xcf[\xc0V\x04f5\x1f\xd4F;\xd6\xf9\xfc\x95żOKbr\xd7\x05\xac\\9Ӊr(\xd5\xd9\xc1y\xb3\xc0d\xf7\x06\xf3\xaf|\xf8\f\xaa\x9b_\x8a\x15\x00_\xcdp\xaf\xca<ƟK\xce\xfcOK\x82r\xd7\x05\xac)\xd5\xf5\xef\x0e \x97\f6;\x18\xfb\xee],\x16\x98\xec\xde`\xfe\x95_\x8b\xf4;8\t\xc4\xfc\xab\xb9\xbc$Zy\x17\xcc]\x170\x00\x00\x80\xbb\x05\b\x18\x00\x00\t\v\b\x18\x00\x00\t\v\b\x18\x00\x00\t\v\b\x18\x00\x00\t\xcb\xe2\n\x98\xfe|\xd1ܼA\x1f\x06\xd7X\xfc\x18\x92\x00\x00\xfc`\x00\x01\x03\x00 aY\\\x01\xbb\xfc\xeb\xf3v&\x04\x04\f\x00\x80Ebq\x05,>@\xc0\x00\x00X\x14\xee\x15\x01\xdb6\x9f\xe7r\x01\x00\xb87\xb0\x13\xb0\xdf\xe0S\x17*\xbd?\xb9\xa6\xbe\x18l\xd3^\xed\xad\x85\u05ceT\xaeߴO}_>\xb7\x83\u0381\xbd\xa1σ=\x8b_&\x96d\x9f\xef\xddT\xfc\xd4E\x8b\x80\x85˝\x8e\xfc\x0eB_Z\xa7\xbd.\xfa\x80\xf8\x02\xc48\b\xa3\x00\r5\xf8o\xbcug\xbe\xf4$k\x8f\xf4&wۙ\xce\xcbv\x81\x1cB)\xf4%\xb7}\x0et(\xbaA?+@\xc6C1\x9f\xe1Q\xdf\xe9t\b!\xed=\x92s2½\xd3Ia,\x85\x9d:\xfaN'G\x94\fB\xbe\xb4L\xff`\xe6\xc2\xdf(\x02\x001\xb0\x17\xb0\x17\xbd\x18\x17\xdf&\x17\x8a\xb1wk%Ư\xd1_\xcf{q\xf1\xf62\x8c\xe9\x8c\x17\xbf\x83\n\xd8?p\x11{\xfb\xe1\xedb\x1a\xba[Hv\n㊭EE\xbb\x05\x01\xcbu\xa2\\\x0fB\xe5\x84L\xa4h\x91}=Q\x038\b\x9c\x15_\xd0Y\xb5\xea[-\xd4`\x14\x03\x8b\xedl\x16bЈ\xb4WH\xa2\xc6(\tT\xf4d\xf1\xd8.\x10=\x8b\t\xbf\x83\xbe\x9a\xda\xe7\xf0OD7\xa4o\xd5\f\x0e\x1e\xf3X\xe27\x9a\boՌ\x81q\x1c\xb8\xb7j2\xd4\x00\x8f쭚\xb3\x1f!\x1eH[s\xbc3\x0f\xcd\xe7\xe5[\x00\x10\x1f\xf6\x02\x86+\xcf_8Mn\x14㣷\x95.\xd4&\x1a\x99\xe8\xbbb\xfc\xf2mr\xe7\r\x1a\xdcC\xd8\xc1\xeeB\xeeħi\xca\xf3x+\x11\xf7^\xc4\x0f\x9c\xbeC\xbe\u007f\n\v\x02\x86\xb2\x95&5\u082fX)A4\n\x00\x19\x89\xe3\x05\x88k\xfc\xfc\xb7\xb0\x1aJ\x97\u007f\x83\bg \xdaFa!\x06-\x92\xf6\x12\xefT3\xf2\x93\x15=Y<\xb6\v\xc4(Y\xa0\xc41E&\x1d%\x81\x98\xa6\xec\xe8L\xb9\xc5\xf8P\x1cq\x84\x87\xe7\x8fC\xdc\xe1\xe1'\xd3K#\xf4\xed\xec `\xc0\xe2\x13\x87\x80]\xa6\x9fG\xb5@\xdc\xef\xe3\x1f\x13\xf22\r\xf1\xa1\xb0[\x91*a\a\x13\xb0\xd3\xeaރ\xf8\x94%\xd9A|\x94n\xdf,\x13\x05\x8c5\x98c(\x9b\xbe\\\x94)\xd7.\x14\xbb\x15\xea\x88a+\xaa\xd57\x8e\xf1\x02\x1654V\f\x16b\x10\tk\xad5\x1c\xfb}\\z\xb2xl\x17\b\x17\x1a\xcb\xd7EN\xf8\xfc6\x02F\x1aRgb\xec\x8fC\xc0\xa2\xc7\xfa\xa2\xcc!`\x81T6vl\x06\x01\x03\x16\x1f{\x01\xabd\x9f\x0fk1!o\xd3\xe8\xb6[\xb4/7n\xdc\x11w0\x01\xbbY\x84\xff\xa9\xfc\xeb\xa5\xff\xf2{\xefl\xc4\x17ٗ\xa3\x82\x80\xade\x9fSI\xca\xf5\x1dq\xd2\xcb\u007f\xc6e^\xea\xb5(\xa5\xbd.\xc7\xe1c\xc1\rȉ\x82\xb4\x9c\xc7o\x11ҫM)\xe5kVcɻا\xb4G\xb3\xe5\f\xb8\xcdZ\x94\xdcZ\xe3\xce(\x15\x1b\x92\xe8Lς\x90\xa0ϝ\xe2*ɞ\x9d\x9b\x89\xd9Z\xed\x93i\xb6\xa3\xc9\bՇ\xab\xb2\x1d\x1b\xa6\xc9\xd4\xe6,\xc9]:J,\xd54<\x88\xe5m\xcb\xd7\xdeknz\xe0\xb3\b\xf8\xdb\xcaI\xc9+T\xc0L\xbf\xa1d\x1a]ύ\x903\xa2\vXcr\x84+/_\x1cA\xc0\xf4\xdcl+D\x88\\\x95\xe5,\xb7\x86\xc6\xe2\x0e\x89\x16\xdbo\xa29\xc2\xf9\xe5j\x1c\xbd\xf2\x00\x10\x0f\xf6\x02ƺS71\u07b2\x9dQ\x84/\x90\xf5\xf8o\xfa~q\x87\xba\x90u\x1f\x1dC\xbeO\x13\n{\xbf\xa7\xb1%)\xa7\x05\x01\xabS7\xb2i\x18\x9bm4Dπ\x16\x17\x98\x12\xeaLF\xae\x86\xe6t\x16\u007f\xae&iG_\xab+\u007f\x86\xdc\n\xb2x(A]\x89j$U\xe0$\x94\xdbٛ\xa9\xd8r\x06\xdc&u\x96}\xf8\xe7\xd9\xe24\x90\xe0\xcc\xc8B\x19\xc7>\xda=\xd0\xeeBӳr31Zk\x1c\xc94\xdb\xc8\xc9\xce\xec\x9ctw]\x15\xbaJ\xfaP\xcd\xe0\xc9Ҥa\xb1\x9a\xa6\a\xa1\xbc\xd5R}_\xbdT%x\xe0\xb3\b\xf8\xc7\xd3&W\xc9T\xc0L\xbf3C\rIC\xa4\x03\x9d\xa0j\xa6\nX~\x1e_^\xbe8!\xd4\x17\x89D\xfa\x91\x90\x9bm\x85Hؙ\xd3\xd1\xebCV\x013\xb3H\xe2\xc6͆_\xae\xc6\xd1+\x0f\x00\xf1`/`\a\xe9\xc7w\xd8\xe4c\xa5;uC\xdf/\xec\xd0\x04\xec<\xdeM\xc8S\xf8}\xcb\xdek\x18\xabi\xce\v\x02\xa6\xc5^[\x8d\xbai\x14n\xd7\f\xf1#~\xa6H\xa2\xb1\f\xab\\\x84\xb6Kz\xabr\x98\x85\x87\x13\x063WS\xb4`4R\xe6\xa4\xd2r\\\xc4b`nJ\xd9S\x84L\xba\v\x88\x88a\xc0e\xd1梍\xa8\xcdi\xf1 \xa0\xb7\xd6x\x92q\xb1\xfd\x90O)\x85\xf2\u007f\xa4\x8bN\x97\xe7\xb1\x18\xc7f5y\x0ffyϰ\xee\xd1\x00\vVfz\x10\x86\x90$o\xdb\x1a\x16ۏ\xf7K\xaa\v&\xdc\xea\x1b\xe5\xa5\xfaȭ\xd1r\xf4\xa1\xf5H\xea\xceBZ\x0f+$\xe4f[\xa1\xb5\x9e[4\x92\xa0E\xc0\xcc,ƌ\x18\xa0b-\xcc\x1aǨ<\x00\xd8\x13\xa7\x80ݤ\x03D\x9d;ڼج\x1d\x9a\x80\xddވ\xbf\xff'\xf6\u07b4콩\x87\xef~_\x10\xb0\xc7\xd5\r7mYă\xceF\x1c\xc9\xfc\xfdv\x16z\x94Ͱ\xf8=\xd3\x14\xb7\x1a`\x98kJ\xb5\xfa\xab'Y\x9c\xf89\xc3ó\x19\xa26d\x89\xa4h\x18pY\x8cgyj\x8f\x8f\xaa\x81\xac\xed\x04,\x9ed\x9c\x80Iz\x98扶\r\x1e\xa7\xda\xdf4\xab\xc9{0\xcb[\xa3\x86\xb5Z]-z\x10\x04\xac\t52\x01\xe3\xfd\x92H^\xa6\xb6\xd2N\xa2\xea\xe4\xa2j\"\x1eI\xddY\b5\x0f\x0f\x0f\xb7P\x01\xe3r\xb3\xabФ\xba\xea\xa2\xde\"`f\x16\xd3\xc9\xe6\xdf#\xbe\x16f\x8dcT\x1e\x00\xec\x89S\xc0H\x996\x99E>\xffǿH%V\x9f\x18\xfa\xf8\xa7\xa7\xc4\x1dڳ\x90/\xe2ӧ\xf1\xb3\xd6dw6au\xe1\xd8k\x82\x80\xa9w\xc5&\x11\xa2\xc3\xc0\x06T\xdbo\x04\xffd\x98Ax\xf3\xb4\x1e\x02\xebYpMI\x96\xf4E\xac|t\xe5\xe8\x02\xc6FQ\x83\xd6 \xa9\x86\x01\x9f\xc5d\xfb\xe6\\\x94\xd9h\xf1 \xa0\xb7\xd6x\x92q\x02\xa6O\xa6\rg\xba\xf7\xf4\x04\xd7Y\xa2+\xf3\x1e\xcc\xf2\xaeUU\xa8\xa4@\xf0 \n\xd8Ğ\t&`\xbc_B\xba\xf55)R\xcd\xf0\xb0:\xfc\x13\x8f\xa4\ue31b\x03\xe3s\xb3\xa9Ј\xea\xde:\x89\xcfe\xa1́M\x0f\x88~\xb9\x1aG\xaf<\x00\xd8\x13\xaf\x80=\x87\xb7ߡ\x9f\u007f\xa0K'\x8ejkU\xf7\xe27\xc4\x1d\x9a\x80]\xc4O=\xa5\x06\xea\x16\xf6\xbe\xa0\x8a\xda\xedJA\xc0V\xb1\xf9\xab_\xa8\x913ǐ\xbb\x16\x9d$\x1c\xe6\xc5]\xe5\x19a\xb0\x85N\xac)u\xb0\xbeC]\x92\x1e\xaf}\x96\x80\xa9\x06\xe6\xa6\xc4&\xdcڭ\x91\x14\r\x03.\x8b\x11ڕ\x99\xeat\xb4Y\x9c\xf1\xe8\xad5\x9ed\x9c\x80\x95k\x1b\xb9\x05tZ\xbb\xdc\"`\xbc\a\xb3\xbc\xd5\x1e\x96\xc4S-x\xe0\xb2\xe0\xc2\xc3\xf3~\x89\x9cY\x9f\xadv8\xcd{\xb4\xe2\x91ԝq\x02\xc6\xe5fW\xa1I5Đu\x12\x9f\xcb\"\xe0`=\xea.4!\xd4\"\xaa\x80\t\xb9\x01\x80-\xf1\n\xd8e/~A\x19\x00^\xdcD\xc5\xe7\x86\x17\xbf\xc1ց\x15\u007f'\xee\xd0\xdfFQYTTqgV\xb2k\xeb\xf1\xaf\uf41b\a-\xeb\xc0\xf2\x14\x05;)i3%\xf7#G\xba\xb0\xd6\xc0\xbc\xb8\a\x10[h_\xcfft\n\v\t\xf9\x96\xfd\xf0\x8dd,\xdb\xe7\x05\xcc4\xe06\xa5\xcc)\xba\"\xc9\x1a\x0f\xcb0\xe0\xb2h@gخm\x16gd찮\x97Fk\x8d'\x19'`z7\xc6M\xa5c&\xcf\"`\xbc\a\xb3\xbc}lª\x13\xf5\t\x1e\xb8,8\x01\xe3\xfdN\x17ԓm\xbe\x19#\v\x86p$\rg\x9c\x80q\xb9\xd9V\xa8\xc0\xad\xe8cx\x95E\xc0\xb8,&\xd3˕!\xe1L\xa1G\xacET\x01\x13r\x03\x00[\xe2\x150r~=\xf6n\xaf\xc4x7\xbd\x93x\xbe\boܾ\t\x17\x9d\xb7\xec\xd0\x05\xec\r\xcc\x1e#\xb2&\xfb\xb8\b\x97\xfdċ\xf7\t\x02\xe6KM\xb9ύ\xf4\xb9\xfc\xe3Hx\x8cH\x8d\x0e5R\x9d\x12\x94i e\xff\xc9\xdejt\x82\xeeh\x90\x9a{|i\xb4\xf3\xf6\xb8\xbe\xe8B\xb0\xe5\f\xb8M\t\xe5w\x1d\xcfqZ\xef'\x9a\x06f\x16\r(\xfd@_O5\x1a\x14\r\b)5\x86\xb8#m\xa8E\x1d\x8c\xda'\xd3m\xa7\x87ح<6i׀6\xb7\x1d\xceG\xae\xa6!\xbe\xe8\xbc\a\xae\xbcUI\x81\xbe@R\x95\xe8\xc1\xccbҿ\xee\x1b\xe5\xeb7\xeb\xfc\x93\x9c\xdfH\xb0\xd65N.9w\x05#t%\xbeQo\xa3\xbc\x9c3a%\xbe\x91[\x8c\nq+\xf1C\x0e\xf7\xa1\xfa\x8c\xa4䎐\xba\x12\xbf%\x18\xbc*\x1c\x12r\xc6q\u007fG\xaf/9\xc8ׂ\xabq\xac\xca\x03\x80=q\v\x18\xb9\xf6Be\x91w\xfb)u%\xc4\xe5g+\x8a\xca\x0e^\xb6\xee\xd0\x05\xec\x869\xcd/$\xfb\xdb\xc12\xef\xf6\v\x1f\v\x02\x16\x18\xf5\xa59\xd6\xf6kߧ$\xe11\"\x16\x1d*\x94\xa6\xfcKo4\x0e\xac\xcbpj\x96\x91\x1d\x19\x8e\a\x87\x95\x8doS\xab\xa2\xda\x1a\x06\xfc\xa6\xf4x\xb53\xabJ&\x168[#\x8b\x13\x85\x87\xdc)\x99\x85\x83V\x03\xd2\xe1jW7n\xa5+Y\xa5Nŕ̰\x1dU\x1f\",\xa1?δ\xe4H.\u007f\x87G*\xe4\x8b\xce{\xe0\xcb{,O[\a\xc6y0\xb3h@\x88N5m\xa3\xcf3\x9a~\a\x14\xc3:\xb2C\xf9\xf7,}\x16R\x9dB\xe7\xcb\xcb9S\x9f\x85T\xfc\xb0Yy=\xb7\x18\x15\x1a垅\f\x97fd\xef\xe9HV\x8a^\xadM|\xf9\xf9,\b}\x16ґY\x1a\x12j\xc1\xd58V\xe5\x01\xc0\x1e;\x01[j.\xc5\xf1\x18\x91@`>\v\xbc\x13-Zq\xa2\x95\x17\x00\x96\x98\x95&`\xf5h\x9eapkjH\xfc\x98\x82\x10\x19SY\xf4g{\x16\x15\x100\x00\x98\x93\x15%`\xa1\xb1\xaeUҬ\x01\xde\"b\n\u0083\xdah\xc7:\x9f\xbf\xb2\x00\x01\x03\x809YQ\x02V\xae(\xca]l\xb2\xeal\xb1J\xb8We\x1e\xe3\xcf%\x87//\x00\x00QXQ\x02֔\xea\x9a\xe7\x00r^\xb0\xd9\xe21;\xab\x95C\xa2\x95\x17\x00\x96\x9c\x15%`\x00\x00\x00\xf3\x01\x04\f\x00\x80\x84\x05\x04\f\x00\x80\x84\x05\x04\f\x00\x80\x84\x05\x04\f\x00\x80\x84eq\x05L\u007f\x94hn\xeeF\\H\x00\x00~\x80\x80\x80\x01\x00\x90\xb0,\xae\x80]\xfe\xf5y;\x13\x02\x02\x06\x00\xc0\"\xb1\xb8\x02\x16\x1f `\x00\x00,\n\xf7\x8a\x80m\x9b\xcf3\xdd\x00\x00\xdc\x1b\xd8\t\xd8o\xf0\xa9\v\x95ޟ\\#\xe4Ƌ\x95E\x9b\xf6^P\u007f\xbev\xa4r\xfd\xa6}\xea+\xee\xb9\x1dt\x0e\xec\r}\x1e\xecY\xf6RC!\xd9\xe7{7\x15?u\xd1\"`\xe1r\xa7#\x9fưiA\xb9\xea\x8f\a\x84\x97\x1a\xc6C\x18\x05H-J겳[<z\x92\xb5\xc7\xc1\x93\xbb\xedL\xe7e\xbb@\x0e\xa1\x14\xfaJ\xdb>\a:\x14ݠ\x9f\x15 㡘\x0f\u007f\xaa\xef\x03;\x84\xd4\xf7\x81\xd90½\x0fLa,\x85\x9d:\xfa>0G\x94\fB\xbe\xb4L\xff`&\x1f\xab\x05\x00\x16\x05{\x01{ыq\xf1mr\xa1\x18{\xb7Vb\xfc\x1a\xfd\xf5\xbc\x17\x17o/\xc3,\xb6\a\xbf\x83\n\xd8?p\x11\v>t\xbb\x98\xbe\xd4PHv\n㊭EE\xbb\x05\x01\xcbu\xa2\\\x0fB\xe5\x84L\xa4hQ\xa1=\xc2K\r\xa3rV\x8c\xcbQ\xb5\xea[\xfa\xec3\xf7$8g`\xb1\x9d\xcdB\f\x1a\x91\xf6\xfaQ\x14;\x02\x85\x9e,\x1e\xdb\x05\xa2g1\xe1w\xf8\x94\x0f\x9f\xc3?\x11ݐ\xbe\x9158x\xcc#\x06\xc5\xe4\x10\xde\xc8\x1a\x03\xe38pode\f\xb1w\xe2\xb37\xb2\xce~\xfc| m\xcd\xf1\xce<4\x9f\x17\xb7\x01@|\xd8\v\x18\xae<\u007f\xe14\xb9Q\x8c\x8f\xdeV\xbaP\x9bh\x98\xa1\xef\x8a\xf1\xcb\xec\x9d\xf8\xde\xef\xc5\x1d\xec.\xe4N\x1aזF\u007f\xdcJĽ\x17\xf1\x03\xa7\xef\x90\uf7f2\xbc\x13?[iR\x03\x0e\x1a\x1b\xa2\x04ј\x0ed$\x8e\x97\x1a\xae\xf1\xf3\xdf\xc2jx\\\xfe\xed3\x9c\x81h\x1b\x85\x85\x18\xb4H\xda\v\xe0S\xf9(\x96\"z\xb2xl\x17\x88Q\xb2@\x89c\x8aL:J\x021M\xd9љr\v1\x9fx\x84\xc8\xdc\xd1\xe1\x8fð U֨D\x1c\x93\xe9\xa5\x11\xfaf\u007f\x100`\xf1\x89C\xc0\xd8ˡ\x8f\xe2\xbd\xec\xfb\xfb\xf8DŽ\xbc\xac\x86\xeb&\xbb\x15\xa9\x12v0\x01;\xad\xee=\x88OY\x92\x1d\xc4G\xe9\xf6\xcd2Q\xc0X\x839\x86\xb2\x95\xa1\x96\xaa\\\xbbP\xecV\xa8#\x06:\xabV\xdf\"\xc6\vX\u0530j1X\x88A$\xac\xb5\xd6p\xecw\"\xea\xc9\xe2\xb1] \\X5_\x179\xe1\xf3\xdb\b\x18iH\x9d\x89\xb1?\x0e\x01\x8b\x1e'\x8e2\x87\x80\x05R\xd9ر\x19\x04\fX|\xec\x05\xac\x92}>\xac\x05x\xbcMC\xd5nѾܸqG\xdc\xc1\x04\xecf\x11\xfe\xa7\xf2\xaf\x97\xfe\xcbウ\x11_d_\x8e\n\x02\xb6\x96}N%)\xd7w\xc4I/\xff\x19\x97y\xa9ע\x94\xf6\xba\x1c\x87O\x8d\xa7q\xa2 -\xe7\xf1[\x84\xf4jSJ\xf9\x9a\xd5X\xf2.\xf6)\xed\xd1l9\x03n\xb3\x16%\xb7ָ3Jņ$:ӳ $\xe8s\xa7\xb8J\xb2g\xe7fb\xb6V\xfbd\x9a\xedh2B\xf5\xe1\xaaldži2\xb59Kr\x97\x8e\x12K5\r\x0fby\xdb\xf2\xb5w\xe2\x9b\x1e\xf8,\x02\xfe\xb6rR\xf2\n\x150\xd3o(\x99Fft#\xe4\x8c\xe8\x02֘\x1c\xe1\xca\xcb\x17G\x100=7\xdb\n\x11\"We9˭aոC\xa2Ņ\x9ch\x8ep~\xb9\x1aG\xaf<\x00ă\xbd\x80\xb1\xee\xd4M\x8c\xb7lg\x14\xe1\vd=\xfe\x9b\xbe_ܡ.d\xddGǐ\xefӄ\xc2\xde\xef1VC{\x9c\x16\x04\xacN\xddȦ\xf1淡\x1d4\"W\x9e\xb1;ԙ\x8c\\\r\xcd\xe9,vaMҎ\xbeVW\xfe\f\xb9\x15d\xb1t\x82\xba\x12\xd5H\xaa\xc0I(\xb7\xb37S\xb1\xe5\f\xb8M\xea,\xfb\xf0ϳ\xc5i \xc1\x99\x91\x852\x8e}\xb4{\xa0݅\xa6g\xe5fb\xb4\xd68\x92i\xb6\x91\x93\x9d\xd99\xe9\xee\xba*t\x95\xf4\xa1\x9a\xc1\x93\xa5I\xc3b5M\x0fBy\xab\xa5\xfa\xbez\xa9J\xf0\xc0g\x11\xf0\x8f\xa7M\xae\x92\xa9\x80\x99~g\x86\x1a\x92\x86H\a:A\xd5L\x15\xb0\xfc<\xbe\xbc|qB\xa8/\x12\x89\xf4#!7\xdb\n\x91\xb03\xa7\xa3ׇ\xac\x02ff\x91č\x9b\r\xbf\\\x8d\xa3W\x1e\x00\xe2\xc1^\xc0XT\xa2\xef\xb0\xc9\xc7Jwꆾ_ء\t\xd8y\xbc\x9b\x90\xa7\xf0\xfb\x96\xbd\xd70VӜ\x17\x04L\x8b\xa7\xb6\x1au\x132\x84\\3ď\xf8\x99\"ɩ\x88S\x95\x8b\xd0vIoU\x0e\xb3Ђ\xc2`\xe6jJ\xadf\x9b9\xa9\xb4\x1c\x17\xb1\x18p\x91\xb9\xb3\xa7\b\x99t\x17\x10\x11Àˢ\xcdE\x1bQ\x9b\xd3\xe2A@o\xad\xf1$\xe3\xe2B\"\x9fR\n\xe5\xffH\x17\x9d.\xcfc\xf1\xb1\xcdj\xf2\x1e\xcc\xf2\x9eaݣ\x01\xd4/x\x10\x86\x90$o\xdb\x1a\x16\x17\x92\xf7K\xaa\v&\xdc,\xfe#\x91\xea#\xb7F\xcbч\xd6#\xa9;\vi=\xac\x90\x90\x9bm\x85\xd6zn\xd1(\x94\x16\x013\xb3\x18\xd3\"~R\xf8Z\x985\x8eQy\x00\xb0'N\x01\xbbI\a\x88:w̠i\xe2\x0eM\xc0no\xc4\xdf\xff\x13{oZ\xf6*_\xd8\xedI\xa5s\xc6\v\xd8\xe3ꆛ\xb6,\xe2Ag#\x8ed\xfe~;\v[\xcbfX\xfc\x9ei\x8a[\rN\xcd5\xa5Z\xfd\xb5\xa5R\r1fc\xa2\v\x18\x9b!jC\x93D\xc00\xe0\xb2\x18\xcf\xf2\xd4\x1e\x1f%\xd3\x16\x0f\x02zk\x8d'\x19'`\x92\x1e\xe2{\xa2m\x83ǩ\xf67\xcdj\xf2\x1e\xcc\xf2֨!\xd1VW\x8b\x1e\x04\x01kB\x8dL\xc0x\xbf$\x92\x97\xa9\xad\xb4\x93\xa8:\xb9\xa8\x9a\x88GRw\x16B\xcd\xc3\xc3\xc3-T\xc0\xb8\xdc\xec*4\xa9\xae\xba\xa8\xb7\b\x98\x99\xc5t\xb2\xf9\xf7\x88\xaf\x85Y\xe3\x18\x95\a\x00{\xe2\x140R\xa6Mf\x91\xcf\xff\xf1/R\x89\xd5'\x86>\xfe\xe9)q\x87\xf6,\xe4\x8b\xf8\xf4i\xfc\xac5ٝMX]8\xf6\x9a `\xea]\xb1I\x84\xe80\xb0\x01\xd5\xf6\x1b\x81c\x19f\xd4\xe6<\xad\x87\xc0z\x16\\S\x92%}\x11+\x1f\x99;\xba\x80\xb1Q\xd4 \xb2\xac\x8a0\f\xf8,&\xdb7\xe7\xa2\xccF\x8b\a\x01\xbd\xb5Ɠ\x8c\x130}2m8ӽ\xa7'\xb8\xce\x12\x99\x9b\xf7`\x96w\xad\xaaB%\x05\x82\aQ\xc0&\xf6L0\x01\xe3\xfd\x12ҭ\xafI\x91j\x86\x87\xd5\xe1\x9fx$ug\xdc\x1c\x18\x9f\x9bM\x85FT\xf7\xd6I|.\vm\x0elz@\xf4\x1b52\xb7\x90\x1b\x00\xd8\x12\xaf\x80=\x87\xb7ߡ\x9f\u007f\xa0K'\x8ejkU\xf7\xe27\xc4\x1d\x9a\x80]\xc4O=\x85/\xccJ\xf6\x82*j\xb7+\x05\x01[\xc5\xe6\xaf~\xa1F]\x1dC\xeeZt\x92p\x98\x17w\x95g\x84\xc1\x16:\xb1\xa6\xd4\xc1\xfa\x0euI\x97f\xd9\n\x06\xe6\xa6\xc4&\xdcڑe\xa5\x93a\xc0e1B\xbb2S\x9d\x8e6\x8b3\x1e\xbd\xb5Ɠ\x8c\x13\xb0rm#\xb7\x80Nk\x97[\x04\x8c\xf7`\x96\xb7\xdaÒx\xaa\x05\x0f\\\x16\x01u\x85\x03\x150\xde/\x913\xeb\xb3\xd5\x0e\xa7y\x8fV<\x92\xba3N\xc0\xb8\xdc\xec*4\x89\xd8\x1e\xeb$>\x97E\xc0\xc1z\xd4]hB\xa8ET\x01\x13r\x03\x00[\xe2\x15\xb0\xcb^\xfc\x822\x00\xbc\xb8\x89\x8a\xcf\r/~\x83\xad\x03+\xfeNܡ\xbf\x8d\xa2\xb2\xa8\xa8\xe2άd\xd7\xd6\xe3_\xdf!7\x0fZց\xe5)\nvR\xd2fJ\xeeG\x8eta\xad\x81yq\x0f \xb6о\x9e\xcd\xe8\x14\x16\x12\xf2-\xfb\xe1\x1b\xc9X\xb6\xcf\v\x98i\xc0mJ\x99StE\x925\x96\x9aa\xc0eрΰ]\xdb,\xce\xc8\xd8a]/\x8d\xd6\x1aO2N\xc0\xf4n\x8c\x9bJ\xc7L\x9eE\xc0x\x0ffy\xfb\u0604U'\xea\x13<pYp\x02\xc6\xfb\x9d.\xa8'\xdb|3F\x16\f\xe1H\x1a\xce8\x01\xe3r\xb3\xadP\x81[\xd1\xc7\xf0*\x8b\x80qYL\xa6\x97+C\u0099B\x8fX\x8b\xa8\x02&\xe4\x06\x00\xb6\xc4+`\xe4\xfcz\xec\xdd^\x89\xf1nz'\xf1|\x11\u07b8}\x13.:o١\v\xd8\x1b\x98=FdM\xf6q\x11.\xfb\x89\x17\xef\x13\x04̗\x9ar\x9f\x1b\xe9s\xf9Ǒ\xf0\x18\x91\x1aYl\xa4:%(\xd3 \xdc\xfe\x93\xbd\xd5\xe8\x04\xdd\xd1 5\xf7\xf8\xd2h\xe7\xedq}х`\xcb\x19p\x9b\x12\xca\xef:\x9e\xe3\xb4\xdeO4\r\xcc,\x1aP\xfa\x81\xbe\x9ej4(\x1a\x10Rj\fqG\xdaP\x8b:\x18\xb5O\xa6\xdbN\x0f\xb1[ylҮ\x01mn;\x9c\x8f\\MC|\xd1y\x0f\\y\xab\x92\x02}\x81\xa4*у\x99Ť\u007f\xdd7\xca\xd7o\xd6\xf9'9\xbf\x91`\xadk\x9c\\r\xee\nF\xe8J|\xa3\xdeFy9g\xc2J|#\xb7\x18\x15\xe2V\xe2\x87\x1c\xeeC\xf5\x19I\xc9\x1d!u%~K0xU8$\xe4\x8c\xe3\xfe\x8e^_r\x90\xaf\x05W\xe3X\x95\a\x00{\xe2\x160r\xed\x85\xca\"\xef\xf6S\xeaJ\x88\xcb\xcfV\x14\x95\x1d\xbclݡ\v\xd8\rs\x9a_H\xf6\xb7\x83e\xde\xed\x17>\x16\x04,0\xeaKs\xac\xed\u05feOI\xc2cD,\xb2X(M\xf9\x97\xdeh\x1cX\x97\xe1\xd4,#;2\x1c\x0f\x0e+\x1bߦVE\xb55\f\xf8M\xe9\xf1jgV\x95L,p\xb6F\x16'\n\x0f\xb9S2\v\a\xad\x06\xa4\xc3ծn\xdcJW\xb2J\x9d\x8a+\x99a;\xaa>DXB\u007f\x9ciɑ\\\xfe\x0e\x8fT\xc8\x17\x9d\xf7\xc0\x97\xf7X\x9e\xb6\x0e\x8c\xf3`fр\x10\x9dj\xdaF\x9fg4\xfd\x0e(\x86ud\x87\xf2\xefY\xfa,\xa4:\x85Η\x97s\xa6>\v\xa9\xf8a\xb3\xf2zn1*4\xca=\v\x19.\xcd\xc8\xdeӑ\xac\x14\xbdZ\x9b\xf8\xf2\xf3Y\x10\xfa,\xa4#\xb34$Ԃ\xabq\xac\xca\x03\x80=v\x02\xb6\xd4\\\x8a\xe31\"\x81\xc0|\x16x'Z\xa4\xebD+/\x00,1+M\xc0\xea\xd1<C\xdb\xd6Ԑ\xf81\x05!2\xa6\xb2\xe8\xcf\xf6,* `\x000'+J\xc0Bc]\xab\xa4Y\x03\xbcE\xc4\x14\x84\a\xb5юu>\u007fe\x01\x02\x06\x00s\xb2\xa2\x04\xac\\Q\x94\xbb\xd8d\xd5\xd9b\x95p\xaf\xca<ƟK\x0e_^\x00\x00\xa2\xb0\xa2\x04\xac)\xd55\xcf\x01\xe4\xbc`\xb3\xc5cvV+\x87D+/\x00,9+J\xc0\x00\x00\x00\xe6\x03\b\x18\x00\x00\t\v\b\x18\x00\x00\t\v\b\x18\x00\x00\t\v\b\x18\x00\x00\t\xcb\xe2\n\x98\xfe(\xd1\xdc܍\xb8\x90\x00\x00\xfc\x00\x01\x01\x03\x00 aY\\\x01\xbb\xfc\xeb\xf3v&\x04\x04\f\x00\x80Ebq\x05,>@\xc0\x00\x00X\x14\xee\x15\x01\xdb6\x9fg\xba\x01\x00\xb87\xb0\x13\xb0\xdf\xe0S\x17*\xbd?\xb9Fȍ\x17+\x8b6\xed\xbd\xa0\xfe|\xedH\xe5\xfaM\xfb\xd4W\xdcs;\xe8\x1c\xd8\x1b\xfa<س쥆B\xb2\xcf\xf7n*~\xea\xa2E\xc0\xc2\xe5NG>\x8daӂr\xd5\x1f\x0f\b/5\x8c\x870\n\x90Z\x94\xd4eg\xb7x\xf4$k\x8f\x83'wۙ\xce\xcbv\x81\x1cB)\xf4\x95\xb6}\x0et(\xbaA?+@\xc6C1\x1f\xfeT\xdf\av\b\xa9\xef\x03\xb3a\x84{\x1f\x98\xc2X\n;u\xf4}`\x8e(\x19\x84|i\x99\xfe\xc1L>V\v\x00,\n\xf6\x02\xf6\xa2\x17\xe3\xe2\xdb\xe4B1\xf6n\xad\xc4\xf85\xfa\xeby/.\xde^\x86Yl\x0f~\a\x15\xb0\u007f\xe0\"\x16|\xe8v1}\xa9\xa1\x90\xec\x14\xc6\x15[\x8b\x8av\v\x02\x96\xebD\xb9\x1e\x84\xca\t\x99HѢB{\x84\x97\x1aF\xe5\xac\x18\x97\xa3jշ\xf4\xd9g\xeeIp\xce\xc0b;\x9b\x85\x184\"\xed\xf5\xa3(v\x04\n=Y<\xb6\vD\xcfb\xc2\xef\xf0)\x1f>\x88\x9f\x8f(\x00\x00\ttIDAT\x87\u007f\"\xba!}#kp\xf0\x98G\f\x8a\xc9!\xbc\x915\x06\xc6q\xe0\xde\xc8\xca\x18b\xef\xc4god\x9d\xfd\xf8\xf9@ښ\xe3\x9dyh>/n\x03\x80\xf8\xb0\x170\\y\xfe\xc2ir\xa3\x18\x1f\xbd\xadt\xa16\xd10C\xdf\x15\xe3\x97\xd9;\xf1\xbdߋ;\xd8]ȝ4\xae-\x8d\xfe\xb8\x95\x88{/\xe2\aN\xdf!\xdf?ey'~\xb6Ҥ\x06\x1c46D\t\xa21\x1d\xc8H\x1c/5\\\xe3翅\xd5\xf0\xb8\xfc\xdbg8\x03\xd16\n\v1h\x91\xb4\x17\xc0\xa7\xf2Q,E\xf4d\xf1\xd8.\x10\xa3d\x81\x12\xc7\x14\x99t\x94\x04b\x9a\xb2\xa33\xe5\x16b>\xf1\b\x91\xb9\xa3\xc3\x1f\x87aA\xaa\xacQ\x898&\xd3K#\xf4\xcd\xfe `\xc0\xe2\x13\x87\x80\xb1\x97C\x1f\xc5{\xd9\xf7\xf7\xf1\x8f\tyY\r\xd7Mv+R%\xec`\x02vZ\xdd{\x10\x9f\xb2$;\x88\x8f\xd2\xed\x9be\xa2\x80\xb1\x06s\fe+C-U\xb9v\xa1حPG\ftV\xad\xbeE\x8c\x17\xb0\xa8a\xd5b\xb0\x10\x83HXk\xad\xe1\xd8\xefDԓ\xc5c\xbb@\xb8\xb0j\xbe.r\xc2\xe7\xb7\x110Ґ:\x13c\u007f\x1c\x02\x16=N\x1ce\x0e\x01\v\xa4\xb2\xb1c3\b\x18\xb0\xf8\xd8\vX%\xfb|X\v\xf0x\x9b\x86\xaaݢ}\xb9q㎸\x83\t\xd8\xcd\"\xfcO\xe5_/\xfd\x97\xdf{g#\xbeȾ\x1c\x15\x04l-\xfb\x9cJR\xae\uf213^\xfe3.\xf3R\xafE)\xedu9\x0e\x9f\x1aO\xe3DAZ\xce\xe3\xb7\b\xe9զ\x94\xf25\xab\xb1\xe4]\xecSڣ\xd9r\x06\xdcf-Jn\xadqg\x94\x8a\rIt\xa6gAH\xd0\xe7Nq\x95d\xcf\xce\xcd\xc4l\xad\xf6\xc94\xdb\xd1d\x84\xea\xc3Uَ\r\xd3djs\x96\xe4.\x1d%\x96j\x1a\x1e\xc4\xf2\xb6\xe5k\xef\xc47=\xf0Y\x04\xfcm\xe5\xa4\xe4\x15*`\xa6\xdfP2\x8d\xcc\xe8F\xc8\x19\xd1\x05\xac19\u0095\x97/\x8e `zn\xb6\x15\"D\xae\xcar\x96[êq\x87D\x8b\v9\xd1\x1c\xe1\xfcr5\x8e^y\x00\x88\a{\x01cݩ\x9b\x18o\xd9\xce(\xc2\x17\xc8z\xfc7}\xbf\xb8C]Ⱥ\x8f\x8e!ߧ\t\x85\xbd\xdfc\xac\x86\xf68-\bX\x9d\xba\x91M\xe3\xcdoC;hD\xae<cw\xa83\x19\xb9\x1a\x9a\xd3Y\xec\u009a\xa4\x1d}\xad\xae\xfc\x19r+\xc8b\xe9\x04u%\xaa\x91T\x81\x93Pngo\xa6b\xcb\x19p\x9b\xd4Y\xf6\xe1\x9fg\x8b\xd3@\x823#\ve\x1c\xfbh\xf7@\xbb\vM\xcf\xca\xcd\xc4h\xadq$\xd3l#';\xb3s\xd2\xdduU\xe8*\xe9C5\x83'K\x93\x86\xc5j\x9a\x1e\x84\xf2VK\xf5}\xf5R\x95\xe0\x81\xcf\"\xe0\x1fO\x9b\\%S\x013\xfd\xce\f5$\r\x91\x0et\x82\xaa\x99*`\xf9y|y\xf9\xe2\x84P_$\x12\xe9GBn\xb6\x15\"agNG\xaf\x0fY\x05\xcc\xcc\"\x89\x1b7\x1b~\xb9\x1aG\xaf<\x00ă\xbd\x80\xb1\xa8D\xdfa\x93\x8f\x95\xee\xd4\r}\xbf\xb0C\x13\xb0\xf3x7!O\xe1\xf7-{\xafa\xac\xa69/\b\x98\x16Om5\xea&d\b\xb9f\x88\x1f\xf13E\x92S\x11\xa7*\x17\xa1\xed\x92ު\x1cf\xa1\x05\x85\xc1\xccՔZ\xcd6sRi9.b1\xe0\"sgO\x112\xe9. \"\x86\x01\x97E\x9b\x8b6\xa26\xa7Ń\x80\xdeZ\xe3I\xc6ŅD>\xa5\x14\xca\xff\x91.:]\x9e\xc7\xe2c\x9b\xd5\xe4=\x98\xe5=úG\x03\xa8_\xf0 \f!I\u07b65,.$\xef\x97T\x17L\xb8Y\xfcG\"\xd5Gn\x8d\x96\xa3\x0f\xadGRw\x16\xd2zX!!7\xdb\n\xad\xf5ܢQ(-\x02ff1\xa6E\xfc\xa4\xf0\xb50k\x1c\xa3\xf2\x00`O\x9c\x02v\x93\x0e\x10u\xee\x98A\xd3\xc4\x1d\x9a\x80\xddވ\xbf\xff'\xf6\u07b4\xecU\xbe\xb0ۓJ\xe7\x8c\x17\xb0\xc7\xd5\r7mYă\xceF\x1c\xc9\xfc\xfdv\x16\xb6\x96Ͱ\xf8=\xd3\x14\xb7\x1a\x9c\x9akJ\xb5\xfakK\xa5\x1ab\xcc\xc6D\x1706CԆ&\x89\x80a\xc0e1\x9e\xe5\xa9=>J\xa6-\x1e\x04\xf4\xd6\x1aO2N\xc0$=\xc4\xf7D\xdb\x06\x8fS\xedo\x9a\xd5\xe4=\x98\xe5\xadQC\xa2\xad\xae\x16=\b\x02ք\x1a\x99\x80\xf1~I$/S[i'QurQ5\x11\x8f\xa4\xee,\x84\x9a\x87\x87\x87[\xa8\x80q\xb9\xd9UhR]uQo\x1103\x8b\xe9d\xf3\xef\x11_\v\xb3\xc61*\x0f\x00\xf6\xc4)`\xa4L\x9b\xcc\"\x9f\xff\xe3_\xa4\x12\xabO\f}\xfc\xd3S\xe2\x0e\xedY\xc8\x17\xf1\xe9\xd3\xf8Yk\xb2;\x9b\xb0\xbap\xec5A\xc0Իb\x93\b\xd1a`\x03\xaa\xed7\x02\xc72̨\xcdyZ\x0f\x81\xf5,\xb8\xa6$K\xfa\"V>2wt\x01c\xa3\xa8AdY\x15a\x18\xf0YL\xb6o\xceE\x99\x8d\x16\x0f\x02zk\x8d'\x19'`\xfad\xdap\xa6{OOp\x9d%27\xef\xc1,\xefZU\x85J\n\x04\x0f\xa2\x80M\xec\x99`\x02\xc6\xfb%\xa4[_\x93\"\xd5\f\x0f\xab\xc3?\xf1H\xeaθ90>7\x9b\n\x8d\xa8\ueb53\xf8\\\x16\xda\x1c\xd8\xf4\x80\xe87jdn!7\x00\xb0%^\x01{\x0eo\xbfC?\xff@\x97N\x1c\xd5֪\xee\xc5o\x88;4\x01\xbb\x88\x9fz\n_\x98\x95\xec\x05U\xd4nW\n\x02\xb6\x8a\xcd_\xfdB\x8d\xba:\x86ܵ\xe8$\xe10/\xee*\xcf\b\x83-tbM\xa9\x83\xf5\x1d\xea\x92.Ͳ\x15\f\xccM\x89M\xb8\xb5#\xcbJ'À\xcbb\x84ve\xa6:\x1dm\x16g<zk\x8d'\x19'`\xe5\xdaFn\x01\x9d\xd6.\xb7\b\x18\xef\xc1,o\xb5\x87%\xf1T\v\x1e\xb8,\x02\xea\n\a*`\xbc_\"g\xd6g\xab\x1dN\xf3\x1e\xadx$ug\x9c\x80q\xb9\xd9Uh\x12\xb1=\xd6I|.\x8b\x80\x83\xf5\xa8\xbbЄP\x8b\xa8\x02&\xe4\x06\x00\xb6\xc4+`\x97\xbd\xf8\x05e\x00xq\x13\x15\x9f\x1b^\xfc\x06[\aV\xfc\x9d\xb8C\u007f\x1bEeQQŝYɮ\xadǿ\xbeCn\x1e\xb4\xac\x03\xcbS\x14줤͔\u070f\x1c\xe9\xc2Z\x03\xf3\xe2\x1e@l\xa1}=\x9b\xd1),$\xe4[\xf6\xc37\x92\xb1l\x9f\x170Ӏ۔2\xa7\xe8\x8a$k,5Àˢ\x01\x9da\xbb\xb6Y\x9c\x91\xb1ú^\x1a\xad5\x9ed\x9c\x80\xe9\xdd\x187\x95\x8e\x99<\x8b\x80\xf1\x1e\xcc\xf2\xf6\xb1\t\xabN\xd4'x\xe0\xb2\xe0\x04\x8c\xf7;]PO\xb6\xf9f\x8c,\x18\u00914\x9cq\x02\xc6\xe5f[\xa1\x02\xb7\xa2\x8f\xe1U\x16\x01㲘L/W\x86\x843\x85\x1e\xb1\x16Q\x05L\xc8\r\x00l\x89W\xc0\xc8\xf9\xf5ػ\xbd\x12\xe3\xdd\xf4N\xe2\xf9\"\xbcq\xfb&\\t\u07b2C\x17\xb070{\x8cȚ\xec\xe3\"\\\xf6\x13/\xde'\b\x98/5\xe5>7\xd2\xe7\xf2\x8f#\xe11\"5\xb2\xd8HuJP\xa6A\xb8\xfd'{\xab\xd1\t\xba\xa3Aj\xee\xf1\xa5\xd1\xce\xdb\xe3\xfa\xa2\v\xc1\x963\xe06%\x94\xdfu<\xc7i\xbd\x9fh\x1a\x98Y4\xa0\xf4\x03}=\xd5hP4 \xa4\xd4\x18⎴\xa1\x16u0j\x9fL\xb7\x9d\x1eb\xb7\xf2ؤ]\x03\xda\xdcv8\x1f\xb9\x9a\x86\xf8\xa2\xf3\x1e\xb8\xf2V%\x05\xfa\x02IU\xa2\a3\x8bI\xff\xbao\x94\xaf߬\xf3Or~#\xc1Z\xd78\xb9\xe4\xdc\x15\x8cЕ\xf8F\xbd\x8d\xf2r΄\x95\xf8Fn1*ĭ\xc4\x0f9܇\xea3\x92\x92;B\xeaJ\xfc\x96`\xf0\xaapH\xc8\x19\xc7\xfd\x1d\xbd\xbe\xe4 _\v\xaeƱ*\x0f\x00\xf6\xc4-`\xe4\xda\v\x95E\xde\xed\xa7ԕ\x10\x97\x9f\xad(*;xٺC\x17\xb0\x1b\xe64\xbf\x90\xeco\a˼\xdb/|,\bX`ԗ\xe6Xۯ}\x9f\x92\x84LjXd\xb1P\x9a\xf2/\xbd\xd18\xb0.éYFvd8\x1e\x1cV6\xbeM\xad\x8ajk\x18\xf0\x9b\xd2\xe3\xd5ά*\x99X\xe0l\x8d,N\x14\x1er\xa7d\x16\x0eZ\rH\x87\xab]ݸ\x95\xaed\x95:\x15W2\xc3vT}\x88\xb0\x84\xfe8Ӓ#\xb9\xfc\x1d\x1e\xa9\x90/:\xef\x81/\xef\xb1<m\x1d\x18\xe7\xc1̢\x01!:մ\x8d>\xcfh\xfa\x1dP\f\xeb\xc8\x0e\xe5߳\xf4YHu\n\x9d//\xe7L}\x16R\xf1\xc3f\xe5\xf5\xdcbTh\x94{\x162\\\x9a\x91\xbd\xa7#Y)z\xb56\xf1\xe5\xe7\xb3 \xf4YHGfiH\xa8\x05W\xe3X\x95\a\x00{\xec\x04l\xa9\xb9\x14\xc7cD\x02\x81\xf9,\xf0N\xb4H\u05c9V^\x00XbV\x9a\x80գy\x86\xb6\xad\xa9!\xf1c\nBdLeџ\xedYT@\xc0\x00`NV\x94\x80\x85ƺVI\xb3\x06x\x8b\x88)\b\x0fj\xa3\x1d\xeb|\xfe\xca\x02\x04\f\x00\xe6dE\tX\xb9\xa2(w\xb1ɪ\xb3\xc5*\xe1^\x95y\x8c?\x97\x1c\xbe\xbc\x00\x00DaE\tXS\xaak\x9e\x03\xc8y\xc1f\x8b\xc7\xec\xacV\x0e\x89V^\x00XrV\x94\x80\x01\x00\x00\xcc\a\x100\x00\x00\x12\x16\x100\x00\x00\x12\x16\x100\x00\x00\x12\x16\x100\x00\x00\x12\x16\x100\x00\x00\x12\x16\x100\x00\x00\x12\x16\x100\x00\x00\x12\x16\x100\x00\x00\x12\x16\x100\x00\x00\x12\x96\xff\x0f}\xc6-\xc8\xe3>\xf6\xcf\x00\x00\x00\x00IEND\xaeB`\x82",
+
+	"analysis/chan2a.png": "\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x04\x89\x00\x00\x01\x95\b\x03\x00\x00\x00M@Q-\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x02\xfdPLTE\x00\x01\x00\n\x03\x01\x04\x06\x02\a\n\x06\x0e\x10\r\r\x12\x14\x0e\x12\x1d\x11\x13\x10\x16\x18\x15\x1b\x1a\x13\x13\x1e7\x1f\x1f\x18!# #$\"%$\x1d%%\x1e$%#%'%'(&+)\x1e()'*+)/,!+-*,-+-/,02/63(241564796<9.9;8<=;=>FA?3>@=#CxDA5AB@DFCFHEKH<MH7IKHKLJNOMUP?PROSTRUVTWXV]XG<Z\xa5_ZIY[Y,`\xae7]\xad[]Z\\^[9a\xab;b\xac<c\xad_a^faO]ao>e\xafac`hcQbdaAg\xb2efdCi\xb3ghfMj\xafEm\xb1qjRikhIp\xb4lmkLr\xb7npm{s\\rtqWv\xb6tvsuwt\\z\xbaxzw]~\xb8e|\xb8\x84|dX\x80\xbf{}za\u007f\xbf|~{~\x80}b\x82\xbc\u007f\x81~d\x85\xbf\x82\x83\x80\x83\x85\x82m\x87\xbdh\x88Ð\x86hj\x8ać\x88\x86r\x8c\xc1\x89\x8b\x88t\x8eė\x8do\x8c\x8e\x8bz\x8f\xc0\x8e\x90\x8dx\x92Ȑ\x92\x8f~\x93\xc3x\x95Ē\x93\x90\x81\x95\xc6{\x98Ȕ\x96\x93\xa0\x96w\x96\x98\x95\x82\x9aė\x99\x96\x83\x9cņ\x9b̀\x9d̚\x9b\x98\xa5\x9b|\x87\x9fɃ\xa0Ϝ\x9e\x9b\x89\xa1̞\xa0\x9d\xaa\xa0\x81\xa0\xa2\x9f\xa1\xa3\xa0\xa2\xa4\xa1\x91\xa5ʮ\xa4\x85\x8f\xa7Ѥ\xa6\xa3\x94\xa7̥\xa7\xa4\xb4\xa7\x83\x92\xaaԧ\xa9\xa6\x97\xabЩ\xab\xa8\x9d\xad̫\xad\xaa\xa5\xad\xc1\x9f\xaeλ\xae\x89\xad\xaf\xac\x9e\xb1ע\xb1ѯ\xb1\xae\xa5\xb4Ԣ\xb5۳\xb5\xb2ö\x91\xb5\xb7\xb4\xac\xb7ҩ\xb8ط\xb9\xb6\xb9\xbb\xb8\xad\xbcܱ\xbc\u05fb\xbd\xba\xb3\xbeٽ\xbf\xbc\xb7\xbfԱ\xc0\xe1\xbf\xc1\xbe\xb6\xc1ܹ\xc1\xd6\xce\xc1\x9b\xc1ÿ\xbb\xc3\xd8\xc2\xc4\xc1\xbd\xc4ں\xc5\xe0\xc4\xc6\xc3\xc6\xc8\xc5\xc0\xc8ݽ\xc9\xe4\xd8ɞ\xc6\xca\xda\xc0\xcb\xe6\xca\xcc\xc9\xc3\xceܿ\xcf\xe2\xc8\xcd\xdc\xcd\xcf\xcc\xc8\xd0\xe6\xcc\xd0\xe0\xcf\xd1\xce\xc6\xd2\xe0\xdbҥ\xe1ѥ\xd1\xd3\xd0\xd2\xd3\xdd\xd3\xd5\xd2\xcd\xd5\xeb\xce\xd7\xdf\xe6\u05eb\xd6\xd8\xd4\xd1\xda\xe2\xd8\xda\xd6\xd8\xd9\xe3\xd6\xda\xea\xd3\xdc\xe4\xda\xdc\xd9\xd8\xdd\xe0\xd2\xde\xec\xdc\xde\xdb\xdc\xdd\xe7\xe0\xde\xe2\xdb\xe0\xe2\xde\xe0\xdd\xf0\xe0\xb3\xd5\xe2\xf0\xe0\xe2\xdf\xde\xe3\xe5\xde\xe2\xf2\xe2\xe4\xe1\xe1\xe6\xe9\xe4\xe6\xe3\xde\xe7\xef\xe8\xe5\xea\xe5\xe7\xe4\xe4\xe9\xec\xe7\xe9\xe6\xe8\xe9\xf3\xe2\xeb\xf3\xe9\xeb\xe8\xec\xee\xea\xe6\xef\xf7\xe8\xf1\xf9\xef\xf1\xee\xf0\xf0\xfb\xf2\xf4\xf1\xf1\xf6\xf9\xf4\xf6\xf3\xf7\xf9\xf6\xf5\xfa\xfd\xf9\xfb\xf8\xfa\xfc\xf9\xfd\xfb\xff\xf9\xfe\xff\xfc\xfe\xfb\xfe\xff\xfc\xfa<^\xc5\x00\x00 \x00IDATx^\xed\xbd\x0fX\x15\u05fd\xef}^\xdb\xf7\xcd\xed\xdb\xc5y`\x1f\xe9\x16\nD\xde\xcb{\xc0s\x94\x83xߛ\x8cA\xbc\xafy\xfd\xcbE\xe5`Qo\x8f1\xb4\xc46\x86T\xebc8\xf14\x98\xee\xa6H\x11o\x12RJ\xbc\x1e\"\t\xdd\x16\"\xd1Rk$\xec<MHKbO\tI(m\xec\xb17x5h\xaa\xd3\xd4\x1eBD=>\xf3\xbc\xb3\xe6\xefZ\xb3g\xefa#\xcc\xf0\xe7\xfbɓ\xbdמ\xf9\xad5k\x96{\xbe\xac\xb5f\xf6\xfa\xfe\x854vD\x00\x00\x18\x17\xfe\xc2In\xa2\xe0T6\x00\x00\x8c\x0e(\x11\x00\xc0{\xa0D\x00\x00\xef\x81\x12\x01\x00\xbc\aJ\x04\x00\xf0\x1e(\x11и\xec\x14\x00\xc0\xc4\x01%\x02\x94\xbe\xa2T\xb2\xdc)\b\x80\tc\xda+Q}N\x9fSH\x8c\xf4\xe7\xd4;\x85LB\x94v\x88\\\xf5\xac\xac@\xd3\xe9\b\xfb\x00\x98x\\W\xa2\xe6\x10}\xbdT]\xa9R\xa3n\xed\f4D\xcb$\xfe\xcfG\xd7\xe4o\xbb\x125Ğ\x1dd\xbbSH\xcc\xec\x88\xdb\xe1\x14\xe2D\xe7b\u007f\xda\xea\xe6\xb4>q\x1d!\xc4ߥonJ\x89\xde\f\f\xf5Y\xb3\xe7\xd5.\x18u\xb8\xd6\x0e\x91\xaa~\x8a4\xdan\a\xc0%\xdcV\xa2\xbe\xca6\xfav\xbe\xb2\xbdW\xe6X\xe5)e\xeb\x99@Ku\xb4\\\xe2W\v\x0e\xef\xce\xff j\x88-\x15qUN!c\xa0!\xbe\xc2)Ġ\xb9\xddfc\xa3?;\xb0\u007f>!!\xb1'\x18\xdcCZ\xf5\xed\r\xfe\xa7l\xa2M\xcc\xc2*Ha\xfd\x16BF[\x0f\xa3\x1d\"T\xbd\x8d\x04\xed6\x03\xe0\x16.+Qo\xad\xaaDb\xe7\x80\xfc2PݢnnhꉪD\x1f\b\x87\xc4+\x17\xa2E\xd8\xd3\xed\xbb?z@\u007fn\u007f\xf4\x00{\xca|=N!:\xd9+÷\xf5'\xdd;(\x9f}\x06Q\xfa\x87m\xa6\x129a\x14\xd6E\xca\xe4\xd7M\xa3U\"\xa6\x1d\xec\xab\x1eC\x1d\x00\x98\b\xdcU\xa2\xe6\xca\xe6@\x9b\xf9\xf1\xe0S\x97\x94\xf7Ϊ\x81ިJ\xf4\xaep4\xda\xee\x88\x14\xa5\rD\x0f\xe8$\x9d\xd1\x03\xec\x19H+r\n\xd1Y`\xa3D\xf7'*sW\x15D\x19\x96Š\x02Fa\x85)\xb2\x94\x89!\xb2'Z\xb4\t\xd3\x0e\xf6U\x8f\xa1\x0e\x00L\x04\xee*\xd1\xf9\x01\xb1\xba\xcd\xf8\x14\xaaT'\x93\xcf\x06\xba\xc4(Jtq\x8d\xa0\xb0W\x14\x1f\x15\x84#\xe2\xbby\xc2\x06\x9a\xcc;\xbcwC\xfe\xb6\xdf(1\xef>\xb4&\xaf@K\x9b\f&mՓ]+S\x12R\xef\xe9\xe5vWd6\x84H\xa8!s\x0f_\u0095Û\xf37\x1e\xba\xc2\x1d\x82?\x9aܳH<\xcf\x15%\x16\x93\x84\xc0\xa6L\xff\xe2\x1e\xe5Ӟ\x05\xfe\xf9\xb4\xd4\x06\xa2\xb2@\xd9Z\x9d\xe3\xcf\xdcD%!C\x15\x83\xfe\n*'\x86\n\x9cI$$N\x9b73b\x99r\xd9\u0092\xd5\x13\xab8\xcd\x1e\x8d\xaf\x83q4\xae\x1dl\xaaNi\x86\x12\x01oqW\x89d\x18%\xaamR\xdf\x1b\xe4\xf7h}\xa27:\x8e\b\a::\xde\x17\xc5\xdft\xe4\x1d\x10\xaf\xbc\xfa\xc8\x12Q|\xebH\x9ePp\xe0\a+\x1e\xa2\x11//\xdb\xfc\x83\x13\a\x84g-\x19\xdbI\xb3\x96j\x9e\xb3`G\xd3v\xcb`\xa6\xb7\x90d\x91yde\x0f_\xc2\xee%\xfb\x8e\xef[\xb2\x9b;\x04w4\x99\x16\xeb\x95\x1b\xaa\x89')\xdb+\x92\x94;\xe1\xeb|e\re\xbeB\xb9\x03\xd2\x12\xcc\\\x18\f\x06\x95QXQ\\ICEʂ\xcb\xe2`\x1cW\x0f\xa3?r,\x18\xf4i\xf3\xebF,S.S\xd8\x19\xc2L\u007f\x19G\xe3\xea`\x94 \xb2\xed \xdaT]\xbc\xd4ל\x9d\xec\xd0y\x04`b\xf1P\x89\xba+{\x94\xf7P\xd5@t%bGgK\x0e\xc8/\a\x96(\xc9\x15r\x0feg\x81\x9c\xba\xb8v\xdbE\xf9\xf5\x88uJ\xbb\x81t\xab\x89\xf3s\x17\xcbݏ\xc1Z\xeb\xa4Pc\x02I8(\xf2%\x1c\x17N\xc8\x1bN\b\xc7E\xf6\x10lR\xa6\x87\x84M-\xfb\x92{訉\x96\xaa܈j$J\xc9ƀ\xaaAQ\x8f6\xb2_\xec&ܽtvd\x94\xb8\xdd\x12˖k\x16֩\xde\xea:\u007f~\x90?\x9a\x19˖`\xb6\x03%\xbc\xea\xf7\xca\x1d\xadQ߄\x03`B\xf0P\x89\x9aj\x95\xb7\x81@\xe8\xf2\xe5˧\xab\xa3=\xe2k\xafD\xbb\xf5\xe4q\xe1\r\xdbl\xf5\xfa\x15x\x90\x9c\xb4\xd9ݿ\xc97\x97\xa4\xf9\xb6\xf4s%\xecޠ\xbcmxDd\x0f\xc1&Ez9\xef\xb7\x14&\xfa\xd6\xc9/\xdb}\xf2K\xd1<eC\x16\xdd`*\xd1\xea\x8c\xc1K2s\x8b\xc4\xc1x\xfb>\x91h(\x91\x19˖k\x16vVљղ\x824qG3c\xd9\x12\xccv\xa0\x84W\xfdtce\x16\xfaD\xc0[<T\xa2\xaac\xca[w\xa5\x0e?\x8b\xc3b\xafDF\xf2Y\xe1\xa2m\xb6V\xfd\x1a\xaf 6s#⎔\xca\x10\tU\xa4\x94s%\x94nS\u07b6m\x16#\x1c\x8d\xd2FZ,\x85\x89\xca\xc0JQ\x81\x85K\x95\r\xf7\xe4\xd0WC\x89\xe6k\xd3<\xf7\x1a\xf3D\x83\x8dZYaJ\xc4\xc42\xe52\x85\xa5Љ\x9f\xbe:r\xff w43\x96-\xc1l\a\x8aM\xd5E1H\xda\xc27\x02\xe0\x1e\xde)Q\u007f\xa5\xf6\x87\xba\xbfO\xa6\xb3\xaa/ʳ\xd0\x16%\xdagц\x13\xc2/l\xb3\r\xe8\xd3.M\xc4\xee\xa9\x1eqP\xb9wF\xa7\x8d\x99\x12v\xaf\xa7OP^YO\xfb@\x11\x95\xa8\xdcw\xd6Z\x98\xa9\x02E\x19ʆ\f\xb3O\x148-\x0f\x9a2\xda\x15\xfa\x8d{g\xb5Dy\xb3Q\"&6\\\x89\x94\xc2Ri\xad\xeb\xe8\xc4\x17{43\x96-\xc1l\a\x8aM\xd5q\xef\fx\x8ewJ\xd4]y\x86\xd9<\xday\xa2\xfc\xbd\xb2J\xfc7\x8b6\\((\xa5]\x9a\xc7\xf6Z\xf3\xad\xccP\xc7|\x03i\xb9\xf4\xca-\xd9d\r\xe8\xa1\x13+\"W\xc2qሜ:\xa2\xce\x13EP\xa2\xcbY\xf7XKbT\xa0A\x19\xff\xecW\xe7^rs\xe5\xce\v\xa9\xa539\xb5\xf4sY9}\x9eh\xb9\\\x9d˹\xaa\x86\xd8(\x11\x13\xcb)\x91QX\x97\xf2\xc8t.U\"\xf6hf,[\x82\xd9\x0e\xa2}աD\xc0s\xdcU\xa2\xf3\xbd\xbdUͽj\xe7'T9hl\xbf,\xf7\x89z#>c\xa8\xde;{\x95vU\xc4҂\xa7\x9f\xde,\xe4=\xff\xd6\xfb\x1dy\x8f\xbcz\xe5\x8dG\xf2\xe8=\xb5\x97\xf37\x1c>\xfe\x98pؚ\xb3K\xbfK\xd5<;\xeb[\aKH\xc0\x1a`\xc0\x94\xb0Sx\xe2\xa5'\x84\x9d\xa2\xc8\x1c\x82;\x1a\x1d\xedY\xfbX\xbd\xc1\x84u\xadb\xfb\xba\x84\xa0<\xc6,\x8c\xbb\xbf\xe1\xfe\xb8Be\xc7v_E\xfd\"\u007f\x8f\x9c\xba\x9f\xac\xae\xad/\"Tr\x1b\xfd9U\xf5w\xc5\xcb\xc3$\xe5\x19\xeb\x8a`P\xee\xe7\f\xb6\x06\x83\xbeu\xc1\xe0Y6\x96+\x97)\xac\x82\x145\x14\xa9\xcfX\x1bG\xe3b\x99\xa31\xed`Wu\xca1\xbb!\x1b\x00\xee\xe1\xae\x12\x1dS\xe6\x83\x02\xca𠛹\x85\xd3\xcb\xfc\x04-\x8c\x8b+\x94lj\xf2ަ\x1f\xde-\xcd_\xb6m\x9f <\xfa(\xdd\xf4\xcbe\xf2\xeb\xa3\xf2\xe6\xb7\x1f^\xbbl\xb3\xdeob(\x9b\xad]a]+\xe7&\xe5ԅ\a\x18\x98%\\9\xb4Q\u007f\x9e\xc88\x04\u007f\xb4`\xe2\x16k\xf6bBHB\xa7_~-\x96?U\xccW\x9f\xf0\x91\x19,IN\\ئ$\x1bsS\x92\x17*7\xd4\xc4λ\xfc\xa9K\xe9C\x95\xeb\xb4\xf9\x1cy\xd8\xd5\x16\xa7&+\xd9X\xbe\\\xa6\xb0\xfa\xacĜ\x83s\x95\xd2\xf4\xa3\xf1\xb1\xccјv\xb0\xa9:\xa5/~\xe5\xa9>,\v\x02\xbc\xc3]%r\x9fM\xbeZ\xa7\x90\x98\xd9\xef+\xba\xe4\x143\xd9\xd0\xda!b\xd5보\xd9m\x00<a\xba+\x91X1w\xdcW\x05I\xbb\xed\x9f\xe2{\x80\xd2\x0eѪ\xdewj\xbc\x1b\n\x80\xd13\xed\x95\b\x000\x05\x80\x12\x01\x00\xbc\aJ\x04\x00\xf0\x1e(\x11\x00\xc0{\xa0D\x00\x00\xef\x81\x12\x01\x00\xbc\aJ\x04\x00\xf0\x1e(\x11\x00\xc0{\xa0D\x00\x00\xef\x81\x12\x01\x00\xbc\aJ\x04\x00\xf0\x1e(\x91\v\x1c\xdd\xfc\xfb\xa9jb\r\x80;\xb8\xaeD\xe1n\xd4竔T\x95\xb9\\Ѥ\xe6\x17t\x89\x92\xddQ\x02\x0e\v\xcaZk&O\v\a\xe8\xdaJ\xe3`b\r\xc0t\xc5m%\xb2q\xa3>Sy\x92\xa6\xa7\xca/\xc1\xff\xf0\xeaƍ\x1d\xbf\x8e\x12\xf0A\xc7\xe6\x03\xec\xe7C\xc2\xf3j\"\x16\x13k\x00f\x16.+\x91\x9d\x1b\xf5\x99\xca\xd3ѲL>\xbeZ\xea\x10\xb0\x8dU\xa2w\xf3\x9eГ1\x98X\x030\xb3pW\x89lݨ\xa7\xb9\x12\xed.\xb8\xa0'c0\xb1\x06`f\xe1\xae\x12ٺQ{\xa8D\xe1&\xd6\u007fX\x93\xb7om\xc1ˏ\xad(\xbd\xc0z_s0Jd8Ws\x85\xc9J\xf4\x98 \b\xf9\xbf\x93\xd3\x17\x971\xeb\xfc\xdb:A\x03\x00\\V\"\xd1\u038d\xfaLe\xd3S\x955A\x0f\xaeQ;\x13\xeb\x97W\b{K\x855O\xafy\x96\xf5\xbe\xe6`\x94\xc8p\xae\xe6\n\x93\x95\xe87;\x85g_\xa3\x9b\xdf\x10:̜\xe1N\xd0\x00\x00\x8a\x87J\xa4\xbbQ\x9f\xad\xac>\xd5\x13\xaa\xdd\xef\xfa\xbd3{\x13낝\xe2qᨸ\xdb\xe2w\xc6`*\x11\xe3\\\xcd\x16&+ѳK^\xd2C\xde6sژX\x03\x00DO\x95Hs\xa3\x16\xc5N\xda\x1d:_\xe5zw\xc1\xdeĺ\xe0\x88\xf8\x9apA|b\xa7\xe8\xacD\x8cs5[ض\x03\a\f\x83\xb6\xa3»fN\x1b\x13k\x00\x80\xe8\xa9\x12in\xd4:\xc1h\x1e@\x13\x82\xbd\x89u\xc1q\xf1\xb5<qtJ\xc48W\xb3\x85m+X\xb1\xe1!u\xf2H|Ux\xd5\xcci\xeb\x04\r\x00\xf0P\x89\f7\xea&\xc5+Uln\xb0\x8d\x9f@\xecM\xac\vN\x88\xaf-a\x95h\x9f\xbd\x12]8\xf0\x01\xeb\\\xcd\x16\xb6\xad\xe0\xadwWh\xb3O\x17\x9607\xd2l\x9d\xa0\x01\x00\x1e*\x91\xe1Fݠt\x86\xfa\xabN\xdag\x988x\x13\xeb\xee\x1d\xaa2\xb2J\xc4x_\x9b\x01\x9a\x12ѩhƹ\x9a-\x8c\xde\xc5?\x9e\xf7\x9a\x1a\xfd\xf0\x86+\xfa\x01흠\x01\x00.+\x91\xad\x1buO\xa0\xb1\xeb\xf4\xb1\x80\xeb]\"\x8b\x89\xf5R\xa2\xc8\xc4[\xab\x9e\xbdp$\xef\xad\v;K\u007f\xc3x_3\x01\u007f\xf8\xf9ƍ\x1d2\x87\xe9M1ù\x9a)샎͏\xbcz\xf1¶\x82\x97\u007fO\xb7\xbf-\xfc@?\x9e\xbd\x134\x00\xc0e%\xb2w\xa3\xeek\xaa\xa9j茜k\xe2`M\xac\xabR\xa8\r\xf4\x955\x82pd\x99\xb0\xec\x88 <\xc4x_\x9b\x01\xe2[\x82F\xfeیs5S\xd8a\xba\xf3\r\xb9\x00A\x1d\x97\x1d\xc8\xd7f\x8a\"8A\x03\x00\\V\xa2\x19ɕ\xbdy\xca/b\xa7\xa2\x895\x00.\x01%\x9ax\xae<\xbb\xf6wS\xd5\xc4\x1a\x00w\x80\x12\x01\x00\xbc\aJ\x04\x00\xf0\x1e(\x11\x00\xc0{\xa0D\x00\x00\xef\x81\x12\x01\x00\xbc\aJ\x04\x00\xf0\x1e(\x11\x00\xc0{\xa0D\x00\x00\xef\x81\x12\x01\x00\xbc\aJ\x04\x00\xf0\x1e(\x11\x00\xc0{\xa0DS\x18\xb8\\\x83i\x83\xebJ\x14\xeeF-\x13:XU˯%\xeb\x16\xdd\t$+lc\u007fqj\xe2=\x97m\xa2LJR\x81\xda\x17\xd1eC8\xe3\xb4G\xe8J#̢\xd7V\xe0r\r\xa61n+\x91\x8d\x1b\xb58\xd8\x14h\xedn\xaf슞s\x82h]\xe7\v۶(\xf5[\xeb\x12\xcf\xd8\x04\x8f\x0f\xef\xee\x15^\xbe ^\xe8\x10\xf6r\xba\U000db38eC\xec\xa2\xd7V\xe0r\r\xa61.+\x91\x9d\x1b\xb5\xd8\x14\xe8\xa5\x12\x15\x8a\x92o\x02\xd9\x1e\xa6D\xfdD\xbe\xb2\a\xecbljC\xca\xea\xfb\u007f\x10\x0eYw\xbc\x16M\x89\xe0r\r\xa61\xee*\x91\xad\x1bu_\xa5\xb2\x82\xb5Wk͇+Q\x17\x99\xe0\x95l\xc7E\x89\xe0r\r\xa6\x13\xee*\x91\xad\x1buk\xc0\xab\xa5\f{\vӒWj\xa3\xb3\xea\x1c\u007f\xe6&\xb9#4\x98B\x146q[O\xc5\x13R\xd6U\x98\x9e\xb8\xd8R\xd71\xf9Y\x9bJ\xf4\xa8\x90wx\xef\x86|\xbd\x00C\x89\xe0r\rf\x18\xee*\x91h\xe7F]\xdf\x10\xaa\vԴ\xb8\u007f-u%eV\xd5\xdfE\x14%*\x8a+i\xa8HYpY\x14O\x06\xf7\x93\xed\xc1`\x1f\xb7\xf5|mMzf\xd2\xdcM\x85\xe44W\xc4\xd8\xfc\xacM%z\xebH\x9ePp\xe0\a+\x1eRw\x18J\x04\x97k0\xc3\xf0P\x89t7\xea\xda\x00u\xa3\xae\xa9uݍza\x86\xdc۹<\x9f*Q\x03\xa9\x12\xa91\xa2b\xd1j\x8cθ\xad\vȢ\xb3\xd61\xe4\x18\xfd\xac\xd9\xd1ْ\x15rogg\x81\xbaCW\"\xb8\\\x83\x99\x86\x87J\xa4\xbbQ7(^\x1f\x03U\xc6\x0e\x978C\x02\xf4\xad\x8c*\xd1\xea\x8c\xc1K2s\x95\xf9\x16C\x89\xb8\xad\v||w\x882F?kN\x89v3\x01\xba\x12\xc1\xe5\x1a\xcc4<T\"ݍ\xbaY\xb5\xa1nv\xfb\x01\xbdc$Hߔ\x19\xeb\xf9\xea\xe4\x10\xb9\x97n1\x94\x88ۺ ;\xbc\x881\xfaY\x1f\x16h\x0f\xe7\x82b\xb4\xc6\x05\xe8J\x04\x97k0\xd3\xf0N\x89\f7\xea\xf6*\xe5!¦\t\xbea\x15F?\xd9Cߔ\x19\xeb\u008cv\x85~\xba\xc5P\"n낕\xe1E\x8c\xd1ϺCɦ\xce\xf4\xd8*\x11\\\xae\xc1L\xc3;%2ܨ\xfb\x95\xbb\xf8g\x03\xae?d\x9d3W\x96\x98\xae\xd9T\x89\x1aI-\xddRVN_\r%\xe2\xb6\xda)\xd1\x18\xfd\xac/\xac\xa2C\xb2ݫ\xe8mx[%\x82\xcb5\x98i\xb8\xabD\xb6n\xd4\xe2\xb1\xc0\xb1\x9e\xce\xea:\xd7\xef\xe5w\xfa疗%\xc7\xc5W\x85D\xf1~\xb2\xba\xb6\xbe\x88T\xeb\xf7\xce\xd4{Q\xc6\xd6K\xad\xc1̅\xc1`\xb7\xb5\x881\xf9YS\x8dy\xf4\xf8\xa3Tm\xde\xef\xc8{\xe4\xd5+o<\x92\xd7\xf1\xbe\xf8k\xfa\x8c\xf5\xb3\x1d\x1d\xbf\x16\xe1r\rf\x1c\xee*\x91\xbd\x1b\xb5\xd8U_Uw\xccu!\x92\x8f\xbb49}KU<)\x96Ӎ\xb9)\xc9\v\x0f\x8a\xe2`\xb225\x14\xaf>\xf1\xado=\x15\xa7l\r\xefz\x8c\xc5\xcfZ\xe6\xf8\xe6e\x9b\xe5\x0e\x0f}\xe0H\xc8\xfb\xe52\x81\x06\xec\xd6\\\xae\x1f\x16\xe1r\rf\x1c\xee*\x11\x18G\xe0r\r\xa6\x11P\xa2\xa9\v\\\xae\xc1\xf4\x01J\x04\x00\xf0\x1e(\x11\x00\xc0{\xa0D\x00\x00\xef\x81\x12\x01\x00\xbc\aJ\x04\x00\xf0\x1e(\x11\x00\xc0{\xa0D\x00\x00\xef\x81\x12\x01\x00\xbc\aJ\x04\x00\xf0\x1e(\x11\x98VL\x9cM\x1d\x98P\xa0D`\xfa\xd0W\x94J\x96;\x05\x81I\t\x94\bL\x1f\xb2\xb2\x02M\xe1k\xfc\x82\xa9\x80\xebJ\x14\xe6Fm1\xa6v\x97\xa6\x14c\xa5ȱXP;\x19H3\xbc|\xb7Pz\x85ZP\xdf\xfdr\xe4\xa0\x13\x05\xfa2\xd5\xe2\xff|tM\xfe6c-\xb4\xe84$\x8f~\xbdK\xfd\x8c\xd7\x11B\xfcᶻ\xfd\x8b\x92w\x84'9F}4\xbeu\x98ss\xe2\xe8\x86\xfc\x8dG6\xbe\xe4\x14\x16\xc6)\xd2\xe8\x14\x02&+n+Q\xb8\x1b5gL\xed6\r~c\x95\xa4\xb1XP;\x19H3\\<!\xe4w\x88\x17\x8e\b',K_\xbf\xcc,@\xfbҲ#z\xf2\xab\x05\x87w\xe7\xf3\x9e!\x11\xd9J\xb6:\x85\x18\xe8g\xdc\x13\f\xee\xb1\xf1&ڒ\xb1#\xae/,\xc91\xea\xa3\xf1\xadÜ\x9b-f;\x1c\x12v\x1e\xdd+\x84\xfbR:Ҧ\xaeL\x0e\xa6\".+\x91\x9d\x1b5kL\xed\x1dc\xb5\xa0v\xb0m5\xb9 \xec|D\x14\xdf\x15.\x88<\x9b\x1ff>\x18\x9d\xa0\x0f\xe4\v\xf1\x8a54\x12e\xa4\xcc)Ď6\x1b%\xca.\x17\xfd\xc1\xb0$G,Gc[ǡ\x83g\xb4\xc3\xdbw\xef\x93_\xf7\x8eI\x89`\xfb6eqW\x89lݨ\xadIo\x18\xab\x05u\fJ\xf4\xf2\xb2\v6J\xb4\x91U\"\x83w\x85Q\x8feD\xb1\x9c\x94;\x85\xd8aw\xe1Ϋ\xea!]aI\x8eX\x8e6\xea\xd6a\xdaaw\x01\xed5\xfe\x12J4\xb3pW\x89lݨ-I\xf78\x93HH\x9c2;\xc5[P3\x84\x9bM[\xb7\xda\x19Hwl[\x9b\xb7f\xdbZş\xe3\xf9\xcd\xcb6\xec\xa5\xeasAxw\xe3\x11M\x89\x8cأڊ\xb1\x9b\xe5\x8d\x1f\xe4\v\x82\xb2\x92\xbexq\x8d\xbau\xaf<\xa6\x91\xdf\xf6\x89Ok{\xec\xab#\xee ʄNO\x92抔\xd4\xc3\xec,&\t\x81M\x99\xfe\xc5t\x9by\xc6\x14\xbb\v\xf7\x9e\xb2{睊W\x16\xcfe\x92\x1c\xda\xd1\xc4XZ\xc7<7\xa6I\x18+n\xb6\x1dV=\xa1\x84\x1d\xa2\xeby\x1b\r\xc5\xd9v\x9b\x8d\xca\xd3\f%\x9a\xba\xb8\xabD\xa2\x9d\x1b\xb5%\xe9\"ǂA\xdfv%\xc5ZP3ؙM[\xb6\xda\x18H\xbfq\xf7\xee#'\x0e\xaf\x11\xfe@\xb7\n\x8f\x1d?T\xb0\xf1\x8a\xa2D\x87\xb6iJd\xc4^x\xb5cCiGG\x87\xe2\xe7\xfaZGG\xbe\xbaD\xf5\x1b\x1dG\x84\x03\x1d\x1d\xefӀ\xb5\x8f\xfe^\xfc\xfd\x81\x15\x1d\x17\"U\x87\xae\xa8_A\xdf\x06\xab*T\xaaX;\xddPM<I\xd9^\x91\xa4\xdc\xdd6\xcfX\xb4W\xa2\xf2$߱K\xf7,l\xe5\x93\x1c\xda\xd1bk\x1d\xf3\xdc\xcc&a\xac\xb8\x99v\xf8@x\xde,\xcch(ζ\xdblT\x86K}\xcd\xd9\xc9c\x18^\x83Ɂ\x87J\xa4\xbbQ\xf3I\x97IԯK\xbbљ\xbd\xd94\xbf\xd5\xc6@\xfaP\x01\u0560C+\xae\xd0.\xcd\xf3J\xcc\x11E\x89~\x97\xff;E\x89\x98X\xcb\xe8L\xbfZ\x99\xd1\xd9\x01\xdaOP\x9c\xad\xed\xab#\x13 \xeaJ\xfd}\xdd*\x16A\xf5%\xf7\x88ba\x8a\xf6)1\xaa\x12\xed \x01\xf1\xac\xff\xa0%ɡ\x1f-\x96֡h\xe7\xc64\tgŭ\xb7\xc3/\x95ƹr\xf1\xe2E\xbe\xa1\xccX\xb6\x04\x93{\xe5\xce\xe0\xd8\x06\xd8`2\xe0\xa1\x12\xe9n\xd4|\xd2e\xa2*\x91\xbd\xd94\xbf\xd5\xc6@\xfa\xd7\x05\xeb\x1f;\xfc\xc6\x15:۱s\xfd\xc5?Ȭݭ(\x91\xb8\xedYE\x89\x98Xg%\xfa\xcdݿ\x14/\xae\xa0W\xa4}ud\xaaH\x15}\xeb&:\xbc\x1b\x92o\x9d\xa8Y\xddR\xa2*Q-I\xde$V\xa4]\xe2\x93<\xda\xd1bj\x1d\x8avnL\x93pV\xdcz;\xa8}\xa2\x9d\xf2P\xed\x04\xd7Pf,[\x82\xc9\xe9\xc6\xca,\xf4\x89\xa6.\x1e*\x91\xeeF\xcd']&\xaa\x12ٛM\xf3[m\f\xa4\xc5\x0f\x0e?\xbcAX\xf3\xb4\xdc'ڨ\xcd\u007f<\xa4*ё\x8d\x8a\x12\xb1\xb1\x8eJ$n\xdb+\x1e_A\x0fi_\x1d\x99\x96dUR\x82\r*\x96;^\xcaxlTJ\xd4\xe7\xdf\xd4<\xbb;c;\x9f\xb4\xa0\x1f-\x96֡h\xe7\xc64\tg;i\xb4\xc3\x1a:O\xf4\xfe\x11ቋ\\C\x99\xb1l\t\x1cA\xd2f\xdd\x04\xa6\n\xde)\x91\xe1F\xcd%\xdd&\xaa\x12ٛM\xf3[m\f\xa4_{BN~p$\xff\x10\xfd\xf3\xfd\v\x85ߩJta\xd9\t\xa5Od\xc6jW\xe0\xe1_\xab\xa5\xd9)\xd1\xd1U\x17\x95\xc1Y\x84\xea83z%\xaa\x97{S\xcbӓ\xce\xf0\xc9\b\xc4\xd2:\x14\xa3Od4I\xb8\x12\xd1vؽ\x86j\xd9Qz\xef\x8cm(3\x96-\x81\x03\xf7Φ0\xde)\x91\xe1F\xcd%\xdd&\xaa\x12ٛM\xf3[m\f\xa4\x0f\xa8\x13@\xa5\x8f\xd2\xebR\x99\xcc\xd8\xf7\xb4\xaaD\xe2\xee\x9d\xea<\x91\x11+\x87\x95\x8a\xe2\xef\xf59\x0f;%\xba\xb8\xe6誗\xc3\x0f<zF\xafDu\xa4K<IV\x8b\x97ӻ\x99\xa4hO,\xadC\xd1\u038di\x12N\x89\x8cvx\xfbny\xeb\x95R\xaaDlC\x99\xb1l\t\x1cP\xa2)\x8c\xbbJd\xefF\xcd&\xddd\xb05\x18\xf4\xad\v\x06\xcf\xf2\x16\xd4\fvf\xd3\xecV{\x03\xe9\x03²\x03/\x1d\xdd-P\xf9x\xe2\xee\x9dG\xe4\xe4\x11\xfa\x8c\xf5\x91\vrV\xe5\xde\x19c6-_\\\xcf\x1e\xfd\xea2\xb9\x84\x8b\xafvt\xe4?\xd2\xd1\xf1\x81~\xef\xecU\xed\xe6\xd0\x13\xebW\xfc!\xbc:\f\rs\xa2L\xd5\xf6\x06\x13ֵ\x8a\xed\xeb\x12\x82\xbd\xec\x19+\xcfXW\x04\x83\xdcϴ\xfa\xfc+\xeb\xd23}%\xe5\t}L\xd2R\xa0q\xb4\x18Z\x8797\xb3IX+n\xa6\x1d\xe4\x01\xde\xee\x97v\xab\xcfX\x1b\r\xc5\xc5\x1a%X8F<~<\x16\x8c\x1dw\x95(\x82\x1b5\x93t\x936\xd5b\x9aTZ,\xa8\x19\xc2ͦ\xb9\xad\xf6\x06\xd2ϗ>\xbd6\xaf\xa0T\xfd}ى\xd25+J\x8f+\xbf;\x93/\x9d+\x9b\v\xaep\xb1\xf2E\xfaت\xfc\xd2\xd7\xe4\xc4\x1bZa\x87ŋ+\x94D\xde\xdb\xda\xe1\x04}n\x96\xad\x0e\xc3\xc1\x94\xf0;\\\x06\xc5\xf2\x89%t\xfa\xe5\xd7b挕ߝQVr\xc1M\x19)\xc5\x03M\x99\xc9{\xb8$\x8fy\xb4ѷ\x8eyn\xa2\xd9$\xac\x157\xd3\x0e\xca\xef\xce6\x1f_K;BFC\xf1\xb1z\t\x16\xfa\xe2W\x9e\xea\x8b\xf1\xa7\x83`\x92\xe0\xae\x12\x81\xb1paI\x94\x1f\xcd\x02\x86\xfa,B\xeeu\n\x02\x93\x12(\xd1\xe4\xe7Ț?8\x85\x00\x8d\xbeS\x1e<\xac\x0f\xc6\x01(\xd1$\xe7闯|\xf5\x80\b\xc04\aJ4\xb9\xb9 l~\xb4`\x94\x8b\x83\x000u\x81\x12Mr\x0e,+}\xdb)\x06\x80)\x0f\x94\b\x00\xe0=P\"\x00\x80\xf7@\x89\x00\x00\xde\x03%\x02\x00x\x0f\x94\b\x00\xe0=P\"\x00\x80\xf7@\x89\x00\x00\xde\x03%\x02\x00x\x0f\x94\b\x00\xe0=\xae+Q\x98\x1b\xb5(\x0e\xb4<\x15x\xaae\xc0!\xe34b\x92\x98X\x030yp[\x89\xc2ݨ\xc53\xd5u\xa1\x9eP]\xb5g\xeb6\xba\xce$1\xb1\xa6|\xf0~\xe4}\xcd\xed\x91\xf7\x010\xbe\xb8\xacDvn\xd4\xc1Z\xea\x1fq\xa9vFy\x9a\x8f\xda\x1cu\x02M\xac\xa9\xb1\xe1\x8aR-y\xf9\xd2\xe5\xcb\xf2\xff\xec\xdel~\x155\x00&\x10w\x95\xc8֍\xba\xa9^\xf9P\xef\x89\xf9\xa2WĠD\x13fb-\xbe\xb5YмZ\xbb\xb2\xb3\xb2\ue657\x95\xb5\x89\x1d#/\x80\x12\x01\xd7pW\x89lݨ\xfb\xab\x9b\xfb\a\xfb\x83\xd5\xfd\x91rM=Fo\xd3졉\xf5\x85\xbd\xc2ڗ\xd4\xe4%\x1f\xc9͝\xe5\xcf͞\xf5\xc0ymo\x83\xb6\xba\xec\x02Q<\x15OHYWaz\xe2\xe2K\xc5$\xaeZ\xec\xf6\x91,%\xa6:ǟ\xb9i\x06\xcd\xef\x81\t\xc4]%\x12mݨ\xcf7UVV6\xea\x97\xc04 \x16\x9bf\xafL\xac\xaf\x1c-\xc8{B\xedh]|\xf7\xed\xff\xbd\\\x92B\xc3\xd2\xc8g\x97\xea\u007f\x0f\x06Z\x82\x99\v\x83\xc1`H\xfe\xf7\xa9\xadI\xcfL\x9a\xbb\xa9\x90\x9c\xee\r&l\x17\xc5\xd6u\x8aQHQ\\ICE\xca\x02,\x1c\r\xc6\x01\x0f\x95H\xb7\xa0\x1el\xaa\r\xf5\x86j\x9b\xc2\xddF\xa7(\xb1\xd84{fb\xfd\xa8\xb0\xf1--Y*\xfc?\xff\xe7\xacY\xb3ĕ\xb3f}\xa6\x9c\xb9o\xc0\x8c\xce\x16\x90EgE\x91:!\x98\x96E\r\x8a\x17l\x1b\xd9/\x02p\xdbx\xa8D\xba\x05u\xb0\x96z\f\r\xd6N\x1b\x87\x98Xl\x9a=3\xb1~~ɪ絉\uedcf\x1e\xfd\x1f\xff\xef\xff%+\xd1\u007f\xb8wG\x17\xe3\xf7\xc4*\x91Ow#2\x95hu\xc6\xe0%\x99\xb9E\"\x00\xb7\x8d\x87J\xa4[P\aN*o'\x03v\xe1S\x91Xl\x9a\xbd3\xb1~w\x9b\xb0Y\xef\x15\x89\x97\xcf\x06d%\x8ao\xefg\x8d\xe7X%\xca\xd6S\xa6\x12\xcd\xd7f\x92`\xa6\x01\xc6\x01\xef\x94Ȱ\xa0֔\xa8}\xda(Q,6\xcd\x1e\x9aXә\xa2\xbd\xc6-\xb9Z\xaaD]\xdc\bYQ\xa2\xc0i#\xa9\xa0(Q\x19U\xa2\u008cv\x85it\xa7\x01x\x87wJdXP7k\xa3\xb3\xe6\b9\xa6\x1c\xb1\xd84{jb}a\xafPpBK\xdb(Qn\xae(\xf6\x91Z\x9a4\x95ȿU\xeeAeS%jTw\x95\x95\x8b\x00\xdc6\xee*\x91\xad\x1b\xf5\xf9\xfd\xb5\x9d=\x9d\xb5\xfb\xa7\xcfͳ\x18l\x9a\xbd4\xb1\x96y\xabT\x1f\xe4\xd9(\xd1v_E\xfd\"\u007f\x8fx\xa9U\xb9\x8d\xa6\n\xea\u0094\x1d\xe59$\xbe*$\x8a\xf7\x93յ\xf5E\xa4\xdaZ(\x00\xb1\xe3\xae\x12ٻQ\x0f\xb6\xd5Uյ\xb13\x14S\x9d\xd1\xdb4{ib\xcda\xa3D\x83%ɉ\v\xdbD\xf1\x94\xeaa\xad\njWnb\xd2\xe2\xafPkk\xb9W\x94\x9b\x92\xbc0\x8a\x116\x00\xa3\xc6]%\x02.\x12\x9b\x89\xb5\x8d\x12\x01\xe0\x1eP\xa2iKl&\xd6P\"\xe0)P\xa2鉓\x89\xb5`\xe5\xff\x96\x95\xe8\xff\x80\x12\x01\xaf\x80\x12MK\x1cM\xac\xa1D`r\x01%\x9a\x9e\xc4lb\x8d\xd1\x19\xf0\x14(\x11P\x80\x12\x01O\x81\x12\x01\x05(\x11\xf0\x14(\x11\x90\x19ܳ\x92\xfe\x02vk\xcbtz\xaa\vL%\xa0D@&G_\x15\xa4\x0eR\x04<\x01J\x04D\xf1\xfc\x1d\xe5\x924$I#w,\x9f9\xbe\x06`R\x01%\x02\xa28@Hn\xee\x1d\xa9\xb9ٳ\x8a\xf0\xcbz\xe0\tP\" \x8a\x97\x82s\x93\x933\x93\x93\x93\x17\xb5M\x9f\xdf!\x83)\xc5LV\xa2\x95$\xa50\xe4\x1443\x18\xec\xeb\xee\xea\xee\xee\xea:\x8d\xf5\xf1\x817\xccd%\xeam\xae\xcaJ\xc1\xa5\xa7B\xbd\xce,~g\x00\xb8\x87\xebJd\xe3F}\xf9T}\xa0Λ\xceI39\xe5\x14\x02\x00\x98x\xdcV\"\x1b7j\xb1\xa1\xaa\xbd\xfbX\xe0X\xf4\x8c\x13C\x1biu\n\x01\x00L<.+\x91\x9d\x1b\xf5\xc9\x00\xbd_\xd3\x15\xf0b\x9c\x04%\x8a\xc8,\xcfq\xaa!\x98N\xb8\xabD\xb6n\xd4\r\x8dʇj/:EP\xa2\x88\xcc:\xe71P\xa2\x19\x85\xbbJd\xebF]\x17T>\xd5{\xb1\f\xe9)2m\xd6\xf1\x1fo\xa0D\xc0M\xdcU\"\xd1\u038d\xba\xa5Z\xf1\xf6\xa8\xaa\xb3\xcf0\xa1\f\xa6\xe4\xb4\xf4\xe0\x86\x91\x1dP\"\xe0&\x1e*\x91\xeeF=P\xd5\xd0w\xbe\xb7\xbe\xb2\xd6>\xc3\xc4r\x90\x10\xb2\xd4)hF\x02%\x02n\xe2\xa1\x12\xe9n\xd4b\u007fCee\xa0\xb5\xa1\xde6~b\x19Hɨh\xeev\x8a\x9a\x910J4jQ\x1au\xe0\xb9Q\xc4B\x89f\x14\x1e*Q\x959E}\xbe\xff\xb2\xa8\xdcGs\x9b6\xd2\xe4\x142S\x81\x12\x017\xf1N\x89\f7jQY\x9e\xabK\x9d\xbev\x19\xdc;\x8b\b\x94\b\xb8\x89wJd\xb8Q+\xb7\xd0\xce\xd6xr\x13\vJ\x14\x11Y)~\xfa\xb7w\xcc\xfa\xc2?ɚ\xf0\x8d/̺\xe3\xef~%\xab\xc3\xd7?\xff\xbf}\xfe\xeb\xf2\x8e;\xe4\xf4\xdf\xc9\xff\xdf\xf13U5\xbe\xf3\x85Y\x9f\xfb\x06\x13(\xe7\xfc\xec\xdf\xfe\x8a\xd9`\x16\U0005dfda\xf5\xf9\xbf?g*\x91V\xe4\xb9Y4!\x97a\x1eթ\x86`:\xe1\xae\x12ٺQwU\xb6\xf5\x9c\xacn\xf0\xe2\xc1F\xb1\x15J\x14\tY)\xbe\xf0\xe5_\xbd\xf7\xcf\u007f#k\xc2_>\xf3\xde\xcf\xfeNV\x9e\xef|\xee\x99\u007fy\xe6s\xdf9w\xee/\u007fx\ue9f3~v\xee\x9f\xffRU\x93\xef\xfd\x87\xef\xbd\xf7ӿc\x02\xff\xea\x99\xf7\xfe\xe5\xbf\xfc'f\x83\x91\xf8\xe7\xbf\xfa\xe7\xf7~\xfa\x1f\xff\xdeP\"\xa3\xc8Y\x9f{\xe6\xbdg>\xf7ߙ\xa3:\xd5\x10L'\xdcU\"{7\xea\xf6ڪ\x86\xf6ș&\x8c\xc1\xde\xf6\x95\xbe^\xa7\xa8\x99\x8a\xac\x14\x9f\xd1z<\xb3~(\xbf\xfc\x8b\xdc\x0f\xfa\xe2w\xa8v|\xf1ܹ\xff\xf2\xe5s_\x9e\xf5\x8ds\u007f\xff\xff\xa9\x01_\xfc'K \xe5_>\xc7l0\x12w\xd2\xc4\xcf>o(\x91Q\xe4,%q'sT\xa7\x1a\x82鄻J4\xb9\xb8\x97\x90t/n\xd8M\rd\xa5\xf8\xafw\xfc\xe7oPYPEC~\xfd,\x1d^\xfd\xea\xb3r'\xe8\xaf\xcf\xdd\xf9\x9f\xfe\xe6\xdc\x17\xbf\xa7\x89Ư\xce\xe9!\xea\xeb\xcf\xfe\xe6\x8eY\xb3f1\x1b\x8c\xc4\x1d\xea/9\f%2\x8aT\xca\xf8\xd5\x1d\xccQ\x9dj\b\xa6\x133Y\x89\xfa\xda{\x9cBf0T)~\xf8\xe5\xbf\xfd\xec\x97\xed\x94\xe8\xbd;~\xf6\x99\x9f\xdd\xf1\xb3Y\xef\xa9rr\x87U\x89\xee\xfc\xaf?;\xf7\x9e\xad\x12\xcd\xd2z<\x91\x95\xc88\xaaS\r\xc1tb&+\x11\x88\x86\xa6\x14?\xfd,##\xc6P\xeaܝ\xff\xf9?\xca\xffߩ\xa9ʝ\xfa\xe8L\u007f\xfd\x8c,Q\xcf\xd8*\xd1\x17\xbf~\x8e\x8d\xb5\x19\x9dQ\x94\xa3:\xd5\x10L'\xa0D\xc0\x1eY)\xfe\xfa\xbf\xbf\xf7\xde\u05ff\xc0\xc8\xc8w\x94Ye*\x19_\x9e\xf5e\xe5\u007f\x95g>\xa7\xcdX\xeb\x81_\xf8\xf2{?\xfcK[%z\xe6\x8eo\xfc\xea\xbdg\xfe\xdaP\"\xa3Hu\xc6\xfa{\xccQ\x9dj\b\xa6\x13P\"`\x8f\xac\x14\u07fbs\xd6\x1d\u007f\xf3SFF\xce}\xfd\xf3\xb3\x94[\xee\xe7~8\xeb\xa7\xe7~\xaaLC+\xfc\xd3_\xa9w\xf1\xf5\xc0\x1f~a\xd6\xe7\xben\xabD瞹\xf33\xb3\xee|\xc6P\"\xa3\xc8Y4A\xef\xe2\x1bGu\xaa!\x98N@\x89\x80=\xbaR\xb8E\xd8\xf1\xa0D3\n(\x11\xb0\aJ\x04\xdc\x04J\x04\xec\x81\x12\x017\x81\x12\x01{\xdcV\xa20\xa0D3\n(\x11\xb0\aJ\x04\xdc\x04J\x04쉺ؽ+8\xd5\x10L'\xa0D\x00\x00\xef\x81\x12\x01\x00\xbc\aJ\x04\x00\xf0\x1eו\xa8Y\xb3\x9d\x1ehy*\xf0T\x8b\xba(Q_}U\xa3\x17+6:\xf1\x88 \b\xf9\xef\xea\x9fN\x14\x1c\x8d\x16\xccrtC\xfe\xc6#\x1b_r\n\x03\x00h\xb8\xadD\x9a\x1b\xb5x\xa6\xba.\xd4\x13\xaa\xab\xa6\xeb6\xf6\x04\x82]\xc1@O\xb4l\xde\U0001b38eC«\xfa\xa7\x97\x96\x1d\x89\x16,\xbe\xfc\v=uH\xd8yt\xaf \x1c\x8a\x16=z\x9a\xbdX\xbb\t\x00wqY\x89\f7\xea`-]\xbd\xfaRmP\x14/\xd7е\xf4[j&\xa5\xed\xd8k\xa6\x12\x89W\xa2\xc4\xc9l~XK\xbc}\xf7>\xf9u\xefx)Q\xf6J\xa7\b\x00\xa6<\xee*\x91\xe9Fݤ.QV\xdf$\x8a\xa1\xc0y95\x10\bE\xce\xe7\x1d\xac\x129\xb0QW\xa2\xdd\x05\x17\xe5\xd7_\x8e\x97\x12-\x80\x12\x81鏻Jd\xbaQ\xf7W7\xf7\x0f\xf6\a\xab\xfbeQRm\xa8\x0fz\xb0\xa4\xfe\xbb\x0f\xad\xc9+\xd8\xf6\x9b([u%\xfa _\x10\x04mtv\xe5\xf9\xcd\xcb6\xec\xbd \x8a\x8f\ny\x87\xf7nȧ\xa1G\x05\x95\xcd\xf2\xfeUO(a\x87~Mc\x0fo\xce\xdfx\xe8\n\x17˔\xc0ГDT\x92z\x98\xad\r\xda\xc6\x05\xa2x*\x9e\x90\xb2\xae\xc2\xf4\xc4ŗ\x8aI\\\xb5\xd8\xed#YJLu\x8e?s\x93'ˀ\x030^\xb8\xabD\xa2\xe9\xedq\xbe\xa9\xb2\xb2\xb2\x91\xf6\x86\xeaT\xa3\xb3\x16\xf7\x17r}y\xd9\xe6\x1f\x9c8 <\x1be\xab\xd1'z\xad\xa3#\xff\x80\x9a\xdc-<v\xfcP\xc1\xc6+\xe2[G\xf2\x84\x82\x03?X\xf1\x90(^x\xb5cCiGG\xc7۲h\tϛ\x85\xed^\xb2\xef\xf8\xbe%\xbbE6\x96)\x81a\xb0\xaaB\xa5j\x90\xd9:\xd0\x12\xcc\\\x18\f\x06\xe5\x0e\xe3\xf9ښ\xf4̤\xb9\x9b\n\xc9\xe9\xde`\xc2vQl]\xe7\xa3!Eq%\r\x15)\v&\xe5\xe0\x16\x80Q\xe2\x95\x12\r6ՆzC\xb5M\x97\x8c-mՑ3M\f\x17\xd7n\x93\x87Q\x17\x8f|\x10e+;:Ӕ\xe8%Ei^SzHKV\xc8}\x9c\x9d\x05\xcav}t\xf6K\xe1\x84\xfcz\xe5\xe2E\xb9\x98\xe3J\xfa\x84p\x9c\x8beK0\xe9\xebV\xb1\xdeEdFg\vȢ\xb3\xa2H\r\t|\xb2\x12\x89۩\x125\x90*\x91\xda%\xed\x17\x01\x98\xbax\xa5D\xc1Z\xfa\x97\xa8\x1c\x16}\x00\x00 \x00IDAT\u007f\xb0V\xee\x0f\xd5\x05\x95-\xcdu\x913M\fDž7\x1c\xb7\xda(\xd1\xce\xf5\x17\xff \xb3V\xee舴\xb7#\x1eX\xa2lוH\xed\x13픇j'\xc4\xdd\x1b\x94M\x1b\x1e\xe1b\xd9\x12\f\xba\x89\x8e\xc5\x1d\x9bU\"\xdfi-e*\xd1\xea\x8c\xc1K2s\x8bD\x00\xa6.^)Q\xe0\xa4\xf2v2 \x8aM\rJ\xb2\xde\xf5y\xa2g\x85\x8b\x8e[m\x94h\xa36%\xf4\x90\x9c^B7Y\x94H\\C\xe7\x89\xde?\"<qQ,ݦlٶ\x99\x8beK0\t6\xa8\x04E\x1eV\x89\xb2\xf5\x94\xa9D\xf35\xfd\xbaW\x04`\xea\xe2\xb1\x12\xb5\a\xa8\x05#\x1dn\x9c\xadt\xfd\xde\xd9\t\xe1\x17b8\xfcV\xdb>\xd1/\x14~'\xda(\xd1\xe1_\x8b\xe2\xee5Tˎ\xd2{g\xbb\xd7ӹ\xa0+\xebws\xb1l\t\xce(J\x148m$\x15\x14%*\xa3JT\x98Ѯ\xd0\x1f!;\x00S\x01\xaf\x94\xa8Y\x1b\x9d5\xd3\xe7\x89ho\xa8\xd9\xfd\xe7\x89.\x14\x94R\xc9xl\xaf\xf2\xa9{G\xb7\xcdV\x1b%:\xa1\xce\xef\xec{Z䕨\xb4T\x14\u007fO\xf7\xbd}\xb7\xbc\xf5J)U\xa2\xe3J\xec\x11u\x9eȈeKp&7W\x14\xfbH-M\x9aJ\xe4\xdf*7\\6U\xa2FuWY\xb9mf\x00\xa6\x06\xee*\x91\xe9F}~\u007fmgOg\xed~z\xf3\xac'\xd0\xdc\xdd\xec\xc53\xd6/\xe7o8|\xfc1\xe1\xb0\xf2a)\xb9Ǻ\xf5\xd7\xf4\x19\xebg;:\xe4~\xce\xc5W;:\xf2\x1f\xe9\xe8\xa0\xf3\xd8Oܽ\xf3\xc8\xd1ݲ\x9a\xbcߑ\xf7ȫW\xdex$\xaf\xe3}\x91\x8a̳G\xbf\xba\x8c\u07ba\u007fV\xd8\xfd\xd2n\xf5\x19\xeb\x9d\xc2\x13/=!\xec\x14\xf9X\xa3\x84Ѱ\xddWQ\xbf\xc8\xdf#^jUn\xa3\xa9z\xb90eGy\x0e\x89\xaf\x92;\x92\xf7\x93յ\xf5E\xc4\xf5\t\u007f\x00\xc6\x11w\x95\x88q\xa3\x1el\xab\xab\xaakSoX\xf76\x06\xea=q\x85~\xfb\xe1\xb5\xcb6k\xbf&\xabJ\xa9\xb4nݭ\xcd\xe7\xc8î7\xb4\xa4\xa2Z'J\u05ec(=N\x9f\x11\x12\x84\xbc_.\x93_\x1f\x95\xb7^|lU~\xe9kJ\tG7\xe4o>\xbe\x96v\x84\xae\x1cڨ?O\xc4\xc6\xea%\x8c\x86\xc1\x92\xe4ąm\xa2x*N\x99\x0fR\xf5\xb2+71i\xf1W\b)\x96Ӎ\xb9)\xc9\v\x0fF-\x03\x80I\x8e\xbbJ\x04\x00\x00v@\x89\x00\x00\xde\x03%\x02\x00x\x0f\x94\b\x00\xe0=P\"\x00\x80\xf7@\x89\x00\x00\xde\x03%\x02\x00x\x0f\x94\b\x00\xe0=P\"\x00\x80\xf7@\x89\x00\x00\xde\x03%\x02\x00x\x0f\x94\b\x00\xe0=SA\x89V\x92\x94B\xd7\x17/\x02\x00\xb8\xc8TP\xa2\xde檬\x14xW\x000\x8dq]\x89\xecܨͭ\x91h&\xa7\xa2\a\x00\x00\xa62n+\x91\x9d\x1b\xb5\xb95\"m\xa45z\x00\x00`*\xe3\xb2\x12ٹQ3[#\x02%\x02`Z\xe3\xae\x12ٺQ3[#\x02%\x02`Z\xe3\xae\x12ٺQ3[#r\x8a\xb8\xeeA\x04\x00p\x0fw\x95H\xb4s\xa3f\xb7Fb0%\xa7\xa5\xc7u\xf3\x0f\x00\x80Kx\xa5D\x8c\x1b5\xb352\a\t!K\x1db\x00\x00S\x15\xaf\x94\x88q\xa3f\xb6Fd %\xa3\xa2\xd9\xe2\xd2\f\x00\x986x\xa5D\x8c\x1b5\xb35\"m\xa4)z\x00\x00`*\xe3\xb1\x12\xb5\x8fZ\x89p\xef\f\x80i\x8cWJĸQ3[#\x02%\x02`Z\xe3\xae\x12ٻQ\x9b[#\xd2\n%\x02`:\xe3\xae\x12ٻQ3[m\x19\xecm_\xe9\xf3ĭ\x1a\x00\xe0\x0e\xee*\xd1ظ\x97\x90\xf4z\xa7 \x00\xc0\x14f*(Q_{\x8fS\b\x00`J3\x15\x94\b\x000݁\x12\x01\x00\xbc\aJ\x04\x00\xf0\x1e(\x11\x00\xc0{\xa0D\x00\x00\xef\x81\x12\x01\x00\xbc\aJ\x04\x00\xf0\x1e(\x11\x00\xc0{\xa0D\x00\x00\xef\x81\x12\x01\x00\xbc\aJ\x04\x00\xf0\x1e(\x11\x00\xc0{\\W\"\x1b7\xea\x81`m\xa0\xfeԥh\xb9\x00\x00\xd3\x1a\xb7\x95\xc8ƍ\xfalU}g\xf7\xb1\xaazH\x11\x003\x16\x97\x95\xc8\u038d\xba\xb9\x96\x1a\x99\xf5\a\x8eE\xcb\b\x00\x98θ\xabD\xb6n\xd4u\xb5꾆\b\x99\x00\x00\xd3\x1ew\x95\xc8֍\xba\xb7G\xd9\xd2\xf2T\xe4|\x00\x80鍻J$Fr\xa3\x16\xc5\xcb5A\xfb\f\x00\x80\xe9\x8fWJdq\xa3\x96\xbbDU\xfd\x91\xb2\x00\x00\xa6;^)\x91ōZl\xad\x84\xd74\x003\x17\xaf\x94\x88w\xa3\xbe\xd4\x1c\bE\xca\x00\x00\x98\xfex\xacD\xaa\x1b\xf5@C5\xec\xcc\x00\x98\xc9x\xa5D\xac\x1bu\xff\xfe:\xea\xbah\xce^\x03\x00f\x18\xee*\x91\xad\x1b\xf5\xe9\xc0\xfe\xee\xde\xdeޖZ\xa7\xdc\x00\x80銻Jd\xebF}\xb0R\x05O6\x020cqW\x89\x00\x00\xc0\x0e(\x11\x00\xc0{\xa0D\x00\x00\xef\x81\x12\x01\x00\xbc\aJ\x04\x00\xf0\x1e(\x11\x00\xc0{\xa0D\x00\x00\xef\x81\x12\x01\x00\xbc\aJ\x04\x00\xf0\x1e(\x11\x00\xc0{\xfe\xe2+\x00\x00\xe05\xb7\xd3'\x02\x00\x80\xf1\x01J\x04\x00\xf0\x1e(\x11\x00\xc0{\xa0D\x00\x00\xef\x81\x12\x01\x00\xbc\aJ\x04\x00\xf0\x1e(\x11\x00\xc0{\xa0D\x00\x00\xef\x81\x12\x01\x00\xbc\aJ\x04\x00\xf0\x1e(\x11\x00\xc0{\xa0D\x00\x00\xef\x81\x12\x01\x00\xbc\aJ\x04\x00\xf0\x1e(\x11\x00\xc0{\xa0D\x00\x00\xef\x81\x12\x01\x00\xbc\aJ\x04\x00\xf0\x1e(\x11\x00\xc0{\xa0D\x00\x00\xef\x81\x12\x01\x00\xbc\aJ\x04\x00\xf0\x1e(\x11\x00\xc0{\xa0D\x00\x00\xef\x81\x12\x01\x00\xbc\aJ\x04\x00\xf0\x1e(\x11\x00\xc0{\xa0D\x00\x00\xef\x81\x12\x01\x00\xbc\aJ\x04\x00\xf0\x1e(\x11\x00\xc0{\xa0D\x00\x00\xef\x81\x12\x01\x00\xbcg\x14J$\xee\xc8IIH\xbd\xe7\xa9\x11\xa7\xc0\b\fҌ\xb5d\xb9S\\\xec(%א\x95\xe6\x96\xd1\x1c\x86\xcb0\x16\xf6\x90\"\xa7\x10\x00@L8+QU\"QI\xefq\n\xb5eO\xe2\x904:\x89\x88\x15\xb5d(\x11\x00S\x1fG%\xdaNHn\xcbՑ\xb3Us\x89\xaf\xcd)؆\x11B\xa8^\xf4\xee\t:EƊV2',\xa39\f\x94\b\x80I\x87\x93\x12\x05\t٣\xa6\x86rI\xf2\x9f\xa2\aۡ\xe9\xc5\x04`\xa7D\xa3!\xe6\fV\xa0D\x00\x8c7NJ\x94A6\xe9ɡTR\x12-\xd4\x1e(\x11\x00\xc0\x11\a%:F\xe2.\x19\x1f\xaaɜ\x11z!\u007f\xb3\u007ferR\xceAu\xe3\xe0\x96t_\xf2\xbd\xed4YE\x02\xed\x19\x89\xd9\x03\x92Ժ:\xcd\xe7\xcf*\x13%i\xab2\xc5ԫO\xe0\xf4\x15\xcfMH\xbeW\x19\xe5Ր\x8a?m\x99\xebK/\xbbJ?\x9d\xfdRzB\xd2\xc2*nV<b\xb0\x82^\xb2,,\xe2\x964_\xc6\x03Ò>OdW\xd8٭\x19\xbe\xe4\xe5!\xa5,&\x03[W\xfe(\x96C2\xe7\xa9*\xd1<\xb2U\x02\x00\x8c\x0f\x0eJ\xb4\x9d,0?\x88\x84\xb4)\x17\xf2\x1c\xdf\xe2\xdc8RL\xb7\xb5\xfb\x89o~\x06!\xe5\x12U\xa2-\xb3\t\xf1\x8fH%\x84\xa4\xcdO\x95_\xaeJ\xf5\xab\tY\xb9zP\x93\x88\x86\x042g\x81\xbc\x83^\xc35dS\x1aIJ&$KV\x8c\xbe$\x92\x9c\x9dI\xc8]̱#\x06\xab\xe8%אy\xa9$U\xde5oDS\"\xbb\xc2Z\x12ɜl\xb9\xb0\xa0\xc4g`\xeb\xca\x1f\x85?${\x9eP\"\x00\xc6\x1b\a%\xba\x87\x1b\x90\xcd%U\xf4\n%\x99\x03\x92ԝL\xea\xe5\x9eB\x12\xd9zM\x92:\x93I\x13U\xa2\xb8\xcc涧\xa46\x92xR\x8e\xee\x9cC\xbee\x8c\xa1\x14\x898\x1dG\xca\xe5˺\xd1G\xaa\xd5r\xe4.J\xd0G\xea$i9)\xbb!\xefO\"-\xc6\xc1\"\ak\x18\xa33\x92\xd1%wm\x12h}\x94\xc3\xd8\x14vi\x0e)\x1b\x91n~\x93̾\xcag\xe0\xea\xca\x1d\x85\xfb\xc0\x9d\xa7\xaaD\r\x81N\t\x000>8(Q6\xd9n\xfd$_\xa1}\xf4\xc3A\x92A\x87HK%\xf5C&U\"u\xcf\xfdZ\xa6\xfb\xa9\x8c\xb1J\xb4R\x9b`\xa9%)#\xb4\x9c~\xfa\xa1\x98v\xae\xd2\xe5a\x96L\xa0\xb0\xd58X\xe4`\rS\x89\xb4]%\xdaal\n\xdbN\xeeQ\xde\x17\x92Z>\x03WW\xee(\xdc\a\xee<1O\x04\xc0x\xe3\xa0D\xf3\xc9\x0e\xe6S\x0e)\xa3W\xe8B\xe5ÈO\xbeR\xe7\x92f\xf5C\x1c\x19\x90\x95(C\x8d\x1bQ\x87P;\xe8\x15\xcb(\xd1H\"\xe9R\xf7\xcf!!\xb9\x9c,\xe5C\x80N /&9\xa1\x1b\x12K\x94`=BW\xa2y\xe6.E\x89\xc2\v\x93\xb2\xb4z\x0e^\xb2d\xe0\xea\xca\x1d\x85\xfb\xc0\x9d'\x94\b\x80\xf1\xc6A\x89\x96s\x93!\x19\xa4\x82^\xa1_Q?\xcd#\xadÄ\xcc\xcbQH m\xb2\x12ݣ\x05\x8e\x84\xea\xcaW\xa7\x13\xb2\x8eS\xa2\x01B\xb4Y\x9e\x85\xf2\xc0\xa8F\xebf(\xe2\x11\xf2\x11\x92\xb4\xbaޜ\x8f\x8e\x16\xac\x1fDW\"uW=}\x8fP\x98\xe4S\xfb7\n\\\x06\xae\xae\xdcQ\xd8\x0f\xfcyB\x89\x00\x18o\x1c\x94\xa8\x8c\xe4\x98\x1f\x86\b\x9dy\xa9ѻI9\xe4\xa0HL\x9ad%Z\xad\xee\t\xa4\xd2\r\xf3\x17Z\x94\xa8\x8f\xc4k%-%U\x92~3]\x15\x97\xbeu~9K|\xc95\xfd`тU,w\xf1M%\n/\xec\x1a!\x83F>.\x03WW\xee(\xec\a\xfe<\xa1D\x00\x8c7\x0eJ\xd4E\xe2\xccK\xb8\x9e$\f\xd1+\xb4L\xfd\x98E\x8e\xc9\xdat\xc6\f֕蛄|\xa9\xa1{X\xaa\x88\xd8'\xcaQ\xba9\xbc\xb8\x8ct\x96\xcf#\xe65\x1e=X\xc9\x10Q\x89\xc2\n\x93\b\xd7'b2pu\x8d\xa8D\xfcyB\x89\x00\x18o\x9c\x9el\xcc4\xaf\xba\xe1\f%]\xa3\x8d\xc1\xae%\xc8\xfd\x8c\x14z/\x89\xd29pCW\xa2\x1bsH\xad\xb2m\x8bE\x89n\xcc\xe6\xa7~\x98\xcb~ \xa4\xa4\xabI\xbc>\xc1\x13%X#\xa2\x12\x85\x17&\x9f\x86\xfa+\x90\xe6\xc5\x01.\x03_\u05c8Jğ'\x94\b\x80\xf1\xc6I\x89:\t\x9d\x1b\xa2\\[J\x12\xcfK\xf4\nMP\xbaI\xfb\xe9\xa3F\xc5$\xfb&\xfd\xd0J|Wu%\x12\xb5[h\xc3i\xf4\xb3ݽ\xb3:\x924b\x1d\xfd\xd0'\v\xa5~\x12g</\x141X'\x92\x12\xd9\x15\xb6U˷\x94|\x93\xcb\xc0\xd75\xb2\x12q\xe7\t%\x02`\xbcqR\"y\xd8B\xeej\x1b\x92\xc4\xfa\f\x12\xa7\xdc?\xaa!d\x81,E\xad\x89\xf41\xc7~\x1f)\x19\x96\aq\xc9d\x8b1:\xbb\x91\xa4Ls_^L\x94\x89\x98\x04\xd2t\xed\x86z=wǓ\x1d\xb284'\x92\x80\xe5J\xbf\x8b,\x96\xd5cx\xb51\xe7\x1d-XG-9\xbcOdS\xd8@\"\xd9qC\xbaYA\xfc\"\xdf'\xe2\xea\x1aY\x89\xb8\xf3\xc4\xf3D\x00\x8c7\x8eJ$5諂\xa4)?u\x90\xafЌ\xd9\xf1\v2\xb4\xbeR\xb3\x8f\xccΖ?䎘\xf3D\x01Bҗf\xc7%oWn\x97g\xcbY\xdb5\ti\x88'I\xd9i\x84^\xce\xfc\x95~>\x99\xf8\xb2\xe6'\x92\xd4\x01\xe6\xc0\x91\x82uԒÕȮ\xb0\xa0\x8f$g'\x93\x84\xa0\xa5\x13\xc5\xd55\xb2\x12q\xe7\x89g\xac\x01\x18o\x9c\x95H\x12+r\x92\xe2R\xee\xa9\xd5\xeeD\xc9Wh\xef\xd29\xc9KO\xa9\x1f\xcfnJ\xf7%f\a\xe88ȸw֖\x9b\xe2\xcb\xda\xfe\xa7a\x1f\xbdc՟;;\xe9\xa0.!}Ei\xbe\xb4\x95\xedZ9J\xb0\xbagpK\xa6ov\xd6v\xf6\xce{\xe4`\r\xb5d\x9b\x19k\xbb\xc2\xfa\x8b\xd3\xe2S\n{%\x8b\x12qu\x8d\xa2D\xecyB\x89\x00\x18oF\xa1D\x16\xf4+\x14\x00\x00\xc6\v(\x11\x00\xc0{\xa0D\x00\x00\xef\x81\x12\x01\x00\xbc\aJ\x04\x00\xf0\x9eؕ\b\x00\x00\xc6\x1b(\x11\x00\xc0{\xa0D\x00\x00\xef\x81\x12\x01\x00\xbc\aJ\x04\x00\xf0\x9e\xf1R\xa2\xe7\x84o\xdb\xef\xc0\xad6\x00\x80#P\"\x00\x80\xf7@\x89\x00\x00\xde\x03%\x02\x00x\xcf$Q\xa2\x96\\n\t\x8f\x98\x18\xcamq\n\x01\x00Ln\x1c\x94\xe8E\xe1\xb9?\u007f{M\xfe\xc6W\xa4[/n\\R\xf0\xddO\x95\xad?ߵ6/\u007fÓ\xff\xa6|x\xe7\xa1U\xcb\x1e\xfc\xad\xa6D\x1f\u007fw}ު\x87\xdedJ\x90\x95h\xa00ٟ\xd3 ѕ\xa5U\xa71\xa9\x82\xb3\x96\xa5\xeb\x95UHc'\x10\xf7\xad\xa8\xfbK\b!\xfe\x81\xa8!:\x9d\x84\xe4JR\xb3\x9c\xe1T\xe4\xa0\xf6TC\xfa\x86\xb6\xa4\xf9\x97ߌ\x1c\n\x00\x18\x15\x8eJ\xf4\xedU\u009a%\x82\xf0\xca\xe3B\xfe\x1aA(\xa5\x1b\xbf-\b\x05\x1b\v\x04a-ե\x17臼\xbc\xaf*J\xf4\xe62!\u007f\xe3zA\xf8\xbeYB\r\x99\x97L\xe6e\x12R(IW\x13\xd4U\xa3\xa5L\x12b\x8f\xb2?\xaeA\xba\x1dZ\xe3k\xa2\xed\xbe\x1c\n\xd5j\xcb\xf3;1r\x92\xf8C\xd2p399\"q\x9c\xea1ӭs\x9a\xf5\xe4Ҵ\xa7J\x12\x87$\x00\xc0\xed\xe1\xa8D\u0086\x0f\xa5뻄\xfc\xfc\x1fߒ^\x11\x84\u007f\x95\xe5Fȧ\x9d\x9ew\x96\t/H\xd2o\x85\xbb_\xbc%}\xf2\xa0@\x95\xe8\xe3e¾\xeb\xf2\x9eU\xc2+F\tԅ\xbe_\xeeG\xf8\xa9\x89\xc6JRN\xb7\x9d&\xe9\xecA\xce\xfb\xca\xf5\xe4\xd5\xc5c\x1a\xa5\xed\xf0]\x8e\x1e\xd0=J%\x92\x86I\xb1\xdc]\x1b$Ö\xed\vm\x17\xd1\x1f\"\xb2\x04ZC\x01\x001\xe3\xacD\x1f\xcao\x1f\n\xc2s\xf4c\xa9\xf0\xa2$\xed\xbb\xfbIe\xdf>\xe1qI\xda%\xec\xa3\xe9O\xd7P%\xda'<\xa4\xec\xf9\x89\xb0\xc1(\xa1Fs\xcf\xd8O\xad\xaa\x83\xaa\x04\x95\x11Cz(%s\x19\xbf\xc5>i\f\\\x9bˏ\xf6\u0088A\x89N%\x8d\xd8(Q\xce:\xbb\xe8\x01\x82)*\x00\xc6\x03G%ZO߮\v\xc2\xff\xa2\xef\xbbh7H\xba~]\xd9\xf7\x03\xe1\x1f\xa5[+h/I\xa2\"$+\xd1Z\xad/$\x87\u007f\xa4\x97PC\x16)\xef\xc3\xd4Q~$\x99*\xc2\xcdT\xd6\xc7P\xba\x91\xb4]\v\xcdj=Cζf)\x0ed\x03\x85\xa9\ti\xcb\x15\xbb\xa0\xda\x1c\u007f6ݶ\x95$ԕe\xf9\x97^\xe6\x92\n;\x12-\xa3)\xbe\x04F\x89\xf4\xc2$)\xb44=!uy\x86\x92>\x98;'\xeb\x01\xaa\x87\xc3d0\xa7YW\"=\xb6E\xf3\x14\xa0~\xb8C\x89\x84\xc45ҽ7Rԭe\xd4|\x88\xc8\xe2Z\xa18\xc4\x02\x00b\xc7Q\x89\x1e\xa4o\xff.\b\x9f\xd0\xf7݊\x12I\xd7\xdfy\xf1\xfb\xbb\xd6\v\xc2n\xe9\x13APe\xe9Dz\x12}*\b\x1b\xefS\xc8\x13\x8cIk\xc326\x83\xba\x12m!\xf7\xcb#5\x92\xcd\x1e\xa3\x87hv=b1\x99/\xff\xb7\x8e\x8aGgRN\xa0\xbd\x82T\xcb\xc9\x12ߎ\xd6\x1d\xbebI\xeao\x8c'\xa9\x15UI\x85\\R!\x14\xde\xe7aJ`\x94\xc8(L\xde\xf4\xa5\xe6\xf6\xbaTB\xdd\x197\xc5\xdd\xdfZ\x93\x9asSQ\xa2\x9a\xe5\x9a\x12\x19\xb1\xd7B\xa1\xac\xbbB\xa1\xd0YZ\xc2\xe9Pȧί\xf7\x86\x1aIE($Ҁ\xf4-\u007f\x92\xaeV$\x870T\x03`,8*\xd1\xc3\xf4MV\"\xe5F\x99\xa2D\xb7^X#\b\xc2\xdd\x1bKe%\xfaH\x10\xd4\xc0\xd7e%\xfa\xb3`bL\x14Ր\x1djb>i\xa6\xee֩7\xa5\"M\x1e4Z\xe5ΒƱ\x04\x92\xd0F\x13#\xe9\xf7ʝ\x9c\x1bMC\xf26B\xdd=ک\x8eI\xbed\xb9\x13T\x9c*\xf1I\x99\xcbĘD\xd6`J\x90L%b\n\xabM\xa5\x1aT\x9b,\xd1\x1a4(1\x8d\x8a\x12]\x9d}UQ\"\xf6\xc0\xfc\xe8̯\xdf\xe93Gg\x15\xb4\xbf\xf4%\x871\"\x00 \x02cP\xa2焻\x1f\xff\xf1o?\x95\xdfw\xd3n\x90zc\xff'j\x9f\xc8\x18\x94\x19Ԑ\a\xd4D\x069)ѻf\xa7F\xfc\xf1ܴt\x90\f\xaa\x89\xa12_:\x99\xeb\xdb.\x8bG\x1b\xe9\xd5wo\x9a\xaf\xbcͧW\xb9\x8f\xbeT\xf8$>)Q%\xb2\x0e\x8b\x98\x12$S\x89\x98\xc2Ĺ\x99[\xeb{%*GE\x997(\xe9%\x8a\x12I˫\x15%b\x0f\xec\xa8D\x97I\xbf4\x92tR\x02\x00\x8c\x85ؕ\xe8\xfa2:m-\xf3]Y\x89n\xad\x12\xdeQ>|\x9f\xce\x13\xadѻB\xef\xfc\xf1\xdf\xf5\x12j4\x87\xb2!\xd5#\xba\x82lmc=\xcb$\xdaO\xd2FN\x81Ժ~ҿ?u\x0f}\xf2Ș\xf7Y\xa4>\x19\xb9r\xa1\xfc\xa2\f\x8b4%2\x93\x12U\x1a\xee\xb1\x00\x89+A2\x95\x88-l\xa8n\xdd<\x92\x16\x90T\vG\xcajU\x89\x9a\xb3\x15%bc\x1d\x95HZ\xfe\x80t,\xf9\x86\x04\x00\x18\v\xb1+ѿ\xa9\xb7ӤO\xd7\n\xbb$\xe9q\xe1\x1f\xe9\x87\xeb\xeb\xa9\x12}[\xb8\xef\x16\xfd\xf4s!\xff\x13\xbd\x84\x1a2[\x994\xdeC\x94.\xc6 I\xdfj\x19I]\xf3\xe9\x17\xf6\r\xe5\xde\x19\xbd\x9cO\x12\xe3\xf9\x9d\x92L\xe5-S\xe9\x13ER\xa2\n\x9fu\x82\x86)A2\x95\x88)\xec4\xbd\u007f7\xdc试\ay\x99=\nWU%\xba6\xa7\x9d*\x11{`U\x89\x1a.\xa9\xa5\xd9)QKꍒM\x12\x00`LĮD\xff\xbeB\xd8'\xeb\xcd\x1f\x1f\x14\xe8=\xfb\x8f\x96\b\xcfݒ>ݥ<O\xf4a\xbe\xf0\xb8<X\xfb\xed*\xe1\xbbF\t5\x84d_\x96\xa4&\x9fv\xd1\xe6\x12\u007f\x92\xe5>\u05faL\xe3)e1Y\xbd\xd75\x9c\xb6\x98\n\xd2W\x94\xfbR\xf4NU#i\x95\"+\xd1\xcdy\xc6OJ\x06\xbfu\xdeZ\x82d*\x11SX\x059F\xb7,\xdeB炔\xb1ݎ=\xaa\x12I%ET\x89\xd8\x03K\x8b\x17Kҟ\xf4!\xa0\x9d\x12\xddHmI\x89\xf2\\6\x00 \x1a\xb1+\x91\xf4#AX\xff\xe0?\b+\x9e\x146ʛ^\xc9\x13\xd6\xfcC\xbe\xf0\xb0\xf2\x8c\xf5\xebK\x84\xfc\xfb\xd6\v\xc2\u05ee\x1b%Ԑ\xa5\x89\t\v҉>q]O,\xbf\xf4\x90\xa4\xb3qU\x92\x95S\xb3\xe7?\xd5v?\xa9\x97\x93\xc5q\xe5\xad\xe5qŲL\x85\x12J\xba\xa4\x9e\x92\x84\x90\xc8$it\xb5\xd9\x01Z\xad\x8f\xfd\xcc\x12D\xfa\x8cuu(t\x89-LV\xa2\xa4\x8a\xd6`\x89r㮜\x145\xb7\x94\x90\x83\xf4\x19\xeb\xe6a\xa93Q\xb9wf\xc6Rͫ\n.\x9d#\x1f\xecFW(\xe4+\tћd\xea\xbd3\xfd\xa6]y&\x06g\x00\x8c\x951(\x91\xf4\xe6\xd7\xd6\xe4ox\xf2\x93O\xf3\xee\xfeX\xfe\xf4\xaf\xbb\xd6\xe4\xdf\xf7\xe6+\xea\xef\xce>z|}^\xfe}/\x98B$+Qy\xdf\xd29\xfeEm\xda\xe7a_ؔ\x8e\xb4cv\xd8&i`]z\xd2\u00a0\x92ܟ\xad?ODHB\xff\x1c\xf9u+\x93\x94w\x84\xfcۍ|\r\xa9u\xd6\x12J\xb4i\xa0\"\xb60\xe9\xe0\xe2\x8a\xf4\x84\xb4\xc5\xea\x13\x04\xed\xf7\xa4$\xd3*v*\x8f\x04\xdd\xccM\xbb\xc9\xc5J\xd2\xc8\xfd)\xfe\xbb\xba\xe5Dw\x9cZX\x1d}8\x8a\x12\u007fV;\x1c\xc1\xe0\f\x80\xb1\xe2\xa0D\xe3\xcfy\xfe\x97\x1e*e\xbe\xdby\"\xb0\xc9W2\tz#þN\xa7\x10\x00@\x04\\W\xa2\x1d\xe4\x9b6[\xab\xd3\xc7\xf4{3\x85\xa1\xb9\xd1\u007f\x8a\xef\x12M)\x93@\x0e\x01\x98\xa2\xb8\xabD\xfd\x83M\xb3}\xa2S\xd4\x14\xa4\xa2SZZ!\x01\x00ƈ\xbbJTH\xc8m\xadD4Y\x19!9[Ӱ8\b\x00c\xc6]%\n$\xa6NG!\x92\xfbDI\xf7\x9cu\x8a\x01\x00D\xc4]%\x02\x00\x00;\xa0D\x00\x00\xef\x81\x12\x01\x00\xbc\aJ\x04\x00\xf0\x1e(\x11\x00\xc0{\xc6I\x89>\xe6~\xdf1\x1a\x873\x00\x000\x18\x17%\xba\xf5B\xfe\xa7\xe6'(\x11\x00 F\xc6E\x89\xae\xeb+7*@\x89\x00\x001\x02%\x02\x00x\x8fgJԒ;\xb6\u07fcnqg퍡\\8\x99\x01\xe0\x1eNJ\xf4\xd1\xe3k\xf3V\x94\xfeH\x9d\x90f\\\xef_\x14\x9e\xfb\xe4\xbbk\xf3\xd6?\xf9\t\xf5:\xa3|\xa8g\x91\x95h\xa00ٟC\xfd2\xaa\xc9<uc\x85e}\xb4\xc0\x18\u007f\u007fv\x86\x94K[I\xdc\xed,\"2:\x02q\xb7\xfd\v\xff\xbe\xa5sҊ:\xd3\xfe\xa4,\x90\xe4\x1f\xd07\xb7\xa7\x8eZ\xe4Z\xe6\xcd^М\xd3\xea\x14\x06\xc0\x94\xc7A\x89>\\&\xac\xbao\x83 |\x8d\xaeOͺ\u07bf(|\xb7@X\xb6J\x106\\\x97~\xbcK\x10\x1e\xde\xf5\xb1\x9e\xa7\x86\xccK&\xf32\t)\x94\xa4\xab\t\x9a\xa9k&\xbf>\xda\xfe\xb8\x06it\xb0\x86\xf42ų\xffD\xd7ndd\x8c\t\xb0\xc4\xde\x1e\xad\xf15N!\x06\xb6\an\x9f\xb3\xb0\xbe1\x9b\x903\xd2e\xbah\xa4\xbe\xb6\xa3\xd4:\xc7\xea\x88\xc4c\x16\xb6\x9f\x14\xb7l'd\xf4\xf5\x00`\xaa\xe2\xa0D\x0f\vO\xcaݡ߮\x10^\xb7\xb8\u07bf(k\xd0;\x92\xf4z\x1e5\xfa\xb0\x8e\xceHF\xbf|!\xfaI\xad$\xadT\x8d\xa7O\xf3룝\xf7\x19v\xd4W\x17G\x1f\xa5\xf1\x86\xf4\x03\xaa\x8f\xa3\x8fQ\"&\xc0\u07bc~\xac\xec\xf0]\x96F\x89݁\x87\x92V\x8fHҵL\xd5\xefv\xd4v\xd8La\x03ʊ\xbbeP\"0\x03pP\xa2\xf5\xea\xa0\xebG\xbb~nq\xbd\u007fQ\x1b\x8e}\x9b\xae\x1a\x1b\xa6DJ?h?ɠff\x8a\x04\x95\x11Cz(%s\xaf\xe9\xc9>\xad\xd3\x14\tސ\xbeD]݈U\"&\xc0\u07bc~\xac\\\x9bk]p;\"v\a.OT$\xb6\x8a(?ҏA\x89\x8c\u008aS\xa9\xf5\xc0\x19R\x1b-\x1a\x80i\x81\x83\x12}M(}G\xb7.\xe3\\\xef_\xa4r$\xf3\x02]\xe8ڪD\x8b\x94\xf7\xe182@\x17{\x96/\xc1\x9b\xa9j\xcf@\xe3F\x92\xb6\xeetMV\xeb\x19r\xb65\xab\xd6bt\xaf\xdbԳ\x86\xf4\x94\xc1\xf8\xaf(\xef\xbe\xedZ,\x13\xc0$\xb7\x92\xf8\x9aM\xe9)+\a$\v\x03\x85\xa9\ti\xcb\x151\xd3=\xef\x99\x03\xf3u\x90;E\x89\x16\x13\x12>@/\x81\xaf\xa4^u)S\x9dZ\xbfZ\xa5\x14\xa2+\xd1P\"!q\x8dZyz,S.[X\x8a\xdaJ\xfb/\xb1G\xb3o(\x00\xa68\x0eJ\xf4N\x9e \xac\xd8\xf5c\xaa3\xbc\xeb\xfd\x8bZ\a\xe9E;%R\x9d}\xa4\fj伅\xdcOm|\xb2\xd9R{\x88\xb6\xe4\xb3XL\xe6\xcb\xff\xad\x13y\xa3{æ\x9e3\xa4\xa7;\xb4\x01\x93\x8f\xccklI+\xe4\x1c\xeb\x99$-,cOE\x86\xdf\xd2\xdd\xeaL\xca\t\xb4W(^؆\xe7=s`\xae\x0e2!k?\x86\v0J\xe0*iT}$\x8e\xb3\xdc6\xfaD\xa7C!\xbdGg\xc42\xe52\x85\r\x11f.ͮ\xbeL\t\x00Lq\x9c\xee\x9d}\xb8+_\x10\x84\xbco_\xb7\xb8\xdek\xa6\x1f\xaa\"Y\x95H3\x14\x9aO-\x16\xbbH\xeaM\xa9\x88p\x97e\xab\xdcY\xd28\x96@\x12T\xdb\x0f\xd3螱\xa9\xe7\a>\x97\x12\xb6\xaa\t\x1f] qS\xaad\t0\x93\xbe\x8ca\xf9RNϕXF\xd2\xef\x95\xfb'7\x9a\x86x\xcf{\xf3\xc0lR\xa2\x0e\xd3aS\xcbf\x00[\x82y`\xb3ꃄ\xbbCƎ\xce4\xbb4\xf64\xd9\x03\xeb\x85\xf5+G\x90FFF\"\u0557k(\x00\xa62NJ$\xcb\xcc;\xdf\xdf(\b\xffhq\xbd\x8f\xaaD\x0f\xa8\x89\fB}\xe23ɩ\x11\u007f<7-\x1d\xa4\xf6\x86\x94\xa12_:\x99\xeb\xdbN\x17^5\x8d\xee\x19\x9bz^\x89\xb6&h\xf9|\x9b$\xc3v\xd1^\x89\x94i\xa9Z\u00ad\xe8\xdaFz\xf5$\xebyo\x1e\x98MJT\x89\xc2\x1e\x160\x03\xd8\x12\xcc\x03\x9bU\xbf\x11o\xdf'\x92\f%bO\x93=\xb0^ذ\xa23E\xf2P\xedd\x84\xfar\r\x05\xc0T&\xba\x12\xdd\xfa\xa3\xeaz\xff#!\xef\xdfy\xd7\xfb\xa8J\xa4z\x1f\x0e\x11Bgd*\xc8\xd66\xdd\rQ\xa3K\xbf,\x03\xa9u\xfd\xa4\u007f\u007f\xea\x1e\x895uel\xea9\xa1\x11}\xfaS\x8d\xac\x01\xac\xbd\x12)\x17{'\xe7H-U\x13cއ\xf5\xbc\x8fhq\xdd\x1d\xee\xccf\x06\xb0%\x98\af\xaa\xae\xcd\x13\xddh\xd7\xca\nS\"\xf64mOH\x99'\x12\x9bI\xf9H\x84\xfar\r\x05\xc0T&\xba\x12}\"ܭ8.~(\b\xd7y\xd7\xfb\xa8J4[\x99\x13\xdeC\x94?\xe4\x83$}\xabe\x98s\u0378\xf7uC\xb9w\xa6\xd8\xf3\x98\x17\x18cS\xcf\x19җŝײ\x85]\xb8j\x80\x99\xf4)SUu\x8a\x95\xab\xc1IS\x98X\xcf\xfb\x88JT\xe1\xe3\xb2\xf3\x01l\t恙\xaa\x97\xfb\x95\xfa7\x11\xe5\xcdF\x89\xd8Ӵ=\xa1\xe24\xaa\x9cAz\x17\u07fe\xbe\\C\x010\x95q\xbcw\xf65Y\x8a>\xdd%<hq\xbd\xe7\x94H\xca\x13^\xb9\xae\xdfb\xa3w\xf1\xb3/S?Dm\xa6$\x97\xf8\x93,7\xa1\xd6e\x1a\x93\xacb\xb2\xe6:d^`\x8cM=kH/\xfa\x8cQ\b{\xe12\x8e\xf5fҗ6L\x9f\xe5Y\xacD\f~KU\xb0\xe1\xb4\xc5T\xf3\xbeR\xc6{\xdeGR\xa2\x9b\xf3\x8c_\xad\xe8%0\x01l\t恙\xaa\x0f%\x15\xcaG\xbb\xb9X\xd5\x10\x1b%bO\xd3\xf6\x84\x06\x94\xe7\xd0\xef\xa1Jd__\xae\xa1\x00\x98\xca8(\xd1ǫ\x84\xbc\r\x1b\xf3\x855t\x8a\x88u\xbd\xe7\x95\xe8>A\x10\xde\xd4\xf3Ԑ\xa5\x89\t\v҉>q]O,\xbf\xf4\x90\xa4\xb3qU\x96-\x9cѽaS/I\xa6!\xbd\xf4\x80>\xcf\xcd\xc52\x01L\xd2Gr\x9a곒\xd5\f\xab\xf5\xc1\xe1\xa9\xd9\xf3\x9fj\xbb\x9f\xd4K\x8c\xe7=S\x18_\xae<\x983\xbaPZ\t\\\x80Q\x02w`\xa6\xea\xc7\xfc\xb9\r-K\xe3C4_\xa8\x96T\x87Br?\xe7FW(\xe4+\t\x85\x86\xd9\xd8H'TM6\xb5\x96\xa8\xcfX\xdb\u0557o(\x00\xa62N3\xd6\xf4\xa7f\xf9\x1b\x9eT\a_\x8c\xeb=\xafD\x1f\x96\xe6\xaf\xf8\x89\x9e\xa5\x86\x94\xf7-\x9d\xe3_Ԧ}\x1e\xf6\x85Ϸ\xec\x98m\xd9\xc4\x1b\xdd\xeb6\xf5\x12cH\u007f5\xb1\xd86\xd6\b`\x93\xbe\aJ\x92\xe7\x16k\xbd\xad\x86\xd4:-\xe7\xc0\xba\xf4\xa4\x85A%\xa9{\xde3\x85\xf1\xe5\x86\xfc\xdaCOf\t|\x80^\x02w`\xb6\xea}K\xfdi\xab\xfb\xe5D\x896\x9fS$\xf7\x8d\xe2\xd4d\x1d\x1b\x1b\xf1\x84\x82\xf3\x12s\xdb\xd2\xdb\"ԗ?\x1a\x00S\x19'%\x1a\a\xce\xf3\xbf\xf4P)\xf3\xc5\xfa#\xd6r\xee\xe1H\a؇\xb0\xc7F\x93\xaf\x04\xee\xd2\x00\xb8\x85\vJ\xb4\x83|\xd3fkuz\x8c\xf3\xac\x9bbY\x0e䶕hh\xeem\xff\x14\x1f\x000j&Z\x89\xfa\a\x9bf\xfbD\xa7\xa8q綕\b\x00\xe0&\x13\xadD\x85\x84\x8cq%\xa2\xdb@\x9d\xd5\x05\x00L\x19&Z\x89\x02\x89\xa9\xae\v\x91:\xab;\xe8\x14\x05\x00\x984L\xb4\x12\x01\x00\x803P\"\x00\x80\xf7@\x89\x00\x00\xde\x03%\x02\x00x\x0f\x94\b\x00\xe0=\xe3\xaaD\xfaB\x8e\xd1y\x8e.}\xad1:o4\x00\xc04\aJ\x04\x00\xf0\x9eqU\xa2\x0f\x9f{\xdd)D\x82\x12\x01\x00\xc2\x18W%\x1a\x1dP\"\x00\x80\x85i\xa7D-\xb91\xfe\xb26*[b\xf9\xd9-\x88\xc2diɡ\xdcQ{\x81\x8f\x85\xc9r\x9aS\x0f\a%\xfa\x91\xf0\u009b\xeb\xf3\xff\xe1#u\xa1\xa2U\x0fiˡ}\xb4o\xfd\x92U\x0f\xabk\\3;\xe8<\xd1\x0f\xb4\x85\x8b\xa4Dž'%K\xb6w\x1eZ\xb5\xec\xc1\xdfZ\x94h\xa00ٟ\xd3 \xd1u\xc1\xe6\xa9\x1b+\xb8\x95Ն\xb6\xa4\xf9\x97\x8f\xdaG'0\xae\xbfr;Cʥ\xad$.\xd6\x05L(\rt\x15\xa2\xd4{{\xa4qf\x13!t\x95\xb9*B\xac\xdf\xf9\xf6\xd4\t\xbd\xc6n\x8f\xc9Ӓ\x818\xfbU\x16ƥ\xf9n\xe34\xc7H0^[\xfc*>\xbaǹF\xdf\xd29iE\x9di\u007fR\xd6\xcc\xf2\x0f8\x85+t\x12\x92+I\xcdr\x86S\x91\x83\x98\xe6c\xae\xd8\x18\x1a\xd5Q\x89\xbe\x9b/\bˮKo.\x13\xf27\xae\x17\x84\xefӭ\xaf\xe7\v\xcb\xee[#P\x8bjn\aU\xa2?\nyʲjחQ\x93X.\xdb\v\x82P\xb01/\ufadc\x12\xcdK&\xf32\t)\x94\xa4\xab\t\x9a\x1dl&\xb7\xb2\xdaҴ\xa7J\x129\x8f\x8e(\xec\x8fkp\n\x89\x8a\xc5\xe0\xbex\xf6\x9f\xe8\xcfi\x19qc\x02NE\xbd6\x86\x1bȷ:\x1brug\xb7qCL\n\xd0\xc6\x18\n$YW8h\x9d\xa3\u007f\x17\xa3\xd7\xcc\x1d&YK2\x87h\x8d\xb7\xb5\xf76\x9b/\x16\xc6\xef4\xc7\x18\x10 ڂ\xa0$`\x93A\xc5\xcc\xd6>ga}c6!g\xa4\xcb4\xdb\xe8~&>r\x92\xf8C\xd2p39iY\x04\x9a\xad\x0e\xd3|\xcc\x15\x1bC\xa3:*\x91\xb0\xfe\xf57_\x94>^&\xec\xbb.wjVQ\u007f\x8f?/\x13\x9e\xbc.\xddz\x8e\xae\xac\xcf\xedP\ue755\n?\xa69_\x176J\xfc\xde\xdf\nw\xbfxK\xfa\xe4A\x81S\"\x92\xd1/7\x90\x9fZ.\xafT-\xabOs+\xab\r\xd1\xc5S\xc3V\xb6\x8f\xc0y\x1fgz\x1d;\xbc\xc1\xfd\x80\xea!\xc9.1\xc2\x04\xf0\xb1a\xf4)\x16e\x8b\xb2\xa2\x06\x8d\x81lUk\xeb9/K\x1e\x87\x9a\x8d\vW\x17G\x1f\x05O\xb2\x96d\x0f\xb1\xc3wY\x1a/\xc6\xf14\xc7\x16P\xed\xd3\x16IO\xe4\\\xad8\x8clCI\xabG\xe8\xfa\xeeꢃ\xa3vH\x1f&\xc5%\xd4\x1a\xc3z\x19\xda\xd77\xa6+\xd6\xc4Y\x89>\xa4\xef\xfb\xb4\xfb\xf3?\xa1&\xd4O\xd2\xf5\xf5%\xaa9/\xf2;\x14%zQݻKx\xc1\x92m\x97\xb0\x8f\xa6?]\xc3+\x91\xd2\x0f\xdaO2\xa8\x8b\x85\"Ae\x84\x95\x93\x012\xea\xfe\x9d$\x95̽\xe6\x14\x12\x1d\xde\xe0\xbeD]Y\x89\xfdb\xd9z\x1a٢^?\xfb\xc9m\xd6(\x8cBuy\xf0\x1d\xbaS\xad\r\x0e5\x1b\x17\xfa\x88\xc5`\xd7\xc2$kI\xf6\x10\xd7\xe6Z\xd7U\x1f;\xe3x\x9ac\v\x18\x19\xd0$e\xc0\xd2aa0\xb2\x95'*\u007f>\xaa\x88\xe2W\x1c\x83\x12\x9dJ\x1a\xb1Q\"\xfb\xfa\xc6tŚ8*\xd1z\xe5}\xad\xe6uv\x9d\xda/n\xd0>|\xfc\xf1-~\x87\xa2D\x9f\xe6\t\xd4\x0e$\x9f\xbe\xb2{o\xad\x10\xfeU\xf9\xb0\x8fS\xa2E\xca\xfbp\x1c\x19\x90F\x92i\xd3\xdcL5\x97\x89\xbd\x91\xa2\x8e\x81\xcb\xe8J\x1fq\a\xa5A\x1f\x9dK\xe2\xad\xe1\x19\xaf\xfb\x1bI\xea\xd2ӽ\xf2\xd8y\xc7@q\x86\xff\xde\x1b\x15r\xeeF\xa9\x91\x18\xeb\xfb+؛\xcb\xf3\x06\xf7\xf2\x1f\x81\xf8\xaf(\xef\xbe\xed\xe1\xa6\xf5Lr+\x89\xafٔ\x9e\xb2r@\xe2P\xaf\x9f\xe2t\xee\x10\x92\x14Z\x9a\x9e\x90\xba<Ú\xcd\xd6\xf6ވeK(W\xff\x10\x15\x95\xb3\xa7)\r%\x12\x12\xa7x\xc1\xf2g\xa1gccm\xe1\x03\xcc\xfa\x0eo\x9f\x97tW\x97\xba\x96\xb6AMV\xeb\x19r\xb65\xab\xd6˖4j\xc6|5$ۦ\xb6VgG\xa2\xf5\xaa5\x9b\x8f?!\x1d\x17N\xd3\xfe\xdf-\xcaY\x98\x98\x92\xe2\x90M\xf3\xe0\xbbZ5\xc2gӿ}\x11\xber\xc3d0\xa7YW\"=\x96-\xd7l>\xe6\x8ae\xb62\x85E\xfc\":*\x91\xd2\xc1\xf9T\x106ާ\x90'\xbc)-\x11\xfe\x97\xbe\x9fߡ>\xd9\xf8\xb0\xdcU\x92{A\x0fZ\xf6~B=\xd3(?攨LMdP\xa3\xe5-\xe4~j\x9dÌ;zC\x8d\xa4\"Dm,\xd4\xd1wW\x89\xcfb\r\xcfxՄ8\xd0\x00\x00\t)IDAT\xddK=\xda\\\xc2HScFVRFY1\xb9t\xb5(74,\r\x87\x16\x15\xb1\x83\t{sy\xce\xe0\x9e\xee\xd0z\xf1\xf2w\xbc\xb1%\x8d7\xadg\x92\xb4\xb0\x8c=\x15\x19~\xbe\x93\xd0GZG\xcen'{\xb8C\xc8\xff\xfa_jn\xafK%7\xf8l\xb6\xb6\xf7f,[B\xfdB\xa9+\xa3KʩgOS\x1eӆB\xea\x9fb\xee,\x8cl\\\xac\x1d\\\x80y\xb4\xa1\xcc\xd4@\xdbVBj\xb9`\xb1\x98̗\xff['zؒf͘\xaf\x86}S[\xab\x13\n\xef\f\x18\xcdǝ\x90\x81\v\xa7i\xff\xef\x16\xe5,L\fIq\xc86\x12g\xefKl|\xfb\"|\xe5d%\xaaY\xae)\x91\x11\xcbU\xc7h>\xe6\x8ae\xb7\x8e\xe2\x8b\xe8\xa8D\xbb\xe8۟\x05\x93W\xe4\x0e\xce\xc7\xfa~n\x87\xa6D\xaf\v\xa5\x92\xf4\xa0\xf0\x13\xcbޏ\x04A\xcd\xf3:\xa7DZWe>5g\xec\"\xa97\xa5\"\xc25\x97\xd9\xd7c}\xc9\fkx\xc6랺\x82\r\xe8\xd9r\xc8\xd2ae\xb4ڠ\xfe\xa5\x9coq\xe2\x89`.\xcf\xf67/%l\xd5b\xd3\xe4\xd27\xf1\xa6\xf5\\җ!\x1fh(=Wb\xe9S\xfe6(~$\xcc!jS\xe9?rm2\x9f\xcd\xde\xf6\x9e\x89eJ\b\xa5J\xdb}ۥTEt\x8dӤ\xf8\xf5A\x81Q3\xfe\xdc\xd8X;\x8c\x00&[\xb1bGWfQ\"\xb9\xc6\t$A\xed'yՒl\xcdX\x1b:ۦ\xe6\a\x12\x97\x89\xdd<\xaa\xde|\xe6\t\xb1L\xfci\xda\xff\xbbE>\v\x13]R\x9c\xb2\r\xf2\xe3&=\x1b\xf3\xed\xb3\xff\xca\xc9Jtu\xf6UE\x89\xd8o*_\x1d\xe3\xdbǍδ\xad\xa3\xf8\"\x8eN\x89>\xa5c/\x9d[\xda\xdcQ\xd8\x0eM\x89\xae\xaf\x10\xfe\xf8oB\xfe\xa7\x96\xbd\x9f\xeaF\xb1?\xe1\x94\xe8\x015\x91ANJ\xf4\xae٩\x11\u007f<\xdb{\x89\xa0D%z\x92\xf1\xba\xa7\x13M\xc6B\x8d9>Mr{\xe3F\xae5\f\xdd\xf01a|\t\x9c\xb9<۶[\xf5e\x1f\x15\x13\xec\xa8\xde\xd7\xca\xc4V-\xe1\xee\xf0\xf5\x91\xaa\xae\xd6\\?-\x839\x8487sk}\xaf\xe6zkd\xb3\xb7\xbdgb\x99\x12.\x91kw}iѰ\xfa'\xc58MJ\xb8\x12\xf1\xe7\xe6\x8b\xd0\x1d\xd21\x02\x98lj\x99\xfd\x16%\x1a*\U000e54f9\xbe\xed\xf4\x84\xbdjI\xb6f\xe6W#BS[\x95\xc8\xee6\xbb\xa1D\xc6\t\xb1L\xfci\xda\xff\xbbE>\v\x13]R\x9c\xb2݈\xb7\xed\x131\xdf>\xfb\xaf\x9c\xacD\xd2\xf2jE\x89\xd8oj\fJ4\x8a/\xe2\xe8\x94HZ\xa3M\xf8H\xef\xfc\xf1ߥ\xf5\x82\xfa\xa3\x8eW\xbe\xf6\x02\xbfC\xfb\xdd\xd9w\x85\x17_\x14\xfeњ\xed\xd6*A}\x00\xe9\xfb\x9c\x12\xa9\xa6\x88C\x84пp\x15dk\x9bn\x93\xa8a\xafDF\x92\xf1\xba\xa7}*\xa3ם\xa3\x8f\xa6G\xe2\xfb\xaaȎ\xb3q\x96\x99\x01\xb3\x04\xce\\\x9ei[ѧ?\xb0\x13f\x15-Y\x92j\x17\xb4\xd3tj\xa4(\xb3\x1bCq\xd4،=\xc4Pݺy$-\xc0g\xb3\xb7\xbdgb\xd9\x12|}I=I}\t\xca\x03\x1b9\xec\xa4A\xb8\x12\xf1\xe7\x16>\xc1\xc0c\x04\x98\xd9.\x13\xc5\x1dnآD\x81Ժ~ҿ?\x95\xb7\xafu\xb5%\xb9\x9a\xd9ׁij\xfe\xa2\xe9\x0e7\xe0\x93\x18%b*i2\xf1\xa7\x19\xe1\xdf-\xe2Y\x98\xe8\x92\xe2\x98M\x9b'\xba\xd1\xceec\xbf}\xb6_9\xaaD\xcdي\x12\xb1\xb11(\xd1(\xbe\x88\xa3T\xa2o\v\xf7ݢ\xef?\xa7w\xee\xf7i\x0f/>$<\xc7\xefД\xe8\xb7\u0083\x0f\xaa\x96\xb0\xdc\xde\xc7Uu\xba\xbe\x9eS\xa2\xd9ʈr\x0fQ\xb4v\x90\xa4o\xb5\xf4\x9c-J\xb4âD'\xd9\u007f\xcdk\xe6M\x8b\x1cc\x9c?\xaf\xf1\x9eE\xf3\x82\xf3$\x1e\xb3\x04\xce\\^i\xdb\x06E\xb2\xcb\xe2·\xc5r\x01fҧLv\xd5\xf1\xf7\x16\xd4y\xd6d\x9a\x979\xc4i\xfa\xd7p\xb8\xd1_\xcbe\xb3\xb7\xbdgb\xd9Jf\x05\xe6J\xe9Uj\x0e\xf34%\xab\x12њ\xf1\xe7\x16\xe5n\x9b\xc4\x05\x98\xd9n&*eZ\xfbD\xf2\x1fMz\xefL\xed\xd9yӒ\\\xcd̯F\x84\xa6f\x8fFk`7F\x1d\xad\x12M\xd4i\xda\xff\xbbE>\v\x13]R\x1c\xb3\x95\xfb\x95J7\x91\xabl6\xe6\xdbg\xff\x95\xa3JtmN;\xad.\xfbM\xe5\xab\x13U\x89F\xf1E\x1c\xa5\x12}\x98/<.\x8f\xad~\xbbJ\xf8\xae$}\x9c/\xfc@y\x9ehٟ\xf9\x1d\xfao\xf1\xd7\xe7\xe5\x15\xdc\n\xcb\xf6\xd1\x12\xe1\xb9[ҧ\xbb,\xcf\x13e_\xa66\x87Z\xeds\x89?\x89x\xe7E=Yo.\xb4(\x11\xe3u/\xb3.\xf3\xa6\x16l\xcau\xd1V\xdf1\xb2\xd5\xfa\xe4\x83Y\x02g.ox\xd2\xcb\u007f\xe1J\xc2c\xd9\x00&\xe9K\x1b\xa6Oi,V\"\x06\xbf\xa5~!\xd5\xeb'\xad\xaco\x0f{\x88\nrLɻ\x85\xcbfo{\xcfIJ\x95\\\x9e[(\x15\xe6.U\x0eb\xffWɨ\x19wnl\xec`\x85\xe5\xcf1\x17\xc0d[\x97J\xbf<\xc5a\xf3D\x92\xa8L\xd3H\u07b5$[3\xf3\xab\x11\xa1\xa9٣I7\xe7\xa9\u007f\xd8-\x8cV\x89\xc6\xfb4M\xec\xfe\xdd\"\x9e\x85\xde:\x92))\x8eن\x92\n\xe5\xab\xe5\xe6\xe2L.\x1b\xf3\xed\xb3\xff\xcaQ%\x92J\x8a\xc80\xffM\xe5\xaa\x13]\x89\"~\x11MF\xa9D\xd2\xebK\x84\xfc\xfb\xd6\v\xc2\xd7\xe8\xfd\xaf\xd7\xf3\x84\x15\xf7\xad\x12\xf2^\xb7\xecЕ\xe89A\xf9\xa5\x875\xdb+y\u009a\u007f\xc8\x17\x1e\xe6\x94hib\u0082t\xe3\x1e{=\xe1~\xe9\xa1\xcd\xc4k\x9d\xc8\xd4\xca=\xb9$\xbe\xa1\x9f\xb3\x86g\xbc\xee%\xe9l\x1c\xfd%\x045\x9f\xa7\xd3\xfa\xea\xa8\xfd[\xfe\xe4\x9bY\xfe=l\xa9\x91\xcd\xe5MO\xfa\a\xf4\xd9\xefH\xa6\xf5L\xd2Gr\x9a곒\xd5\f\xab\xb5\xe1e\x9f2\xabw\xcf\xf2\x92\x05\xec!*HREk\xb0D\xb9\xc9\xc7d\xb3\xb5\xbdgc\x99J\x96\x91\x80\x14\xa0w\x19\xd9Ӕ\xd3!_I(4\xcc\xd7\xcc\xc8\xc65\t}\x884iH\xe2\xe0\x02̣\x89i\xe9\xb5ͫ}\xe1J\xa4\xe1]K\xb253\xbe\x1a\x91\x9a\x9a=\x9a<\xa2\x0f\x93a\xb3\xf9\xf8J\xeaL\xe4i\x9a\xd8\xfc\xbbE>\x8b\xd5\xc64FO-\xa9>\xad\xa4\x1c\xb3\x1d\xf3\xe76\xb4,\x8d\x0f\xd1Z\xaa\x8ff\xd3\x1e\x8d\xf1\xed\xb3\xffʍ\x9c$\xcd\xc3Rg\xa2҅3c\x99r\x99o\x1fsŲ\xdf\xc9H_D\x93\xd1*\x91\xf4\xd1\xe3\xeb\xf3\xf2\xef{A\xbd\x11\xff\xe1\xe3\x05ykv}hݡ+\xd1\xc7\xe6\x9c6\x97\xed_w\xadɿ\xef\xcdW8%*\xef[:\xc7oX\xbb\x0f\xfb\xb8!\xfcH\xb22\xba\x8cW\xee\x14\x0e,\xf6'--\x0f\xf3\xafg\xbc\xeeeѝM\xb3\xf7\xaa\xe6\xf3\xea_\xbe\xd3\xc9ߔ\x02I\xdd\x12KDsyÓ\xfejb\xb1m,cZo&}\x0f\x94$\xcf-־\xb9\r\xa9tBC\xee\x01\x13\xfa\xfc}_Vj+{\x88\x83\x8b+\xd2\x13\xd2\x16wZ\xb3\xd9\xd9\u07b3\xb1L%[\xfd\xbdRߜ\x16\xfe4\xbb\xd54\xa9\xe3kfd\xe3\x9aD\xaed\x12\xe1[\xc4\x12`\x1e\xedjI\xba\u007f\xe9\xe9\x88J\xe4]K\xb253\xbe\x1aR\x84\xa6f\x8f\x16\xf2o\x97\xac\x98\xcd\xc7WRg\"O\xd3\xc4\xe6\xdf-\xe2Y\xe8\xad#\xf7\xad\x92\xe4C%\x0e\x8f.[\xdfR\u007f\xdajY\xb0\x95ߝQ\x94\xc1\x82\xfe\xed\xb3\xff\xcau\xcaaM\xd2\xcdܴ\x9b\\,S\xae\xd9|\xec\x15\xcb}'#|\x11M\x1c\x94\xc8m\xces\xbf\xf4\x18\x03e\xbe&\xa7\x90QQn>^\xe9\x8c9=\x15\x13c\xcc6.\x04\xc3\x1e\x98\x8d\x86u\xc6:\x16&\xb6%c\xafY\x93\xaf\xe4\x86S\xcc\x18\x98\xd8Ӝ\x01L2%\xdaA\xbe\xe9\x14\xe2@u\xfaU\xa7\x90Ѱi\x934z\xc6\xf8\xc5\x1ac\xb6\xf1\xa0!y\x8bS\bK\xec\u05fb\xc9Ķd\xcc5\x1b\x9ak\xffS\xfc\xdbe\x8c\xa792\xa8\x12\xf9\xa7\x1a3\x85ɤD\xfd\x83M\xb3}a]\xd6)@\xcc\u05cf\xca\x18\xb3\x8d\x03bjYL_\xfd\x98\xaf\xf7\xb1\x12s\x93\xb8V\xb3q\xc5<ͻ\xb4A\x92u\xf2z\xe61\x99\x94\xa8P\xfe\x17\x89\xf5\x9b8\tPg(cf\x8cټ`\xe0\x18)s\xa3\xaa\xb17\x89[5\x1bW\xd8\xd3\x1chQ\x19\x88\x96aF0\x99\x94(\x90\x98:\x05\x85H\x9d\xa1\f\xbf\x17\xe0\xc4\x18\xb3y\xc1\":\a9\xe0\x14u\xfb\xc4\xde$n\xd5l\\\x89\xfd4g\x02\x93I\x89\x00\x003\x15(\x11\x00\xc0{\xa0D\x00\x00\xef\x81\x12\x01\x00\xbc\aJ\x04\x00\xf0\x1e(\x11\x00\xc0{\xa0D\x00\x00\xef\x81\x12\x01\x00\xbc\aJ\x04\x00\xf0\x1e(\x11\x00\xc0{\xa0D\x00\x00\xef\x81\x12\x01\x00\xbc\aJ\x04\x00\xf0\x1e(\x11\x00\xc0{\xa0D\x00\x00\xef\x81\x12\x01\x00\xbc\xe7\xff\a\xfd\xa4@\x82&\x8eJ\xdf\x00\x00\x00\x00IEND\xaeB`\x82",
+
+	"analysis/chan2b.png": "\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x04Q\x00\x00\x011\b\x03\x00\x00\x00\x83\v\xcdh\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x02\xfdPLTE\x00\x01\x00\x03\x06\x02\b\n\x06\x0e\x10\r\x19\x1a\x18!# #$\"$%#%'$&(%'(&()'*+)+-*,-+-.,01/2313425747968:7:;9<>;>@=AB@CEBEGDFHEIKHKLJMOMPROSURUVTVXV,`\xae7]\xad[\\Z8^\xae8`\xaa]^\\:b\xab;b\xac<c\xad_a^Fb\xa1=d\xae?e\xb0ac`Kd\x9dAg\xb2cebefdCi\xb3fheLi\xafDl\xafMk\xb0Fm\xb1ikhei\x8fjliGo\xb3Ip\xb5lnkJq\xb6ll\x8dnolKr\xb7pl\x88Us\xb3Vu\xb4xp\x84Xv\xb6surZx\xb8uwt[z\xba\\{\xbbxzw\\}\xb7\x8evve|\xb8^\u007f\xb9{}z\x95wq_\x80\xba|~{a\x82\xbc~\x80}b\x83\xbd\u007f\x81~c\x84\xbed\x85\xbf\x81\x83\x80k\x86\xbb\x84\x85\x83m\x87\xbdn\x88\xbe\x86\x88\x85p\x8a\xbf\x87\x89\x86\xb3\x81_\x88\x8a\x87q\x8c\xc1\x8a\x8c\x89s\x8dË\x8d\x8ay\x8e\xbe\u0083Wz\x8f\xc0\x8d\x8f\x8c|\x91\xc1\x8f\x91\x8eƇT\x90\x92\x8f~\x93\xc4x\x95Ā\x94Œ\x94\x91z\x97\xc6{\x98Ȕ\x96\x93\x96\x97\x94\u074bE\x81\x9aė\x99\x96\x98\x9a\x97\x84\x9c\xc6\xe1\x8eA\x9a\x9b\x98\xe9\x8e<\x86\x9eț\x9d\x99\x87\x9fʜ\x9e\x9b\x9d\x9f\x9c\x89\xa1˞\xa0\x9d\xf6\x935\xa0\xa2\x9f\x90\xa3ȡ\xa3\xa0\xa2\xa4\xa1\x92\xa5\xca\xff\x952\xa4\xa6\xa3\x94\xa8ͦ\xa8\xa5\x96\xa9Η\xaaϨ\xaa\xa7\x98\xabѩ\xab\xa8\x9d\xac̪\xac\xa9\x9f\xaeά\xae\xab\xa0\xb0Ю\xb0\xad\xa2\xb2Ұ\xb2\xaf\xa4\xb3Բ\xb4\xb1\xa5\xb5ճ\xb5\xb2\xb4\xb6\xb3\xab\xb6ѵ\xb7\xb4\xac\xb7Ҷ\xb8\xb5\xad\xb9ӷ\xb9\xb6\xb9\xbb\xb8\xb0\xbbֻ\xbd\xba\xb2\xbdؼ\xbe\xbb\xb3\xbeٶ\xbeӽ\xbf\xbc\xb8\xc0տ\xc1\xbd\xb9\xc1\xd6\xc1ÿ\xbb\xc3\xd8\xc2\xc4\xc1\xbc\xc4پ\xc5\xdb\xc4\xc6ÿ\xc6\xdc\xc0\xc8ݻ\xca\xde\xc7\xc9\xc6\xc5\xc9\xd9\xc9\xcb\xc7\xc0\xcc\xda\xc7\xcb\xdb\xca\xcc\xc9\xcc\xce\xcb\xc3\xcf\xdd\xca\xce\xde\xce\xd0\xcc\xcc\xd0\xe0\xcf\xd1\xce\xc6\xd2\xe0\xd0\xd2\xcf\xd1\xd3\xd0\xc8\xd4\xe2\xd2\xd2\xdc\xd2\xd4\xd1\xd3\xd5\xd2\xcd\xd6\xde\xd4\xd5\xdf\xd5\xd7\xd4\xcf\xd8\xe0\xd6\xd8\xd5\xd8\xd8\xe3\xd2\xda\xe2\xd8\xda\xd6\xd3\xdc\xe4\xda\xda\xe5\xd9\xdc\xd8\xd8\xdd\xe0\xdb\xdd\xda\xdc\xde\xdb\xdc\xdd\xe7\xd9\xdf\xe1\xdd\xdf\xdc\xe0\xde\xe2\xdb\xe0\xe3\xde\xe0\xdd\xdf\xe1\xde\xdc\xe2\xe4\xe0\xe2\xdf\xdd\xe3\xe5\xe1\xe4\xe0\xdf\xe4\xe6\xe0\xe5\xe8\xe3\xe5\xe1\xe4\xe6\xe3\xe8\xe5\xea\xe2\xe7\xea\xe5\xe7\xe4\xe3\xe8\xeb\xe6\xe8\xe5\xe4\xe9\xec\xe7\xe9\xe6\xe8\xea\xe7\xeb\xed\xea\xf0\xf2\xef\xf4\xf7\xf3\xfa\xfc\xf9\xfe\xff\xfcS\x19\x91\xf7\x00\x00 \x00IDATx^\xed\x9d}P\x14\xd7\xde\xe7\xcdݧQ\t\xa8\xf8\xae\xb9r\x91\xd82\x16\xb8S\xd9I\x14\x1c\xf7֔\x0fٰ\x9aD\xddK\xb6\xa2\\\xa3\x0fX>IH=\x88k\x89Z<P\xeel\x15(W\x85X\x18//F \xa5\x80o1\xbe\x11\x1c\xd1@\xe2\vP\xb7\\ū\xa5\xa4H\x95rE\v\x84\x92\x02\xce>\xcfsS\xdb\xe7\xf4L\xf7\xe9\x99\xd3Ӄ6\r\xcc\xfc>\u007f̜9\xfd;\xa7\xcf\xe9\x9e\xfe\xce\xe9\xd3=\xfd\x1d\xf3\xeb+\x80\x00\x00\x00h\xc6h\xa9\x867\xb4*\a\x00 \xc0\x00E\x01\x00@?@Q\x00\x00\xd0\x0fP\x14\x00\x00\xf4\x03\x14\x05\x00\x00\xfd\x00E\x01\x00@?@Q\x00\x00\xd0\x0fP\x14\x00\x00\xf4\x03\x14\x05xE\xfa\xb5\x02\x80@\x02\x14\x05x\x15Z\xe2\xa7poi\x05\x01\x01\x04(\xca\b\xe6PD\xabV\x881\xb4E\x1cb/\xe8\x9f=\xdb^\xde\xc4^\x06\x04$\x06)ʱzW\xaa\xfe\xf0\xee\xfc\xf38\xd1Q\x95o?t\xa9\xc7-\xa9\xc6\xdfv,\x89I\xee\xf3\x16\xe1A\xe1XNd\xec\x01\xadPL\xdd\xfc\xd0)\x8b\x8fM\xb9\x87\xe2\x85\"\xa1\u05f5\xc2\tG9.\xa2\x1f\x1d\x10\n|\xa3\x1eT>\xb9ȕl]1%dA\xbf{\xae\x1a\x9b\xb9\x8dZ!/AM\xdc\x19\xad\x10\xc2i\x13/b:!4%\xe8\vf\xd0%\xee03\x1f\bX\x8cQ\x94{\xd9߉\x89\x9er\xfb\xa9\xa6\x8b\xd97\x10j\xcf=T\xd7t~wa\x8f\"\xa9\xca'q_\xa7\x9b\x9fx\t\xf0d3WU\x95\xc9m\xad\xaa\xe26\xab\xc6\x1c\xbd\xe8J\x1d\t\x8d\xb0\xef\x9f\xc3q\xf5\xe8\x16.vJ\xb5\bMW9\x17R\x85:\x0ep\xe5]\xca\x05r\xbd\b\x95\x84J\x8a\xf6\xe6\x94\xcc\xf8\x906\xf7\\\x152\x83v\x8b\t\xba2&\xb5\xd7\x06\x11p\xd6|B=\x90\xe2 \xefp\x94\xf2\xc5\x0eǼ\x83§\x92\xb1\xdbYA\xdfq\xc7Y\xd9@\xe0b\x88\xa2\xb4\xe4\xbb\x14\xa5\xdc\xde\"\xfcRg\v#\x96o\xf2\xf1ou\x9b\xfd\xbc\"\xa9\xc6c\xbe\x14\xf5u\xaa/g\xb1u<B\xdfbi\b٪\x1a\xf3\xbb\xc5\xceD\xdbķ\x04Q\xe8\x98ɑ\xc1Է>*\n\xea\xe0\x96\xc6#\xd4\xc4u\xb8\xe5K\xf5b\xa4\xa9\xcb6n;\xeaw\x85jMh\xde\x18\xbf֙RT&\xd3\x1a\xe9:'Z\x9d\xca\f\x90Q\x04\xf88\xd2+6!\xd4\xc0_E\xc8\\\x8c?\xae\x0f\xbe\xc5\b\xf2yC\x01\x81\x82\x11\x8ar,\xfb\x98]T\x94\x96\xec\xef\xf1\x1b\xfe\x95.\xcc'9G\x8b\x14I5\xee\xf2\xbe\r\xd5i\xban8\xbf\xf17\xdc\x06\x10\x14\xe1\xef8\x13kC\xee\xe1\xb7-\u070f\xf8\xcd\xe7\x03\xa5\x83\xfbf\xc2S\x86\xa2H\xf5*\xb8\xcei\x9e\xe9\xc8\xc4OuUʮ\f\xd5qu\xce\xd4J-E\xd1\f`\xd0}ש(w\xbb\xf1ǎ\xa9\xf1\x8c \x9f7\x14\x10(\x18\xa1(]OQ\x9e\xa8(\xa7\xec=\xae\xdf\xe6\x96;\xe4\xed\xe4\x01E\x92Io\xacxB\xbf\v\xa1\x9d|T%\xbao\xe2\x97㤩lW\x82y\xc3\x03\x12s75\xd6\x14\x97\xfc\xc0\xbd\xa8\xfc\x8dϋ\b\x9d\xb5\x8a\x1c\xa3\xc7\xe7O\x1f\x17\xb6`\x06BE\xcey\x96p!s\xa6x\xbc\xb4n\xe9R\x16\xcb\f\x0f\x9d\x93\x89\x14\xc5\xe8\xca:\xb8\xa6\xf0|\x97\xa2\xb8b\xe9z\xdbB8.h/^\xda\x13&\xe6\xaeR\xe4R\x95]\x1a\xcbq\xeb\xaf/\x9d\x112\x1f\x9f\xfe\xf5L\xfc\x98,\xa5+\xa3\xd8>\xab\xa8\x9e\xab/\x99\x95\x89\xce8\xa7;V\xe3쁊Ds®\xe78yy\x83\xcd\x14\x9bl\x1bP\x04<1\xf3x\v\"\xb7\xcd\xf78=֖\x93\x13k\xaeV\xaeDT\x14'\xebC\x18\xc2|\f\x14\x05Pb\x84\xa2\b8\x15\xe5PQ}\xa1}\xefI\xf9\xabٿ\xb7\x8a\x91t禣\x92/p8~F\xe8\x81\xc3T\x80\x06\xaen\x8bF\xa8\xb9\xd2\xc4\xc7\x15\xfc\xd9\xf2\x19\x8e\xa85\xaf\xfe\xaa\xa6\x80/v/)IC|\xd0\a%\xdb'\x87\xf7\xe3S\xff\xf8\x03\xe5\xf60\xae\au\x9c\xac\x9a5\xb7\xaa\xaaJ8\xd1\xe9\nR\x9c\x19\xc9łח\xac\x0f\xfe=\xa2\x8bѕ\t\x8a\xb2}\x81SQ\xa4X\xaa^\x84\xceWU\x05o\"u}_\xb5\x9f\xdbTUբ̕+\xeb\xca\xdf;c\xd6\xc4髖r\xf8\xe2\xc9E\xee\x18Y\xac\xa8L\xa6e)\xf7\x06\xf7[n\xf1\x1d\xd4yő\x90\xe4p8n\xe3쌨\xacs\xa5q+\x85\x13\x9b\x9f楟\xa8)\x8b\xe5_(\x03\x1a\x1c\x8e\x98\x02\x9c\xa07_\xefrk\xe9\xbe\x18s\xd9\x06\xf7\xedG+\xcaI\x0f\xf1\xe8\xb9w\xecw\x93\xdcGg@\x80c\xac\xa2\xe4\xdb\xf3.ݪߛ/\xcd\xc1\x9e\xccmc$=\x91\xcfz\xa2\xf1\xf1P\x10M\x92\x16\xe1\a6=NHuے\x85\xa1yo\xf5c\xf7r.i(\xe2rɧ\xfd\xc2Hb2^{\xe6$2Vr\x9dP4q\x87X\xc5\x0esG\x84\xd7#\xf8\x82\x06U\x8c\xaaLP\x94{\xaf\xdf#\x8aBź\x9d\xa8\x848\xb5Cy\xd6\xe3̥*\x13\x8aqo\xb6\x89'\x85\xa8\x84\xbb\xe1\x8ad\x9f\xf5\x1c\x1eǍs^h\x91Nj\xce\xf2\x15\b\xeb\x800\n)\x8d{!$K-}\x8a\x00\x8c\xa8(\xf4\xe6\xab\xe6\x1b\x85P\xbe\x19\xb9C+\xca-\xce}\f\xf9\x960t\x1a\xc4i\x1c\x10\x10\x18\xab(E\xf6v\xe1\xb5#\xf7[g\xf6\xa9l\xe9^\x06*ɀ\xad(\xe9\xae\xe4\x05\xfe&\xbb\x9cK\x1a\x16\xcf\xec\xc1L\x13\xcem\xeeL\x9d\xb1\xc2\xfe}\xbf(j\xae\x83\xb5g,s\x8c\x12\xff[\xf2\xf6\x86\xb2\x18U\x99\xa0(h\xc1V\xa2(T\xec`\x14\x85\xaaL(\x16,m\x84BNJ\xb2\x14\xa5m\xd5\xf8i\xdc\xd4\xe0\x8f\xc8\xe4\xac$\x18i\xef\xf6\xbe\x10\xb0e \xf4к,\xab\xecf_/R\x04`$E\x916_\x8eEx\xb9͟F\xee(\x15e\xbf\xdbҦ\xc3ٳ\xc3`\x8c\x02(0VQ\x8e\x15\x8ao\x87\xc8[\xcfQ\xbbk,O%\x99\xb0\x15EJ\x16\xf3\xdd\xecr.i\x98㜍\xc0\xb7w\xb6e\xbf3\x9b\x9b\"^Q\x96\x0eV\xe7<J\xcf\x11E\xb1\xb9\v\xc9ۂ\bE1\xaa2\xac(\xf9s\x88\xa2б\x83P\x14\xbae(\\\x9e-9%\x9fd\xb0\x14esXv=W\x9f\x19\xf69\xfe \tƇ\xce)\x93\x14!\xfd\xa4,5\x81_rp@\x11\x80\x91\x14E\xde|\xf3\x1ecU\xf6>F\xf9\x96;\xe9\xb1\x1cUq\xdf\"\x00\xa00VQ.\xee&\xe7\x1a\xe5\xe4\xc0zZ\x94\xd7\xe2\\L%ٸ)\xca\x1e7E\xa9\xe1U\xee\xc8pI\xc3ҙ\x17\t\xc2O\xfay|Q\xb6m\u007f\b\x99o%\a\xab\xbdI\xba֓ϵ\xd2\xc5\xe2g\x92\xb7\x19\xf1\x8abTeXQ:B\xcb\xc9\x18E\x8e\xa5\xea\xc5xU\x14\xaa2\xa1\xd8\xdb\xd2\xe2\x8e`\xe9\xf66Ee.zȵ\x1eq\xa4E\x04\xa3\xe2!\x1e\xa3\\#\b\x02ѐ#hɓʘRE\x00\xc6SQ\x1eF%?lLH\xf4\xbc\xacL+ʧ\xe3\xdb=\x96õ\x1e\xc0\x1dc\x15\xa5\x8d\\=n'w\x9e\xb4\xee? |E\xfb\xbb\x94I\x15dE1\xe7 \xd4\xf7\a7E\xe9\xb4&\xe1\xe1}V\x96{9\xd77\xfe\bG\xaeP\xffQ\xf8I\xdf$\xcetD\xae \xaf\x91\b\xdd\xc3\xcb\xda&\xbe-\x1c\x9d\xfd\x913\x14\xc5J\xc8H\u007f?W\xa2(FU\x86\x15\x05\xc5/ƊB\xc5R\xf5b\xbc*\nU\x99r4\xb2x\xa6\xeb\x8e\x15Ee2w&\xddq\xa6\x92\x92\x10z\xc4Wce%Wkr\x0e\nۅ\xbf@\x16\xedP\x04`<\x15\xe5\x1a\xbf\x84\xe7\u05f9.\x945}!\xcd\xe0P\x8a\xd2?{\x01\xf2\x04\x14\x05p\xc3\bE\xe9ji\xc9=\xdaB\xc6\x00\xe7\xed\xe7o\xd5\xe5\xe1\xbbc\x9b\xec\xfb\x9bZZZN\xe6+\x92l\xc4k=W\xc9ohb\xdc\xc1\x82D\xdeT\xd1\xfc\xb3ô\xed\xea\xc0\xcdm&|\r\xa86f\xf9\xd7\x17\xb2\xf82\xb7\x82\x173\xb9\xad\xe2}sk\xb9\xc5\xf9\x87\xe2\xb9<,\r\x136\x96\x14Ƌ\x97R6\x06o)|3\x14\x1f\x99\x87C#r\x0f\xcd\x1f+\x8c\xec\xef8o\xb5Ń\x82\xa5Ak\x8b\xd6\x06-E\xcabRe]\xe5܁\x0et4\x84\\\xeb\x91c\xa9z{NUU\x05\xc7W\x1dos]\xeb9\x85u\x82ʕ+\x132\xf1U\x1d\xd7X\xe4Ǡ-Δ\xdcH\x15\n\xa2\x8bO\u007fb\xc6C\x90\x9cyi'Ng\xe0\x99\xd9\x02\u07bc\ufb10\xacU\x04\xf4^u8b\xb69.?C\xf4\xe6\xbb\x16Ss\xce\xf1\xc05DYȹ\xb4\xe3f)_\xdc\xe0Lo\xe5Xw\xee\x9eg\x9d\n\x01\x81\x8c\x11\x8ar>\x1bC&eэC\xb9\a\xce\xe3\xb1\xfa\xe1l\x91\"E\x92I\xb7E\xfc\u007f\t\xb9\xfcy7)Ʋa\x0f\xcf\xef܉\xb3\xfeb\x16^w\nٷSm\x96D\xf7\xa9Ŏ\t\x1c\xc79\xefz?\x12\x196i.\x1ef\xe4\xcd\xfdt\xfa\xb8)\x91\xe2\xb5ٮ\x0f\xc2B\xe6\x8aS\x01\xf8\u007f=\v\xf1=c\xf1Ι\r|\xa7j\u007f\xe6\x9c\xd09\x99\xfd\xee\xc5\\\x95\x1d\x13\xc2\xf2Q\u007fĔ~E,U\xefwAbe٨k\x12I\x8c\xadW\xe4R\x95]\x123\xa5\xa1\xc0\xfaםG+\xd5H6\xddY\x8bb\x92\xc4C\xbff]\xace\r\x1e\x9dT\xac)\xb0\x99\xacI\xb5ʀ\x9f\xa2ĉ\x962Do\xbe+\xe4/<\xa65\xe2DJ\xee\xe4l\xb1\xda\xe7x\xa9\xf9\x19I\x1f\x0f\xf9\xc8}\xad\x98{c߹tO\xeb\xee_ \x900BQ\x80\x97c\xd5x\xd5Q\x9b\xae<2\xefx\xf4\xe2œ\x9f>[\xa4\xfaǩ\xfd\xe3\xe3{\x10\x8b\xc2\xd9\x1c<\xcd\x00\xa0\x00E\x19\xc1l\x9dvO+D\x0fN\x8b7\xad\xa0\xbe\xd8\v*\x11mS\xd9\u007f=\xc6ܻ\xe4}R\x1d\b,@Q\x80kQ\xe2\xe9Ns\x94\xca]=\x00\xe03\xa0(@_\x86yGum\xf5\x0esƀV(\x00h\x00\x8a\x02\xa0\x813\x1b\xac&k\xf2Y\x10\x14\xe0\x95\x01E\x01\x00@?@Q\x00\x00\xd0\x0fP\x14\x00\x00\xf4\x03\x14\x05\x00\x00\xfd\x00E\x01\x00@?@Q\x00\x00\xd0\x0fP\x14\x00\x00\xf4\x03\x14\x05\x00\x00\xfd\x00E\x19\x1d\x9cI|\xa4\xf8\xac\xea\x1b\n\x00ÊA\x8a\xe2ݥ\xb4\xe5\xc8^{\xfeI\xc6#\xc2\f\xa0i\x1c7\xdb#\x93r\x13\x1d\f\xbeZ\xa9*\f@}\xe2 _\xe0vC\xab\x9ao(\x00\f+\xc6(\x8aw\x97\xd2{\xd9%\xf5w\xea\x0f\xec}꽒!\xe2T|\xb0G\x1e\xe5&:\x18d+UᄀJ\x03P6\x8a\x1aJ\xa3*<rU|C\x01`X1DQ4\\Jod\xe3\xe7\x93=\xcd\xf6\xfa\xec\xea\xa1c\x93\x87\xa2(\xdcD}\x87\xb2R\xf5\xee\x1b\xeaf\x00ʄ\xae\xe1\xae)\x87\x91\xcb\xf6\r\x05\x80a\xc5\bE\xd1r)EdpҚ=L\xcf\xd9\xf0T\x94A\xb9\x89\xcaPV\xaa\xdemA\xdd\f@\x99\xd05dX\x9f3rپ\xa1\x000\xac\x18\xa1(Z.\xa5$\xe6V~\xd1\xe0'.^\x95\x96\xa5S'\xbd\xed<\xebq\x99\x85\xd2n\xa2j\x16\xa2\x12\xcfR\xad&[J#RX\xa9\xb2}C\x1bM<\xbf\xe7n\xfa\xb2\x98dl\xcd%?\x14Z\xcbXT\xa8\xda\"\x0eQ\x94\xb9*\xbe\xa1\x000\xac\x18\xa1(Hӥ\xb45;;;\xd7\xf8\x99\xd9\xeb\x13g\xe5\x1e\x9a\xcf\x11E\x91\x9dGi7Q\x15\vQ\x89\xb3|FmuJ\x14~\x84\xabl\xa5\xca\xf6\r\xed\xae\xae\xb4%Xl\xbb\xd2\xe6\x11\x97\vIQ4\x8dE\xd1M\xdeAޕ\xb9,\xdfP\x00\x18n\x8cU\x14U\x97\xd2֖\xba\xfc\xbd\x86K\xcaܙ\xc2\xe8\xa3\u007f\x0eV\x14\x85Y\xa8t֣f!*\xf1\xbc\xbaS\x18e\xbc\x9fB>\xb0\xcez(\xdfP!\x97\xff\xe4\x19\x1a\x10\x1f\x05\xedR\x14\x1f\x8cE\xcf\xf1\u007f\xf5\xa8\x17\xe3\xe9\x1b\n\x00Í\xb1\x8a\xe2ť\x14\xf5\xe4\x97{\x96\x1bR\xda8;~[\x8f\x15Ea\x16*)\x8a\x9a\x85\xa8\xcc\xe3\xd2\xe4w-\xfc\x87$\xcdR\x14\xca7Tȍ~(\x15t)\x8a\x0fƢ\xa7\xf9\xfb\xae\xa4\x9b\xa2\xb8\xfb\x86\x02\xc0pc\xac\xa2\xb0]J\xbb\xc4\t\x94Kv\x83'R\xces\xe4\x94k#V\x14\x85Y\xa8\xa4(j\x16\xa2\x12\rq\xb6\x9cӎu\xea\x8aB\xfb\x86\xa2\x95\xae\x19\x10$+\x8a\x0fƢWe\x1f.\x85\xa20}C\x01`X1VQ\x98.\xa5\xfdyG\xc9\xc2\xef\x8dV\x94V\x8e8\x95\x92\x99Y\x85Y\xa8\xa4(j\x16\xa2\x12\t\x89xJ5\x95\xad(n\xbe\xa1J=\x90\xc7(\x9aƢϣ\v<\xea\xc50}C\x01`X1VQ\xd8.\xa5{\x89}\xb9\xf1g=(bz\x9b \x1f\xafcEQ\x98\x85J\x8a\xa2j!\xea\u0086\x8f\xf0\xbe\x95\x1e\x8a\xc2\xf2\re+\x8a/Ƣ\xa9\xef\xb9nĥsپ\xa1\x000\xac\x18\xa1(Z.\xa5?f\x97\xd7ߩ\xcf7\xfe\x9eٺ\xd0韮\x0f\v\x1a\x9b[OۘRn\xa2\xaa\x16\xa2.\n\xf8\xd4҂\x95|\xecWW\x15V\xaa,\xdf\xd0\x17?\x90+5\xf7ł\xb2\x01\xa8\x96\xb1\xa8\xc0\xed\xa8?\xbb\xd6G\xe5\xb2}C\x01`X1BQ\xb4\\JQ\xcb7\xf9\xf6\xc2S\xc3ps\xc5\xf5\x85a3>\xca\x1d˭@\xb2Y(\xed&\xaan!꤯8!:.\xad\xe2=S\x92\xc2J\x95\xe5\x1b\xda(\x1a\x84&\x93L\xda\x00T\xc3X\x14\xb3/\xe6\nr\xcfU\xf1\r\x05\x80a\xc5\bE\x01^\x95\x81,S\xb5[\x96\xaao(\x00\f'\xa0(\xa3\x82\x81b\xdb/\x8a\fo\xbe\xa1\x000|\x80\xa2\x00\x00\xa0\x1f\xa0(\x00\x00\xe8\a(\n\x00\x00\xfa\x01\x8a\x02\x00\x80~\x80\xa2\x00\x00\xa0\x1f\xa0(\x00\x00\xe8\a(\n\x00\x00\xfa\x01\x8a\x02\x00\x80~\x80\xa2\x00\x00\xa0\x1f\xa0(\x00\x00\xe8\a(\n\x00\x00\xfa\x01\x8a2\x829\x14Ѫ\x15b\f\xe0\x89\n\xf8\x8aA\x8a\xe2ݥT\xa0\xce\xfeR\x169CK.~\x80A\xd8\xfc\xa1|\f\xc9\xd7|T\xa5ڲ\xcd\xdcF\xc5\xe7\x15\\P\xbeJ\xa8\aڱ\xf1B\xdfB\xaf{\x8fA\xefd\x8a\xef\xe0\x89\n\xf8\x881\x8a\xe2ݥ\x14ao\xc1\x93y^\xca\x1b\xccQ\xa7\x86\xb4\xe5r_\x1c͍\xe0\x8ey\x0f\u007f\x15\x9e\\N,@l2\x83v+3Z\xaa\xc6mb\x87z\xa2\x1d{\xab\xaa*S˞\xe3;n\xad3\x05\x9e\xa8\x80o\x18\xa2(\x1a.\xa5\x02E\xe5wF\x90\xa2\xfcn\xb13Q\xc7\x1dA\xa8\u007f\xee,\xafѯH\x8a\x8a\xa2\xdc\x18\xbf\x16\xb9\x13쳢\xf8\x14\xfb\xad\x86\xa2\x1c\x9f&)\nx\xa2\x02\xbea\x84\xa2h\xba\x94\xa2\xba\xddO[F\x90\xa2HO\x94%\x8a\x822\xb9\xc1{ \xfb\x8e\x9a\xa2\xc4O\xf5\\\xab\x0f*!\xe1C\xac\x86\xa2\xbc\xc3-\x0e\x95\x14\x05<Q\x01\x9f0BQ4]J\xdb\xed\xd7Ѱ(J\xebҰi\x1f}\x146\x01\xab[fx\xe8\x1c<kP\xe4t\xd4\xc0^\x1a\xa2\xa2,\x9dF\x82]\x86\xa5\xc2\xd1\xf5\xf1\xec\tsOM;\xec^]\xee\x14b\x00tk\xa2\xb3\x8a\x89w\xe4e/\x96\x98rl\xd6\xda,KR'mnJ\x14%\x8b\xe7\xf9\x98\xc7\n\xc3R\xd43\xf1cW\xd1\x1bo\x87\x8d\x9b\xb2\x00\xfb\x06\x04\u007f\xb4jV\xe8|<Xh{g\xea\xf8\xe9\v/!<c2\xce\xeeʥ\t\xfe ~j\xd8Bq\xa2\xc4\xd57eRKQ\ued60I\xf28\t<Q\x01_0BQ\x90\x96KiI9\x1a\x16E\xe9ycJ\xe6\xc6\xe0\x10\xfb\xfc\xad\xd8cc}\xc9\xfa\xe0\xdf\vrq\x92<\xa3\xba\n\xcf%\xd7q%O\xeb?\xe6ȣ\xf0e\x1bӶ\x99a\x9bKVp\x9c\xeb\xc0\x94x\x8b\x9bO\xaaݽ]$\x97~nc\xad\x85ߵ\x8e\x8f=\xb8\xa4Xan\x8a\x15\xe5AZ\x14y\x8c\xb5lX\x8a\xd0Ei\xf6\xe6\u0604\xf0\xcd\xe5\x1b9\xa1\x8d(\x98\x9b\xbd\xf7\xd0\x14\xec\xf2Q\xc4\xc5\x1f\xcb_\x18\xf4-B\xf5{\xc7r\x937m\x99\xe8\xee\xfd\x11̅\xef\xdf?'\xb4\x0eQ}S$5\x15E\x80R\x14\xf0D\x05|\xc1XEa\xbb\x94\xd6\xe7v\f\x8f\xa2\xec\xe7.\xe1s\x1a|\xd0\x1d&\xa3\x91#\x1c\x19wPg=\x98\xa58I\x19\x96\xfe~\x12\x1e/\xac\xf2T\x94\xa6\xcfo\x90\xf7{M\"\xf7\x14K\xad\xe9\xe8\x1c\u007f\x06\xa5g(\xcdM\x05E)\x8e>\x8bS\nG\xd3\x12N\xac\vuM\x9f߅\xbdG\xf0\xa9b\xf0\x94VA\x14&\v\xa9\xa7\xf9x\xb4\xf4[bM\x16<I\x18\x9f,\x9d\x8c\x94\x04\xcf\x16\x8au͊P\xf4M\xd1\xcd\xc1)\nx\xa2\x02\xbe`\xac\xa20]J;\xec\xf5\xfd\xfd\xfdMy\xfd\x06\x1b\x80!\xb4v\x12\xc2\xe6<\x87\x84\xd7\xf8ߒ\x9c7D?RYQ\xb6\x9c*\x89\b\xc1\x9e\x1a\xb2ai\u007f(\xb9\xa8[\xef\xa9(N\x9a8\x17\n3\x0ek\xa5\xa0\x16\x9d('\r)\xccMS\n\xf69}~\x14\x8e\xa6\x85\xae\xc2%\xdc\xf7R\x15\xc1\xb8y\xc4\x03\x11\xb5fΟ9\x91\x9b\xe3\x96K\x11\xfcG\xfc\x9aɵ\xd1}Sts\xb0\x8a\x02\x9e\xa8\x806\xc6*\nӥ\xb4)\xdbE\x8bJ\xe9\xa1b+\u05ca\u007f\xb6\xf1\x18e\xeeB\x92\xb3 \x02\xbf*gfۂ\xb2\x11mXz\x8b#\xbdhWU\x14TU$R\xa5ȵ^@\r&D\x14\x8567M\x89\xb3$|F\x8cI\x15\x8e\xa6\xa7\\G\xfbVN>I\f\xc6Z\xb6\tkǷS\xa6\u007f\\X\x159G\x99K#\xce\xccVq\x17\xe9\xbe)\xba98E\x01OT\xc0\x17\x8cU\x14\xb6Ki+\xa6.\xb7\xb5\xd5\xe8AJSЂ\xa6K\xb3\"\xf0j\xe3g\x92\x9c\x19\xf2\x18\xc5\xde䚙\x9d\x88\x8fXٰ\xb4?\xe4S\x1cT\xa7\xae(l\xac5\xa8!ZT\x14\xda\xdc4%\xae\xf9\xbe\xa5\x18\xa7\x14\x8e\xa6\x1d\xc1\xce\xdb\xdb\xca)\xa3/\xa2\x12D;fG`\xbf\xb4\xb7\xe7(si\x82W\xe1W;\x1e\xa3\xcc$\x19\xb8o\x8an\x0eNQ\xc0\x13\x15\xf0\x05c\x15\x85\xedRJ\x18\x8ey\x94\x8b\xdc\x14\x8e\x8b$\xb2VB\xc6\xf4\xfb\xb9\x12\xfc!2\x12\xa1{ؠTT\x94)\xab.}J\x1b\x96.\x0e\xc37\xc7/ẹ|q\xc3=\x8b\x82R\x14\xda\xdc\x14_=\xbe`\xc2\x13\xb3\nGS\xe14K\x14؎)\x91x\xda\xe9\x03,\x10\xb2vL\xc7\x13\xb1\xfds\xbc)\xca4<\xfd2;R\xd17E7iEi\xdaļ3XV\x14\xf0D\x05|\xc2\bE\xd1r)\x15\xe8o\xa9\xcbmi\xf3Z\xcb\x10p1\xb8\xbc\xa4\xaaE<p\x97\x06\xad-Z\x1bD&a\xd1\xc6\xe0-\x85o\x86\xdeA\xe8\x12\x99\u008c\\\x80\xa7\x1fd\x1bӖ)\xd33\x0f\xbc\x15\xec\xa9(\v=<\a)\x9a\x17\x15?\xaf45>O[\xf7\x8027}r9q\xdb\xd5\xde\xcedk\xed#ڰT\xe0Ǡ-b\xc1\xa3\xaf\xbf\x91Y\xf2\x01g\xc7\xf7\xc1ƟB\x17\xe3\xc7U\xb5\xa0M\xdc;\x99\x9f\x87sa\x9bOѹ4\xc1\xdc\xfcS\xdfDL\xc2\x1aG\xf5MN\xde\xc1\xf7\xccnu\x19\xaf.\xe4&xl\xfe{UU\x13\x16;\xedZ\xc1\x13\x15\xf0\r#\x14Eӥ\x14\xdf\xfa&\xb0\xd7[%C\xc1\xc9\xf1xfd\xdc\\<\x91ҟ9'tN\xa6x\xf4t}\x10\x162\xf7[\x84\U0008595b\x05]\x99\x15\x86\u007f\xd3]\x86\xa5\xc2\xf0*~zț\xe7=\x15%wr\xb6{\x96D\xdf\x12\x9e\xaf\xb4\xf0\xe6j<O\"\x9b\x9b~\xcd\xf3|\xd4O\x95\xc2\xeb>D\x19\x96bֿ\ue738\xb8\xfeδ\x89\x11\x85\xf8\xce\x13\xa1\xb1u\xa1\xc2\xeb\nԿuV\xf0\xe4Ź3\xc7Gҹ4\xb3?}g\xe2ԥ\xe2y\xa5\xdc79\x19\xef\x9c\x18\x12\xef\x0f\xb6O\xe0\\\xd3\xe5\x12\xeb\xc9\xf2\xb1\xe4\x96\x16\xf0D\x05|\xc3\bE\x19\xa9\xb4NX\xd1\xda\xd3\xd3\xf6\xdd\xdba/3:\xea\x18\xec<ʠY5\xde\xe7?\x06\xbe:\x85\x9c\xb7\x8d\x00\x9e\xa8\x80\x8f\x04\xb2\xa2\x14N\x12\x87$\xfda%\x1a\x91,\x86^Q\xd0\xd6i\xca;Z\x86\x8e\xfe\xdcI\xca\x11\x8e\x12\xf0D\x05|%\x90\x15\xe5bP\x1dy\xaf\v\x92\xef\xf8\xf0\x1d\x03\x14\xc58Z\xc2V\xc1=\xf6\x80\x1e\x04\xb2\xa2\xf4LJ\xac\xd8\u007fl\xff\x8a\x90\x97\xf9\x0f\xdc\xf5\xc3ܪSF_\xee\x06\x80\x91N +\nBE\U000e739f:\xff\xa5\x9e\xf54W\x9a\xb4\x04\x00@\"\xb0\x15\x05\x00\x00}\x01E\x01\x00@?@Q\x00\x00\xd0\x0fP\x14\x00\x00\xf4\x03\x14\x05\x00\x00\xfd\x00E\x01\x00@?@Q\x00\x00\xd0\x0fP\x14\x00\x00\xf4\x03\x14e\xd4\x01ޥ\xc0\b\xc6 E\xf1\xeaRڵ\x9b<\xd7 w$\xfe\xbb\xb5n~\xe8\x94\xc5Ǧ\xdc\xf3\xcd\xd4S/\xc0\xbb\x14\x18\xad\x18\xa3(\xde]J۲\xbfo\x11\x18!\xbf\xbc\n\x8e\x84F\xd8\xf7\xcf\xe1\xb8z\x9fL=u\x03\xbcK\x81ъ!\x8a\xa2\xe1Rږ\xadxf\xfc\b\xa2m\xe2[]\xc2hj&G\x86Xڏe\xd5\x0f\xf0.\x05F'F(\x8a\x96K\xe9\xc8U\x94\xb5!\xe4\x01%[\xb8\x1f\xf1\x9b֡\xa6'\xe0]\n\x8cN\x8cP\x14-\x97\xd2\xe1S\x94\xe3\xf3\xa7\x8f\v[0\x03Ѯ\x9f\x1b9\x8eۋ\xf6\n\xaf\xeb\xd1L\xf1xi\xddB\x1e\x1e\"\x1fj\xb2է\\\x03mc\xaa\x00\xbcK\x81\x00\xc2\bEA\x1a.\xa5m\xd9\xe5\a\xb2\xf7\x1e7\xfe\xab\xf9\x1d\x17\u007f\xa0\xdc\x1e\xc6\xf5Ю\x9f\xad\x8b#\x8e\xb7\xa3\xf6\x93s\x17\xdf\xeb\n\xdaJ\x87K\x87\x9al\xf5I\xd5@٘*\x01\xefR \x800VQ\xd8.\xa5m\xd987\u007f\xbfᒒ9\x197$\x13?\x1c\x92r\xfd\xdc=\x9b,\xfcm\x1ej\"v\x83\x12\xaeC\x8d\xb2\xfa\xa4j\xa0lL\x95\x80w)\x10@\x18\xab(L\x97R\xd4_\x87\xb5\xa4k\xb7\xd6\x17Yw\xeeL\x9d\xb1\xc2\xfe}?\xd17\xd9\xf5\xf3RPW\xc7\ued9e\xe0K\xa8g,s\x8cBY}R5\xc86\xa6l\xc0\xbb\x14\b\x04\x8cU\x14\xa6K\xa9\x8b\xe3\x85\xc8hڲߙ\xcdMٌ\x14\xae\x9f]c/m\xe5\xfe\xa9>H\x909\xe7<J\xcf\x11\xf2\xe6:\xd4h\xabO\xb9\x06\xd9\xc6T\x05\xf0.\x05\x02\x00c\x15\x85\xe9R\x8a\xca\xc5G\xd1\x1f}\xa9\xa73\xbe\n\xe7\xf1\x91Ѷ?$S\xe9\xfa9{o\xe4\xdcم\xf8\xdc\xc7y\xad'\x9f#\xf7\xcaHc\x94\x99\xe4\r[}R5\xc86\xa6\x83\x02\xbcK\x01\xbf\xc2XEa\xbb\x94\x96\x90S\xf1\xb6ܗy\"\xfd+\xb1I\x9c9\x88\\\xa1t\xfd\\\xbcb\xfcan\x05v\xc6j\x9b\xf8\xb6pB\xd3\x1f)^\xcbq\x1dj\x94\xd5'U\x03ec\xaa\x04\xbcK\x81\x00\xc2\bE\xd1r)\xbde?|\xbd鼽\xc4\xf0'\xcbo\xe2&l,)\x8c\xc7\xd7Od\xd7O\x84\xbe\b\x9d\xd8?+\x84(\xc3\xe1Ј\xdcC\xf3ǞT\x9az\xcaV\x9fT\r\x94\x8d\xa9\x12\xf0.\x05\x02\b#\x14Eӥ\xf4^\xf9\xdeܢ:\xc3\x05\x05\xe5\xcd\xfdt\xfa\xb8)\x91X\x0ed\xd7O\xa1\xbd\x93\xfe\tm\x9e \xce\x1e\xe3\xff\xf5,$\xd7Z)SO\xd9ꓪ\x81\xb61U\x00ޥ@\x00a\x84\xa2\x00z\x02ޥ\xc0H\x06\x14e\xd4\x01ޥ\xc0\b\x06\x14\x05P\x05\xbcK\x81A\x03\x8a\x02\x00\x80~\x80\xa2\x00\x00\xa0\x1f\xa0(\x00\x00\xe8\a(\n\x00\x00\xfa\x01\x8a\x02\x00\x80~\x80\xa2\x00\x00\xa0\x1f\xa0(\x00\x00\xe8\a(\n\x00\x00\xfa\x01\x8a\x02\x00\xc0K\xc1\xfc'\x1e(\n\x00\x00\x83\xa7%~\n\xf3\xe9b\xa0(\x80\x933\x89\x8f\xb4B\x86\x9c\x97t`}\xc9b\x80&\xaaN\xb4\xfd\xb3g\xdb\xcbY\x1e\x16\x06)\x8aW\x97R:wt\xb1\x93\x8f\xaa֊yEj\xe7\xf1\x89}\xe8\x04\xcfϫU\viL^dYS\xfb\xfe\x15\xb5\xe5\xbeq\x90/\x18@\x15<\xcf\x17\xa0\x02\xe1\xb5\xccK\xe8}\x13\xbf\\x\xdb&\x84\x99慎9\xe69\x1fh\x19Ө\x1e\xa4@r`\xfdێ%1\xc9}ރe܍[\xd9\xe0\xbe\xf1\x8b\x92oj\xc5\r\x96\f\x9e\xc7\x0f\xdb+\xe6\xf9\f\xb7%5qgX\x05\x86\x16\x9d\xbb\xa9\xe6D{\x89\xf3|n\a\xc1\x18E\xf1\xeeRJ\xe5\x1a\xcd\xd1W{`\xd0\x03\x87\x89rꪽ\xc6JR\xb0s\xbd\at\xd7\xf01\x0e\xd4y\x82\xaf\xe9f\x14\xc0\\3\xa5\x9c\xa8\xfc\x8c\xe7_M\xdbJ\xa3\xf0#\xf7\x9fU\xf0\a\x1f\xa1G_\xf1\x15ϼ\xc4\x0e\\\xdd\x16\x8dp\xef\x1d\xa5\xfcU\xf5\xb0\xee+q\xc9\x0e\x81\n\xfe\x02\xf2\tف\xf5\x93\xb8\xaf\xd3\xcdO\xbc\x06\xcbx\x18\xb7\xb2\xc1}\xab\xadHTW\xe6\x97\xe4\xa1\xf9+\xfc\xc4\xce\xc7_Y\x1e\xba-9k>\xe1Li\xeey\xfdХ\x9bT{U\x9ch\xbf㎳\xb2\rR\x14\r\x97R*\xd7h~\xb7X+B\x83hJQV\xa7\xb2\x92\x14\xec\\\x8d\x80N>}\x9b0,\xe0;=\x17\x89lX7 \x1c\xe4\xdb^MQ\xee\x9ar\xc8{3_#\xbc\xd6\xf2\xcd^\xa3QA\xb4\xf8\xde\xe0MQ\x10Z\xb6\x03\xbf\xde\xf6QQd\a\xd6\xc7|)\xeaS\xed\xb0\x1b,\xe3V&\xa4o}k\x12\xb4\xe2\x06\xcb\xfb\x15\xe4\xad\xecC\x8f%\xd2(Ks\xcf\xeb@k\xa4x\xea\xa7G7\xe9\xf6\xb2\x9dhU\x9fFl\x84\xa2h\xb9\x94R\xb9F\x13\xfe\x8eV\x84\x06\xb4\xa2\xacLe%)ع\x1a\x01\x9d|\xad\xf9\xb97EYF\xb4\xa0\x91?\xad\x16\xe0\v\x19VѴp(\x14\xa5\xb7\xd4ۀGFv`\xbd\xcb\x0f\xe2t\x81e\xdc\xcaD\xec[)\xff\\+p\x90|\xb6\x87\xbc\xe5|\xa6\x1e\xa2\xb9\xe7u\xa0\x8e\xab#\xefzt\x93n/ۉvX\x15E˥\x94\xca5\x94\"\xe7\x13\x10\xc3\xf1\a\xdan\x94ƛǨ@tή\x04\xf3\x86\a\b\x9dq\xce\x19\xacV$w\xf2\xa6\xd2\f뢔\xbb\x8a\\\x85\xf3\xe8\xe5\r6Sl\xb2m@\x19 \xd3\xc9\xdf_y©(R\xb1}B\\%\x12\x1f\x1b\x99fŇ\xff\xc09E@\xa3\x89\xe7\xf7\xdcM_\x16\x93\xfc\xa2\x9aw͍T\xb3\x03\x84r\xbd\x16q\x88B+\x8al\x9a*\xf4\xa2\xcc\xd9M\xe1\\'\xcdjI\xdd\xe6\xae(\xeczEE!5DU:\xa7_\x14\x95\xa1\xbb\xa9\xb1\xa6\xb8d\x92v9\xb0\xf6Ɗ\xdba\xd7\xe0\x8a]\x1a\xcbq\xeb\xaf/\x9d\x112\xbf\x876\x9a\xa5\x10\xfb\x96f\xc5i\xd6\x0e\xa0v\x96\x10\xf0\xf5j\xf3\xca\xd2\x01\xb7\x15K\xb1t\r\xc4k\t\xa1\xd4\x1cE矘y\xdcz\xa4\xb6\xe7\x95;\x80\x01\xd5!D[\xe0v|<{\xc2\xdcSӔ\xd3\x18\xdbg\x15\xd5s\xf5%\xb32U\xbbٙ\xb3ܜt\xd5v\x81ި\xbe}\x11\x99N\xb4džSQ\x90\x86K\xa9G\xaeAt\x9c\xac\x9a5\xb7\xaa\xaa\n\x9fm\xd1v\xa3\n\xbcz\x8c\n\x8a\xc2'T\x9eY\"\xfc:u^q$$9\x1c\x8eۊds\xa5\x89\xb7\x15\x14\xd8\xcc\xcdt.\xed<\xfaӼ\xf4\x135e\xb1\xfc\ve\x80\x8c\xa0(\xa5\xc9NE\x91\x8a=JK\xbc\xdc)\x94X\x93\xf6\vzh\x8bJ.\xf8\xa1\x17)\xea\xed\xae\xae\xb4%Xl\xbb\xd2\xe6=\xec\xbcl\xd9\xf7\b=\xdag\x11J0\x03\x84r7y\x87\xb8\xb6f\xfe\\ww\xf7\x05\xac(\xb2i*\xeeE\\\xc1\x9f-\xf8G\xf8\xae%\xa1\xe2\xcc\x06\xde]Q\xd8\xf5.\xcb\xe8\xee.ND\xce\t'q\xfa\x85\xae\f՚W\u007fUS@f6e\a֛\x8eJ\xbe\xc0\xe1\xf8ypź\xf2\xf7Θ5q\xfa\xaa\xa5\\\x13e4\x8b(\x84\xbe=\xbf\x9d\xc3\x17(\xdaK\xed\x00jg!\x94\x1e\xbd\xe7ܞ\xe8t\xe5\x8a\xe5X\xba\x86\xb2\xd5\xe8\xaa\xed*ZY\xa6\xec|\x83\xc3\x11C\xd6\xc5\xde\xf3\xca\x1d\xc0\x80\xea\x10m\x81\xdb63ls\xc9\n\x8e\xcbD4-K\xb97\xb8\xdfr\x8b\xef\xa8u\xf3ɻ\x8b\x8a/\xec\xe4\xf9\xaf\xe9\x8d\xea\xdb\x17\xd1Ӊ\xb6\xe7ޱ\xdfMR\x19\x19\x1a\xab(l\x97R\x8f\\\xe3\x90\xcez(\xbbQ%\xde=FQt\xdc߄\xdd\x12G\xd2̳\x9e\xe8e\u0090\xff\x89-Q\x91K9\x8f\x96\xc6\xe1\xafg\xa9\xa5ϭ\x06\tAQ~\x89\xf9\x85(\nU\xac\x82\xfc\u0088\xa7\xf0\x8f\v\xfe`\xe2-\xd5\xc8\xcd\xd1t%\xff\xc934\x80O82\xf0\x8fhZ\x86z\x00:\xc7\xffU\\[\xb3\xf3\xf7\xa9Yi\x9a\x1am\x11~\xa2\xd3q7\u05fc'\xfc\xa0\xf5}\xe8\xa6(*\xf5.\xc3U\x91\x1fK\xf1\xf4P<Y\x92+\xeb\xb6%w\v\x83\x92j\xe2E$9\xb0\xd2g=\x83*\x16ν\xd9FΞe\xa3Y\x1a\xb1o\xe9x\x80\xa1\xb2\x03\xe4\x9du\x81\xfc\xd0א\x19 y\xc5T,U\x83#\x16\xe5\x98r\xd0\"\"\xca\xd4FE(\xc6uN\xcc\xda\xf3n\xb1,\xa4\x0eQ\x16\xb8\xbf\x9f\x84\x9f;\xbe\xcaMQ\x10:<\x8e\x1bG\xc6-\xecn\xa6\xe3N\xa0,AQ\xe8\x8d\xea\xd3\x17\xd1Ӊ\xf6-a\xf8\xa7\xe6\xaee\xac\xa2\xb0]J\xdds\rDR\x14ڰ\x94\x85\x8a\xc7(\x8a\xc6ǩsV\x81\xad(\xe4t\xa2\x94\u007fL\xe7RΣ\x0f\xad˲\xcan\xf6\xf5\xba\xd7 !(\nJ.&\x8aB\x15k\x8c\xea~^\xf1\xe4E\xb4\xf3\xbalwM2\u007f\xce\xcd\xd1te\xb4\xebǯ6\xe69zn\xaeE\xaa\x01贰\x12B3\xff熆\x86b2\x8fB\x99\xa6\xe2\x1fk\xd2\xcd'\xe2e\xe5=n\x8a\xa2Rﲔ\x86\x86tOEqU&\x1c\xb7\xd4E\xceByӲ\x15E\xb3Xx\xb03)\x1b\xcd\xd2ྜྷM\x8c\xb9\x8fTw\x80\xbc\xb32\xde'E\x96oC\xf4\x8a\xa9X\xba\x06\xfeyR\xfa\x9aN\x9e\xf4\x9aڨ,EQ\xdb\x01l\xa4\x0e\xc9\x16\xb8\xfd\xa1\xe4Jy\xbd\x9b\xa2\xb4\xad\x1a?\x8d\x9b\x1a\xfcQ\xabJ7\xfb\xcc\xd8UAX\xa6T\x14\x9f\xbe\x88\x9eN\xb4M\x87\xb3g\x87\x8d\x881\nۥT\x99k(\xf2̬l7ʆ\xed1J\u007f\xe3U\x14\x85|\xa9\x1c\xfc5:\x97v\x1e}R\x96\x9a\xc0/98\xe0V\x83\x04V\x94\x13+\x89\xa2PźM\x8d\xc5\xfc\xbe\xdbQ\xc2ou\x039\xc3\xefKLqs4])MȼXt\x1a\x9d\x8e\xedC\xaa\x01\xe8\xaa\xeb셚G\xa1MS\xa5n6\x88\xa7G\xee3\xb3*\xf5\xe2y\x94f\xf1J\b-\rR\xb2\x98\xa7.\x89\x9f\x92\a\xd7lE\xd1,\x16\x1e\xeeLPF\xb3\x14\xa4oO\xa2\xb0$\xaa\xec\x00yg%\x92\x9e\xa0\xe4D\xa4h\x83\x1cK\xd5\xd0\x17\xddl\xbefn6\x89\xbf\xee\xf2Fe)\x8a\xda\x0e`#uH\xb6\xc0\xbdő\xa3\xa5\xddMQ6\x87e\xd7s\xf5\x99a\x9f\xabt\xf3\x818q\xdf\xe9\xa6(>}\x11\x99N\xb4U\x9e\xbe+\"\xc6*\nۥT\x91k,DQ\xecM\n\xbb\xd1A\xe1\xa1(\x15\x0f\x95\xc9\xe8,\xfc\xb9\x8c\u007fF\xe7RΣ\r9\xc2.|R\x19S\xeaV\x83\x04V\x94\xe7\xe6\x1aq\x8c\"\x1b\x96&T\xae[\x93p\x1a\x9f\xfbX\xc9\x1aP\xce{n\x8e\xa6Է\"+\x05}F\xa2\xd4\x02\x9e\xbb\xaeYQ\x8aB\x9b\xa6J\xdd\xfc\x1bO\x1a\x9a\xee\xa6(*\xf5J3\xb3\xce\x1a\xf6\xb8IC\rOݧ!9\xb0z(\x8a\xaf\xc5\xc2\xdfv\xa5d\xa3Y\n\xb1o\x16\xfcc\xad\xb2\x03䝕\xf1.\x99}]\xee\x03\xcf]\x00\x00 \x00IDAT\x86\x87'\xf2\x8a\xa9Xž\xf8ʊ\xac\xc5\uf455(\x8eE\xa5\xa2\xb8\xedy\xf6\x0f\x88\x02\xa9C\xb2\x05n\u007fȧ8\xa3\xce\xfd\xac\xa7\x87\\\xeb\xc1clf7\xfb̤)\u007f\x91\x15\x85lT\x9f\xbe\x88L'\xdaa\xbdփ4\\J\xe9\\\x83\x89\x8cD\xe8\x1e\xb6\x17\xa5\xecF\x95x\xf7\x18U(JR\x12B\x8f\xc4\xdbB\xe4d\xf4\x12A\n:\xdfMR\xe4RΣ\x05\xe2\xcd\x1aI;\xdcj\x90V\x8c\x15\x05\xa5\xa7aE\xa1\rKӲL\x17\xf8\x9dx\xc7\xc7Z\xf1׳\x0f\u007f\t\x14\x8e\xa6\xd4\xf7\xf5\x87\x98\x9fc~\xc0\t\xb5\x00\x94\xfa\x9ex\xef\x04\xa5(\xb4i\xaa\xdc\xcdD\x9b\xb0\xb6\xdb1n\x8a\xa2R/\xa5(fᄢ\xef\x0fn\xd2\xd0iM£\xec,Q\x13]\x0e\xac\xb4\xa2\f\xaa\x98<┍f)ľ\xc5e5\x16\xa8\xed\x00yg\x9d#3\x1d\x95\xf8T\x92Z1\x15K\xf789\xf13\xf4Y\xe2\x06\xb2\x12\xb6\xa2\xb0\xf6\xbc2\x96i\b+u\x88\xb2\xc0]\x1c\x86o;Y\xea1\x8f\x82\xeeL\x12/C\xb2\xbb\x99\x1a+췁t\xa2(\xf2F\xf5\xe5\x8b\xc8v\xa2\x1dVE\xd1r)\xa5r\x8dfc\xf0\x96\xc27C\xef(\xedF\x15x\xf5\x18\xfd\xd9a\xdavu\xe0\xe66\x13\xbe0!|\xe9\x8aO\u007fb&\xc2.'\xa3\xf9\xd5\xd5e\t\x96\xbf*se\xe7\xd1\x02\u07bc\ufb10\xacU\x06H+\xee\xae\xe1Ot\xa2Z3\xb9\xd6C\x19\x96\x1e4[\xfa\x12\xc876\x96\xb7\xee\xbb \x14\xbbM\a\xbc\xf8\x81\xcc\xd7\xdf\x17\xdb\xd9g\xdd`\x15\x15C%\x00ݎ\xfa3~\xa3\uf655MS\xe9n6\x9bm\x05{\x16E\x99*\x9a\xd1C|\xcfl\xb1á\xe8\x10Uo\xf7ո\xe4+\xae\xdbh\x12\xe3\x0e\x16$\xf2B1\xc56\xab\x8dY\xfe\xf5\x85,\xe7-\xff.\aV\xf1Z\xcfվ\xc1\x15\xeb9E\xae\xdc5\x91<\xcahV\xa6\x91\x1c3뒷\xbd\xaf\xb6\x03\xa8\x9d\x95\x16\x95s6'*M\xb9\x8f\xe9Xj_d\xcd;\x88\xbe\x9a'\xe8\x1b\xbdQ{\xaf:\x1c1\xdb\x1c\x97\xc9\xc4+cϻ\xed\x00OCXE\x87d\vܖ)\xd33\x0f\xbc\x15\xec\xa9(.\xd8\xdd\xfc\xd9j+=\x91\x12C\x14Eڨ>}\x11\xd9N\xb4\xe7Y\xa7B\x18#\x14EӥT\xce5\x9a\xae\x0f\xc2B\xe6\xe2\x13B\x85\xdd(\x8d7\x8fQ\xb4S8\x055\xfd\xc5,\xbc\xee\x14>ug-\x8aIj \v\xe4d\xf4\xae\f\x8b5\xfdg\xb7\\\xd9y\xb4bM\x81\xcddM\xaau\x0fp\xad\xb8v\x1e\xbe\x8f\xa4/QT\x04ٰ\xb4A\x18\xd6\x1e4\xe3\xd8?\x94\xe5,7ǥ\xdcV\xd4\xdb\x18EΏ\x93źPqt\xb13\xa5\x12\x80\xf6\xc5\xe0\xff\x05\xd1\xff\xeb\x91MS\x15ݼ\x9b\xb2hYN\x85IH\xa6;O\xc2SU\xea%\xff\xeb\xa9t\xd6\u007f7)Ʋa\x8fP\x83r\x9b\xddN\xb5Y\x12]\xf7\xe6\x89\x0e\xac\xdd\x16R\x83\xe9\xf6\xe0\x8a]\n\"3\r\xa2\xfe\xd3F\xb3.\xf0}9_\t\rL\x88=\x8bTv\x00\xb5\xb3\xfaJ?4\u007fXڧ\xdcNJ\x9d%\xef\x8bs\xe6FAi\xcf(7\xeaObZ\x94=ƞw\xdb\x01\x9e\x86\xb0\x8a\x0eQ\x16\xb8\xad\xf1\xd3C\xde<\xaf\xaa(*\xddD\x8f3l1\x9f4\x10E\x916*R\xd9\x0et{U\x9ch\xef\x8d}\xe7ҽ~\xe4\x89\x11\x8a\x12\xd0\xd07Վd\x06\xb2L\xd5Z1C\xceK:\xb0\xbed1O\x86sgy7\x84u\xa7C}\x8c\xe2\rqfv0\xa8:\xd1\x16\xce\xe6\xe0i\x06\xc3\xc1p~I\a\xc5@\xb1\xed\x17\xad\x98!\xe7%\x1dX_\xb2\x98\a÷\xb34\fa=0JQ\xbc9\xd1\u07bb\xd4\xc2\xc8\x05E\x19b\x86\xefK\n\f\x9a\xe1\xdbY\x835\x845JQ\x06\x0f(ʐ\xf2\x80L\xebiE\x01#\x82Q\xb4\xb3\xae\x1f\xe6V\x9db\xcdbx\xe7\xee\x05~\xd7\x0f}hH\x01E\x19Rȴ\xde}\xad(`D0\x8av\xd6\\\x8e\xe3\xc6^\u05ca\xf2`\r\xee\xe1]\xad\xa8W\x03\x14\x05\x00\x00\xfd\x00E\x01\x00@?@Q\x00\x00\xd0\x0fP\x14\x00\x00\xf4\x03\x14\x05\x00\x00\xfd\x00E\x01\x00@?@Q\x00\x00\xd0\x0fP\x14\x00\x00\xf4\x03\x14\x05\x00\x00\xfd0HQ\xbc\xb9\x94\xf6\xe49\x1fl\xb0W\xbd\xbc\u007f\xa1\xb3\x91$\x00\x8c\x1c\x8cQ\x14\xaf.\xa5]\xd9\x17[\x04\xceg+\x9f3쇸\xbc\x1f_\xc6H\xf2\xd9\xcf\xea\xcb^\xd1k\x15\x00\xf4\xc3\x10E\xd1p)\xad{*\xa4\x9e\xe6\xa9<\x13ʏ\x90\xbc\x1f\am$\xd9WfY\xa7\xbe\xf4\x95\xbdV\x01@/\x8cP\x14-\x97RBɁ\xe1x\x86\x9b\xb1\xacT(\xca \x8c$\x1bW\xf3)\x0f\xd4\x17\xbf\xb2\xd7*\x00\xe8\x85\x11\x8a\xa2\xe5R\x8a\xa9\xcf\xd6\xe7\x999#\x83\xc7鱶\x9c\x9cXs5\xe5vI{?j\x19I*\xe9\xdc\x15e;\x8bԠ\xbcV)_\xcb\x15\\P\x1ej\x1aω\x8f\x83\x97-.\x01`h1BQ\x90\x86K)&\xbf\x9cUl\x94һ\xdcZ\xba/\xc6\\\xb6\xa1\x98r\xbb\xa4\xbd\x1f\xb5\x8c$i\x06N[M9\xe2\xf3\x9f\xbb\xef\x8bPn5\n\xafU\xcaײ\xa5j\xdc&A\xc1\xe3\x83q\x88lq\t\x00C\x8c\xb1\x8a\xc2v)\x15h\xcaV\x1a\x94\x8fn\xaa\xf9F|N\x83}\xf9h\xb7K\xfa\xac\a\xe3\xcdHRf'\xbf\xb2ٙLr\x0es\xd6 %\xd4Y\x8f\xe4k\x89\x82\x05EA\x9b\xb0\xa2P\x16\x97\x000\xc4\x18\xab(l\x97R\x81r\x9d\x1e=<2ȱ\b/\xb7\x89\x8b\x1b\xedvI+\x8a\x96\x91\xa4LE\xf4\xa2\n\xe7\x83\xc5n\x9f\x11q\xf3ZW(\x8a\xcbגR\x14\xd9\xe2\x12\x00\x86\x1ac\x15\x85\xedR*\xb0{\x18ܿ\x86\x8e\xe2y\x8f\xf1\xe8\x04\x0f-h\xb7K\xb7\x99Y\xafF\x92\x14w7\xf0\x89\xcd\xc8\x1b\xb4\xa2\x84\xbbR\xb2\xa2\xc8\x16\x97\x000\xd4\x18\xab(l\x97R|=\xd9\xf5\xcb\xea\x17<\x8cJ~ؘ\x90\x88\x1f\xe8I\xbb]\xcaޏ\xdaF\x924\xd4L\n\x1b\xc9k\x956\xea$\x8a\xb2\x1e+\x8alq\t\x00C\x8d\xb1\x8a\xc2v)\xc5\xd3(\x83\xf1*\x19\xf1\\\xe3\x97\xf0\xfc:r\xb9\x97v\xbb\x94\xbd\x1f\xb5\x8d$\x95t\ue2b2\xd6x\xe4JH^\xab\xf4p%\xf4ca\xebF`E\xa1,.\x01`\x881BQ4]JQ}\xf6\xa0\xac\x05F:\xd7bj\xce9\x1e\x88\xcf\x1c\x97\xdc.\x11\xe5\xfd\xa8m$\xe9N\xf3\x1a\xdaO\xd7\r\x97ת\xc2\xd7r\xee\xe4/>\x8f\xe0\xc6\xe6\xd6\xd3\x16\x97\x000\xc4\x18\xa1(\xda.\xa5M\a\xbcV0ڸb\xc23#\xa65x\xf6Cr\xbbD\xb2\xf7\xa3\x0fF\x92\x83\xc2嵪\xf0\xb5\xbc\x1e\x192q\xfe\x1f9\x0e\x1bK\xc9\x16\x97\x000\xb4\x18\xa1(\x81\xc6#\xf3\x8eG/^<\xf9\xe9\xb3EO\xb4B\x19\x18`\xd2\x04\x00C\x06(\x8a\xfe\x9c\xb6\x88C\x92\xbeX\xf7\xbb_}\x01\x14\x05\x18̀\xa2\xe8ϵ(\xf1bos\xd4\xcb<\xaf\x00\x14\x05\x18̀\xa2\xe8O_\x86yGum\xf5\x0es\xc6KX^\x1aa$\t\x00C\x06(\xca\x100pf\x83\xd5dM>\xfb\x12\x82b\x88\x91$\x00\f\x19\xa0(\x00\x00\xe8\a(\n\x00\x00\xfa\x01\x8a\x02\x00\x80~\x80\xa2\x00\x00\xa0\x1f\xa0(\x00\x00\xe8\a(\n\x00\x00\xfa\x01\x8a\x02\x00\x80~\x80\xa2\x00\x00\xa0\x1f\xa0(\xa3\x99C\x11#\xef)Jm\x11\x87\xb4B\x8c\xe7L\xe2\xa3\x11\xda2\xbf\xc3 E\xf1\xe6R\x8a\x1f\xe7~\xc0~\xe0$\xb8?\f\x96\xcd\xdcF\xf2\u07bc\xc1lM\xab\xb5>B\xdbx\x9e7\xfbv\xc3m\xed<>\xb1\x0f\x9d\xe0yoΆ5qg\\ɿ\xedX\x12\x93\xdc\xe7\x9e\xcbbs\xd0\x17\xacl\x83\x1b\xa9\xe0 _\x80\xef_Vi\x19\xa0'\xc6(\x8aW\x97RԖWX\u007f\xab\xfe@\x9e_=\xc7\xcd\x002\x83v\x93\xf7\x1a\xf3\x1f\xca*?\xe4\xf9\xff\x8b\x1e8\x1c\xa5\xfcU\x8db\"\xdd5|\x8c\x03u\x9e\xe0k\x14^\x1d\xb2\x95*\xe6\xac\xf9\x84+\xf9I\xdc\xd7\xe9\xe6'\xee\xb9LJ\xc6n\xf7\xcc4\xba\x914\xa5Q\x15b\x82\xd92@W\fQ\x14\r\x97\xd2*\xe2\xb6ѓ\u007f\xdc[\x1d\x80;7Ư%\xef\x8f-)\xc2\xf1\xd6\xf9\x9ep\xb0\"\xec\xd3\xe1\xdb\xc1\x8a:\xf9\xf4m\b\xdd\xe7\xdd\x1f`\xbb\x9a~X\x9c\xf4{\xff\x98/E}\xaeP\xad?2\xae\x0f\xbe\xe5\x9ee|#e\xee\x9ar\\IF\xcb\x00}1BQ\xb4\\J\xcb\xc5'\xe4\x1f\xf2'\x130\x03\x88\x9f*\x9e'昉\xc9z1OL7\x06q\xb0֚\x9f3\x0e֕\xcc\xc7O\xde彞\xe9(\xe9\x98\xeaa\xe41\x9c\x8d̰Jn\xb0\x8c\x96\x01\xfab\x84\xa2h\xb9\x94\xb6\xe5\x1dk\xedi\xad\xca\x1by\xb3\x8c/͍\xb7\xc3\xc6MY\xd0▤ɝb\xc7o\xb7&:\xad/&\xd2\x16h\x8d&\x9e\xdfs7}YL\xf2\x8b}<\xcfW\xa2J\xe1u\x9f\xb2\x82\x9e\x89\x1f\x8b\x89\xf72\xc8\xdb\xe3brf \x1d\xac\x92=*B\x977\xd8L\xb1\xc96\xf2T~\xc9\x13\xb5\x93\xbf\xbf\xf2\x84\xf3`eZ\xa9>1\xf3|\x14~\xee6\xea\x8d\x15sw)r\xa9ʨ\xf6\x92\x05\xebCܟ\x1blh#\xcf\no{P\x81\xf0\x8a\x9f\n\xdek\x91\x86(\xac\x96\x01\xfab\x84\xa2 -\x97Ү\xf2\xec\xec\xec#~\xb4\xab\x8fM\b\xdf\\\xbe\x91۪L*x\x8b\x9b\x8f\xdfzvo\x17ɥ\x8d仫+m\t\x16ۮ\xb4y\x0f\x1f\xa5%^\xeeD\x9dW֤\xfd\xa2\xac\xe0\"wL\x8c\x8d*\xa6\xb3\xa5\x83U\xb2GE?\xcdK?QS\x16\xcb\xe3\xa3]\xf6D\x15\x0e\xd6\xd2d\xe7\xc1ʴRE\r\x0eG\f1\xfc@7\x1d\x95|\x81\xc3\xf1\xb32W\xae\x8cj/Yp\x92;\x85\x14\x18\xdb\xc8\xe7Wl;\x1e\xa1G\xfb,\x97q\xb9\x9b\xbcC^\xb3G\xcb\x00\x9d1VQ\xd8.\xa5=\xe5\xf9\xf5-\xf5\xf9\xe5\xf415\xaa\xe9\x9a>\xbf\vO\f\xb5)\x92J\x9a>\xbfA\xde\xef5\x89\xb8\x1bɯ\xe4?y\x86\x06\x9e!T\xb1\x9c|~\xbf\xc2-\xa0\x84\x13+\xb8/\x1a\x87\xb9p\x1d\xac\x94=ji\x1c>LK\xf1\xb3*)OT\xe1`\xfd%\xe6\x17r\xb0\xb2\xadT1.\xedP\x9eP8s\xa9ʨ\xf6bnqn\x8f\"7\xba\x91\x05x\xfc\x92.\x8e\x8b\xce\xf1\u007f\x95c=Z\x06茱\x8a\xc2v)=\x9e\x8f\x87'=\xf9'U\n\x8f:J\xb8\xef\x19I&M\x9c\v7\x0f\xb4\x95\xd1\xe2\xcf=j\x8c\xea~^\xf1\xe4Et\xa3[\xc9Bg\x89^\x13\xf3矲G}h]\x96Uv\xb3\xaf\x17ў\xa8\xf8`E\xc9\xc5\xe4`e[\xa9b\xbc*\nU\x19\xd5^\xcc-w\x8fe\xa3\x1b\xf9`\xde_P\xb7\xa5\x86\xa4O\vuHx\xb4\f\xd0\x19c\x15\x85\xe9R\xdao\x17\x0f\xba\xef\xed\xfd\xac\xa2\xa3\x90\xad\\\x17#ɦ\xaaH\xa4\xca-\u007f\xe5jg\xa2\xdb\xd4X\xcc\xef\xbb\x1d\xe5v\xfd\x14\x9dr\x8dߝS\x14\xbd5\xe4\xcdu\xb0\xd2\xf6\xa8O\xcaR\x13\xf8%\a\ahOTr\xb0\x9eXI\x0eV\xb6\x95*ƫ\xa2P\x95Q\xed\xc5|˹\xff:\x18\xdd\xc8\xe4\x1ct\xc1\xd2K\x92W\xe9i`ϖ\x01\xfab\xac\xa20]J]\x8ar\xd1o\x14\xa5\x9c\xbb\xc8H\x0e\x0e\xf9\x98I\xa8\\\xb7&\xe1\xf4r\xf7\x80\x8e`\xf1\xf66\x94\x13CfX\xaa\xf9G\xf8M\xfa\xf9\x97\xedQ\x1br\x84\xe4\x93ʘR\xda\x13\x95\x1c\xac\xcf\xcd5\xe4\xe7\x9fi\xa5\x8a\xd1\x18\xa3H\x95\xb9\x1d㟎oGJ\x8cn\xe4\x99E\xbdΓ\x1e\xf4<ڵ\x1c\xb1Z\x06英\x8a\xc2v)\xfd\x86\x9c\xf5t\xe5\u007f㭆\xd1DǔH<'\xf4\xc1*ERI\xd3\x177<\vR\xc8GhZ\x96\xe9\x02\xbf\xd3\xf9\x91*\xb6x\xa6\xa8\xc0\x8f-\x9f\t?\xc6}I\xcb\xc8'\xd7\xc1J٣\x16\x88s\x0fI;\x10퉊\x0fV\x94\x9e\x86\x0fV\xb6\x95*ƫ\xa2P\x95)\x15\xa5\u007f\xf6\x02W\xd2\xd5^\xa3\x1b\xd9\x1b{f\x91\xeb>\xdb\xd4\xf7\xa4;V\xa8\x96\x01C\x83\x11\x8a\xa2\xe5Rڵ?\xbf\xeeN]\xfe~\xff\xb9\xd8s\xf4\xf572K>\xe0\xecʤ\x82\x85\x9c\x97\xef\xf6\x8b\x1f\xc8Ռ\xfb\xe4\xc3A\xb3\xa5/\xc1u\xd4P\xc5~\f\xda\"&.\x98\x13+\xcel0]A\xe8!\xbe\x1d\xb5\xd8\xe1\xc0?\u07b2=j\x01o\xdew\xf6t\x06\x8f\x8f0\xc9\x13\xb5\xbb\x86?щj\xcd\xe42\n\xd3J\xb5\xf7\xaa\xc3\x11\xb3\xcdq\xf9\x99\xeb2\xcaU|`R\xb9re\x8a\xf6\xe2S=i`&\xb5\xd7\xd0F\xe2:\u07b5\xbcp\xb6\xe1vԟ]\xcd\xd9\xfa\xb2CF\xc0W\x8cP\x14M\x97Ҟo\x0f\xe4\x16~\xeb7\x97z\x04\xae\xbf3mbD\xa1{\x92&wr\xb6G\x9eDc\x14\x99HH&\x1f\x1a,\xfb\x04Ui\xf0,\xb6\xfeu\xe7\x9c@\xf3\x06\U000d253f\b\x89t\xe7\f\x04\x1e/\xc8\xf6\xa8\x15k\nl&k\x92\xf8\x93\xed\xf2D\xad\x9d\x87\xef\xd6\xe8K\xb4\xf6)be+U\xf4\x93\xd8\b\xbe\fu[H\xc2t[\x91KU\xa6h/:\x1e\xf2\x91\xd4F\xb9\xbdF6R\xe06\x9f!5b_\xcc\x151A\xb7\f\x18\x1a\x8cP\x14`\x88X5>_+d\x18\xd8?>~\x04\xfc8tF\xcb\u007f.\x1c\xc82\x91\x13\xa4\x91\xd12?\a\x14e4\xb3u\x9a\xfbm,\xc3O\xdb\xd4\x11\xf1\a\xdf\xea\xd8\x17\xf2\x87\x81b\xdb/#\xa6e~\x0e(\n\xe0\u007f\x14\xd4\x0e|\xe2\xf6\xa7\x05\xc0 @Q\x00\xbf\xe39\xbfz\xa7\xd5\xf3\xa1\x06\x80\x11\x80\xa2\x00\xfe\xc7>\xf3\xba\xdbZ1\xc0\xd0\x00\x8a\x02\x00\x80~\x80\xa2\xe8ϗL\xb4J\x01\x80?\x00\x8a\xa2?\xa0(@\xe0\x02\x8a\xa2?\xa0(@\xe0\x02\x8a\xa2?\xa0(@\xe0\x02\x8a\xa2?\xa0(@\xe0\x02\x8a\xa2?\xa0(@\xe0\x02\x8a\xa2?\xa0(@\xe0\x02\x8a\xa2?\xa0(@\xe0b\x90\xa2xw)\xed\xbfTh/\x94\"F=\xa0(@\xe0b\x8c\xa2xw)\xed/ʽ\xd8t\x9e<\xd8\xcd/piȟ\xfe\x0f(\n\x10h\x18\xa2(\x1a.\xa5\xdf۱\xf7\u05cfv\u007f\xb1RwJ\xc8?\xff\xe7\xff\x06\x8a\x02\x04\x1aF(\x8a\x96Ki\xc9\x11\x92\xcc\xf3\x97A\n\x11\x90\u007f\xfd\xaf\xfc\u007f\x871\n\x10p\x18\xa1(Z.\xa5\x85\xa2\xb3ġ\x12f\xe9ч \x1f\u007f\xfa\x1f\xa6\xff\xf2/_*\x10\x16\xdcM\x8d5\xc5%?@\xca$\x00\xf8\x11F(\n\xd2p)=\x99\x87\xe7g\xbbr\xfd\xc5\xed\xed\xcb/\xff忘\xfe矈\x8e\xfc\xe9\xff\x88\xfcIP\x94Z\xf3\xea\xafj\nx\xec\x85E%\x01\xc0\x9f0VQ\xd8.\xa5\x1d\xbb\x8bZ\xbbZ\x0ee\x8fć\xa6\xbe\f_\xfe\x0f\xfe\xbf\xfe\xabsd\xf2\x8f\xce\xc74\xff㗨ۖ܍Po\xf5cD'\x01\xc0\xaf0VQ\xd8.\xa5\xa8\xad(;\xdb~\xaa\xe8\x10\xbb\xec\xa8\xe3\xcb\u007f6\xfd\xe7\u007fv*\xca\xff\xfe\x17\x91\xff\xfd%\xba\xc0\xdftEPI\x00\xf0+\x8cU\x14\xa6K)\xa6\xab\xad\x1f\xe5\xf9\x8b\u007f\xa4\xa0#\xffM\x1e\xa5H\xf3(żd4J%\x01\xc0\xaf0VQ\x98.\xa5\x82\xb4\xe0\x97\xeb\xd9-̢\xa3\x0f\xac\x1f\xf2L\x8a\xa4(5\xfc5W\x04\x95\x04\x00\xbf\xc2XEa\xbb\x94\xd6g\xb7\n\x8b\xf6\x1e\xf3Z\xc3(\x82\b\b\xbe\xda\xf3\xbf\x14\x8a\xd2iM\xc2\xd6\xdeYY\x88N\x02\x80_a\x84\xa2h\xb9\x94\xfe\x98\xfdݝ\xef\xf3\x8a\x9ej\xd53ZpJȿ\xfe\xe3\u007fW(\n\xaa\x8dY\xfe\xf5\x85,\xe2\xc6G%\x01\xc0\x9f0BQ4]J/\xe6\xe7\x16]\xec\xf7^\xc9(\xe2K&\u0082۩6K\xe2i\x12C%\x01\xc0\x8f0BQ\x02\rUE\x01\x00\xbf\a\x14E\u007f@Q\x80\xc0\x05\x14E\u007f@Q\x80\xc0\x05\x14E\u007f@Q\x80\xc0\x05\x14E\u007f@Q\x80\xc0\x05\x14E\u007f@Q\x80\xc0\x05\x14E\u007f@Q\x80\xc0\x05\x14\x05\x00\x00\xfd\x00E\x01\x00@?@Q\x00\x00\xd0\x0fP\x14\x00\x00\xf4\x03\x14\x05\x00\x00\xfd\x00E\x01\x00#h\xf5\x9f\xbf\xc2z\x05\x14\x05\x00\f\xa0gҍ\xa7\x01\xa1)\x06)\nå\xb4\xe5\xc8^{\xfeI\xf2\x88\x03\xd4r(\xf7\x88\xbf<\xc1\xcd7\x9a7\x98\xadi\xb5\xd6Gh\x1b\xcf\xf3\xe6\xbbZ\xe1\xc0h\xe7\xe9\x98\t\xdfw\x04\x82\xa4\x18\xa3(\f\x97\xd2{\xd9%\xf5w\xea\x0f\xec\xc5\xcfY\xbac\xaf\xbaQe\xbf\xe3\xb5\n\xff\xa2\xc6\xfc\x87\xb2\xca\x0fy\xfe\xff\xa2\a\x0eG)\u007fU+^\x8dg?\xab/;zQ}\x19`4\xedc\xc6L\xbc\xe47\x0f\x15\xf3\x82!\x8a\xc2r)\xbd\x91\x8d\x15\xe4)N\xf6\xef\xc5Ϭ>\xb97\x10\x14\\\xe4\xb1%\xa5\x1b\xa1\xce\xf7\x04E\x11hxYE\xe9+\xb3\xacS_\xfa\xbb\xc5\xea\xcb\x00\xa3i\x1f\x13\xff\x9b\xb0\xfa\x00\x90\x14#\x14\x85\xe9R\x8a\xc8\xc6mŏ\xab\xae\xb7cK\xb0\xa7҃\xf1\xfd\x9f\x1c3\x19[\x14\xf3\xb7\xf1\xdb\xcb*J\xe3j>ŋ+a\xf8;\xea\xcb\x00\xa3i\x1fSx\xfe7S\xebe\xf3;\u007f\xc5\bEa\xba\x94\x92\x05\xb7\U0008b10f\xe5\x87ɧ\x92\xa3\xac£\x92\xcb\x1bl\xa6\xd8dۀpZ\x92j5\xd9R\x1a\x85\xbc}<\xcfW\xa2J\xe1u\x1fz/\x83\x84=.&&\x1b\x92\xa2\f|\xbdڼ\xb2t@Y\x03\x1a\xa8H4'\xecz\uef8e\xce]Q\xb6\xb3\xee\x99\x12E\x9cH8B\x97\xc6r\xdc\xfa\xebKg\x84\xcc\xefY\xc1\x05塦\xf1\xdcl\x12\x93\x17\x11:k\x95\xbf\xd8\u05cft\xda\xc7\x1c\xf8\xf5\xe4k3\u007f\xf4{I1BQ\x10ۥ\xb45;;;\x17\xcf\xcc\x16\x8aF='\v\xd5J\x8f6~\x9a\x97~\xa2\xa6,\x96\u007f\x81\xd0Y>\xa3\xb6:%\xaa\x01\xa1Gi\x89\x97;Q\xe7\x955i\xbftG)\xecI%EI\x8f\xdesnOt\xba\xb2\x06\x94\x11\x95u\xae4ne\x9fb\x15\x03\xa7\xad\xa6\x9cN\x92\xec\xbe/\xa2\xb0\x00\xea8Y5knUU\x950\xee\xeb\xca\xdf;c\xd6\xc4髖rM-U\xe36\t\xba\x1e\x1f\x8cC\xe2\x83>(\xd9>9<p\xce5\x87\x95\xf61\xf9\xbf\xfez\xe4\xb5\xd97\xfc]R\x8cU\x14\xa5KikK]\xfe\xdevi\xe1wy\xaa\xc5G\x19\xa5qX\tJ-\x82\b<\xaf\x16\x0e\xfb\x81\xf7S\x84\xcf\x15\xcb\xc9\xc2\xf7+\xd0}^\xf1\xccj\x97\xa2\\\xe0k\x10\xf6\U000b9828\xe1,_Ab*\xe9\"h'\xbf\xb2ٙLr\x1a\xa1\xaeAJ\xa8\xb3\x9ep\xee\xcd6\xf1d3XP\x14\xb4\t+J\x11\x97+\xbc~\xcb\xedG\x80\x01\xb4\x8f\xd9\xff\xf7_\u007f-|-\xbc\xc9\xcf%\xc5XEqw)E=\xf9\xe5\xc2\x18\xa5\x8a\xa4\x8f\xf9\xcd\x18\xe5\xa1uYV\xd9\xcd>lɃ\x1e\x97&\xbfk\xe1?\x14R\x8dQ\xdd\xcf+\x9e\xbc\x88nD\xbd&\xe6\x18%\xe3}\xf2\xb6|\x9b\xa2\x86\xb4w{_\b\xd82\x14\xab\xa8\x88^T1 &o\x9f\x11\xb9\x8d\x94Њ\x12\xdc\xe4LɊ\xb2xf\x0ffZ<\x02\f\xa0}L\x9e\xa0(\xbf\xe6\xbd6\xb7\xa9\a\xf93\xc6*\n\xe5R\xda%\x8e\xb6/\xd9\xfb\x9d\x16\x83\xe8\xd07̢\xa3\x91'e\xa9\t\xfc\x92\x83\xc2!\xdf\x10g\xcb9\xedX\x87\x15\xa5\xdb\xd4X\xcc\xef\xbb\x1d%\x9c\x9d8\xe7QzkțKQ\x12S\xc8[r\xa2\xa2\x86\x0f\x9dC\x90\x14\xe5*\xeen\xe0\x13\x9b\x917hE\tw\xa5dE\x99\xe3\x9ciy\x8bQ\x14Н\xf61\xbb\xff\x03KJ\xe6\x98\xf9\xfe-)\xc6*\x8a\xecRڟ'\xce\xc3~/(J}6\x1e\xb9\xb4e\xfb͵\x9e\x86\x1cA\t\x9eTƔ\"\x94\x90\x88\xa7TS\xb1\xa2\xa0\x84\xcauk\x12N\xe3s\x9f\x9c\x98_pF5\xff\x88\x84\xbb\xc6(\uf489\xd8e\xe9\x8a\x1a\xd2\u07bdFx\xec\xb6\x12j&\x85\rQ\x14;\x19\x9c\x84\xbf\xed\xca$\x8a\xb2\x1e+\xcaҙ\x17\t\xad*\xc5\x01]i\x1f\x93K\x14\xe5\xd7/Ƽu˟%\xc5XE\xa1\\J\xf7\x1e\xc1\x19䬧\x9f\x18\x94\x1e\xf5\x9f\xfbQ\n\xf0T\bBI;\x10\xb2\xa5\n\x89\xbe\x95DQҲL\x17\xf8\x9d8\xe3\xb1\xe53ᄦ/i\x19\tw)\xca92WRɟS\xd4P\xc3W\xe3d\xceA\x8f\xd5t\ue2b2\xd6x\xe4JDF\"t\x8f\xcb\xc7Iy\xb8\x12\xfa\xb1\xb0\xbd#\xb0\xa2\x1c\x11\x17\xfd\xf1svi@_\xda\xc7\xd8\xff]\x94\x94\xf5c\x96\xde\xf1cI1BQ\x98.\xa5?f\x97\xd7ߩ\xcf'\xf7\xcc\u07b2\x1f\xbdq\xcc~K\xa3\x9a\xd1C\x01o\xdew\xf6t\x06_\x8b\x93\xa9\xa5\x05+\xf9د\x04\xd18h\xb6\xf4%\xc4\x14\xe0\x88\v\xe6Ċ3\x1bLW\x10z\x88\xef\x99-v8\x1e\n\xb9iQ9gs\xa2Ҕ5\xa0\x9cyi'\x84\xa4rfV\xa4yM*#\xd7\xc9\xc6\xe0-\x85o\x86\xdeA=\xa7\xc8e\x1fq&e\xee\xe4/>\x8f\xe0\xc6\xe6\n\xe3\xc1\xb5\xdc\xe2\xfcC\xf1\x9c\xdḟ\x8fl\xda\xc7d;\x15\xe5\xd7U\xaf\xadh\xf1_I1BQ\x98.\xa5\xa8\xe5\x9b|{\xe1)q\xe2\xbb\xe5\xb0\xfd\x90\x1f\xfd\xaf\xa7bM\x81\xcddM\xc2r\xd0W\x9c\x10\x1d\x97V\xf1\x9e)I\x18\x8bX\xf6\t\xaa\xd2@B\x9a7\x98\x97\xa4\xfcEH\xa4;\xa7I\xc8X\xa6\xf4C\xf3\x87\xa5}\xca\x1a\x84QʺX˚\vj+S\xa5냰\x90\xb9\xdf\"t)\x88̗, \x99\xd7#C&\xce\xff#ǭ\x10\xd2G\"\xc3&\xcd=\xec\xbd\x12@'\xda\xc7d\xfeۿ\xff\x87x\xdcĿ\xb6\xca\u007f%\xc5\bE\x01\x80\x80GP\x94\xff\xe7\x1a\xa4\xfc\xfa\xf6kk\xef\xf9\xab\xa4\x80\xa2\x00\x80\x01\xb4\x8f\xd9ޏ\a)\u007f?y\xfc\xf8\xf1c\xaf\xbf\xb6\xb1\xd5O%\x05\x14\x05\x00\f\xa0}\xcc\xd6\x1e2H\x996\x86\xf0\x9b\xedm~s%B\x01(\n\x00\x18@\xfb\x98-]\xe8\xdf\xec\xff\xfek\xf9\x98\x05\xff\xb4y\xf3\x16\xfb7~\xfaP7P\x14\x000\x80\xf61\x9b;z6\xbe\xb6\xf9ᅫ\x9ft\xb8\xbe\xa9\xa9\xa9\xd5O\xef\xc6\aE\x01\x00\x03\x10\x14\xa5m\u0558\xff\xf4\x0f\xff\xfe\xeb\xde\xd72[z\xfa\xfb\xfds\x84\x02\x8a\x02\x00\x86 (J\xfc\x987>~-\xf3\xef\u007f\xff\x87Yu~:>\xc1\x80\xa2\x00\x80\x01\xb4\x8f\t\x1d3g\xf7\xa9\xd9\xdc\u007f\xfc\xba\xf97\xf9~:\x87\x82\x01E\x01\x00\x03h\x1f\xf3ZD^]k\xf9k\xb9\u007f\xff\x8f\u07fc\xe5\xc7\u007f\x16\x04E\x01\x00\x03h\u007fma~}G\u007f\xdbl\xee\xdf\xda~\x13Y\x0f\x8a\xc2D\xabr\x00\x00D\x9e\xfe\xd3qAPP\xcf\xe1\xdf\xfc\xa7\xdf\xfcç?\x82\xa20Ѫ\x1c\x00\x00\x91\x9e\xb6V\xf2H\xa0\xf6\xa2\x88\xf9[N\xc2<\n\x1b\xad\xcaG:\x8b\xb9\xb0\xdf\xfb\xcdCY\x80\x91\x8d\xf3rq\u007fۍ\xba\xeb\xfez\a>&\xa0\x15\xa5\xe5h\xee\xec0\xf1a\xf0m\x11\x87\\\xb9T\x12\x00\xf4\xa6\xbf\xa7\xa7\xc7\u007fG(\x86)\x8a\x86K)\x1d`,ǸKbbs\xd0\x17\xae<*\t\x00\xc0\xa00FQ4\\J\xa9\x00\xa3\xf9\x96;\xe5L\x95\x8cݎ<\x93\x00\x00\f\x06C\x14Eå\x94\x0e0\x1aYQ\xd0\xfa\xe0[\x8c$\x00\x00\x83\xc0\bE\xd1r)\xa5\x02\f\x87R\x94\x8e\xa9\xf1\x8c$\x00\x00\x83\xc0\bE\xd1r)\xa5\x02\f\xe7\x12wLJ\xaf\x0f\xe9b$\x01\x00\xf0\x1d#\x14\x05i\xb8\x94R\x01\x86\xd3\x13\x16q\xf2\x8eS\xe4N\xca\xe3\x15*\t\x00\x80\xef\x18\xab(l\x97R*\xc0x\x0es\x1c\xb7PL\xde\xe2\x0e\xb8r\xa9$\x00\x00\xbec\xac\xa2\xb0]J\xa9\x00\xc3\xe9\x98<c\xeb7N\v\xcf[\xb2\a\xf0-\xb0\x03\x06\x80\x97\xc1XEa\xbb\x94R\x01\x86\xf3-WN\xa5O2\x92\x00\x00\xf8\x8e\xb1\x8a\xc2v)\xa5\x02\f\x87\xbaփ>\x1d\xdf\xceH\x02\x00\xe0;\xc6*\nۥ\x94\n0\x1cJQ\xfag/`$\x01\x00\x18\x04F(\x8a\xa6K)\x15`4\xa7dE\xd9\xca]d$\x01\x00\x18\x04F(\x8a\xa6K)\x1d`$=-\x17\x17\a\xbb\xdcQ\x8f\x87|\x84<\x93\x00\x00\f\x06#\x14e\xc4\xf2\x16\xc7\xcd8\xe4L\xef\x1f\x1f\xdf\xe3\x99\x04\x00`P\x04\xb4\xa2\xb4\\\xbc\xe3J\xb6M\xfd\x82\x91\x04\x00`p\x04\xb4\xa2\x00\x00\xa03\xa0(\x00\x00\xe8\a(\n\x00\x00\xfa\x01\x8a\x02\x00\x80~\x80\xa2\x00\x00\xa0\x1f\xa0(\x00\x00\xe8\a(\n\x00\x00\xfa\x01\x8a\x02\x00\x80~\x80\xa2\x00\x00\xa0\x1f\xa0(\x00\x00\xe8\a(\n\x00\x00\xfa\x01\x8a\x12(\x9cI|\xa4\x15\x12\x10\x90\xed0\xb4N\xb4\xee\xab\x18ڵ\x8d0\fR\x14\xef.\xa5\x1dU\xf9\xf6C\x97\xe0\xff\xbe\xbeS\xcc\v\xccK(\x1b\x10?\xd6ĝq\x8f\xd8&\x04\x98\xefʟ\x0f\xf2\x058\xb8>,\x17\xd9î\xbbG3\x19L,\x8b\xc6(\xa1\r\x19\xd2GF#u\xa18\xe6\xcfR\xfa\xbe\x89_\ue664qn\a\xb6\x13mc\xf2\"˚\xda\xf7\xaf0\x16\xb9\xf0\xa1\x17\x9e\xab\b$\xdf[c\x14ŻKi{\ue87a\xa6\xf3\xbb\vAR\xd8\xd4^\xf3\xc8z|\x90\xafp\x9cK\xe3\xf7\x89\x1fϚO\xb8G<p8J\xf9\xab\xd2\xc7Ҩ\n\xf2^έB\xab\xb8oH\xfa\xa8\xc6c\xa5\xe8X6\x8c\x96Q\xbc\xb8\xba\xf2}\xc7C\xe9#\xa3\x91Z5\xf8ć\xa6\xf7\xa5\xf4\xc0\xd5mўI\n\xd7v`:\xd1^3\xa5\x9c\xa8\xfc\x8c\xe7\xab\xf1\a\x95\x961{\xa1\x80\xb5\x8a\x00\xf2\xbd5DQ4\\J\xbf\xc9\xc7Ϛm\xb3\x9f\xf7VG\x00\xb3:\xd53\xaf\x86o\x16\x0e\x9a\x9d\xfcm\xf1c\x9fg\x04B\r\xb2\xa2\xdc5刉\xf3\xdcF\xb4\xd1\xf9\x84\xba\xdf-f\x95\x92\xa1cٰZF\xf3I\x12\xfd\x89\xd5H\xad\x1a\xb4\xe9\x8cJ\x8b\xea\x94?\x16D\xb3\x92.\xa4\xed\xc0t\xa2ݰN\x18[\fl\x13\x15E\xade\xccMM\xc1^E\xe0\xf8\xde\x1a\xa1(Z.\xa5\x85\xf9d\xe1\xd1\"v\xf1\x80g\xa5\x9a\xa2\xa0n\xcbN\xcfE\x12\x94\xa2dX\x9f\x8b\x89\xeb\xdcV\xb4\x9d\xbbA\xd2\xe1\xef0\x8bIбlX-\xa3Q*\n\v\xad\x1a\xb4\xa9\xe5\xaf\xf1\xb5\xf2G\xef\x8a\"m\a\xa6\x13\xed2\xa2\x05\x8d\xfci\xfc\xf6\xb2-c\xaf\"p|o\x8dP\x14-\x97\xd2\x16\xf1\xb9G'\x87\xc1t\xeb\xc6\xdba\xe3\xa6, \x0f\x86\xcc\f\x0f\x9d\x93)\xbc\xaf\xe0\xc6\xd9W\xcd\n\x9d\u007fK\x91T%/\"t֪\x0e\x84.\x8d\xe5\xb8\xf5ח\xce\b\x99\xdfC%݂s\xa7\xd8\xf1ۭ\x89\x9c\xc8D\xe9\x89O\x02;ySٮ\x04\xf3\x86\a\xf8\xc3@E\xa29a\x97\xf0\xdd<Ë\xacV\xd6$*\n\xda\x19\x8b\xd0\x133\xcfGU\x92\xdcg\xa9V\x93-\xa5\xd1\x19#+J\xaf\xc5\xf5\xbb\xd9\xca\xe5\xa1|\xae\x15\xa1\"g\x13\xc2I\xb6k;\xac\xe0\xc6n\x8f\x9f\x16\xb6\xf0\xba\"\x96\x8d\xa2e\x977\xd8L\xb1ɶ\x01e\x88\xac(T#\xe5XE\rR\x8f\xd9ۡ\xd1\xc4\xf3{\xee\xa6/\x8bI~\xa1\\G\x81\rYœ\xbf\aiVK\xaax\xaa#%\x95\xc5\xe4\xed\x80XN\xb4iV\xbcQ\a\xceu\xd2-\xa3k\x90{\xa1h\xe4\xe3\xf4X[NN\xac\xb9\xda\xcb*\x02\xc6\xf7\xd6\bEA>\xb8\x94\"Կ\xb7\x8aYt(96!|s\xf9F\xe1\xa7\x18\xa1\xf8\xe0\xf5%\xeb\x83\u007f\x8fP\xfdޱ\xdc\xe4M[&\xbe\xadH\xaa\x11\x1f\xf4A\xc9\xf6\xc9\xe1\xfd\xa8+\u007f\xef\x8cY\x13\xa7\xafZ\xca5QI\xb7跸\xf9\xf8\xadg\xf7v\x91\\Zr\x9a+M|\\\xc1\x9f-\x9f\xe1\x0f\x19QY\xe7J\xe3V\xf6\xa1\xce+\x8e\x84$\x87\xc3q[Y\x93SQ\xcaxa\xc0\xdf\xe0p\xc4\x14\x90ܳ|FmuJT\x83\x18#+\xcaM\xde\xe1L\xf5O;\x85\xbe\x9b&\xc8x\xc7ɪYs\xab\xaa\xaaȔ\xb9\xb4\x1dp\x8fg|\xfe\xe9\x8c\xd0::\x96\rݲ\x9f楟\xa8)\x8b\xe5ݎvj\x8c\"7R\x8eU\xf4M\xea1{;tWW\xda\x12,\xb6]i\xf3\xe4\x99\x19ºT\x94\xba\x0e'\xeeZ\x12*\xcel\xe0\xa3\x15Ie1y; \x96\x13\xedC[Tr\xc1\x0f\xbdH\xd17E\rR/\xe8F\xf6.\xb7\x96\xee\x8b1\x97m(\xf6\xb2\x8a\x80\xf1\xbd5VQ\xd4]J\x85M\x9e\xdb\xc6.;ttM\x9f߅\x1d>ڰY)v\xfb8\xc2\x1d\x16^\x83'\t\x83\x92\xa5\x93\x912ɤ\x88\xcbEآ\x838\x10\x86so\xb69O\xe9\xa8$M\xd3\xe7\xe29Ľ&\x11\xb7\xc7\xffG[\x84\x9f\xbc\xf48\x84\xa5\x01\xcf\xee5\xf0\xe4\xf7P\xfd\xac\a]pN\xa48\x0f\xd6\xe7Ղ\xc0\f\xbc\x9f\"\xc6Ȋr\x8e\xff\xabG\r\xd4Y\x0f\xb5\x1dP\xf0\f\xdc\xf0\xe9\x11\x8cxO\xa4\x96\x95\xc6a-)\xb5\xb8M2(\xcfz\x9c\x8dT\xc4J5\xd0=V\xdb\x0e\xfc'\xcf\xd0\xc03\xa4\xa0\xcf\\\x8c\x8a\u0378\xae5\xef\tC\x99\xbe\x0f\xa3\x95IE1\xc5v`8\xd1>.\xf8\x83\x89\xb7T\x8b\xc5䭮X\xb1\xb3\x17T#\xabyaTX*\xee\x10\xd5U\x04\x8cﭱ\x8a\xa2\xeeR\x8aNe\xbb\xff\xa0\x0f=%\xdc\xf7\xaed\xfco\xc9\xdb\x1b\xf8l7\x18\xbfl\fF\xca$\x93\xc53{0\xd3\xc8Irx\xb0\xd4\x05*ɠ\x89s\xa1\x8c\x8aNGγ\xff\xb4w{_\b\xd8ȵW/\x8aR\xc1?&\x1f]_\xf3ǥ\xc9\xefZ\xf8\x0f\xc5\x0f\xb2\xa2\x9c\xe6\xef#O$E\xa1\xb6\x03\n\xfe#~\xcd\xe4|\x92w\xa9e\x0f\xad˲\xcan\xf6\xf5\xba-g*\x8a\"V\xaa\x81\xee\xb1\xdav\x88v\x1b\x9e`\x1a\xf9+\xddW\xf0!\xfd\x84/ß\xf7D+\x92\xcab\x8a\xed\xc0v\xa2\xed\xaeI\xe6\xcf\xe1\x04\xad(\xf4\x8a%E\x91\x1a\x99c\x11^n\x8b\xb3/\xaa\xab\b\x18\xdf[c\x15Eե\xb4\xe7\xa8]\xbac\xc58\xb6rҹ\xed\\\xd1M}\x01\xfem\x0e\xde(\xbcl\x12\x15EN2\x99\xe3T\x86\xb7\xf0\x87\xf0p)\x9fJ\xb2\xa8*\x12q;ϋ\xc6_V\xf2%\xfd\xd0y\x1eOF\x1b^\x14\x85|\x99\x91\xf45o\x88\xb3\xe5\x9cv\xac\xf3P\x94\xab\xd4ud\x19IQ\xa8퀂7\xe1\xd7c\xbe\x19\x16\xc9-{R\x96\x9a\xc0/9\xa8:\x8f\x82q\x1d\x8bt\xacT\x03\xddc\xb5\xed\xe06\x97D(%\xcbKqo\xc9\xe9\x06.F%\x95\xc5\x14\xdb\xc1Ӊ\xb6\x81̊\xf4%\xbaouŊ%E\x91\x1aY<\xef1\x1e-\x8ac\x14\xb5U\x04\x8cﭱ\x8a\xa2\xe6R\xfa\xb4(\xcfe\x9bc$\xe5\xf2q\x13?\x93\xbc\xcd c\x14|P9\x15EN2Y:\xf3\"\x81L_\x86\xcb\xf3-\xe1^\xa6^ԑ\xbf\xa4i\xef^#\x90\x11\b\xf9nW(\u007f\x9fEE\xe9\x8ds~\xed\x9d_\xf3\x84D|\x9d!\xd5CQ\x9eG\x17 O\x88\xa2؛\x14\xdb\x01\x05\xaf¯\xf6A\x8cQp\xcb\x1ar\x04}xR\x19S\xaa\\.*J\xe7>\xc5@J\x11+\xd5@\xf7\xd8\xdbvp'uuCC\x03\xbe\xd2\xfb7\x9eT\x98\x1e\xadH*\x8b)\xb6\x83\xa7\x13\xad5\x8b\xbc弇_\xa9\xad\xaeX\xb1\xa7\xa2<\x8cJ~ؘ\x90(\x9e\xf1\xa9\xad\"`|o\x8dU\x14\x15\x97\xd2\xd6\xfd\a\x84\xcd\xddo\xf8dxǔHf\b$f\x00\x00\x03\xb5IDAT<\xa3\xf3\xc1*<\xf0ǃ\xd2\xfd\\\tRW\x94\xa6M\x1e?\xdcG8r\xe5\xfb\x8f\x9f\xe3W\xeaj\xacʅ٦/\xbc]\x8b\xa5\xbe\xa45\xe2=\x119\a\xf1k\x92p\\>\x123\xa4\x1aDE\xc9\u1777a9\xbf\xe66\xfc\xd5\xef[\xe9\xa1((\xf5=\xc6m\x14\x91\x91\b\xdd\xc3\x1d\xa0\xb6\x03\n\x9e\xd2!ďt\x0fft\x9ejY\x01\u007f\x81|\xde!ƺ\xba)*\xcaM\xfe2\xf9\xe4l\xa4\"V\xaa\x81\xee\xb1\xcav\xa0\x0fli\x15\xd6]\xc2\xcb.\xab\xf0\x92h\x13t\xe7vL\xb42\xa9,Fm\aʉ\xd6UY\xac\x15+W\x9fX\x80\xda\xea\x1a\x8ar\x8d_\xc2\xf3\xeb\x1e8\x97\xb3W\x118\xbe\xb7F(\x8a\x96Ki\x93}\u007fSKK\xcb\xc9|\xad\x8at\xe7\xe8\xebod\x96|\xc0\xe1K\xbaK\x83\xd6\x16\xad\rZ\x8aPKո\xf8S\xe8b\xfc\xb8\xaa\x16*\x89\xa3\x17r\x13<~\xb9\xd7r\x8b\xf3\x0f\xc5sy\xa8\xe7\x14\xb9v\"\xfc\xe2\xd3I7\x16r^\xbeW?;Lۮ\x0e\xdc\xdcfr\xfc,\x1cC\xf3\xd2N\x9c\xce\x10g$\v\xa2\x8bO\u007fb~H\xd7@\ue67d\x90N\xee\x99\xed\xbd\xeap\xc4ls\\~\x86\x0f\xd6\xd4҂\x95|\xecWW\xd1C|\xcfl\xb1\xc3y\xcf\xea\xed(\xf9Nu\x89\x8d\xc1[\n\xdf\f\xc5\x17\xb0\xa9\xed\x10̅\xe7\xdbgM\xf2P>V\xe7\xe5\x96\x15\xf0\xe6}g\x85\xf6\xd6:cI#_\xfc\xb0\xf2}\x87\xc0\xd7\xc2I\x88\xa2\x91T\xac\xdc7\xa9\xc7\xec\xed\xf0\xe2\ar\xf5\xe5\xbe\xd4\x1c\xb2\x8a\xee\v|N'\xea\xcc\xe1/t\xa3f\xb3\xad`Ϣ(SE3\x95t+Fm\aʉֵ[by\xeb\xbe\vBsn\xd3-\xa3k\x90{A7\xf2ZL\xcd9\xc7\x03\x97\x8e\xb0W\x118\xbe\xb7F(\x8a\x96K\xe9\xe1l\x91a\xb8\xc3\xed\xfa;\xd3&F\x90ɝ\xfe\xcc9\xa1s2\xfb\xf1M(\x1c7\xae.Tx]A%q\x88}\x02'M)K\x1c\x89\f\x9b4\xf70B\x97\x82Ȅ\n\xfejRI7r'g{f\xba\xd8\xc9\xf3\xbc\xe9/f\xe1\x15߶V\xb3.ֲ\x86\xfc\x98\xa3\xee\xacE1I\r\x8a\x1a\xc8\xffz\xf8ed\x02\xf2\xa7(q\xaeA\xf8\xd0W\x9c\x10\x1d\x97V\xf1\x9e)\t\xa5;g \x9c?\xaf\xfbb<\xff\xac\xd2\xf5AX\xc8\\\xb1G\xf2v\b^\x15?q\xeaR\xcfsPf祖U\xac)\xb0\x99\xacI\xce;͜\x8dlt6\x8c\x17\x0eQ\xaa\x91\x8aX\xaao\xae\x1e\xb3\xb7\x83\xb3\xb2d\xa4XE\xcd<|\xcf\xfc\t\x9e\x9fW\x83\xd0ݔE\xcbr*L\xb8\x98\x94t+&o\aډֵ[\xfeP\x96\xb3\xdc\x1c\x97\"^>s\xb5\x8c\xaeA\xee\x05\xdd\xc8+&\x9cgZӬ\xbe\x8a\x00\xf2\xbd5BQ\xfc\x86B\xdff\x17F\"\x03Y\xa6j\xad\x18\x8283\xcb`\x14w\x9eµ\x1dtt\xa2}d\xde\xf1\xe8ŋ'?}\xb6\xe8\t\xf9\xccX\x85\x8ek\x1b\xf1\x80\xa2\xf8L\u007f\xee\xa4\x15Z1#\x97\x81b\xdb/Z1\x18\x15E\x19ݝ\xa7\x10\xb7\x83\x9eN\xb4\xa7\x9dw\xe1\xf4ŊCJ\xcfU蹶\x11\x0f(\x8aϴ\x84\xad2|\xee\xd8xT\x14%0:\xffR\\\x8b\x12Ow\x9a\xa3njD\x06\x04\xa0(\x00\x858\x17\r\f\x86\xbe\f\xf3\x8e\xea\xda\xea\x1d\xe6\f\xb7\xbbq\x02\x13P\x14\x80\x82\xccE3.R\x01^\x188\xb3\xc1j\xb2&\x9f\x05A\xc1\x80\xa2\x00\x00\xa0\x1f\xa0(\x00\x00\xe8\a(\n\x00\x00\xfa\x01\x8a\x02\x00\x80~\x80\xa2\x00\x00\xa0\x1f\xff\x1f\xec\x88D\xdc\xfa\xfa\x88\xfa\x00\x00\x00\x00IEND\xaeB`\x82",
+
+	"analysis/error1.png": "\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x04\xc1\x00\x00\x00\xbd\b\x03\x00\x00\x00\x8d\xa5\x9a\x96\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x02\xfdPLTE\x00\x01\x00\x02\x05\x01\n\x03\x01\x05\a\x03\x1e\x01\x00\v\r\n\x10\x12\x0f\x16\x17\x13y\x00\x01\x19\x1b\x18\x1b\x1b\x14\x83\x01\x00\x8c\x00\x00\x8c\x00\x04 \x1f\x19!# #$\"%%\x1e$%#&'%'(&+)\x1e()'++$*,)/,!-/,02/63(241\x98\x1b\x1b786;8,\x82%#:;9><0>?=C@4@B@\xa0*,CEB\x9c.-KH<MH7\x00f\x00\x00g\x00\x00h\x00JKI\x00i\x01\x00j\x02MOL\x04l\x05TO>\tn\aPRP\xa9:<WRA\fo\t\x0fp\vTVT\fr\x17\x11t\x19^YG\xaaDCY[X,`\xae7]\xad\x15v\x1c\\^[\x19y\x1e;b\xac_a^faO>e\xaf*{!bda)}*Bh\xb2egdLj\xafpiR.\x81.Em\xb1ikh\xb3XX0\x8301\x841/\x858Jq\xb5mol;\x86:Vu\xb4>\x89={t\\tvs@\x8b?B\x8c@@\x8dG\\z\xbay{xJ\x8eI^~\xb8\x84|d\xbbkkL\x90K~\u007f}O\x93Mb\x83\xbdN\x95UW\x95V\x82\x84\x81\x8f\x85hm\x87\xbdZ\x98Y[\x9aZ\x87\x89\x86\xc0{|]\x9c\\\\\x9dcr\x8d\u0096\x8cnd\x9dd\x8c\x8e\x8b{\x8f\xc0f\x9fg\x90\x92\x8f~\x93\xc4j\xa3jy\x96Ŕ\x96\x93s\xa4l\xa1\x96xq\xa5s\x81\x99×\x99\x96\x83\x9bť\x9b}u\xaaw\x9a\x9c\x98Ǒ\x92\x9c\x9e\x9b~\xaby\x88\xa0ʞ\xa0\x9d\x81\xad|\xab\xa0\x82\x8e\xa2ǡ\xa3\xa0\xa2\xa4\xa1\x81\xb1\x85\x92\xa5ʋ\xb2\x88\xb4\xa7\x83\xa6\xa8\xa5\x8d\xb5\x8a\x97\xabЩ\xab\xa8\x8e\xb6\x8c\x8d\xb8\x93\xab\xad\xaa\xb9\xad\x88\x9f\xaeή\xb0\xad\x96\xba\x96\x98\xbb\x98\xa3\xb2Ұ\xb2\xaf٨\xa6\x9b\xbe\x9aµ\x90\xb4\xb6\xb3\xa3\xbf\x9d\xac\xb7Ҷ\xb8\xb5\xa2\xc0\xa4\xb7\xb9\xb6۰\xb3\xa5ħ\xba\xbc\xb9\xb1\xbdקƩ\xbd\xbf\xbc\xa8ǫ̿\x99\xafƫ\xb8\xc0տ\xc1\xbe\xb2ɮ\xd0Þ\xc2\xc4\xc1\xbc\xc4\xd9⽾\xc4\xc6òͷ\xbb\u0379\xc0\xc8ݻ\xca\xde\xc7\xc9\xc5\xd8ɝ\xbdϻ\xc6\xca\xda\xc0\xcc\xda\xca\xccɿҾ\xd7ϡ\xcd\xcf\xcc\xc4\xd0\xde\xcb\xcf\xdf\xc8\xd3\xc1\xe0ѥ\xd0\xd2\xce\xc8\xd6\xc9\xea\xcc\xcb\xd1\xd3\xd0\xd2\xd3\xdd\xca\xd8\xcb\xd3\xd5\xd2\xdf֨\xcd\xd6\xde\xcc\xda\xce\xe6֪\xd6\xd8\xd5\xd4\xdb\xd0\xeb\xd4\xd2\xd2\xda\xe3\xd8\xd9\xe3\xeaۯ\xda\xdc\xd9\xd7\xde\xd3\xe1\xdb\xda\xd5\xdf\xda\xdc\xdd\xe7\xdc\xdf\xdb\xd7\xe1\xdc\xde\xe0\xdd\xdc\xe1\xe3\xf0\xe0\xb3\xe0\xe2\xdf\xe2\xe4\xe1\xee\xe1\xe2\xdf\xe5\xe7\xe4\xe6\xe3\xe8\xe5\xea\xe5\xe7\xe4\xf2\xe4\xe5\xe6\xe8\xe5\xe3\xe9\xeb\xe7\xe9\xe6\xe8\xea\xe7\xeb\xed\xea\xf6\xf0\xef\xf2\xf4\xf1\xfe\xf8\xf7\xf9\xfb\xf8\xfe\xff\xfc!l\x99S\x00\x00 \x00IDATx^\xed\x9d\x0fXTם\xf7\xf7\xd9\xd9\xd8w\xd3$C\x03\x9b\x12-K^\xd6fm\xfb\xdc\xe1\x19\xa9\xbe+\f\x8d\x1d\x14\xd7?1+\xbeVQ\x8aV1\x1b1\x18\xe7a\x13\xa3\x82ƄL\n\x19%) B\xe6\x89E\x1eY3*\xbe\">\x19Me\xc1\x96hqm\x12\xe8S\xa6ѱ\xb6\xda\xe4\xf2(\xac\xe4y\xaf\xe7\xed\xa6\xe5y\xcf9\xf7߹ý3(\x03\x97\xd1\xdf\xe7\xd1;\x87;\xbf\xf3\xbb眹\xf7;\xe7\xfc\xee\x99{\xfejh\x14 \x00\x00\x00\xf3\x18\x1a\xfa\xabH*\x15\x8eH\xee\x01\x00\x00\xc6\x10P0\x00\x00b\x17P0\x00\x00b\x17P0\x00\x00b\x17P0\x00\x00b\x17P0\x00\x00b\x173\x15,p\xa0\xaa\xa2\xfa\x18O\x92\u0099\xba\x8a\xba\xceH\x19\x00\x00\x004\x98\xa8`A\xb7\xb7\xb3\xbb\xb3\xae\nK\x98\xe0\xf5\x9c\xee>Yq2R\x16\x00\x00\x00\x16\x13\x15\xac\xcbݍ\xb7\xbc\x1bw\xbd\xceT\\#;*\xf8Hy\x00\x00\x00\x18LT0D\xf5*\xe8\x0e \xe4=@wTB'\f\x00\x80;\xc1L\x05\xc3\xf4wW{\x05\x84\xea|\xf4/\xef\xfe\b\xe6\x00\x00\x00,\xa6*X\xd0\xedv{HO\xecX\xe5\x00\xde\x0ex\xea\"\xe5\x00\x00\x00`0U\xc1P0\xd0^M\"\xf9\xbc\xc7\x1b\xec\x0fx\xddՑ2\x00\x00\x000\x98\xab`\x98\x81\xea&\xbc\xbd\xe6\xc5ݱ\x16\xaf7\x925\x00\x00\x00\x83\x89\n6 З3n\xfa\xda\u007fM@\x95\xc7\xc2f\x00\x00\x00\xd0b\x9e\x82\t\x95b\xf8\xfeL\x05V\xb0A\x92\xea\"\xb7%\x01\x00\x00F\x8cy\n\x86\xaa\xe8\x14\n:\x8a\xect\a\x11\xe2\xab|\x91\xb2\x00\x00\x00\xb0\x98\xa8`]\xee\xa6\xce\xeeN\x1a\xc9\xefr\x9f\xec>S\xe9\x85\t\xad\x00\x00\xdc\x11&*\x18\n4UWԵ\x90y\x14\xe8t\xb5\xc7{Z\x88\x94\x01\x00\x00@\x83\x99\n\x06\x00\x000:@\xc1\x00\x00\x88]@\xc1\x00\x00\x88]@\xc1\x00\x00\x88]@\xc1\x00\x00\x88]@\xc1\x00\x00\x88]@\xc1\x00\x00\x88]@\xc1\x00\x00\x88]@\xc1\x00\x00\x88]@\xc1\x00\x00\x88]@\xc1\x00\x00\x88]@\xc1\x00\x00\x88]@\xc1\x00\x00\x88]bK\xc1\\.\xbd$\x00\x00\xf7+&+X\xbb[z4~\xc0\xeb9\x10\xf1\t\xad\x1fs;u\x92\x84z\x8e\xe3\xcaQ9\xde\xd6\x0fϦ\xd0k\xe3\x16\xe1\x17\x176K\xeb\tc\xa7\xe5\xb8\xe3p\x98w\xef\xd0\xd9\xe8\xc0\a\xab\xc1/5\x1c\xc7\xea\xf7\x8b\x1cר\xfcq\xeeG\x8eY+[\x97|0,\xafH-k\x1b\x81\x17Gd{w\x8d\xfaً\x0e\xfb\x8f\xa2\xf28%\xed\x81\xc3\u007fX\xe3\xc3D(\xc3\xfd\x83\xb9\n\xc6W\x1c\xab\xa4\x89\xee\n_\x97\xaf\xa2;\x82y\x91\xfd\x8aN\x92\xc0\xbf\xcb\xed\xbe\x8e\xae\xbfŽ\x1b\xf6)\x89\x1d.;\xde^\xf2\xfbk9\xa3K|8\xcdi\xe1\xae\xe3;t\xa6\xd2z6\x92\xc5p.\xa5\xbdՇ_\xfaޚq\x89\xd9{\xc5o+\x97\xd3gm\x05\x87\x1a\x9f3\x96\x9e>\xff\xf2r\xa4\x87NqX\xbfa\xb8\xabF\xcdsԺ\xd2\xfa\"Y\x8d\x04\xed\x81\xc3\u007fXw\xd7\xea#\x81\xf5\x1b\xa9\f@41W\xc1\xbcM\xddT\xc1\x84*\xb2\xc6DZ\xaa\xf0_\xca=\\\x89NR\xe4\x02w\x1co[\xb9\v(,\xe5v\xf1\xb5\xe3\x0e.6\x14\xa9\xabpG\xce\x14~P\x18\xc9B\x87%b\x17\xb3~\x89v\xb7]Q\x9a\xd5yd\xeb\n\xd3y*\xd0W%\xdd\xe2\xd8G\xa2`wӨ}\xb8/)\xf4G\xb2\x1a)\xec\x81#|Xw\xd5\xea#@\xe37\xd2\t\x03D\x11S\x15\xac\xdd\xc3\a\xa8\x82uV\x90\xb3\x99\xaf\xe8\fk\xeeR\xfb].m\x17ll\x15,\x12w\xe7l\xd9\xdd\\K\x85e\xf4\xa5,$\xaf\xaa4s\xa9\xc19\xee\x102\xc2@\xc1t\x8b3f\n\xd6\xc3Es\xa0u\a\a\xbe\xabV\x1f\x01c\xe5\x17\x88\x84\x99\n\xc6Wt!Q\xc1\x9a\xf6\xd3\x1d\xfb\xc3.\xf5\xd1k۪\x93\x94`\x14\x8c/̴e\x15\x9c\xc3\u007f\xbe\xc4\xd9\xeaK\x16\xa4\xad\xa6C\xae+E\x99酮a\x17[\xe3ʴ\x05%X?\xcf\xd98\xae\xac\xa7h\xae}\x8d\xe6\x1b\xb4/\x8d\x13\x87d\x82\xc3\xf6jVf\xeb\xd6Yy<\xf1[\xe3\xcaJ/\xe81p\xc6\xda2\x87`\x8as\x98\x13YF\xde\xf7\xafβ9~\x94\x854\xa8\xb5`\xd9)^(\x85;Y\xbfXi\xb6\xba2\xc5\xe2\x14fR\ro\xa6\xbbk\x97\xa5-\xa9\x153\xf6\x14:\xf01\x88\xecc\x05ۊ\x8fl\xff\x8c\xf1\xa0)\x0e\x83\xbdDn\xbeh6\xea\xa0C<\x9a؍\x96\vi\xf0\x01\xe8\xb7\x03[!\xf5\xc0ʇE\x88\xd4\xea\x06\xce\xe4\xe20\xd945fZ]\xc9\xc6\xfaՔA\xc7\x19\x10e\xccT0o\x13\x92\x14\xacN\\(\xf2X]8s\x97\xed\x92NR\xe2\x02\xd7<00\xd0L\x14\xac\x99s\xb56\x16p\x1d\b}\xdch\xe3\x1c\xe553\xc8e\xdf3kA\xfd\xe1\xd5\\\xe8\xc5\xe6\xe2\xb66\xd78\x96\th\xa0\xb11k\xc1\x8c\xac\x92\"\xaeW\xe3\xf8\xac\xdf/\xf6DZgq%y\x9cc\xb7\xa3\x86\xfa\xcd\xda]\x9e\x95v\xc1\xc0\x19c\xcb\xece\x8a\xc3\u007f\xe0_\x90\xe7\xf7\xfb\x89\xe8\x9c\xe5\x8a\x1a\x8f\xd7;8\xed\xd8C\xad\x05K\xfd\x0fPG\xd6\ahY=\xeb\x17+\r\xb7\xac\xb1q\t)No\x16\xb7\xa6\xbccP,\x8e\xbd\xac\xb9\xcc^D\x92\xadi\xcb\xde:^No\x03`\x05\xbbR\xc4\xd5t\xb0\x1e\xd8\xe2\xb0عE\x8d\x87\x1d\xa4\xf9\xa2ڨ\xe7\xfc\x8d\\\xb9\xdfO\x15C)\xa4\x81\xad~;\xb0\x15b\x0e\xac|X\x91[\xdd\xc0\x99R\x1c&\x1b[c\xb6Օl\x1a\xbfl\x19t\x9c\x01Q\xc6D\x05\xeb\xf4\xf0\xb2\x82U\x9e\xa4{NV\x861ﵽ\xa8\x93\x94\xb9 }\r⋸\xbf\x91|C.y\x8e춧c\xa9+r\xe0\xd4\xca\x05x\xaf\xb0$\xe4bk\xe6ޥ\u007f\xd1/\xcde\x1c\xe93\r\xbf\x15 \x9d\x90\x99E\xd8\xfc\xb08\x8d\xc3>\x17\x9b\xf5e-7r\xc6ز\x87P\x8bÌ;j\x1d\xe4r\xa8\x9d\xa5U0\xb6\x16*~\a\xdai+A\x0e\u007f\x88\xdfE\x03X\x02\x16,\xc7ɾ\xdd\xcbm\\:\xd9y\x9cvK\x8fs\xcd\xf8\xad\xac5\xd8`\xb0\x91\x84α\x82\xd5؛\x893m\xe5uG\x91\x0e\xdcSs\x91\xf2F\xb9Q\x95Q$SH}[\xfdv`+\xa4\x1dEJ\x1fV\xc4Vg`\x9c\xb1\xc5a\xb2\xa9IƯ\xa6\f\x1a\xbfR\x19\f\x9c\x01Q\xc5<\x05\xe3+:\x05A\xe8\xae\x14\xf0\x95['\x0e\x1f}\xe1\xfa`/\xd9zu\x922\x17p\xaf\xa2\xa3\xa3\x86\xc6\xc1>\xab]3w\x16G\x83\xddv\"7$N\xd3'N\xb3(\v\xb9\xd8\n\xe7\x0e\xe2B\bYtr\xc22\xfb0\xb7\x14Y\xc1\x1aq6\x1e\xed|\x9e\xec\xa2øZ\x8e\x9e\xbd:\xce\x18[\xf6\x10Jq\x10s\xce_ʜ\xfbR\xfd9a\x10iaj\xa1\xd2\xcb\xf5\xe7\x15\xad\xec'\xdd\x14\x8d\xdfWɛRq\xd0@\xeb\x1arո\x16ѿ\x16Q\x15U\x87a\x05\xe5e\x92|h+\xaf\xab`jy\xa3ۨ\x8a\x821\x854\xb0\xd5m\a\xb6B\xba\n\x16\xb1\xd5\x19\x18glq\x98lj\x92\xf1\xab)\x83\x9e\x82\x198\x03\xa2\x8ay\nv\xd1-\x13@M\xe2\xac02\xac4\xe2\n=\aB\x93\nL\x1c\xacÑ\xb5\xf3\x90?O\xbc\xd8ȹDN\x9c\xb3\x9c\x1f\xa1\xe1A\xe7%R\u05cd~\xc5/\x1b\x16\x1f\x11\x91\x15\xec8\xea\xb0!I\xc1\xe8.?G\xef\xa1\xeb8cl\xd9C(\xc5A\xec9\xdfW_\xb8\b\x0f9\x91\x06\xb6\x16*\x82\xfdBڹ\xb4\v6A\xc7/-N\a\x1d\x9a\t+\vp\a\xa9\x80f)XN&\x90\r(.\n\x1c3\x16\x89\x87\xd6V\xde0\x92O\xcb\x1b\xe5FU\x14\x8c)\xa4\xbe\xad~;\xb0\x15\xd2U\xb0ȭ\xae\xc28c\x8b\xc3dS\x93\x8c_M\x19\xf4\x14\xcc\xc0\x19\x10U\xccS0!Hh\xf7\x04\x83\x02\xeat\x93\xa1\x03\xef\x0es/r+ף\x93T`\x14l\xd1r2\xee(\xd4^l\x9fq\xb5\xe4\xefРs\xd1ܳ\x14\x12\xd66\xbc\x9f\xc4(\x98]V0z'\xa1\x9e\xa3#\x1e\x1dg\x8c-{\x88a\xd7R}/\xd6\x01ҟ\xebk\xb4\xd7j\x0e\xcaւa\xc1[\x99(\xabf\x01\n\xf1K\x83\xe2\xa48\x99/Q\xb32l\xe1\x9aK\x93s]\xa4]\x98>\x98\xe3B\xef,\x1a?\x1a^yR\x1c\x16\xb5\xbcQnT\xb5\x0f\xa6\x16R\xdfV\xbf\x1dZ#\xf5\xc1\"\xb6:\x03\xe3\x8c-\x8e\xae\x821~[\x87\xf5\xc1d\xbfr\x1fL\xdf\x19\x10U\xccS0\x91\x804\x1f\x8c\f#}a\xe6\x83E肱\n\x96EN&a\x89\xf6bC˳\xf0\x10\xab\xc7\x1er\xb1\x1d\x17\x835e\xb4\x03t'\n\xe6\xc0\xd7\x15?\x97N\xbe\xd2s\xc6ز\x87`\xcf\xe3<\x9c\xf9\ny\xaf\x9c\x16\x1d\xe5ic{l-\x18֬|\x0e\x15\xae\\\x8dB\xfcf\x91\x88\xcc\"\xec\xd1A\xaa\x89\x04R\x95fj\xd0H\x06\x94\xfd\x99y\x838\xbd\x95\xe8.\x99M\xd1l\xeb\b\xf1\xa0\x16\x87E-o\x94\x1bUQ0\xa6\x90\xfa\xb6\xfa\xed\xc0VHW\xc1\"\xb6\xba\xbe3\xb68\xba\n\xc6\xf8ՔA\xe3W*\x83\x813\x84zw\x8f\xfc\xc7\v@\x04\xccU0!\xd0\xee\t\\CtN\xfeŰs\xf2K\xd4~W\x89N\x17\x8c\x9d\x93_\xce\x15\xd6\xee^\xc69\xde\xea\xb8ⷹ:\xd0Y\x97\xcd\u007f\x05]H\xcb*/K\xe7l\xef^\x10gq\xd7\xf8\xfd\xbd8\xe3N\xee\xf9\xc6Cd\x02\xa8\xd0A\xef'\xf5\x868\x1e\xfc\xc0ﷻ\xfc~\x1e]H\xaf\xe9o\xb4\x9d\xeb\u007f>\xef\x12\xa27\xff\xea\x17\xa4\xf7 }g\x1a[e/[\x1cr:\xd7\x1c\xcaK\xbbD\x14,\xad\xac\x19\x1b\xb4j\x0e\xac\xd6B\xb3{+\xb7\x1b\xbd\xc5ыF\xf1K\x8a\xb3\xa6\xa3u%)\x8e\x83\xcb,;\x8e\xfd\x92&*\xe2v6\xef\xe4\xc4{\x91\xf6E\xb5\xcd[\xb9z2'\xdf\xf5\xc1`\u007fAf\xebu\x8d\a\xb58*ly\xa3ڨ\xe2\xbd\xc8\x0e\xfa}\xa5\x14\xd2\xc0֠\x1d\x94\n\xb1\aV?\xacȭ\xae\xefL-\x0e\x93M\xe3\x81i3&\x9b\xea\x97-\x83\x9e3b\\\xc0\xfd\b\x01Q\xc2\\\x05\v\x900X\x15M\x1d\xa8\xf0\x86\xf9]\xe4\xf5\xb4\"\x9d\xa4\n\xfb\xbbH\xa1f\x81\xddQX\xbf\xc0\x96\xf7\"\xfe\xdbv\x81L\xd0\xc1\xfd\x9b\x9e\x82\xf4\xb9%\xef\xdap\xd2%\xc52\xe87\xfe\xf1<G\xfa\xcaf2\t\x94R\x10\xe2\xf8\xacd[/88\xaeq\x06\x97\xd6Hc \xf6\x12\u05ec\xcc\"r:\xea9\xd3\xda*\x87\xd0\x14\a\rlM\xb7\xe7\x91˲qey\x96-3O+`L-4\xbb\x9b\xd3\xcea\xdd\x10;0\xb2_<\xd4*/\x9c!\x16gy}٢4\x878SM\xa8Y\x92\xb6\xa4V\xec\xd7\xf6\x14f\xcdX~\x88\xfe.\x92\xe3\xce\xe2\x82qe\x1a\x0fjqT\xd8\xf2F\xb3Q\afѽ6m!\r>\x00\x83vP*\xc4\x1eX\xf9\xb0\x88A\x84V\xd7w\xa6\x16\x87ɦ\xf5\xc0\xb4\x99\x9aM\xf5˖A\xcf\x191\xaew\x84\xfb\xf5.pG\x98\xab`#\xe6U\xeec\x9d\xa4yH\xe3\x04\x00\x00\xcc%F\x14l\xa2=V\a\x14\f\x00&\x041\xa2`\x13\rP0\x00\x98\x10\x80\x82\xdd\x05b`V\xe6\xcdo=\xc4\xf2\xad7\xc3\xe4\x04\x00 \xaa\x80\x82\xdd\x0540\xdb+\xa6\xff\xa8\xd5/\xaaa\u007f\f\x9b\x1b\x00\x80\xa8\x01\n6J\x86\v\x18\x96\xb0H\x99\x00\x00\x88\x0e\xa0`\xa3\xe3M\x1d\x01{\xe8!\x18H\x02\xc0\xf8\x00\n6:\xf4\xba`\xd0\t\x03\x80\xf1\x02\x14lt\xe8\n\xd8C\x0fE\xca\x06\x00@T\x00\x05\x1b\x1d\xa0`\x00`&\xa0`\xa3\x03\x14\f\x00\xcc\x04\x14lt\x80\x82\x01\x80\x99\x80\x82\x8d\x0eP0\x000\x13P\xb0\xd1qo)\x98wf0\x92ɸsm\xa67\x92\tp\x1fc\xb2\x82\xb5\xbb\x95\xd3\xd3\x17~\xb1\xc8\x11\xe3\xb1Z\xadŨ\x18o+\xc2X]\x8c\xb7N\xc3/\xb9\xd8,\xb1+\x8c]$\"+X\xbe5\xae\xda0{\b\xbb\xacqU\x91ldƠ\x9e۰\xc3\xc848\x9dG\xc2\x1a\x1ct:\x9d{\xd1^\xbc=\x18\xc6\xea\xd3l\xe7*\xfc\xf2\n6\x9b\xffi\x18;\xb4-n[\xb8\xb7\x81\xfb\x1bs\x15\x8c\xaf8&/O\x14t\x9f\fk:bx\x8fu[\x10\x05\xb7Y=\xc3W\x1dbh\xc9M\xc0\xdbn\x9fo\x97\xb5%\x9c]\x04\"+X\xc0\x17?\x12]\xa0\xf0G\xa7\xeb\xdb\xfaN\x0f\xdb\x15\xfdz\xee\x8a\xf3D\xb0\xa0\xdch[\xbfW\xf7\x8d\xb6\xf3\x92\xc1A\xe7\xde\xcf\xd1\xe7\xef8\x0f\xdeе\x13\xb9\xfd\xf3W\xb2\xf1\xcb\xef\xdb\xda\x1a\x9c?\x0fc\x87{\x86\x8f\x96\x86}\x1f\xb8\x9f1W\xc1\xbcMݒ\x82\x05\xaa\xa3\xa5`\xa8\xddz\x00o}\xd6\xf6\xf0f\xc5\t\xe2kK\xc4+;\x1c\x91\x15\f\xa1\x84\x11+\x18B\xf3\xf4m\xa7/\x1e\xbe/\xda\xf5\xbc\x18\xbf!\xbc\x81\xc2f}\x05[\xbfEJ|\xe4<\x85\xb7mΏt\xcd\x14\xf6f\x8b\xaf\xe7#(\x18ڔ\x10\xe6\xe9\xbd\xc0\xfd\x8d\xa9\n\xd6\xee\xe1\xc5\xe7\xe4#\x9f\xdbW\x11\xc3\n\xf6\xbf\u007f\xf7_\xff\xf5\xeb\u007f\xfc_x\xfb\xbb\xa7\xc6D\xc1R\xc7A\xc1r\x93\xc3v\xe6\x18\f\x14l\xed\x16)\x11m\x05\xe3\x93s\xc3\x1b\x00\xf7/f*\x18_\xd1%\xad\xf4\x81\xfayy\xd5[]\xaa\x95\x98O5\xe2\x17'ǧ\xcc;\x83\xf7\x9ey\xd4j\xddԵtj\xe2\x9cA֘\xb9\xb2U\xdb|k\xbc{ݴ\xc4\xd9\xf4\xcb<\xb04y\xca\xc2\xdcaWv\xe5\xcc\xc4i\xebx#\xbfݓ\xad\"\x93\xd9\x0e\x81\xa8`o\x92\xb6x\xea_\xc9\xf6_e\x05\x93\xbda\x05\xcb\xcfM\x9e2\x8fF\xa1\x8e\xceN\x89O\x9a\x93B\xb3\xeeJML\xdd%z\xe9Z\x98\x14\x9f<\x87<e\x1b+X>>\xc6cAƃW:p*\xd2\x10\xe5z\x0eL\x96\xbb`m\x9bWd?\xb3y\xc5m\x9c\xbcݰ~\xfeچ\xdbt\xf7\xa7[\x9e\xc9\xce\xd9\xfc{D\x15\xecu\xa7ә\x8d\a\x89\xb7\x0f\xae\x9f\xbf\xea\x8d[\b\x9dp\x8a\xacG\x1a\x05\xbb\xb1%'{\xc5f\"e\xaf8\xb3\x0f\xbe\xb1j>u\x80~\xbf=\xe7\xe9-\xaf\x84*\x98\xe2\xec\xa3l\xa7sϧ\xdbWdo\xfe\x82\xbe\xb1)\xb1\x1f\x01\x80\x1ef*\x18Y\x1e2\xa0,\xd3\x1dN\xc1\xf8\xa3\x937\x05QpӔ\xa3<\xbe\x9es}\xd5\xf3\xe2\xf0\xe5\xd8_]\x95\xf2\xe4\xe4\x94uK\xad\x9aAF\xbb\xd5\xdb\xdf\u07ff\x9f\\٪mgգ֤\xe2\xd2\xc9\v\xb1A\xd7\xe4i\x1e\xeflk蕝\x1b\x97\xef-MJ\x15\f\xfc\x0exJE<\xecR\x85\xa2\x82=\xfc\xe6\xd0\u007f\xfc\xe3C\x0f\u007f\xeb\xd7C\xff\xf6\xb0\xa4`\x8a7\xac`\xd6Ԫ\xaa\xd4D\\\x9e\x93֥\xd5M\xee$+Q\x8c܄M\xdeM\tK\x89\x13_b궦b+\x89\xf6`\x05\v,\x8d+ma\xcb\xc3\x1f\xf3=\x99\xe1\xf3\x85\xde\xea\x88r=O[}\xe2\xfb\xbf\xfc\xfe\xf6#\xa7\x0e>\xe3$\xe2\xb1#{ϩ=\xd9\xdb\xc9\xee\xb6\xf9\xeb\xdf9\xb5\xd7ـ\xa8\x82\xfd~\xbb\xb3\x81\x84\xbdv8_?Ր\xb3\xf66\xba\xd1ֶjc[[\xdbo\x10U\xb0[\xb7n\x9d\"\nv¹\xa3\xed\xc8f'6\xfd\xe8H\xb63g\xef;\xf3\xb7`\x83O\xe7\xaf:xb\xb33T\xc1\x14g\xb7\x8e\x1cY\xb1j~\xce\x1bۿ\u007f\x95\xbeq,R\xff\x11\xb8o1Q\xc1:I\bzd\n\x86/;2\x8cZL\x06\x13|5\xe9ؤ.\xa4\xbbS\xad\xb3\xf9\xd0u\xeaۥ.K\xbb\xd66a\n\xbeN\x97&\xe1T\xc6T\xbcWH\r\xb9\xb2\xbdV\x0f\xfd\xab\xca\xc8o\xf0\xa2\x88f\u0081\x14\xf7zj\xe8\xd7\x0f}\xeb[\x0f\xfdߡ\u007f\x94\xe2`\xac\xb7\x84i\xb8\a\xd1?u&\xeev%\x11\xed\xda5\x05\xeb\xda\x01ڃ:`ݏ\xdfJ\x99\x83Eq\xa0\x9a,ڄ\x15l[\x82wxytG\x91Q\xad\xa7\xd7zQ4l\xc8!\xda\xd5\xf04\xeey\x9d\xa2\x9d)\xba\xbd\xb5b3\xee\x1c\xdd>B\x82\xf3X\xc1\x1a\xb2O\x10\xdb\x13\xf4v\xe3y\xf1\xe6$3\x8a\x14\xc1\nv\x8bd\xb8-\xbe\x93\xfd4\xee\u007fm\xcf\xc1\xa9\x8d\xab\x88\xaf\xb5!\n\xa6u\xe6\xdcx\x03ݖn\x05t[G|;\x17\xb8\xcf0O\xc1\xf8\x8aNA\x10\xba+\x05i\x91\xc8\xf0\n\xe6K\xe4\x11\x9fH{\t\xc1]s\xa6N\x96\x86T\xa9:1\xdevkiKKK)\x8d\x0f1\xb6\tD\xfeHP\x88\xb7\xba\xc9ߛB\xae\xec\xc5S\a\x061)\xb9\x06~/Ze\x86\x8f\"\x1f\xfa\xfb\xa1??\xf5硧\x86\xfe\xfc\xb0\xa4`\xac\xb7\x04:<s[\xaf\xa1\xee\xe4\xa9\xf9\xee3\x02\xe9\xc4\xe5N\xa3\xf9\xa7a\x83\xfd\xd63\x8a\xbfyś\xac\xe2\x04\x13myt\x15,\xaa\xf5\xac\x93\x15\xecjΊ\xd7\x0f\xfe\xea6\x19:\xeeXK\xf7\xacz\x85\xc8دdK\xac`?qR\x01C\xdbW\xdc\xfe\x02\x93\xb3\x83\xfc\xc1(\xd8;\xe7ϟo\xa0q\xb0\x1b\r\x9bW\xccwR?\xd9Ċ\x04\xbfn\x88\xd3,\xf6\x84(\x98\xd6Y\xf6U\xa4\xd0m\x1d\xf1$\x13\xe0>\xc3<\x05\xbb\xe8\x96\x11WY\v\xaf`\x83Iu\xa8.\x89\x88]Krʆ:_\x86\xa4`Ӈ\x9b2\xf1!֖\xc6\xd3ɕ}R\x1c.\x85F\xb8S%}Zh\xe4\xd7\xe7\x15\xf1\xb1;%\x05{过\xfech\xe8\xd7C\xbf\x93\xfe\xd4x\x13#\xf9>\xebi\xb2,\xf9\xe2i\xd6$2\xbfi\xe6<\x9a\u007f\x0e>P\xa9U\x8d\xf2\xccK\x9e<M\xee^\xb2\xe5\t\x1fɏF=\xd58ٍ\x83[V9\x9fy\aK\xd8\xc6\xcdt\xc7\xe6\xf5d\x16\xd8-\xc5ts\xce\xfcU[hpl\xad\xd4ۢvz\x91\xfc\xf39+\xf6\x9ch\xdb(*\x18\xb9\x01@\x14켳\r\xa1\xe1\x91|\xad\xb3\xf5H\xa5\xc5z\f\x01\x80\x1e\xe6)\x98\x10$\xb4{\x82A\xb1\x13\x16^\xc1P\xfeB\xb40\x9f$\xa6\xcd$\x83\x9e\x85\x92\x82-\x1cn\xc9\\٬\xadre_\xb3\xd2\xf8yh\x84{\xe9\xd4Ӕ\xa0\x91_]d\x05\xfb\x0f\xb1=\xfe]V0\xd6[\xc2:bYa\xe5\xd1I\xd2\x1b\xe3\xab\x12q\x01r\xa7\xd2\xfcSqW\xa8ɪ\xce\xf6\x9a\x97\xd4~q2\x9d\xfe\xa4-\x0fQ\xb0\x90\x15\x81\xa3\\O^\xbeez~\x0f\x16\xa7\x1bG\xb2\x1bp\x1fL\f\xe7\xaf\xd8A\xfa`\xe7\x15\xd3\xcd9\x1f}:\x9f\x04\xc4p\xb7\xe9<\x85\x8e\xf6\xa8\x82\x1d\xbc\xaaQ\xb0U\xeb\x89\xf0m\xd1*\xd8\x1fi4\r\xed\x18\xd6\a\vu&S\x1c?\xd2ۤ\xc0\xfd\x86y\n&2\xd28\x18jI\b$\xd0K0\x85\\tB\xaa\xa4`\xe1\xfb&\xac\xadre\xa3\xe9)\xd7\x10\xeaz,\xe4\xca> \xc6Z6\xd1\t\xe0z~u\x91\x15\xec͡\xa1?\xffyh\xe8\xdfd\x05c\xbd%\xa4\x900״\f|xZ4\x94\x91O\xc2Nd`TE\x86\x8c|r\x06\x19W\xe6\x13\xa1#\xb3)\xf6Ǔ\x12iʓ\x813\a\xa5`P\xf76q\xb8\x17\xedz.\x9e*~\x95\xec\xa5\xfa\x836ҡ#\x89I\x1d!;n\xe4l$j\xf6\xfa\x1bH\x9cMq*\x9b(\x9ah\x80\xf6\xd0\xe9\x15\x1b7\"\xf49\xd9\xc1(؊-\x88D\xbc\xb4\n\x86֯\xc0*\xf5\x9b\xec\x10\x05\xd38c\x15L\x986\a\x01\x80.\xe6*\x98\x10h\xf7\x04H\x00\xbb?\x10\xf0\xf8\x02\xe1~\x94'$\xcfN\xa6WX\xb1u\xf1\xaem\xa9x(\xd62\xd8B\xef\xd1]\xd4\x1a\xb2s\xd5Uۀ/>\xb7\x05\x9d\u038d\xf7\x05P{bJ\xf1\xa6)q\x8fz:Ź\xea\xa5>\x1f\xe9\xddl\xb0.\xae\xf6\xe6Z+\x91\xbe_}d\x05\xfbס\xa1\xff\xf3\xefCCO\xc9\n\xa6z#\xf7\"\xe7\xb44͜r\x91\x94=\xb1\xd8[\x97K\x87wK\xe36x7ĉ\xf7\"\x1f\x9b\xe6ޟo\xad s\xf2s[\x06\xf89ɾ\xa0\xc6\x03V\xa4Һىb\x1fl\x9e\x95^\xcfQ\xafgW\x9c8\xf5}\xafs\xfe\xde\x13'vБ\xdev\xe7\x9e\x13{\x9c\xe2\xbd\xc8\xecU\r\xa7^w\x1e$s\xf2_\xf9\xf9\xed\x1b\x9bs\xda>\xc7r\xf3\xfd\xedG\xb0-\x95\x9e\xbd\xd9\r'6ο\xaa\x99\x93\xbf\u05f9\xa5a\xefZ<&\xfd\xf9նl\x9c헯d\xb7]E\x1f\xcd\xcfٻ\xe7ig\xf6\xc1\x8f\xd0U2'\xbf\xa1\xad\x8dD\xbd\x14g_\xfc\x82\xdeؔ\u007flT\xcatR\x01@\x83\xb9\n\x16 a0\xd2\x179)F\xc4\u008d\x15J\x13\xc4\vL(}2!i\xb1gj|ƙ8\x1a\xd0\t\xf9~V\u007f/\xe8fl\xc9$\xab\xf8\xf6D\xbc\xc5\xfd\x9f\xaeyS\xa6\xae\xf3<\x8a\x93\xb9RP\x88vE\x0ed$M\xc9؏\x90\xbe_}d\x05\xfb\xfb\xff\xfa吏\xfa\xef\xdf=\xac(\x98\xe2\r\x8f\xf1\x8a\x17ON^J\xa2}\x95\x19\xc5)\xf1\xc9\x194>%\xd0\xf9`b\xb7\xa7kq\xca\xe4\xe9u\xe4w\x91Vk\xdc\xc9*\xbcݤ\xf1\x80\x06\xf2\xa7$fHq*O\x12\x8d\xd0G\xbf\x9e\x9b\x1e\xa3Ѧ\x83\x1b\xf7\xae\xc8\xce\xd9HCU\xb7\x1b\xd6*\xf3\xc1~\xb3%g\xfe\xfa\x13\xf4w\x91N\xe7/\x8f\xe0\xcdO\xf0\xdeS\x1b\x9fyz#\xed\xb4\xa1[\xaf?\x9d\xbd\xf1\xbc\xf6w\x91\xb7\x1bVe\xe7l?\xb8*{#\xf9\x01d\xf6\xaf\xe6\xe3-\xee\xdc}\xba\xf9\xe9\x15{\x0ef\xe3\xe4\x0e)\xf8\xb5\x051\xce>b\x02b\b\x1dM\\\x87\x00@\x1fs\x15,\xf6yH\x9fH\xd9&&\xeb\xe2'⤅\xaa\xf8\\͌e\x00`\x00\x05\x1b\x1d\xf7\x94\x82\xa1Ҕ\t\xf8t\x9ddx4\x05`\f(\xd8\xe8\x10\x05\x8bi\x91\x98V0\x00\x885@\xc1F\a(\x18\x00\x98\t(\xd8\xe8\x18>\x80\xfc\xeaà`\x000^\x80\x82\x8d\x8ea+\xde>\xfc7\xff\xe3aX\xf1\x16\x00\xc6\tP\xb0\xd1\xf1o\x0f\x85\xf0\xb0\x05K؛\x91\xb2\x01\x00\x10\x15@\xc1FIh'\xec\xab\x16\xcb\xdf\xfcO\xf8\r\f\x00\x8c\x0f\xa0`\xa3\xe4\x8f!\x12\xf6UK\xee_O\xe9\x04\t\x03\x80q\x01\x14lԼ\xa9Ѱ\xafZ\xeaNZ\x92;ᙢ\x000\x1e\x80\x82E\x19\xdeR=t\xcc2\xb5\v$\f\x00\xc6\x01P\xb0(C\x14l\xe8\x80e\xdaE\xf6Y\xd4\x00\x00\x8c\r\xa0`Q\x86\xb7T\xfdeh\xa8\xce2\x1d$\f\x00\xc6\x1eP\xb0(\xc3[*\xb1\x82\rUZ2\xbaA\xc2\x00`\xac1Y\xc1\xda\xdd\xe2C\xe1y_u\x85\xf7̽\xf0\b\x02\xde\xe2\xf9\x92H\xd8.\xcbl\x900\x00\x18k\xccU0\xbe\xe2\x18}\x80\x1f\xef\xf1\xb6w\x9f\xf4\xd4\xdd\x03\x12&+\xd8\xd06\xcbB\x900\x00\x18c\xccU0oS7U\xb0\xa6j\xf2\xa4\xbfkQ[\xb6\xdbDxKŗ\xa2\x84m\xb2,\x05\t\x03\x80\xb1\xc5T\x05k\xf7\xf0\xe2s\xf2\xeb\xc4'\xeb\xf9\xbca\xcdc\x02\xde\xe2\xfe\x93\xa8`C\xeb,\xf9\x01\x900\x00\x18K\xccT0\xbe\xa2KZ\xe9# >\x01\xfe\xd8D|D\xe8\x1d\xc2[v\xfd\xe9\xcb/\xc5\xd6ɵ\xac\x03\t\x03\x80\xb1\xc4L\x05\xf36\xb1k\x15!$Ti\x96b\x8cM\xb0\x82\xfd?\xb9\x136\xb4в!x\x0f\xc4\xf6\x00`\xc2b\xa2\x82uzx\xad\x82\x1d\xf3\\3\xb6\x8e\x15xK\xa9@:a\u007f9v\xf4\xe8Q\xdfc\x96b\x900\x00\x18;\xccS0\xbe\xa2S\x10\x84\xeeJA\x90v\xb4\xb8\xb5+\xba\xc6&X\xc1\x06i',\xc5\"R\xca\v\b\x00\x80\xb1\xc1<\x05\xbb\xe8\x96!됡A\x9f\xbb3R\x96X\x00+X?\xfaSŗCM\x969\x9b\xb6m+u7\x05A\xc1\x00`\xac0O\xc1\x84 \xa1\xdd\x13\xa4W8\xef\xad\fD\xca\x11\x13\xf0\x96m\xfc`\xb1e\xdb_\x86\xe2\xa7\xec\xef\xbcx\xb1;8`\xb9\xe7\x88\xd4\b\x000^\x98\xa7`\"R\x1c\xecZU\x1d\x8fE\xed\x1ex\xa0\x03Q\xb0u\x96I\u007f\xfb\xe5P\x95eW`\x00\x0f\x94\x91\xe5\xe6=\x06(\x180a0W\xc1\x84@\xbb'p\r\xa1\ue2aa\xee@ po̦ؖk\x99\xb6\xc1\xb2\xeb/\u007f\xf9\xdb'\xdb\xe9\\\nP0\x00\x18+\xccU\xb0\x00\t\x83U!\xb4_\x8a\x88\xdd\x133Z\x13-\xa9\x9e\x96i\xd6/\x87\xb6Y\xaa\xe9\b\x19\x14\f\x00\xc6\ns\x15\xec\x1e\x84\xb7X\xa6W\xb6_k\xb2x\xfe\xf2\xa5e\xe1E2\x95\x02\x14\f\x00\xc6\nP\xb0(\xc3[\xe6Uw\xf2\x02?\xcd\xfa'ޒ\xd1I\x86\x91a\x14L\xef\xad\b\x82\x17E=\x8c\xecJ\xdf\x02\x14\f\x980\x80\x82E\x19~\xd3Q,`h\xe0\xc0\x03\x93,_)\xee\xba\xd7\x14\x8c\xee\x00\x05\x03&\f\xa0`Qf\xe0Z\xb0_\x9c\x1e2}v\xe9\xb1k\x11\xe2`\xa0`\x000*@\xc1\xa2\x8d\xf4\x1b\x03\x81\xbf\xd8\xdeu\x8d\xfe\xa2\xc8\"+\x01I\xbc\xf6\xb8e\xd2w?\xc1\u007f\xbc\xfc\xc8_?\xf2\x02\xd9\xff\xe3\xaf[\x1e\xf9\xe1\x1fH\xe2q˃/S\xab\xf7\xbf3\xe9\x81\xef`#˳\x0fZ\x18\x03%\xcbMƑb\xfb\xc2#\x96\xaf\xff\xf4\xe5G,O\xfc\x8cu*\xf1\xb3Ix\xf3]\xfc\u007f҇\xea\x9b8\xcb_?\x82\x8fH|X\x1e\u007f\r'Ȏ\x17nj\xcar\xf3\xa7_yA\xc9Bg\x83\x81\x82\x01\x13\aP\xb0\xb1B\x18\x18\x18\x10\xc5L\xa3`_\xdbw\xf9\xc3\xefb)y\xfb\xc1}\x97\xf7\x11}\xfa\xe9\xdf\xfd\xf4\xf2\xfb\xdf\xfc!\xde\xf3\x95\xb7/\xbf\xffO\xd4\xea\xef\xf6]\xfe\xed?\u007f\x0f'\x9f\xf8\x905\x90\xb3P_\xb2#\xd5\xf6\xfd\xcb\xff\xf2\x00\xd9|\x93ɣ\xf4\xa2\xbe\xf6\xde͟Y>\xbc\xf9\xdeט7-\xd4\xe1\xdb7o>\xfe\xec'\u007f\xf8鷱N=\xb8\xef\xb7\xfb\x1e\xfc\xb1\xa6,x\x1f\x9b\x85\x1e;B\xd5\x01`\xdc\x00\x05\x1b{4\n\xf6\x1e~\xfdO\xdc!z\xe2Ǥ\xa7\x83\xf7\xfc\x03\xd9\xf3\xe1#7o~㵛\xb2\x15\xe1\xb7\x0fJ֊\x81\x92\x85ZɎ\x14\xdb\xf7o\xde\xfc\x84n\x1e`\xf2(\n\xf6\xcf\xcf\xde|\xd6\xf2\xf2\xcd\x1f\xfe3\xf3\xa6\x85:|\xe2\xe6\xcd\a>\x14\x8d\xbeAw|\x83-\xcb\v_\u007f\x9f-\x03(\x180\xb1\x00\x05\x1b{4\n&'&\x91\x91\xe4'$!\xfeP\a\xef\xfcDV\x8d\x9b\x1f~{\x92\xb8\x8b\x8c\x03\x15\x03%\x8bd\x15b\xab\xece\x9d*\xbc\xfd͛O|\xef\xdb7\xbf\xf1v\xe8\x11?\xc1*\xf8/\x93\xbe\xf72\x11\xb1I\xf2\x0e\xa5,?\xfc\xc6oo\xb2e\x00\x05\x03&\x16\xa0`cOx\x05\xb3H\xfd\x1fq\x8f\xf8\xe6\x13\xff\xf2\xe1\x1f\xfe\xa0\xe8\x85\xc6`\x98\x82im\xe5\xc3\xc8y\x14.O\xfa\xf0\x81\x0f'}h\xb9̼\xa9(\xd8\xcd\xf7\x9e\xfdΤg\x19\x05Sʲo\xd2\xdb\xf4U\xc9B7\x91j\f\x00\xe3\x05(\xd8\xd8C\xf4\xea?\x89L\xb0\n\xa6\f\t\xbf\xf1\x82$\x0eO\xbc\xa6\x88\xc4\x03Xg\xf6\xc9֪\x81f\x14\xa9k+o\x94<*\xff\xf0\xbd\u007f\xa0\xff\x997\x95Q$\xe1g\x0f0\xa3H\xb5,\xef}\xe55M\x16\xba\x89Tc\x00\x18/@\xc1\xc6\x1e|\xd5\u007f\xf7\xbb\x1f^\xde\xf75V\xc1\x94\xb0\xfc\xbeI/\u007fry\xdf7q\xe2A%z\xfe\xf8\xb3\x97\xdfS\xac\x15\x03m$_\xdejl卒G\xb2\xc3<ky\x96\xfeg\xdeT\"\xf9\xdf|\xfb\xf2\xe5\x17\x1e\xa7Q\xfb\xcb4\x92ϔ\xe5\xfd\a_`\xb2<\xf26(\x180\x91\x00\x05\x1b{\xb0\f|\xf2O\x93,_\u007f\x8dU\xb0\x9b/?(M\x8d\xd8\xf7\xc4\x03\x96'\xf6\xe1\xc4k_\x97g0\xbc\xf7\xb8\xe5\xc1\x17\x14k\xc5@\xc9\xc2*\x98\xc6V\xd9(y\x14\x05{\xcf\xf2\xfe\xcd\xf7i\xfc_y\x93L\xc0\xa0\xb3)\xde~\xc22\xe9\xdbd\x12\x06\xd9A\xbb[jYn\xfe\xec\x91g\xd5,\xaf=\x02\xb3)\x80\x89\x04(\xd8أ\x88Ƚ\x02(\x180a\x88-\x05s\xb9\xf4\x92\x13\x1dP0\x00\x18+LV\xb0v\xe9\x81:\x81\x03U\x15\xd5\xc7\xf8\b\xd6\x1fs;u\x92\x84fN\xc2\x11f]\x8d\xe3\x8e\xc3\xc6oF\a\xf6\x10\xbd6n\x11M\x80\x82iy\x91\xe3\x1a\x99?\xc7\xe1c\x91\b9\xf0]0z\x0f\x91q\xe1\xd38\xad'\xbc\xcd\xf8\xb5ل\xc7\\\x05\xe3+\x8e\xd1g\xb4\x06\xdd\xde\xce\xeeκ\xaa\b\x12Vd\xbf\xa2\x93$\xf4\u007f`s\xf91;\xb9\xebó\xc94\xa7\x8d\xf9٧9D\x87\xcbN_A\xc1\xb4\\\xf1\xdbʙ?\xc7\xe1c\x91\b9\xf0\x1d\xd0zV|\xbd{\x0f\f\xb23\x03.\xf9\xfd\xb5\xdc\aaMƱ\xcd&<\xe6*\x98\xb7\xa9\x9b*X\x17]\xa6\x88\x8f\xb0\xd6G\x0fW\xa2\x93\x94\xb0\xd33\xab\x91\xfb\f\x193\x0eKnh\x0eQ\x0e\n\xa6\x8f]#\x03\xe3\xf0\xb1\xc8\xd8\xefR\u007f~P(\xa7\xee\xd6\x03\x83\xeä\x8eH\n6\x9em6\xc11U\xc1\xda=\xbc\xf4\x9c|\xda\xf9\n\xba\xc3/\xf6\xe1R\xfb].m\x17\f\xc9gVO\xa8\xb0\x99\x8a\xac`\xf7\x1c\x11\xea\x1d\x91(\xc8\xc0\xddq\xb7\a^\x16M\x05[\x16\x05\x05\x03d\xccT0\xbe\xa2\x8bY\U00076ffb\xda\x1b\xf6\x9b\xa5\u05f6U')\xa3\x9cY/q\xb6\xfa\x92\x05i\xab/\x91\x1e\x19Ǖ\xa3r\x8e\x04/\xfa\xd28)\x86q\xce\xc6qe=Es\xedk\xc8\xe1j\x97\xa5-\xa9\xd5fc\xc0{k\\Y\xe9\x05=F\xd9\xf4\x0f\x81\x87\x1bE\x99\xe9\x85\xd2(\xb2qeڂ\x12\xba\x88\x89\u007fu\x96\xcd\xf1\xa3,\xcd!\x10_\x98i\xcb*8\x87\x8c\xca\xc0x\x18u\xdd\x04\x87\xedլ\xcc֭\xb3\xf2x\x03\xbf\x87\xa5\x80\xe22M\x01\xca\xe8\x01\xc81\xcbpS\x97\xa8\x85\xd4\xf1\xc0\xa2\xd6M\x83}\xab+\x936*Stփ\x9a\x8d\xa9\x10\x89u\xbe*\xd5\xd8\x00\xa5}_\"FJ \xb2\xa7Ёw\x93\xef<\xb6\xe8\nl!\xf5>!M\x93\xe8U^\xc3gE\x8e\xac\x92\x12\a\x1d\xe6\xc9\x1f\x80\x913ր\xb5\r\xaf`\xecy\xa6{F\xddW\x98\xa9`\xde&u\xcd\xee\xa0\xdb\xed\xf6\x84\x0f\x83\xb9l\x97t\x922\xf6\xb2\x81\x81B\xd2\x03\xfb\xb8\xd1\xc69\xcakf\xe0/\xba~\xff\xac\xb2\xeb\xe8z\xd9,?>\xcd\xce\xfa\xfd\xa2\xca\r46f-\x98\x91UR\xc4\xf5\x92\xce\\Ys\x99\xbdH\x93\x8d\x81\xec\xcd\xda]\x9e\x95v\xc1 \x9b\xfe!PϬ\x05\xf5\x87WsT\xc1\\\xdc\xd6\xe6\x1a\xc72,)g\xb9\xa2\xc6\xe3\xf5\x0eN+\xd4͜\xab\xb5\xb1\x80\xeb0*\x03\xe3a\xf4uk\x9dŕ\xe4q\x8eݎ\x1a\x03\xbf\xfc\a\xfe\x05y~\xbf_\x1bJ\xbe\xfe\xfcJ?\x8f\xdf[\xf9\xfcu\xdc\xd4ܢ\xc6ÎB\xa3\x92\xb1\xa8u\xd3`\xe7\x9656.\xc1\x8d\xca\x14\x9d\xf5\xa0fc*\xd4\xffA\u058bW\xe4\x1a뢶\xaf\x18\xaf\x92\x02\x91\xadi\xcb\xde:^\xce\xd5 M\xd1U\x98B\xea~B\x9a&ѫ<\xcb\xe0\xa2\xcc\xda2{Z\xfd\xea\x1a\xe6\x030r\xc6\x18hl#\xf4\xc1\xd4\xf3L\xff\x8c\xba\xaf0Q\xc1:\x89b)}\xb0`\xa0\xbd:l$\xbf\xd7\xf6\xa2NR\xc1N\xbe\xd8\n\xc4d:ַ\"\aI\xbaȩ\xf6\xbc<\xf1B\xe9\xa7-\xe3H\x1f\x04\xff;\xce\x1dGd۬\xcd\xc6\xfa\x9d\x8b\xcd\xfa\xb2\x96\x1bf\xd3=\xc4\xca\x05\xf8*\x13\x96\x90\v\xa8\x99{\x17\x91s\x12\u007fi\xd6:h\xcfh\x96\xf6|\xebo$W\xe4\x92]M\xa7\x00\x00\x00\x11\xe6IDAT\xe7hv\xbd20\x1eF_\xb7\xcc\"\xec\xef0\x9d\x8cb\xe0Ww\x94\xf3\xae؛YDm\x1d\x9f\xe1\xa3\x13[#\x0f\nl\xdd\x18\xec\x8b\x06\xb08-X.\xfd%\x15]\xf5\xa0ɦT\b\x95\x93\x8eK\x91\xf14\x1a\xb6}\xa9S:\x8c\x1f\xc8Z\x83\x8f6\xd8؇آ30G\xd3\xff\x844\xa3H\xddʫ4r\xb83W\xcb\x11qf?\x00\x16\xc5\x19c\xa0\xb5\x8d<\x8a\x94\xdą\xbc\xf7\x11\xe6)\x18_\xd1)\bBw\xa5\xa0\xb4\xfe@uS\x18\xfb\x97l\xbd:I\x05\xbb\xab\xa3c\x89\xa4`\xe4\x1c\x17cP\xad\xf6~ԟ\xe6\x97m\x94\xab\xdc.9pI\x17\xa6K\x9b\x8d\xc1Ngm\xd4r}F\xd9\xf4\x0e\xd1\xc7Փ\x972\xe2\xacp\xee \xae\xa7\x90\x85m/e\xce}\xa9\xfe\x9c\x10:\xe1\xe3\xb3\xda5sgqKhv\xbd20\x1eF_\xb7\xccF|}\xf0h\xe7\xf3\x86~u\x15\xec\x1c7\xd0\xffn\x9f`?\xa7\xb15\xf2\xa0\xc2ԍ\xc1\xfe*ي\x8d\xca(\x98\xea\x81ͦT\b]\xc2\xc200\xa3\x15\x19\xc1\xb6\xaf\xaa`͜:\x8a\x8dTH\x83O\x88U0\xddʫ\xecLG\xe4F\xd3!\xa4\xfd\x00X\x14g\x8c\x81\xd6v\xc4\nfT\xde\xfb\b\xf3\x14\xec\xa2[&\x80\xa4G\x01\x9eq\x1b\u007f\x97\\\xb1\xbbt\x92*\xe4#mnU\x92\xd2i*8\x0e\xa1C\x0e٫z\x95\xcbQ\x9e\x95\xa2\xe6\x15,\xd7fc\x10\xf3\xf8\xb9\xb3F\xd9\xf4\x0eq\x96\xa3\xc2B\x9d-\x91\x02\x1f\xe4+\xbe\xaf\xbep\x11\x1e\xc2!\r\x1d\x8e\xac\x9d\x87\xfcyK\x94\xec\xa1e`=\x8c\xban\x99\xc7Q\x87\rQ\x053\xf0\xab\xab`\x03\xb6s5\\Y\x0f7\xa0\xb15\xf2\xa0\xc0֍\x81mTF\xc1\x14\x0f\x9alJ\x85\x10ZS\x82\x8e\xa7\x87\xb9\\\x99\xf6U\x9d\xd5\xd0B\x8bD,\xa4\xee'4,\x92?\xac\xf2*5\xe4n\xf8q\xda\ac?\x00\x16\xc5\x19c\xa0\xb5\x1d\xb1\x82\x19\x95\xf7>\xc2<\x05\x13\x82\x84vO0(\b\x95>\xba\xebL\x85\xb1\x82m\xe5zt\x92*\xd2Gz\xee3\xedi\xba\xf59\xf4\x9c\x12\xf5W\xafr\xe5[p.}\x99\xebB\x06g7\xb2\xd3\xdc\xf5\x1co\x94M\xef\x10\x9fq\xb5Ԍ8+\x9a{\x96\x82\vv\x96\xf4\xe7\xfa\x1a\xed\xb5\x88e\xd1r2\x88)4V0\xc6\xc3\xe8\xebF\x14\xcc.*\x98\x91_\ua87e\x17iXԘ\xb7r\xd1!\xdaSPm\x8d<\xa8\xb9\x98\xba1\xd8\xe9-c\xb1Q\xf5\x14L\x93\x8d\x11\xd4Î\xc1p\xbf\xc5`ۗ:\xa3\x9d\xe0V\xb6\x0f\x16\xa1\x90\xfa\x9f\x10\xdb$\xfa\x95W\xe9\xe5\xd6\xf4\x9e[\xb0\x92\x9cȚ\xb3\x84Aq\xc6\x18hmG\xac`F彏0O\xc1D\xc48X\xd5\x01\xb2\r7\x8a\x8c\xd4\x05\x93?\xd2̝\xdaӴ\xc3~Ůđ\x87_\xe5\xcd4\x8a\xd1(Ɗ\xf4\x15́Oo~n\x9ea6\xddC,\xcf\xea\xc3c\t;qv\\\f\x94\x94\xe1\xef\xc9r\xee8I\xe6i\xa3xYī\xb0\xc4X\xc1\x18\x0f\xa3\xaf\x1b\xa3`F~\xf3pe\xaf\x84\xde\xf0{\xfe%\xdbq\xeeE\xea[\xb55\xf2\xa0\xc0֍\xc1\x9eE\"S\x8b\U000a4fc6)\x98&\x1b\xa3`\x83\x8e\xc3\xe9\xf2 \xb2\xb7|\xd8-N\xb6}\xd3\xf0\x89 ,'\xce\xfa3\xf3\x06\xf1\xcbV\"\xf6\x91\n\xa9\xff\t\xb1M\xa2_y\x95\xb3\x9c\x83\xe3\xf2\xe8\\\x1f\xcdY\xa2\xe7\x8c1\xd0\xda2\n\xa6SM\x82\xd4fF彏0W\xc1\x84@\xbb'p\x8d\xcchm\xea\xec\xee\f\x17\xc9/Q\xfb]%:]0yN\xbe\u007fV\xc9\x15\xbf\xcdՁκl~r\x1a\t\x99\xab3i\xc7n\xf0\x03\xbfߎmx$tлA\xbd4c\x11\xb7\xb3y'WDg[3\xd9T\xc8m\xb3\xfa\x05\xe9=\x06\xd9\xf4\x0f\x81.\xa4e\x95\x97\xa5s\xb6w\xf1hb'\xf7|\xe3!\x179C˹\xb4\xb2f\x9c\xd4Frʹ\xc2\xda\xdd\xcb8\xc7[\x1dFeP<\x8c\xben\x17\xd2k\xfa\x1bm\xe7\xfa\x9fϻd\xe8\xb7\xdc^s(/-\xe4n\xef\xee\xb4Y\xc2\x02\xfb\ue4062\xf0\xa0\xa0\xd6M\xe3\xccέ\xe9h]\x89\x1b\x95):\xebAͦ\xa9\x10>\xde\xdct\xb9\x9b^\xc0\xa5\xf5!-l\xfb\xaet\xec\u07bd\\\xfc\x00Z\xed\x8bj\x9b\xb7r\xf5#(\xa4\xfe'\xa46\x89~\xe5Y\xce\xd9[\x9b\xfdW\xc4B\xb2g\x89\x8e3\x8d\x81\x9a\xa4s\xf2k\xe4:\xebT\x939ό\xca{\x1fa\xae\x82\x05H\x18\xac\x8a$\x9a\xaa+\xeaZ\xd4xE(\xd7ӊt\x92*\xca\xef\"\xb9\x9a\x17\xf1\xc6v\x81L\x99\xa1_L5\xf6\x1ajqVz\xbf\x1e\x9d\x13\x13b\xe0A\xa8Y\x92\xb6\xa4V\xa0\xbfxc\xb3)\xd8K\\\xb32\x8b\xae \x83l\xfa\x87\xc0\xfd\xaf\x82\xf4\xb9%\xefڨ\xb3\xe3y\x8e\xf4\x95\xe4˵qey\x96-3/\xe4t\x13j\x16\xd8\x1d\x85\xf5\vlyFeP<\x8c\xben\xb8\x83\xd08\x83Kk\x14\xc37\xfa~\a\xb6\xa6\xdb\xf3B'@\x9c\x9dU\x86U\xac#\xd4֠d2j\xdd4\xce\x16\x95\x17Π\x8d\xca\x14\x9d\xf5\xa0f\xd3T\x88\x84ȕ\xfew}ڰI\x1al\xfb\xf6\xe4\xd9g\xac~U,NOa\u058c\xe5\x87FRH\xfdOHm\x12\xfdʳ|`#嵭<\x87BΒ\xe1\xce4\x06j\xd2%5\x89\xd8\xf5ԩ&s\x9e\x19\x95\xf7>\xc2\\\x05\x1b1\xafr\x1f\xeb$\xc7\x03et\x06L\x00\xfa\xed\xea\xc5z\x88\v\xed\x9cL\x00\xae\xa7\xbdx]\x10\xfa\xce\x16\xa6G\xabp\x13\xb2\x9a\x13\x88\x18Q0\xf3\x1e\xab\x03\n6\x91hT\xee\xbd\n\xef\xce\x1a\xdf\x13ad\x1c\x92F\xb9\x82#4\xfauwL\xd0jN bD\xc1\xcc\x03\x14l\xc2Pފ\xf2\xca\xe4?\xae8J\x8c\x83\x0e\xe6qV\xba\xf1y\x8e\xd3\r\xc0\xdf1\x13\xb4\x9a\x13\bP\xb0\xb0\x88\x91[`\"\xd0\xcf-{)s\xa2\x8f\xa8\x04W\x9a\xab\xb1\xb5\x11o#Y\x02\xd1\x01\x14,,4r\xdb\x1b\xc9\n\x18\x17\xca\xd2\xf2\"<\xf8o\"pxu\xa6-sMtƐ@d@\xc1\x00\x00\x88]@\xc1\x00\x00\x88]@\xc1\x00\x00\x88]@\xc1\x00\x00\x88]@\xc1\x00\x00\x88]@\xc1\x00\x00\x88]@\xc1\x00\x00\x88]@\xc1\x00\x00\x88]bK\xc1\xcc\xfby$\x00\x00\x13\x11\x93\x15\xac\xdd\xed\xd5I\x1a\xf11\xb7S')3ҕ\xd8k\x8d\x97\xebR\xd6\xe7\x02\x00 &0W\xc1\xf8\x8ac\x95Ó\x86\x14\xa9\xeb\xdc\x16\r[\xf2v\xc4+\xb1\xf7\xf9\x97\x1b\xfeZ[Z\x9f\v\x00\x80\xd8\xc0\\\x05\xf36uW\x0eO\x1a\xd1Õ\xe8$U\x86=JΈ\x02\xe3\xe7M\f{\xca4\x00\x00\x13\x18S\x15\xac\xdd\xc3\xcb\xebE2IC\\j\xbf\xcb5\xbc\vv\a\x80\x82\x01\xc0=\x82\x99\n\xc6Wt\xc9+\xde2ICzm[u\x92\x12\xba\xab\xd77\xe2}\xe5\xca:\xf5\xea\xb2\xeeX\xc1\xb6\xe2\x9dv\xb2ʌ\xbar\xfc\x95\xa2\xcc\xf4B\x18E\x02@,a\xa6\x82y\x9b\x945\xbb\x99\xa4!.\xdb%\x9d\xa4\x8c\xde\xea\xf5\xfd\xfeYe\xd7\xe5u\xea\x99eݱ\x82])\xe2jȃ\xbfԕ\xe3{f-\xa8?\xbc\x9a\x03\x05\x03\x80\x18\xc2D\x05\xeb\xf4\xf0\xb2l1ICzm/\xea$Y\x94U\xbb\x94\xd5둋,\x97\xf0<\x99x\xc1.\xeb\x8e\x15\xac\xc6N\x9f\xe0Ĭ\x1c\xbfrA?Ys\v\x14\f\x00b\b\xf3\x14\x8c\xaf\xe8\x14\x04\xa1\xbbR\x10ؤ1/\xa9O\x1ad\x92,\x8a\x82\x11\xc5\x12\x03Z\xad\xf6~ԟF\x16\xd0f\x97u/(/\xe3ę\x17\xea\xca\xf1}t\x89!q\x8dT\x00\x00b\x04\xf3\x14\xec\xa2[&\xc0$\r\xcd#.y\xab\xb7r*\x12\x1c\x87\xd0!\xba:\x04\xbb\xac{\x81c\xc6\"q-+u\xe5\xf8\xb3\x1c\xd19\x88\xe4\x03@La\x9e\x82\tAB\xbb'\x18\x14\x98\xa4\xa1\xf9Vu\x9dۭ:K\xde\x12t\x14\fm}\x0e=G\xa3\xfe\xec\xb2\xee\x05\x8e\v\xbd\xb3\xe8R\x8b\xea\xca\xf1\x9fq\xb5\xd4\f\x14\f\x00b\b\xf3\x14L\x84\t~\x85\x8d\x83\x8d\xa0\v\xa6\xab`\x1d\xf6+v\xbaT\a\xbb\xac;\x99M\xd1l#\xbb\x99\x95\xe3\x97g\xf5!\xd4c\x97\x14\xacww\f<\x92\x1d\x00\xee{\xccU0!\xd0\xee\t\\\vM\xeaQ\xa2\xf6\xbbJ\xf4\xba`\xfa\xab\xd7c\xb7\x99\xab3C\x96\x80\xef\xf3/w}0\xd8_\x90\xd9z\x9d]9\xfeBZVyY\xba\xb8N=Y\xec\xfdG\xc3\x0f\x02\x00\xc0\x04\xc3\\\x05\v\x90\xd8WUhR\x87\xebiE:I\x06\xfd\xd5\xeb15\xf6\x1a\xd1BYֽ\x96\u061d%s\xc5\xc8\xe2\x83\xea\xca\xf1=\x05\xe9sK\u07b5\x89\xd9\xea\x1d\xf5:G\x01\x00`ba\xae\x82\x8d\x98W\xb9\x8fu\x92\x00\x00\xdc\xe7Ĉ\x82\xc1cu\x00\x00\xd0!F\x14\f\x00\x00@\aP0\x00\x00b\x17P0\x00\x00b\x17P0\x00\x00b\x17P0\x00\x00b\x17P0\x00\x00b\x17P0\x00\x00b\x17P0\x00\x00b\x17P0\x00\x00b\x17P0\xf3\x18\xe8\xef\xef\x1fDh\x10\xbf\fD\xb2\x05\x00@\x0fP0\xd38\x16g\xb5Z\x13y>\x11\xbf\xc4\x1d\x8dd\r\x00\x80\x0e\xa0`c\x88wf\x10\xa1k3\r\xd6\"\xaf\xb6z[Z\xda\x11joi\xf1Z\xab\xf5m\x00\x00\b\x8b\xc9\n\xd6\ue997w\xbf\x87>c\xda\x13\x8d\xc1\xd4~\xabDR\x18oMI\x06\xb2\x12\x9ek\xf9I\x89sF\xbc\xb0\xee6k1}\x89ۦ\xfbv\xb5\xb5[Nv߁\x82\xdde\xd1Gʩ\xef;Ern\x871\xca9a\xfc&\x00\x8c#\xe6*\x18_q\x8c>\x98\x95w\x9f\t`\x82\x91\xecG\x02\u007f,>ׇ\xd9`\r\xe3Λ8r\xc9`\x98\x9d\xec\xceM\xe4#YI\xec\x8a\xf3\x88\t\uf8e5z\xefGR0\xdf\xe9\xe1\xfb\xd0]\x17}\xa4\xdcj\xcb~\xa5\r\xb3\xc7\xf9\xb9\xb1щ\xf9G\x8c\xdf\x04\x80q\xc4\\\x05\xf36uK\n\xa6\\\xccQ \x81v}*\xc3)\x18\x1aqG\x8a嚵\x14\t#\x15\xb0\x8b\xf1\x1b\xe4\xe4\xa6\x04\xbd\xeaER\xb0鋇\xef#\xdcU\xd1\xef\x80\xec\xbdd{\xd0y#\x8cM\x98\xfe\x19\x00\x8c'\xa6*X\xbb\x87\x0f\x8c\x99\x82u\xad\x8bdw\xc7tY\xef`\x00\x97\x9b\xach\x1d\x9f\x9c\xabc\x10I\xc1R\r\x14l\xac\x11\x15\xec7o\x80J\x011\x80\x99\n\xc6Wt\xa1\x91)X\xb5\xd5j-F\xc5x[\x8d\xf8\xc5\xc9\xf1)\xf3\xce\xe0\xbdg\x1e\xb5Z7u-\x9d\x9a8gPc-*\x18&\xdf\x1a\xef^7-qvw\x88\x87D\xab5\x8e>\xd0Z\xebaWjb\xea.m6\x86\x81$1\xbc\xb6\x8e\x18\xc4U\xe2>\x96uZ\xa8m\xd7¤\xf8\xe49tɸ\x81\xc9J\x17\fw\xc2\x12\xfb\xd10\xf4\x14\xec\xe8\xec\x94\xf8\xa49)\xb8w*\x05\xf3R\xb5\x85T\x8b\xae9ppiRʺuI\x9a\xf1e\xf7d\xc9\xc5dm=n7\xac\x9f\xbf\xb6\x81\xcaS\xdb\xe6\x15\xd9\xcfl^\x11\"U\xa2\x82a^qf\x1f|c\xd5\xfcͿG\xe8\x88\xd3\xe9܋\xf6\xe2\xed\x11tc>}\xc1|\x94\xedt\xee\xf9t\xfb\x8a\xec\xcd_0~\x99l\x000֘\xa9`\xde&\xa4(XS\xb5\xbb\xea\xa8\xcee.\xc2\x1f\x9d\xbc)\x88\x82\x9b\xa6\x1c\xe5\xf1\xb5\x9d뫞\x17ׂP\u007fuUʓ\x93S\xd6-\xb5j\xafфM\xfd\xfd\x8bI\x0f\xac\xb3\xeaQkRq\xe9\xe4\x85Z\x0f\xe8\xa4\xcf'\xaa\x9c\xc6Cn\xc2&濾\xa5\x9al,g|U\xd6b\x9f\x0f\xebS\xc0\x17\x8f\xb3\xb7\xe4&\x84\xd8\xfa\x12S\xb75\x15[i\xd4\xeb\xb4էf=fmA\xc3\xd0Q\xb0\x93֥\xd5M\xee$+\x96\xaac\xbe'3|>_gH!\x95\xa2\xb3\a\x1e\x98\x96\xbc\xab8!\xb1b6\x1bo\x1b\U00014284\xdc\x1fّ\xbd\xe7Ԟ\xec\xed8\xf5\xcb\xefo?r\xea\xe03\xce/4\xef\xa3\xec\x9fܺ\xb5\xe5\r\x9c\xf8\xe8H\xb63g\xef;\xf3\xb7 t\xa3m\xfeO>G\x9f\xef}\xba\r\x8f-Ϸ\xb5\x89*w\xebȑ\x15\xab\xe6缱\xfd\xfbW\x19\xbfL6\x00\x18kLT\xb0N\x0f\xaf*X\xe5\x99\xee\xce\xea*㻇\xb9dH\xb5\x98\f\xc6\xf8j2:K\x15\xe5%\xd5:\x1b\xff\x15\x12\x9aJ =\x8fybr\n\xbe\xea\x97&i=\x10\x12\xe5~\x9a\xe2\xe1\x80\xf5\x00\"\xdb\xfd\xdal,\xea(\x92\xaaHq\x02\xd2\xd8\xf6\xa7\xcc\xc1\x15\x18\xa8\xa6+.y\xad\x17Ռ\xba\xa3D\x1d\x05ەD\xfb\x82Sh\xa8\x8b\x19Ej\xaa)\x17]=p\x95\x15wIwYۑ\x86\xe0E\x11m8\xf0\x94\xf3\x94\xbcm\xc8!\xda\xd5\xf0th\x1f\x8c܉\xdc,&\x9f\xc6\x1d\xa9\xed9$\xb9\x83h\xde\xf6\x1d\xb2\x8d\xdcO[\xeb\xdcx\x03ݾ\xa1\xf1\xcbf\x03\x80\xb1\xc5<\x05\xe3+:\x05A\xe8\xae\x14\xf0\xe5*\xb4\x93\xeeW\xbfG\xa7\xa7\"\xe1K\xe4\xf1\x10\x8avk\x82\xbb\xe6L\x9dL\x86W\x98T\xbd\x18yBnKK\xaa\xa4`D\xb1D\xa5a< V\xc1d\x0f\xb9\xd3\xe8˴\\m6\x16}\x05Sl\xf7\x13!\x91\xa9\xd3*\x98\xce*L:\n֝<5\xdf}F\x10\x85\x9cU0\xb6\x9a\x8a\x82)\a\xde0\x05\r\x0f\xd2]\x94g\x95h{\xa8;\xd6җU\xaf t5g\xc5\xeb\a\u007fu;4ޕ\xbd\xe3\xfc\xf9\xb5\x92\x82\x11\xc5ڛM\x92mٷЭ\xf9m\xb2\x8d\xa2`\xd9W\xc5\x04\xe3\x97\xcd\x06\x00c\x8by\nv\xd1-\x13\x90w\x1d\xad3\xb4\x1eL\xaaCuI\xa4oҒ\x9c\xb2\xa1Η!)\xd8t\x1d[\"/\xfb\x9b\x94\xa4\xa44\xaa\a\x82\xaa`\xb2\x87\x99\xa2\xe6͙\xae\xcdƢ\xaf`J\xb2\xd4\xca\f\x83[\u0601c\x8b\xf5\x18\x1a\x86^\x1c\x8cw/\x9efM\x12珱\n\xc6VSQ0\xe6\xc0A\xd2{\f\xe9\x83\xf9\xbc\"\xcch\x16\xb3QԦ\xcd\xeb\xf1\xe6\xc6\xc1-\xab\x9cϼ\xa3\x13\a;զ$%)\xfa\xe2\xe9\x13\xe8\xc43\xb2\xa9\xaa`\xeb\xa5\x04\xeb\x97\xc9\x06\x00c\x8by\n&\x04\t\xed\x9e`P@M\xa22\xf8\xc2\xdc\xea\xcb_\x88\x16\xe6\x93Ĵ\x99d4\xb5PR\xb0\x90X\x15E\x8a\xe4\x9f\tj\xa5H\xf1@P\x15L\xf6\x90;\x95\xbeL\xcdE#U\xb0M!\n\xd6defp\xf1\xca\xfd\x04\xf2v\xbc\xce\x1c\f\xbd8\x18\x89\xfe\xf3U\x89\xe4~\x82\xa8`\x15\xd4FS\xcd\xe1\n\xd6\x1d7\xa7\xfb\xccԙ#\x9af\xb1\x83\x06\xeeo\xaf\xc0ݤ\xf3{p\xf2Ƒ\xec\x06\xad\x85\xa4N\x1f\xdd\xd0J\xd1\xeb[Ж\xd7Cl\xb0\x82m\x91\x12\x8c_P0`\xfc0O\xc1D\xc48\x98\x97v\xbe\xaey\x98QX(-\t\x81\x04ګI!W\xb3\x90*)\x98ތ\x03I;\x927h\xa5H\xf1@P\x15L\xf6\xe0\xa5#\xbd**R\x11\x15,\x11\xfb\x16\xa6\x87(\x18\x9f\x9cA\xc6\u007f\xf9\xe24\x8e\xc5S\x15E\x11\xa6\xcdA\xc3\xd1Q\xb0b\x1a\x8bC\x19Th32\xf0\x88Y|CS\xcd\xe1\nvښd\xb5f(]ٰ\x9c\xa2\xb7\x11\x8f\x90x\xd5^\x1a\xb4B\x1b_\xa1oto\x93\x86\xbd\x92:\xe5\xec\xd1J\xd1/\xb2\xaff\xffB\xf62\\\xc1\x18\xbf\xa0`\xc0\xf8a\xae\x82\t\x81vO\xe0\x1a\xbez\xdc\a\xba\xbaOVx\xc3\xf4\"\x84\xe4\xd9\xc9\xf4\xedb\xeb\xe2]\xdbR\xf1P\xabe\xb0\x85ޯc\xe2M\x04yN\xbeo\xf2\xba\x80/>\xb7\x05\x9d\u038d'7\x10U\x0f\x03->_B\xae\xef(\x8f4\x1e\x96\xc6m\xf0n\x88[Jo52\xd9\x14\xc4{\x91-\xd4\xc5̤m\xdbfZ\x1f\xf5tjl}\x8fMs\xefϷVP\xf3\xae8\xe5\xce`\xa9Uoz\xbd\xae\x82%\x16{\xebr\xc5ۘ\xc5\t\xa5u\xb3\x13\xbb5\x85T\x8b\xce\x1e\xf8tB\x93\xd7\x17\x18Q\x17\f\xa1\xed\xce='\xf68I\\~\xafs\xfe\xde\x13'v8\xc5\x11\xe3<+\x95YyN~\xdb\xfc7\xae\xe2\xe4\xcfo\xff\xf2\x95\xec6\x12뺝\xb3Y\xfc\xa1\xd1ퟷQ\x9b\x1b\xe8\x8b_\xb4\xad\xda\xd8\xd6\xf6\xa9֯6\x1b\x00\x8c)\xe6*X\x80\x84\xc1H\xd7'\xd8T\xe5\U000761fd\x06K\x13DE\x10J\x9fLHZ\xec\x99\x1a\x9fq&\x8e\x06\xaaC\xfa7\xca\xef\"\xad\xa5\xf9x\x13\xdfN\x9e\xfd\x90\xcfz8)泺\x91ƃ@\xe7\x83\td\xaa\x95&\x9b\xc4\xc0\x14j\xfbh'\xf9\xa3+#q\xf2\xec\r\xd8@k۵8e\xf2t9\x98\xb7\xe91)\xf8u4Qwrm\xb5\xb5K~\xbaN\x97\xa4`\x95\x19\xc5)\xf1\xc9\x19b\xe4j \u007fJb\x06\xee4\xb2\x85T\x8b\xce\x1e\xf8X<\xd9\x17\x9f\x11\x12\b\xd3\xe7v\xc3Zi>\xd8\xc1\x8d{Wd\xe7l\x94\xa2\xf3\x9e$7y9\xe5\x94ix\x05o\xb2\u007fEf\u007f\xd1^Z\x834\xdc\xfc\xa5\xf4\xfeA\xf4\x91\x98ج\xf5\x1b\x92\r\x00\xc6\x12s\x15\xec\xdef]<ե\xaa\xf8\\\xed\x8c[\t:iUz\xba\x0e\x9d\xc3q\xb7\x04\x13\U000c30c3\xfcɅSF\xfa\x8b'\x00\xb8W\x00\x05\x1bCJS\xc8\xd3u\x92\xf5\x1fM\x81\x06ϴ\xc8O\xd7i9\xa3\xabq#\xa4N\x9c?\x86\x84\xa4\xd1\xe8 \x00\xc4\"\xa0`\xb1\xcf\xe98q\xf8\xd8\x1e\x17\xe6N\b\x00ܓ\x80\x82\xc5>Bnb~\x95\xaf*?Q\xef\xf7\xe3\x00pO\x03\nv/\xe0\x9d\x9d\x1c\x9f<\xe7\x0e\x1e\x9c\x01\x00\xf7\b\xa0`\x00\x00\xc4.\xa0`\x00\x00\xc4.CC\xff\x1f\xf8\xaa\xf0z\xf7Oɏ\x00\x00\x00\x00IEND\xaeB`\x82",
+
+	"analysis/help.html": `<!--{
+        "Title": "Static analysis features of godoc"
+}-->
+
+<style>
+  span.err { 'font-size:120%; color:darkred; background-color: yellow; }
+  img.ss { margin-left: 1in; } /* screenshot */
+  img.dotted { border: thin dotted; }
+</style>
+
+<!-- Images were grabbed from Chrome/Linux at 150% zoom, and are
+     displayed at 66% of natural size.  This allows users to zoom a
+     little before seeing pixels. -->
+
+<p>
+  When invoked with the <code>-analysis</code> flag, godoc performs
+  static analysis on the Go packages it indexes and displays the
+  results in the source and package views.  This document provides a
+  brief tour of these features.
+</p>
+
+<h2>Type analysis features</h2>
+<p>
+  <code>godoc -analysis=type</code> performs static checking similar
+  to that done by a compiler: it detects ill-formed programs, resolves
+  each identifier to the entity it denotes, computes the type of each
+  expression and the method set of each type, and determines which
+  types are assignable to each interface type.
+
+  <b>Type analysis</b> is relatively quick, requiring about 10 seconds for
+  the &gt;200 packages of the standard library, for example.
+</p>
+
+<h3>Compiler errors</h3>
+<p>
+  If any source file contains a compilation error, the source view
+  will highlight the errant location in red.  Hovering over it
+  displays the error message.
+</p>
+<img class="ss" width='811' src='error1.png'><br/>
+
+<h3>Identifier resolution</h3>
+<p>
+  In the source view, every referring identifier is annotated with
+  information about the language entity it refers to: a package,
+  constant, variable, type, function or statement label.
+
+  Hovering over the identifier reveals the entity's kind and type
+  (e.g. <code>var x int</code> or <code>func f
+  func(int) string</code>).
+</p>
+<img class="ss" width='652' src='ident-field.png'><br/>
+<br/>
+<img class="ss" width='652' src='ident-func.png'>
+<p>
+  Clicking the link takes you to the entity's definition.
+</p>
+<img class="ss" width='652' src='ident-def.png'><br/>
+
+<h3>Type information: size/alignment, method set, interfaces</h3>
+<p>
+  Clicking on the identifier that defines a named type causes a panel
+  to appear, displaying information about the named type, including
+  its size and alignment in bytes, its
+  <a href='http://golang.org/ref/spec#Method_sets'>method set</a>, and its
+  <i>implements</i> relation: the set of types T that are assignable to
+  or from this type U where at least one of T or U is an interface.
+
+  This example shows information about <code>net/rpc.methodType</code>.
+</p>
+<img class="ss" width='470' src='typeinfo-src.png'>
+<p>
+  The method set includes not only the declared methods of the type,
+  but also any methods "promoted" from anonymous fields of structs,
+  such as <code>sync.Mutex</code> in this example.
+
+  In addition, the receiver type is displayed as <code>*T</code> or
+  <code>T</code> depending on whether it requires the address or just
+  a copy of the receiver value.
+</p>
+<p>
+  The method set and <i>implements</i> relation are also available
+  via the package view.
+</p>
+<img class="ss dotted" width='716' src='typeinfo-pkg.png'>
+
+<h2>Pointer analysis features</h2>
+<p>
+  <code>godoc -analysis=pointer</code> additionally performs a precise
+  whole-program <b>pointer analysis</b>.  In other words, it
+  approximates the set of memory locations to which each
+  reference&mdash;not just vars of kind <code>*T</code>, but also
+  <code>[]T</code>, <code>func</code>, <code>map</code>,
+  <code>chan</code>, and <code>interface</code>&mdash;may refer.  This
+  information reveals the possible destinations of each dynamic call
+  (via a <code>func</code> variable or interface method), and the
+  relationship between send and receive operations on the same
+  channel.
+</p>
+<p>
+  Compared to type analysis, pointer analysis requires more time and
+  memory, and is impractical for code bases exceeding a million lines.
+</p>
+
+<h3>Call graph navigation</h3>
+<p>
+  When pointer analysis is complete, the source view annotates the
+  code with <b>callers</b> and <b>callees</b> information: callers
+  information is associated with the <code>func</code> keyword that
+  declares a function, and callees information is associated with the
+  open paren '<span style="color: dark-blue"><code>(</code></span>' of
+  a function call.
+</p>
+<p>
+  In this example, hovering over the declaration of the
+  <code>rot13</code> function (defined in strings/strings_test.go)
+  reveals that it is called in exactly one place.
+</p>
+<img class="ss" width='612' src='callers1.png'>
+<p>
+  Clicking the link navigates to the sole caller.  (If there were
+  multiple callers, a list of choices would be displayed first.)
+</p>
+<img class="ss" width='680' src='callers2.png'>
+<p>
+  Notice that hovering over this call reveals that there are 19
+  possible callees at this site, of which our <code>rot13</code>
+  function was just one: this is a dynamic call through a variable of
+  type <code>func(rune) rune</code>.
+
+  Clicking on the call brings up the list of all 19 potential callees,
+  shown truncated.  Many of them are anonymous functions.
+</p>
+<img class="ss" width='564' src='call3.png'>
+<p>
+  Pointer analysis gives a very precise approximation of the call
+  graph compared to type-based techniques.
+
+  As a case in point, the next example shows the dynamic call inside
+  the <code>testing</code> package responsible for calling all
+  user-defined functions named <code>Example<i>XYZ</i></code>.
+</p>
+<img class="ss" width='361' src='call-eg.png'>
+<p>
+  Recall that all such functions have type <code>func()</code>,
+  i.e. no arguments and no results.  A type-based approximation could
+  only conclude that this call might dispatch to any function matching
+  that type&mdash;and these are very numerous in most
+  programs&mdash;but pointer analysis can track the flow of specific
+  <code>func</code> values through the testing package.
+
+  As an indication of its precision, the result contains only
+  functions whose name starts with <code>Example</code>.
+</p>
+
+<h3>Intra-package call graph</h3>
+<p>
+  The same call graph information is presented in a very different way
+  in the package view.  For each package, an interactive tree view
+  allows exploration of the call graph as it relates to just that
+  package; all functions from other packages are elided.
+
+  The roots of the tree are the external entry points of the package:
+  not only its exported functions, but also any unexported or
+  anonymous functions that are called (dynamically) from outside the
+  package.
+</p>
+<p>
+  This example shows the entry points of the
+  <code>path/filepath</code> package, with the call graph for
+  <code>Glob</code> expanded several levels
+</p>
+<img class="ss dotted" width='501' src='ipcg-pkg.png'>
+<p>
+  Notice that the nodes for Glob and Join appear multiple times: the
+  tree is a partial unrolling of a cyclic graph; the full unrolling
+  is in general infinite.
+</p>
+<p>
+  For each function documented in the package view, another
+  interactive tree view allows exploration of the same graph starting
+  at that function.
+
+  This is a portion of the internal graph of
+  <code>net/http.ListenAndServe</code>.
+</p>
+<img class="ss dotted" width='455' src='ipcg-func.png'>
+
+<h3>Channel peers (send ↔ receive)</h3>
+<p>
+  Because concurrent Go programs use channels to pass not just values
+  but also control between different goroutines, it is natural when
+  reading Go code to want to navigate from a channel send to the
+  corresponding receive so as to understand the sequence of events.
+</p>
+<p>
+  Godoc annotates every channel operation&mdash;make, send, range,
+  receive, close&mdash;with a link to a panel displaying information
+  about other operations that might alias the same channel.
+</p>
+<p>
+  This example, from the tests of <code>net/http</code>, shows a send
+  operation on a <code>chan bool</code>.
+</p>
+<img class="ss" width='811' src='chan1.png'>
+<p>
+  Clicking on the <code>&lt;-</code> send operator reveals that this
+  channel is made at a unique location (line 332) and that there are
+  three receive operations that might read this value.
+
+  It hardly needs pointing out that some channel element types are
+  very widely used (e.g. struct{}, bool, int, interface{}) and that a
+  typical Go program might contain dozens of receive operations on a
+  value of type <code>chan bool</code>; yet the pointer analysis is
+  able to distinguish operations on channels at a much finer precision
+  than based on their type alone.
+</p>
+<p>
+  Notice also that the send occurs in a different (anonymous) function
+  from the outer one containing the <code>make</code> and the receive
+  operations.
+</p>
+<p>
+  Here's another example of send on a different <code>chan
+  bool</code>, also in package <code>net/http</code>:
+</p>
+<img class="ss" width='774' src='chan2a.png'>
+<p>
+  The analysis finds just one receive operation that might receive
+  from this channel, in the test for this feature.
+</p>
+<img class="ss" width='737' src='chan2b.png'>
+
+<h2>Known issues</h2>
+<p>
+  All analysis results pertain to exactly
+  one configuration (e.g. amd64 linux).  Files that are conditionally
+  compiled based on different platforms or build tags are not visible
+  to the analysis.
+</p>
+<p>
+  Files that <code>import "C"</code> require
+  preprocessing by the cgo tool.  The file offsets after preprocessing
+  do not align with the unpreprocessed file, so markup is misaligned.
+</p>
+<p>
+  Files are not periodically re-analyzed.
+  If the files change underneath the running server, the displayed
+  markup is misaligned.
+</p>
+<p>
+  Additional issues are listed at
+  <a href='https://go.googlesource.com/tools/+/master/godoc/analysis/README'>tools/godoc/analysis/README</a>.
+</p>
+`,
+
+	"analysis/ident-def.png": "\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x03\xd2\x00\x00\x00\xf5\b\x03\x00\x00\x00\x8b\f=\xff\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x02\xfdPLTE!# #$\"$%#($#&'%'(&-'\")+(4,\",.+01/>/\"241A2%685G6$8:7;<:Q9$>@=W>#AB@CEB\\B'cC$GIF\x00f\x00\x00g\x00\x00h\x00gF'\x00i\x01KLJ\x00j\x02\x02k\x03\x04l\x05mJ&\x06m\x06sJ(OQN\vo\b\x0ep\nwN&\nq\x16TUS\x10q\f\fr\x17\x0fs\x18~R%WYV\x12u\x1a,`\xae7]\xad\x15v\x1c\x86T)\x16w\x1d[]Z9a\xab\x19y\x1e^_];b\xac<c\xad\x8dZ(>e\xaf)z ac`+{\"(|*\x92]%cebAh\xb2egd+\u007f,\x9a_)Li\xafDl\xb0.\x81.ikh0\x830Ho\xb31\x841/\x858Jq\xb6mol\xa3f);\x86:Us\xb3\xabg->\x88<Wu\xb5\xaej(sur@\x8b>B\x8c@\xb3m,vxu@\x8dGC\x8dA\\z\xbbxzwI\x8dH]}\xb7K\x8fJ\xb9r*_\x80\xbaM\x91L}\u007f|\xc1s-O\x93MP\x94Oc\x84\xbeN\x95U\x81\x83\x80\xc7x+W\x95VX\x97Xm\x87\xbcY\x98Y\xd1z(Z\x99Z[\x9aZ\x87\x89\x86\\\x9b[r\x8c\xc2\xd6~-^\x9d]\\\x9dc\x8a\x8c\x89d\x9ddz\x8f\xbff\x9ff\x8f\x91\x8eh\xa1hޅ+~\x93\xc4j\xa3j\x92\x94\x91k\xa4ky\x97\xc6s\xa4lq\xa5s\x95\x97\x94\xec\x8a,\x83\x9bŘ\x9a\x96\x9a\x9b\x98u\xaaw\x86\x9e\xc8\xf1\x8e/\x9b\x9d\x9a~\xaay\x88\xa0˞\xa0\x9d\x80\xad|\xf7\x93-\xa0\xa2\x9f\xfd\x92/\x81\xb0\x85\xa2\xa4\xa1\x92\xa5\xca\xff\x952\x82\xb2\x86\xa4\xa6\xa3\x83\xb3\x87\x8b\xb2\x88\xa6\xa8\xa5\x96\xa9\u038d\xb5\x8a\xa9\xab\xa8\x8e\xb6\x8c\x9e\xad͍\xb8\x93\xac\xae\xab\x95\xb8\x95\xa1\xb1ї\xba\x96\xaf\xb1\xae\x98\xbb\x98\xa4\xb3Բ\xb4\xb0\xa5\xb5՛\xbe\x9a\xb5\xb7\xb4\xac\xb7ѣ\xbf\x9d\xa2\xc0\xa4\xb7\xb9\xb6\xa4¦\xb9\xbb\xb8\xa5Ĩ\xb1\xbd\u05fb\xbd\xba\xa8Ǫ\xb7\xbfԯƫ\xbe\xc0\xbd\xb9\xc1\xd6\xc0¾\xb2ɮ\xc1\xc3\xc0\xbb\xc3ؼ\xc4ٱ̶\xc4\xc6ó\u0378\xb9̸\xc1\xc8\u07bb\xca\xde\xc7\xc9ƻκ\xbdϻ\xca\xcc\xc8\xc7\xcbۿҾ\xc4\xcf\xdd\xcd\xcf\xcc\xcb\xcf\xdf\xc8\xd3\xc1\xc6\xd4\xc7\xcd\xd1\xe1\xd0\xd2\xcf\xc8\xd6\xca\xd2\xd2\xdd\xd2\xd4\xd1\xca\xd8\xcc\xd3\xd5\xd2\xce\xd6\xdf\xcc\xda\xcd\xd5\xd7\xd4\xd6\xd8\xd5\xcd\xdc\xcf\xd4\xdb\xd0\xd8\xd9\xe3\xd2\xdb\xe3\xd5\xdc\xd1\xd9\xdb\xd8\xd7\xde\xd3\xd5\xdf\xda\xdc\xde\xdb\xda\xdf\xe2\xd7\xe1\xdc\xe0\xde\xe2\xde\xe0\xdd\xd8\xe2\xdd\xdd\xe2\xe5\xe0\xe2\xdf\xe2\xe4\xe1\xdf\xe5\xe7\xe4\xe6\xe3\xe8\xe5\xea\xe2\xe7\xea\xe5\xe7\xe4\xe6\xe8\xe5\xe4\xe9\xec\xe7\xe9\xe6\xfe\xff\xfc\x93\x8dkM\x00\x00 \x00IDATx^\xed\x9d\u007ft\x14\xd5\xdd\xff\a%\x064*\x15\xe1y<\xb3=lbJ0@\x94\x86F\xac(\x98o崆\xf4\x89i\xfa\x8d\xf6\xa4R\u007f`A\x10\x1a͓ñ\"\x02\x15\x1e\x8c\xf5l\xea\x81ش\x91`h\xf6(\xb89r\xb2\x12\xe4Ⱥ(<\x12\xda''\x94\xd2\xf6!\xc5\b\xc8S(ȓv\xd7Գ\xde\xef\xf9\xde{\xe7\u05fd\xb3wfv\x03a\xc8\xec\xe7\xf5\xc7\xee\xec\xe43\xf7\xde\xf9̼\xf7\xde;;\x99\xb7\xf4\xff.\x00\x04\x00\xc0e\x86\xe4$[;\x9c\n\a\x00\xe0R\x03\x92\x06\x00O\x01\x92\x06\x00O\x01\x92\x06\x00O\x01\x92\x06\x00O1\x92$]_/Z\x04\x00\x80\xc1=I\xf7w4\aZv\x9dS?u\a\x82\xb6ј?\xc9\xeb\x04\x8b\x84_˄9\xed\xc9\xdbX\xf0\xb1O.u\x8a\xb1'\xc5\x12\x9e\x95\xe5\x90S\xccP\xe9$;]\x82\x17z\x17\x14\x16TE\xca\xf6!\x94h\x983\xcd7\xed\x9eF\x84\xa2\xb2\\\x95@!\x1c\x11q*\xc7\x0e\xf1n\xa6\xb8\xf3\xa8\x0eW\x9f\xd7\xe7\x14\xa5s\xb6\xbe(wA\xc2)*\x89\xc8\xf4\x9dN!\x19\x85k\x92>\x11\b\xf6\x1c\xeb\xd9\xd2<@?\x9d\v\xecjr\xd8\x00\xd5\xe6\x9e\x16,\x12ο*\xb7G\xbb\x96\xca\r\xc9\x1bYp\xa0\xce\xef\x14\xe2\x80}\t\x91^\xe5\xfdT\xd4\xd7h\x13\x96\x1aZa&\x06\xf6E\v\x16\x1dƊ\xf6=ڹ}\x11\xfd\xee\x88\xc8\vں\xda\x17\xcaQ\x14\x8fȹQ\x14\vɑ\xb8p\xe3T\x11\xeff\x8a\xe9;\x1e\x8d\xb6\xc9\xfb\x9c\xa2t\xaa\x8b\xda\xea\xf2\xce;E%ѕ\xa7}kZ$*\xc3pM҇\x02\xc7\xf0\xeb@\xa0\x87~\nv\x1cs\x92t\x9f\xbcZ\xb0\xa8\x10\x91\U0006937b\xc4?\xa3TiL霴ö\x84\u007f[\xa2-\xf9/\\\xd2Faf\n\xd7◚j\xb2XG$\xbd\xba\x80\b8>\x05\xa7'&\xd7\xd6\xe1\xfeT\x8eYm\x9b\"\xe2\xddL9}\aS\x97\xf4y\xb9\x15%\x86\xd2\\\xbdc\xb7NT&ᚤ\x11\xed\x9eO\x06\xfa\xc9[w\xd3@\xbf\x93\xa4\xeb\xfc\xa7\x04\x8b\n\x8a\xa4\xe3\x05+Q\xaa\xa4|NZb[B\xf9Ŕt\xb9\xbd\xa4K\xe8\xe0\xa4W\xee\xc4\xfd\\\x05]]QC$\x1dɏ\x8d(I\xf7\xc9\x17:\x80\xb6NT&ឤ1\xb1\xa3-A\xf2\x15{.p\b9I\xfac\xdf*\xc1\xa2\x8a\"i\xb4\xb2\x90\xbcn\xafʻg\xb5r&\xf7-*\xf4\x15-\xa0\xfao+\xcf+k\xa3+O\xd5Θ\xb2H\x1d92\xb1\x1a\xbd>Yn\xe8\xab-ɭI\xb0\x01\x03Kf\xf8J\x16\xf6\x9aK\x88֔\xf8\n\x17\x94p%\xec\x94\x15\xca\xc9\a\xff\xda\xd5\xf7\xe4\xd5\x1c\xa7\u007f\x10ԶR\xf6\xb5'\a\x1c\xc6mX\x88f\xcarA\x9c+\xcc\f\x95\xf4\xd2\"\xba\xf3]x\xbb\xaaEt\xf5\xa2*\"\xe9\x8f\xcbC\x02IkU\xf0\x15\xa7\x91(v\xad\x06\x99\xb37\xa2F\x99\x8c\xfe\xd9D\xe9\x92^)\xcbۍ)\xb8 \x0f\x83\x85\xcan\xae6\x1f\x00\xb59\x89\"ߋ3gDV\x15T\x0fp\u06ddϓ\xd5\xcb\x15\\\xa2D\x87%SpQ\xd2'\x03\x18zy,\u0601\x1c%]\xef;.XTQ%\xdd.\xe3\xe3]/\xaf\xeaj\x9d^NN\x87H~\xf9\xab\x91F<\x9e#\x1d{CW\x83\xff)\xbc\xd4WpO\xfb\xce\x1a\x99\x9e\x93L\xacN<\x14*\x99\x93?su\xad|\x9c\r\xe8\x92\xeb#\xa1\x85\xf2A\xbe\x84\xdf\xcaO\x85\"\xed\x852W\x02\x9e\xe4Ω\x8eF\xa3t\x1a\xe0\x97KC;\x8b\x16Y\xd5\xf6\xa7\x90O\x9e\xde\xf8\xeb|> q\xa0Q>\x80ޔ\xb7\xf7\U00085661\x92>^\"\xd74\x1e\x18$\x9f˖\xd1\xd5\xcbʨ\xa4[\x17(\x92\x8e\u007f\xac\x10g\xab\xe0*N#Q\xecZ\x9dX\xb4\xa0\xe1o\xe8o\r\x05\xd1\x18\x9b(\xa4KZ\xb9\xa6\xa0N\xc1Ey@\xbdѐ\xdc\x18\x8d\x9e6\x1d\x00\xbd9\x91\x02yu\xb5\\\xb8\xb1\xa8\x95\xdb\fo\x17U\x06Bl\xa2\x84\x87%SpQ\xd2\xe8d\u007fwK3\xd6tO`\xc0Q\xd2\xc7}\xcf\n\x165TIw\xe1\xc9t\x97\xfc&\"g\x12\xfe掗\xd4\xe0\xb3x0t\x1e\xa1w\xe9\x85߈܅{\xb29\xf8,O\x94\xf9i\xbc\x1e\xcbQ.\x93\xbe`\x80\v\x88\x85H\xb7R\xb6\x10q%\xb4M\xa7=I\x81\xf9\xdca\x06\xdeEg\xf1I<\x1dY\xd6柂\xcf\xdcڤ\x80\xba\x8a\xb337\x9a\v3C%\x8d\xceo\xac\xf0\xc9S\xc8V\xa5\xb5tum)\x95\xf4\xe9\xdc\xd3T\xd2\xd5j\xffU\xc5WaT\x9cN\xa2\x98\xb5,\xf5K\xf1\xcb2\xf2\xd3\"\x93(\xc4\f\xbc\xa9\xee\x1a\xed\xb2\xce\f\xbc\xf5\x03\xc04\xa7\xa8\x16o\xb9\x13\xd5%\xff|\x99\xab\xcdm\xf4DY\x1d\x96\x8c\xc0MIc\xe2-\x1d\xe4\x12Y\"\x918ڔ\xb0;\x00+}\x1f\v\x165\xf4^\xfa<Zz\xc7 .-1\xb3\x9e\x9c;\xfa\x15\xd0\xfa2\xfaVZ\x87\xce\xcb\xf4\xb7\xae\x06rr1\xb1\x1c\xe5~u\x18\xc0\x06\x9cm\xab\xb9\xa3@.C\\\t\x9f\xce(Y\xd9ޛ\x184\x15\xc0J\x9al\xdbhS\x9b\xbfN\x18\x10/+z4\xa903\x8a\xa4It\xe4G\xe4\xb4W{\xe9\xa5J/\x8d\x16\xb4RI\xf7\xedT\xe8\xe3\xab0*N#Q\xecZ\x96Hn\f\xc5\xf2\xa2dQO\x14A i\xab\xac\xb3\x92\xd6\x0e\x80\xd1\x1cT\x14\u0085\r\xa0\xb5ː\x99dI[\x1d\x96\x8c\xc05I\xc7\x15\x01\xef\x0f$\x8e\x044\xfa-\xa3O\xf9\xeb\x05\x8b:\xaa\xa4\xd7\x16\xe0\xb3Z\xed\x92p/\xd1*\xeb?\xe0T)\xf2x\xb4\x02\xf5\xca\xf4\xbc\xa3'\x17\x13\xcbQ\xaeM\\\x99\x80\x83E%k;\xa3\xd5e\x88+\x01\x9do_R*\x17\xbdj*\xc0|y̮6\xab\x80\x90~a\xc9A\xd2\a\xe9\x148Q\x857\xabR6]\xa8̥Q\xa8\xcc<\x97f\xab0*N#Q\xdc\xce3$\n;Qg!9\xa6F\xa2\b\x02I[e\x9d\x95\xb4v\x00\x8c栢w\xd1A\x1fB\xebR\x91\xb4\xd5a\xc9\bܒt\xa2i\a}ǒN\x9c$t\aN\x9e\xb4\xee\xa6W\xc9}\x82E\x1dE҃\xd3\xf1!\xad\xbd\xa3\x97r\x96\xac5:\x9f;\xe8[I\x1d:+\xd3k?tV\xc7\xc4r\x94/R\x17\x98\x80\xd2\n\"\x8eE\xf8LeK\xe8%\xb7\xbc\xfc=\x94\xdbf.\x81\x9c\\\xed\xa4\xab1Ne\x8b\xda,\x02N\x155\x94\x9c5\x17f\x90\xa0sk*颕tM\xc3\x1c<\xc4V\xa4P^\xa3H:\x96\x171I\x9a\xad¨8\x8dD\xb1k9V-D\x8b\xe8UK#Q\x04^\xd2\rvYg%\xad\x1d\x00\xa39\xa8(\x82\x0e\xfaS\x904I\x94\xd5a\xc9\bܒ4j\xee \xafd\xe0\xad`;\x97>M\a\x89\xe6E\x03E\xd2\xebș\x19Q\xe6h\rx\x1e\x1a+\xaa&C\xafU\xab\xc8В\xac\r\x91\xc1iE\t\x9e2\xf6\xe5*\xa7\xb2\x1eˡ\u007f\xdb3\x01%\xe4,K\x94\x913\x95)\xa1Q~\x97\x04T\x9b\a\x0e\xd5ո\xa5ʌ\x95\x11\x8e\xb06q\xc0`E\x03\xaa\xafN\x98\n3h#\xbd\xe5Y\xf9u\xbcX8\x93ܞ\x91 2X\x9dO\u007f\x97ΫW$\x8dꖙ$\xcdVaT\x9cN\xa2\x98\xb5\x1c\a\xfc\xa7\xfc\a\xc8\x02\x93(\xc4H:\x0f\u007f\xfb$*\xec\xb2\xceJZ;\x00LsR\x90\xb4\x9e(\xabÒ\x11\xb8&\xe9C\x81\x8e\x9ec=-\xea\xddc\x89\xfe\xee@\xff\x19\xcb\xe0\xb5FϼV\xd0I+w\x8f=\xa5\xdc=\xb6N^\x16\uab17\xb7#2\xc1+m\xebZEg\u007f\xb5\xf2\xba\xaeu2\xb9zt8ofc\xc34\xd9\xf7\xe6a.V'q\x80^9U\xe6\xebF@\xa3\xbc\xa4mc\xb9\\\xf8\xea\x01\xb6\x84F9\xbf\xa1\v\a\x98\xef\xbal\xf4\xff\xba\xb3:\xefSr\xa5\xb7\xee\x00\xea\xad\xf3EO\x89k\x13\a\xc4\xf7=;\xfd8\xea+X\xbd/\xce\x14\xc6\x12\x91\x17\x84ެ($+\v墆wq@\x1fY[\xd3\x19\xed\xac\x91;\xc9\xddc\xa1\x18\x8a\xe6\x99\u007f\xc4ҫ\xe0*N#Q\xecZ\x96Č\x9a\x19\xf4\x1b\x88Iԧ\xe4\xee\xb1\xd6h\x94\f0\xaa\xa6\xbf\xba\xb1\xc2:\xeb\xea\x15\xef\x03\t\xd3\x01ЛsxZk,\xe4\xeb\x8d-\xab\xe6\x86+\x83\xfb\xa2Q\u007f]4JO#=QV\x87%#pMҨ\u007fGK`\xebnu\x12\xd7O\xa6\xd2\xcdV\xa1\xa7\xf3j\x05\x8b\x06\xca=\xde%\xea=ޑ\xea\xc2)U]t\xb1o\xc9\xcc\xfc\x8aN\xb2\x94x\xbd,\xaf\xac\x8d\x9es}\v\xa7\x95\xac}\xd3'?\xcb\xc7j\xf4*3\xbdGM\x85%Z\xe7\xf8\xa7/m\x9f\xe3\xabfK\xd8^\xd5X\xe2+\xaaN:u⫦\xe5V\x1f\xa4\xf7x˾\xc3\xe4\xb7S\x8b\xda\xc4\x01\x11\x99\xfcB\xbbJV\xee\xd0\xd6\n\xe3\xe8,\xcf+x\x94ʪ\xa2\xbd\xa14o\xfaB\xf2M\x97h\x98S \x17\xcciL\xd0\x12B\xb8[,2Of\xb4*\xf8\x8a\xd3H\x14\xbb\x96\xa5\xd5\xdfJߙDթ\xb3f\xd2\xe7\xf6U\xe7\xe6\u05fch\x99\x87x\x01\x8d\xf4\xfd\xd9t\x00\xb4\xe6$\x8a\xf0\xfe\xe4\xcby!\xd3\x1c\xfc\xb7j\x15\xf4\xd8뉲:,\x19\x81{\x92N\x83\x17\xe5?\t\x16\x01\x00HfDH\x1a\xfe\xab\x12\x00ReDH\x1a\x00\x80T\x01I\x03\x80\xa7\x00I\x03\x80\xa7\x00I\x03\x80\xa7\x00I\x03\x80\xa7\x00I\x03\x80\xa7\x00I\x03\x80\xa7\x00I\x03\x80\xa7\x00I\x03\x80\xa7\x00I\x03\x80\xa7\x00I\x03\x80\xa7\x18I\x92\x86[\xbd\x01\xc0\x11\xf7$m\x18\xe8Ě\x94\xe7\x149\xf8BX\x1b\xe8\x10\x86\xcdF%U\xb7\x98\xa1\xe3\xd8t\xc7\x00\x95\xa1\xda\xf5\xa4it#&\xd5FR\xd2O\xeaP\xf7-\xf3pMҌ\x81ι\xc0\xfe~\xccI\x87-\xac\rt\b\x86\x8d\x8a#i\xfa\xac\xa4f\x95s\x018:\xc08\xedۅ\xda\xf5\xa4it#F\xd8H\xcb\xec\b\x92j\x9fɡ\xee[\xe6ᚤ\x19\x03\x9ds\x81\xa3N\xd1\xc8\xde@\x87\x90\xfa\x03^\xd3\xf5YI\xd1*g\xe88:\xc08\xec\xdbE\xb0\xebI\xc3\x15\xc3\nQ#\xad\xb3\x93\x9cT\xa7L\x0ey\xdf2\f\xd7$\xcd\x18\xe8\xa4&i;\x03\x9d\xf4H\xd7g%E\xab\x9c\x8b\xc0\x10\v\xbb\bv=\x17A\xd2\"\xacw(9\xa9N;?\xe4}\xcb0ܓ4\xd2\rtR\x92\xb4\xad\x81\x8ea\xa3\xc2\xf8\xc2\xe0\xc5\xd6\xfa\x99\xd3\xc8\x13|\x18\xff\x16\vC\x1a\xc3\xf6\x85s\x96\x11\xb9\xc50\xf6,|a\x9a\xf5\x8c\x85\x05\x8f\xd8\xd5\xc5\xc2\x01F\x14\xc0{\xdeh\xa4c\xd7s\xe1F7LR\x11c\xb6#l$\xbfC\xf6\x16<\xe2Lr\xf8W\xd5Ϡ\x15w\xe1\xb8\x17ս0`\xf7-\xa3qQҺ\x81ι@ǖ@s\xd8\xf4\xe0;\x13\xb6\x06:\x86\x8d\n\xe3\vC\x16K66\x96\xe4\x1df\xfd[,\fi\f\xdb\x17\xd6YF\xe8\x16\xc3سp\x85\xe9^/\x16\x16<\x16\xae.B\a\x18a\x00\xe7y\xa3\x93\x8e]υ\x1b\xdd0Ie\xcdv\x84\x8d\xe4Z\xe6`\xc1#\xce$\x87_.\x0f\x85\xcapű}%\xf5\xa7ս0`\xf7-\xa3qQҺ\x81ι@S\xf7ў\x96f\xbb+\xde\xf6\x06:\x04\xedѯ\x86/\f\xf2\x97\xe0\xd1\xfd\xf9\x12b\xe7h<\xe1V<\xc2cm_\x8c\x12\xc4n1\x9c=\x8b^\x18\xe3\xf5\"\xb6\xe0\xb1vu\x11<[^\x1c\xc0\xec\x1bK\x1av=\x17ntc$\x95\xdbcq#\x99\xa7\xf7:Y\xf0Xd\xd2\xc0_\x8aO\x90\xf8\x1cr4\x1bIg\xfe\x94\xf9\x87Lc\xdf2\x1a7%\x8d\xd4\xe7x'\xba\xc9\xc9\x15k\xdam\x13ho\xa0C\xd0\xcf(\xf2\x9coE\xbc\xfe\xff \xafm\xf2ygI\xb3\xb6/z\t\x16n1\x9c=\x8b^\x18\xe3\xf5\x82\x84\x16<֮.\xa9K\xda\xd87\x964\xecz.\xdc\xe8\xc6H*\xb7\xc7\xe2F\xea-s\xb6\xe0\xb1Ȥ\x81\xffE\xf2J\x8f\xe6q\xf90\x8a\xe7\x9b\x1f\x00\xca\xec[&㚤\r\x03\x1dmMx\xabe\xb0\x93\x81\x0eA?\xa3\f\xf1*C\xc1(yb\xbf\x93\xa4Y\xdb\x17=\xd6\xca-\x86\xb5g\xd1\vc\xbc^\x90Ђ\xc7\xda\xd5%uI3{\xc1\x90\x86]υ\x1b\xdd\x18I\xe5\xf6X\xdcH\xbde\xce\x16<\x16\x994`\x8e&\xfa\xd1Z\xf4\xee\x14\U000d78f1o\x19\x8d[\x92f\ftPG\x90.\xee\bZ\x87;\x18\xe8\x10D\x92\xa6\x97ѨE\xad\xe1\xdf\xc2\xf8\xac0\xb0\xb6/z\t\x16n1\x9c=\x8b^\x18\xe3\xf5\x82\x84\x16<֮.\xc9\x0e0\x16\x01v\x92Nͮ\xe7\u008dn\x8c\xa4r{l#iҲ\x14,xę4\xf0\xd3_.\xe9\xd1D;\v\a\x05\x16\x96\xfa\xbee4nI\x9a5\xd0\tn!\x8bg\x02\xfb-\x83\x9d\ft\b\"I\x17\xe1\xb3v\xe0\x8ej\xc4\xfa\xb7\x88\riX\xdb\x17\xa3\x04\xb1[\fgϢ\x17\xc6x\xbd0=\x0e\xe3\x16c\xed\xea\x92\xec\x00c\x11`!\xe94\xecz.\xdc\xe8\xc6H*\xb7\xc7\xe2F\xea-K\xc1\x82G\x9cI\x03\xffL\xe2\x98[J\x8e&\x1a,\xdc9-\xf9\xc1\xfb\xfa\xbea>\xdex\xa1\xb7ÍT\\\x934c\xa0s4\xb0\xed\xd0ѽ\x81\xa0\xf5\x90\xc9\xc1@\x87\xb1Q\xe1|a\xc85\xd2\xf69S\xc8\x06\x8c\u007f\v\x12\x19\xd2\x18\xb6/l\tb\xb7\x18Ξ\xc5(L\xf7z\xb1\xb4\xe0\x11\xb9\xba\x88\x1d`\x84\x01ܾ\xb1\xa4l׃.\xdc\xe8\x86M\xaaa\xb6c\xd5Hc\x87\x9c-x\x04\x994U\\s R5E9\xfc\xeb\ue612|\xba\xe8\xfb\x86Y(/H\xfa{f\xe0\x9a\xa4Y\x03\x9d\x13\x1d́`\xb7\xb5\xa2\x9d\ft\x18\x1b\x15\xce\x17ƿ\xba\xbe`F-=\xffY\xff\x16\x91!\x8da\xfb\u0095 t\x8b\xe1\xecY\x8c\xc2t\xeb\x19\v\v\x1e\xb1\xab\x8b\xd8\x01F\x18\xc0{\xde0\xa4l\xd7C\xb80\xa3\x1b.\xa9\x86َU#\x99\x1dr\xb4\xe0\x11d\x92\xa3\xb4qI\xbeZ1\xb9\x81PtEE\xdb7L\xfb\xf4vA@&\xe0\x9e\xa4\xd3`\xa8\x06:p\xbf\xd10py$5\xe6\xcfLë\x14\x18\x11\x92\x1e\xea\u007fU^\x1eg\x9fǸ<\x92\x1a\x82+\xdbV\x8c\bI\x0f\x95\xcb\xe3\xec\xf3\x18\x97AR\x1b#\xa8\xba\xc1)(c\U00070915\v5\xc0E\xe5rHjL._Yt\xde)*c\xf1\xb0\xa4\xe9\x85\x1a\xe1\x8df\xc0\x90\xb9,\x92ڐ_m\xbe\x11\x1e\xd0\xf1\xb0\xa4\x01 \x13\x01I\x03\x80\xa7\x00I\x03\x80\xa7\x00I\x03\x80\xa7\x00I\x03\x80\xa7\x00I\x03\x80\xa7\x00I\x03\x80\xa7\x00I\x03\x80\xa7\x18I\x92\x1e\xea\xad\xde\x00\x90A\xb8'i\xc3@\aӳ\xad\xa9e\xaf}\xbc\x83\x81\x0e\x00\x00\x04\xd7$\xcd\x18\xe8\xa0xG`\xf7\x91\xbd\x81C\xf6[\xd8\x1b\xe8\x00\x00@pMҌ\x81\x0e\xea \x9e\x1b'\xe9\xa25N\x06:\x00\x00 \x17%\xcd\x18\xe8\xf4+O\x1d;g\x1f\u007f\xf1\ft\x00\xc0ø'i\xa4\x1b\xe8\xec\x0e\f:\x19\xb99\x18\xe8\x00\x00\xa0⢤u\x03\x9d`\xb0gk\xa0yׅ\x18\xe8\x00\x00\xa0ࢤu\x03\x9d\x16j\xa0\xd3\xdcra\x06:\x00\x00 w%\x8d\xb4\xe7xӾz \xb0\xc7&\xd0\xd9@\a\x00\x00䢤\x19\x03\x1d\xd59'l㶑\x82\x81\x0e\x00\x00\xc8=I\xb3\x06:{\x9b\xa8\xbc;.\xcc@\a\x00\x00䞤Y\x03\x1d\xc5:\xe7\\\xc0\xfa\xf6\xb1T\ft\x00\x00@.J\x9a1\xd0A{\x03{\x8fv7m\x15ش\xaa8\x19\xe8\x00\x00\xa0⚤Y\x03\x1dt(\x18ز\xd7Zю\x06:\x00\x00\xa8\xb8'\xe94\x18\xaa\x81\x0e\x00d\x1e#B\xd2\xf0_\x95\x00\x90*#B\xd2\x00\x00\xa4\nH\x1a\x00<\x05H\x1a\x00<\x05H\x1a\x00<\x05H\x1a\x00<\x05H\x1a\x00<\x05H\x1a\x00<\x05H\x1a\x00<\x05H\x1a\x00<\x05H\x1a\x00<\x05H\x1a\x00<\xc5H\x924\xdc\xea\r\x00\x8e\xb8'i\xdd@g\xb0)\xa0\xd0l\xbf\x81\x9d\x81N\xef\x82\u0082\xaaH\xd9>\xf36\xb6<+\xcb!\xa7\x18\xf2\x88a\xb9\xd4)\xe6\xa2\x11\x99\xbe\xd3)D\xe7l}Q\xee\x02LJ%#T%\x93\xfd\f\xe1\xd7*\xa7P\v,\x12U\x87\x8b\xcc\x13\xfd\xf7z\xaa-\xa3\xa4\x91_-;\x96\x15'\x93\xda1\xf6\x14\xaeI\xda0Љ\x05\xf6\xf6c\xf6*\x0f\xe8\xb7\xc6\xc6@\xa7\xd7\xf7h\xe7\xf6E\xa9\x1e\xbdH\xaf\xf2~*\xeak\xb4\x8f\xa4\x1c\xa8\xf3;\x85\xa4\x88V\xb1\xf5ڮ\xbc\xd4v\x81P]\xd4V\x97w\xde)\n\xa1\xbe\xd5r$\x86bQyuj*H\xc6\"Qǣ\xd16Y\xf4-\x9aj\xcb\x14\x04\xf9\x15'Jώe\xc5ɤr\x8c-j\x1b\xa9\xb8&i\xc6@\xa7\x9b<\xd9d\xa0i\x97\xfd\x06v\x06:5\xd5\xe4\xb5.EI\xff\xdb\x12m\xc9\xefx\xb8\t\x8d\x17K\xd2FŖkS\xed\xdb\x10:/\xb7\xa2\x84\xfd\xb3\xcfUZe\xf2\xa0\x89\x04\x8e\x1f2V\x89:(RV\xea-SHί8Qlv\x84\x15\vq>\xc6V\xb5\x8dP\\\x934c\xa0Cٶ\xc5\xfa\xa9&\x14;\x03\x9d\x92\x06\xf2\xda+w\xa2T(wK\xd2\xe5\xc2sG\xbc֑>9\xd51\xfa\xa5\x96t\xea-SHίsJ.\xa6\xa4\x9dk\x1bQ\xb8'i\xa4\x1b\xe8\x10z\x02'\xeccm\rt\x96\x16\x1d&o]\xb4k\xd8^\x95w\xcfj\xa5\x93`\x165v\xca\n\xe5\xe4\x83\u007f\xed\xea{\xf2j\x8e[\xc5\xe2q[\xed\x8c)\x8bԁa[y^Y\x9b\xb2\xbaoQ\xa1\xafh\xc1)\xb4R\x96\xb7+\x93\xc1D\x91\xefř3\"\xab\n\xaa\a\xd8\xc2Vʾv\xb5\n\xb6\xe2\x81%3|%\v{M\xcd9\x9f'\x1bs\a\xad6\xa6\x04\x86\xc1Be\xb3\xd5\\l\xafO\x96\x1b\xfajKrk\xb8\xceސ\xb4Q\x18\xd7^\xa39\\\tњ\x12_\xe1\x82\x12R\x84\x91(#\x96\x90\xac\xac\xb4Z\xc6\xe5W˙8Q|v\x8c\x8a\x99F\x1a\xb0\x8d\xf4\xaf\xaa\x9f1m\xa12\xe70\x92\xaa\x1d7\xfe|\xf0\x04.JZ7\xd0!\xb4t\xd8\xc6:\x18\xe8\x1c/\x91k\x1a\x0f(\xdd|\xbd\xbc\xaa\xabuzy\x82_\xd4\x19\xd8\x17\x9dS\x1d\x8dF\xffL>\xf8\xe5\xd2\xd0\u03a2E\xa6\xcd\f\xfa\n\xeei\xdfY#\xd3S\xae\xce\xdf\xd0\xd5\xe0\u007f\x8a,F\xf2\xcb_\x8d4b\x89(35:\x19\x8c\x14ȫ\xab\xe5\u008dE\xadla\u007f\n\xf9\xe4鍿\xce_\xc4W\xdc%\xd7GB\v僦\xe6\xf4F\xa3Z\x9f\xa2\xd7Ɣ\xc0\xd2\x1b\rɍ\xd1\xe8i.6\x1e\n\x95\xccɟ\xb9\xbaV\xe6\x12dH\x9a)\x8cm\xaf\xd1\x1c\xb6\x84\xdf\xcaO\x85\"\xed\x852I\x89\x91(#\x96 \xe8,\xd3i\x19\x9b_=g\xe2Dq\xd91*f\x1bi\xc0n\xe6\x97\xcbC\xa1\xb2<\xf2\x9d\xaf7\x879n\xdc\x01\xf0\x04.JZ7\xd0\xc1\x1c\xa13k\x1b\x1c\ft\xceo\xac\xf0\xc9S\xc8wx\x97\xfc&\"G<\xc4-r0\x03\uf8b3\xf8\\\x9a\x8e\xacb\xab\xe6\xe0^#QFN\xb9w\xe5\b~\x8d\xc8]\xf8\xfc,\xa9\xc1\x1a\x19\f\x91\v@\xf4$\xa3#ǢZ\\\xc8NTW\xcf\x17柂O\xe2\xda\xe9|ű\x10\x19\x0e\x94-\xe4\xd7\x12r\x95\x93\x96\xa9\x8d+\x81A\x1f\u07b2\xb1\xa8\\\xa6\xdd.\x17\xc9\x0e\xbc\x8d\u0098\xf6\xf2\xcd\xd1Jh\x9bNt\xd2V@%\xad'\x8a\x8bu\x18x;\xb6\x8c\xc9/w\x00ĉҳ\x83\x8c\x8a\xd9F\x1a\xb0\x9b\xf9K\xf1\xde\xc7\xe7T\x98\x92\xaa\x1f7\x18x\xb38\x15\xeeL\\\xed\x9d;Z\xec\xe3R0ЉG~D\x0e\xd6\xd2;\x06\x13\x98\x99\xf5\xdc\"\a#i\xf2'z`\x85\xb1\xe7\xe5v\xf2\xd6@\x02\xea\xcb\xe8\xaa\xd2:r\xf6\x19\x97H\x19I\x87\xf0y6\x80\xd6.\xe3\v\xa3\x8f\x1dO:wζ\xd5\xdcQ \x97\x99\xd6\"\xfd\xa4ej\xe3J`Ѕ\xc3Ƣr\u007f\xb2\x05 'i\xbd0\xa6\xbd|s\xb4\x12>\x9dQ\xb2\xb2\xbd7A\xc7>F\xa2\xb8X\aI;\xb5\x8c\xcd/w\x00ĉ\x12I\x9am$\x03\xb3\x99\xffE\xf2\xda&\x9f\xe7\x93\n\x92\x16\xe2T\xb8\x1d\x8c\x81\x0e\xa6\xc9\xfa\xb1\xfc\x14\a\x03\x9d\x83\xf4rY\xa2\n\u007f-\x97\xa9s#~\x91\xc3ty\x8c\x1eXal\xaf\x1cEZ@գtգ\x15\x9aD\xcc%\x14\xbd\x8b\x0e\xfa\x10Z\xb7\x8c/Lx\xee\x1c,*Y\xdb\x19\xad\xb6\x964S\x1bW\x02\x83.\x1c6\x16\x95\v\xe6\x84m\xf2\xdf\xf1kL&\xb3Ha{\xf9\xe6\xe8%\x9co_R*\x17\xbd\x8a\xb8\u0378X\aI;\xb5\x8c\xcd/w\x00ĉ\x12I\x9am\xa4\x01\xbb\x992X\x8f\xe2\xafa\xab\xa4\x82\xa4\r\x9c\n\xb7\x815\xd0!~\x1bG\xec\xc3\x1d\ft\x8aVҷ\x869xPyG/\xe5,\xb7\xc8A\x0fa;\xe93\x8c\x03+\x8c=KU\x80\xe8\xe5\x9b\xfa;誒:2t3\xf5Ҵ\x9b)\x8a\xa0\x83~E\"laI\xe7\x0e\xa9\xb8\xb4\x82\f\f\x17\x95\xf1k\tZ/m\xd4\xe6(i6\x16\x95\x9b\xe6܄(m\xaf\xa2\x1fF\xd2F{\xf9\xe6h%\xf4\x92\xdby\xfe\x1e\xca\xe5\xbf\t\xb8X\xa7^ڡel~\xb9\x03 N\x94H\xd2l#\r\xd8\xcd\xfc\xf4B];\x1e\x90$%\xb5\xc1tX\xbc\x81[\x92f\rt\xc8TZ\xbbL&\xc6\xc9@\xa7p&\x99\xd7&\xc8Y\x13Qfc\r\x1b\xb9E\x8e\xeaj\\\x8c2\xd1\xd5\xcfTqlE\t.\xb7/\x97\x04tр\x10\x19\xdbNJ\xaa\xc9@o\x15\xb9\ue7b7\x16\xd7[a\x92\b[\x18+H\xbd\xe2\x12rz'\xca\xcaL\xcdA\xfaI\xcb\xd4\xe6(i6V\xd8\xe3\fL#\xe3\x9a\xfai\x03\xc8B\xd2\\s\xf4\x12\x1a\xe5w\xc9[u=\xb7\x19\x17\xeb iǖ1\xf9\xe5\x0e\x808Q\"I\xb3\x8d4`7\xf3\xcf$\x17>J\xab\xf9\xe6\x18\xc7\xcdt\x00F>\xaeI\x9a5\xd0A=\x01;oig\x03\x9dB\xb9\xa8\xe1\xdd\xcejz\x93\xe0:yY\xa8\xb3^\xde\xce/\xb24\xfa\u007f\x8dc?%\xd7=\xeb\x0e\xa0\xde:_\xf4\x94E\xecἙ\x8d\r\xd3dߛ\x87q7\"\xaf\xebZ'גՑ\xdcҶ\xaeUt\"X5\xfdՍ\x15$\xe0\xf0\xb4\xd6X\xc8\xd7\x1b[V}\x9c)\x8c\xabB\xaf\x18\x9f\x88K\xda6\x96˅\xaf\x1e`\xd7\x0e\xee\x8bF\xfdu\xd1(I\x89^\x1b_\x82\x8er]\xf9\x00\x9d\xb5豉\x03\xf4\xeamҥ\x86\x90\xfclW=9g\x99\xc2\xd8\xf6\x1a\xcdaKh\x94\xf3\x1b\xba\xf0^D\xb860M\xff\x94\xdc\xc4\xd5\x1a\x8d\xf2\xfd[:-c\xf3\xcb\x1e\x00Q\xa2\x98\xec0\x15\x1b\x8dda\xf3\xeb\x97k\x0eD\xaa\xa6\xf4!\xee\x10\xeaǍ\xad\xcd\x1b\xb8&i\xce@\xe7\xc8\x16\xdbPG\x03\x9d\x8a\xf6\x86Ҽ\xe9ꏏ\x91\xea\xc2)U]\xe6E\x86\xf8\xaai\xb9\xd5\a\xe9\xfd\xbf\xb2\xef0\xf9\xb9\xf3Y\xabؾ\x85\xd3J־\xe9#\x01\x89\xd7\xcb\xf2\xcaڔ+\x00}Kf\xe6Wtҥ\xea\xdc\xfc\x9a\x17e\xb9\xbeH\x96C\xf9r^H\x99\rj\x85\xf1Uh\x15\xa3D\xeb\x1c\xff\xf4\xa5\xeds|\xd5\xec\xdaߪ\xd3I\xf2U\xa1\xd7Ɨ\xa0\x11/\xa0\x91>\xfaӋ\x1e۫l\xff(2\xd3U\x9eWNv\xcd(\x8ck\xaf\xd1\x1c\xb6\x84\xedU\x8d%\xbe\xa2\xea\b\xdf\x06\xa6\xe9uj{\xb9\xee7\xbd\x961\xf9e\x0f\x80(QLv\x98\x8a\x8dF\xb2\xb0\xf9-m\\\x92?\xa3V\xb9\xd8b\x1cB\xed\xb8q\x87\xc5\x1b\xb8'\xe94\x00\x03\x1d\x00H\x95\x11!i\xf8\xafJ\x00H\x95\x11!i\x00\x00R\x05$\r\x00\x9e\x02$\r\x00\x9e\x02$\r\x00\x9e\x02$\r\x00\x9e\x02$\r\x00\x9e\x02$\r\x00\x9e\x02$\r\x00\x9e\x02$\r\x00\x9e\x02$\r\x00\x9e\x02$\r\x00\x9eb$I\x1an\xf5\x06\x00Gܓ\xb4n\xa0\x83\xd0\xc0\xae-\x81-\xbb\x06\x1c6\xb03\xd0ѹ\xf4\x86)\xe9x\xde0\x88Mf:\xc9\xff\f\x92'\xd8\x1a\x8e@\x89\x869\xd3|\xd3\xeei$O'\x91\xab\x12\xd4\t\xc7\xf4\xbf\x84Cm\x83\x90\xce\xd2ܲPy\xd2\u007f\xa4ړ\x86\xa5\r0̸&i\xc3@\a\x9dk\xda\xdas\xb4gK\x93\xfd\x93M\xec\ft\xd26Ź\x88\xa4\xe3y\xc3 6\x99\x19\xd8\x17-Xt\x98s\x04\x8a\xc8\vں\xda\x17\xcaQ\x14\x8fȹQ\x14\v\xc9\x11\xf3\x03#\x84m\x18\x9a/\xcc\xebrm\xe7Z9\xdd\xc7\xf8\xa7ai\x03\f3\xaeI\x9a1\xd0\t\xb7\x90\xe7\xfe\f\xb6\x84m7\xb03\xd0I\xdf\x14\xe7\"\x92\xba\xe7\r\x83\xb5\xc9L\xe1Z\xc49\x02\xad. \x02\x8eOYM\x9e\bX[\x87\xd0\xc7r\xf2v\xa26\f\xc9\x17\xa6On\xc0\xaf\xabӕ4J\xc7\xff\x02\x18V\\\x934c\xa0ӱ\x95\xae\b\xda?\x9d\xdf\xce@'驟\x97=\xd6&3TҌ#P5}\xbe&\xaa\xa8!\x92\x8e\xe4DŽ\x92\x161\xa4\a_>5\x9d|\x81\xfcI\xe6\x1fϗ\n \xe9\xcb\x04\xf7$\x8dt\x03\x9d3M\xe13\xf13\xe1\xa63v\xb1v\x06:\xe9\x99\xe2\xe8\xf67HhSC檍\xa8QV&\xe5Z\t\x16\xce2ix\xde0\x01\xbcɌ\t*i\xc6\x11\xa8Jy\xb2\xe6\xa2*\"\xe9\x8f\xcbCI\x926\xda`a\xd7\xc3y\xff\xe8\xf0N8\x1a\xd3\xd6ҷ\u05cf[l\xc6fG\xe8\xa5\xc3x\xd3 \xab\x03\x00\f'.J\xda0Љu\xe0\xa5\x0e\xfb#og\xa0\x93\x96)\x8ea\u007f#\xb6\xa9\x89E\v\x1a\xfe\x86\xfe\xd6P\x10\x8d1%X9ˤ\xe1y\xc3X\xf0\xb0&3f\xa8\xa4\x19G\xa0\xb2et\xf5\xb22*\xe9\xd6\x05ɽ\xb4\xde\x06\v\xbb\x1e\xd6\xfbǀw\xc2QQ\x1f\x96\xaf ڌ͎\xd0K\x87\xf1\xa6\xb1:\x00\xc0\xb0⢤u\x03\x9dxGKO\u007fOK\x87\x9du\xa5\x83\x81N\x1a\xa68\x8c\xfd\x8d\x85MM\xfdR\xfc\xb2\xac\xde\\\x82\xd0Y\x06\xa5\xeey\xc3\xd9\xc98\f\xbc\x19G\xa0R\xe5\xf9\x89\xb5\xa5TҧsO\x8b\x06\xde\xda\xd3p\x85v=\\\xc5:&o\x1a\x85\xc3\xca\xc5\xf4x<n\xb5\x19\x93\x1d\v/\x1d\xe3\x01\xc1V\x0eF\xc0p⦤\x91\xfa\x1c\xefp\v\xbd\x00\xd4bg0\xedd\xa0\x93\xb2)\x0ek\u007fcaS\x13ɍ\xa1X^\xd4\\\x82\xd0Y\x06\xa5\xeey\xc3\xd9\xc98I\x1a\xe9\x8e@j/\xbdT\xe9\xa5тV[I3\x15\xeb)\xe1*6\xe0\xbdi\x14\xfeN{\xe9e\xf4w2\x8b͌\xecXx\xe9\x18\x92\xb6r0\x02\x86\x13\xd7$m\x18\xe8$\x02\xfb\xb5E\xcbh\a\x03\x9d4LqX\xfb\x1b\vG\x95Da'\xea,L\x98K\x10:ˠ\xd4=o8;\x19\aI3\x8e@UJ\xf3\x17*si\x14*\xb3\x954S\xb1\x9e\x12\xaeb\x1d\x937\x8d\n\xad\xfdt\xa7\xbc.n\xb1\x19\x93\x1d\v/\x1d\xa7\x03\x00\f/nI\x9a1\xd0\xd1$\xfd\xa1\x8d\xa4\x1d\ft\xd20\xc5a\xedo\xacljV-D\x8b\xe8\x158\xde\xd5E\xe4,\x83R\xf7\xbc\xe1\xecdD\x92NЉ/\x15\x15\xe3\bT\xad|\x93\x94\xd7(\x92\x8e\xe5Eґ4I\tW\xb1\x8eɛF\xe5\xa9\"\xf2\x85\xd7I\xae4\x887c\xb2c\xe1\xa5cx\xd3X9\x18\x01É[\x92f\rtv\xa8\x03\xef\x1d\x96\xc1N\x06:\xe9\x98\xe20\xf67V65\a\xfc\xa7\xfc\xc4\a\x83/A\xe8,\x83R\xf7\xbc\xe1\xecdD\x92n#\xaeUg\xe5\xd7\x11\xe7\b\xb4:\x9ff'\xaf^\x914\xaa[\x96\xa2\xa4\xf5\x94p\x15똼iT\x94ߥ\xab\x89\xa4ś1ٱ\xf0\xd21\xbci\xf8\x03\xf0\xf1F\xb8\xbd\xecR\xe0\x9a\xa4\x19\x03\x9dXsK\xf7\xb1\xee\x96f\xebK\xdeN\x06:\xe9\x98\xe2\xb0\xf67\x1665\x89\x1953\x94\x11\x83^\x82\xd8Y&-\xcf\x1bƿ\x855\x99a\x1a&/\b\xbdYQH\x9c\\\x18G\xa0\x88\\\xd3\x19\xed\xac\x91;\xc9\xddc\xa1\x18\x8a\xe6\x99$m\xb4\xc1®\x875\x8e1\xe0L|\fZ\xe5\xfa\xaez\xe5\xee1\xe1fLv,\xbct\x18o\x1a\xee\x00,\x94\x17\x98\x8b\x02\x86\x01\xd7$\xcd\x1a\xe8\xc4\xf7l\tl\xddcm\x8b\xe5h\xa0\x93\x96)\x0ec\u007fceS\xd3\xea\xd7\xee\x9e\xd2J\x10;ˤ\xe3y\xc3\x04p&3\f\x9d\xe5y\x05\x8f\x1e&K\x8c#P\xa2aN\x81\\0\xa71\x81\xc5M~\rNT\x14\xf1_\x05F\x1b,\xecz8\xef\x1f\x1d\xceć\xa1\xb34\xaf\xa2\xab\xa4\xcbj3dd\xc7\xc2K\x87\xf5\xa6a\x0f@\xfbt\xe6\a2`\xd8pO\xd2i\x00\x06:\x00\x90*#B\xd2\xf0_\x95\x00\x90*#B\xd2\x00\x00\xa4\nH\x1a\x00<\x05H\x1a\x00<\x05H\x1a\x00<\x05H\xda]6_0N5\x00\x19\x06H\xda]\x9c\x04\xeb\x8cS\r@\x86\x01\x92v\x17'\xc1:\xe3T\x03\x90a\x80\xa4\xdd\xc5I\xb0\xce8\xd5\x00d\x18 iwq\x12\xac3N5\x00\x19\x06H\xda]\x9c\x04\xeb\x8cS\r\x97\x92K\xfbD\xa2K[ۈ\x01$\xed.N\x82uƩ\x86KF\u007f\xe5u\xd2\\\x84\xe6I9\xf3{\x9cb/\x1c\xb56 \t\xefK:8\xf9\xa4Sȥ\xe1\xcc\xe4`\xf2J'\xc1:\xa3\x16\xe4\xfan&&N\ft\x1c%\xffa\x17\x98\x983@W\t\xf7\xf8\xe2\xa0\xd5\x06$ឤ\x19\x03\x9d\xc4\xfe\xad\x81\xad\xf6\xdf\xec\xff\xbb\xe1;\xb3\x9f\xfe\xc26D\xcc\x1ai\x85\xbatd\xb44\xd164\x897\x8a1_\xff\xfe[_:\x05j|2\xab\xf8\x01뿮\x19\xf5\\ҺoK\x84\xeb\xff\xaf\x93pu~v\xa5t=\xb7B-[\xdfM!\x1d9C\x12י\x1f\xe4dߞ\xe2\xf8\xb6[ڦ-\x86%\xe595\xc2=\xbe80\xb5\x01<\xaeI\x9a1\xd0I\x04\x03\x1f\x1e\xd9\x1b\xd8k\x17\xfe\xe4}o\xbd0\xfb3\xbb\b1\xebG5\xe9˻+\xb3l\"\x05|\xf6\x9b\xe2\xb7?z\xff\xf9\xe2ל\x025\xbe\xfc݆;m\xfe\x1c\xbcb\xbdy\xd5+ߖ\x1e\xfc\xc9\xe37KwY(8\x99\x9f\xdcr%\xf7\x99\x16\xc3\ue988`\xf6\x96\xe4\x95;l3N\xb8\xed\xba\x97*\xb3\x1d|\x8d4\xf6Hacq\xb7\xba$\xd8\xe3\x8b\x03S\x1b\xc0㚤\x19\x03\x9d\xfd\x813tŀu\xf4g\xc5o\xa0/\xfea\xfdw+\x8e\x8c^\xcc|Z\x91\xaa\xa4ONUF\xb1\x1f\x14\xff\x11\xebtC\xf1_\xec\xc3\x19^\xb3\x934Z\x9ee\x1e+n~B\xfa)\xd6\xe5\xad\xd2\xcf\xc4\x02\x16\xf0\u007f\x92%\xcd\xef\xa6\bQW;y\x9e`%\xcb\x19i=J\xd8\x1c\x15\x0eC\xc7\xecb\xf2\x1e_\x1c\x98*\x00\x1e\xd7$\xcd\x18\xe8\xa8\xce9M6\x9d\xc6'\xc5\xefY\xffц\xca\xeb\xd832eIwK\xdd\xf4\x9dJ\x1a}~\xf7\x06\xfbp\x06{I\x0f\\WiZ\xa3J\xfa\x97W\xdd*֯\x00\x81\xa4\xf9\xddL\x95IN\x92>$\xa51\\\x17K:y\x8f/\x0e iKܓ4\xd2\rt\xb6*c\xa8\xa0\xd5\xec\xe8\x8b\xef\x14S^FhCq\xf1;\xea\x8cuC\xf1\xac\xb7^~`\xf6\xd3\xffCc>y\xe6;\xb3\xeeS\x97\r\xe2c\xb5ޫ\u007f\xfe\xb8\xab\xbf\xa5\x0e\xbc\x9b&gOxD\xd1\xc0\xa1o匾\xee\xf6~n\xa3\xf5\x13\x82=ROp\xc2K\x9a\xa4ц\xef\xe0\x97/\xdf\xfe\xf1\xdd\x0f\xbc\xfc\x99\xd61\x82\x00\x00\x0f\xfaIDAT9\r1j\xfb\xf2\xad\xc7f?\xfc\x06\x9dl\xff\xcf\xf3\u07fd\xf7\x19e\xe0\xad\xc7\xfeqVq\xf1\xa6O\x9e\xbf\u007f\xf6\xd3\xff\xa4\x1b.\xcf6=`M\x95\xf4\xe6[ǐ\xd7\ao\xbc\xea\xfao\xfc\x92*\xf5g7\x8f\xb9r\xccW\u007fN\x16\xbfw\xc3U7|\x8f\xae\xfc\xf9\u05ee\x19s\xb3:\xf0\xd6b\x91\xb1\x9b-xZ\xbe\x02\xad\xc0\xaf-l\x1d\xe7\xb2%iT3Y\xfa\x814:\xf0Ȅ\xec\xdbq\xcf\x19\x94\x14&\xd1\x10-%\xfb\xaf\x90\xa4\xe5\x87\xe6\x8fϾ}0\x9e\xa3\x04<BJ\x987n\xf4\xb8\xb9\xea\x04\x99\xc9\x19\x93I<\x81\xd6E\xd6͌\x8a\x93\xf6\x18\tkc\x16q\xc0K\x93\xb2'\xe1\xf4#~-K\x18$m\x85\x8b\x92\xd6\rtv5\xd1g`\x06\x04\xd3=\x85?|\xf4N\xf1k\x1f}\xf4W,\x9b\x8ff\xbd\xa6\xceX\xff\xfb\x9dY\xc5\xf7\xbd\xf6\x9b\xbb\x9f!\x11\xffy\xf7c\xbf\xf9\xe05<:\xe7٫\x9d[\x87\xc6N\b\x04o\x93\xa8\xa4+G=\x14\\\x9f3\x89\fE\xc3c'\xad\xe9X!\xad\xe16\xea\x9f/M\x94n\x92\xe6\x1d\xd3%\xfdV1\x1e\xf3\xbfP\xfc\xf2\xfbo\xdc\xf70\xb9D\xc7\xd4\xf6\u009d\x9b\xde\xdft\xe7\xf3x铻\x1fx\xfb\xbd\xa7\x8b\xa9\xa4\xf5\xd8\xcf\xdfy\xe7\xfe\xef\xdf\xfdݗ\x9f\xff\xfa_iٻ\xccg\xa2&\xe9\xefIX\x9d\xb7H\xb7>\xfe\xbd17\xfc\n\u007f\xfe\xc9U7|\xfb\x89\xbb$\xa2\xe4[\xae\xbc\xeb\U0007bbbc\x85\xc8\xfc\xaa\xeb\x1f|\xfc_%*i=\x16\x19\xbb9\x10\x1e\xbb\xfc$:\xb9\xfc\xea0\xdfi\xef\r\x87\xb3\xe8ճ\x9e\xe6+\xa4\x9c\x15k\xc6~\x8bxz\x87'L\r\x87\xc3\xf4\xaa\xa4\x9e\x92XK\xf3W&\x8c\x1d\xf7\xc8|\xe9(\xda\x1fn\x96V\x84\xc3D\xbbA\xa92\xdc2w\xd4\x1e\x12\xcb\xe4\xcc\xc8\xe4\xe0\x89\xf0\xe4\xab\xf5J\xe39\x93w\x1dS\x87\xfaI{,\xae\x8d\xad\x18Uf-\x0f.Ϛ\x8f\xb8\xe60\xf0\xb5\x01<.JZ7\xd0\x19h\n\x9e\x8c\xf5\a\x03-֡\xc6\xc0\xfbNr\xadJ\x19\xde\xdey/\xee'\x9f\xbf\x0f/}~\xffӸK\xfc\xe2\x1d\xf3\xf5\xb3\xa0tDY\x98:\x9e\\\x86\x9b\x94E\xd7\x05\x10\x19\xb8\xe1n+6\xee\xf68yڰ\xd9_o\xdbhi4\x1d2\xa8\x92~\x1fO\xa6\xdf+~\x1b/\xfd\x1e\x0f\x12\xd8\xda\xde/\xfe\x80\x86\xbd\x8fЏ\xbfOV>LZ\xc6\xc4\"\xf4p\xf1\x93\xff@_\xaa\xd7\x01\x8eJ\xa6\xef-M\xd2O\xe0\xc9\xf4\xe3҃x\xe9ߥ\x1f\xe2\x81\xf85\xff\x8a\x85\xfd\xcb\x1f\xbeB\xfe\xf2\xc4f\xf5\xf5\xc6k\xb1\xee\u007fu\x03\x91\xb4\x11\x8b\x98\xddD\x95d,=O0\xd6\xcdV/\x88g]\x8d\xc51?\x87.\xeb\x03o&%x\xadt\x1b>&\xf4\x9a\x98>\xf0\x1eh!\x02\xba\x89\xfc\x0e\xcc\xe4\x8c\xd9l.\xeeΙA\xfa6\xfc\xf1\x9b\xcab\xd2\x1e[֦/n\x93\xc8L\xacC\xb9\xa6\xcd\x04\xe8\x98j\x038ܔ4R\x9f\xe3\x8d\xce\x04q\u007f\xbd;hs\x94Ē~A[|\xbf\xf8\x0f\xc2Ͷ\xaa\xe7\xfa9z\x16\xa1\xe5D\xd2\xf3\xc6\xc7\a1\xe3*ɹ\xb3_\xb0љGF\x8f\x93\xc6e->\xa3K\xfa\xed\xe2\xcf\xd0\xf3\xf7\u007f\xf1O\xccw_\xe0j{A\xf9\xcd\xea\x81\r\xe8\xb3\xe2\xb7\xc8\xd2&\xd2\x1c&\x16K\xfaο\x1ae\x1fUNd\x03M\xd2\x0fJ\xafl\xbe\xf9\xda_\xfe\ns\xcd-\x9b\xb5\xb5\xb4;V~\xb3\xba\xfe\x96ͯ\xd0N{\xf3]D\xd2F,2v\x13w\xa1\xd9\x03h [\xf0@t]\xd2D\xee\xea5\x05]\xd2LJ\xf0Zゖ1\x97>\xf9\xd2\xed\xe3\xc7J7!.g\xccfG\xb7\xe9?Fc\x06rƯߡ6)i\x8f-k\xd3\x17+o\xa2o\x13\xcd\x01:|m\x00\x8fk\x926\ft\xc8[\xecL\x025\xd9xb\x89%\xad/\xbeQ\xfc\xb9p\xb3\xdd\xea\xa8O\x1d\x99\xd2Sy\x92:\x89\xc4]\xcezI\xf4\xe8\xf059\x01<\x97^\x9f\xf3\x9c.\xe9_\xdcM:[\x85\xa7\xb9\xda~\xfc4}{\xfa1\xdc'\u007fD\x96hs\x98X\xfc\xe11\xa6\xec=\x92i'5\xf1~\xe3\xaa͛oP[\xf6Uu\x1c\xaep\xe3W\xe9\xdbWo\xdc\xfcS\xe9'\xba\xa4\x8dXd\xec&\x1e\x92\xe6lE[s\x12(\t]\xd2\xe4\xdd,i&%\xf8\xc3$}#]\xd2{\xae\x1b\xb7xk\xf86\"5&g\xdcfxv\xbbG\xfb\xc3\x1eɰ\nO\xdac\xcb\xda\xf4ũJ\a\xff\xcdɦ\x00\x16\xa66\x80\xc7-I3\x06:\xf8D$K\x87\x02\xfcU*\x0e\x93\xa47\x99$\xfdA\xf1\uf15b\r(SHtF\"\x17[\x10\xbd<6\u007f\xfc^\xcaI2\xb6\xfbP\xb4U\x9c^\xf1&\xf3{E\xd2_\xdc\xf7\f\xe9y\u007fO\xf9\x8c\xab\xed\x85\xfbɕ\xb1/\xef\u007f\x01\xfd\xaf2\x91\u007fA\xe9\xa5\xf5X,\xe9g\x98\xa2W\x8c6\xfdʫ]\xf1\x1es\xf3\xe6\xcd_\xbb\xf6\xa7\x94\x9f\xf3\xbd\xf4\xb5\xf4\xedZ\xbd\x97\xa6\x97njXd\xec&桹h\xeeC(\x19KI\a\x8er)\xc1k\xbf\xa5o\xa4Kz\xe2d\xd2'~\x8bH\x9a\xc9\x19\xb7\x99\xc5\x15\xef\xe4=\xb6\xacM_\xac\x1cO\xdf\xc6W\x9a\x02X\xe0\x8a\xb7%nI\x9a5\xd0\xe9\t\xe0\xa3{\xae\xd9\xee\xde\x01Cҳ\u007f\x815\xf6\x98I\xd2\xff\xb8\xefIr\xd9\xea\xe5\x97\xcd\xdb\xcd\x1b\xaf\xf4X\x93\xc7\xe1a\xf4\xa1,r*w(\x97\x83\x97?G~a\x99J\x84\xfbP\x92\x06\x8e]}\x8c\xbe+\x92\xdeD$\xfc\x8123\xde\xf4\x1b\xae\xb6\xf7\xe9\xdaw\xc8\\\xfa\xb1\xfb\xb1\x82\xff2[\xf9\x86\xd1cyI'&~\x13\xf1\xa8⽋\xbc>Af\xd1x\xf9ۛ7\xbf2\xe6_H7}\xeb7Ȭ\x99\xac\xfd\xa1\xf48\uec2fy\x85\\##\x926bI)\xdan\xe2\x0e;\xab?Kt\xb2\x8b$=u*B'H6\x98\x94p?m\xe9\x92\x1eGt\x95\x98D$\xcd\xe4\x8c\xdb\xccB\xd2\xc9{lY\x1b3\xb5'c\xf5f\xa5r\x8b_\xda@Җ\xb8&i\xc6@\xe7P`ϱ\xfdMA\xebɑr\xc5\xfbw\xf4~\xd0\x1f\xdf\xf7\x9b\xd7\x1e+\x9e\xf5\xf6\u007f\xff\xf5\xa3Y\x1b~\xf7\xe5\x1f6\xcc\"W\xc2\xffs\xf6\x03o\xbd\xff\xb22\x9de94J\xb9\x9aݝ=n\xc5\xf2\x9cQW\x90;[\x16K\xf3Z\x82\x95\x12\xb9\xddjG\xd6ė\xb6=\xa4L\xb4\x05pw\x8fm\xfa\xfa\xf3\xef\xbc\xf7\x02\x15+S\xdb\xf3ś\xde\xdbTL\xaex\xffq\xf6w_\xdbt/i\x19\x13\xfb\xcf\xff\xfa\xe8\xfbO~\xf4\xd1'j\x81k$\xf3o\xef\xf4\xee\xb1'nQ\xee\x1e\xbbK\xfa\xda\x0f\x1f\xbf\x85^\xf8\xfa\xc9U\xd7\u007f\xef\x89[%r\xa3\xe8פ\xbb\x1e\xc7\u007f\xc1K?\xbd\xea\x9ao\xdf5F\xba\xf2\xc1\x9f1\xb1\xa4\x14m7\xb1\x84\xc6\xdd>\xce<\xee\x8e\xef\x0e\x87\xb3*\xc3\xe1s\xa8?<\xbar7\xda[9\x9a^\xc7^\x91\xb5f\xebm\xd9\xe4\xcbKO\xc9\xe0nz\x1d\x9c\u0383\x95+\u07bbIi+\xa4y/=7I\xcaY\xb3\x9b\xcb\x19\x93I2\xb9\xd1G\xd8\xc6D@\xb0\xc7\xe2\xda؊\xd1\xfcQ\x8b\x83\x8bG\xcd7\xad\xe5؛4\x9e\aT\\\x934k\xa0\xf3aK \xf8\xa1`\x02\xa8\xf2\xf9\xbdtf:\xeb/\xe4\xc3'Oξ\xfb\xe9M\xc5\xc5\x1b6\x90U\u007f\xb8\x1b\xbf\x92\x1bA\xfe\xf2\xccw\xef~\xec\xbd\xe4m\x97g)\x87\xfe\xd0ܜ\xf1\x8b\x03WH?\xc0\xcb\x1d\xb7\xe5\\=U\xf9\x11\xfcмqc'oM\xdeL\x81\xde\xe3]|\xbf\xfaE\xf1\xc1\x93߹\xf7\xc7\xef\xd3E\xa3\xb6/\xdexx\xf6\xc3o\xd0/\x9bO\x9e\xbe\xf7\xfe_\xbc=\x8b6G\x8b\xfd#3\xa9&\x17\xaf\x92n\xf2R\xee\xf1\xbeV\xf9\xd9y\xf3\x13\xff2f̍O\xd0ş\xdd|\xcdU7>N\x96~E\u007f\x97\xfe\x15]\xf9\xd51\xd7~\xe3\xc1+\xa5[\x99XZ\x8c\xb6\x9bx\xae\x9b\xc5\xff$\x87\xd93J\x99\xbc\x06\xd0\x0f\xf0\xeb\xe8\xeel\xfcJ\xf2\x10\u007f('{\xaa2%\xd5R\xb2_\t%=k\xfcj\xbax\x05\xf9\x95+\xb1fBVμ\xc0\xf8Ѹ_gs\xc6d\x12\x9d\xb8b\xde\xfe\x13\xf8 \xc6\xfb\xf7\xce\xcb\xd2\xe6P\x82=\x16\xd7\xc6,\xe2\xea\xd6ߔ}\xd3K\t\xd3Z\x0e\xad6 \t\xf7$}\x89xht\x8bSȥ\xa2yt\xa5\xf9\x8e\x89\x8b\xf6\x9fX\x97\xc1nn\x9dH/y͕\xa4\xafh\x17\xcaE{|\x91Pk\x03\x92\xf0\xbc\xa4њq'\x9cB.\rg\xae{.y\xa5\x93`\x9dQ\v\xba\x1cv\xf3\xc4~\xdc;\xf7\u007fxL\xfb,\xdc\xe3\x8b\x06\xad\rH\xc2\xfb\x92\xbe\xbcq\x12\xac3N5\x00\x19\x06H\xda]\x9c\x04\xeb\x8cS\r@\x86\x01\x92v\x17'\xc1:\xe3T\x03\x90a\x80\xa4\xdd\xc5I\xb0\xce8\xd5\x00d\x18 iwq\x12\xac3N5\x00\x19\x06H\x1a\x00<\x05H\x1a\x00<\x05H\x1a\x00<\x05H\x1a\x00<\x05H\xda+\xc0\r\xcf\x00\x05$\xed\t\xc0N\x06\xd0\x00I{\x01\xb0\x93\x01t\\\x95tw@\xfd\x97\x9d\xfe`\xa0Ý{\xf0\x19g\x19\v\xb7\x18{S\x9c!\x13\xbc:\xf5\a\xe2i\x8d\xac\x94$)\xfb\x90 \x00\xecd\x00\x1d7%}.\xb0K\xf9\xef\xf9c\x81\xf0\xa1p@\xff\a\x9eK\t\xe3,c\xe1\x16\xe3`\x8a3T\x16KN\x06\x19\x06Z#\x8f\x86\xc3/\t\x9f\xe6\x01v2\x80\x8e\x9b\x92\x0ev\x1c\xa3\x92N4\x93\xff\xdf\xdf\xd5\xec\xca\x05\x1e\xbdRk\xb7\x18{\a\x8d!\xb2\\Z\xee\x14b`dF\xfc\x80\x1exl\x0f\xa0㢤\xbb\x9b\x06\xfa\xa9\xa4{\x02䡓\xd4\x1e\xcbE\xac\xddb\x86E\xd2+\xec\xad&\xad\x00I\x03\x0e\xb8'\xe9s\x81CH\x91t\x872\x11\xdc&x\xfc\xf4\xf0b8˰n1,\"S\x1cda\xd7#r\xcd1\x1b\xe8\x18\xacQ<>\x8e\x8eU*\x96Ʋ\xf3\x0e\xc6\xe8\x86i$A,^\xb0\x93\x01tܓ41\xb7S$\xbdUyn\xd6.\xcbg\x80\r\x1b\xba\xb3\f\xeb\x16\xc3 4ű\xb2\xeb\x11\xb9\xe6\x98\rt\f\xd6KԦ5\u07b4^!\x10g\xfe\xc8\x18ݰ\x8dDBI\x83\x9d\f\xc0⚤{\x88\xf7\xac\"\xe9&\xe5\x91v{\xec-\x92\x87\t\xedi\xb8\u0081\xb7\xd8\x14Gl\xd7c\xe5\x9a\xc3\x19\xe8\x18\x04\xd4璞8\xa2`z\xcc\x10kt\xc34R$\xe9\xb9\x12\xd8\xc9\x00\x06nI\x1aϜ\x13\x89\xc4ѦDBw\xae\f_\xfa^\x1a\xd9K\xda\xc2\x14Gl\xd7c\xe5\x9a\xc3\x19\xe8\x184)\xcf\xca=\"i\xf0O\xb6e\x8dn\x1c$\rv2\x00\x8b[\x92>\x12\xd0\xe8G\x1d\x8a\x96\x82\x97|.M\xb0\x93\xb4\x85)\x8eخ\xc7\xca5\x873\xd01\xd8u\xb5\xa2\xcdpP\xc1\xf4+\x14\xfb\b}\aI#\xb0\x93\x01\x18ܒt\xe2$\xa1;p\xf2d\x02\x8f\xc1ɯ\xc1\xe7ܹ\xe2m'i\vS\x1c\xb1]\x8f\x95k\x0eg\xa0\x932\xe9I\x1a\xaex\x03:nIZ\xa1_\xfd]\x9atQ;\xdc\xf9]\xdav.-6\xc5\xe1\xedz\x8e<\xa7\f\x99\xad\\s\xac$m\xbf\xb7 i`\x88\xb8)\xe9D\u007fw\xa0\x9fx;\x1f\r\xec8\x12&~k\x97\x18\xc3Y\x86u\x8ba\x10\x9a\xe2\x98\xecz\xe6J\xb7+\xc1\"\xd7\x1c\x93\x81\x0eCp\xac\xcd%-\xd6\xe8\x86i\xe41r\xf7\xd8\xfap8)S`'\x03\xe8\xb8)\xe9~2\x95\xa6\xbf\xb8\xf6o\v\x04]\xb8\xc7\xdbp\x96a\xddbXD\xa68\x88\xb7\xeb\t\xe4h\x96Z\x02\xd7\x1c\xde@\x87e[\x8e\xcdm٬э\xd1Hz\x8f7!\xc9\xf9\r\xecd\x00\x1d7%\r\\4\xc0N\x06\xd0\x00I{\x04\xb0\x93\x01\x14@\xd2\x00\xe0)@\xd2\x00\xe0)@\xd2\x00\xe0)@\xd2\x00\xe0)@\xd2\x00\xe0)@\xd2\x00\xe0)@\xd2\x00\xe0)@\xd2\x00\xe0)@\xd2\x00\xe0)@\xd2\x00\xe0)@\xd2\x00\xe0)@\xd2\x00\xe0)\\\x95\xb4n\xa0\x83PؕG\x9a\x8c\x14\x86\xc9\xc4\a\xf0\"nJZ7\xd0A\xe8D \x13\x1e\x9e\xb5c\xafS\x84\x05\xc3d\xe2\x03x\x117%\xad\x19\xe8 \xd4ߒ\x11\x92\x9e\x9c\xf4삔\x19\x16\xc7\x0f\xc0\x8b\xb8(i\xdd@\a\x85\x03ጐ\xf4$\x9040\xec\xb8'i\xc3@\a\xc5\x06\xb4\xc7\xf3{\x82\xfdWH\xd2\xf2C\xf3\xc7g\xdf>\x88?5MΞ\xf0\xc8\x00\x1e\x93\xa8O\x19\x9aD\x9eC4\xaa\t\x1d\x19-M\xe4bY\xd7\x1c\x96\xe13\xf1\x01\xbc\x88{\x926\ft\b^\x92t\xac\xa5\xf9+\x13Ǝ{d\xbe\x84\xd5Y9\xea\xa1\xe0\xfa\x9cI\t4\xb0+<aj8L\xae\x03\xf6\x87G\xaf@hwe\x16\x17˹\xe6\x18\f\xa3\x89\x0f\xe0E\\\x934c\xa0C\xf0\x92\xa41\x93\xa4\xdb\xce\xe1\x81\b\xe9\x9b\xc9\xc3\x06\xf7H\xf4\xa9\x89\xc6\xc0\x9b}\xa6\xaf\x1ekr\xcdQ\x19F\x13\x1f\xc0\x8b\xb8%i\xd6@\x87\xe05Ig\xa9\xc3\xe7y\xe3ヘq\x95t\xadX\xd2Z\xac\xc95Ga8M|\x00/▤Y\x03\x1d\x82\xd7$=I[Pg\xd0\xf4\xf1\x9d\x16\x92\xd6bM\xcf\xe3W\x18N\x13\x1f\xc0\x8b\xb8%i\xd6@\x87\xe05Ik\x13\xe2\xf9\xe3\xf7RNҵD\xd2Ԃ\x80\x8awy\x16\x1f+\x94\xb4\x8b&>\xc0\x88\xc4-I+xw.\xad\xf5\xc7\x1dR\vy[\xfe\x1cy\x9d:\x15\xa1\x13tE\xf6b\xfc\xad69\x8b\x8f\x15JzXM|\x00\x0f⦤u\x03\x9dX\u007f\u007f`G\xbf\xc9ay\xe42\xb8\x9b^\xdbVT\xb6X\x9a\xd7\x12\xacT\x9cgWd\xad\xd9z[\xf61\xbc45\xe7\xb9\xe7&KW\x04z\x98X\xd65\x87a\x18M|\x00/⦤u\x03\x9d\xbdʬ\xfa\x9c\xd3\x06#\x84\xfd\x8a\xe5\xcd7\x95O\x1d\xb7\xe5\\=U1ˉ?\x94\x93=\x95\x0eG\x0eM\xcd\x1e{\xfbbI\xfa\x01\x13˺\xe6\xb0\f\x9f\x89\x0f\xe0Eܔ4\x00\x00\x17\x1d\x904\x00x\n\x904\x00x\n\x904\x00x\n\x904\x00x\n\x904\x00x\n\x904\x00x\n\x904\x00x\n\x904\x00x\n\x904\x00x\n\x904\x00x\n\x904\x00x\x8a\x8c\x96\xf4<)g>X\x02\x00\xde\"\xa3%ݿ#01g\xc0)\n\x00F\x12\xaeJZ3\xd0\x19\b\xb7\x04\x82\xfb\a\x1d\xa2\x87\x85\xb0\xb4\xdf)\x04\x00F\x12nJZ3\xd09\x17\bv\x1f\xd9۴\xd5\rM\xef\x91v;\x85\x00\xc0H\xc2MIk\x06:;Z\xc8\xf3\xc7\xce\x04\x86\xea\x18u!\x80\xa4\x01\x8fᢤu\x03\x9d\xad-\xf4\xf3\x0e\xdd\xc6\xf2\x12\x02\x92\x06<\x86{\x926\ft\xfa\x8f\xd1\x15\xbb\xb6\xd8\xc6\x0f\x0f\xddR\xd8)\x04\x00F\x12\xeeI\x9a7\xd0A(\xd1솸\xe29\x93w\x1dK8E\x01\xc0\x88\xc15I\x9b\ftp'\x1d8c\x1d=|l3\x1e\xfc\a\x00\x1e\xc0-I\x9b\rt\xd0\xee\xc0\x11\xdb\r\x86\x89\x81\x9c\xf1\xebw\xb8R3\x00\f\vnI\xdad\xa03\xb8#\xe0\xcem\\{\xa4\x0e\xa7\x10\x00\x18I\xb8%i\xde@g \xd8\xc4=\x8e\xfe\xd2\x01W\xbc\x01\x8fᖤ\x15Թ\xf4\x99\xe6-\xe7\xb0\xcac\x0e\xd1\xc3\x01H\x1a\xf0\x18nJZ3\xd09\x1ah>\xd2\xdf\u07ff\xab\xc5i\x83a`7H\x1a\xf0\x16nJZ3\xd0٦Ϊ/\xf9\xad&\xf1\xfe\xbd\xf3\xb2\\\x1a\xf1\x03\xc0\xf0ত]g\xae$}\xe5\x92\u007f\x8f\x00\xc0\xb0\x92ђ\xee\xff\xf0\x98S\b\x00\x8c02Z\xd2\x00\xe0=@\xd2\x00\xe0)@\xd2\x00\xe0)@\xd2\x00\xe0)@\xd2\x00\xe0)@\xd2\x00\xe0)@\xd2\x00\xe0)\xfe??\xe8B\x81\x97E\xcd\x14\x00\x00\x00\x00IEND\xaeB`\x82",
+
+	"analysis/ident-field.png": "\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x03\xd2\x00\x00\x00\xde\b\x03\x00\x00\x00\xe6g\xc8\n\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x02\xfdPLTE\x00\x01\x00\x02\x05\x01\n\x03\x01\x05\b\x03\f\x0e\v\f\x10\x1c\x0e\x11\x14\x10\x12\x0f\r\x15$\x16\x17\x14\x1c\x1b\x15\x1b\x1d\x1a\x1f\x1f\x19\x13#A!# $$\x1d#$\"$%#&'%\x19(G((!'(&+)\x1e\x14+N()'++$*,)/-\"*.0-.,02/63(241685<9-5:=:;9=?=CA5AB@CEBKH<MH7HIG\x00f\x00\x00i\x01JLI\x00j\x02SN=MOL\x05m\x05PRO\fo\t4U\x98XSBTUS\x0fq\v\fr\x177Y\xa3WYV,`\xae7]\xad\x15w\x1c\\^[c^L9a\xab\x19y\x1e_`^;c\xad=d\xae)z!ac`De\xa3?f\xb0)|*Bh\xb3egdghfLi\xafDl\xb0qjSikh/\x82/Ho\xb3/\x859Jq\xb6mol;\x86:Ut\xb4Xv\xb6?\x8a>|u]tvsB\x8c@@\x8dG\\z\xbby{x]~\xb7e|\xb8K\x90J\x85}e_\x80\xba}\u007f|O\x93Nb\x83\xbdN\x95Ud\x85\xbf\x81\x83\x80W\x95Vl\x87\xbc\x90\x86hZ\x98Yo\x89\xbf\x87\x89\x86]\x9c\\\\\x9dds\x8dÕ\x8cn\x8b\x8d\x8az\x8e\xbfe\x9ef\x8d\x8f\x8c|\x90\xc1\x9b\x91s\x90\x92\x8fi\xa2i~\x93\xc4x\x95Ā\x94œ\x94\x91\x9f\x95w{\x98\xc7s\xa4lq\xa5s\x95\x97\x94\x82\x9aė\x99\x96\x83\x9cƙ\x9b\x98u\xaaw\xa6\x9b}\x87\x9f\xc9~\xaay\x9c\x9e\x9b\x89\xa1ˀ\xad|\x9f\xa1\x9e\x8f\xa2ǫ\xa1\x82\xa1\xa3\xa0\xa2\xa4\xa1\x92\xa5ʂ\xb1\x85\xa5\xa7\xa4\x8a\xb2\x87\xb4\xa7\x83\x8b\xb3\x89\x96\xa9Χ\xa9\xa6\x98\xabю\xb6\x8c\xaa\xac\xa9\x9e\xad͍\xb8\x93\xba\xad\x88\xad\xaf\xac\x95\xb9\x95\xa1\xb0Я\xb1\xae\xa3\xb2Ә\xbc\x98\xa5\xb5ճ\xb5\xb2\x9b\xbf\x9bµ\x90\xab\xb7ѵ\xb7\xb4\xa3\xbf\x9d\xa2\xc0\xa4\xad\xb9ӷ\xb9\xb6\xb9\xbb\xb8\xb0\xbc֦Ũ\xbb\xbd\xba\xb3\xbeٽ\xbf\xbc\xa8ǫ\xb7\xbfԯƫ\xbf\xc1\xbd\xce\xc0\x9b\xb9\xc1ֲɮ\xc1ÿ\xbb\xc3\xd8\xc2\xc4\xc1\xbd\xc4ڲ̷\xc4\xc6\xc3\xc0\xc8ݻ\xca\xde\xc7\xc9ƻκ\xd9ɝ\xc6\xca\xd9\xc0\xcc\xda\xc7\xcb\xdb\xca\xccɿҾ\xc9\xcd\xdd\xd7ϡ\xcd\xcf\xcc\xc4\xd0\xde\xc8\xd3\xc1\xcc\xd0\xe0\xcf\xd1\xce\xe1ѥ\xd2\xd2\xdd\xc9\xd7\xcb\xd2\xd4\xd1\xcd\xd6\xde\xcc\xda\xce\xe6֪\xcf\xd8\xe0\xd5\xd8\xd4\xd2\xda\xe2\xd8\xda\xd6\xd8\xd9\xe3\xd5\xdc\xd1\xd3\xdc\xe4\xda\xdc\xd9\xe6ݯ\xd8\xdd\xe0\xd5\xdf\xda\xdc\xde\xdb\xdc\xdd\xe7\xda\xdf\xe2\xd7\xe1\xdc\xe0\xde\xe2\xde\xe0\xdd\xf0\xe0\xb3\xdf\xe1\xde\xdc\xe2\xe4\xde\xe3\xe6\xe1\xe3\xdf\xe3\xe5\xe2\xe1\xe6\xe9\xe8\xe5\xea\xe5\xe7\xe4\xe4\xe9\xeb\xe7\xe9\xe6\xf1\xf3\xf0\xfa\xfc\xf9\xfe\xff\xfcŃ\x89%\x00\x00 \x00IDATx^\xed\x9d\x0fX\x14\u05fd\xf7/\u05fc\xf5m\xea\x9d(o\xb9o/)\x04S\xac\xb6Y\xd9摖p\xcd<f\t\xe8\x8d\x18\xb9\x8a \x1aR\xa4&J\xa3VL\x8c\x18b\x1e5ָ\xc1\x10,i@\xafJ\xb34\x06\xb4\xa4P\xe3\x1fb\xc0\x98\bj0&$/)i\xc0\x98\r\x1a\x93\x9a?\xf8\xc8B\xe0\xb4<\xef9gfg\xce\xcc\xce\xec,\b;\xec\xf2\xfb<\x0f\xbbgg\u007fs\xe6\xec\xd9\xf3\xdd\xf3g\x86\xf9\xfeK\xff\xa0A\x00\x00\x8c8\xfe\xc5H\xb8\xfa\x18e\r\x00\x80\xff\x01I\x03@P\x01\x92\x06\x80\xa0\x02$\r\x00A\x05H\x1a\x00\x82\n\x904\x00\x04\x15 i\x00\x18Zz\x8d\x02\x86\x17\x904\x00\f!\xce\xf4\x89\xdc,\xa3\xa0a%\xd8%]6\xcdi\x14b&\x1d\xd3ʌB\x02\x91Q\\\xebS\xa6\xd8+?4\n\x1aV̓tӾ\xa2\x92cb\xfa\xb4\xdd\xe15\xf6\x9b\x8ds\x13s\xfb\xbc\x86h\xf3\x18\xb7\xc6(d\xa8h]\x95\x94\x92w2\xe5K\xf5\xf6Ol\xfc\"\xadx\x81\xc7Ư\xf3\xd8V\xc4a\xa2f\x1c\xd7\bgh\t\xe5\xa6\xf8\x1a\xeb#$\xb35h\r~,\xf0\x12%\x1c\xd8\x1bC_\xeb\xfbyL\xf2\xaaw\x8c\xe2|D\xabև\x86\x06n\x9fQ\xc8pc\x96\xa4]\x95\xf6\xc3-\xc7\xed\xcd\xf4\xc5\xe5\x82C\xc5^\xa3\x1fJ\xa9\xc8O\xba\xe65D\x93\xcd㋌B\x86\x8a\x13I\xbf\xaa\xa8\xce\xe2\xf9\x0f\xd4o\xf4\x9d\xd9h\xd3\xdaA\xc41a\xb3zӕ\"n]U\xd14\xaeJ+^\xe6pz\x98ϱީ\x12\u007f\x11HfN\xe4|\x8c+\xba\xe2-\x9c\x1e\xd8\v\xc3P\xeb\xd7\xf6\xf3{O\xeeϾ\xf3\xa4Q\xa07N\xbe+%5j}h\xa8\xe5j\x8cB\x86\x1b\xb3$]Y\x80\x87fN{\x13}\xe1\xa8l\xf7*\xe9\xaf\xf8r\xd4\xd7\xe5-B\x9b\x96\xd0e\xde\x03:\xe2:\xbc\a\xf8\xccWɹ=\buexJ\x1a\xa1Ro\x92F+\xc2\xda՛Nӟ\xfa\xb8\xc9\x1a\xd1,k\xc2|\x8f\xf5\xca\xedsĄ\x90Y\x15w\xda[\xb4x`]\x86\xa5\xd6[\xf9\x13\xf8\xd71'\xc3(\xce\x1b\xd9k\xe5\xb4F\xad\x0f\t\xb5\xdca\xa3\x90\xe1\xc6$I;\xedo\x92'\xa138]\xe4rz\x95\xf4y\xfe\x88\xb7\xb7uI\x9f\xd8\xe9=\xe0\xb4Q\xe3\xf5\x99¤\xcf\xc8S9\xff\x91\xe7{\xde%\xdd91]\xbdIP\xd6fΠ\xf4\x8c\xa4\rc\xbd\x123\xa4\x92\x1e\x96Z\xa7\x92\xc6\xd5;\x88\x1fv\x89,F\xd2\x1a\xb5>$\x8c^I\x1f.\xe8\x96\xd2W\n\x9a\x91\x17I\xf7\xcc\xe5)O#\xb4\x85\xe7\xabŹ\xe9\x16\xdeV\xf1tFҪ\x8b4\xe6\xfcڹ\xb6\x94܋\xaa=]\x11Rw\xd1<'*t\xe2\f\xe5\x9a\xcd\xe6Ɏ&\xae\xc91\xf9)\x9cn\\\x95f\x9b\x9b\x9bF\xa6\xeb}\u007f\xcaN\xcax\x1a7\x9d\xf7m<\xbf\xe3|~Z\xe2\xaao\xab\xf1\xf1KQ)O\x8e\xaf\x19\x8026\xd1<\xbf(\xc7}u_EvRV\x05\x9d\xfa_\xccKM^+\f\xbc\xa5ݐ\xaa\xbc+\xc2]H\x89\xa0\xacy\xd1\xf4E\xf1\xb4\xf0\xc9K\x88H\xae̙\x18\x1a}w\x03\xdd\xe8\x9c71rN\xba,iu,\xea\\6%\"\xeep\xf4>\x94ɍ/\x96\xa7\xbfr@͌\xe8Ш\x19x7\a'\x10\x83T\x9268\xb0\x1c\xd00\x81\xe3V4ϛ\x14>\x83|\xa9\xeeZWn\x95\x90k\x9d\xa9>\xfcm\x96oJM\xce=OC\xb4\xbeMA\xd2y\xa9$\xcd\xd4dWᢤ\x9c3\xa9ul\xd3P\x04H_\xec\x11\xa1\x15\xf1\xd9b\x86\x9e\xb5\xae\xf9\x81\x94\x9f⩘\xf0\x18\xd2\\t>\x1b\"u7Z%]\xe6h\xdae/>Dk\xd5Q\x89\xbcI\x1a}\xd0X͗66\xe2^\xf0b\xa3\xadT\x9c\x9b\xb6V\xdb\xf8\x94\xd2?$璈\x93I\xd9{O\x94\xe2ѹ\x92\xe3\xd2\f\xb3*\"\xe6\xb1\xca5\xdc\x06\xc5\xdb\xcey\xdc\x14\xee6n\x0e\x1e\x81\xbdsg\xfe+'*\xe6\xf2\xdf\xe2͛\xf8mu\xe5)Y}\xa8\xa7\xba:-\xe3\x9eԧ\xf3\xee\xfc\xb4\xab1\xf9\xb9/ї\xcf%7vi\a\xf4\xb0\aϷ\xed\xa8\xdba\xcbǩ\xf3\xc9\x19\xfb\x8f\xac⩤\xa5\xdd\xd4\xe5=\xe4\xd1\nNs\x0eW\xd32\x8e.ᤏ\xcftl\x8e\x8a\xe9%\xdaK\xaf*\xb9{|-\xde\xd8\x1c1\xb9\xa8l:\x17\xa6\x1b{yR\xd4c\x8eL\x8e{\n9kB\xd7H\xd3_9\xa0\x96\x9b\xb7\xab\xd2\x1e\xc5u\xa3\xceC5\x93\xe3jjj\x9a\xc4\xcc\\\xae}T\xd2F\a\x96\x03\\%\xc5ѓ#\xa2\x97\xcc\xe3\xc8R\xaf\xbb֕[%\xe4Zg\xaa\x8f|\x9bi\xa5\xa5iI\xadH\xe7\xdbl\xe5\xeb\xba>*Ŀ\xab\x88\xad\xc9ki\xc9\xe5uX\xcd\x15l\xd3`\x03\xe4/\xb6\xebLcFNcc\xa3{\x14\xe5Y\xeb\x9a\x1fH\xf1)\xd2\xc3V8V\x84\xcd\xd3\xfdl\xddΪ\xdb#\xafg\xb84$\x98$\xe9\x12{qC{Sq\t\xd6tSQ\xa7wI\xb3\x03o\x1b\xf9N\x85\x81\xac-\x19\xff\x8e\xe7\xa7\xe0TO\xda*\xdc7\xf6T\u007f\xa5\xda\xcd\xc1\xb5\b\tW\xf4\f\x17\xf9\x1e\xd4S\xb8}\xa1\\(]\xa0\xacH!b.Oƍ\xe0U~?N\x9e#\xdd1\x1e\xaa\xf1\x0f]C}d]nS\x1e~\xc8#]\xb1f\xc0'\xccԠ\x8ev('\xf8:\x84r2\xf0O@_\x96M\xb9\x9b\xaa\xbc\xed\xdc.\xa4\xe44\xed6瑤\x83#KM\xb5\xdc\xf3\xa4\xfc\xa4\xb5\xdcFNz\xc6M\xc2\xc9ޘ0\xdd\xd8y\x91dD\xb2\x84#]J\x18Y~\xa6ce&\xe0\xa9(ҿl\x8e\xa4\xc7c\x06\xde\x02\xa7}80\x13\x80s\xe0\xa6_\x11\xe7QR\xad+\xb62H\xb5\xce֯-\xed\x1aQh\xb6\u07b7\xd9J\xbb\xd8|\xf2\x83\xc8\xd4d>i\x03h\x1b\x964\xdb4\x98\x00\xe6\x8bU\x0e\xbc5j]\xef\x03I\xc9}t\f#<j~\xb6Y\xb8꼟\xba\xf1\a&I\xdaQ@*\xa3\xb3\xa8\x16u\x164\xf5\xf6\xf6~X\xec\xed\x92\x1bmI结uZkR\x982w\xe3rpoj\xbcݱ$4\x9a\x9b\x18\xb6\x04\v\xfd\xd3Դm\x15\x1f\xf4ᦄ\xf2\xd2z\xbeŤҁt\x96\xedS1\xf8db\x17\xeaJ:\xa9\x17\xd0c\x93;\x95M\xc29\xabE\x1b\xd15\xda\xd6\xd0\x0e\x9br7UyۅF\xc4p\x9a\xdbp\xd81-\x9c\x94\xfe\xdeI\xaenL4\x99\xf9u<5cR\x04w\x1b\xee\x839;\t[\x11\xa6\x1b\x1bN\xcf\"5\xa9$\xcd\x04\xb4O\x9c\x94i\u007f\x13\t\x83OF\xd2\x1bjkk7\x10I\x1b\x1e\x98\r@1aRwU\xc6H:LщQ\x98Zg\xeb\xd7VH\x1e\xcb\xf9\xaft\xbe\xcdV\xfe\x0f\xe7^\xcdN\xfc\x04\xb15ٗT*\xbc\xa7\x944S\xd5\xcc\x17\xeb!iu\xad\xeb} )\x99~\x1b}\x9a\xa2\x0e\x90\xf8p\x9f}ʨ\xed\xa5\xab\x84\x9fȪ2\xd4bw\xa3\u007fu\x82\xb6\xa4\xa5d9ߣ\xb9\xdba\xf7\xd8j3\xe79oB\xe8\xb1(;\x9e\xd5m\x8e\"c\xd6k\x15k3\xf8\xb9{\xfbH\xc7!@G\xf4Y\xee\x99\x17\xfa6\xf9\b:2\x97\xfc\xd8k\a\x88s\xe9\x1e\xdcA?H\xdfA\xb9ٸ\xa3h$)ZHf7Uyk\xb9CH\t\x9d\xd2^\x1eO\xe4\x13#\xf6\x9b\xb8\x8b\xac\x9d\x18\xbdlW\xcdtܮ\x8e\tgJ\xe4\xe51u\xac\xd8\x05]QI\x9a\xc9\f]\xb6ϙ\xc2E=F\x8f\xa7\xb5<fx`63\x14s\xbbT\xf8\xc3\xf2\x88\x96\xd9*\xc1\xd6:S\xbf\xf4\xdbD\x8d\xfc\xbb:\xdf&\x9dK\v?\x91rM^\x14\xdaE\x97J\xd2\xec7$\u007f\xb1*I{ֺ\xde\a\x92\x92\xd3\xee\xa6O3\xa6\xa9\x02Xj\xb8Z\xcd\xed~\xc4$I\x1f/\xa2\xbdr%\x1e\xa6t81\xa7\x8b\x9c\xfa\x8aVKz\x87J\xd2'\xf8\xf75w\xeb\f\x13\xafx\xa8\xe44/\xc5pѵW\xa2\xf6s\x85dbV\x9dXA~\xe2ߥ|A\"\x98F\xb0-\x17\xe5n#\t\xed\x80\xc2D\xfa\xba\x9a\xff\x12m\x12V\xd9\xd2\xf2\xd17B/\x9doS\xee\xa6*\xef\x9aP\xf5\xd0TPV\x04)\xfd\xbcI\xc7)\xb8S\x9b2\x8d\x14u\x0eVV\a\x95*b\x96\xc7T\xb1\xbdB/}Z\x964\xedX\x99̎\x915\xac+χӌ\xa8\xa4\v>TH\xda\xf0\xc0L\x00\xf3\xa3\xc0Ժb\xab\x8c\\\xebl\xfd\xdah\xddV\xf0\xd7t\xbeMay,\x99|\xe7rM\x8a\xbd\xf4\a\xb2\xa4w\xa8\xaa\x9a\xf9bţ\xed\x17\xc7\x05\x9e\xb5\xae\xf7\x81\xa4d\xfa$\xfa4)]\x15\xc02zW\xbc;\xe8I\xac+\x05\xee\xcb\xc7|\x9dK'\xe1\xf1Y߯T\x92\xeeJ\xc9!?\xec۶\xa9\xf7\x9b3Y\x18\xcewN\x8c#M(s\x89:\xa0=R8;YJ&\xbex껑\xe8\x8dN\x92\v\xf7\x92GF\xd2o%~\x96\xf8\x16Ih\a\b\xe7\xa5\xfbr\xd2ȸ\x9a\x04T\x93,\xb3\xd3\xf0\x8c\xf0\xa3D\x9br7ey{\xa7\xcc@*\x04eM\\Ұ\x06\xcf\xdcJȖ\x15\xb8S\x8b&\x8d\xa87\x86\x8c\xfe\xa6E\xe3v\xd7\xfc\x830\xdd\xd89Q\xa4aΣ\n\f\xc7\xea\xed\xbd\x9d\xc42\x01k\x84\x19a\\&}\x8c\xc3\xdf\x00y\x8f\x91\xb4ၙ\x00e\x03w\u05fan\xb3w\u05faB\xd2s\xbbpŤ\xe5\xa8k\xa7e\x9d0\x8c\x17$\x9d\xb2\xad\xb5\x94\xadɵs\xb1l\xfb\xf2\xa9\xa4\xe5\xa6\xc1\x040_,~Ĺ\u007f)\xbc\xa7U\xebz\x1fHJ:\xe8X\xfdya\xba\f\x92Vs\xac\xe0X\xfb\xe9\xe2]\xdd\xf4E/\xe9\xa5u/?\x10V\xbc\xcfбӃ){K\xb3y\xdb\xfe\xd6\xcf\x1am\x1b\xcf\xf4\xbd\xb3\xd1FV\xc2O&.\xaa\xa8\x13\x16I\x144\x8f\x17\u05f8\xab~0\xe5)G\xa6\xfee\x8e\xa5|R\xe9\xabG6\xf1d\xae\\xg\xde+8Y\x8d\xbe}\x8b\xae\x91~\"\x84\xf4\xa5\xaeJ\x15.I\xd5\x0e\xa8Kzp\xff\x91U\xb638\x99\xc7\x17\xbeZȓ\xf5\xb4֤\xd4\xd2\x1dɤ\xbc\xccn\xaa\xf2n\xf0\x1cB\bW\x15N\x9fA&o˸{K\xcaҹb\xa2\xc29O\xad\x8b\xc1\x83\xe5\xc3\xe8tx\xf4\x9a\x15\x91\xe3'\x145\xe9\xc4:'F?\xb5kV\x18\x95\xf4\xb4\xa8u\xeb\xa6q$V\x91Y\xc4\x1aǮtauzM؆\xb2\xe9\xe1\xedʫnj\x0e,\at\x1f\xa6k\xe6\xee)\xb4X몭\x9e(\xaa\xcf\xc6gWWd$\x93\xf5hE\xed\xcc\xe2\x04\xe9\xb5Rm\xe6\xe4n\xccbk\U000b3534\x8aWr\x13i\xac\xd44\xd8\x00\xf6\x8bſ\xff\xe5G\x1eJ\x12zi\x8dZ\xd7\xfc@\x8aO1o\xfc2Dz\xf1\xf3\xbc}\xb6c\x1e\xe3y\xbfc\x96\xa4QsYѮc\x82\xa2\x91\x93L\xa5\xf5\xfa\xe9\x9ed:1\xb2ѳ\x0f\xe7s\x12\xefY\xb5\x83\xe7\xb7l!\x9b>H\u008f[\xf0\xe6\x8f֦ޓ-\xaf9K\xac\xf8\x81X\xc1\xcds\xa2#\xa6\xa9\x978e\xfe\x94S\x9afK\xc9\x11.7<\x91379\a7\xa0\xf7\x9993\xa6\\Z\x01\xd3\x0eh]\x9547\x97\xae\xec\xf4\x95g%e\x95S\xfd\x9f\xcfMN+\xdco\xa3\x85t\xef\x86\x14\xe5\xad\t\xf7\x18;\x94\xe0\t\x1d\x9e\xe46L\x8e\"\xfd\xc1\xbe\xe9Q\x91qD\xb6\xbd\x1b&\x87E\xdd[49\x14\xf7\xa9\xcdwGNZR4\x81\xcbԉE\x1d\xe9\xd1\xe1ӏQI7DžG\xccX\xc6q\x99l@qܚ\xe8Љq\xe2\xf9\xa6\xcc\xc8\xf0\xb8Z\xf6\x1ao\xbbၙ\x80\x86\xf1t\x0e*u{B\xad\xab\xb7z\xa0\xa8>\xdbӛ\x92S\xf3\xe9\xe5:\x8ao\xb3(\x8a.ȑ\v\x03p\xa7ۚ1\xf7U\xc4\xd6\xe4\x17\x9b\xd2\x12\x1f:G%-5\r6@\xf1\xc5\xf6lKN\xcc9G\x93\x1a\xb5\x8e4?\x90\xf2Sl\xbe-\xfc\xb6\xcd\x1e[Y\x9c\x13\xe648\xcd\xfd\xefJ\xd3$\xed\x1f\x96\x84\x96\x18\x85\x98\xcb\xf3\xa1\xe9\xddF1\x83\xa6S\x98\xfa\xfa\x9dAԺ\xb0<68\xba<\xc7g\x06\fc\xad\x97M\xe1\xe0\x9f+\x87\x95\r\xd1^\x96\xdḑc\xe2:\xa3\x90\xeb\xc0,I\x0f\xa2\xd6\xfd*\xe9\xe1\xadug\xc3@?\xfc\xd0\x12\xec\x92\x1e\u0558&\xe9\x81\xe3WI\a7 \xe9\xe0\xa5y\x1f\xb7\xc4\xf4\xf5W\x9f\xb8H\x17;\x8d\xa2t8_\xc7?\xfd\xd6`w\x0eB@\xd2\xc1K\x1c\xc7q\x13\x9a\x8d\xa2F\x02t\xb1\xf3\x13\xa3(\x1dr\xc8\xce獢F\x0f i\x00\b*@\xd2\x00\x10T\x80\xa4\x01 \xa8\x00I\x03@P\x01\x92\x06\x80\xa0\x02$\r\x00A\x05H\x1a\x00\x82\n\x904\x00\x04\x15 i\xb38\x92\xfd\xe5\xf0Z\xb9\x00\xa3\x13\xf3$\xed6\xd0q\x15\xd1\xdb\x14\x15i\xddK(\x88\xd9˗\x92\x8b\x18\x87\xcf\xca\x05\x18\xa5\x98%i\xd9@\xe7\xb2\xfdMr\xab\"s\xff{\xc5\x1f0\xfe-\xe4\xfec\u007f\x12\x12\xc3f\xe5\x02\x8cR̒\xb4l\xa0s\xd9n\xaeџ\xdf`\xfd[\xce\vw\xc4$\f\x97\x95\v0J1IҌ\x81Ψ\x914{\x83\xcaM)]\xee\xe4pY\xb9\x00\xa3\x14\x93$\xcd\x18\xe8\x98(i\r\xa7\x16\xd6\x14GөŇX-7\x1e\xa5\u007fK\xcf=R'\xadm\xe5\x02\x00\x83\xc5$I3\x06:\x97\xed\x958YcB\xb3\xd6rja\\]\xb4\x9dZ\x8cc5\xddx\x94\xfe-\xef\b7\xf8\x16аr\x01\x80Ac\x92\xa4\x19\x03\x9d+4Y\xf2\xbc\xdf5\xad\xe7\xbb#\xb9\xba\xe88\xb5\x18\xc5\xea\xba\xf1\xc8\x03\xef:\xd6\xe0\xd2\xd3\xca\x05\x00\x06\x8fI\x92\x96\rt\x10:M\xc4\xec*\xf2{W\xa5\xe7\xbb#\xb9\xba\xe88\xb5\x18\xc4\xea\xbb\xf1Ȓ>\xc23\xff\xef\xefi\xe5\x02\x00\x83\xc7$I\xcb\x06:nj\xfc\xdeU\xe9\xf9\xeeH\xae.:N-\x06\xb1\xfan<\xb2\xa4\xcf\xf0g\xe4<<\xad\\\x00`\xf0\x98$i\xc6@\xa7\x92\x9a\x17\xa0*\x87\xd7\x1d\x86\x01=\xdf\x1dIz:N-\x06\xb1\xde\xddx\x04\xff\x96.\xf6\xeey\x9eV.\x000xL\x924c\xa0\xe3\xa0\xddsG\x91\x96\xb9䰢\xed\xd4\xc2\xc8Tǩ\xc5(Vύ\x87\xf5oY\x9b!\xdd\xffN\xc3\xca\x05\x00\x06\x8fI\x92f\ft\xda\xed\xfb\x9a?<V\xe0\xf7NZ۩E\xe1\xea\xa2\xed\xd4b\x14\xab\xe9ƃ\x94\xfe-\x1f\xf1\u007fp\x97B\xcb\xca\x05\x00\x06\x8dY\x92f\ft\x9c\x95\xc5E\x8e\xd3F\xf1Á\x86S\x8b\xd2\x14Gө\xc5(VӍ\a)\xfc[\x10z.Q\x9cMk[\xb9\x00\xc0`1Mҁ\xc8\x10\xde\x03\xbeo\x9b\x8dv\xdd\xc3h\xe5\x02\x8cN@\xd2\x03`\b%\x8d\xfa\xcaS\xbf\x18n+\x17`4\x02\x92\x1e\x00C)i\x00\x18\x1e@Ҿ\x03N-@\x00\x00\x92\xf6\x1dpj\x01\x02\x00\x904\x00\x04\x15 i\x00\b*@\xd2\x00\x10T\x80\xa4\x01 \xa8\x00I\x03@P\x01\x92\x06\x80\xa0\x02$\r\x04)\xbdF\x01A\nH\x1a\bF\x9c\xe9\x13\xb9YFA\xc1\tHz\xd4A\x9d{\xae\x9f\x91\xed\xfd3e\x8a\xbdҴ;Ϛ\x8by\x92v\x1b\xe8(\x93\xfe\xa52J\xfa7\xed\x8ę\xf0\x19\xa6\x8c\xd5>\xb1\xf1\x8b\x8cb\x10\xb9\xaf\x12\xe6Ό\n\x9f\xafH\xd5\xc9Wt\xee\xe9\x98\x1e\xf9\x98ƻ\x03`\x88\xbd\u007f\x1c\x91\xbe\xff˼\xfb{K\xe78.\xbcY#\xa0\x81ۧ\xb1ut`\x96\xa4e\x03\x1d6\xe9o\x1c\xe1\xd2\x1dϦO|*=\xfc\xb2\xb7\xe0\xe1\xa2\xef\xccF\x9bQ\f櫽\xfc\xfeƺ<\xfe9\xa3@7\xda\xf9\xba\x9d{\x96Lzl\xfcu\x9a\x16\r\xad\xf7\xcf2n\x99Q\x88\x84\xfb{k\xaf\xa9٬y\xcb\xe4Z\xaeFc\xeb\xe8\xc0,I\xcb\x06:l\xd2<:8\xdc<;\x8d\xa2\x86\x89R_$\x8dN\xf0\xadX\xa7[\xd8\xfb\x05\x1b\xa0\x91\xaf\xe4\xdcs\xfb:\x14~\xbd\xcd~H\xbd\u007fVp+\x8cB\xb4\xa8Ց\xb4\xdfo8;b0IҌ\x81\x0e\x934\x91f\xce\xf7aߐ3\x00I\xa3\x9e\xe4-F\x81\x12\x1a\xf9J\xce=\xb7\x15\xb5s\xd7;0\x1aR\xef\x9f5\xdc\x1a\xa3\x10-@\xd2jL\x924c\xa0\xc3$\xfd\xcb\xe5p\x8e\x1b_LR\xae(\x8e\xe2qˠ\xe2iᓗྻa\x02ǭh\x9e7)|F7\x93T\x05\x8b\xb7/j\x8f\x102\xe3\"T]\x98\x86]\x0fB\x17\xf3R\x93\xd7\n\x03dƂG3V\x904\xda2W7\xb6\xaf\";)K\x98l\xeb\xe4+;\xf7\xccX1\xeb6\xfcY&4i\x1f\xcd7#!\xd9\xfbG\xfc\xf0\n\xa4ݘ\xcc\x14\xf9*x\x8c\xa3s{\xed\xea\xcb\xe4B\xedK&\x87\xcf \xdb\xe4\uf360-\xde*\x90\xf4`0\xca\xda\x1b\x8c\x81\x0e\x93\xf43\xc7jj\u0084\x9e\xe1͚\xe7\xb9555\xea\xb9e\xfa\xf8L\xc7樘^\xe4*)\x8e\x9e\x1c\x11\xbdd\x1e\xf7!\x93TE\x8b7\x19t\x15m\x16P9fk\xd9\xf5\xa0\xf3\xc9\x19\xfb\x8f\xac\xe2\xa9\xf4d\v\x1e\xedXQ\xd2\x15|\x97^l\xbemG\xdd\x0e[\xbe~\xbe\x8csϚ\x88\xb0c\xdd3\xe2\x0e\xeb\x1c\xcd7#!\xd9\xfbG\xfc\xf0\n\xa4ݘ\xcc\x14\xf9*\xd8\xccљ\xb9v\xf55\x15O\xe0\xa2\xd6l\x88\xa0\xe7\xa5\xe4\xef\riJ\xba\xdbYu{\xa4Y\x93(\xf31IҌ\x81\x0e\x93\xf4?\xe1\ue9a15\xf0vpE\x88\xb4\x19j\x86\x11\xc3M\xbf\"N\x0f\x98$\x8b\xfbV\xc0\xce\x16\x01\xe5\x0f\x84\xb6]ON\x06\xd6g_\x16\x91\x1ec\xb6\xa3\x1d+J\x9a\x98\xefh\xc7\xd6\xf1'hX\x9d^\xbe\xacs\xcf:Ύ\xae\x84\x93\x0f}\x1dFB\xb2\xf7\x8f|\x1fd\t\xa5{\x90;3E\x92\xc5\xce\t\xfd\xbcv\xf5\xa1\xb0H\xdcCϋ\x12_\x85{\x93\xf4,\xdcǛ8\x8d2\x1b\x93$\xcd\x18\xe8\xb0^:~ǫ\xa4\xef\x9d\xe4\xea\xc6D\xd3\tcL\x98\xd4+3I\rZ87\x8aF\xaei\xd7sM\xd0\xc6\x0e\"=\xc6lG\xdb\xdaG\x94\xf4~\xfe+\x9d\xd8M\xc29\xabE\x1b\xf5\xf2e\x9c{J\xb8\xc8%h\xc3D2y\xb8\x0e#!\xaf\xde?J\xf7 \x9b\xd4+3I\x96\"\xfa\x03\xaaW}(\x8c|\vk\xc2\xc4W^%\xfd\xe1>\xfb\x14\xe8\xa5\a\x83Q\xd6\xde`\ft<\xbdt\xfc\x88WILjm\x8b\x8e\xf6bn\x97\xb7\xcbI-j\x1c\x02\xca\xf5dM\xbb\x9es\xc28\x98.c1f;\xda\xd6>\xa2\xa4\v\x93\xf5b\x1f\x14n?\x9c\x9b\xad\x97\xaf\xec\xdc\xe3\f_R\xf5\x83\x96I\xf4\xd3_\x87\x91\x90W\xef\x1f\xa5{\x90;3E\x92\xe5P\xa4\xa0M\xed\xeaCt\xa8훤15\x9c)=Ĉ\xc0$I3\x06:L\xd2\xffx\x95\xf4\xbcI\xc7)\x1d\xe4E\xcc\x1ci;\x93\xf4\x1dM\xbb\x9eo\x04m\xe4\v\xbd\xa9d\xb6\xa3m\xed#\xaex\xa7\xacՋ\xdd$XZ\xa7\xe5\xeb\xe5+;\xf7\x94\xe1>p֤\x88\xcbB\xbe\x836\x12\xf2\xea\xfd\xe3\xe9\x1e$\xc0$\a\xc0\xc0$\r+ރ\xc2(ko0\x06:L\xd2\xffx\x95\xf4>\xae\x84<\xad\xa0\x17I\x19KZc:ɠmד\x9d\x86g\xb0\x1f%\x12\xe91f;ڱ\x82\xa4\v\x89\x00\xb5c\xeb\xe8\xd6j2\x97\xd6\xce\x17I\xce=\xbb\xb8f\xf4&w/\xea\x8dn\xb9\x0e#!\xc6\xfb\xa7e\x8d\xc7\x191ŁA\xd2~\xc3$I3\x06:lү\xb8\x0e\xd7Ԅ\xa5\xd7\xd4\\q\xafx{\xb4\x82eܽ%e\xe9\\1\xea>\\39\xae\xa6\x864v&\xa9BkїAˮ\a\xb5&\xa5\x96\xeeH\xe6m\xfb[\x15f;Z\xb1\xc2\xd5c\xf9<\xed'\xb5c\xf3\xf8\xc2W\v\xf9<\xfd|%\xe7\x1eg\xf8\x9c]ѓC3ׅ:\xaf\xc3H\x88\xf1\xfe\x99\xc5\xc5!5\xd2nLf\x8a|\x158\"\xbc\x8cӜ5\xa1\xe9\x87\xd1\xf1\xf4\xd0\x1a'\xfb\xbdѫ\xc76\xd7\xd4x\xacm\x1c\x1b\xc5n\xa0fI\x9a1\xd0a\x93\xfe\xa4v\xbc0U\xb6#W$ML\xf0\xb8\x80m\xdf\xf4\xa8ȸ}\b5\b\xa1\xa4\xb13I\x15Z\xa7fY4\xecz\x10:\x9f\x9b\x9cV\xb8\xdfƓ\xebG\x18\xb3\x1d\x8dXz\x8d7\x9f&\x0ey5c\xfbʳ\x92\xb2\xca\xfb\xbc\xe4+9\xf7TN\x8e\xca쬜\x1c\xf9\x94\xce\xd1|1\x12b\xbd\u007f6\x87E!\x0fܻ1\x99)\xf3e\xd9\x17\xe5\xe5\xb2\xecL\\塧\xc3\xf1c&\xf3\xbd\xd1k\xbc\t\x1e\xc3&\xe7\x849\rNS\xae\xd87\x1f\xd3$\r\x98\x83۹\xe7z\x10\x96ǔ\xde?\xb3\xa6\xebE\x9bB\xd9\x14\x0e\xfe\xb9r\xc0\x18e\r\x8cH\x04\xe7\x9e\xeb\x82JZ\xe9\xfd\xb3nĝ\tv6\xa8\xaf\x1c\x1a%\x80\xa4\x81\x01\xe3i$\xd4\x1e\xb5Y3\x12\xf0? i`\xa0\x80\x91Ј\x06$\r\f\x140\x12\x1aр\xa4\x01 \xa8\x00I\x03@P\x01\x92\x06\x80\xa0\x02$\r\x00A\x05H\x1a\x00\x82\n\x904\x00\x04\x15 i\x00\b*@\xd2\x00\x10T\x80\xa4\x01 \xa80OҢkNw\xb1]\xa0\x18\x01\x00pݘ%i\xc95\xc7e?\xee\xc4\x1c\xb37\x18\xed\x12\xe8T\x1dG\x000\xec\x98%i\xd95\xe74\xb9ۯ\xab8\xf8\xefBq\xfb`nY\x06\x00\x03\xc4$I\xab]s\x1c\xfe\xbfO\x91\xdf\x19\xd4]\b\x01`\x80\x98$i\x95kN\x93=x\xfe]]\xe9\xb0\xe3\xb6\xe0q\x88\xb7ԉ!7\xdd\x19_\x8cZB\xb9)\x8aX\xd6\"\x86e`.4\x00`\x92\xa4U\xae9%\x95^\xa3\x03\n\x85Îd\xc1\xd3y\x88ޅ\xb0\xa6\x89\xde\x1ao\r\xfeQK\x0fS\xc4*,b\x18\x06\xe6B\x03\x00&IZ\xe9\x9a\xd3b\x1fBS\xd3\x11\x80䰣\xb4\xe0\x91\x06\xde\xec\rle7\x1e\xa5E\x8c\xc8\x00]h\x00\xc0$I+]s*K\xbcG\a\x1a\x92Î҂G[Ғ\x1b\x8f\xd2\"Fd\x80.4\x00`\x92\xa4\x95\xae9E\xa6ܖ\u007f\xf8\x90\x1cvb\xc4\x19\xb4`\xc1\xa3-iɍGy\xf3y\x91\x01\xba\xd0\x00\x80I\x92V\xb8\xe6tؽ\xd9T\x04 \x92x=-x\nH\x9fLŻ\"L\x19\xab-\xe9\xa1u\xa1\x01F\x01&IZ\xe1\x9a\xd3b\xbfl\x10\x1e`H2UX\xf0\xc4\xc5!\xe4\xa4\x1b\u0097!\xd4{\xbbO\x92\x1eZ\x17\x1a`\x14`\x92\xa4\x15\xae9Mv\xf7\xcaw0\xa0pؑ,x\x10Q놲\xe9\xe1d!pZԺuӸ\tEML,k\x11\xc320\x17\x1a\x000KҬkN\x8b\xdbw<(P:\xec\xb8-x0\xae\xcc\xc8\xf08\xba\x1e\xd8\x1c\x17\x1e1c\x19\xc7e2\xb1\xacE\x8c\x82\x01\xb9\xd0\x00\x80i\x92\x06\x00`8\x00I\x03@P\x01\x92\x06\x80\xa0\x02$\r\x00A\x05H\x1a\x00\x82\n\x904\x00\x04\x15 i\x00\b*@\xd2\x00\x10T\x80\xa4\x01 \xa8\x00I\x03@P\x01\x92\x06\x80\xa0\x02$\r\x00A\xc5(\x96\xf4\x1c.j^\x93Q\x10\x00\x04\x18\xa3X\xd2Ϊ\xa2)Q\x9dFQ\x00\x10X\x98'i\xd1@\a\xa1\xceC\xbb\nv\x1d2E[U\\\xd0{|\x00\xa3\r\xb3$-\x19\xe8\xa0\xcbŻ\x9aڛv\x15\x9bqg\x93Z\xee\xb0Q\b\x00\x04\x16fIZ6Щ)!7B\xe8.\xa91\xdae\x18\x00I\x03A\x87I\x92f\ft*\x85\xbb\x84\x96\x99qw~\x904\x10t\x98$i\xc6@\xa7\xa3\xb8\xaa\xc3\xd5QS\xdc\xe1-~\x98hઌB\x00 \xb00IҬ\x81\x0e\x9eV\xdb\xed\xfbL\xb9\xa3\xa0+jڡ\xf6^\xa3(\x00\b L\x924c\xa0\xe3\xaa,ir6\x95T\x9ab]\xb9\x8f㸻\x8d\x82\x00 \x800IҌ\x81N\r5\xc6r\x95\x98a0\xdd\x195isU\x90\xf9\x02\x00\xa3\x1c\x93$\xcd\x18\xe8\x14Ѕ2\xf4f\x81\xb7\xf8a\xa2\x963cQ\x0e\x00\x86\x11\x93$\xcd\x18舒>n\x8e\xa4a\xc5\x1b\b2L\x924c\xa0S%\x0e\xbc\xcdX{\x06I\x03A\x87I\x92f\ft\\ϗ\x9cn?]\xf2\xbc\x19KއA\xd2@\xb0a\x96\xa4\x19\x03\x1dW\xed\xae\xa2]\xb5\xfeW\xb4\xcby|N\x98Ҁ\n\x00\x02\x1e\xd3$m>\xb38.\xba\xcc(\b\x00\x02\x8cQ,i\xe7\xf1v\xa3\x10\x00\b8F\xb1\xa4\x01 \x18\x01I\x03@P\x01\x92\x06\x80\xa0\x02$\r\x00A\x05H\x1a\x00\x82\n\x904\x00\x04\x15 i\x00\b*@\xd2\x00\x10T\x80\xa4\x01 \xa8\x00I\x03@P\x01\x92\x06\x80\xa0\x02$\r\x00A\x85y\x92\x96\ftz\x1b\xca\nv\x8d\x1c\xbf\xb9\xd6\xdc\xe4䜓Yg\x8c\xe2\x04N\xa4\x1c\xd1\u007f\xb3\x94\xb7\x91w\xeb\x92\xf8R\xed\x80-<_\xad\xfd\x0e\xfa\xc4\xc6/\xd2ykh\t\x88B\x02\xbec\x96\xa4e\x03\x1d\xe4(:\xder\xac\xe0\x98\xd1\x1e~\xe2][\xee+չ\xfa\xadXūI\xaf\xe8\xbf\xf9E^\xd2C\xf8\xe9\xa1ļ/\x94o\x9c|Wx\xbe\xd8h\xd3\xd1\x11\xea;\xb3Ѧ\xf3\xd6\xd0\x12\x10\x85\x04|\xc7,I\xcb\x06:o\x16\x90\x9b\xf27\x17\x98\xe2s\xe7ɪ\x9c>\xdcT7\xfa*i\xd4\xe7\xed\xcd\xc2ܤk\xe8\xab\xc4\xdcB\xd5\xf6\xec\xb5\ue52eZp\xf7\xe9'\xb5\x04D!\x01\x9f1IҌ\x81\x8ec\x1f\xddR<B\xba\xe94ڲ[y/\xe3i\xdf)\xcc{\xa8\x1a\xfdiU\x9eZ-Y#I-\x01QH\xc0gL\x924c\xa0\xb3K\xf0\xb7+s\xe8\x06\x0f\x0f\xef\xdbx~\xc7\xf9\xfc\xb4\xc4U߲\x9b\xf3RZ\xf1c_]\x17y\xfcSvR\xc6\xd3]\x8a\xd8j\x9eǓ\xceR\x9e\fͯ%\xf1\xf2\b\xfd\xfcڹ\xb6\x94܋\xecnX-\x15\xb9(\xb7\x82\xaaE\xdaz\x84\x17\xc8&{\xd9\n\x9f\xceHZE\xf6B}\x15\xd9IY\x15\xb4\u05ff\x98\x97\x9a\xbcV5\xa6m\x8f\xe0\x04\"Twn\x90\x0f,\xa1\xf8lrqPWᢤ\x9c3\xa9u\x8a\xfd\x87\xb2\x90\x80\xf9\x98$i\xc6@\xe7P1\xbdCh\xd1.\xa3}\x86\x98\x9e\xea괌{R\x9fλ\xf3Sv\xf3\xa7i\xfc\xaaҷzhz\x13\xbf\xad\xae<%\xab\x8f\x8d\xedjL~\xeeK\xf4\xe5sɍ\xb8\xe1\x9fklL\x14{\xb0\x93I\xd9{O\x94\xf2\xe5\xecnX-\x17\x93\xbeI\xfc\x8c\xaaE\xda\xdau\xa61#\xa7\xb1\xb1\xf1#\xb2\x9b\x8dϨ>27\x97$\xf3m;\xeav\xd8\xf2q\xea|r\xc6\xfe#\xabx\xa5Z\\E\x9b\x05\x8a\x94\xb7ic\x0e,\xa1\xf8lrq\xae\xa5%\x97\xd7m\xe1\xf9\nE\x06CYH\xc0|L\x924c\xa0\xd3Y\xe4p\xba\x9ce\xf6\x12\xa3}\x86\x9e,\xfe\xa1k\xa8\xef\x9ar\xe3W\xa5\xbf\xb2\xf1ɤ\xef}\x95ߏ\x1f\xcf\t\xfd\xb0\x1c\xbb)\x0f?\xe4m\x12\xc3EI\xf7\xa4\xad\xea!R\xfaJ\xb1[a\x1e\xcaژ\x8d\x88Z\x94\x99\xc9cڔop\x8e)8Uǟ\xc0\x8f'x܅\xe6d\xe0\x9f\x8b\xbe,\x95Z\x9c-\x02\xca; 2\aV \x95\x979p~2\xe9i\xb7yHz\b\v\t\x98\x8eI\x92f\ftP\x87\xc3n\xb7\x1fv\x98pg\xbf,\x9b\xa2\x83\x96\xe89\xb1\x8a4ڼ\xb4\x9eo1\xa9\x9b\x94\xb1'\x13\xbbPW\xd2I\xf1\x95(\xe9:\xfe\x03\xf7\xde\xccnX-{\xf9\xbdT-\xca\xccd\xb5\x90\xd7tB\xbaI8\x1d\xb4h#\xba&hn\x87R--\x9c\x1b\x85\xe3\x0fs`\x05Ry\xe5\x03\xf7%Ѳ\xb6zJz\xc8\n\t\x98\x8fI\x92f\ft0\xae\x8e^Tl\x82'VV\xb6\xe7\xb6s\u0094\xf1\xc1\\\xd2\xd1\t\xe4*c\xbfM>\x82\x8e\xccu\xaft\x8b\x92.\xe7{\xdc\xef3\xbba\xb5|Q\xf8%U\x8b23\xe5\xca\x13U˃\xf4\x1d\x94\x9b\x8d{\xc9F\x84<W\x9ej\x1c\x025\x8a\xad́\x15H\xe5\x95\x0f|QX\xf3\xeb\xf2\x94\xf4\xd0\x15\x120\x1d\x93$\xcd\x18\xe8 \xbaP\xd6l7\xe1\x8e\xdar\xa3\x95I\xd9F\x9f\n3H\x9f\xf5.\xe5\vU\xec\xb6\\\x94\xbb\xcd\xfdB\x94\xf4\t\xfe}\xf7\x16f\xb7\xc2<aK\xa1Vf\xfbI7*\xabeS\x1a\xf9\x95\xe8K\xcbG\xdf\xf0\xe5\xbd\x1dW\\\xf9>\xa9\x859\xb0\x02\xa9\xbc\xf2\x81\xc5^\xfa\x03OIӸ\x81\x16\x92\xe6\xe2[!\x01?b\x92\xa4\x19\x03\x9d&\"\xe6+\xc5f\xf8簒nY'\x8cg禒Yi\x1fy\xeb\x840\xa7,ܫ\x8a}+\xf1\xb3ķ\xdc/DIw\xa5\xe4\x90\xder\xdb6\xc5n\x8cZ\x14\x99\xe5\xe4 \xf4%\xdd \xab\xa5\x8e\xbe\xae&#\xfe\xec\xff\xfaј1?\xfa\xb9Oja\x0e\x8c\xe4O\xc1\x94\x979\xf0ڹX\xab}\xf9\xa2\xa4ݱ\x83-d\x1a\xae\xa8\x8f\x12}*$\xe0GL\x924c\xa0\xd3l\xafm\u007f\xb3\xd8\xe1w\xb7\x8doߢk\xba\x9f\x88/gq3\xe8\xf3\\>\xa5\xb4\xee\xc8CId\xa9\xb7\xf0μW\x8el\u00adX\x19ۗ\xba*\x95\x8e\xbb{\xce46&nll$\x8bf'\x13\x17U\xd4\t+O\xd2n\xdf\xe4\xe5|\x86_\u007f\x96\x93\xf7\r\xb3\x15\x11y\x94\xe3C|\x8a>k\xb4m<\xd3\xf7\xceF[#\x8e\xcb\xe3\v_-䉾\xde\xff?\xdf).\x18\xf3\u007f\xff\xb3\xa2\x15\x19\xc3\x1cX\xfa\x14\x8a\xf2\xca\a\xfe,%\xad\xe2\x95\xdcDe\xec`\vٚ\x94Z\xba#\x99\xb7\xed\xf7\xa5\x90\x80\xff0KҌ\x81\xce\xf1\x92\"\xc7q\xa3\xf0\xa1\xe7}fڈ)\x8a\xb2\xd3\xe7_U\x14.JJɥ'oЉ\x9c\xb9\xc99u\x1e\xb1\xe56\xe1\x94\xd1;\xe2ԓJ䣵\xa9\xf7d\x1fQ\xecV\xca\xf3dai#O/\x9fvo\xc5\xf4lKN\xcc9G/\x9f\xe6m\x1f\x90\xb3\xdb[\xf0/EyVRV9\xf9\xadp\xfdpV\u007f\u007f\xe4\x8f~N\xb6\x1a\xc3\x1c\xd8\xfd)\x94\xe5\x95\x0f\xfcŦ\xb4ćΉ\x92\x16c\a[Ht>79\xadp\xbfͷB\x02~\xc34I\x03\xfatF\xce\xc1\x92\xbe\xadyxF.\xea\xe51 \xb8\x00I\x8f@\xa8\xa4#nk\x02I\x03\x03\a$\xad\x84\x1f\t\xfc\xe7\xffƒ\xfe\xe1\xff\xfa\xb7\u007f\xfb\xf9p\x88\x1a$\x1d܀\xa4\x95\x18\xa9\xcd/PIG|\xe7\x87\xdf\xfdN\xc3.\xc7\xe5n4\xa4\x9c\xaf\xe3\x9f~\xcb\xeb\xff\x8f\x01\x01\rHz\x04B\a\xde\x13;\xfa\xbbC0\xa1\x87\xdb;\x87R\xd59\xf87\xc3v\xde(\n\bX@\xd2#\x8f\xde+D\xd2w\xe3*\xfe\xde,W\xf3ؐ\x90\xef\xd9;{\x8dv\x02\x00\x01\x90\xf4\x88\xa3%.f,\x96\xf4f\\\xc5ӛ\xfa\xfbӗ\x1c\x8a\v\x99\xde\x01\x9a\x06|\x03$=\xd2pE|\xef\xf6\x1b\xb0\xa4kq\x15/\xfb\a\x96\xb6\xb3\xbf\u007fF\xf80\x9d\xd0\x02\x82\x0f\x90\xf4H\xa3!\xe4p\u007f8\x964\xc2U|\f\xff\x1d\xc6\u007fs\xc2\x1aF\xc8}\x9c\x80\x11\x0fHz\x84ѻ!\xe4\x1f\xfdd.M\xf8\xa7\xf8\a\x92\x06|\x06$=\xc2\xe8\xce\xfc^\u007f\xff\xc49\xfd\xbd\xae\u007f\xf6w\xe3?\x17\xfe\x03I\x03\xbe\x03\x92\x1ea\xb8\xe6\x85\xf5\xf7\xc7d\xfe\xf3\x1f\xfd\xc7\xff\xf1\xcf\xfe\x86\xde\xfe\xfe&\x9040\x00@\xd2#\f\u05ecHZ\xbb\x9b\x1fs\xf6oXw\xa5\u007f\xdd:\x04\x92\x06\x06\x00Hz\x84\xe1\x9a\x1e\xfdO\x0f@ҀϘ#\xe9\xeeb\xbb@1y\xe5,+\xdag\xc2=MF&\xaei\x93\xff\xe1\xc1,\x904\xe0+\xe6H\x94>:\xac\x00\x00\f\bIDAT\xdae?\xee\xc4\x1c\xb37\xe0\x17\xed\x055\xcd5\x05\xaa\x9bS\x8fZ\\\xd3&zn\x8c\x8e\x02I\x03>b\x8e\xa4\xd1iz\xefnz\v\xc1^\xfax\xa8\x18.\x8f\xa2\xb8\x96\x8d\xa9\xb9\xa2bWȽ\xa7AҀo\x98$i\x8a\x83ܧ\b5\x15Py\x17\x8c\x1c\xefJS\xe9m\n\r\xb9Ổ\xb1\x84\x1b0!?(iq\xa1\x90\x00\xc5\xe8\x13\x03C\x8b\x89\x92n\x12n\nZ)xb9̸\x9f\xe0H\xc4uzŬ\xe9230\x99\x8e\x86˽(\xe4j@\x02\x92\xf63&J\xba\xa4\x92>\xed\x12n\xe0}Ȅ[\xf3\x8fL\\Ζ&\x05\xcd-N\xf2\x9fX i\xc0\x17̓t\x8b]X\x11+\xae\xa5O\xb5\xc5ނG\x17\xdd.%\xddt\x9d\x01$\r\xf8\x82y\x92\xae\x14M\xb0D\xe7\xca*\u007f\xdb\xdc\x05\x1c i\xc0\x17̓t\x91h(M\x1d7\x10*\x83\xb9\xb4\x01D\xd2O\x8eŏ\xac\xb6C<\x12\xde\xf0)HB/Z7\x17\xcd7@\xd2~\xc64Iw\xd8E_\x88&;q\xbc\xbbb\x87\x15o\x03\x88`\xc6\xfd\xf9\xaawI\u007f~\xdfMcn\xf8\xe9\xee\xab\xdahi.\xe4\x16\xe1\xf9\x16\x8fl}\x94t\x88F\x8a}\xdb\xe8s\x01C\x8bi\x92n\xb1_\x16\x12\xbd\xd4;\xa7\n\xceK\x1b\x11\xa2%\x1a\xb5\xa4\u007f\xf1\xb3\xd7?\u007f\xfb\xc9[\xd5a^\b\xb9\x89\xfe\x00\xec\xbe\xe9\xfa%\xad\tH\xdaϘ&\xe9&\xbb\xfb>\x1d\xed\x05U-Up\xf5\x98!d\xc8-\x80\x85\xf2\xcc\u007f\x8c\x19w\x9f\xa8\xa7G\xc7\xfd\xeb\xb8߈\xc2\x1a\xf37\xb7\x94\xa4\x88\an\f\x19{\x01'.\x8c}\x9b\xeey\xf3\x98\x1b\x1fe\xdf\u007f\xfc\xc7$\xfcǏ3\xd9\nG\ty\xfc\xe61c\u007fA2\xfc\r9\xc2Uա^\xff\xe9\xd817?\xee\x8e\xc5G!\x85a\xf6\xb9Q\b\x05I\xfb\x19\xd3$\xdd\"/\x879\xf7\x15\x94\xc15ކH\xbd4~x\xf1\xdf_\xbc\xf0\xfa\x8f\xef\xa3\xe9\xdf߸\xfb\xc2\xee\x1bE\x9d\x8d{QT\xb4\x1cq\xeb\xdbW\u007f\xf28\xde\xf2\xf8Oh\xf4w\x9f\xb9\xf0\xfa/\x149܄G\xf3\u007f\xfe\xbe:[\xda\u007f_x\xfbg?\xc3B\xbfq\xf7\xe7\xbbo|Fu\xa8\x9b\x1f\xf8\xdb\xe7/\xfe\xc4\x1d\x8b\x8fB%\xcd\xec#\x84\x82\xa4\xfd\x8ci\x92\x06\x06\n+\xe9[ɜ\xfa\xedqB\x1ak\xed\xea3\xa2Ξ\x19\xfb\xd3\a\xa8\xaa\xe5\b\x9c\xa0#\xf1[\x9f$ѷ<)\x0429<\x8e\x15\xf8\xb3'\xd5\xd9\n{^\xfd\u007fc\xf1>\xf4\b\xb7\xa8\x0eu\xc3\xdb³\x1c\x1b\xc2\xec#\x85\x82\xa4\xfd\fH:``%=\xd6=\x02'i2\xcc\xfd\x9b\xa8\xb3\xab\u007f{\xf4\xae\x9bIW-G|~\xf5\xea\xe7c\u07fe\xfa\xf6\xd8\xcfI\xb4{d\xce\xe6\xf0\xfd\xd7_\xff\xbeG\xb6\xe2\x03y\xbc\x81\x1e\xe1\x06ա\xfe{\xec]\x8f\xbe-\x95\xe9sQ\xd2\xca}@\xd2\xfe\a$\x1d0\xb0\x92\x1e#\xf6\x90\n\xf1H<\xfe}e\xc4իw\xddw\xf5\xbe\xbb\xe4\x1f\x80\xab\xca\xf7\x9f\xbc\xeb\xae'=\xb2Ւ\xb4\xf2P\u007f~\xe0\xa77<\xc0Ƃ\xa4G\x02 送\x95\xf4-\xbf\x91\xb5\xa7\x18\rS\x88\xfa\xd8\b<I\xbe\xe9\xeaM/\n\xd1\xe2\xc0[\xf1\xfe\xcd7_\xf5Ȗ\x91\xa7\xf6\xc0\x9b\xf0\xfa\rz\x92\x86\x81\xb7Y\x80\xa4\x03\x06Vһ\xc7>\xfa\xb7\v\xbb\u007fLӊ5\xab[\x9f|\xfb\xf3\xd7\u007f\xf6\ve\x04\xe6\xa6\an\x12\xf7\xbc\xf1\xf7tyL\xf5\xbe*\xdbq\xbfw\x1f\x8c<\nK]\xea\xe5\xb1\x1f\xff\xfe\u0085\xdf\xdc\xccƲ\x92~f\x1c\x0e\x1d\a\x92\xf6? 送\x95\xf4\xd5ݷ\x8e\x19s\xebn!\xfd\xe8\x8d\xf2\x99\xa5\xdd?\xbda̸\xff\xbe\xa0\x8a\xb8z\xf5\xbe\u007fu\x9f\xf2z\xe6?\x84\x93X\xca\xf7U\xd9>3.$D\x96\xe7\xd5ߌ\v\x11Ob1\x87\xfa\xfd\xadc\xc6\xfe\xe4u6\x96\x954=\x89\xf5\xc0\x18\x90\xb4\xdf\x01I\a\f\x92\xf6\x02\a<\xde\aI\xfb\x1b\x90t\xc0\x10`\x92\xfeş/\xbc\xf8\xef\x0f\x80\xa4\xfd\x0eH:`\b0I?\xfa\xfd17aE\x83\xa4\xfd\rH:`\b0I\xbb\x01I\xfb\x19\x90t\xc0\x00\x92\x06|\x01$\x1d0\x84\x04(F\x9f\v\x18Z@\xd2\x00\x10T\x80\xa4W\xaf\xd6J\x02@\x80b\x8e\xa4\x95\x06:\bU\x99wK\x93\xbfZ\x9e\xd0H\xbayقI\xc0\x89\xf7~\x19\x1f\xbb\xf0\xe8\xfc7pr\xeb\xcc;\xa6\xde1s;B\xf5\x16\xcbB\x84\x0e\xe0\x88\xa3\xea\xfd\x86\x89\xa3\xf1\u007f\x91\xd2mS-\xb3\xbd\x84z\xe7a\x8b\xe5\x80Q̀\x18\xba\x8aZ\x8dìmFQ\x80.\xe6HZa\xa0\x83\x90\xd3^k\xb0\xc3\xf0\xb1\xd2zI#\xe9\xc6\xf5F}\xec\xf2\xf7\x10:;u遗\x96S\x1d\x1c\xb5\xfcr\xcf\xc1\x17\x96Z\xea\x91\xeb\xa8Ŋ\x1f\x0fX\x8e\xba\xd0\x10s\xf4\xac\xe6\xe6\x83VF\x88\xa7V[5\x83|\xe1R\xfd\xd4\xedF1\x03b\xe8*\xea\xe3\xfa\xfa\xff\xb1\xbca\x14\x05\xe8b\x8e\xa4Y\x03\x1d\xac\xe8\x12\xf3$\xddfY\xaf\x91d\x89']\xf7\xe2\xc5$\xb9\x9a\xb4\xd4\xf5\xb1\xb4\xec\xb18\xd8eY\xb9\x9a\xec\xe7CC\x1d \xf3\x97\x1bE`\xb6\x0f^\xd2\bY\x87V\xd2h(+\xea\x14H\xfa:0I\xd2\x14\xc1@\aU٫\nL\x93\xf4j\xb9g^\xed\xd9I\x13hKM\xd8J\x92\uf456\xbax\x01ݼ`1i\xa9Gq\xb3\xf5\xb9\xa5\x0e\x80\x80\x95\xf4\x90T\x14H\xfaz0QҢ\x81\x0er\xb9ܷ\xe7\xf7?mS\xd7k$\x15Ж\xba<\xfe=\x92>\x88\xdb\xe4BAm\xcb\x17\x92\x96\xda6\xff\x80\xba\xa5\x9e\x9dj\xb1lm[\x99`\xbd\x9f\xdc \xf1\xa5\x85֙\xeb\xe9\xfb\xae'f\xc7.|#\xe1 z\xc4byI\x9e\t\xcb\x01\xf5\x8b\x13\xa6\xc6\xff\x12\xcfG\xffb\x11\x98\x8f\x14|m\xb5\x90=)\x97V\xc6\xc7.\xf7\x1cx\xb7-\x8f\xc7Y\xe0_\xa6N\x9cHXJF\xef\x8fX\xa6\xeeY?Ӻ\xf8cU\xa8u\xfd\xea\xf8;\x96\xb6Ѵ\\\x06\x19\xcd\x1c\x0e\xe2\x12\xfc\x16m\xb7h\xce\xc4\aZQdn\xbd]\xccL>\x1aA\x94\xb4^E!\xf4B\xfc\x1e\x04\xe8`\xa2\xa4E\x03\x1d\x82i\x92^=\xf5c\x8d\xa4\x02\xdaR?N\xb0ܿ\xfd\x14\x1dT\xcc\xff5\xdd\xfc\xeb\xf9\xb4\xa5\xee\xfc\xa5\xba\xa5\xba\x0e\xbc\x94036a\xfdJ\xcb\xc7d\x04\xba\xfe\xe0\xce\xf8\xf9X\xdc_'\xc4\xef<\xf8\xb0ŲG\x9cNJ3a9\xe0\xace偣{\xe2-\xbdd^:sa}}}\x9b\xaa$g\xeb\xebž\xb5-v\xe6\v\u007fYlQK\xfa\xb5\xd8\xf9\xbf;\xbaݲ\x93ho\xf5k\a\x96ZN!\xf4ח\xa6Z\xe2\xb7\xef\x8cUw\xfbV\xcb\xfc\x97^\x9ao%\x02\x94\xcb\xc0\xa0\x99\x83덄\x87/\xa1K[c\xeb5\xfa\xdb\x01WT}\xecVwf\xf2\xd1\b\xa2\xa4u*\n\xb3\xdcr?\x02t0O\xd2n\x03\x1d\x82Y\x92\xfex\xea\xc3\x1aI%\xb4\xa5\xa2\xaf\x9f]0\xd5\x12K\xfa\xa6\xd9+\xe9敳iK\xbdd\xbd\xe49\x9e\x9coY܉\xfb9\xa2\x8b?\"\xd2Bqߺ2\x96\f\xeb\xd7[H\xf7B\x85I\x87\xcdL\xc0\x9ex\xd2\\\xff'V\xc8Ag\xe0-Jz\xe1L|\xc8\xde\xf9*I\xbb\x12\xeeǛ\xbb\x0f|M~WH\x99\x84\\\xac\xb1\xf8\xb7ee\xbc:\xa7\xd98\xc25s\x81\xa2\flf\xda9l'C\x87\x95\x9a'\xfb\x06^Q\xabI\xee\xbf&\x99\xb1Gc\x06ޚ\x15\x85i{\xb6\r\x01:\x98'i\xb7\x81\x0e\xc1,I?2\xb5M#\xa9$\xde}f\xcbu\xf4~\xcbA\xa9\xf3Y.t>\xe8\x97;5$m\x15;\xfc\xe5\tݽ\x98\x04\xdcj\xadt\x92\xf9W\x95\xa4\x99\x80\x8f\xe3\x13\x1e\xd9s\x16u\v9x\x95\xf4\xd74\x17\xb4U%\xe9\x83\x16y\x9d\xfc\xef{\xeeO\x88\x15\x86\xeeV\xa2\x19\x8fy\xb7\xf5\xb7\xe4q\x8f\xe5k\xb6\f,\xda9|ly\x0f\xb9b5\xcfE\r\xbc\xa2^\xb3\xba\x90\xcbZO\x92\xcc\xd14%\xadSH\xc0\x13\xf3$\xed6\xd0!\x98$\xe9K\xd6\xd5\x1aI\x15\xb4\xa5\x9e\x12V\xce\x16.\x15\xfe0K\x85)\":0_C\xd2\xeeY\xf0|qV\xbc\x1cK\x81\xce>]*I\xcb\x01X\xa8{\x96϶\xc4\xffN\xd8ѫ\xa4\xcfZ\xa8\f\xd42\xdd)\x17\xe4T|\xc2\x13\a\xea\x17ϗ\xf6\xf1\x944ͩ\x1e\xff\n\xb0e\x90\xd1\xcb\xe1\xfe'\xd0\xd1\xd8n\xa4\xc1\xc0+\xaa7\xfe\x00z\x99\x0eNأiJZ\xbb\x90\x80\x06\xa6IZ2\xd0!\x98$\xe9\xf5\xb8\xa5y&%z\xe9&\xdaR\xe3\x1f\xa1[\xb6\xceDHlw\xf3\x17\v-\xd5e=\xea)iw\xc3[\x99p\x96\xf2w\xd4+H\xe8=YҴ\x8f\x95\x03\xd0Yr\x9c\xaf_\xb2\xee\x91rx\xc1sr/\xe4\xf2w\xa1\x97V/\x8f\x1d\x95{\xe9\xd9\vH\x99\x96{\x934]\f|\xc1\xd2ɖ\x81A/\x87\xbf\xc4w{\\d7\xe8\x8aZ\xbf\x1c-\xa7\xe5`\x8f\xa6\x96\xb4\xba\xa2\x00\xef\x98&i\xc9@\x87`\x8e\xa4\x8d:\xe9=\xa43\xfc;YmB\xf1\t_\x93-Di\xe2\xe9V\xb2\x03i\xa9h\xf5\xaf\xf5%}T蛷>K\x96\x82Ik\\)H\x1a7\xfe\xde\x05Ve\xc0v\xe1Ҫ\x85tJ\xbf\x10wm\x974\x96\x95Ź\xf4\x02R\x9c6\xabJ\xa6\xae\xf8\x85\xa4\xfb\\\x8fE\x92@J\xd0;ߛ\xa4\x13ȼ{\xf6BE\x19\x18\xf4r\xe8\x8e\xff\xcb\x1d\xeaq\xf7\xa0+\xea\x94\xf5\x92\x95.\x89\xb1Gc%\xadUQ\x98\xb6\xedm\b\xd0\xc14I\xcb\x06:.\xa7\xb3\xa8\xcai\x82\xdd\xc6\x13r\xcf\xfc\x84F'M.\u007f:\xf0\xc7\x05\U00064bcc\xb7\xc4o=z`1\xb9P\xf1\xa8\xe5\xfe\x97\xeb_^ly\x99\\\x14u\xc0\x85\xea\xadʖ\xda{\x8a\xaeW\v\xf9=a\xf9\xf5\x81\x97W\x93E\x9dK\xf1\t{\x0e,\xb7RI/\x8c\xffݳ\v,S\xff\xf8\x1e\x1b\xb0\xdd\x12\xbb\xf5\xe0\x81Ֆ\xd7\xc8~ۭ;_^lU\xf6\xd2\xddo\xd4\xd7[W\xd7\xd7w\xe2\xceޚ\xb0}\xeb\x1dB\x0e\fG\xad\xb3\xf7\x1c\\oy\x81d\xb6|ϳ\xf3\xf10\xfeԥ\xfa\xa9\xabO\xa1\xb3\xab\xa7\xd6+Ϻ[-\xf7\x9f:\xba0\xb6\r\xb1e`\xd0\xcdቄX\xb5}\xd9\xe0*\x8a\x10\xbfXX\xb6\x93\x8f&\\=\xb6\xb3\xbe\x9e\xe4\xa6YQ\x98\xa5\xe4\x02S@\x1b\xd3$-\x1b\xe8\x1c\x13.\xf7\xbe\xe2-z8\xb8d]\xa9\x91d90\xdf\x1a\xbb\x94\xaaf\xc1\v[g[\xe3\x85Ӹ[g\xc6Zbɥ˯\xd1S\xaa\xbd\v\xe2\x15M\xfc\xac0\xe9\x13&\x92\xe8\xe8\xe2\xf8\u0605\aI\xea\xef\xab\x13\xac\x8b\xcfRI\xb7-\xb4\xc6.\xfe\xad\xc5\xf20\x1b\xf0\xd2\xc2\xed\tS\xe3\x17\xbeFws\xad\xbfú\xf0\x14R f,\xe4\xb0\xf4\x8e\x84'\xfe8բZ\xa5o[\x9e\x10\xbb\x80tg\xbd;gZ㗿0s\xea\u0087\xf1\x1eS\xdf#\xa7\xb4\x95\xb1\xb3\xb7/\x8f\x8d_)\xc8\\.\xa4\x8cn\x0em\x16\xcf\x01͠*\x8a\xb0Ӻ\x93>\xcbG\xa3\xd7x\xbbg͚\x15EwS/\xe0\x03\x12\xa6I\xda|~k\xf9\xabFrx\x11\x96\xc7\x02\x1a\x97\xf55\xa3\x90\xe1g\xe9b\xa3\x88\xd1\xcb(\x96\xb4\x19\xffU\x19\x04\x92>\xe0\xd9\xd7\xfa\x9dg-\xaa1\x05 3\x8a%m\x06\x81.\xe9\xed\xaf\xa1\xc5[\x8d\x82\x86\x9d\x8f\xe3w\x1a\x85\x8cb@\xd2\xfe\xa4\xed\xa8e\xbdj\x86\x1cP\xb8,\xf3\x1f\x89\xff\xda(\n0\x15\x90\xb4?YHV\x9aڌ\xa2F0[c\x17\xb7\x19\xc5\x00\xe6\x02\x92\x06\x80\xa0\x02$\r\x00A\x05H\x1a\x00\x82\n\x904\x00\x04\x15 i\x00\b*\xfe?\xb6^u\v\xa5[\x1f\x81\x00\x00\x00\x00IEND\xaeB`\x82",
+
+	"analysis/ident-func.png": "\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x03\xd2\x00\x00\x00\xda\b\x03\x00\x00\x00}\xf6\x8a\x1c\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x02\xfdPLTE\x00\x01\x00\x01\x04\x00\x02\x05\x01\n\x03\x01\x05\b\x03\t\f\b\t\x0f\x11\x0e\x10\f\x10\x12\x0f\x13\x15\x12\x15\x16\x14\x0f\x17&\x19\x18\x11\x1a\x1a\x13\x1a\x1c\x19\x1c\x1c\x16\x13\x1e7 \x1f\x19!# $$\x1d#$\"$%#'(&)(\"+)\x1e\x14+N++$*,)/-\"-.,.2402/63(241:7+685;9-:;9?<0=?=C@4AB@CEBGE8KH<MI8HIG\x00f\x00\x00i\x01JLI\x00j\x02SN=MOL\x05m\x051S\x96WRAQSP\fo\t\x0fq\vUVT\fr\x175[\xa4XZW,`\xae7]\xad\x15w\x1cb]K\\^[9a\xab\x19y\x1e;c\xad=d\xae`b_)z!?f\xb0)|*Bh\xb3egdLi\xafDl\xb0qjRikh/\x82/Ho\xb3/\x859Jq\xb6mol;\x86:Ut\xb4Xv\xb6?\x8a>|u]tvsB\x8c@@\x8dG\\z\xbby{x]~\xb7e|\xb8\x84|dK\x90J_\x80\xba}\u007f|O\x93Nb\x83\xbd\x8b\x81cN\x95Ud\x85\xbf\x81\x83\x80W\x95Vl\x87\xbc\x8f\x86hZ\x98Yo\x89\xbe\\\x9a[\x87\x89\x86\x93\x89k^\x9d]\\\x9dds\x8dË\x8d\x8a\x96\x8doz\x8e\xbfe\x9ef\x8d\x8f\x8c|\x90\xc1\x9b\x91s\x90\x92\x8fi\xa2i~\x93\xc4x\x95Ā\x94œ\x94\x91{\x98\xc7s\xa4l\xa0\x96xq\xa5s\x97\x99\x96\x83\x9bţ\x99{\x99\x9b\x98u\xaaw\xa7\x9d~\x87\x9fɜ\x9e\x9b\u007f\xabz\x89\xa1˫\xa0\x82\x9f\xa1\x9e\x8f\xa2ǡ\xa3\xa0\xa2\xa4\xa1\x92\xa5ʂ\xb1\x85\xa5\xa7\xa4\x94\xa8ͳ\xa7\x82\x8b\xb3\x89\xa7\xa9\xa6\x96\xaa϶\xa9\x84\x8e\xb6\x8c\x9d\xac̪\xac\xa9\x8d\xb8\x93\xba\xad\x88\x9f\xafέ\xaf\xac\xa1\xb1ѯ\xb1\xae\x97\xbb\x97\xc0\xb3\x8e\xa5\xb4Ԛ\xbe\x9a\xb3\xb5\xb2\xab\xb7ѵ\xb7\xb4\xa3\xbf\x9d\xa2\xc0\xa4Ÿ\x93\xb7\xb9\xb6\xae\xbaԹ\xbb\xb8\xb0\xbc֦Ũ\xbb\xbd\xba\xb2\xbdض\xbeӽ\xbf\xbc\xa8ǫ\xafƫ\xcd\xc0\x9a\xb9\xc0տ\xc1\xbe\xba\xc2ײɮ\xc2\xc4\xc1\xbc\xc4ٲ̷\xd2Š\xc4\xc6\xc3\xd5ƚ\xc0\xc8ݻ\xca\xde\xc7\xc9ƻκ\xd8ɝ\xc0\xcc\xda\xc7\xcb\xdb\xca\xccɿҾ\xc9\xcd\xdd\xd7ϡ\xcd\xcf\xcc\xc4\xd0\xde\xdfϣ\xc8\xd3\xc1\xcc\xd0\xe0\xcf\xd1\xce\xe1Ҧ\xc9\xd7\xcb\xd2\xd4\xd1\xd2\xd3\xdd\xdf֨\xcd\xd6\xde\xcc\xda\xce\xe6֪\xd6\xd8\xd5\xd0\xd9\xe1\xd8\xd9\xe3\xd5\xdc\xd1\xd3\xdc\xe4\xda\xdc\xd9\xe6ݯ\xecܰ\xd5\xdf\xda\xdc\xdc\xe7\xdc\xde\xdb\xda\xdf\xe2\xd7\xe1\xdc\xe0\xde\xe2\xde\xe0\xdd\xf0\xe0\xb3\xdf\xe1\xde\xdd\xe3\xe5\xe1\xe3\xdf\xe3\xe5\xe2\xe1\xe6\xe9\xe8\xe5\xea\xe5\xe7\xe4\xe4\xe9\xeb\xe7\xe9\xe6\xf1\xf3\xf0\xfa\xfc\xf9\xfe\xff\xfcd\x82\x05\xe8\x00\x00 \x00IDATx^\xed\x9d\x0fT\x14\xd7\xdd\xf7\x1fZ\xf3\xc6\xe6M\xda\xd7Q\xf6\xe9S\xe2K\xa9%F\xdbd\x95x\xdeJ\xa0fN\\@\x13\x90*\x82Ę*M\xa2\xb4Q⟜h0\xc4\x1c\xff\xb4.\xc1@\f\th\"I\xa4\xc1\x83A\xa4V\xadx\fA\x03\x96'\xc1D\x92\x87\xa4\xa6nj$QL#\t\x1c\x16\x02\xb7\xf5\xbc\xf7ޙ\x9d\xb93;\xb3\xb3\xc0\xee\x0e\f\xbf\xcf\xd1ݻw\u007f\xf7\xcfܹ\u07fd\u007ff\x98\xdf\u007f\\\x1b<\b\x00\x80\xe1\xc6\u007f\x18\xe9\xd6\aFy\x03\x00\x10r@\xd2\x00`)@\xd2\x00`)@\xd2\x00`)@\xd2\x00\x10`\xfa\x8c\f\x82\nH\x1a\x00\x02\x89+c\x127\xc7\xc8(\x98X^\xd2e3یL̤}f\x99\x91\xc9Hd\x14\xb7\xfaԩ\xce\xcaO\x8c\x8c\x82\x89\x89\x92n\xdeWTrB\f79\xcb}\xda~\xb3y^bN\xbfO\x13m\x9e\xe4\xd6\x19\x99\x04\x8as9I\xa9\xb9\xa7R\xbfR\xc7\u007f\xee\xe0\xefӲ\x17xr\xc2\x06\xaf\xb8\"\x0e\x135\xfb\xa4\x869Ck87\xd5_[?!\x99\xadC\xeb\xf0k\x81\x0f+\xa1`_\x04\xbeիxLr\xce\xfbFv~\xa2\xd5ꁡ\x81\xdbgd\x12dL\x93\xb4\xbb\xd2y\xb4\xf5\xa4\xb3\x85~h/8\\\xec\xd3\xfa\x91Ԋ\xbc\xa4\x0e\x9f&\x9al\x9dPdd\x12(\xea\x93~Sqp)\xcf\u007f\xa4\xfe\xa2\xff\x9d\xcd\x0e\xad\x04\"\xe5\xe1[\xd5QW\x8b\xb8\r\xd5E3\xb9j-{\x99\xa3\x196\xbfm}S-\xfe\"\x90\xcc\xdaPۓ\\\xd1U_\xe6\xb4`\x1f\x04\xa1ջ\xab\xf8\x97NUe\xddu\xca\xc8\xd0\x17\xa7\xceJA\x8dV\x0f\f\xb5\\\x8d\x91I\x901Mҕ\x05.\x84ڜ\xcd\xf4Cy\xa5˧\xa4;\xf8\n\xd4\xdf\xed\xcbB\x9bV\xdbr\xdf\x06mq\x81\x9a v$\xaf\xe9\xc5=/\xd3[\xd2\b\x95\xfa\x924Zis\xa9\xa3\x9a\xe8O\xfd\xcc)\x1a\xd6,\xebl\xfe\xdb\xfadF\x8a\x18\x102\xab\xe6\x9a|Y\x8b\x05\xeb\x12\x94V?\xc7\xd7\xe3_\xc7\xecL#;_d\xad\x97\xc3\x1a\xad\x1e\x10j\xb9\xa3F&A\xc6,I\xbb\x9c\r\xe4M\x18\f\x9a\x8aܾ%}\x81?\xee\xebk]2&u\xfa6h2\xea\xbc~S\x98t\x99\xbc\xed\xe5?\xf5\xfeη\xa4;'e\xa8\xa3\x04em\xe5\fj\xcfH\xda\xd0\xd6'\xd3\x03*頴:\x954\xaa\xe0\a\xf1\xc3.\xb1\x94\x91\xb4F\xab\a\x84\xd1+\xe9\xa3\x05=R\xf8jA\v\xf2!\xe9\xdey<%\x1f\xa1m<\u007fP\\\x9bn\xe3\x1d\x15\xf9\x99I9_P\x9b\v\xeb\xe79RŰ\x8c{\xa24\\\xb4\xa4D\x85O\x9a\xad\xfca\xde:\xa5\xbc\x99k.\x9f\xe2\xc4\xe1ƜtǼ\x9ct\xb2\\\xef\xaf\xcaJ\xca\xcc\xc7]\xe7C\a\xcf0\x97\x9e\x98\xf3\xedA\\~)*\xe5I\xf9\x9a\x06(s\vͳc/\x1e\xab\xfb+\xb2\x92\x96VХ\xff\x17\xb9i\xc9녉\xb7\x94\f\xa9\xea\xbb2\u008d\x94\bʚ\x1fM?\x14ό\x98\xb2\x8c\x88\xe4j\xca$[\xf4\x1c\xfaS\x88\\\xf3'E\xa6dȒVۢ\xce\xe5S'\xc6\x1d\x8dއ\x96p\x13\x8a\xf1\xc0).\u007fe\x83\x9aY\xd1\xe1Q\xb3q\xb2rN`:RIڠ`٠!\x9c\xe3V\xb6̟\x1c1\x9b\x9cTO\xab+c%\xe4Vg\x9a\x8f\x9c\xcd-i\xc9k.P\x13\xad\xb3)H:7\x8d\x84\x99\x96\xec.\xbc/)\xfb\x9d\xb4z\xb6k(\f\xa4\x13{\\\xe8E|\x96\x98\xa1w\xabk\x1e\x90\xf2(\x9c\xd3#\xa6\x93\xee\xa2sl\x88\xb4\xddh\x95tYy\xf3ng\xf1aڪ\xe5\x95ȗ\xa4\xd1G\x8d\a\xf9\xd2\xc6F<\n~\xd1\xe8(\x15צ\xe7\x0e:\xf8\xd4\xd2W\x92\xe9\x0f賓\xacW\xeaK\xf9\xbd\xaa\x84'\xa5\x15f\xf5\xc4\xe9OV\xae\xe36)\xbev\xcd\xe7\xa6r\xb7s)X\xe8\xefߕw\xa4\xbeb\x1e\xff-\x8e\xde\xc2\xe7\xd7W\xa4.\xedG\xbd\a\x0f\xa6gޓ\x96\x9f{\xd7\xe7ݍ\xc9/|\x85\xbez!\xb9\xb1[۠\x97-<ϱ\xb3~\xa7#\x0f\x87.$gV\x1d\xcfᩤ\xa5d\xea\xfa\x1e\xf6\xea\x05M\\\xb9\xbby9G\xb7p2&,)\xdf\x1a5\xbd\x8fh/\xa3\xbad΄Z\x1c\xd92qJQ\xd9,Φk\xdb>9\xea\xc9\xf2%\x1c\xe7D\xae\x9a\xf0u\xd2\xf2W6\xa8\xe5\xe6\xef\xaetFq=\xa8\xf3p͔\xb8\x9a\x9a\x9af13\xb7{\x1f\x95\xb4Q\xc1\xb2\x81\xbb\xa48z\xca\xc4\xe8e\xf39\xb2\xd5\xebiue\xac\x84\xdc\xeaL\U000d1cd9^Z\x9a\x9et\x0e\xe9\x9cM,\xe9\xeeO\v\xf1\xef*b[\xb2#=yo=Vs\x05\xdb5X\x03\xf9\xc4v76ff766zfQޭ\xaey@\x8a\xa3Ȱ\xad,_i\x9b\xaf{l=m\xd53\"\x872]\n\x04fI\xba\xc4Y\xdc\xe0j..\xc1\x9an.\xea\xf4-iv\xe2\xed \xe7T\x98\xc8:\x92\xf1\xefx^*\x0e\xf5\xa6\xe7\u0c71\xf7\xa0z\xff\xac\x9ck\x15\x02\xee\xe8\xd9nr\x1e\xdaU\x06\xfb¹p\xbaAY\x91J\xc4\\\x91\x8c;\xc1q\xbe\n\aϒ\xe1\x18O\xd5\xf8G\xba\x85U\xfc\x96\\\xfc\x92K\x86bM\x83\xcf\xf9\xbfH\xb9\xd6\xd3\x01\x85\xbefg\xe2\xb4\xfdK\x1d\xcad\xaa\xfa\xba\xb8\xddHI\x13\x1d6\xe7\x93`9G\xb6\x9aj\xb9\x17I\xfdIo\xb9\x9d\\\xf4\x9c9\x19\a\xfb\xa6\xdbtm\xe7G\x92\x19\xc92\x8e\f)6\xb2\xfdL\xe7ʌ\x813\x8a\x8c/[#iy\xcc\xc4[\xa0ɏ\x82\x19\x03\x9c\x037몸\x8e\x92Z]\x11\xcb \xb5:۾\x8e\xf4n\xa2\xd0,\xbd\xb3y\x8e\x0e\xb1y\xe4\a\x91i\xc9<\xd2\aP>\x964\xdb5\x18\x03\xe6\xc4*'\xde\x1a\xad\xaew@Rp\x1f\x9d\xc3\b\xaf\x9a\xc76\a7\x9d\xefK7!\xc0,I\x97\x17\x90\xc6\xe8,\xaaE\x9d\x05\xcd}}}\x9f\x14\xfb\xba\xe5F[\xd2y\x9e`\xbd֞\x14\xa6\xccӹʹ\x06\x8d\xafۗ٢\xb9I\xb6eX\xe8\x97\xd3\xd2\xf3+>\xea\xc7]\t\xe5\xa6\xf7~\x8bI\xa3\x13饎\xcfE\xe3S\x89ݨ;锞A\xafC\x1eT\xb6\b\u05ec\xee\xdbL\xb7\xf50;\x1d\xcad\xaa\xfa\xba\x84N\xc4\xd0\xc4m:Z>3\x82\xd4>e\xb2\xbb\a\x13MV~m\xceٓ'r\xb7\xe3\x9aS\xa9\xa2\x956]\xdb\bz\x15\xa9Y%i\xc6\xc05i\xf2\x12g\x03\x12&\x9f\x8c\xa47\xd5\xd6\xd6n\"\x926,\x985@\xd3m\xd2pU\xc6HZ\x8e\x95`Z\x9dm_G!y\xad\xe0;t\xce\xe69\xfe\x95\xb3dz\x12\x89\xb9ܒ\xfdI\xa5\xc2wJI3M͜X/I\xab[]\uf024`\xc6\xed\xf4m\xaa\xda@\xe2\x93}Ω\xa3v\x94\xae\x16~\"\xab\xcbP\xabӃ\xfe\x16\xa4\xb6\xa4\xa5\xe0^\xbeW3\xd9Q\xcf\xdcj+\xe7\xbdnB\xe8\xc9('^\xd5m\x8d\"s֎\x8a\xf5\x99\xfc\xbc\x97\xfa\xc9\xc0!\xb0\x86\x98,\xf5\xac\xbcз\xc9GБy\xe4\xc7^\xdb@\\K\xf7\xe2\xa1\xf9a\xfa\r\xca\xc9\xc2\x03E#\t\xd1J2\xc9T\xf5\xad\xe5\x0e#%tI\xdb>\x81\xc8g\xba8n\xe2!\xb2vR\xf4\xf2\xdd5q\xb8_\x9d\x10\xae\x94\xc8\xdbcj[q\b\xba\xaa\x924\x93\x19jw\xa6L增\xa4\xe5im\x8f\x19\x16\xccf\x86\xa6ϐ*\u007fT\x9e\xd12\xb1\x12l\xab3\xedK\xcf&j\xe4\xcf\xea\x9cM\xba\x96\x16~\"\xe5\x96\xfc\x82?B\xbe\xebVI\x9a=C\xf2\x89UIڻ\xd5\xf5\x0eH\nΜM\xdff\xcfP\x19\xb0\xd4p\xb5\x9a\xf1\xa1\xc3,I\x9f,\xa2\xa3r%\x9e\xa6\xb4\x11\x9a\x8a\xda|\\\xd8PIz\xa7Jҧ\xf8\x0f5\x93u\xda\xc4;\x1e*9\xcd[1\xdct\uf568\xfdl!Y\x98\x1dL\xac ?\xf1g)t\xde\xc7t\x82\xfc5h}>\th\x1b\x14&\xd2\xcf\a\xf9\xaf\xd0\x16a\x97-=\x0f}#\x8c\xd2y\x0ee2U}\xd7\xd9\xd4SSAY\x13I\xed\xe7O>I\xc1\xad3u&\xa9j\x8a<X2\xdbc*\xdb>a\x94n\x92%M\aV&\xb3\x13d\x0f\xeb\xea\x8b\x114#*\xe9\x82O\x14\x926,\x981`~\x14\x98VW\xc4\xcaȭζ\xaf\x83\xb6-\xd9\xd1\xd6>\x9b\xc2\xf6X29\xe7rK\x8a\xa3\xf4G\xb2\xa4w\xaa\x9a\x9a9\xb1biU\xe2\xbc\xc0\xbb\xd5\xf5\x0eH\nfL\xa6o\x933T\x06,\xa3wǻ\x9d^ĺZ\xe0\xb9}\xccߵt\x12\x9e\x9f\xf5\xffF%\xe9\xee\xd4l\xf2Þ\x9f\xafN\x972E\x98\xcewN\x8a#]h\xc92\xb5\x81+R\x98\x1a\x94\xd2\x0e\x83\xb27\x93Y1]$\x17\xbeD^\x19I\xbf\x9bx9\xf1]\x12\xd06\xe8H^O\xf6\xba\xb3\xd3=\x06\aI\x96Y\xe9\xb8[}\x9a\xe8P&Sַo\xeal\xa4BP֤e\r\xeb\xf0ʭ\x84ĬăZ4\xe9D}\xd3\xc9\xecoF4\x9e\xb7\xb6\xd8l\xba\xb6)Q\xa4cΧ\n\x8c\xc0\xea\xed\x9bAl\x19\x83u\u008a0n\t}\x8dÿ\xac\xe4;F҆\x053\x06\xca\x0e\xeeiu\xddn\xefiu\x85\xa4\xe7\xe1\xb5twz\xb6\xbauZ7\b\xd3xAҩ\xf9\xe7Jٖ\\?\x0f\xb7o\u007f\x1e\x95\xb4\xdc5\x18\x03\xe6\xc4\xe2W\x9c\xfbW\xc2wZ\xad\xaew@R\xb0\x9c\xce\xd5_\x14\x96\xcb i5'\nN\xb8\x9a\x8aw\xf7\xd0\x0f}\xae\xa6\"\x97z\xefJB\xd8\xf1~\x87Ν\x1eN}\xa94\x8bwT\x9d\xbb\xdc\xe8\xd8\xfcN\xff\xfb\x9b\x1dd'\xfcT\xe2}\x15\xf5\xc2&\x89\x82\x96\t\xe2\x1ew\xb5m\xaa\xb3|\x89\xfem\x8e\xa5|R\xe9\xf1#[x\xb2V.\xbc+\xf7\xc8_\xb6\xe03\xff\xed\xbbt\x8fT\xfcU\xefO\xcbI\xa3U\xd01\xa8Oz\xb8\xeax\x8e\x83̴s\xf9\xc2\xe3\x85<\xd9O;\x97\x94V\xba3\x99ԗI\xa6\xaa\xef&\xef)\x84pWa\xdcl\xb2x[Υ\x94\x94ep\xc5D\x85)\xce\r\xd3\xf1d\xf9(j\x8a\x88^\xb72rBxQ\xb3\x8e\xadkR\xb4s\xf7\x1c\x1b\x95\xf4̨\r\x1bfr\xc4V\x91\xd9\xc4u\xe5\xbb3\x84\xdd\xe9u\xb6Me\xb3\"\\ʻnj\n\x96\rz\x8e\xd2=s\xcf\x12ZluU\xac7\x8a\xe6s\xf0Y\a+2\x93\xc9~\xb4\xa2u\xe6p\x82\xf4\x04Ig\xe7l^ʶ\xe4\xe5\xd4\xf4\x8a#k\x12\xa9\xad\xd45X\x03\xf6\xc4\xe2\xdf\xff\xbdG\x1e\x11\xee\x1f\xd0ju\xcd\x03R\x1c\xc5\xfc\t\xcb˗O\x98\xef\xeb\xd8Nx\xcd\xe7C\x8di\x92F-eE\xbbO\b\x8aF.\xb2\x94\xd6\x1b\xa7{\x93\xe9\xc2\xc8A\xaf>\\\xc8N\xbc'g'\xcfo\xdbF\xa2>J¯\xdbp\xf4\xa7\xeb\xd3\xee\xc9:\xe2\x9dv\xa5Ml\xe0\x96\x94\xe8\x893\xd4[\x9c2U٥\xe9\x8e\xd4l\xe1v\xc3\xfa\xecy\xc9ٸ\x03}(\xac\xc8rD\x9b\xbd\xd2\x0e\x98\xb6\xc1\xb9\x9c\xa4yk\xe8\xceN\u007f\xc5R\xcfu\xe9\vk\x92\xd3\v\xab\x1c\xb4\x92\x9edHQߚ\b\xaf\xb9C\t^\xd0\xe1EnÔ(2\x1e싋\x8a\x9cId۷i\x8a-*\xa5h\x8a-\x0e\x1fϜ\xc8\xc9ˊ¹%:\xb6\xa8-#:b\xd6\t*閸\x88\x89\xb3\x96s\xdc\x12֠8n]t\xf8\xa48\xf1zӒȈ\xb8Z\xf6\x1eo\xa7a\xc1\x8cA\xc3\x04\xba\x06\x95\x86=\xa1\xd5ձ^(\x9aϑ\xbf%9-O\x90\x1b{6\x8b\xa2\xe8T\x9f\xdc\x18\xf0\nn\xe3\xccyd\xbe&\xb7dǖ\xf4\xc4G\xceRIK]\x835P\x9c\xd8\xde\xfc\xe4\xc4l\xe1\xa6P\x8dVG\x9a\a\xa4<\x8a\xad\xb7Gܾ\xd5+\x96\xa5-<\xa5\xa1\xcdԿ\xae4Oҡa\x99\xad\xc4\xc8\xc4\\^\xb4e\xf4\x18\xd9\f\x9aNa\xe9\x1br\x06\xd1\xea\xc2\xf6\xd8\xe0\xe8\xf6\x9e\x9f\x19\x10\xc4V/\x9b\xca\xc1\x1fW\x06\x95M\xd1\x03\xbf\x9f8\x84\xb4O\n֟\x04\x11̒\xf4 Z=\xa4\x92\x0en\xab\xb75\x04\xe7\xf6q?\xb1\xbc\xa4G5\xa6Iz\xe0\x84TҖ\x06$maZ\xf6q\xcb\xcc\xde\u007f\xf5\x8f/\xe8f\xa7\x91\x95\x0e\x17\xea\xf9\xfcw\a\x9b\xd8z\x80\xa4-\xccL\x8e\xe3\xc2[\x8c\xac\x86\x03t\xb3\xf3s48\xb2I\xe2\vFV\xa3\x06\x904\x00X\n\x904\x00X\n\x904\x00X\n\x904\x00X\n\x904\x00X\n\x904\x00X\n\x904\x00X\n\x904\x00X\n\x90\xb4i\x1c\xcf\xfa*\xb8\xae\\\x80Q\x89\x89\x92\xf68\xd0q\x17\xd1\xc7\x14\x15i=K\xc8¼ė\x92\x9b\x18\x83\xe7\xca\x05\x18\x9d\x98&iفN\xbb\xb3\xc1\x85\x19\xe8\x9f\xee\x8c<\x18\xff-\xe4\x91<UB h\xae\\\x80щi\x92\x96\x1d\xe8\xb4;\xbd\x1f\xb5hIX\xff-\x17\x84'b\x12\x82\xe5\xca\x05\x18\x9d\x98%iƁΨ\x914\xfb\x80\xca-\xa9\x92'\x98`\xb9r\x01F'fI\x9aq\xa0c\xa2\xa45<\xb5\xb0Nq4=\xb5\xf8a\xab\xe5\x8dG\u9fe5\xf7\x1ei\x90\xd6v\xe5\x02\x00\x83\xc4,I3\x0etڝ\x958XcB\xb7\xd6\xf2\xd4\xc2xu\xd1\xf6\xd4bl\xab\xe9\x8dG\xe9\xbf\xe5}\xe1\x01\xdf\x02\x1a\xae\\\x00`\xb0\x98%iƁ\xceU\x1a,y1\xe4\x9a\xd6\xf3\xbb#yu\xd1\xf1\xd4bd\xab\xeb\x8dG\x9ex׳\x0e.\xbd]\xb9\x00\xc0\xa01KҲ\x03\x1d\x84\x9a\x88\x98\xddE!\x1f\xaa\xf4\xfc\xeeH^]t<\xb5\x18\xd8\xea{\xe3\x91%}\x84g\xfe\xde\xdfە\v\x00\f\x1a\xb3$-;\xd0\xf1P\x13\xf2\xa1J\xcf\xef\x8e\xe4\xd5E\xc7S\x8b\x81\xad\xbe7\x1eY\xd2\xef\xf0\xef\xc8yx\xbbr\x01\x80Ac\x96\xa4\x19\a:\x95\x82\xaf\xbf\xear\x9f\t\x82\x80\x9e\xdf\x1dIz:\x9eZ\fl}{\xe3\x11\xfc\xb7t\xb3O\xcf\xf3v\xe5\x02\x00\x83\xc6,I3\x0et\xca\xe9\xf0\xdc^\xd4`\x90$\xe0h{jad\xaa\xe3\xa9\xc5\xc8V\xcf\x1b\x0f\xeb\xbfe}\xa6\xf4\xfc;\rW.\x000h̒4\xe3@\xc7\xe5\xdc\xd7\xf2ɉ\x82\x90\x0f\xd2ڞZ\x14^]\xb4=\xb5\x18\xd9jz\xe3AJ\xff-\x9f\x12\xdf\x11\x02Z\xae\\\x00`\xb0\x98&iƁN[eqQy\x93\x91}0\xd0\xf0Ԣt\x8a\xa3\xe9\xa9\xc5\xc8V\xd3\x1b\x0fR\xf8oA\xe8\x85D\xf12\x96\xb6+\x17\x00\x18$\xe6Iz$\x12\xc0g\xc0\xf7\xe7;\xe8\xd0\x1dDW.\xc0\xa8\x04$=\x10\x02(iԿ7\xad#خ\\\x80Q\bHz \x04R\xd2\x00\x10\x14@\xd2\x03\x00<\xb5\x00\xc3\x1f\x90\xf4\x00\x00O-\xc0\xf0\a$\r\x00\x96\x02$\r\x00\x96\x02$\r\x00\x96\x02$\r\x00\x96\x02$\r\x00\x96\x02$\r\x00\x96\x02$\rX\x95>#\x03k\x02\x92\x06,\x89+c\x127\xc7\xc8Ȓ\x80\xa4G\x1f\xd4s\xcf\xd0\x19\u07be\u007f\xa6NuV\x9a\xf6\xe4YS1Q\xd2\x1e\a:\xca`h\xa9\x8c\x92\xfeL\xbb}IT\xc4lS\xe6j\x9f;\xf8\xfb\x8cl\x10y\xae\x12\xe6\xae\xcc\n\xbf\xefH\xd5\xc9W\xf4\xdc\xd3>+\xf2I\x8do\a@\x80}\xff\x94G\xfa\xff'\xf3\x9e\xf3\x96\xc1q\\D\x8b\x86A\x03\xb7O#vT`\x9a\xa4e\a:l0ԔGHO<\x9b5ə\x11\xd1\xee\xcb8X\xf4\xbf\xb3\xd9ad\x83\xe9x\x89\xafj\xac\xcf\xe5_02\xf4\xa0\x9d\xaf\xc7sϲ\xc9ON\x18\xa2Ӣ\xc0\xfa\xfeY\xce-72\x91\xf0\x9c7WM\xcdV\xcdG&\xd7r5\x1a\xb1\xa3\x02\xd3$-;\xd0a\x83\xe6\xd1\xce\xe1\xee\xd9id\x15$J\xfd\x914\xaa\xe7\xcfa\x9dnc\x9f\x17l\x80F\xbe\x92\xe7\x9e\x19\x1bP\xc4P\xbb}@}\xff\xac\xe4V\x1a\x99hQ\xab#\xe9\x90?pv\xb8`\x96\xa4\x19\a:L\xd0DZ8\xff\xa7}\x01g\x00\x92F\xbd\xc9ی\f%4\xf2\x95<\xf7\xdc^\xe4\xe2\x86:1\n\xa8\xef\x9fu\xdc:#\x13-@\xd2*̒4\xe3@\x87\t\x86\x96\xf6\b\x8e\x9bPLB\xee(\x8e\xe2\xf5Ƞ\xe2\x99\x11S\x96ᱻ!\x9c\xe3V\xb6̟\x1c1\xbb\x87\t\xaa\x8c\xc5\xc7\x17\xb9&\n\x99q\x13UC\x98\x86\xbb\x1e\x84\xbe\xc8MK^/L\x90\x19\x17<\x9a\xb6\x82\xa4Ѷy\xba\xb6\xfd\x15YIK\x85ŶN\xbe\xb2\xe7\x9e\xd9+\xe7\u070e\x8f%\xbcY\xbb4\xff\x1c\tɾ\u007făW %c2S\xe4\xab\xe0I\x8e\xae\xed\xb5\x9bo\t\x17\xee\\6%b\x16\x89\x93\xcf\x1bA[\xbc\xd5 \xe9\xc1`\x94\xb7/\x18\a:L0Ĝ\xa8\xa9\xb1\t#CC͋ܺ\x9a\x1a\xf542c\u0092\xf2\xadQ\xd3\xfb\x90\xbb\xa48z\xca\xc4\xe8e\xf3\xb9O\x98\xa0\xcaZ|Ƞ\xbbh\xab\x80\xcac\xb6\x96\xbb\x1et!9\xb3\xeax\x0eO\xa5'\xbb\xe0Ѷ\x15%]\xc1w\xeb\xd9\xe69v\xd6\xeft\xe4\xe9\xe7\xcbx\xeeY7\xd1v\xa2gv\xdcQ\x9d\xd2\xfcs$$\xfb\xfe\x11\x0f^\x81\x94\x8c\xc9L\x91\xaf\x82\xad\x1c]\x99k7_sq8\x17\xb5n\xd3Dz]J>oHS\xd2=m\xd53\"\xcdZD\x99\x8eY\x92f\x1c\xe80\xc1\xd0\x13\xe1\xe9\x1aZ\x13\xefr\xae\b\x91>C\x9daL\xe7f]\x15\x97\aL\x90\xc5\xf3(\xe0\xb6V\x01\xe5擶\xbb\x9e\xecL\xac\xcf\xfe\xa5Dz\x8c\xb3\x1dm[Q\xd2\xc4\xf9\x8e\xb6m=}\xda0}\xd5Η\xf5ܳ\x81s\xa2\xab\x11䠇\xe0HH\xf6\xfd#?\aYB\xe9=ȓ\x99\"\xc8\xe2\xe4\x84q^\xbb\xf9\x90-\x12\xff\xe0Ώ\x12?E\xf8\x92\xf4\x1c<ƛ\xb8\x8c2\x19\xb3$\xcd8\xd0a}\xe9\x84\x1c\x9f\x92N\x99\xec\xee\xc1D\xd3\x05\xe3t\x9b4*3A\rZ9\x0f\x8aN\xae鮧C\xd0\xc6N\"=\xc6َ\xb6k\x1fQ\xd2U|\x87\x8e\xed\x16\xe1\x9a\xd5}\x9b\xf5\xf2e<\xf7\x94p\x91\xcbЦI=hH\x8e\x84|\xfa\xfeQz\x0frH\xa32\x13d)\xa2?\xa0z͇l\xe4,\xac\xb3\x89\x9f|J\xfa\x93}Ω0J\x0f\x06\xa3\xbc}\xc18\xd0\xf1\xf6\xa5\x13B|Jz\xbaط\xe8lo\xfa\f9^\x0ejQS.\xa0\xdcO\xd6t\xd7sV\x98\a\xd3m,\xc6َ\xb6k\x1fQ҅\xc9z\xb6\x0fS?=('K/_\xd9sO[IJj[\xebdz\xf4Cp$\xe4\xd3\xf7\x8f\xd2{\x90'3E\x90\xe5p\xa4\xa0M\xed\xe6Ct\xaaퟤ15\x9c)#\xc4p\xc0,I3\x0et\x98`\xe8\xf1)\xe9\xf9\x93OR\xe8\x14pz\x8a\x14\xcf\x04\xfdG\xd3]\xcf7\x826\xf2\x84\xd1Tr\xb6\xa3\xed\xdaG\xdc\xf1N]\xafg\xbbEpi\x9d\x9e\xa7\x97\xaf칧\f\x8f\x81s&O\xa4\xd7\xe1\x87\xe0Hȧ\xef\x1fo\xefA\x02Lp\x00\fLҰ\xe3=(\x8c\xf2\xf6\x05\xe3@\x87\t\x86\x1e\x9f\x92\xdeǕ\x90\xb7\x95\xf4&)cIk,'\x19\xb4\xdd\xf5d\xa5\xe3\x0e\xffi\"\x91\x1e\xe3lG\xdbV\x90t!\x11\xa0\xb6\xad\x10{\x90\xac\xa5\xb5\xf3E\x92\xe7\x9e\xdd\\\vj\xe0RP_t\xeb\x10\x1c\t1\xbe\u007fZ\xd7y]\x11S\x14\f\x92\x0e\x15fI\x9aq\xa0\xc3\x06C\x8a\xfbhM\x8d-\xa3\xa6\xe6\xaag\xc7۫\x17,\xe7RJ\xca2\xb8b\xd4s\xb4fJ\\M\r\xe9\xecLP\x85֦/\x83\x96\xbb\x1et.)\xadtg2\xef\xa8:\xa7p\xb6\xa3e+\xdc=\x96\xc7\xd3qR\xdb6\x97/<^\xc8\xe7\xea\xe7+y\xeei\x8bH\xd9\x1d=ŶdCx\xdb\x10\x1c\t1\xbe\u007f\xe6p3\x91\x1a)\x19\x93\x99\"_\x05\xe5\x13}\xcc\xd3\\5\xe1\x19G\xd1Ɍ\xf0\x1a\x17{\xde\xe8\xddc[kj\xbc\xf66N\x8c^o\xa0\xa6I\x9aq\xa0\xc3\x06CI\xed\x04a\xa9\xecD\xeeH\x1a\b\xf7\xba\x81m_\\T\xe4\xcc}X\xf2\x82)\xe9\xecLP\x85֥Y\x16\rw=\b]X\x93\x9c^X\xe5\xe0\xc9\xfd#\x8c\xb3\x1d\r[z\x8f7\x9f.Ny5m\xfb+\x96z\xaeK\xeb\xe4+y\uea5c\x12\xb5\xa4\xb3rJ\xa4S\xa74\u007f\x1c\t\xb1\xbe\u007f\xb6ڢ\x90\x17\x9edLf\xca|Y\xf6E\xf9\xb8-{\t9=M\x11\xf8u\ts\xde\xe8=\xde\x04\xafiS[xJC\x9b)w웎y\x92\x06\x82B_\xfbU\xdfW\x03=\x9e{\x86\x82\xb0=\xa6\xf4\xfd3'N\xcf\xda\x14ʦr\xf0Ǖ\x03\xc6(o \xf4\xb8&\x8d\x193\xc5\xe5SԂ\xe7\x9e!A%\xad\xf4\xfd\xb3a\xd8]\tnk\b\xe0\r\xe8#\b\x90\xf4\x88\x81\xf7\x83_\xfe\xd7\xff*.\x18\xf3_\xbf\xd4\xfe֨\x04\xbf\xf1v$\xe4\x8aڪi\t\x84\x1c\x90\xf4\x88A[\xa6J~\xf9\xbf\xe7\\\xbb\xf6\u007f\xff\xcf\xff\xd3\xfe֨\x04\u007f\x01GB\xc3\x19\x90\xb4\xa5\xe8\x8cL\xb9v-\xf2\xf6\x96\xe0\xde\\\v\x8e\x84\x863 iKA%=\xf1\xf6\xe6\xe0J\x1a\x18\u0380\xa4-\x85 i[ܬ&\x10\xf5h\x05$m)\x04I\x8f\x8d\xfc\xfe\r\r\xbb\xcb\xdbC\u007f\xa9\x1f0\x1f\x90\xb4\xa5\xa0\x92\x9e\xd4~\xad\xe7;aaa\xb6\xa3\xaeNP\xf5\xa8\x03$m%\xfa\xae\x12I\xcf\xc6\xe7\xe6\xfbs\xdc-c\xc3¾\xef\xec\x1c\x9d\xb7P\x8db@\xd2\x16\xa2u\xe6\xf4뱤\xb7\xe2s3\xab\xf9ڵ\x8ce\x87g\x86ŵ\x83\xa6G\x17 i\xeb\xe0\x9e\xf8\xfd\x19\xd7aI\xd7\xe2s\xb3\xfc_X\xdamxĎ\b\xf2\x05-`\xb8\x01\x92\xb6\x0e\raG\xafE`I#|nN\xe0\xffG\xf1\xff\x14[è}\xbc\xc7(\x05$m\x19\xfa6\x85\xfd\xeb\x1aYK\x13\xfe-\xfe\aI\x8f:L\x94\xb4\xe85\xa7\xa7\xd8)P\x8c\x80\xa1г\xe4\xfb\u05eeMJ\xb9\xd6\xe7\xfe\xf7\xb5\x1e\xfcߍ\xff\x13I\x87\x01\xc3\x17\xa3\x93:\bL\x93\xb4\xe45\xc7\xed<\xe9\u009c\x10\x1e\xd0oe\xaaO\xa2`\xe2\x9eo\xbbvm\xfa\x92\u007f\xff\xeb\xda\xc9\u007f\xfd\xfbZCߵk͂\xa4\xbb\x80እ$-{͡7:\xb9\x8b\xad\xff\x14\x8a\x19\x83yd\x99\xff\xb8\xe7D\xd2Ӳ\xf5I\u05f5M\x1b\xae^۰\x01\x81\xa4\x879V\x92\xb4\xdakNy\xe8\x9fS\x14r\x06\xf5\x14B\xffqϊ\xfe\xb7\x17 \xe9a\x8d\x95$\xad\xf2\x9a\xd3\xec\x1c\xa2\x13\xc5a\x84\xd2Î\xc7\x05O\xb9\xf8H\x9d\xe9\xe4\xa1;\x13\x8aQ\xab\x8d\x9b\xaa\xb0e]İ\xf8\xed\x85\xc6=sʿ\xbc\x98\x03\x92\x1e\xceXI\xd2*\xaf9%\x95>\xadG\x14\n\x0f;\x92\v\x9e\xce\xc3\xf4)\x845\xcd\xf4\xd1x\xeb\xf0\x8fZ\x86Ma\xabp\x11\xc3\xe0\xb7\x17\x1a\xf7\xccIȋ\xe8(\"\xe9gn4\xd4\xf5\xfd\xb7\x1aYx\x13F\xff\xe9\u007f\x190\xbc\xf2\xba\xf5~-3\xdf(2Q\x1d\xaeAe\x8d\xda\xef\x89\x1f|\x87\xbe\x87\xdd\xf8\x18y\xf3\xbfvV\x92\xb4\xd2kN\xab\xd3Zϔ\x91<\xec(]\xf0H\x13o\xf6\x01\xb6\xb27\x1e\xa5\x8b\x18\x11\xff\xbdи\x97\x8f\xa9\xb9\xaabwXJ\x13\xee\x8d\xe3^7\xea[\x17ǾE\xbb\x98\x91\x9d\x02}I\xbf>\xde8\xab\xb0\xb0\xb017\xdd\xf6\x94\x91\x19\xc1+\xaf\xb7\xc6^\x14\xbf\x19\\&\xe2\xe1j~\xa7Qq\xa3\xf6\xbb\xe1\xf9/\xe9\xfb\x97\xcf\xdfHޤ\xda\x19b%I+\xbd\xe6T\x96\xf8\xb6\x1eiH\x1ev\x94.x\xb4%-y\xe3Q\xba\x88\x11\xf1\xdf\vM_\xb3-\xec\xfa\x1bn\xb8\xe1{\xdf\xfb\xdeرc\xaf\xc7\\w]\x98\xad\xa4\xd5\xe7X\xea\u125fuu\xdd\xf1\xdb+aW~{\x87\x91\xa9\x8c~\xb6\xbf\xfa\x95\xeeW\x128\xf5\x95\xbf\xfe\xe1Ƿ^12\xd4*\xe8֧\xa4o\x06\x93\t9\\=4\x8eʨ\xfd¾\x14\x03_\n\x96\xb7\xfa\xf5\x1b\xd3e-I+\xbd\xe6\x14\x99\xf2X\xfe\xe0!y\xd8Q\xba\xe0і\xb4\xe4\x8dG\xf9\xf0y\x91\x01x\xa1q7\xad\x9c3+n\x96\xcc\xec\xd9K\xca\x1b\xda\xc3\xc8P\x16&vK\xa2\xef\xa7n\x1e3\xf6\x17\x1f\xe3\x0f\xcf\xde<\xe6\xa6DŽ\xbeu\xdb\x13X\x1b\x8f\xde\x12vˣX\x1c\xcf\xfeh̸\xfb\xbfԲ|t\xdcw\xc7\xd1\x14\x8f\xe1\xc0\xa3a\xaa\xfc\x1e\xfd\x81\x10\x89\x87\xb5?\x93o\u07bam옛\x9fb\x92ɦ]\x1e\x9d|y\v\x99\xa5zJ\xd4/H\xaeԃd\x16\xfc\xc4\x1dC\xca\x04\x1f\xee\xc7t(\xbd8\xf6c1\x1bO\xdd\xe8\xe5beq4\xe6\xadۮ\xbf\xee6\xb6-\xa4\xe2X\xc9\v!O픕\x16j.\xb5\x05\x8d\xf2:\x89C\xc7,I+\xbc\xe6\xb4;}\xb9\xa9\x18\x81H\xe2\xf5v\xc1S@\xc6d*ޕ6\xa5\xad\xb6\xa4\a\xe2\x85\xc6\xdd\xd6ڬ\xa0\xa5\xd5\xd5\xd9'\x8eҲ\xa4ǿ|\xf1\xbd;p\xa7{\xfe\x86g/\xbe\xf5\v\xa1\xef\x8d{K\x96\xf4\xeb?|\xfd\xe2[d=\xe8e\xf9̍/\xff\xe3\xe5\x1b\x9f\xc5\x11?x\xf5\xe2\xab7\x85)\xf3{\xd6\x13\xd9\xf5\xc6x\xfa\xcd\xcd\x0f\xfe\xfd\xca\xeb?g\x92I\xa6\x8c\x0e^\xff\xcf.\xb9D\xfd\x82\xe4J\xfd\xf4\xbfq\xaa\xb7\xc6\r)\x13r\xb8?#?6O\xfd̫Yh\x96\xca\xe2H\xd4\x0f_\xbe\xf8\x8f\xbb\xef\x96s\x97,\xf0\uf0b0\x92&|\x87N\xb9=\xb5S\xe5B^䶠Q\xde'qȘ%i\x85לVg\xbb\x81\xf9\bC\x92\xa9\xc2\x05O\\\x1cBm4\"b9\x9e'\xcf\xf0K\xd2\x03\xf3B\xd3\xe3V҃\u007f8\xbd$\xfd\x06~\xff\x9f\xb1]]?\xfe\x83\xd4\x13\xbb\xc6\\\x94'\u07b7\x10\x83\xf7\xc6iX\xfe\xf8\x19\xfc\xf2̏\xbb\xba~\xf2,\t\x84)\xf3\xa3\x91ϒrȼ\x1b\xbf_\xf7\x9e*\x99d*V\x85pqL\x97\\\xa2~Ar\xa5\xfe\xecI5\x84L\xc8\xe1\xfe\xe1\x16\xfc\xe1\x96?x\xb2\x91\xeaF\xb3T\x16\xe7\x19\x85\xffq\xa3\x9c\xbbd\xd1u\xe5\xb1\xf1]\x1e\xc6?F\x96\x00\x9eکr!/r[\xd0(\xad\x938D̒\xb4\xc2kN\xb3\xd3J\u007f-\xa4\xf0\xb0#\xb9\xe0AD\xad\x9b\xcafE\x90\x8d\xc0\x99Q\x1b6\xcc\xe4\u008b\x9a\x19[\xd6E\f\xcb\xc0\xbc\xd0h\xe0%iO`\xcc\xc7RO\xa4}\xdcc46L\x9c|zY^\xffw\xfc\xf2\xf7\xeb=\x810e~R$\x99w\x93\x88_\x8d\xbd\xfb\x89\xf7\xd8d\x92)\xf3F\xba\xbfT\xa2~Ar\xa5\xaexR\r!\x13r\xb8Wƾ\xd7\xf5\xde\xd8+\x9el\x94\xed\xa3,\x8eD\xfd\xf7\xcf\xc7*r\x97,\xf0T]\xfem\xfc\x03\x8d\xf1\xd4N\x95\xcb\x15\xb6RB\x94\xd1\xc9\x1b\x04\xa6I\x9a\xf5\x9a\xd3\xea\xf1;n\t\x94\x1ev<.x0\xee%\x91\x11qt?\xb0%.b\xe2\xac\xe5\x1c\xb7\x84\xb1e]\xc4(\x18\x90\x17\x1a\r\xc2\xf4$}=#\xe9q\xcc\x0e\xf0\x18qp\xf5\xb6\xf4S\xd2\u007f\x1e'&\xfe\xf3\x83\xb7]\xff\xa0\x81\xa4ɜY*Q\xbf U\xa54&\xde\x03Ʉ\x1e\xee\xdd\xf7w\xdd\u007f\xb7\x94\x8d\xb2}\x94ő\x97\x9f\xfc\xea\xbd//2m!Yt]\xf9-3J\xff\x96(\xd5S;\xef\\Tma-I\x03!B\xec\xa5c\xff\a\xbf\xbc\xc1\xf6ݟ0\x13o\xb2=\xe6\xe1Ǐ\x8a\x01/K퉷d\xe5\x99x\xd3\xfdnQl\u007f\xbd\x8e\x9dl2يo_\x92\xa5\xa6T\xa2~A\xaaJ\xa9\xb6\xc7\x06\x9a\t=\xdc\xd7\xc7w\x8d\u007f]\xcaF\xaa\xdbwȖ\x97\xb28\xf2r\x1d\x1e\xd8_e\xdb\xc2c\xa1\xb1\x96\xf6\xd4\xce;\x17U[\x80\xa4\x81A v\xd7;\xeex\xef\xe2\xcb\xe3پ\xfb\xea\x8d\xcfK\xdbc\xecU\x9d\x97\xaf\u007f\xe2\xe3\x8b/ߪa\xf9\xccMd\x9fI\xbd=\xe6\xb1zv\x1c\x8e\x1c\x87\x03\xe3\xdf\x10\"n}\xfe\xe2\xc5Gof\x92ɒ\x16\xd2]yO\xb8\xfe$\x95\xa8_\x90\xaaR\xf42\xd1\xe03\x11\x0ew\xfc\x83\x9e\xe1\x95=\x8cq\xcf{\xb5\x01y\xb9\xf9\xc1\x8bo\x8cg\xdaB\xb2\xe8\xf2\xa4\x95C\x9e\x8bX\u07b9\xa8\xda\x02$\r\f\x02\xb1\xbb~\xfc\x8b\xb1c~\xf4\x14\xdbw\xbb\x9e\xf9ј\x1f\x88\x17\xb1\x14\xf7^\xbc\xfa\xd3\xeb\xc6\xfc\xf4e-\xcbG\xc7}G\xbc,\xf4\x03\xf9\"\x96d\xf5\xe8M\xdf\x1d\xf7\xe0\x18a\xdeM\"\x9e\xffɘ\xb1?\xff+\x93L)ir\x97\xc8ϞR\x94\xa8_\x90\xb2R\xc2\xcd\x1c\x83\xcfD8\xdc\xfb\xbf\xeb\xb9͋=\x8cgƑկ\xa28\xf2\xf2\xc6\xcdcn\xfa-\xdb\x16Rq]\xea\xeb\xd2\xf2\xad&^\xb9\xa8\xda\x02$\r\f\x82\xb0.\u007f\x18\xcc\r\xa1Z\xe0\xd9,\x9dw\u007f9\xc6\xc8r(\xf8\u007f˥\x0e\x81:\\\x81\x9b\xa4\xbb\xc7n\"o\xfe\xd7\x0e$\r\f\x02\xff$\x1d\b~\xf1狯\xff\xf0Aa\x81\xfa\xfa\xcdF\xd6\x16≛\xc4{\xbcox\xcc\xc0R\x05H\x1a\x18\x04\xa1\x93\xf4\x13\xff9f\xfc\x83B0l\xfc\xab\xbem\x01\x02H\x1a\x18\x04\xa1\x9340P@\xd2\xc0 \x00I\x0f_@\xd2\xc0 \b\x03\x86/F'o\x10\x80\xa4\x01\xc0R\x80\xa4\x01\xc0R\x80\xa4\x01\xc0R\x8cfI\xa7pQ\U000db34c\x00`d1\x9a%\xed\xaa.\x9a\x1a\x05\xeee\x00ka\xa2\xa4E\a:\bu\x1e\xde]\xb0\xfb\xb0)ڪ\xe6,\xef\xe3\x03\x18e\x98&iɁ\x0ej/\xde\xdd\xecj\xde]lƓMj\xb9\xa3F&\x000\xa20MҲ\x03\x9d\x9a\x12\xf2 \x84\x9e\x92\x1a\xa3$A\x00$\rX\r\xb3$\xcd8Щ\x14\x9e\x12Zf\xc6\xd3\xf9AҀ\xd50KҌ\x03\x9d\xf6\xe2\xeavw{\x8d)\x13\xef\x06\xae\xda\xc8\x04\x00F\x14fI\x9au\xa0\x83\x97\xd5N\xe7>S\x9e(莚q\xd8\xd5gd\x05\x00#\a\xb3$\xcd8\xd0qW\x964\xbb\x9aK*Mq]\xb9O~\xf0\x1f\x00X\x01\xb3$\xcd8Щ\xa1\x8e\xb1\xdc%f8\x98\ue31a\xbc\xb5\xdab~\x01\x80эY\x92f\x1c\xe8\x14\b\x97\x86\x1b\n|\xd9\a\x89ZΌM9\x00\b\x1efI\x9aq\xa0#J\xfa\xa49\x92\x86\x1do\xc0Z\x98%iƁN\xb58\xf16c\xef\x19$\rX\r\xb3$\xcd8\xd0q\xbfX\xd2\xe4j*yь-\xef\xa3 i\xc0b\x98&iƁ\x8e\xbbvw\xd1\xee\xda\xd0+\xda\xed:\x99b\xb3\x96\xafz\x000O\xd2\xe63\x87\xe3\xa2ˌ\x8c\x00`d1\x9a%\xed:\tC4`9F\xb3\xa4\x01\xc0\x82\x80\xa4\x01\xc0R\x80\xa4\x01\xc0R\x80\xa4\x01\xc0R\x80\xa4\x01\xc0R\x80\xa4\x01\xc0R\x80\xa4\x01\xc0R\x80\xa4\x01\xc0R\x80\xa4\x01\xc0R\x80\xa4\x01\xc0R\x80\xa4\x01\xc0R\x80\xa4\x01\xc0R\x98(iɁN_CY\xc1\xee\xe1\xe3o\xee\\Nrr\xf6\xa9\xa5\x8dFv\x02\xf5\xa9\xc7\xf5\xbf,\xe5\x1d\xe4\xdb\xfa$\xbeT\xdb`\x1b\xcf\x1f\xd4\xfe\x06}\xee\xe0\xef\xd3\xf9*\xb0\x8c\x88J\x02~c\x9a\xa4e\a:\xa8\xbc\xe8d뉂\x13F)B\xc4Yǚ#\a\xd7\xeb\xf7b\x15Ǔ\x8e\xe8\u007fّ\x9b\xf4\b~{$1\xb7C\xf9ũ\xb3\xc2\xfb\x17\x8d\x0e\x1d\x1d\xa1\xfew6;t\xbe\n,#\xa2\x92\x80ߘ&iفNC\x01y(\u007fK\x81)~\xee\xbc\xc9\xc9\xee\xc7]u\xb3\xbf\x92F\xfd\xbe\xbe,\xccI\xea@\x1d\x899\x85\xaa\xf8\xac\xf5\x9e\x90\xaeZ\xf0\xf0\x19\"\xb5\x8c\x88J\x02\xfeb\x96\xa4\x19\a:\xe5\xfbhL\xf10\x19\xa6\xd3i\xcf>\xc7\xfb\x18|\"\x05\xd7\xcf\x00\x00\r\xafIDAT\xfd\xa70\xf7\x91\x83\xa8*'W\xad\x96\xa5\xc3I-#\xa2\x92\x80\xbf\x98%iƁ\xcen\xc1\xbf]Y\xb9\xaeqp\xf8\xd0\xc1\xf3;/\xe4\xa5'\xe6|\xcbF禞ï\xfd\xf5\xdd\xe4\xb5*+)3\xbf[a{\x90\xe7\U00062cd4'S\xf3\x8e$^\x9e\xa1_X?ϑ\x9a\xf3\x05\x9b\f\xab\xa5b=ʩ\xa0j\x91b\x8f\xf3\x02Y$\x95\xa30?3\x89\xa6B\xfd\x15YIK+\xe8\xa8\xffEnZ\xf2z՜\xd65\x91\x13\x98\xa8zr\x83\\\xb0\x84\xe2\xd8\xe4\xea\xa0\xee\xc2\xfb\x92\xb2\xdfI\xabW\xa4\x0fd%\x01\xd31KҌ\x03\x9d\xc3\xc5\xf4\t\xa1E\xbb\x8d\xd2\x04\x98ރ\a\xd33\xefI\xcbϽ\xebs6\xfa\xf3t>\xa7\xf4\xdd^\x1a\xde\xc2\xe7\xd7W\xa4.\xedgm\xbb\x1b\x93_\xf8\n}\xf5Br#\xee\xf8g\x1b\x1b\x13\xc5\x11\xecTR\xd6+\xf5\xa5\xfc^6\x19V\xcb\x17I\xdf$^\xa6j\x91b\xbb\x1b\x1b3\xb3\x1b\x1b\x1b?%\xc9\x1c|\xe6\xc1\xe3\xf3\xe8x\x98\xe7\xd8Y\xbfӑ\x87C\x17\x923\xab\x8e\xe7\xf0J\xb5\xb8\x8b\xb6\n\x14)\x1f\xd3\xc6\x14,\xa186\xb9:\x1d\xe9\xc9{\xeb\xb7\xf1|\x85\"\x83@V\x120\x1d\xb3$\xcd8\xd0\xe9,*os\xbbʜ%Fi\x02\xcfR\xfe\x91n\xd4߭\x8c\xec(\xfd\x8d\x83O&c\xefq\xbe\n\xbf\x9e\x15\xc6a\xd9vK.~\xc9\xdd\"\x9a\x8b\x92\xeeM\xcf\xe9%R\xeaP$+\xccEK7g!\xa2\x16ef\xf2\x9c6\xf5\x1b\x9cc*\x0e\xd5\xf3\xf5\x9e\xd7\xecL\\N\xffR\x95Z\xdaZ\x05\xda\x14\xb1L\xc1\n\xa4\xfa2\x05\xe7%\x93\x916\xdfK\xd2\x01\xac$`6fI\x9aq\xa0\x83\xda˝N\xe7\xd1r\x13\x9e\xec\xb7ԡ\x18\xa0%zO\xe5\x90N\x9b\x9b\xde\xfb-&m\x8b\xd2\xf6Tb7\xeaN:%~\x12%]\xcf\u007f\xe4I\xcd$\xc3jy\x85\u007f\x89\xaaE\x99\x99\xac\x16\xf2\x99.H\xb7\b\x97\x83\xeeی:\x04\xcd\xedT\xaa\xa5\x95\xf3\xa0\xf0\xf8\xc3\x14\xac@\xaa\xaf\\p\u007f\x12\xad\xeb9oI\a\xac\x92\x80\xe9\x98%iƁ\x0e\xc6\xddއ\x8aM\xf0\x89\xb54\xcb;\ueb30d|x\r\x19\xe8\x04\xd6(m\xbfM>\x82\x8e\xcc\xf3\xect\x8b\x92\xde\xcb\xf7z\xbeg\x92a\xb5t\x14~Eբ\xccL\xb9\xf3D\xd5\xf20\xfd\x06\xe5d\xe1Q\x92^\x14W\xef<Ք\v\xd4(b\x99\x82\x15H\xf5\x95\v\xfeB\xd8\xf3\xeb\xf6\x96t\xe0*\t\x98\x8dY\x92f\x1c\xe8 \xbaQ\xd6\xe24\xe1q\x9dr\xa7\x95Iͧo\x85\x99d\xcc:K\xe9P\xd9\xe6\xafA\xeb\xf3=\x1fDI\x9f\xe2?\xf4\xc40\xc9\ns\x85\x98B\xad̪\xc80*\xabeK:\xf9\x95\xe8O\xcfC\xdf\b\x9a\xcb\xf3K-L\xc1\n\xa4\xfa\xca\x05\x8b\xa3\xf4Gޒ\xa6vA\xac$\x10:̒4\xe3@\xa7ى\x17\x87W\x8b\xcd\xf0\x9f\xc3J\xbau\x830\x9f\x9d\x97F\xfas?\xf9\xaa^XS\x16\xbe\xa4\xb2}7\xf1r⻞\x0f\xa2\xa4\xbbS\xb3\xc9h\x99\x9f\xafHƨE\x91Yv6B_\xd1\bY-\x82\xc1A2\xe3\xcfJ\xc7u\xf84\xd1/\xb50\x05#\xf9(\x98\xfa2\x05\xaf\x9f\x87\xf3\xed\xcf\x13%\xed\xb1\rA%\x81\xd0a\x96\xa4\x19\a:-\xceZWCqyȽm|\xfb.\xdd\xd3\xf5\xac\x90\xe7\x88~\xa6\xe7\xf1\xa9\xa5\xf5G\x1eI\"[\xbd\x85w\xe5\x1e\xf9\xcb\x16܋\x95\xb6\xfdi9it\xde\xdd\xfbNcc\xe2\xe6F\xb2\xf7\x8dW\xd8\xf7U\xd4\v;OR\xb2or\xb3/\xe3ϗ\xb3s\xbfab\x11\x91\xc7^\\\xc4et\xb9ѱ\xf9\x9d\xfe\xf77;\x1a\xb1]._x\xbc\x90'\xfa:\x97\x94V\xba3\x99wT\x9dC\xc60\x05KG\xa1\xa8\xaf\\\xf0\xe5\xd4\xf4\x8a#k\x12\x95\xb6!\xa9$\x102L\x934\xe3@\xe7dIQ\xf9I#\xf3\xc0\xf3\xa1\xb0l\xcc\x11?\x16E9\xe9\xfbo*\n\xefKJ]C/ޠ\xfa\xecy\xc9\xd9\xf5^\xb6{\x1d\xc2%\xa3\xf7ť'\x95ȧ\xeb\xd3\xee\xc9:\xa2HV\xca\xf3dci3Oo\x9f\xf6\xc4bz\xf3\x93\x13\xb3\xcf\xd2ۧy\xc7G\xe4\xea\xf66r\xc9w\xa9\xe7\x92\xef\x855\xc9\xe9\x85U\x0e\x12k\fS\xb0\xe7(\x94\xf5\x95\v\xeeؒ\x9e\xf8\xc8YQҢmh*\t\x84\n\xf3$\r\x98\x85z{\f\xb0\x14 \xe9\xd1\aH\xdaҀ\xa4G\x1f iK\x03\x92\x1eu\\\xa8\xe7\xf3\xdf\xf5\xf9\xf7c\xc0H\x06$=\xea\xc8&\xbb]\x17\x8c\xac\x80\x91\nH\x1a\x00,\x05H\x1a\x00,\x05H\x1a\x00,\x05H\x1a\x00,\x05H\x1a\x00,\x05H\x1a\x00,\x05H\x1a\x00,\x05H\x1a\x00,\x05H\x1a\x00,\x85I\x92\xee)v\n\x14\x93O\xae\xb2\xa2}&<\xd3\x04\x00,\x88I\x92v;O\xba0'\xe8\xb3M\\\x055-5\x05\xa0i\x00\b\x00&I\x1a5\xd1gw\xd3G\b\xf6\xd1\xd7\xc3\xc5}\x06I\x00\x000\xc6,IS\xca\xc9s\x8aPs\x01\x95w\xc1\xf0\xf1]\t\x00#\x173%M\x9f#\x88P\xa5\xe0\x13\xab܌\xe7\t\x02\x80\xd50S\xd2%\x95\xf4m\xb7\xf0\x00\xef\xc3&<\x9a\x1f\x00,\x87\x89\x92n\x15\x9f\xdc]\\K\xdfj\x8b}\x19\x03\x00\xe0\x17&J\xbaRt\x82%z\xae\xac\x0e\xb5\x9b;\x00\xb0\"&J\xbaHt(])x\xa1-\x83\xb54\x00\f\x1d\xf3$\xdd\xee\x14\xfdB4;\x89ǻ\xabN\xd8\xf1\x06\x80\xa1c\x9e\xa4[\x9d\xedB\xa0\x8f\xfaΩ\x86\xeb\xd2\x00\x10\x00̓t\xb3\xd3\xe32\xc7UP\xddZ\rw\x8f\x01@ 0Oҭ\xf2v\x98k_A\x19(\x1a\x00\x02\x81y\x92\x06\x00 \b\x80\xa4\x01\xc0R\x80\xa4\x01\xc0R\x80\xa4\x01\xc0R\x80\xa4\x01\xc0R\x80\xa4\x01\xc0R\x80\xa4\x01\xc0R\x80\xa4\x01\xc0R\x80\xa4\x01\xc0R\x80\xa4\x01\xc0R\x80\xa4\x01\xc0R\x80\xa4\x01\xc0R\x80\xa4\x01\xc0R\x80\xa4\xd1ڵZA\x00\x18\x99\x98$i\xa5\x03\x1d\x84\xaa\xcd{\xa4\xc9\xdf\xecOk\x04=\x1c\xb0c\x12p\xe0\x83_\xc7\xc7.:\xb6\xe0m\x1c\xdc>\xf7\xceiw\xce݁P\x9dݾ\b\xa1\xfd\xd8\xe2\x98:]\x908\x16\xff')|~\x9a\xfd^\x1f\xa6\xbeYk\xb7\xef7\xb2\x19\x10\x81k\xa8\xd5\xd8,漑\x15\xa0\x87I\x92V8\xd0A\xa8\xcdYk\x90 x\xac\x8a\xb9\xa4\x11\xf4\xe0~\xbb.v\xc5\a\b\x9d\x99\xf6Ё\xfd+\xa8\x0e\x8e\xd9\u007f\xbd\xe7\xd0k\x0f\xd9\xeb\x90\xfb\x98=\x06\xbf\xee\xb7\x1fs\xa3\x00s\xec\x8cf\xf4\xa1\x18F\x88\xa7W\xc7h\x1a\xf9å\xbai;\x8cl\x06D\xe0\x1a곺\xba=\xf6\xb7\x8d\xac\x00=L\x924\xeb@\a!W\x89y\x92>oߨ\x11d\x89'C\xf7\xe2\xc5$\xb8\x9a\xf4ԍ\xb1\xb4\xee\xb1\xd8\xd8m_\xb5\x9a\xa4\xf3\xa3\xa3\x0e\x90\x05+\x8c,0;\x06/i\x84b\x02+i\x14Ȇ:\r\x92\x1e<fI\x9a\"8\xd0A\xd5\xce\xea\x02\xd3$\xbdZ\x1e\x99W{\x0f\xd2\x04\xdaS\x13\xb6\x93\xe0\a\xf6\x03\xb8\xd3.\xa4\xd1\v\x17\x93\x9ez\fw[\xbf{\xea\x00\x18\xb1\x92\x0eHC\x81\xa4\x87\x80\x99\x92\x16\x1d\xe8 \xb7\xdb\xf3x\xfe\xd0s~\xdaF\x8d\xa0\x02\xdaSW\xc4\u007f@\u0087p\x9f\\$\xa8m\xc5\"\xd2S\xcf/د\xee\xa9g\xa6\xd9\xed\xdbϯJ\x88y\x80< q\xff\xa2\x98\xb9\x1b\xe9\xf7\xee\xa7\xef\x8d]\xf4v\xc2!\xf48\x99\x96J+a٠nq´\xf8_\xe3\xf5\xe8\x9f\xec\x02\v\x90\x82\xafc\xec\xd2\n\xf8Ҫ\xf8\xd8\x15\xde\x13\xef\xf3+\xe2q\x16\xf8\x97\xa9\x13\a\x12\x1e\"\xb3\xf7\xc7\xed\xd3\xf6l\x9c\x1b\xb3\xf83\x95i\xccƵ\xf1w>$\xacY\xe5:\xc8h\xe6p\b\xd7\xe0\xf7h\x87]s%>І\"k\xeb\x1dbfri\x04Q\xd2z\r\x85\xd0k\xf1{\x10\xa0\x8d\x99\x92\x16\x1d\xe8\x10L\x93\xf4\xdai\x9fi\x04\x15О\xfaY\x82\xfd\x81\x1d\xa7\xe9\xa4b\xc1\xefh\xf4\xef\x16О\xba\xeb\xd7\xea\x9e\xea\u07bf?anl\xc2\xc6U\xf6\xcf\xc8\ft\xe3\xa1]\xf1\v\xb0\xb8\xbfN\x88\xdfuh\xadݾG\\NJ+a\xd9\xe0\x8c}\xd5\xfec{\xe2\xed}d]:wQ]]\x9dz\x8f\xe8L]\x9d8\xb6\x9e\x8f\x9d\xfbڟ\x16\xdbՒ~3v\xc1s\xc7v\xd8w\x11\xed\xad}s\xffC\xf6\xd3\b\xfdm\xff4{\xfc\x8e]\xb1\xeaa?ƾ`\xff\xfe\x051D\x80r\x1d\x184sp\xbf\x9d\xb0\xf6\x12\xba\xb4=\xb6Nc\xbc\x1dpC\xd5\xc5n\xf7d&\x97F\x10%\xad\xd3P\x98\x15\xf6\a\x10\xa0\x8d\x89\x92\xf68\xd0!\x98%\xe9Ϧ\xad\xd5\b*\xa1=\x15}\xfd\xdc\xc2i\xf6X26ݻ\x8aF\xaf\xba\x97\xf6\xd4K1\x97\xbc\xe7\x93\v\xec\x8b;\xf18Gt\xf1GDz(N\xb7*\x96L\xeb7\xda\xc9\xf0B\x85I\xa7͌\xc1\x9ex\xd2]\xf7\xc4\n9\xe8L\xbcEI/\x9a\x8b\x8b\xec[\xa0\x92\xb4;\xe1\x01\x1cݳ\xffk\xf2\xbbB\xea$\xe4\x12\x13\x8b\u007f[Vūs\xba\x17[\xb8\xe7.Tԁ\xcdL;\x87\x1dd\xea@\x16\xc6\xde\f\xbc\xa1V\x93\xdc\u007fGڝ-\x8d\x99xk6\x14\xe6\xfcs\xb0%\xae\x87\x89\x92\xf68\xd0!\x98%\xe9ǧ\x9d\xd7\b*\x89\xf7\\\xd9r\x1f{\xc0~H\x1a|V\b\x83\x0f\xfa\xf5.\rILj\x03\xfe\x8a\x84\x9e>L\x02\x96@\f]d\xfeM%i\xc6\xe0\xb3\xf8\x84\xc7\xf7\x9cA=B\x0e>%\xfd5\xcd\x05mWI\xfa\x90]\xde'\xff\xe7\x9e\a\x12b\x85\xa9{\f\x11\xa0\u05fa;\xe6\xf7\xe4u\x8f\xfdk\xb6\x0e,\xda9|f\xff\x00\xb9c5\xafE\r\xbc\xa1ތq#wL\x1d\t2\xa5iJZ\xa7\x92\x80\x17&J\xda\xe3@\x87`\x92\xa4/Ŭ\xd5\b\xaa\xa0=\xf5\xb4\xb0s\xb6\xe8!\xe1?\xe6!a\x89\x88\xf6/А\xb4g\x15\xbc@\\\x15\xaf\xc0R8@\"\xdc*I\xcb\x06X\xa8{V\xdck\x8f\u007fNH\xe8S\xd2g\xecT\x06j\x99\xee\x92+r:>\xe1\xe9\x03u\x8b\x17Hi\xbc%Ms\xaaÿ\x02l\x1dd\xf4rx\xe0it,\xb6\ai0\xf0\x86\xea\x8b?\x80\x0e\xd0\xc9\t[\x9a\xa6\xa4\xb5+\txc\x9e\xa4%\a:\x04\x93$\xbd\xd1~^#(\xd1G\xa3hO\x8d\u007f\x9c\xc6l\x9f\x8b\x90\xd8\xef\x16,\x16z\xaa;昷\xa4=\x1doU\xc2\x19\xca?Q\x9f \xa1\x0fdI\xd31V6@gH9_\xef\x8f\xd9#\xe5\xf0\x9a\xf7\xe2^\xc8\xe5\x9f\xc2(\xad\xde\x1e;&\x8f\xd2\xf7.$uZ\xe1K\xd2\x1b\xc9\xebk\xf6N\xb6\x0e\fz9\xfc)\xbeg\xb5z\xa8\x1ctCm\\\x81Vl$\x01\xb64\xb5\xa4\xd5\r\x05\xf8\xc4<IK\x0et\b\xe6H\xfaR\xccj\x8d\xa0\xcc\x1e2\x18\xfe\x93\xec6\xa1\xf8\x84\xafI\fQ\x9ax\xb9\x95\x8cꤧ\xa2տӗ\xf41a\xed\xb7\xfd9\xb2\x15Lz\xe3*AҸ\xf3\xf7-\x8cQ\x1a\xec\x10n\xadZDg\v\x8b\xf0\xd0vIc[Y\\K/$\xd59\x1f\xa3\x92\xa9;~\x11\x19>7nD(\x81Ԡo\x81/I'\x90u\xf7\xbd\x8b\x14u`\xd0ˡ'\xfeOw\xaa\xe7݃n\xa8\xd31\x97b\xe8\x96\x18[\x1a+i\xad\x86\u009c\xdf\x01ki=̓\xb4\xec@\xc7\xedr\x15U\xbb\xda|Z\a\x85\xa7\xe5\x91\xf9i\x8dA\x9a\xdc\xfe\xb4\xff\x8f\v\xe3\xc9X\x19o\x8f\xdf~\xec\xc0br\xa3\xe21\xfb\x03\a\xea\x0e,\xc6\x13i7\xeegnT\x17\xa3\xec\xa9}\xa7\xe9~\xf5y1\xdf\xdf\xed?@o\xbc\xb8\x14\x9f\xb0\xe7\xc0\x8a\x18*\xe9E\xf1\xcf=\xb7\xd0>\xed\x8f\x1f\xb0\x06;\xec\xb1\xdb\x0f\xe1\xe0\x9b$ݎ\x98]\xb84\xe5(\xdd\xf3v]]\xcc꺺N<\xd8\xc7$\xec\xd8~\xa7\x90\x03ñ\x98{\xf7\x1c\xdah\u007f\x8dd\xb6b\xcfs\v\xf04\xfe\xf4\xa5\xbai\xabO\xa33\xab\xa7\xd5)\xaf\xba\xc7\xd8\x1f8}lQ,\xa9\xa6\\\a\x06\xdd\x1c\x9eN\x88U\xbb/\x1b\\C\x11\xe2\x17\v\xdbvri\xc2\xddc\xbb\xea\xeaHn\x9a\r\x85y\x88\xdc`\nhb\x9e\xa4e\a:'\x84۽\xaf\xfa\xb2\x0e\x06\x97bVi\x04Y\x0e,\x88\x89}\x88\xaaf\xe1k\xdb\uf349\x17.\xe3n\x9f\x1bk\x8f%\xb7.\xbfI/\xa9\xf6-\x8cWt\xf13¢OXH\xa2c\x8b\xe3c\x17\x1d\"\xa1\u007f\xaeN\x88Y|\x86J\xfa\xfc\xa2\x98\xd8ſ\xb7\xdbײ\x06\xfb\x17\xedH\x98\x16\xbf\x88*\x1a\xb97\xde\x19\xb3\xe84R f,\xe4\xf0Н\tO\xffq\x1á\xe1\xfc\x8a\x84\u0605d\xd1\u07b7knL\xfc\x8a\xd7\xe6N[\xb4\x16\xa7\x98\xf6\x01\xb9\xa4\xad\xb4\xbdwNJ\xd8\xf8U\x82\xcc\xe5J\xca\xe8\xe6p^](\x1adC\x11v\xc5\xec\xa2\xefri\xf4\x1eoϪY\xb3\xa1h2\xf5\x06>\xe0\xc1<I\x9b\xcf\xef\xed\u007f\xd3\b\x06\x17a{lD\xe3\x8ey\xd3\xc8$\xf8<\xb4\xd8\xc8b\xd42\x9a%m\xc6_UZ@\xd2\xfb\xbd\xc7ڐ\xf3\x9c]5\xa7\x00$F\xb3\xa4\xcd`\xa4KzǛh\xf1v#\xa3\xa0\xf3Y\xfc.#\x93\xd1\vH:\xa4\x9c?fߨZ!\x8f(\xdc\xf6\x05\x8f\xc7\u007fmd\x05\x98\tH:\xa4,\";M#\xf9\xfa\xcb\xf6\xd8\xc5#\xb9\xfa\xa3\x01\x904\x00X\n\x904\x00X\n\x904\x00X\x8a\xff\x0f\xb8\x98\xba\xeaw\xacpV\x00\x00\x00\x00IEND\xaeB`\x82",
+
+	"analysis/ipcg-func.png": "\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x02\xaa\x00\x00\x01\xb1\b\x03\x00\x00\x00\x9d\xa2d\x9d\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x02\xfdPLTE\x02\x04\x00\a\t\x05\n\f\b\x0e\x10\r\x13\x15\x12!# '(&+-*2319:8?@>QSPVXU,`\xae7]\xadZ\\Z8^\xae8a\xaa:b\xab;b\xac^`]<c\xad=d\xae?e\xaf@f\xb0Ag\xb2Bh\xb3Ci\xb4fgeCk\xafEj\xb5Lj\xafMk\xb0Fm\xb2Ol\xb2Ho\xb4Ip\xb5Jq\xb6molKr\xb7Ms\xb8Nt\xb9Ou\xbaPv\xbbrtqWv\xb6Xw\xb7Yx\xb8[y\xb9wyv\\{\xbbV~\xbd^|\xbdX\x80\xbf`~\xbeZ\x81\xc0`\x81\xbbb\x80\xc0}\u007f|b\x83\xbd\x80\x81\u007fc\x84\xbed\x85\xbfe\x86\xc0\x82\x84\x81f\x87\xc1\x84\x86\x83h\x88\u0085\x87\x84i\x89Æ\x88\x85j\x8a\xc4k\x8bƈ\x89\x86q\x8b\xc1r\x8d\u008a\x8c\x89s\x8e\xc3t\x8f\xc4v\x90ō\x8f\x8cw\x91Ə\x91\x8ex\x92\xc8q\x94\xc9y\x93\xc9z\x94\xcas\x96ˀ\x94Ł\x95\xc6z\x97Ǔ\x95\x92\x82\x96ǃ\x97Ȗ\x98\x95\x84\x99\xca~\x9b\xca\u007f\x9c̆\x9b̀\x9d́\x9eΈ\x9d\u0382\x9fϛ\x9d\x9a\x88\xa0˄\xa1ѝ\x9f\x9c\x8a\xa2̌\xa4\u038d\xa5Ў\xa6ѣ\xa5\xa1\x8f\xa7Ґ\xa8Ӧ\xa8\xa5\x91\xaaԘ\xabє\xac֙\xacҪ\xac\xa9\x9a\xadӛ\xaeԭ\xaf\xac\x9d\xb0֘\xb4ذ\xb2\xae\x9f\xb3ر\xb3\xb0\xa0\xb4٢\xb5۳\xb5\xb2\xb4\xb6\xb3\xa3\xb7ݝ\xb9ݨ\xb8ض\xb8\xb5\xaa\xb9ٷ\xb9\xb6\xa4\xbcڬ\xbb۹\xbb\xb8\xad\xbcܮ\xbdݯ\xbeߩ\xc0߰\xbfཿ\xbc\xab\xc2\xe1\xb1\xc1\xe1\xb6\xc1\xdc\xc0¾\xad\xc4\xe3\xb7\xc2\xdd\xc1\xc3\xc0\xb8\xc3\u07b2\xc5\u07b9\xc4\xdf\xc3\xc5º\xc5\xe0\xb4\xc7\xe1\xbb\xc7\xe2\xb6\xc9\xe3\xc6\xc8ż\xc8\xe3\xb8\xcb\xe5\xbe\xca\xe5\xc9\xcb\xc8\xc0\xcb\xe6\xba\xce\xe7\xc2\xcd\xe8\xbf\xcf\xe2\xcc\xceʼ\xd0\xe9\xc3\xce\xe9\xc7\xcf\xe4\xc8\xd0\xe6\xc3\xd3\xe6\xca\xd2\xe7\xd1\xd3\xd0\xcc\xd4\xe9\xc6\xd6\xea\xd4\xd6\xd2\xce\xd6\xeb\xcf\xd7\xec\xca\xd9\xed\xd0\xd8\xed\xcb\xdb\xee\xd7\xda\xd6\xd4\xd9\xe9\xcc\xdc\xf0\xd6\xda\xea\xd7\xdb\xeb\xda\xdc\xd9\xd2\xde\xec\xdb\xde\xda\xd9\xdd\xed\xd4\xe0\xee\xdb\xdf\xef\xde\xe0\xdd\xdc\xe0\xf0\xd6\xe2\xf0\xdd\xe1\xf2\xd7\xe3\xf2\xe1\xe3\xe0\xdf\xe3\xf3\xe3\xe5\xe2\xda\xe6\xf4\xe1\xe5\xf5\xde\xe7\xef\xe5\xe7\xe4\xdc\xe8\xf6\xe6\xe8\xe5\xdd\xe9\xf7\xe6\xe7\xf1\xe0\xe9\xf1\xe1\xea\xf2\xe8\xea\xe6\xe2\xeb\xf3\xe9\xeb\xe8\xe3\xec\xf4\xea\xec\xe9\xe5\xee\xf6\xec\xec\xf7\xec\xee\xeb\xed\xed\xf8\xe7\xef\xf8\xe8\xf0\xf9\xee\xf0\xed\xe9\xf1\xfa\xef\xf1\xee\xf0\xf0\xfb\xee\xf3\xf6\xf1\xf3\xf0\xf4\xf2\xf6\xef\xf5\xf7\xf2\xf5\xf1\xf0\xf6\xf8\xf4\xf7\xf3\xf2\xf7\xf9\xf3\xf8\xfb\xf6\xf8\xf4\xf4\xf9\xfc\xf7\xf9\xf6\xf5\xfa\xfd\xf8\xfa\xf7\xf6\xfb\xfe\xf9\xfb\xf8\xfa\xfc\xf9\xfd\xfb\xff\xf7\xfd\xff\xfb\xfd\xfa\xf8\xfe\xff\xf9\xff\xff\xfc\xff\xfb\xfe\xff\xfc\x1d\xe0k\xdb\x00\x00 \x00IDATx^\xed\x9d\tp\x14\u05f9\xef}\x93\xdc\xfb\xde]t2\xaa\xbe3\x12\xd2\x13TI\"b\xb9PzFU\xc0Ř\xb5j\"\x95)!\x97\x8b\x87\x1d+U\x02\xa2\xd8O@L \x18\xa1g\f\x97\xa4,,\x16\x13H\xbc@t\xcbv\n\xd9\xd8V\x99'{\xd8\\Pl\x97\xe0`\x85\xb2͢\xc8\x06\x83\x1fKر@\bMթw\x96\x99\x9e\xd33=\xea\x99Ѩ՟\xfa\xfbE\x91z\xce|}\xba\xc7\xfa\xe9\xcc鞦\xff\x0fQ\x04\x01\xc1CV\x05\b\xe2\fPU\x04\b\xa8*\x02\x04T\x15\x01\x02\xaa\x8a\x00\x01UE\x80`\xa1j\x1b\x828\x04T\x15\x01\x02\xaa\x8a\x00\x01UE\x80\x80\xaa\"@@U\x11 \xa0\xaa\b\x10PU\x04\b\xa8*\x02\x84$Tm\x988X\xcb\x1d\xf3\\\xbc\x9e\x12c\n!\xa4\xdc\xd02\x8c\xb5l\x89S\xfd\xe9\xfbq\x9e\x88\xc3H\xd6\x17\xf9ȪJ\xe2g\xa5\xb5r\xf1ͪ\xe2<\xcdW0m\xe9\xe1\x1e\xd7@\xfa\x95\xc4U}\x96\b\xfcq\xbbJ\x88dT=\xbdj\xc8\"\xd3'\xe2\xf1\x8e\xd8\xc3j\xab2\x89\xae\xea\x81i$L\xd6*\x8b\x95\x90\xfe#aU\x0fg\xc8\xdf\xe6\xc2\xf8}%B\x12\xaa\xbe_BHr\xaa>%\xf6p\xc8\xe7Vu\x82\xb0\xaa\x9f\x16\x13\x85eV\xab!\xfdEªna\xbfnj\x15\u007f\\\xbf+~_\x89\x10\xab광#G\xfeѬt\x06IR\xd5\xd6AR\xb7\x97\xad\n\x05aU\xe7\xf3U|\x13ʧ\xe4\xf1\x05-\xc1\xe9\x03b;\t\xab\xfa2\xfb=\x16\xc7\xef'QbU\x8dKҪ\xbe\x1c\x1a\x19'Y\x15\nª\x0ef?\xffן\xd8\xc2\xe7\v\xf9\xcas-VC\xfa\x8b\x84U\xfd\r\xfb5\x8e\x8d\xdfO\xa2\xf4\xa5\xaa\x13\xf9.\xf2\xc1\u007f\x8fU%'\xa4\xea\x01\xee\xe7\x9fdSIz\xfe\x1c\x91>!AU\xcbC\x03\x16\x19\xd9֖\xcd~\xc8#\xf3!l\x89\xbfw\x17\xb0wж\xd6ec\x06\xf9\x8a\x17|\x1aZ\xe3\xf3U~vT]\xf4ě\xc6\xed\xf50W\xdd3\u007fL\x8e\xa6\r\x9e\xb0H\x8837\xbc\xc5M\xfcсg\x8b\xb3\xbc\x85\xe5\xe19\xad\xd9\x06\xdbv\xf1\xd9\xf4G|\x90\\\x10n2\xab\xdbU5ԛ3\xe5U\x83\xaa\xafȧ^\xad\xaa\xaa\x9a/\x17\x8d\x1b\xfc\\8\xbcl\xa8\x967\x83\xff\x97(\x93\xad{\xf8\x06w\xc5V#}B\xdaT\xdd5R\x16\x14\xca\xc9\xecG#\xc3k<\xf5\xa5\xba\xbd\xf8\xaan\xca\n\xaf\x91\xc7\xe7\x8b\x06Uׇ\x9f\xf3K\xe1L6\xd8ֶ\x80=\x18#\xd6+<\x1dj2\xa9{\xd9+\x1fV\x86T=ͧ\xa8ު\xa8\xb3bQ\x1b\x14\xaa\xf2\xfeɣ|\xce\xee\x95{\xb1\x88-N4\xa9F\xfa\x84t\xa9\xaa\r\rW\x88\xb3Y{\x06\x13\x9dy\xea\xf6⪺K($O3\xe4\xb7\x1aUݔ\xa1w6AX\x18\xbbA\xe6\\!\xe1\xee\xbdϛ^\r\xf5\x1d[\xb7E\xef*\x93ȹ\xeas\xf2a^\xc5\xca\xc8\x11c\xf4\x06\xb9\xaa\x83DۊӼ?yN\x8b\xff\rԛT#}B\x82\xaa~\xb8\x85\x9fV-\u07b2\xe5\x9d8\xaa\x12R\xb0\xe2\x9dz\xbe\x90\xc9G\x16n\xa4\xb7zS\xfd\x04\xf6\xd3\U000e1cbd\xb8\xaaV\xb3\x1fU\xbbN\xb7n\xe2\x9d.c[\xdc4\x9e-<\xb1iӁ\xb6Os\xd9Ҙ\x86?\xfe\x8a\x1f\xe1\u05f6\x99nP\x9e\xa2\xc8< \x05\xfaq\xa8\xef\x98:!\x9a6\xff\x9d-O\b\xb3xg\xadcI\x98⥲\xab\x98\r~.\x9e\xce\x1c3\xccs@\x8c\xa5\x13x\x15\xff\xa3\x18\xd4jR\x8d\xf4\t\t\xaa\xaa\x1eV\x99\xab\x9aÏe\xc49xf\xf3\x87\xfc'\u007fW\xffr\f1\x9e\x93\x8f\xab*\u007f?\x16\xf3\xdaM?\x9e\xbf^\x1c\x17\xe9\x87U˸E\xfcd\xe9\x1f\xd9\xf05\xbc\xcdl\x83\x8c\n\"\x8f\xfd\xb9J\xda\x01\xd9wL\x1d\xf7\x99\xac\xe7OU\x91\xb0X\x9f\xf25C\x14l1ݠP\xd5\xc7\xd6\xdf\xce楙\xa1\x037>\xeeW\x99\xee\x1e\xd2\x17\xa4M\xd5gE\v\x1fX\xd8o{1\xe1\xd3FΖ\xe7^1\x9c\x89\x8d\xab*\xf7\xc5W\xf1\xf2\x81\xc8\x13\xba\xaa\xfc\xc8~\x85h\xe2\xe2\xf3\x89l\xcc\x06\x99p>\xb6\xf4\x1b\xb6\xb0\x87k\xb5Dv\x11S\xf7\xac\xbec\x875\xa2\x8f\x81\xef?\x95\x13vU{\xd3l\x83Bէd\xb1\xf8\xa3Z\xcc\xfe\n\a\x87\xfe;\xc4\xee\x1e\xd2\x17\xa4MUy\u07bd\x88\x88\xc9%\x9f\xdaVEoJ\x10W\xd5M!W\x86=\xb5\xa9U>\xa1\xab\xca=*\x9b\xcb\x19\x1e\xdaP\xcc\x06\xdb\xda\xfe\x0f[\xf0\x89\xf7o\xfe\x86>Bv\x11S\xf7c\xa2\x0f\xf2\xfcC\xaa\xda\xf0N\x9c~gѣ>\xb1\xfd\xa1\xa7M6(T\r\u007f\xb2\xc0\xf7\xb4\xb8\xad\xedU\x12:\xb3\x15\xbb{H_\xd0+U\xf9$-\xac\xaa<Q3R\x1a1\x89\xfd\x98\x1f\xbd)A\xfc3\x00\xe2\x1dY\x90/Ǩ\xb0\xaa_\x12\x03\xb5m&\x1b\x94#Zn9g4\xaf\x92\xe7\xc8b\xea\xf8\xdcy\xb1\xdc\xee$\x125\xb3lm\xe0\xbb\xc2\xeac7(T}'T\xf7%?g\xf0\xa1x\x1b\xe0\xeb\x9b\xec\x1e\xd2\x17\xf4JU~\x8e&\xac\xaat\x83\x0fU!U\x9f\x8dޔ\xa0\x87\xf3\xaa\x9b&z¿oq\xf9VX\xd5V\xa3\v\xbc)f\x83rv\xacP!\x9e\x8d\xa9\x9bH\xf4\x8f\x15B\xaa\xbe\xbc\xa8jF\xf8\x84\xc1\x01>\xb0.3٠PU\u007fk\xe7\x1f\xc5\xceoe\xb5\xde?\x99\xef\x1e\xd2\x17\xa4\xa0*\x9f\xf6\x89\xdf\xff\x97\xfc$\x8d\xa9\xaa|\xc4yB4\xb4~d8\xad\xda\xf3\xe5*\a^~B\fl\xc4\xcb\xe7\x00\xfa\x04\xc0\x17\xa9\b\x11\xabj\xb5Q\x98\xd0\\ \xa6\x8e\xf7\x19\x9as\x8e&B\xd5\x12u\x87\xf8\xd8\xfb\xac\xc9\x06\x85\xaa\xfag`\xfc\xb3\x86\x91\xaf\xe8\xeb\xc5\xee\x1e\xd2\x17\xa4\xa0\xea\xe0\x90\x1dr$3U\x95\x1fV\x15\x88S\x8c\xbf&\xdeb\xf5c\xf5\xf8\xaa\xb6n\x97\x9fK\xf1uŨ͵\x12\xc3+\u007fo\x97\xc7I[B\xba\xc4l\xf0\xcb|\x12\xc5\n\xd3:~\x12u\xa4h\xd8Ç\xf0Z\xe9\xb8\x16:\x9d\xb6\x8b\x1fj-3٠QնG\x89\xfc\x04W\n\x1a\xbb{H_\x90\x82\xaa|\xe8\x11\xf6\x89\x93<\xa6\xaa\n\x89\u007f\xc5\x1e\u007f\xce\x1b\u0087Μx\xaa\xee\xe2}D\xa6\x15\x1f\x86\xba\x17\xb3\x88\x85la0\x1f%\xdf!${\xec\x01\xb3\r\x8a\x832\xfd\x13'~\xf2\xf4\xe16\xb3:qҊ[|\xba\x8c/Նv\xb5@|\xb2\xfa\xfe\b\"7\x1d\xb3A\xa1j\xe4\xe4D躘Їb\xb1\xbb\x87\xf4\x05)\xa8\xca\x15\xf2,|\u007f\x8b_\xfc\xbeLUm\x9bƟ\xf2\xd7.*\x0e\xfd\xf2u\xb8\xaa\x85\xe5:[\xf4Q\xb5X\x18s\xb8\xf5C~r>\x8fK\xc0\xaf>͙\xff\xd4\u007f\xca)d\xf1\xab\xbb^\xe1\xdb\x11g\xdfc6\xc8ŋ\x9c\xd2\xe4\xf2\x90\xed\xa6;Ƈ@\xf2D\xc3o\xe4y\xffڶ\xf0\aq\xf9c'ɹ\a?5\x1b\xb3\xc1(U?\xcf\x15\xa5\xa1Kwcw\x0f\xe9\vRP\xf5U\x12\"\x93\x8fB檪\x1f\xac\x1a\xaeʟB\f\xd4ꪾ\xefS\x9a\xf9Ǖm\xb5z\xc9\xca\xc83Y\xc2\xfb\xe8\r\x8a\x93\xa4\x91\x8b\xbeŅ+\x95\xa6;\xf6\xa1\xbe\x99a\xb2\xef\xb6\xc3\xfa\xd5\n\x9c\"!d\xf4\x06\xa3Tm\x9b\xc7\x1f\xeb\x17p\xc5\xec\x1e\xd2\x17\xa4\xa0j\xf8\xe3\xf9\xac\xfaY$\x9e\xaam\x1f\x8d\b\xff\xf6\xaa\f\x1f\x8b\xc7U\xb5\xedͼp\xa3W\x9e\xac:,\xcf\xcbs\xd3\xeb\u0082\xe5ɋ\xb0\xa37\xc8?0\"\xcaG\r\xfc\x9cTN\xab鎽\x19\xba\xfezn\x1d\t\xff\x83\x952\xa23)\xd4I\xd4\x06\xa3U\x15\xb3\x86\xc8e\xb1ѻ\x87\xf4\x05\xa9\xa8\xda\xf6ʣ\xb9\xdea\xf3\xf6\xb4\xf5\xa0j\xdb\xe7+\xa7\f\xd6|ß\n\x9f\x8d\f\x11_ն\xd6\x15S\xf2\xbcZ\xee\x98g\xc3\xce}T>X\x1b<It\xb7g~qn\xe6\xa01\x8bBW.Eo\x90\u007f\x1f\xa3l\x85\xef,?\x19o\xb6c\a\xe6\x16y\x87\x94\xbd٦\xab\xcaF\xf4\xb9c\x06k\u07bc1\xf3\xfeS\xef\xc1\xb8\xc1hU\xdb\xf8\xf5\t\xf5\x91\x87Q\xbb\x87\xf4\x05\t\xab\x8a \xfd\v\xaa\x8a\x00\x01UE\x80\x80\xaa\"@@U\x11 \xa0\xaa\b\x10PU\x04\b\xa8*\x02\x04T\x15\x01\x02\xaa\x8a\x00\x01UE\x80`\xa1*\x828\x05T\x15\x01\x02\xaa\x8a\x00\x01UE\x80\x80\xaa\"@@U\x11 \xa0\xaa\b\x10PU\x04\b\xa8*\x02\x04T\x15\x01\x02\xaa\x8a\x00\x01UE\x80\x80\xaa\"@@U\x11 \xa0\xaa\b\x10PU\x04\b\xa8*\x02\x04T\x15\x01\x02\xaa\x8a\x00\x01UE\x80\x80\xaa\"@@U\x11 \xa4]ՉdIlc\xfb\xbd\xd86+V\x90\xa7\xadJBE\tU\x9a\xd3@ʭJ\x10\x87`\x87\xaa\xc1\x95\xbe\xebf\xa5=\x93\x90\x80\xa8\xaa{\xb0C\xd5\x0eBPU\xa4\xb7\xa0\xaaV%\x88C@U\xadJ\x10\x87\xd0\x1bU?~O\xe7\xff\xea\x8dR\xd5\x06Rw\xa9\xba@+\x9a\u007f\x89\xd2\x1a\x11\xfbs\x84\xb5\xb6W\x17i\xb9e;xY=Y\xb5c\xb8o\xec)\xb5\x90\xb1\xbd\xa2@\xf3\x8d^p\x81F\vx\xe2\x99aZ\xee\x8cݦE\xc6ʝe\xf9\xbe\xf1M\x87Ȥ\xc8F\f\xab4\x90\xda\xe3\xe59\xd9\xe3_\v\x8a\a\xe5\x17\xf8\xe6\x17\xa6\xf0\xb7\x84\xd8KoT}\xe4\xefu\xfeMo\f\xabZ]@\xb2s\t\x19\xddA7W\x10R^\xd1N\xe9\x8e,\xe2}\xb8\x88\x90Ŕ[T\xed%$\xabC-\xa4\xb4\x8a\x90\x82\x92<\xf6\xedr\x94\x80M>\x92]\x92OH\x93Y\x91\xa1\xb2\x81\x90\xfc\x12\x8dTHU\xe5F\f\xab0;\xb35\xff\xa3\x1eR\x19\xe4\x0f\x1e\xce#\xf9l\xf3\xc5\x1d\x14q6\xbdQ\xf5\xcc?\xe8\xaa\x1e\xd4\x1bê\x92Ql\bl\xd2\xc8\x06}\x02ОMj\xeePڒK\x1a\xb9E\x9e\xe1M\xcd\x1b\x8c\x85\xcd\xc4LJ\xdc@6Yi\x14\xf0\xebl\xb2\xa0\x83\x06k\x89\xf7\x92I\x91Zy\xd4C\xea\x83\xf4\xf2\f\"U\x95\x1b1\xac¶8\xfc$\xa5\ar\xc9F\xf1`\xd8>J?\xd0\xc8f\x8a8\x9bި\x1a\x19V#\x83jDտ\xf0GU\xa4JW\xb5\x86\x94\x89\x8a7\xc8(n\x119F\xa3\vk2\x16\x89\x8a\x1a2\xc7(\xe0\"\xe2\x0fu\xbeޤH\xad\x9cEj\xf8\x8f\x8eaRU\xb9\x11\xc3*l\x8bG\xf9\x837H\x91x\xd0\xca\x1f\x88\xcd#\x8e\xa6W\xaa\xea\xc3jdP\xd5U-\x16\x8fV\xf1Ö\x90\xaa\x85\xe4m\xd1\xd6\xe1!\xa7\x98EE\u2061\x90ޓo\xc3\xcbȓF\x01\x8bC\xab\xb6\xb7\aM\x8a\x94ʮl)'k\x13\xaaʍ\x18Vi \x13d\x9b\x97\x1c\xd77_\x8f\x87W\x8e\xa7W\xaa\xd2\u007f\x8f\x19TuU\xe5\b\xba\x9e\xcc\b\xabz\x8bM\b\xc7\v4\xd2\xccܐ㤡\x90\x95\xeeް\xb8b(!\xb3\x8d\xaajr\xec\v\x11]\xa4T\xb6\x93̠Xh\x96\xaa\xfacWi\x90\xe3.\xf7\u007f;{ +6ꕈS靪_\xfcC\xf4\xa0\xaa\xab*G\xa9\xf5\xdcD\xa9\xeay%\x05\xb8\x91YT!\n\f\x85\xc1U\xecȉd\x94L\x88R\xf5\x0e!\xed\xfa\x06b\x8b\x94\xcaC$K.|\"U\xad\x88]\xa5\x81,\x95%\xe3\xc8\x1b\xfa\xe6QU\xe7\xd3;U\xe5\xb0\xfa#\xb5%\xae\xaa\xd7\t9\x11)3U\xb5\x96dTn\xde\u007f\x8b\xd6E\xa9\x1a$\xec\xbd:Ll\x91Ry\x82d\x18FՊ\xd8U\x1a\xc8\x02Y;\x9a\r\xee\xa8*\x1cz\xa9\xaa\x18V\xd5A5\xbe\xaat\b?\xf2紜\xec2U\xf5A6;j\xe2TGO\x00\x86\x8b\xb3T\x94\xbe=m\x95I\x91R\xf9\xc0\x1b\x9a\xab\xaeTT5\xae\x12~Ͽ\xa3\xb1\xa1\x1aU\x85C/U\xe5êaP5S\xf5\x1e!\u007f\xa3\xfc(\xbbD\x8cx\xdb\xf9)'3U/\x84\x06\xcf[\x05\xfcIU\xd5\x1a9\x93\xa5e\xa4֤H\xad\xac\x90cfW\xb1\xa2\xaaq\x95\x06\xa2\xb5\xcb-\x97PT\x15\x10\xbdU\x95\r\xab\x86A\xd5LUvT\xd4x\xa7\x8b\x1e\xf7\x9297\xd9,2\x97T\x9bO\x00\xba\x06\x91\x1a&\xf3Y?\xe1k\xa9\x02\x9e\xf6\x91e\x0fh\xb0\x8ed\x9d7)R+\x0fgx\xd6\a\xe9\xcd'\x89\xa2\xaaq\x95\x06BJ\x98\xab\xdb}\xec\xfd\x1fU\x05DoU\xa5\xffn\x1cTMU-a\a5\xcd\xe2<\xbf\xb7d8\x93\xa8#\xce\\\xb5\x9e\x90\xa1\xfe\xb1\x9e\x9cE\xe4\xe1\xe8O\xab4\x92S\x92K\xb4&\xb3\"Ce=\xff\xb4\xcaG\xc6q\xf7\xc2\x1b1\xac\xd2@\x86y3K\x86\x11RKQUH\xf4Z\xd5/\x8c\x83\xaa\xa9\xaa\xc7'zs\xde`?O\xfc\xacH\xf3\x95\xac\xe2\xd7Y\x9b\xaaJ\x9b'\r\xf1\x8e^t首\xd1n\x14\x90\x1e\xaf,\xc8\x1cR\xc1/$\x88-2V6\xfb\ay'47\xf0)Cx#\x86U\xd8\x16\x8f\x94e疵\xa8\x9bGU\x9dO\xafUu(+ȼ8\xcf\xe0\xc5T@\x19h\xaa\x96\x95\x04\xc4ωd]\x9c\nT\x15(\x03M\xd5\xf9☩c1ɽ\x1c\xa7\x02U\x05\xca@S\xf5B\x11\xc9\x1cU\xec#Y\xcd\xf1*PU\xa0\f4U\xe9͕%\xb9\xbe\x115'\xe3\x16\xa0\xaa@\x19p\xaa\"\x03\x15T\x15\x01\x02\xaa\x8a\x00\x01UE\x80\x80\xaa\"@@U\x11 \xa0\xaa\b\x10PU\x04\b\xa8*\x02\x04T\x15\x01\x02\xaa\x8a\x00\x01UE\x80\x80\xaa\"@@U\x11 \xa0\xaa\b\x10PU\x04\b\xa8*\x02\x04T\x15\x01\x02\xaa\x8a\x00\x01UE\x80\x80\xaa\"@@U\x11 ؤ\xea\xc5o/^\xb9ml\xba}\xe5\xe2\xb5k\xdd\xe6\xe5\b\x12\x83M\xaaF\xf8x\xed\x15\x8a\x82\"\xc9c\xaf\xaa\xf7)]\xfd\xd8_\xf9\x0f\x04I\x12{U\xa5\xfc}\x1f\xc7T$\x15\xecT\xf5\xfe\xfd\xce\xfb\xf7\x0fn\xbb\xc6~t\xa3\xafH\x92ة\xaa`u\xe99\xab\x12\x041\xc1vU\xbb\xafXU \x88\x19v\xa9\xca\xde\xf0\xbf\xd8\xf6۵kּ\xbe\x8d}[\xfb\xd6{\xdfY\xad\x81 \x06\xecR\x95\x1d\xf4\xaf}\xbct\xfa\xe4ɓ\x1fa\xff\x9f\xfe8\x9b\x06\xe0y\x00$\x19lT\xf5\x85\xc9\x1f\u007f\xf6\xe7\xcf\xfe\xcc\xf8\xec\xb3_N>\x83\xaa\"Ia\xa3\xaa/\x96\xde\xd5\x1f\xae)=C;)ڊ$\x8e\x9d\xaaN\xffB\u007f\xf4\xc2\xf43=U#H\fv\xaa:UW\x95.GU\x91$\xb1Q\xd5\xe5\x8f\xdd\xd8\xf6\xa3\x1f\xfd\x1b\xfb_\xe9\xfd\xdfN\xbf\xb8wm\xe7\xc15\xca\xf5\x00G<\x84\x90\xb9\xfa\n;\xf2\x9aL;\xb2\xa0\xde\xfbk\xb3\xe6v\x8d\x14\xf3\x9fGg\xe4\xe7Lk)\xd9mV\x838\x1b\x1bU}~&\xfd\xe5\xf7\xfe\xee\xfb\u007f\xf7\xfd\xef\xfd\xf7\xcemSo\xbf\xfe\xd8\xed?\x94*\aW]\x9f\x8c-\t\x9c\xd7W\xf8 \xfb\xed\xd8^Z\x0eŶ\x19)\xd1J̚\x83\xfb\xaa4\xf6\xe3\x90V\xde\xf4F\x05\tGh#\x90\xb0Q\xd5\x17J\xbf=\xb7m\xdb{\xec\u007f\x1fӗ\xa6\x9e\xbb\xf2Y\xf7\x95/:\xd5\x1a\xbf!<2Hc\x99\xf0\xa4I\xa3\xca\x1dO\xa5\xe7\x96\xe93u\\\xd52?\xeb5X\x85\xaaB\xc4FU\x95\xb9j\xb7\xe9\\\xd5o\x99s:~\xb6EA\v9DZL\x9f\x11\xaa\x0e\xe7\xf9\xaf\xf4(Iin\x81\xf4/v\xaaZzN\xceLٷ\xff\x98z\x86ލ>Y\x15Q\xf5\xba\x8f\x10\xcfV\xb9\xbc\xb3\xacH˟1,H\x9b\x88d\x1co\r\xbe\xf6hv\xf1\xc2\x0eJ\x9f!\xda\xc6\x05\xc5YegEq\xddPZ\xc8\x13\xa9\r\xad\xdfT\x16\xe6\xce\x12\x13\x80'\v\x8e\xf1u\xb7\xdfR{8\x92I\xc8\xd2S\x95\xc3}e]\x8d\xac\xfb:ZG\xc4\x14A/@\x1c\x81\xad\xaa\xde\xd0\x1f\xae)5\xf9\b@\x19U\x0f\x05\x02\xde:\xb1t \xa3\xf2\xed\x1d\x1b\xf3I\x17\xbd\xb3;0zZ \x108\xc1\x9b\xe7yj\xb67\xe4\x8d\x0fҿl\xcd$yu\xbfΑ\x19\xd5\xfeYt6\xefEm=\x95S\xbc\xb9\xa9\x8cpUۋ<eu{\x1ePC\x0f\x1d\x8d[\x87\x8d\x1eT\xb4\xa02\xe3\xeb[;s\x96]\xa2\x97jsw\xdeR\n\x10G`\xa7\xaa3\x9f\u007f\xe9\xc5Ռ\x17W\xbf\xf4\x93GL.\xb06N\x00|R\xd5uy]\xfc{\xae0F\x9f\x00\xbcK~Ǿ\xef'|\xe4\xd5r\xcfRZ\x99Ǜ\x83\xd9\xf5\xb4>[\x94FZ\xa7\x8cb#c\xb0\x84\xabJ\xaf\xae\x98\xa0\x91\xdcƨ\x1e\xe8x\xe2\xbfI\x837\xd9\xd2<>\x1b\xae\xfcYt\x01\xd2\xffب\xea[?}\xact\xaa\xa4\xf4\xa7?\xbf\x98\xa0\xaa\xe7\v\x87\xd7l<\x1c\x94#\xa1\xae\xea\x93#\x1et1\x86\xf2\x93[\xda\x1c\x1a\x9a\x8a\xd2#dw\xc7nr\x84\xaa\xad\xd7\xc9F\xfex\xa9\x16Z\xf5ގ2\xb2\xdd\xd8\x03\x1d\xaf}\x1dz\xb6\xc5\xd7A;\xb2Z\xa26\x818\x00\xbbTe\xdc8w\xe6\x8b0\xe7\xbe5\xb9\xb6\xdaTUz}\xc3\xecb\x92\xbf\xca8\xaa\x96\x84\xe6\xad\xfc\r^\xe3\x85R\xd5\x06\xd1\xd8@\xd5\xd6CDĮ\x8b\x82\xfd\xdf\xf0\xc5\xe0\xa4rc\x0ft\xfc\xb8\xf0V\xbb\xf2\x9bhS~0j\x13\x88\x03\xb0QUK\xa4\xaa\xb7\x96]\x15\x8fB\xaa\x1eZ̼\xb9\xbeշ\x8e?\x10\xaanf#`\xe5\x88C\x02\x9e\xa4\xae\xa8:k\xdc\xfe\xfd\xfb\xc7͢j\xeb߈Xu\x0e/(\xa8\x11}.\x19e쁎\x9f\x15\xde\aZSA+D\x95\xa1\x00\xe9\u007f\xecT\xb5\xbb\xfb~\x98n\xb3\vU\xa4\xaa\x87\xc9N\xf1(\xa4j\x1d\x11q\xe9\xfe\xeap\xc5%~t\xde,O\x8d.YI\r\xaa\x16.d\xdf\x16\x14RC\xeb\xc4\"\xe6\xfeI/_\xcc/\xe4\u007f\x06An\xa6ڃz\x12l\x8f\xf7\x82w\x0f_0\x14 \xfd\x8f\x9d\xaa\xf6Lמ\xb1%\xec\xf8>\xb0\x81\xbda?\xf8$\x10\xf0V\x05v\xde\xe4\xaaf\xd7~\xd04W\x9e-\xad\xd3\xea\x9b\xfc\xd9\xfc#\xad\xc5\x19O\xbf\xcdZߠ\x17\x02Zվ\xe0\xe1*-p\xa1\xa3\x99,\xb9C\xef\xfc\x8a4\xdfSZ鱬\xa2\xba\xa5\x83=\x99\xbf;N\xf3IAms\x93\xdfwR\xed\xa1k\x8f8\xb3\xd0.w#XXV(\x0f\xfa\xf5\x02\xc4\x118Gգ\x9e\xd0\xe4\xd0w\x82\x1e\b-o\xa0\xf4\xb5iuEZ\x81_\x9e\u05ffW3\xd87m\xbfXl\xf6\x0fɝ\xd2\xccϠ\x12\xa2\xb5f\xb3\xef\xcf\xec\xc8\xe0\xe7C\x9b\b\xc9ء\xb4Rz\xaa|\xf0\xf0\xe7~\x97\xc9\x16'l^R\x9c\x9dWq\xd2\xd0\xc3\x11\xb9\xb1\xf2\xd0~\xd4k\xf5\xa1\xa5p\x01\xe2\b\x9c\xa3*\x82\xf4\b\xaa\x8a\x00\x01UE\x80\x80\xaa\"@@U\x11 \xa0\xaa\b\x10PU\x04\b\xa8*\x02\x04T\x15\x01\x02\xaa\x8a\x00\x01UE\x80\x80\xaa\"@@U\x11 \xf4\xb3\xaa\x18\x12\x84$J?\xab\x1a\x01C\x82\x90\x9eq\x86\xaa\x18\x12\x84X\xe2\fU)\x86\x04!V8AU\f\tB\x12\xc0\t\xaa\n0$\b\xe9\x19Ǩ\x8a!AH\xcf\xf4\xb7\xaa\x18\x12\x84$H\u007f\xab\x8a!AH\x828@U\f\tB\x12\xc1\x01\xaabH\x10\x92\bNP5\xa1\x90\xa0\xa6G/\xc5y&U\xaeN\u009bWC\xc2\t\xaa&\x12\x12\xb4\x8a\xd4Eݓ\xb7\xd7a)\xc1U\x9e\xd8\xfbQa\u038bcq\x80\xaa\x16!A\x82\x06\xcfkQ+\xa6#,e{fCt\x13\xe6\xbc8\x16\a\xa8j\x11\x12\xc4i\xd3\x16\x87\x17/\xfb\xe5]$\xd3\x12\x96\xb2L;\x1bӆ9/\x0e\xc5\x01\xaaZ\x86\x04Q:\xb7@O\x8f8F\x8e\x89\x9fi\tK\xb9S\x10{Oj\xccyq(\x0eP\xd52$\x88>\x18\xb4H.4\x8c~\xf7\x049\xb1}\xf4\xfaT\xc3R\x94\x02\xd1\xe12_L\x82\n\xe6\xbc8\x14'\xa8j\x15\x12D\x0f\xcb{\xa4\xf3_7y\x98\x94\x90Y\xe7S\rKQ\nĚ\xbb\xc9\x1e\x1a\x05\xe6\xbc8\x14G\xa8j\x11\x12D\xb7\x93\x93\xe1\xc5f\x8dh\U000969e9\x86\xa5D\n\x18gI\xcca\x13\xe6\xbc8\x14'\xa8j\x15\x12\xc4\xdetC\xb7\x94\xbe\xba@+$\x85\xde\xe7\xfe&\x1f\xa6\x14\x96\x12)\xa0\\\xd5F\x1a\x05\xe6\xbc8\x14\a\xa8j\x19\x12D\xf7\x91O\xe4ª\xfc\r\xc7\xc9_\x1a\xf2W\xf6\",%R@\xf9p\x15sr\x13s^\x1cJ\u007f\xabJ\x13\b\t\xa2\x1dZH\x18\xfa\x80\x1e#\xc7\xe9\x83`/\xc2R\x94\x02\xaeN\xccI%\xccyq(\x0eP5\x01f\x8d\xd2\x0f+\xce\xe7\xca\x13\xf4)\x87\xa5\xa8\xa7\x9a\x82\xc5\xe1\x04\x00ھ\xb2M.`\u038bCq\x82\xaaV!A\x94\x9e\xf0\xc4|P\x99ZX\x8a\xb1\x80\xd6\x13\xfd\x83\xa7\n2\x83\xff\xc0\x9c\x17\xc7\xe2\x04U\x13`\x997zN\x99ZX\x8a\xb1`\xa7\xef9\xbd\xbf\xcdy\x1b\xf8\x0f\xccyq,@T\r\xce\xd7\x1a\xadj\x92\xa6Q\x9b\xdbeU\x838\x06 \xaa\xd2`\xfd\xd0t\x1fY\\-X\x89'\xd6\x01\x01EU\xc4\xf5\xa0\xaa\b\x10PU\x04\b\xa8*\x02\x04T\x15\x01\x02\xaa\x8a\x00\x01UE\x80\x80\xaa\"@@U\x11 \xa0\xaa\b\x10PU\x04\b\x0eU\x15\x93W\x90h\x1c\xaaj\x04L^A$\xceV\x15\x93W\x10\x1dg\xabJ1y\x05\t\xe3dU1y\x05Qp\xb2\xaa\x02L^A$\x8eW\x15\x93W\x10\x89SU\xc5\xe4\x15$\n\xa7\xaa\x8a\xc9+H\x14\x0eV\x15\x93W\x10\x15\a\xab\x8a\xc9+\x88\x8a\x93UM(y\x05q\vNV5\x91\xe4\x15\f\tr\r\x0eV5\x91\xe4\x15\xdbB\x82\xd2\xd0/\xd2;\x1c\xacj\x02\xc9+\xf6\x85\x04\xa5\xa5_\xa478X\xd5\x04\x92Wl\f\tJK\xbfH/p\xb0\xaa\xd6\xc9+v\x86\x04\xa5\xa5_\xa4\x178YU\xcb\xe4\x15;C\x82R\xeb\x17I\x1f\x8eV\xd5*y\xc5ΐ\xa0\xd4\xfaE҇\x93U\xb5L^\xb15$(\xd5~\x914\xe1`U\xad\x93Wl\r\t\xa2)\xf6\x8b\xa4\t\xa7\xaaJ\x13I^\xb13$(\xe5~\x914\xe1`U\xad\xb13$(\xe5~\x914\xe1dU\xad\x93Wl\f\tJ\xb9_$M8YUk\xec\v\tJ\xb1_$}\xc0Vվ\x90\xa0\x14\xfbE\xd2\apU1$\xc8=\x00W\x15C\x82\xdc\x03tU\x11׀\xaa\"@@U\x11 \xa0\xaa\b\x10PU\x04\b\xa8*\x02\x04T\x15\x01\x02\xaa\x8a\x00\x01UE\x80\x80\xaa\"@@U\x11 \xa0\xaa\b\x10`\xaaڍ!A\xee\x03\xa6\xaa\xf7)}i&\x86\x04\xb9\v\x98\xaa2:\xa3\xc2\x02\x91\x81\x0eLU\xd9;\xff\xde\u05ef\xe1\x04\xc0U\xc0T\x15'\x00.\x04\xa6\xaa\x14'\x00\xee\x03\xa6\xaa8\x01p!0U\xc5\t\x80\v\x81\xa9*\xc5\t\x80\xfb\x80\xa9\xaa\x9c\x00tw\xd2\xee\xfb\xfc\v\x87W7\x00S\xd5\xd0\x04\x00q\x130Uet\xde\xe8y(Ő\xa0\x81\x06LU\xf95\x00o\xdd\xdf\xfbR\xe7\xde\xd5\xec\xeb\xee\xc1\xb51\x15\xb6\x85\x04U\x11B\xb2NŶ\xab\xfc\xad:\xdf7\x03o\x83\xd1K`\xaa\xca\xefi\xfd\x93\xef^\x9fy[|\xdd\xd8\xf6\x93\xe8\x02\xfbB\x82\xce\x06\x02\xeb·y\x8d\x87\xbf`\xc3\x1c\xdf\xf5\x9ek\x10+`\xaaʸ\xfb\x1d\xbd\xf6\xd7\xd0\u05cdsQO\xda\x18\x12D\xf9}\x83{V\xf5*i\xa0\xc1\xe8\xfb\xb5\"\xc9\x02SUq\x06\xe0J\xfc\xe7m\f\t\xa2֪\x9e\xea\xddF\x11\tLU\xc5\x19\x80\xaf\xba\xef\xc69YegH\x10UT\r\xae\x1f\x975v\x9d\x98\x94^\xae\x1c2t\xe1\xc2!ٍ\x0f\x86ț\xad/\x88]\x0fI\n\x98\xaaҞ?\x02\xb03$\x88*\xaa\xceіn_\xaaU\xb1\xa5\a\x0f\x17\xac\xab\xf5\xfa6\x97\xd5\xd3Á\xad\xa4.\x10\xb8\x10\xbb\x1e\x92\x140U\xb5\xb8\x06\xc0\u0590\xa0\x88\xaaͤ9\xfc\xbd\x91\x1c\xa1t\x1d9.\xdaq\x02\x90\x16`\xaajq\r\x80\xcd!AaU畈\x1f\x0f\xb3auq.[8\x19R\x14UM\v0U\xa5=O\x00\xec\f\t\xa2\x11U'\xc9\x1b\xad\x97O\xa4\xb4>\xe32\x1f_\xe5\x11\x1d\xaa\x9a\x16`\xaaj1\x01\xb03$\x88FT\x9d;\x82{\x1e\x1c>\x87ү=e_\x1f\x19=I\x9e\xf6GU\xd3\x02LU\xad.\x02\xb41$\x88FT\xdd.&\xb7[\xf9\x1c\xe3\x10\xc9'\xc4\xff\x8d|\x1eUM\v0U\xa5\x16\x17\x01\xda\x18\x12t\x9e\u007fZU\x1f\b\xf0\tm\xa5g\xf1\xbb\x8b=\x95l\xe9\x90w\xc7\xf6\xc07\xa23y\x06`\x1f~\xae\xda[`\xaaj\xf9\xaf\x00\xec\v\t\x9a\x13\x9a\xd7\xf2\xd3\a\xc1\x86\x92\xac\x12q^u\xb7\xc6۴i\xc7\xe8\xbd\\\xf1t\xe6\t\x8a\xf4\x0e\x98\xaaZM\x00\xfa;$\xe8Rv\xf5\xa5\xae\xae\xeb\a*\x06\xe3'\xffi\x03\xa6\xaa\xd4\xf2_\x01\xf4oHPS\xae\xac\f\xe6c\xccZڀ\xa9\xaa\xe5\x04\xa0\x9f9䑧\xa9\x8ey\x0e[T\"\t\x03SU\xcb\t@?\x13\x9c\xeb\xabnli\xac\xf6U':\x0e#\x96\xc0T\x95ZN\x00\xfa\x99`SY\xa1VX\xf6.\x9a\x9a>`\xaa\xea\xf4\t\x00\xd2\a\xc0T\xd5\xe9\x13\x00\xa4\x0f\x80\xa9*u\xfa\x04\x00I?0U\xc5\t\x80\v\x81\xa9*N\x00\\\bLU)N\x00\xdc\a\xaa\x8a\x00\x01\xa6\xaa8Wu!0UŹ\xaa\v\x81\xa9*\xc5\t\x80\xfb\x00\xa6\xea\xb6\xce+w;\xef\xdfg_{_\xbf\xc2\u007fܧ\xf7\xef\xde\xed\xbck\xb5\x1e\x02\x1f`\xaa\ue95d\xfc\a{\xe7\xff\x8f\xd238\x01p\x15\xc0T\xedԗ\xae\x9c\x89,#n\x00\x98\xaa\xfc\xa0\xff\xe0\x1fV\xbf\xb0|\xf9\xf3\xbf\\\xbe|\xf9\v\xbf\u007f\xeb6\x9e\ap\t\xd0Te\xef\xf9k\x1e/e̔ߧ\x9e\xc3i\x80K\x00\xa8\xea\v\x93\xf7~u\xe6\xab\xef\xe8\xc53_}\xf5\xfcd\x9c\xb1\xba\x05\x80\xaa\xbeX\xfa\x1d[x\xef\x17\xfc\xe1\x9a\xd23\xddw1\xb6\xc2\x15@Tu\xfa\x17l\xe1_\x1e\xda\xcb\x1e-\x9f~\xc6j\rd\x80\x00RU\xae\xe7\xffx\x88\v\x1b_U\x8c\xad\x18h\x00Tu\xf9\xcc\xdb\u007f\xf8\xd7\x1f\xfe\xb7\xef\xfd\xf3\xbf\xfe\xcf\xfb\xafO\xbd\xf2\xf1\x8b\x9d\a_\x8a\xa9\xb3-\xb6\"\x01\x8e\x97e\x17T\xb6\x14\xa4\xfbO\xc7m\x00T\xf5\xf9\x99ݿ\xfc\xc1\xf7\xbf\xf7\xd0\x0f~\xf0\x8f\x9doM\xbd\U00047677\xfb3\xb6\u009a\xe6\xec\t\x1b\xb7\x96\x10\x82\xf7W\xe9\x1d\x00U}\xb1\xf4ܕ\x83\a\u007f\xf8\xfd\xb5\a\xffLWO\xff\xea\xc6W\xf4\xf6\xb7QU\xf6\xc6V\xf4\xcc՜\x8a{\x94\xde\x19\x85\xaa\xf6\x12\x88\xaaN\xfd\x8c-\xfc\xf0!6K\xed^^j:W\xb57\xb6\xa2g\x16\xfb\xfe\x1f\xffQ\x8f\xaa\xf6\x12\x88\xaa\x96^d\v\xa5\xffą]=\xdd\xecd\x95\x8d\xb1\x15\xcf\x10m\xe3\x82⬲\xb3T\xed\xb7\x96u\xb3\x95neߗ\xd1Q?\x13\x85\x97\xeb\xef)\xb9\x16\xcaj\x86\x1e\x90\xf8\x80T\xf5\x9a\xfe\xf0%ӋVl\x8c\xad\xf8\xcb\xd6L\x92W\xf7\xeb\x9c\nC\xbf\x97\x9e~\x94usk\xf7\x94\xca\xcb\xf7<\xe1\xbb\vR%\xd7BY\xcd\xd0\x03\x12\x1f\x88\xaa>\xfe\x8b\xe5\xcf?\xbf\xe6\xf7\xec\xdb\xf2\xc7\x1f1\xbb\xc0\xda\xd6\xd8\n-\xf7,[-ϸ\xdak\xc5\u2e52\xd7h\xbb2\xe5Pr-\x94\xd5\xd4E$>\x00U\xdd\xf6\U000d93d5J\x1e\xfb\xf9/\xae\x98\xa8jkl\x856\x87\xf2\x1b\xaf\x1bW;\xe2\xb9\xd7\xf1\xda\xf5.\xed\b}\x90\x19\x19U\x95\\\ve5u\x11\x89\x0f4U\x19w\xaf\\\xbc\xf8\xed\xb7\xd7\xee\xb2o\xdf^\x89\xcc\x05\x14l\x8d\xad\x10\xb9\x03B4e\xb5{\x99G\xebɲ\x13\x1e6?\r\xcdU\x1f4\x1br-\x94\xd5\xd4E$>\x00U\xa5\xe2R\xc05?\xbd\xe2\x8c؊\x88h\xeaj\xc5[\xfdS\x8a\x9b\xf84`\xb1Ot\xd3H.\xa9\xb9\x16\xa8j\xd2\x00T\xb5\xbb\xb3\xf3Fg\xe7O'\xef\xed\xbcq\xbf\xd3\xfcB\x15;c+\"\xa2\xa9\xab=]\xa35\x93g\xf8\xec\xf7jN\x05;\x98\v\xfa\x87\x1br-Pդ\x01\xa8\xaa\xe4\xf6\x95\x1e.\xa9\xb6/\xb6\xe2B@\xab\xda\x17<\\\xa5\xf1dJ}5JWf\xe5\x04G\xfbV\xf0\x92\xe6\xacI\xbfk*\xcb\xe43\a=\xd7BY\xcd\xd0\x03\x12\x1f\x98\xaavR\xba\xf6\u007f\x9f\xa1\xf1\xffɊm\xb1\x15\xcf\xf0t\x8a\xd6l\xf6\xfd\x19e5J\x0f\xe5\xd6\xd2U\xd9\xfbE\xe9\xf1\xb2\xac\xfc\x8aV\xbe\xa4\xe7Z(\xab\x19{@\xe2\x02Sջ\x94\xb2\t\x00\x8d\xff\x0fU\xfb9\xb6\x02\xe9\x03`\xaaJ-&\x00\xfd\x1d[\x81\xf4\x010U\xc5\x1b\x01\xb9\x10\x98\xaa⍀\\\bLU)\xde\b\xc8}\xc0T\x15'\x00.\x04\xa6\xaa8\x01p!0U\xa58\x01p\x1f0U\xc5\t\x80\v\x81\xa9*N\x00\\\bLU)N\x00\xdc\a\xaa\x8a\x00\x01\xa6\xaa8Wu!0UŹ\xaa\v\x81\xa9*\xc5\t\x80\xfb\x00\xa6*\xc6V\xb8\x17`\xaabl\x85{\x01\xa6*\xc6V\xb8\x17`\xaabl\x85{\x81\xa6*\xc6V\xb8\x16\x80\xaabl\x85;\x01\xa8*\xc6V\xb8\x13\x88\xaabl\x85+\x01\xa9j_\xc7V`@\x85\x13\x01\xa8j\x8a\xb1\x15I\x90r@\x05҇\x00T5\xb5؊\xe4H-\xa0\x02\xe9K\x00\xaa\x9aZlE\x92\xa4\x12P\x81\xf4)\x10UM)\xb6\"IR\t\xa8@\xfa\x14\x88\xaa\xa6\x14[A\xe9\xe9Y\xf9Z\xc1\x8cohb\xe9\x111\x01\x15\x94\xee,+\xd2\xf2g\f\x13\xf7HM8\xf8\x02I\x17 UM%\xb6\x82\xb6d\x8f[\xb5\xa3\x8e\xf0{\xfd%\x92\x1e\x11\x13PA\x0fdT\xbe\xbdcc>\xe1\xb7XK<\xf8\x02I\x17\x10UM)\xb6\xa2\xa3\xa8\xec\x1e\x1bo\x1b\xaf&\x98\x1e\x11\x1bP\xb1.\x8fK\xba.7\x98l\xf0\x05\x92\x16\x00\xaa\x9aZlE39\x1c~:\xa1\xf4\x88\u0600\x8a\xf3\x85\xc3k6\x1e\x0e\xf2<\xa1\xe4\x82/\x90\xb4\x00MU\x9ajlE=\xd1'\x8e\t\xa5G\x98\x04T\\\xdf0\xbb\x98\xe4\xaf\n&\x1b|\x81\xa4\x05\x80\xaaҔb+vD\ue35ePzDl@š\xc5l\xb5\xeb[}\xeb\x92\r\xbe@\xd2\x02@US\x8b\xad\xb8U\xe0\xe7o\xdd5\xf3\x13K\x8f0\t\xa8\xa8\x13\x93[\xea\xafN6\xf8\x02I\v\x00U\x95$\x1b[A[\xbc\x0foh\xae!\x9biB\xe9\x11\xb1\x01\x15L\xd5\xec\xda\x0f\x9a\xe6\x12>\x17M<\xf8\x02I\x170UM!\xb6\x82ғ\xb3\x87\x0e\x9a(\xaeC\xb1N\x8f0\t\xa8\xa0\xafM\xab+\xd2\n\xfc-\xe2A\xc2\xc1\x17H\xba\x80\xa9j_\xc7V`@\x85\x03\x81\xa9*\xed\xdb\xd8\n\f\xa8p\"0U\xc5\x1b\x01\xb9\x10\x98\xaa⍀\\\bLU)\xde\b\xc8}\xc0T\x15'\x00.\x04\xa6\xaa8\x01p!0U\xa58\x01p\x1f0U\xc5\t\x80\v\x81\xa9*N\x00\\\bLU)N\x00\xdc\aXU\x11\xb7\x01SU6I\xfdxm\xfc\xebU\x91\x81\bLUq\xae\xeaB`\xaaJq\xae\xea>`\xaa\x8a'\xab\\\bLUq\x02\xe0B`\xaaJq\x02\xe0>`\xaa\x8a\x13\x00\x17\x02SU\x9c\x00\xb8\x10\x98\xaaR\x9c\x00\xb8\x0f\x98\xaa\xca\t@w'\xed\xbeϿpxu\x030U\rM\x00\x107\x01SUF獞\x87R\x8c\xad\x18h\xc0T\x95_\x03\xf0\xd6\xfd\xbd/u\xee];\xee\x1e\\\x1bS\xd1/\xb1\x15Gg\xe4\xe7Lk)\x89\xbd[\x06\x92\x06`\xaa\xca\xef\xb2\xfa\x93\xef^\x9fy[|\xdd\xe8\xdf؊\x96\xf0-\x83\x0ei\xe5MoT\x10y\xbb*\xbdռ\x16I\x1a\x98\xaa2\xee~G\xaf\xfd5\xf4u\xe3\\ԓ\xb6\xc6VLx2\xb4P\xe6g\x03\xe6\xac֍\x00\x00\aLIDATy\xb0J\xaa\xaa\xb7\x9a\xd7\"I\x03SUq\x06\xe0J\xfc\xe7m\x8d\xad\xd0\xef\x048|\t\xff~\x944\x19Z\xcdk\x91\xa4\x81\xa9\xaa8\x03\xf0U\xf7\xdd8'\xabl\x8c\xadh\n\xdd\xf3\x97\xdf\x0e\xf8\xc9\x02\xfeW\x11\xdc~\xcb\xd0zsv\xa1VT~\x84\x1ak1\xd7\"i`\xaaJ{\xfe\b\xc0\xc6؊;\xbb\xc5M+\x03'Xc{\x91\xa7\xacn\x0f\xbf\x8b\xab\xda\xfa.\xa9ni,\xf7\xec7\xb6b\xaeE\xd2\xc0T\xd5\xe2\x1a\x00\x9bc+\xf47\xf5\xab+&h$\xb7\x91\x1aZ;\x1ao\xb11\xb4\xa4\xc2؊\xb9\x16I\x03SU\x8bk\x00l\x8e\xadP\xe7\x9f\xf7v\x94\x89\xbba+\xad\x97ו\x8d\xc8!r\x9bz+\xe6Z$\rLUi\xcf\x13\x00\x9bc+\xc2\xfa\xed\xe7\xf3`\x1a\x94\xddGZ\v\x8a\x165\x05\xfcQ\xaab\xaeE\xd2\xc0T\xd5b\x02`sl\x05\xd7o\xf3ה\x16\x88\xc4\n\xbad\x94\xa1\xb5x\"\xff\x1b\x99\xa5\xa8\xca[1\xd7\"i`\xaaju\x11\xa0\xad\xb1\x15~?\xa5\x97xC~\xe1U\xbe\xa6L\\\xd1[\x8b\xf8\xc3\xe0X\xa9\xaaފ\xb9\x16I\x03SUjq\x11\xa0}\xb1\x15\xbc]\xabo\xf2g\xb3?\x88|RP\xdb\xdc\xe4\xf7\x9d4\xb4֑\xd9\xebV\x8cg\x13\x87}j+\xe6Z$\rLU-\xff\x15\x80m\xb1\x15\x8c{5\x83}\xd3\xf6\xb3\x85\t\x9b\x97\x14g\xe7U\x9c4\xb6\x06\xebGkyOn\x1e\xa5\xf9\xd5V̵H\x1a\x98\xaaZM\x000\xb6b\x00\x02SUj\xf9\xaf\x000\xb6b\xc0\x01SU\xcb\t\x002\xf0\x80\xa9\xaa\xe5\x04\x00\x19x\xc0T\x95ZN\x00\x90\x01\aLUq\x02\xe0B`\xaa\x8a\x13\x00\x17\x02SU\x8a\x13\x00\xf7\x01SU\x9c\x00\xb8\x10\x98\xaa\xe2\x04\xc0\x85\xc0T\x95\xe2\x04\xc0}\xa0\xaa\b\x10`\xaa\x8asU\x17\x02SU\x9c\xab\xba\x10\x98\xaaR\x9c\x00\xb8\x0f\x98\xaa\xe2\x04\xc0\x85\xc0T\x15'\x00.\x04\xa6\xaa\x14'\x00\xee\x03\xa6\xaa8\x01p!0U\xc5\t\x80\v\x81\xa9*\xc5\t\x80\xfb\x80\xa9*\xc6V\xb8\x10\x98\xaabl\x85\v\x81\xa9*\xed\xdb\xd8\n\x10\xb8.[\x03\xac\xaa\a\xdf\xeb>\xf8\xdbN\xf9\xf5_\xbf\x8fy:\xb1؊\xe6\f\xe2\xd9G?\xf1\x10\xdfu\xabRA\xbdW\u07b5\xa5\x8a\x10\x92u*ܺ#\xaf\ai\x8exXm\xe4~\u007f=\xd6&E\xdcl\x8d\xf0N\x0e4`\xaa\xca\x06\xd4_L\xbe\xb1\x96}=¾\xae\xbd\xfe\xf3\xe8\x02=\xb6\xa2眈\x8e\xb7Ɏ\a\xb4cԄ\x04\xd3$J4y멳\x81\xc0\xba\xf0\xdd\x06)\xfd ;\xfaV\xac\n]\x9f\x8c-\t\x9c\xd7\x1f\x9a֦\x18f\x11'[#\xbc\x93ɑ\xe2>\xd8\bLU\xad\x88\xc4VX\xe4D\xb4\x93[\x94\xd6\x0e\x89\xa8\xd4#w<\x95\x9e\xf0\xfd\x01\xf7GT\xa5=\x8f\xdf\xfc\x96j\x11\xccjS\r\xb30\xcd\xd6Pw2\tR\xdd\a\xfb\x18\x98\xaaFb+,r\"\xb8\xaa͙-=\xd6Dh!\x87H\xb8VU\xb5g\x8c\xaa\x9a\x91j\x98\x85i\xb6\x86\xba\x93I\x90\xea>\xd8ǀT5\x1c[aȉ\xd0c+\x9e!\x99\rՅ\x83\xcb\xf9\\\x93\xa9ڞ\xbbB\xae\xa5\x04I\xe8\x8bj-\xa5uCiamh\x1baU\xaf\xfb\b\xf1\x88ۤ7\xb2-\xd5\xd1:\"\x82\xab\x94\xce\"\xaaFj\x95\f\f\xf30\vC\x8a\x86\xdez$\x93\x90\xa5\xa7*\x87\xfb\xca\xe4-\xb5L\xb25ԝ\x8c\x04u\xa8\x99\x1d&\xaf\xcd\xf8\x1fʡ\fHUñ\x15\x86\x9c\b=\xb6\x82\aT\f[\xb1bX\xd61\xaeꥒA\xf7\xe4ZJ\x90\x84\xbe\xa8\xd62\xe9f\xd1\xd9a\xef\xf4Q\xf5P \xe0\x15w\x1e\xbe\xb53g\xd9%z\xa96w\xe7-Cgʨ\xaa\xd7*\x19\x18\xe6a\x16\x86\x14\r\xbd\xb5\xa3q\xeb\xb0у\x8a\x16Tf|-z\x89\xcd\xd6PwR\t\xeaP\x16\xcd^\x9ba\x1f\x9cʀTU\x89\xad\x88\xa4GDb+\xa86\xfc&\x1b\xe2\x8a&rU\x9f\x1eU\xb0N\x14(A\x12j\xa6D\xa4\x96\x06\xb3\xebi}vh\xb2\xa9N\x00|\xa1\x9bd\xcf\xe3\xf3\xbdʟ\x19;\x8b\x9a\x00\x84j\x95\f\x8c8a\x16\x91\x14\rcH\x06\xf1ߤ\xc1\x9b\xb2>6[C\xd9I\xe5\x15+\x8bq^\x1bN\x00\xfa\a=\xb6B\xf9\r(\xb1\x15T\x1et\xad#W\x99\xaa\xbe㛇\x88_\xbc\x12$\xa1fJDj\xe9\x11\xb2\xbbc79\"\xfb0S\xb5\x85\xbd\x1fwd\xb5\x18;3WU\xc9\xc0\x88\x13f\x11I\xd10\x86dh_G:\x8b\xcd\xd6PvRy\xc5\xcab\x9c׆\xaa\xf6\x0f\xfb\"\x1a\xe9\xbf\x01%\xb6B\xdeJ\x9d\x06\xc8!\xa6\xeaV\xdaU,R\xfc\x94 \t5S\"RK\x1bDc\xe8\x04\x91\x99\xaa]\xf9M\xb4)?h\xec\xcc\\U%\x03#N\x98E\xe4~\xefƐ\fu>i\x92\xad\x11\xd9I\xe5\x15+\x8bq^\x1b\xaa\xda?Db+\"9\x11Jl\x05\xd5\xe6\xf3\xef\x1b\xc9My\xb2\xaa\xd9\xcbOV)A\x12j\xa6D\xa4\x96\xce\x1a\xb7\u007f\xff\xfeq\xb3d\x1ff\xaaҚ\nZ!\xb2+\xd4\x1e\xa4\xaa\xb7\x96]Uk\x95\f\x8c8a\x16\x11U\x8d!\x19\xb3h\x84\xd8l\re'\x95W\xac,\xc6ym\x91}p,\x03RU%\xb6BωPb+\xa8\x96\xcf~\xc3wF\xf8C\xe7U\x83\x93x\x82\x95\x12$\xa1fJDji\xe1B\xf6mA\xa1\xec\xd8T\xd5=\xde\v^q\xa0\xa3\xf6 U=Lv\xaa\xb5J\x06F\x9c0\x8b\x88\xaa\x86\x88\vu\xf43\xc9\xd6PvRy\xc5\xcab\x9c\xd7\x16\xd9\a\xc720U\x8d\xc4VDr\"\x94\xd8\n\x8d\x8ck\xdc<:\xf7$\xedh\xe2\x9fVѷ3\xb6\xdf3\x04I(\x8b\x91\xdaf\xb2\xe4\x0e\xbd\xf3+\xd2|\x8f\x9e\xe7\x9fV\xd5\a\x02l\x10z\xf0\t;\xaa\xaf\n\xec\x14\xf3\xdd`aY\xa1\xfc#\xd1{\xe8\xda3\xb6\x84\x1d[\a6\x90\x80Z\xabf`\x98\x85Y\x18R4\x94\xceđzx&\x1e\x9b\xad\xa1\xee\xa4\xfa\x8a\x95E\xb3\xd7f\xd8\a\xa720U\x8d\xc4V(9\x11\x91\xd8\nm\xe1ܜ\xc2\xca\v|\x88\xe1\xd7\x00\xd0i$\x83\x0f\x91J\x90DdQ\xafݑ\xc1O\x986\x11\x92\xb1\x83\xce\tM\xf8\xd8\x11\xff\x01\x8f\\\x94\xd1\x16\xf5Z}h\x0f\xc2=\x1c\r=O|'\xd4ZC\x06\x86I\x98\x851E#\xdczDv\x10\x1aKM\xb25ԝT_\xb1\xbah\xf2ڌ\xfb\xe0P\x06\xa8\xaa=\xc7VD\xa6\xb2\xd6$Sk/\xbd\xcf\xd6p\xeek3c\x80\xaa\xdaslE2\xbf\xa2djm%\r\xd9\x1a\x8e}m\xa6\fTU{$\x99_Q2\xb5Ѐ\xf5\xda\\\xa8\xea7\xe2\x88ŪJ\x92L-4\xa0\xbd6\x17\xaa*\x8eX\xdaiB$S\v\rh\xafͅ\xaa\"0AU\x11 \xa0\xaa\b\x10PU\x04\b\xa8*\x02\x04T\x15\x01\x02\xaa\x8a\x00\x01UE\x80\x80\xaa\"@@U\x11 \xa0\xaa\b\x10PU\x04\b\xa8*\x02\x04T\x15\x01\x02\xaa\x8a\x00\x01UE\x80\x80\xaa\"@@U\x11 \xa0\xaa\b\x10PU\x04\b\xa8*\x02\x04T\x15\x01\xc2\xff\amu\xa3\x1c\xa2\xebff\x00\x00\x00\x00IEND\xaeB`\x82",
+
+	"analysis/ipcg-pkg.png": "\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x02\xf0\x00\x00\x03\xc6\b\x03\x00\x00\x00\xb2,^L\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x02\xfdPLTE\x02\x04\x00\t\v\a\r\x0f\f\x10\x12\x0f\x13\x15\x12\x1b\x1d\x1a !\x1f!#!$%#&(&+-*/1.2416859:8<=;>@=AB@DFCFHEJKIOQNQSPTVSWYV,`\xae7]\xad8^\xae[]Z8a\xaa:b\xab;b\xac_`^<c\xad=d\xae?e\xaf@g\xb1Bh\xb3egdDi\xb4Ck\xafFk\xb6Lj\xafhjgNk\xb1Fn\xb2Ho\xb4Pm\xb2kmjIp\xb5Kr\xb6nomMs\xb8Nt\xb9Ou\xbaPv\xbbrtqXv\xb6Yx\xb8vwuZy\xb9[z\xbaxyw]{\xbbV~\xbd_}\xbeY\x80\xbf`\x81\xbbb\x80\xc0[\x82\xc1~\x80}b\x83\xbdc\x84\xbe\x81\x83\x80e\x85\xc0g\x87\u0084\x86\x83\x85\x87\x84i\x89Æ\x88\x85j\x8aŇ\x89\x86\x88\x8a\x87q\x8c\xc1\x89\x8b\x88s\x8eË\x8d\x8at\x8f\xc4v\x90ō\x8f\x8cw\x91Ǐ\x91\x8eq\x94\xc9y\x93ɑ\x93\x90z\x94ʀ\x94Ł\x95Ɠ\x95\x92{\x98ǂ\x96ǃ\x98ɖ\x98\x95\u007f\x9cˆ\x9a˘\x9a\x97\x80\x9d͈\x9d\u0382\x9fϜ\x9e\x9a\x88\xa0˄\xa1ў\xa0\x9d\x8a\xa2̋\xa3Ρ\xa3\xa0\x8d\xa5ώ\xa6я\xa7Ҥ\xa6\xa3\x90\xa8ӑ\xa9ԧ\xa9\xa5\x92\xabՔ\xac֩\xab\xa8\x98\xacѪ\xac\xa9\x9a\xadӛ\xafԭ\xaf\xab\xae\xb0\xad\x9d\xb1֘\xb4ذ\xb2\xaf\x9f\xb3ء\xb4ڲ\xb4\xb1\xb3\xb5\xb2\xa2\xb6ܣ\xb7ݝ\xb9ݵ\xb7\xb4\xa9\xb8ٶ\xb8\xb5\xa3\xbb٫\xbaڸ\xba\xb7\xac\xbbۦ\xbdܹ\xbb\xb8\xad\xbcܮ\xbdݯ\xbeߩ\xc1\u07fd\xbf\xbb\xb0\xc0\xe0\xab\xc2\xe1\xb2\xc1\xe2\xbf\xc1\xbe\xad\xc4\xe3\xb7\xc2\xdd\xc1ÿ\xb2\xc5\xde\xc2\xc4\xc1\xb9\xc4\xdf\xc3\xc5º\xc5\xe0\xb4\xc7\xe0\xbb\xc7\xe2\xb6\xc9\xe3\xbc\xc8\xe3\xc6\xc9ſ\xca\xe5\xb9\xcd\xe6\xc9\xcc\xc8\xc1\xcc\xe7\xc2\xcd\xe9\xbc\xcf\xe9\xbf\xcf\xe2\xcd\xcf\xcc\xc7\xcf\xe4\xc8\xd0\xe6\xc2\xd2\xe6\xca\xd1\xe7\xcb\xd3\xe9\xc6\xd5\xe9\xd2\xd4\xd1\xce\xd6\xeb\xc9\xd9\xed\xd5\xd8\xd4\xd0\xd8\xed\xcb\xdb\xee\xd4\xd9\xe9\xd8\xda\xd6\xcc\xdc\xf0\xd6\xda\xea\xd7\xdb\xeb\xda\xdc\xd9\xd1\xdd\xeb\xd8\xdc\xec\xd9\xdd\xed\xdc\xdf\xdb\xd4\xe0\xee\xdb\xdf\xef\xde\xe0\xdd\xdd\xe1\xf1\xe0\xe2\xdf\xd7\xe3\xf1\xd9\xe5\xf4\xdf\xe4\xf4\xe3\xe5\xe2\xde\xe6\xef\xe5\xe7\xe4\xdc\xe8\xf6\xdd\xe9\xf7\xe6\xe7\xf1\xe0\xe9\xf1\xe7\xe9\xe6\xe8\xea\xe7\xe2\xeb\xf3\xe9\xeb\xe8\xe3\xec\xf4\xeb\xed\xea\xe5\xee\xf6\xec\xed\xf7\xe7\xef\xf8\xed\xef\xeb\xe8\xf0\xf9\xee\xf0\xed\xf0\xf0\xfb\xf0\xf2\xef\xee\xf3\xf6\xf1\xf3\xf0\xf4\xf2\xf6\xf2\xf4\xf1\xef\xf5\xf7\xf0\xf6\xf8\xf4\xf6\xf3\xf2\xf7\xf9\xf3\xf8\xfb\xf6\xf8\xf4\xf7\xf9\xf6\xf5\xfa\xfd\xf8\xfa\xf7\xf6\xfb\xfe\xf9\xfb\xf8\xfa\xfc\xf9\xfd\xfb\xff\xf7\xfd\xff\xfb\xfd\xfa\xf8\xfe\xff\xf9\xff\xff\xfc\xff\xfb\xfe\xff\xfc\x9fIc\x17\x00\x00 \x00IDATx^\xed\xbd\vlT\xe7\x9d\xff\x9dn\xbb\u007f\x92\xf4\xbe\xffM[\x1e\a\x9d\xe0\x91c\xaf\x16\xd9kհuJ\x9b8\xf0&\u0080\x18\xe3\x80l(\xb7֊X\x87\xb0\x15\x97\x10\x93FXd^BH߄\x05\x8aCK\x92%\x1b\xe3\xd5\xca.V\xc1ZHF@P$\xccE\xa4)I\x1b\xc0\t!\\\x82\x13\b66c\xec\x91~z\xcfs\xce\\\xce̜\xb9ٞ\xe7\xfc\xec\xf9~\x82f\x9e9\xf3\x9ccW\xfd\xcc\xf1\xf7\x9c\x999\xdf;\b\x80,\xe2\x8ed\x13\x00\x18M@x\x90U@x\x90U@x\x90U@x\x90U@x\x90U@x\x90U@x\x90U@x\x90U@x\x90U@x\x90U$\x12\xbe\x03\x80\xd1\x06\x84\aY\x05\x84\aY\x05\x84\aY\x05\x84\aY\x05\x84\aY\x05\x84\aY\x05\x84\aY\x05\x84\aYEj\xc2\xe7\n!\xfe\xdfx\x9b\xf8\xf3\x9f\xe2=\x93\x16%\xfa\xcf\xf8\xafd\x93\"\b\xae\x91\xfe\x9aI\x90\x1b\xfc\xefd\x93\xc0\x88d\xc8\u009f\xd98\xe1i\xfbg\xd2$}m!<H\x9b\xa1\n\xff\xa72! <\x181\fU\xf89\x02\u0083\x11\x04\x84\xb7\x01\u008f^ \xbc\rq\x84?\xfa\xefQ\xe0E1\xf2HO\xf8B!r;\xfeZ\xffP^\xee\x03\xab\xfe\xac?\xae\x15\x01^\x95\xb3\x8e\xfe\xfb\x03\xae\xf1\xc5U\x01\xf7\xfe\xaa/\xfeYG}\xb1V0\xe7L̊:g\xfe\xc3]8>\xc75\xf1\x17\u007f4\x1f\xc7j\xfb\xd7\x17\xdd\x05Zn\xc9/\xfe\xa7#\xf1\x1a\xb1k\x1e\xae-\x19\x9f_\xfej\xc73\xfa3\x9e\xa8_%f3\x9a\x10\x85\x1dG\x97M\xd4\xd7\xf8}x\xc3\xff\xfd7\xcfC\xae\xdc\xc9O\xbfo\xd9\xec\x83\"\x02\xedp\a\x18i\xa4/\xfc\xe1\u007f5\xff\xef.>\x1c%\xfc+\xae\xc0\x03\xb7\xa1\xb4a\xd9*\xf9\xb8<vŎ\x8e??\x1c\x12g\x85\xf13b\xb4}\xeb_\x83\x13~\xf5\xb7\x84kĬ\xf9jn`\xbd:\x11\x16>\xf8\xab\xc4lF\n\xff?\xf9撪\xbf\x067\xbc\xad\xcc\\2\xe9\x84e\xbb\"\x82E\x1d`đ\xb6\xf0Zq\xf0\xffow\xa4\xf0\xaf\x8e\r\x99\xf0\xa8\xbe\x1f5,\xcb3\x96=\x1f\xbbbGG\x95\b\xf3\x9frA\xb4\xb6\x87\xf3\xc3\x13j\x13\xae\x11\xbd\xe6\x1f\xb5\xe0\xb4\t\"$|\xe8W\x89ٌ>;//\xb8dAp\xc3\xc1W\xaf\x98g\xd9\xf2\xcf,\xebb\a?\"I[x}w\xe8\xf9\xe3\x169\x18\xf7玷^\x9d\xaa\x0f~\xf1\xea\xab':\xfe,\xfd|h\xdb\x1f\u007f#\xdd\xd1%3,\xd3'=T\x92s\"vŎ\xff\x95\xf7\xab\xff\xf8\xa7\x8dr\xb5_ɟ\x11\xad\xedt\xfd\xf1\xf8e\xafnyT\xbf\xcfy+\xd1\x1a\xd1k> \xd7\\\xf5\xc7\xff2\xd5\xf6D\xfe*\xb1\x9b1^\x1e\xf9O\xbf\xea1^\x91\xc1\r\x8a\xe2\x8d\u007f\xfa\xddD\xb9%K\xa8\x89\xd8\xc5\xff\xa2\x03\x8c<\xd2\x17>O\xee\xd8\xfe(\xff\x1f\x97ﰆ\x0eZ\xeb\xf5\xc1\x032\x10\xfcQߕN\xec\bX\x96\xab\xcf\xd9k\xb7\xe2\x9f~55\xcfH\x14\x1ea\x04\x8d\x18m\xdf\n\xda\xf7\xb7\x87\xf4\xc1\xb2DkD\xad\xf9?rM#\x8d\xd7ȑ'\xf2W\x89\u074c\x16\xfc\xddNH\xe3݁\r\xe6\x1d\r\xfe\x12\xd67\x92-\xbbx\xec\xe0G$\xe9\v\xff\xefƒ\xbc\x80d!\xe1˅\x11\x18t\xa4\xa0o\x05,\xfbU`\x03\xb1+\xea\xc8\xe0\xd3\xf1\xbc\xfe\xb8L\x0e\xa2\xb4\x95Ǜ\x0f\x19\xa3\xffz\xea\xf7A\xb7\xec\u05c8Zs\xb5\xfep\xb21\xfa\xf3x\x11\x16>\xf8\xab\xc4lF\n\xff\x94\xb1|\xa3>r\x9d17h\xa4\xa8\x8e\t\x91\x9b\xee\xf8\xbd\b\x81\x04?\"I_\xf8\xff0\x96H'\xe4\x91jHx)re\xadD\xe6\x80\xdf\x05,\xfb]`\x03\xb1+\xea\xbc\xff\xdf\xf5s\xfeI\xcez(\xf8\x84ŭ\xaa\x90t\x16\xec\u05c8Z\xb32\xbc\xa6<>\xf5D\xfd*1\x9b\x91\u009b'l\x0e\xcbe\x87\xcd\r\x9a\xbf\xed\xc4\xf0ok2Y\x04\x18\x87\x1d\xfc\x88$}\xe1M\xb5\xfeUD\n\xff7\x11A}\xc0\xb2\xc0\x99?\x9b\x15;~W\x1e:\xb6|X>\x8e\xd2V\xfe\xc5X\xd5\x11A\xbc5l\xd6\f\xbc5\xe0\x16aჿJ\xccf\xe4#\xd3^\xe3\u007fğ\xac/\xca\aD\x94\xf0\xbf\x0f\xae\xfa\x8b\x0e0\x12I_x\xf3ݖ\xa0\tA\xe1\xff*\"x:\xb0\xe4\xad\xc0\x06bV<Si\xcc+\xf9\x85<\xd1\x13O\xf8\u007f\xef\xb0\x10\u007f\x8d\xa85\xe5Q\xeejsh\x15\xfe\xadx\x9b\xd1BO\x1a\xf3\xf6\x9a\x1b\x8c\xfc\x9f\x19&\xb0\x8b\x1f\xf7V\a\x18\x89\f\x97\xf0Ɣ\x88w\x1e\r{\x82\u007f\xf7cV\x94Ǹ\xf9\x1bOtt\xfc\xa7>\xf8\u007f\xe4\x13Q\xda\xce\x13\xc1\xbd\xe8\xfbo\x19\xa7\xe1\xe3\xafa\x13i\x02\x81]\x1ecz\"\u007f\x95\xd8\xcdH\xe1\x8d\xf3\x93\x11\x91&\x9e\xf0\xbf\x17\x06\v:\xc0\x88d8\x847\x8e\xf8\xe4\xa1j\xbd\xf1\xd4\u007f\x9bj%\x16^\xaah\xc4\xe4\xff\xd0\a\x8fʁ\xcdAk\xa1qt\xf9[1\xfe\x81\xdaDkD\xad\xb9J\u007fXl\xacyX\x9e{\x8f\x12>v3Rx\xf3\x05\xf2\xa2>\xca\xefH,\xbc\xb9\x8b\xc7\x0e~\xa42T\xe1\xe7\x89@\xf2\x90\xe7F\xfeI\xbe\xc5\xfaG!\\\x0f\x1f\rXv4\xb0\x81\x98\x15\xf3\x83&UF\xeb\x1b\xe0-\xb9\xfao\xf4\xc1_'\x9bB\xc6_#jM\xe3\xcc\xe73\xfa\xe0}\x19\x8bB\xc2\a~\x95\xd8\xcdH\xe15\x99\xf0\xff,7TՑD\xf8W\xe4\xc6~\xd1\x01F&C\x15\xfeW\xfa}ު_\xfdw\xc7Q9g\xf2\u007f\x1e\xfe}a@\xa4\xc4\xc2˻\u007f}\xab\xe3\xf0/\xe4,\xbb\xb34\xc6\x1bO\xc2\xedyZ\xce\x14\xff\x9bh\x8d\xe85\x8d\x8f\xbc\xcc\xd9Xo~4!J\xf8\xd8\xcd\x18\x87\xb0\xe3\x97m\xab\x97\xdb1\x8em\x13\n\u007f\xe6\x01\xf3\x8d00\"\x19\xaa\xf0\x1e\x11\xb4j\xa3\b\xe1\x92>$\x16\xfe\x19c\xe2xs~\xb1|\"Z[\xebG\v\x96u$Z#z\xcd?\x05&\x89q\x05\"F\xf8\xd8\xcdH\xe1s\x83?\xe9W\xc1\r\xc7\x15^\xa6\xf8_t\x80\x11\xcaP\x85?a~\nE\x1a\xe9\tZS`\x9c\x01L,\xfc_\xa7\x9bssV\xffk`Z\xb4\xb6\x1doM\nlO\xd4\x1a\x9f͉\xbbF̚\xaf\x98\xbf\x89\xf6[\xb9\xca\xf3\x91\xbfJ\xecf\xa4\U0002f598K\x17\x19\xc7lj\x85?\xf3\x00v\xf0#\x97\xa1\n\xdf\xf1VU\xbe\xf6O\xe5\xc6\xf0\xf0\x8a\x9f\xe5\x8f\xcb{\xe8i\xf3\U000ff245\xef8\xe3yȥ\x15\xff\xea-\xe3\x03hu\x1d6\xdav\xfcu\xe3\xf4\u007f\xd2r'\xfe*\xf0\xde~\xdc5b\xd7|\xebW\xc5\xda?\xcd\xfb_#\x16\xfd\u007fQ\xbfJ\xccf\x8cӒ\u007f\xfe\xf7\x12-\u007fz\xc0\xed\xc4\xc2w\xfc\xce\xfay20\xb2HM\xf8\x11\xc5\xdf\xfe\x16\x1a\xcawZ\xff3\xc1T\x83\xf0y\xf8\x149s\xb4\x03\x8cTF\xa1\xf0\u007f\xcc)x\xa8r\x9b\x1c\xfdY此\x1f\x01H[x0\x82\x19\x85\u009f\xc8\x11\xf2\xbd\xa5?\xfd\xe9?\xe4{\x03\x0f$\x9b\x0e\u1ccaQ(\xbc\xf1\xde@\x88\xdf'\x9b\r\u1cca\xd1(\xfc\x9f\xcbC\xba\x8f\xfbM\xb2\xc9\x10>\xbb\x18\x8d\xc2wt\xbc\xfa\x8b\a\xf24-\xff\xa1e\xa9\x88\f\u1cc9\xd1)<\x00q\x80\xf0 \xab\x80\xf0 \xab\x80\xf0 \xab\x80\xf0 \xabH$<\x00\xa3\x0e\b\x0f\xb2\n\b\x0f\xb2\n\b\x0f\xb2\n\b\x0f\xb2\n\b\x0f\xb2\n\b\x0f\xb2\n\b\x0f\xb2\n\b\x0f\xb2\n\b\x0f\xb2\n\b\x0f\xb2\n\b\x0f\xb2\n\b\x0f\xb2\n\b\x0f\xb2\n\b\x0f\xb2\n\b\x0f\xb2\n\b\x0f\xb2\n\b\x0f\xb2\n\b\x0f\xb2\n\b\x0f\xb2\n\b\x0f\xb2\n\b\x0f\xb2\n\b\x0f\xb2\n\b\x0f\xb2\n\b\x0f\xb2\n\b\x0f\xb2\n\b\x0f\xb2\n\b\x0f\xb2\n\b\x0f\xb2\n\b\x0f\xb2\n5\xc2_\xbe\xfcygw\xe4\xa2\xee\xce\xcb_}9`?\x1d\x80L\xa1F\xf80\a\xb7w\x124\a\x8e\xa1T\xf8>\xa2Ms?\x96w\x008\x83R\xe1I&\x19\xec߁\x83(\x14\xbe\xaf\xcf\xd7\xd7w|ϗ\xfa\xdd\x00\xac\aΠPx\x83\x97\x1e\xbb\x98l\n\x00\x99C\xb5\xf0\x03\x9d\xc9f\x00\x90A\x14\t\xafG\x98\xd3{\xfe\xb0}\xeb\xe67\x9b\xb7oݺ\xbdy\xdf\xcddk\x00\x90\t\x14\t\xdfG\xb4}\xfe\xac\x99\xd3fL\x93̜_q\x11\xe7j\x80\x13\xa8\x13~ô\x83\xa7\xdf;\xfd\x9e\xce\xe9\xd3k\xa6\x9d\x83\xf0\xc0\t\x14\n?\xbb7\xf4pk\xc59\xf2\x11\x9c\a\xcaQ(\xfc̳\xa1G\x1bf\x9eK4\x1b\x80L\xa1P\xf8\x19!\xe1i}X~\x00T\xa2N\xf8\xf5s\xbb\xf7\xfc\xf8\xc7?\xd1\xff\xab\xe8{}\xe6\xe7G\xb6\xfb\x8eoU\U0007969f\x8e\x193\xe6\xee\xe3\xc9f\x81,A\x9d\xf0\xeb\xaai\xcd\u05fe\xf6w\xfa\u007f\xdf\xf25\xcf\xe8~cn\xf7\xeeY6\x87\xae\x9d\t\xc2\xce\xee\xb7\xe3?\x17\x97\x0f\x9b\x9bW\x8e\xd9c\f\xcf\xe1M\x80\xacG\x9d\xf0\x1bf_\xbeؼgߞ}\xcd\ai\U000cc2dd\xa7\a:?\xf4E\xcf\x1bX\xfb\xcd\xfb\xec\xd67\xf9\xc1\x8f\xe3?\x97\x88}\x01\xe1\xef\xfb\xe6\xda\xcc\xffE\x01\xacQ'\xfc\v3N\a\x1f\r\xc4\xcb\xf0\a\u007f0\xe6\xfe\x0fm\x9f1\xb8\xe7_\xe2?\x97\x88\xa0\xf0g\xef\x1f\U000c30c9\xa7\x82Q\x8e:\xe17̺h&v\xfdfӌs\xd4\x1bsZ\xb2sƝ\xdf\xddn\x0e\xd7\xfd\xf0\xee\u007f\x98\xd1Mt\xe4\xce1c\xee\xa7\xef\x8d\x19\xf3\xcdޭcL\ue258pP\x9f0\xf7\xf8O\xbew\xf7}\xbeG\xc6ܹv\xda?\xdc}\x9f|\xc5t\xfe\xcbw\xee\xfa\xee\xfd\a\x03\x1b\x0e\nO\xb4\xfd\xbbwNC\xae\xc9f\x14\n?;\xfc\x9d\xa7\xcd\x156\xe9}\xf3w\xee\x9c\xfd\x959\xfc\xf9\x9d\x8fl_\xf9\xed{\xfa\xa8o\xcf\xc2;\xf7к;\xd7\x1d\xa4\xaf\x9a\x9b\xff\xe1G\xcd\xcd\xcd\xc7#&\xdcܰ\xfe{\xff\xf0\xcd\xefM\xfbɝ\xa7\x8f\xac\xbfs̷\x17>\xf9\xcd\u007f֟\xdf>\xe6\xe7\xbb7\xdc\u007f\xe7>ssa\xe1\xe9\xab\xd9w~{S\xf4O\x06كB\xe1\xab\xd7m~a\x93\xce\v\x9b6\xff\xf2\x91د\x81<2枃\x81\xe1\xf61ϒ\xd4\xf49\xf9\xe0\xa7?\xbc\xf8\xbd\xc7\xcd\xe5\xa1H\x131\xe1\x9e1\xf7\xe9;m\xb9\u07fe\xeb\x9b\xfa\xde\xfd'\xdf\xd6G\xdd\x1b\xbe\x94\xcf\xfc\xb39\xdd\"\xbc\xfe7\xe1\x9e1\xd3\bd+\xea\x84o~\xfc\xb1\x8a\x19&\x15\x8f?\xf9y\x8c\xf0\xcf\xde\xf5\xadu\x81\u13ff\xef\x93|\xf7\xa7\xf2\xc1\xcd{\xbe}\u007f`yH\xf8\x88\t\xf7\xdc\x15<8\xb8K>\x9e\u007f\x97\x1c^\\s\xdf\xf7\xbf\x19\x88?\x91¯\xfb\xd6\xddk\td+\x8a\x84\xd7\xe9\xbex6\xc4\xc5\xcb6gK\x8e\xdf7\xe6\x87\a\x8d\xd1=\x81\xb8n\xee\xa07\x8di\x0e\xcc\b\t\x1f1\xe1\x9e\x1f\x04\xb7p\xd7|\xfdf\xa1\x14~߷\xbf;\xeb\xa5\xe6{c\x85?\xf2\xc31\xf7\x87\x0e\x9eA\xf6\xa1N\xf8\x14x\xe9;wΒQ\xe4'\xdf\u007f\xdb\xc0\xf8\xae\xc8\xd9\xef\xcc\xfd\xdee\xf3yC\xf8gOGM\b\x9f\xbb\xb9k!\x05\x84\xff\xbf?\x94\a\f\xff\x12-\xbc\x9e\xe0\x83\x87\xc5 ;Q(\xfc\xc0@_\x90\x818\x1f\x1b\xeb\x9cq\xe7w^'z}\xcc\x06\xf9h\xae\x8c\xee\xbe\x1fV\xd3\xcf\xef3\xe7\xdf{/\xd1\xc7\xf29\xeb\x04[\xe1\xbf+\x97\xf5\xdd\x13%\xfc\x9b\u07fds\xd6W\x04\xb2\x19\x85§\xc4\xc1\x1fIUg\xdf\xf9\xe3\x176\xfft\xccz\xba\xd9\xfcȷ?\xa4\xf7\xbe9\xadY~\xd4r\xfe]On\xbe\xef\xee\xb3\xd6\t\xbe=ƹ\x9b\xf7\xf4eg\x9b\xef\xfc\xe9\x1ez\xfb\xa7w6\x9f\xa5\x85c\xfee\xcd\xe3\xf7\x8c\xf9ֿ\xed\xd1\x177\xaf\x1c\xf3\xeb\xe6f\xfd\x0fÿ\xfc\xe8`\xc2\x1f\x0eF?܄\x0f\xf0\xfa\xbd\xdf\xfa\xe6\x8f\xfe w\xe5c\xc6L\xa3Gƌ\xb9s\xb7\xbe\xb4\xf7\x91o\xdd\xfd\xa3}\x11\x13\xe4y\xf81\xf2\\\xbd<ͣO;r\xb7~\xfb\b\xf5\xfd\xfa\x1f\xee\xfa\xf6\x8f\x9f\xfd\xfe]\xf7\x1a\x9f\xa5\x91\f\xf2]Z0\xba`*<\x00\x99\x01\u0083\xac\x02\u0083\xac\x02\u0083\xac\x02\u0083\xac\x02\u0083\xac\x02\u0083\xac\x02\u0083\xac\x02\u0083\xac\x02\u0083\xac\x02\u0083\xac\x02\u0083\xac\x02\u0083\xac\x82\x8b\xf0\xbe\xa8VK\x002\x02\v\xe1\a\x88\x8e\xbc\xf1\xa5\x82\xcb\ue06c\x87\x85\xf0}D\x9b\xabQg\t\x14\xc0BxB\xa4\x01\x8apV\xf8=\xbe\xce^\x9fQgy\xf0\xcdNy\xd7G}\xbd\xbd\xbeps\x02\x00Ë\xb3\xc2\x1f!\xe3r\xaa\xb2\xa1{6Jp\x80\x02\x9c\x15>|\xf5\xe0\xces1W\x12\x06`\xf8qVxyb\xe6\xf8\xeeM\x1b\x9e[\xff\xec\xda\xf5ϭ\xdf\xf0zs7\xceՀL\xe2\xb0\xf0z\x8aٺp\xf6c\xb3fUϟ=k\xd6c\xd53Pg\t2\x8a\xf3\xc2o\x98v\xe4\xfc\xd9\xf37\xe9\xf2\xd9\xf3\xe7\x9fE\x9d%\xc8,\f\x84\xaf\x90\xad\xdc\xfbVʇ[+\xce\r\xc4^7\x1e\x80a\xc3y\xe1_\x98)\x1b\f~t\xc7A\xfd\xd1s\xa8\xb3\x04\x99\xc5y\xe1\xcd\xfe\xd6\xfb\uf437\xa8\xb3\x04\x19\xc6y\xe1\xd7\xcf\xed\xde}\u07fdw\u007f\xed\a\xf7\xfd\xbc\xef\x8d\x19\x9d\a7\xf8\x8eo\x8e\x9a\xb5e\xfco\xe5\xddr\x91\xd3d\xb3\r\x00R\xc7y\xe1\xd7U\x0f\xac\xfd\xc6\xd7\xff\xee\x8eo|\xe3;\xb2\xcerwu\xf7\x9e_F\xcd*\xd3\xca\xe4\xdd\x05\xaf\xe6\xb1\xd9\x06\x00\xa9\xe3\xbc\xf0\x1b*.v\x1e?~\xef\u05f7\x1f\u007f\x8f^\x9ay\xbe\xfb<u_\x8e\x9cԕS\x93\xd3e\x8c <\x18\"\xce\vo\xd6Y\xde+3\xfc\xc0\xfaYv\x19\xde+\x8e\x89\x03\xc6\b\u0083!\xe2\xbc\xf0\x1bf\xc9\x1d\xfa\xac\xefI\xed7ʹ;-\xe9)\xa6b\xd3tm\xc5\x13\xc5\xf9Ug\xe4\xd0[Y\xa2\x15\xcd)\xf1\x13\x00i\xc0@\xf8\x8a/C\x0fm\xeb,ɽ\x88\x16\xbb\x8d\x91&\xa645\x96\xb9N\x11\x1d\x1d\xbb\xb4e\xff\xce\"q;f6\x00\t` \xfc\xfc5\xeb\x9f]\xb7\xf5\xf5\xe7\x9e]\xb7~\xbeM\x9d%\xf9][\xe8e\x97\xb1+\xd7&\xf7\x10\xf5\x94\x96\x135\x14H\xd5\x1b\xf2\xb1\x87\ai\xe1\xbc\xf0{\x9e\xac\x9e;{vEE\xc5\xec\xd9s\x9f\\\xd9\x19+\xfcIq\xa8\xe7\x908)\x87\xda3\xf2v\x87\xb8F\x9f\x15O\\\xb1\xf3\x84\xbf?z2\x00\tqXx\x9d\xde\xce\xcb:_\xf5~\xae\xdfv\xdaU\x8em\x13\x92mrh\x1e\xb4\xea\a\xb1D\xd7w,\x9e,\x8a6b\x0f\x0f\xd2\xc2y\xe1\xc9\xf8\x90\xf0\xe6\xc7;\xe3}0xє\xf6\xf6\xf6)\x8b\xe4P[%ow\x8a\x1b\xd4^\xa7\xab~\xbd1\xb7\xc1~\x1d\x00\xecq^\xf8\x01\x9f\xaf\xdb\xe7{|\xda\x11_w\x9f\xcf\xeeccū\xf5\x9bU\xc5r\xa8\x15\xdf\"\xea\u007fP?\x82\xf5\x886\xb9\xc0\xbd\xccf\x05\x00\xe2\xe2\xbc\xf0&ݝq\xf6\xef=m\xa2\xbe\x8b\xba~#\xdanɳ4\x95\x87\xf7\x97\xe7\u007f$\x85wշ\xb6\xd4\x06\xce\xcf\x03\x90\",\x84\xf7\x11m\u007f\xf2,\xd9~\xc9o\xffX!\x9a\xa8E\x88\xb1\xfb\x89\x1e\xf4,\xce+\xae\xb9\xa4/\xde5\xddS\xa2\x15\xba\xe1;H\x0f\x16\xc2\xf7\x12鑆p\xb1\x02\x90qX\bO\t\"\r\x00\xc3\t\v\xe1q\xa9=\xa0\n\x16\xc2\xe3R{@\x15,\x84'\\j\x0f(\x82\x85\xf0\x884@\x15,\x84G\xa4\x01\xaa`!<!\xd2\x00E\xb0\x10\x1e\x91\x06\xa8\x82\x85\xf0\x884@\x15,\x84'D\x1a\xa0\b\b\x0f\xb2\n\x16\xc2#\xc3\x03U\xb0\x10\x1e\x19\x1e\xa8\x82\x85\xf0\x84H\x03\x14\xe1\xac\xf0(5\x03\x8aqVx\x94\x9a\x01\xc58+<J̀b\x9c\x15\x1e\xa5f@1\x0e\v\x8fR3\xa0\x16\xe7\x85G\xa9\x19P\b\x03\xe1Qj\x06\xd4\xe1\xbc\xf0(5\x03\nq^x\x94\x9a\x01\x858/|\x92R\xb3F\xe3R\xaa\x13\xe6}\x12o\x13\x00\xa4\x81\xf3\xc2')5\xebj\x15\xbf\xf1zw\x95M\xf8\"\xeeF\x00H\x19\xe7\x85OVjvI4\xea\xb7WsQ\xef\x04\x86\x01\xe7\x85OVjf\nOeKb\x9e\x01 m\x9c\x17>Y\xa9\x99)\xfc\x95\xf1\xcf\x13\xddX\\\xac\x95T\x19] \xd6R3\xff\xaer\xd7\x03\xab{b6\x0e@\f\f\x84ORjvI\xec\xec\xb9\xf1N\xd9\xcfn\x10\xb5\x8ae\a\x9a\xaar\xda)\xb2Ԭ6g\xc5\xdem\x05SQ\x06\x02\x92\xc3@\xf8$\xa5f\x97\x8c\xd34\xa5\x17\xf4aOS\x97\xbe?/\x9bG\x11\xa5f\xadb\x97>l7\x93\x0f\x00\tq^\xf8d\xa5f\x97D}{{\xdb\x13\x13\x8e\xea\xe3\xab\r\x95\x93\xf2\x84졷\x94\x9a-\x99\xd4\u007f[\xa7\xb86v\xf3\x00D\xe1\xb0\xf0\x94\xbc\xd4,pк\xa4\xd4O\xed\x85%O\xb7x\xddRxK\xa9Y\x990\x99\x17\xbb.\x00Q8/<%)5\v\b\xff\x9a\xb8J\x93\xcb\xe5\x91\xe9\")\xbc\xa5Ԭf\xd21\x83\xab\xb6\xab\x03`\xc5yᓕ\x9a\x05\x84_\x9a\xe7\xa7\x12Y\xe5\xe7\u007fX\no)5k\x13MrX\xbf1v]\x00\xa2p^x\x93\xb8\r \xe6;\xad-5\xe2Ei\xf9\xe2\x86秊\xa2\x17ߍ(5\xab\x1b[Ӣ\x0fw\xd9o\x00\x00\v,\x84OTjf~\x96F+۩G\x18\xff\x96R\xad`\xc9k\xa5\x9a;\xb2Ԭ\xcd=!\u007fz\x9b\xdd\xda\x00D\xc2Bx\x94\x9a\x01U\xb0\x10\x9ePj\x06\x14\xc1Bx\\j\x0f\xa8\x82\x85\xf0\xb8\xd4\x1eP\x05\v\xe1\t\x97\xda\x03\x8a`!<\"\rP\x05\v\xe1\x11i\x80*X\bO\x884@\x11,\x84G\xa4\x01\xaa`!<\"\rP\x05\v\xe1\t\x91\x06(\x02\u0083\xac\x82\x85\xf0\xc8\xf0@\x15,\x84G\x86\a\xaa`!<!\xd2\x00E8+<J̀b\x9c\x15\x1e\xa5f@1\xce\n\x8fR3\xa0\x18g\x85G\xa9\x19P\x8c\xc3£\xd4\f\xa8\xc5y\xe1Qj\x06\x14\xc2@x\x94\x9a\x01u8/<J̀B\x9c\x17\x1e\xa5f@!\xce\v\x9f\xa4\xd4L\xe7T\xa5\xab\xb0\xe6@\xe1\x15\xaa\x15B\xb8\xce\xd8o\t\x80Tp^\xf8$\xa5fDm\xaeGw6\x96\t\xf1\x01]\xf0z\x1b\xc4;q6\x05@\n8/|\xb2R\xb3ky\xf3n\x11u\x95\xea\u0093\xec=\x80\xf0`\b8/|\xb2R\xb3\xba\xdcK\xf2n\x8b0\xb2\f\x84\aC\xc2yᓕ\x9a\x95>a\xdc]\xddrKޅ\x84\x0f7\x99\x85\xabΖ\vm\xe7\xaa\a\\\x95\x17\b\x00{\x18\b\x9f\xb8\xd4\xecV\xce\x16\xebÐ\xf0\xe1&\xb3p\xd5\xd9_\x1alj\x02\xcfo\xf3\x16\x10\x00\xf60\x10>q\xa9\xd9'\xa2\xc5\xfa0(\xbc\xa5\xc9\xccRuFZ\xbe\xbew\xaf) \x00\xecq^\xf8$\xa5f\xfd\xe3l\xf7\xf0\xd6&\xb3p\xd5\x19iK\xf5\x1b\x8fF\x00\xd8\xe3\xb0\xf0\x94\xbc\xd4,\x90\xe1\xfb\xcd\u0083\xa0\xf0\x96&3kՙ&\v\xea!<\x88\x8b\xf3\xc2S\x92R\xb3\xba\\\xa3\xad\xacI\\\x91wA\xe1-Mf\x96\xaa3\b\x0f\x92\xe0\xbc\xf0\xc9Jͮ\xe5-\xe8\xd73\xba{\xa2\xf1((\xbc\xa5\xc9\xccRu\x06\xe1A\x12\x9c\x17\xde$A\x03H\x9b\xab|WK\xe5\xb8CD\x9f\xc9wZ\xb7x\xbd\x9f\x92\xb5\xc9,\\uvɫվ\xeb?Q\xaby/\xc5\xdb\x18\xc8rX\b\x9f\xa8Ԍ\x8c\xcf\xd2\x14\xcd{_\x1f,\r\x04\xf7%ri\xa8\xc9,\\u\xb6\\֟\xbd\xef\xd2o\x97\xc7\xd9\x14\xc8vX\b\x8fR3\xa0\n\x16\xc2\x13J̀\"X\b\x8fK\xed\x01U\xb0\x10\x1e\x97\xda\x03\xaa`!<\xe1R{@\x11,\x84G\xa4\x01\xaa`!<\"\rP\x05\v\xe1\t\x91\x06(\x82\x85\xf0\x884@\x15,\x84G\xa4\x01\xaa`!<!\xd2\x00E@x\x90U\xb0\x10\x1e\x19\x1e\xa8\x82\x85\xf0\xc8\xf0@\x15,\x84'D\x1a\xa0\bg\x85G\xa9\x19P\x8c\xb3£\xd4\f(\xc6Y\xe1Qj\x06\x14\xe3\xac\xf0(5\x03\x8aqXx\x94\x9a\x01\xb58/<J̀B\x18\b\x8fR3\xa0\x0e\xe7\x85G\xa9\x19P\x88\xf3£\xd4\f(\xc4yᓔ\x9am\x91W^\x1a[\xba\xd3o>\xdc_\xd0j\xbb!\x00R\xc2yᓔ\x9a]\xdb(^\xf3\xee]\"\xea͇\xad\xae\x88\xcb\xc5\x03\x90\x1e\xce\v\x9f\xacԬM\x9c\"\xf2/7;\xcd\xf4\x91\xddf\x00H\x11\xe7\x85OVjf\bO=y\xb8\\$\x18\x06\x9c\x17>Y\xa9\x99)<-/\"\xba\x9e+DN\xa3|tr\x9c\x10\xf5gj&\xe6Vގ\xdd(\x00qa |\xe2R\xb3\xa0\xf0;D\x17Q\xbb\xd7;^^\x01\x9ez\x9a\x1aKJ\xf3JVՌ\xfd\x94\x00H\x1d\x06\xc2'.5\v\n\xdf\x16\b\xf1\xb9\x9e\xc0\xf2\xa9\xc2}\x83\xfc7\b\x804p^\xf8$\xa5fA\xe1_\x13\u05cc\x87a\xe15\xec\xdcA\xda8,<%/5\v\b\xffT\x9e\xf90,\xfc\x94ع\x00$\xc1y\xe1)I\xa9\x99)|\u007f\xc1\x12\xf3aX\xf8E\xb6\xd3\x01H\x84\xf3\xc2'+53\x85\xaf\x13\xc7̇a\xe1\x17\xc7\xce\x05 \t\xce\vo\x12\xb7\x01\xc4x\xa7\xb5m\xa9\x90\x9e\xf7\xbf\xe3\xf5\x8e\xaf\xf5zo\xd0\xed\xc3\xde\xd2\xe9^\xef'\xf6\xeb\x00\x10\x0f\x16\xc2'*53>K#&\xee\x90\xe3\xa39f\xa9\xd9\x0e:i\x8e\xaa\xec\xd6\x00 >,\x84G\xa9\x19P\x05\v\xe1\t\xa5f@\x11,\x84ǥ\xf6\x80*X\b\x8fK\xed\x01U\xb0\x10\x9ep\xa9=\xa0\b\x16\xc2#\xd2\x00U\xb0\x10\x1e\x91\x06\xa8\x82\x85\xf0\x84H\x03\x14\xc1BxD\x1a\xa0\n\x16\xc2#\xd2\x00U\xb0\x10\x9e\x10i\x80\" <\xc8*X\b\x8f\f\x0fT\xc1Bxdx\xa0\n\x16\xc2\x13\"\rP\x84\xb3£\xd4\f(\xc6Y\xe1Qj\x06\x14\xe3\xac\xf0(5\x03\x8aqVx\x94\x9a\x01\xc58,<J̀Z\x9c\x17\x1e\xa5f@!\f\x84G\xa9\x19P\x87\xf3£\xd4\f(\xc4y\xe1Qj\x06\x14\xe2\xbc\xf0IJ\xcd\xdaƚ\x17_\x12\x05\xfdq\xb6Q\xab?\xe9:c\x8eOΙ\x907\xfd@١8S#\xe6\xda5\xa4\xbd\x12(\\\x00\xa3\x15\xe7\x85ORj\xd6sH\xab\xf5\xeaԉ+q\xb6q\xc1\xebm\x10\xef\x18\xc3cZUˮ\x05B4řj\x9dKv\ri\u05fd\xe5\x1e\x02\xa3\x18\xe7\x85OVjF\x9a\xa1\xe0.q\xd5v\v\x06\xed\x01\x89+\xdd~\"\u007fm|\xe1-s%6\riU\x10~T\xe3\xbc\xf0\xc9J\xcd\x02\u009fY\x95\xa0\xbf/(\xf1\xc4zy{R$\xaa\xb6\xb4\no\x03\x84\x1f\xdd8/|\xb2R\xb3\x80\xf0:Mz\x00\xf7\x90G\xc8\xc8rcq\xb1VRu2\xf0LP\xe2%\x85\xf2\xd2\xda\xfe\xbd]Ԫ\xcfzƘ\xdbX\xa4\xfd\xa6\xb8\xf8\xc0\x8a|wW\xc4\xdcpC\xdar\xa1\xed\\\xf5\x80\xab\xf2\x82|\xa0\v\xbfB_k\xbc\xfe\xf7\xc4[Y\xa2\x15\xcd)AQ\xe6h\x82\x81\xf0IJ\xcdH\xab\xef\xe9Y\xb2Z\x1fty\xf3\xea\xafЕ\xfa|\xaf\x14zف\xa6\xaa\x9cvsJP\xe2OJr*=\x87\xe5\xd1mϡ\x92ern\x9e\xb7\xeb@\x9eX\xe5\x16\x136\x16\xbd\x1c17ܐ\xf6\x97\xc6q\xa2\xc0\xf3ۼ\x05\xf2\x81.\xfc\x85\x9a\x9c-\xfa\x86\x8f\x8e]ڲ\u007fg\x91@O\xe0h\x82\x81\xf0IJ\xcdH\v_\x18\xbbVր\xd4<A\xb2\xc6O\xdf_\xfb\xcb\xe6\x99SB\x12_{\xfeQM\xe4\x1b\x11\xde#+q\x96\xd6\xea7\x855\xb4W\xb4\xd2\xd2e\x91s)ܮ\xa0\xe5\xeb{\xf7\x9a\x029ԅ\u007fY3N\xde4\x14H\xd5\x1b\xf2\xb1\x87\x1fM8/|\xb2R3Җ\xb5\xb7\x97\x99\xc2\x1f\xc8\xed\xa1\x1e\x97W\x0e\xaf6TN\xca\x13e\xe6\x14\xabķ\xf6W\x8a\xbd\xfa\xfd\x85\xb1\xefӭ\xbc\xfd\xfa\xa8\xb0\x91\xde\x15]\xf4tM\xccܐ\xf0K\xf5\x1b\x8f&\x87U\x9eza\x9e\xac\xfc\xacx⊝'\xfc\xf1Ά\x82\x11\x89\xc3\xc2S\xf2R3#÷\xed7\x86\xb7'\xb4PK\x91\xdc\xe5\xb6\x17\x96<\xdd\xe2uG\t\xdfn\xc4p\u007f\xb9\xf1\xf2\xa8\\Mm\xf9R\xd7\xc26j\xd7e\xaeK \xbc\xbc\x0f\b_\x987y\x81\xb9S\xbf\xbec\xf1dQ\xb4\x11{\xf8ф\xf3\xc2S\x92R\xb3\xe0A\xebIyZr\xc5<Z\xb0B>\x9a\\ޣ\xdf.\x8a\x12\xbe\xd0x\x8e\xeaK\xe5m\xeb\x84~#Ѥ)|\xc1\xa9O\xf2\xb6\x18\x13\xebtկ7\xe66\x10\x18=8/|\xb2R\xb3\xa0\xf0\x85u\xfa\xcd\xe1\xf1\x97\xc6\x1f\x96\x8fJd\x87\x9f\xff\xe1(ዊe\x99\xab\xdf,\xf8\xeb/j\xcd7\xfe0\xa4'\xbc\xfc{\xa2Ƀa\x8fh\x93\v\xdc\xcb\b\x8c\x1e\x9c\x17\xde$n\x03H\xf0\x9dVo\x9e<Q\xe3/\xae,6\"\x86G,nx~\xaa(z\xf1]\xfaL\xbe{\xba\xc5\xeb\xfdT\x17^\x14z\xdaZܹ\x1f\x19\xab\xd6Mʗ\x87\x9d\xa7\xf2_\xeei\xd4N\xf6Ը/X\xe7\x86\x1b\xd2.y\xb5\xdaw\xfd'j5\xef\xa5\xeb\xde\xf2\xdaw\xfa\xbb\xaa\n\x0f\\\xd1\u007f\x84\xab\xbe\xb5\xa5V\x1c\xb0\xff\xc5\xc0\x88\x84\x85\xf0\x89J\xcd\xdaD\x10#glь;\xf2o)\xd5\n\x96\xbcV\xaa\xb9ii\xe0\xf9%D\x8f\xee\xac\xff\x99\xab`\x9e\xe9;}$\xe4\xce\xd9_$Dc\x9ep5\t1\xcf:7ܐ\xb6\\\xbf\xd5\xdew\xe9\xb7\xcb_\xd1or\x8e6\xea\xb7\xf5\xb4k\xba\xa7D+t\xc3\xf7Q\x05\v\xe13Tj֥AV\x10\x05\v\xe1)3\xa5fM\x13\xf0\x9e\x11\x88\x82\x85\xf0\x99\xb8Ԟ\xe7\x80\xdf]\x9fl\x12\xc8:X\b\x9f\x81K\xed\xf5\x88)\xcb\v\xaf'\x9b\x05\xb2\x0e\x16\xc2S\x06.\xb5\xe7q\xb9?H6\ad\x1f,\x84\xcfD\xa4\x01\xc0\x0e\x16\xc2g \xd2\x00`\v\v\xe1)\x03\x91\x06\x00;X\b\x8fH\x03T\xc1BxD\x1a\xa0\n\x16\xc2\x13\"\rP\x04\x17\xe1\x01P\x02\v\xe1\xf5\xf0\xfe\xf6\xf6\xb8\x9f\x87\a`\xf8`!<2<P\x05\v\xe1\t\x19\x1e(\x82\x85\xf08-\tT\xc1BxD\x1a\xa0\n\x16\xc2\x13\"\rP\x04\v\xe1\x11i\x80*X\b\x8fH\x03T\xc1BxB\xa4\x01\x8a`!\xbc\x8c4o~5\u08c1>\xf9\x0f\xbbz\x901X\b\x1f\x884\x00d\x1c\x16\u0093\x8c4ح\x03\x05\xb0\x10^\x8f4\aw\xf7\x1d\xd9\xec;\xf2\x92\xfe\xaf\xf7\xf8v\xcbs\xc9K\xcd\x00H\x1d\x16\xc2\xcb⛅7߬\xee6\xff\xa5Vjv\xe0\x18\x01\x90.,\x84\xd7\xe9\xbdI_~\x1c\xf8\xd7}1\xe2\xa98\xa5f\x8f.!\x00҅\x85\xf0\xc6\x1bO\x9d\xf1\x9e\x8dSj6u\xb1\xddd\x00\x12\xc2Bx\xe3,\xcd\xf9\x81^\xfbӒ\xa1R\xb3Sㄨ\xf2\x97\b\x91\u007f\xab5\x10\xec\xa7\xc4n\f\x80\x04\xb0\x10\x9e\x12\xbe\xf1\x14*5\xf3\x1f\xf6\xe4\x1c\xa6]cw\x9d\xa0\xaeC\xde\xd2\xe9z\xb2ǵ\x96@z\xb0\x10>\xf1gi,\xa5f\xfe\xa5\xe5WK6\x9a\x8b\x11i\xc0 `!|\xe2\xcf\xd2XJͨ\xe7ᢪ@\x96\x87\xf0`\x10\xb0\x10\x9e\x12G\x9ap\xa9\x19Q\x8b8\x14\x18Ax0\bX\b\x9f$\xd2XJ\xcd.\x14֗|a.6\x84\xdf\xf9\xa9\xfd:\x00\xd8\xc3B\xf8$\x91&\\j\xd6_^O\xcb\xdcf\xa6q\xbb\x89\xae\x88&\xfbu\x00\xb0\x87\x85\xf0\x94 \xd2XJ\xcdz\x0e-/\xb8@\x1dy+\x0e\xdd\"Y\xba\xb7\xa5\xc5\xed\xfa,\xcej\x00\xd8\xc2B\xf8D\x91\xc6Rj&\x87\xabh\x85\x10cewӭ\x15\xf9\xb9\xd3\xdb\xedV\x01 .,\x84\xc77\x9e\x80*X\bO\xf8\xc6\x13P\x04\v\xe1\xf1%n\xa0\n\x16\xc2#\xd2\x00U\xb0\x10\x9e\x10i\x80\"X\b\x8fH\x03T\xc1BxD\x1a\xa0\n\x16\xc2\x13\"\rP\x04\v\xe1\x11i\x80*X\b\x8fH\x03T\xc1BxB\xa4\x01\x8a\xe0\"<\x00J`!<J̀*X\b\x8f\f\x0fT\xc1BxB\x86\a\x8a`!<NK\x02U\xb0\x10\x1e\x91\x06\xa8\x82\x85\xf0\x84H\x03\x14\xc1BxD\x1a\xa0\n\x16\xc2#\xd2\x00U\xb0\x10\x9e\x10i\x80\"X\b\x8fR3\xa0\n\x16£\xd4\f\xa8\x82\x85\xf0\x84R3\xa0\b\x16\xc2'*5\xf3\x06K\xcdƟ\x8c\xbb~\x98\x93s&\xe4M?Pv\x88\xa8V_\xc5u&\xfe\xcc\xe5\"\a\x97\xe9\xcbBX\b\x9f\xa8\xd4\xec֡\xc29\xf2J{\xbbD[\xdc\xf5C\x1cӪZv-\x10\xf2\x8a\x93\x17\xbc\xde\x06\xf1N\xfc\xa9\x17\xbc\xa1f\x11\x90E\xb0\x10\x9e\x12\x96\x9aM\\&o?JE\xf8Jy\xa1U\u007fm\xe0\x12\xab퉄\xb7T\xe9\x80,\x82\x85\xf0\x89K\xcdL\xe1\xfb\xb7݈7!\xcc\xc4zy{R\xb4\x18\x8f <\x88\x81\x85\xf0\x89K\xcdL\xe1uN\x8e\x13\xa2\xfeL\xcd\xc4\xdc\xca\xdb\xfa~\xfc\x95)\xae\x87\x1b\xfct\xbbH\xfbMq\xf1\x81\x15\xf9\xee.\xa2%\x85\xa7\xf4y\xfe\xbd]\xc6\xfc\xa0\xf07\x16\x17k%U\xe6!\x80\xb7\xb2D+\x9aS\"\xaf\xb8\xad=\xb5\xea\x01W\xe5\x05\x02\xd9\x04\v\xe1)\xe1\x1bO\x13k{z^.\xd7\a=M\x8d%\xa5y%\xabj\xc6~J\xb4T\xab\xdf[\xaf\xd5\x12\x1d\xc8\x13\xab\xdcb\xc2Ƣ\x97\x89>)ɩ\xf4\x1c\x0eVv\a\x85o\x15\xcb\x0e4U\xe5\xc8+\r\x1f\x1d\xbb\xb4e\xff\xce\"\xa1\xbfbH\x13\x93\x1b[\x8a\x16\xc4\xf9\xa9`t\xc2B\xf8ğ\xa5\x99(\xcf\xd1\x14\x9a\xe3\xa9\xc2}\x83\xfc7\xe4U\xb4e\xa47n\vkh\xafh\xa5\xa5\xf2\x0f\xc1\xb5\xe7\x1f\xd5D~\xe0\xf4KP\xf8\x9e&}\x8f\xef/\x9b\xa7\x0f\x1b\n\xa4\xea\r\xf9\xc6\x1e\xbe\xf0\v\xa2ڂ\xd8\x1f\bF1,\x84O\xfcY\x9a\x89U\xed\xedK\x83\xc2k\x9f\x9a\x83\xda2\xe3\xeeA}\x17_\xd8H\xef\x8a.z\xba\xc6|\xe6\xd6\xfeJ\xb1\xd7\x18\x852\xfcՆ\xcaIyB\xae\xf1Y\xf1\xc4\x15;O\xf8\x8d\xbf\x01\x9a|\x85x4\x02\xd9\x04\v\xe1)q\xa4\xd1\xc5<\xb5\xd3\x1cO\r6\x11\x97\x9b\xb5~Uz\xd4)l\xa3v]\xdb:]\xf8v#\x91\xfb\x03O\x06\x85o/,y\xba\xc5\xeb6^\"\xd7w,\x9e,\x8a6\x1a{xy\xd0\n\xe1\xb3\f\x16\xc2'\x894\xcb\xc2㩋\x02\x83\xdaI\xd2Y\xffĥ\x11\xc2\x17\xae0\x9e\xac/5\xee\x82\xc2O.\xef\xd1o\x17I\xe1\xdb\xeb\xf4ծ7\xe66\x10\x84\xcfNX\b\x9f$\xd2X\x85_\x1c\x18\xec\x15\x8d\xfam\xa3\f/\x16ዊ\xaf\xe9K\xfd\x81\x97EP\xf8\x12\xf9\xd0\xff\xb0\x14\xdec\x9e\xcdw\xcbMB\xf8l\x84\x85\xf0\x94 \xd2\xdcz\xa7p\xce!\xf34\xe3\xed\xc3F\xdf\xfc'ƃ\x9a\x9c\xbaֺ\x1c]\xf2S\xf9/\xf74j'{j\xdc\x17\xa8H\x14z\xdaZܹ\x1f\xe9i]\xbeӺ\xc5\xeb\xfdTZ\xbe\xb8\xe1\xf9\xa9\xa2\xe8\xc5w\xf5\xa1\xab\xbe\xb5\xa5V\x1c\xa0K^\xad\xf6]\xff\x89Z\xcd{)\xceO\x06\xa3\x11\x16\xc2'\x8a4\xc6giv\x19Ó9\xc2\xd2B\xbf\xad\xccU\xd6\xe0'\u007f\x91\x10\x8dy\xc2\xd5$\xc4<ztg\xfd\xcf\\\x05\xf3t\xdfii\xe0#8K\xf4\xa9[J\xb5\x82%\xaf\x95jn\xda5\xddS\xa2\x15\xba\x0f\xc8\xcf\xd2\b\xa1\xbd\xef\xd2o\x97\xdb\xfdX0Ja!<\xbe\xf1\x04T\xc1Bx\xc27\x9e\x80\"X\b\x8f/q\x03U\xb0\x10\x1e\x91\x06\xa8\x82\x85\xf0\x84H\x03\x14\xc1BxD\x1a\xa0\n\x16\xc2#\xd2\x00U\xb0\x10\x9e\x10i\x80\"X\b\x8fH\x03T\xc1BxD\x1a\xa0\n\x04\x82U\v\x00\x00 \x00IDAT\x16\xc2\x13\"\rP\x04\x84\aY\x05\v\xe1\x91\xe1\x81*X\b\x8f\f\x0fT\xc1BxB\xa4\x01\x8apV\xf8^=\xc6\f\xf8$\a\xdf\xf8\xdc\xe7\xeb\xeb\x93;y$\x1b\x909\x9c\x15>\x80\xae\xf9\xa6\xd9\xe7\x10i@\xe6a!\xbcN\xe79_\xb2)\x00\f\x1d\x87\x85\xd7\xe3\xcb\xf1\xed\xeb֮]\xa3\xb3v\xcdڭ\xafw#рL\xe2\xb0\xf0\xf2\xfc\xcc¹\xd5sM\xaa\xab\xa7\x9dG\xb0\x01\x99\xc4y\xe17\xcc8\xfe\xe5\xe7_\xea\xe87\xebf Ƀ\x8c\xc2@\xf8\x8a\xf0\x19\xc9ͳ\xce\xc9k\b#\u0383L\xe1\xbc\xf0/\xcc\xf80\xf4h\xfd\xac\xb3\x89f\x030T\x9c\x17~\xc3̰\xe4\xcfʹ\x13\xbe\xe5\xc1\xf1e-S[\xe3\xf46\xa1\xac\t\xa4\x81\xf3¯\xaf\xee\xfd\xc3?\xfe\xe3=\xfa\u007f\xff\xec\xdb=\xa3\xf3\xed\xb5\xbdo\xaf\x8d\x98\xb3MԴ<%Ķ8\xbdM(k\x02i\xe0\xbc\xf0\xeb\xaa\xfb\xd6\xfd\xfd\xdf\xff\x1f\xfd\xbf\xef\xfb\x9agt7/\xbc\xd9\\m\x9d\xf2\xd1\xd8z\xfdv\x95\x14\x9e\xeckl <H\x19\xe7\x85\xdf0\xeb\xfcͳ\x1f\x9f\xff\xf8\xfc\xd9˴i\xe6ǾN\xf2}e\x9dR[pK\xbf\xfd@4\x18\x8f <\x18\x12\xce\v\xff\u008cӡGv\a\xad\xf9O\x1bw\xdb>1\xeeB\xc2\a;\x9et\xb4\x15O\x14\xe7W%\xe8d\x05 \x88\xf3\xc2o\x98\x19\xee\xef{if\xcci\xc9\xeb\xe25\xeb\n!\xe1C\x1dO\xb2\xaciJSc\x99\xeb\x14\x01\x90\f\x06\xc2W|\x1ez\xf8Ҭ\x987\x9e\xde7\xae\xe8\xee\xef\xe9\xb9e<\f\no\xe9x\"mr\x0fQOi9\x01\x90\f\xe7\x85ߴ\xf0\xc95+W\xfe\xfa\xd7+W\xae\\S\xfdH\xcc\xd7@\xcc=|\x8d\x10b\xbf|\x18\x14\xde\xd2\xf1D\xda3r\xb8C\\#\x00\x92\xe0\xb0\xf0\x03D\xfbV\xfer~u\xf5\xc2ǫ\xab\xab\xe7\xaf\\\xdb\x19\xf3\xe1\xb1\t2\xc3_j\x11u\xc6.>(\xbc\xa5\xe3)p\xd0\xea\x15\xc7\b\x80$8,\xbcN_o\xb7\x8eo@\xde\xf6\xf6\xc6>_[$Mo\x89:-i\xe9x\"m\x95\\\xb2S\xa4P\xd5\r\xb2\x1d\xe7\x85'c?\xff\xc2\xc2\xcf\xe3|0\xd88\x0f\xefwG\to\xe9x\"\xadX\u007fI\xf4?\xe8\xb6]\x1d\x00+\xce\v?\xd0\xd7\xd7\xed\xf3\xfd۴#\xben_\x9f\xddG%\xb7\x88'Zk\x8dwZ-\xbdM\xe1\x8e'y\x96\xa6\xf2\xf0\xfe\xf2\xfc\x8fl\xd6\x05 \x12\xe7\x857\xe9M\xf0%\xee\x96ɹ\xe5m%m\x11\xbdM\xa1\x8e'\x9d\a=\x8b\xf3\x8ak\xd0M\x06R\x80\x85\xf0>\xa2M\x8f\x9f%|*\x18d\x1c\x16\xc2뇪z\xa4!\x9b#V\x00\x86\x17\x16\xc2S\xe2H\x03\xc0\xb0\xc1Bx\\j\x0f\xa8\x82\x85\xf0\xb8\xd4\x1eP\x05\v\xe1\t\x97\xda\x03\x8a`!<\"\rP\x05\v\xe1\x11i\x80*X\bO\x884@\x11,\x84G\xa4\x01\xaa`!<\"\rP\x05\v\xe1\t\x91\x06(\x82\x85\xf0\x884@\x15,\x84O\x10i\xb0\xe7\a\xc3\n\v\xe1)\x8e\xd8\xd8\xf3\x83ᆅ\xf0\xf1\xc4\xc6\xc1,\x18nX\b\x8fH\x03T\xc1Bx\x8a/\xf6\x91\xdd\x11\xd7\xdd\x03`h\xb0\x10>&\xd2\xec\xf1u\xf6\xfa\xfa\xfaz\xfb\xfa6T\x9c\x95w}\xd4\xd7\xdb\xeb\xc37D\xc0Pa!|L\xa49\x12\xfa\xba\x1f\xda\xfd\xc0\xb0\xc2Bx\x8a\x8e4\x90\x1cd\b\x16\xc2Ǟ\xa5\x91u\x96\xbb7mxn\xfd\xb3k\xd7?\xb7~\xc3\xebͨ\xb3\x04\xc3\x02\v\xe1c\xcf\xd2\xe8í\vg?6kV\xf5\xfcٳf=V=\xe3\"NN\x82စ\xf0\x14s\x96F^Uxڑ\xf3g\xcfߤ\xcbgϟ\u007fv\x1a\xea,\xc1\xb0\xc0B\xf8\xd8Hc\\F\xfb&\xc9K\xadʇ[+\xe4u\xe3\xe1<\x182,\x84\xb7\x8d4/̔u\x96?\xba\xe3\xa0\xfe蹙\xe7\xe2\xad\v@:\xb0\x10\x9el#\x8dQay\xff\x1d\xf2v=\xea,\xc1\xf0\xc0Bx\xdbH\xb3~n\xf7\xee\xfb\xee\xbd\xfbk?\xb8\xef\xe7}o\xcc\xe8<\xb8\xc1w|s\xc4Z\xa8\xb3\x04\xe9\xc3Bx\xdbH\xb3\xaez`\xed7\xbe\xfeww|\xe3\x1bߑu\x96\xbb\xab\xbb\xf7\xfcҺ\x12\xea,\xc1 `!<\xd9F\x9a\x8a\x8b\x9dǏ\xdf\xfb\xf5\xed\xc7ߣ\x97f\x9e\xef>Oݗ\xadSPg\t\x06\x01\v\xe1m#\x8dYgy\xaf\xcc\xf0\x03\xa8\xb3\x04\xc3\x04\v\xe1m#͆Yr\x87>\xeb{R\xfbM3cNK\xa2\xce\x12\f\x06\x16\u0093}\xa4\xf9R\x1f\x98\x9d\xad\x9b+Pg\t\x86\x05\x16\xc2ۿ\xf14\u007f\xcd\xfag\xd7m\u007f\xe3\xb9g\u05ed\x9f\x8f:K0<\xb0\x10\xde6\xd2\xecy\xb2z\xee\xec\xd9\x15\x15\x15\xb3g\xcf}reg\xcc۬\xa8\xb3\x04\x83\x80\x85\xf0d\xf7\x8d\xa7\xde\xce\xcb\x17/_n^\u007fZ\xbf\xeb\xb4\xf9\xda\x13\xea,\xc1 `!|\x82/q\xaf\x9du>\xceGhPg\t\x06\x01\v\xe1c#\r\xc9\xc3U_\xaf\xcf\xf7\xd2\xfc\xb3\xbe\xde>\x9f\x9d\xf3\xa8\xb3\x04\xe9\xc3Bx\x8a\u007f]\x9a\x83\u007f\x88-\xa3\x0f\x82:K\x906,\x84\x8f\x17i|Dkf\x1e\xc7\x17\xfe\xc0\xf0\xc1Bx\xdbH\x13X>\x1f\x17b\x02\xc3\b\v\xe1ip\x91\x06\x80\xb4a!<.\xb5\aT\xc1B\xf8\x04b\xe3R{`Xa!<\xe1\xea\xc1@\x11,\x84G\xa4\x01\xaa`!<\"\rP\x05\v\xe1\t\x91\x06(\x82\x85\xf0\x884@\x15,\x84G\xa4\x01\xaa`!<\xc5\x17\x1b\u0083a\x85\x85\xf0\xf1\"\r2<\x18nX\b\x9f\xe8\xb34\xc8\xf0`8a!<!\xd2\x00E\xb0\x10>AtA\xa9\x19\x18VX\b\x1f\x13]Pj\x062\x04\v\xe1):\xba\xa0\xd4\fd\b\x16\xc2\xc7D\x1aH\x0e2\x04\v\xe1c\xcf\xc6\f\xa0\xd4\fd\x04\x16\u0093ݥ\xf6Pj\x062\x00\v\xe1\xed/\xb5\x87R30\xfc\xb0\x10>6\xd2\xf4\xa1\xd4\fd\x04\x16\u0093]\xa4A\xa9\x19\xc8\x00,\x84\xb7\x8f4\xc9J\xcdNΙ\x907\xfd@١\x88\x85\x91\xfdf\xfb\vZcV\x03Y\r\v\xe1m#M\xb2R\xb3cZUˮ\x05BDV\xf5E\xf6\x9b\xb5\xbaZ\x02\xa3\x03\xb8\x840\x90\xb0\x10\x9e\xec\"M\xb2R\xb3J\xb7\x9f\xc8_+b\xba)\xaduO\xfe\xe0\xe0\xd1%\xd1\xd3@V\xc2Bx\xfbH\x93\xa4\xd4lb\xbd\xbc=)\x82\xfb\xf0\x10v\xfdf4uq\xec2\x90\x85\xb0\x10\xde6\xd2$+5[R(˛\xfc{\xbbh\xb9\x18\xb7mY\xb8\xbe,(\xfc\xf5\\!r\xe4ų\xa95p\xb1\xd5)1\x1b\x01\xd9\x06\v\xe1ɶ\xe3)q\xa9\x19}R\x92S\xe99ܯ\x8f\xfe\xd28N\x94<\xef)\tԗ\x85\xf6\xf0\xed^\xefx\xa3\x04\xa4됷t\xba\xd7\xeb\xfd\x80@\xb6\xc3B\xf88\x91&a\xa9\x19ѵ\xe7\x1f\xd5D\xbe\x11ᵉ7\xf4=z\x89Y_f\x8d4\xb9\xc1\xaaVD\x1a`\xc0Bx\xfb7\x9e\x12\x97\x9a\x19\xdc\xda_iv}\xd4\xc9G\rf}\x19\x84\a\xf1a!<\xd9E\x9ad\xa5f\xed\x17\xe4\xad\xdfh1\x8b\xa8/\x83\xf0 >,\x84\xb7\xfd\xc6S\xb2R\xb3\xc2\x15\xc6]})E\u0557\xc5\x17~\xe7\xa7\x04\xb2\x1c\x16\xc2\xc7F\x9a\xd0\xf2\xf8\xa5fE\xc52\xc0\xf8\xa7.\xd2o\xb5\xa2.\xfd\xd0t\x92Y_f+\xbc[\u007f\xeeJ\xec9{\x90m\xb0\x10\x9e쾬\x9d\xacԬH\x14z\xdaZܹ\xb2\xb3L\x96\xcc\xef,\x95\xf5e\x96~\xb3\xfew\xbc\xde\xf1\xb5^\xaf\xb1\xdb\xf7h[Zܮ\xcfb7\x03\xb2\v\x16\xc2'\xb8.M\xfc\x06\x90Gw\xd6\xff\xccU0\xcf\xe8\xe8\xd3V\xd7\x06\xea\xcb,\xfdfGs\xcc\xe1\x0e9\xe3֊\xfc\xdc\xe9\xed\xb6\x1b\x02\xd9\x04\v\xe1\xe3E\x9a\x94K\xcd4\x0f\x01\x90\n,\x84\xa78ן\xe9K\xb5\xd4\f\u0083\x14a!\xfc\xa0\"\x8d\x15\b\x0fR\x84\x85\xf0\t\xceҤr\xa9\xbd\v^\xad\xf6]?\x01\x90\x1c\x16\xc2\xd3\xd0.\xb5\xb7\\?2\xd5>I6\v\x00b\"|\x82H\x83\xab\a\x83a\x85\x85\xf0C\x8c4\x00\xa4\f\v\xe1ih\x91\x06\x80\x94a!<\"\rP\x05\v\xe1\x11i\x80*X\bO\x884@\x11,\x84O\x10] <\x18VX\b\x1f/\xba Ãᆅ\xf0\x94\xe0\xb34\xc8\xf0`8a!<\"\rP\x05\v\xe1\x13\xec\xc9Qj\x06\x86\x15\x16\xc2S\xf4\x9e\xbcW\xdfۛ\xdfx\xdaP\xf1\xa1\xef\xa6,5#Dy0\f\xb0\x10>A\xa4A\xa9\x19\x18VX\b\x8f\x83S\xa0\n\x16\xc2S\xcc\xc1\xa9\xbe\xb3?\xbe}\xddڵkt֮Y\xbb\xf5u\x94\x9a\x81a\x81\x85\xf0\xb6\x97\xdaۼpn\xf5\\\x93\xea\xeai\xf1.\xd6\x01@Z\xb0\x10>6\xd2\xe8\xc3\r3\x8e\u007f\xf9\xf9\x97:\xfaͺ\x19(5\x03\xc3\x02\v\xe1\xc9\xf6\xea\xc1\x15\xe1E\x9bgɫ\a\x0f\xe0\xf8\x15\f\x15\x16\xc2\xdbF\x9a\x17f|\x18zdw}x\x00\x06\x01\v\xe1\xed#\x8d\xa5\xc8\xec9\xbbR\xb30\x91Mf\x01\x96\x8b\x1c\\Y\x0fD\xc3Bx\xb2\x8b4\xeb\xab{\xff\xf0\x8f\xffx\x8f\xfe\xdf?\xfbv\xcf\xe8|{m\xef\xdbk\xe3\xac\x1c\xd9d\x16Z\x88\x8bw\x80\x18X\bo\x1bi\xd6U\xf7\xad\xfb\xfb\xbf\xff?\xfa\u007fߗ\xa5f\xcd\vo6W\xc7߄]\xb1\x13\x84\a1\xb0\x10\xde>\xd2\xcc:\u007f\xf3\xec\xc7\xe7?>\u007f\xf62m\x9a\xf9\xb1\xaf\x93|\t>V\x03\xe1AJ\xb0\x10\x9el\x9b\xb8\x8dR3\xf3\x91\xedA\xeb՚\tūWOp\x19I=$\xbc\xff\x95)\xae\x87\x1b\x8c\xcb2i+\x9e\bW\x9d\x01 a!\xbcm\xa4\xd90\xb33\xf4𥙱\xa7%\xfb\x1f,l\xf0\x8c\xcf\xddY\xf9\xb2|\x14\x12~\xa9V\xbf\xb7^\xab\x95Cy\x11\xedƲ@\xd5\x19\x00\x12\x16\xc2\xdbG\x9a\x8a\xcf\xf5\xc1\x80\xb1\xf0\xa5Y\xb1o<5\x89\x93\xb2\xd6)\xa0sP\xf86\xd1\x16\xba\xd5&\xf7\x10\xf5\x94\x96\x13\x00AX\bOv\x91f\xd3\xc2'\u05ec\\\xf9\xeb_\xaf\\\xb9rM\xb5M\xa9Y]\xbe~\xf3Q\xb0\x978(|m\x99q\xf7\xa0\xdc\xc5k\xcf\xc8\xe1\x0e\xb3\xea\f\x00\t\v\xe1c#\x8d>ܷ\xf2\x97\xf3\xab\xab\x17>^]]=\u007f\xe5\xda\xd8k\b\xbf<\xf6\xaaܕG\xedፎ3\xa2*\xb9[\x8f\xa8:\x03@\xc2Bxۏ\a\xf7\xf5v\u007f\xd5ݽgù\xee/\xbb{{cW\xfa4\xa7\xf2ӓ\xa5偫\x06\x87\xf6\xf0\x93\xe4\x02\xffĥ\x14Uu\x06\x80\x84\x85\xf0\x14\xffK\xdckf\xc6\xfb\x9c\xfc1Q$\x84\xfbB\xe0QP\xf8\xbdB\x96\xcd7\x9a\xed\xadŷ䱭\xdbvu\x90\x9d\xb0\x10\xde\xf6\x1bO\x03}}\xbd>\xdf\xf6\xc7\xcf\xfaz}}6\xce\x1f\x1b\xbf\u007f\xaf\xf7\x82\xb1\x83\xb74\x99QMN]k]N\x8d\\\xac\x89\xca\xc3\xfb\xcb\xf3?\x8a]\x17d-,\x84\x8f\xf7\x8d'\xfd\x15p\xf0\xf5xץ9\xa4\xc9\xc62m\xfa\xa9\x88&3\xf2o+s\x95\x99\xe7\xe1\x1f\xf4,\x0eT\x9d\x01\x10\x80\x85\xf0\x14'\xd2\xf8\x88~=#N\xa9\xd9\x15ײ+\xb7o_?\xba \xff\xba\xdd\xd3\x00\xd8\xc2B\xf8x_\xe2\xd6w\xf9\xdb\x1f\x8f\xf3]\xa7\x96|\xf3p\xd5_\xd4f\xf74\x00\xb6\xb0\x10~0\x91\xe6X\x8eyB\xf2T\xce\t\xbb\xa7\x01\xb0\x85\x85\xf04\x88K\xed\xf9ks\x975\x1dhZ\x96\xbb\fuf uX\b?\xa8K\xed\xf9[+\x8b\xb5\xe2\xcaV\xf8\x0eҀ\x85\xf0\t\"\r\xae\x1e\f\x86\x15\x16\xc2\xd3 \"\r\x00\x83\x81\x85\xf0\x83\x8a4\x00\f\x02\x16\xc2#\xd2\x00U\xb0\x10\x9e\x10i\x80\"X\b\x8fH\x03T\xc1BxD\x1a\xa0\n\x16\xc2\x13\"\rP\x04\v\xe1\a\x11i\x10u\xc0\xa0`!|\xba\x91\x06Q\a\f\x16\x16\xc2S\x9a\x91\x06Q\a\f\x16\x16\xc2#\xd2\x00U\xb0\x10>\xe5H\x13h\xf7\xd39\xf8\xc6\xe7>\x1f\xda\xfd@\xba\xb0\x10\x9eҏ4\x9bf\xa3\x13\x04\f\x02\x16\xc2\x0f\"Ҡ\xce\x12\f\n\x16§\x1ci\xe4\x10\xed~`\b\xb0\x10\x9eR\x8e4}h\xf7\x03C\x82\x85\xf0\xa9G\x9a>\xb4\xfb\x81!\xc1B\xf8\xd4#M\x1f\xda\xfd\xc0\x90`!<\xa5\x13i\xd0\xee\a\x86\x00\v\xe1Ӌ4\xc9\xdb\xfdZ\xe4e\xc8&F\u007f\xbb{\u007fA\xab\xddd\x90U\xb0\x10>\xadH\x93B\xbb_\xd7!oޢ\x98\xe2\x8fVWK\xf4\"\x90u\xb0\x10\x9e҉4\xa9\xb5\xfb\x15\xad\x8e]\x86\vz\x00\x1e§\x17iRj\xf7\xb3\x13\x1e\x00\x1e§\x15i\x92\xb6\xfb\x19\x98\u0087+\xfd\xae\xe7\n\x91#/\x1dO˅\xb6s\xd5\x03\xae\xca\xe0\x95\xe5AV\xc1BxJ'\xd2$k\xf731\x85\xb7T\xfa\xb5{\xbd\xe3\x8d\n\x9c\xbf4\x8e\x13\x05\x9e\xdf\xe6-\x88]\t\x8c~X\b\x9f^\xa41\xda\xfdL\xec\xda\xfdL\f᭕~:\xb9\x81\xa2b-_\u07fb\xd7\x14خ\aF9,\x84O+\xd2$k\xf731\x84\xb7V\xfa\x91ExY\x00\xe5\xd1l\xd7\x03\xa3\x1c\x16\xc2Sʑf y\xbb\x9f\x89!\xbc\xb5ҏ,\xc2\xcb{\b\x9f\x9d\xb0\x10>\xf5H\xa3\xd3\xd7ۭ\xe3\x1b\x90\xb7v\xed~\xb7?\x90\a\xa9\x13\x8c=\xbc\xa5ҏ < &§\x1eiB\xcb_X\xf8y\x9c}\xfb+\xc2KtUl\xa3\xc8J?\x82\xf0\x80\x98\bO)G\x1a2\xda\xfd\xba}\xbe\u007f\x9bv\xc4\xd7m\xdb\xeew@\xcci\xd9U>\xe139\x0eW\xfa\xf5\xbf\xe3\xf5\x8e\xaf\xf5zo\xd0%\xafV\xfb\xae\xffD\xad\xe6E\xddY\x16\xc2B\xf8\xb4\"\x8dIo\xfc/q\xb7Lu\xe5W\xbdo\fÕ~Gs̢\xbf\x1d\xb4\\v\xff\xbd\xef\xd2o\x97\xc7\xdd\x04\x18\xb5\xb0\x10>\xddH\xe3#\xda\xf4\xf8Y\xfbv?\x00\x12\xc1BxJ'Ґ\xbcx\x01鑆l\x8eX\x01H\f\v\xe1\x877\xd2\x00\x10\x1f\x16§\x1bi\x12\xbc@\x00H\b\v\xe1)\xcdH\x13o9\x00\xc9`!\xfc \"\r.\xb5\a\x06\x05\v\xe1\x11i\x80*X\bO\x884@\x11,\x84G\xa4\x01\xaa`!<\"\rP\x05\v\xe1\t\x91\x06(\x82\x85\xf0\x884@\x15,\x84G\xa4\x01\xaa`!<\r5\xd2\\\xbe\xfcyg\xd4\x06\xba;/\u007f\xf5%^\x12 \n\x16\xc2\x0fc\xa49\xb8=ޗ\xfe\x00 &\xc2\x0fW\xa4\xd17\xb0i.\x0efA\x02X\bOC\x8d4a\xba;\xb1\u007f\a\t`!\xfc\xf0D\x9a\xbe>__\xdf\xf1=_\xeaw\x03\xb0\x1e\xd8\xc3B\xf8\xe1\x8a4:/=v\xd1f)\x00\x01X\bO\xc3\x17i\x06\xc2\xd7\xe1\x03 \x16\x16\xc2\x0f=\xd2諞\xde\xf3\x87\xed[7\xbfټ}\xeb\xd6\xed\xcd\xfbnگ\x06\xb2\x1d\x16\xc2\x0f=\xd2\xe8\xabn\x9f?k\xe6\xb4\x19\xd3$3\xe7W\\Ĺ\x1a`\a\v\xe1iȑF\x1fn\x98v\xf0\xf4{\xa7\xdf\xd39}z\xcd4\xb4\xfb\x01[X\b?\xf4H#\x85\x9f\x1d\xbe\x8a\xc1֊s\xf2\"\x1ep\x1eD\xc3B\xf8a\x894\x96\xb2\xb3\xbe\r3\xcfE\xaf\x03\x80\x84\x85\xf04,\x91fFHxZo\xdf\xee\a\x00\v\xe1\x87%Ҭ\x9f۽\xe7\xc7?\xfe\x89\xfe_E\xdf\xeb3??\xb2\xddw|k\xe4\xe7jNU\xba\nk\x0e\x14^\xa1Z!\x84\xeb\f\x81,\x84\x85\xf0\xc3\x12i\xd6UӚ\xaf}\xed\xef\xf4\xff\xbe%\xdb\xfdޘ۽;\xb2\x1f\xa4\xcd\xf5\xe8\xce\xc62!>\xa0\v^o\x83x'z\xab \x1b`!<\rK\xa4\x99}\xf9b\xf3\x9e}{\xf65\x1f\xa4\xcd3.v\x9e\x1e\xe8\xfc\xd0z\xf5\xc9ky\xf3n\x11u\x95\xea\xc2\xeb\xb4C\xf8섅\xf0\xc3\x12i,\xed~\x03v\x19\xbe.\u05f8<\xf6\x16ad\x19\b\x9f\xa5\xb0\x10~X\"͆Y\x17\xcd%\xfaͦ\x19\xe7\xe4\xa5V#6X\xfa\x84qwu\xcb-y\x17\x12\u07bf\xab\xdc\xf5\xc0\xea\x1e}tcq\xb1VRu\x92\xd0l9\x9aa!<\rO\xa4\tobsE\xcc\x1bO\xb7r\xb6X\x1f\x86\x84\xaf\xcdY\xb1w[\xc1T?Q\xabXv\xa0\xa9*\xa7\x1d͖\xa3\x19\x16\xc2\x0fK\xa4\xd9P\xbdn\xf3\v\x9bt^ش\xf9\x97\xb1\xed~\x9f\x88\x16\xebà\xf0\xadb\x97\U00068468\xa7\xa9K\xdf\xe1\x97͓\x8b\xd1l9Za!\xfc\xb0D\x9a\xe6\xc7\x1f\xab\x98aR\xf1\xf8\x93\x9fGo\xad\u007f\x9c\xed\x1e~ɤ\xfe\xdb:Ų\xd9\xf2jC\xe5\xa4<aT]\xa2\xd9r\xb4\xc2Bx\x1ar\xa4\xd1\xe9\xbex6\xc4\xc5˱\u007f-\x02\x19\xbe\xdfl)\x0e\n_f6\xe1\b}\xbf\xde^X\xf2t\x8b\xd7m\n\x8f\u07b3Q\n\v\xe1\x87\x1eiR\xa0.\xf7\xaa\xbck\x12W\xe4]P\xf8\x9aI\xc7\f\xf4\xe7&\x97\xcbC\xd7E\x10~T\xc3B\xf8\xa1G\x1ac\xe9@_\x90\x81\x98M\xc9\xf3\xf0\v\xfa\xf5\x8c\xee\x9eh<\n\n\xdf&\x9a\xe4]\xfdF\xa2\x92E\xfa\xc0\xff0\x84\x1fհ\x10\x9e\x86#\xd2$\xa5\xcdU\xbe\xab\xa5r\xdc!\xa2\xcf\xe4;\xad[\xbc\xdeO\xf5\xa5uckZZj填G,nx~\xaa(z\xf1]4[\x8e^X\b\xaf$\xd2\x18\x9f\xa5)\x9a\xf7\xbe>X\x1a\b\xeeK\xe4\xd26\xf7\x84\xfc\xe92\xd8\xfb\xb7\x94j\x05K^+\xd5\xdch\xb6\x1c\xbd\xb0\x10~x\"\r\x00\xc9a!<)\x894\x000\x11^Q\xa4\x01\x80\x87\xf0\x884@\x15,\x84'D\x1a\xa0\b\x16\xc2#\xd2\x00U\xb0\x10\x1e\x91\x06\xa8\x82\x85\xf0\x84H\x03\x14\xc1BxD\x1a\xa0\n\x16\xc2#\xd2\x00U\xb0\x10\x9e\x10i\x80\"X\b\x8fH\x03T\xc1BxD\x1a\xa0\n\x16\xc2\x13\"\rP\x04\v\xe13\x1di\xf4\r\xbf\x8d:K a!|\xa6#\r\xfe\"\x80 ,\x84\xa7\xccG\x9a\xb4\xfe\"\x80\xd1\v\v\xe1\x15D\x9a\xb4\xfe\"\x80\xd1\v\v\xe1\x11i\x80*X\bO\x884@\x11,\x84G\xa4\x01\xaa`!<\"\rP\x05\v\xe1\t\x91\x06(\x82\x85\xf0*\"͛_\r\xf8h\xa0O\xfeK\xeb\x95\x02F\x17,\x84W\x14i\x00\xe0!<\xa9\x884\x89g\xb7\x94_I\xf8\xfc\x90\xb8V\x1eqmz\xe0 ,\x84W\x10i\x0e\xee\xee;\xb2\xd9w\xe4%\xfd_\xef\xf1\xed136\n\x8f?bA\x1a͖\xcbEN\x93\xfd3_,+ʝ\xa3o\xd7\xffb\xceF\xfb\x19\x83\xe4\x13MLN6\a\xd8\xc2Bx\x05\x91慅7߬\xee6\xff\xed\xf9e\xf4\x84m9\xbb\xa2\x96\xa4\xd1ly\xc1k\\k\xd8\x06wᎥ\xb9\xd7\xe5h\xef\xb8m\xf6S\x06\x87\xff\xddZ\\\xd9xp\xb0\x10\x9e2\x1fizoҗ\x1f\a\xfeu_\x8cz\xb2C\xab\v\x0e\xaf\xba\xaf\x06\x87\xa9\x17\xfd\xc5\x11\xfe\x9a\xd8F\xfe.s\\\xaf\roC\x1a.\xe5=HX\b\xaf \xd2\x1cy\xa33\xfe\xf3\xb5\x85=\xc1\xe1)q*8\x1c\xb2\xf0gDkh\xdcUXk;g\xb0@\xf8A\xc2Bx\x05\x91fs\xf5\xf9\x81\xde8\xa7%\xfb\xf3\x9e6\a\xdbJ[?\x10\x1f\xec-}\xc5x\x14\x14>\\gI\x93\x03\xd7ٞN\xad\xfa\xed3\xe4\xd1o\xf5\xfc\xae\xadx\xa28\xbf\xea\x8c\x11\xe7w\x05\x02v\xff\x04s\xea\xaa\xc0\x0f\xa9\xcf\r\xbd\xa8\x02Xk2\xc7m[\x16\xdcBhh\xa9Ԍ\xe8ѼPS\x9c\xbf\b\x91f\x90\xb0\x10\x9e2\x1fi\x12\xfdE8!\xbc\xe6\xe0B\x8dxP\x94\x89E\x9f\x19\x8f\xc2E\u007f\xc1:K\xd2j\xbd:\xe5b#\xf5\x1c*Yv\x85\xae\xd4\xe7y\xf5̢\x89)M\x8de\xaeSf\x9c\x0f\x04\xec\x13\xdeF\xe1\xf1\x86*\x15\x0e\x89\xc3Q?6\xb2&\xb3\xe4yO\x89\xbe\x05\xcb\xd0R\xa9i\xed\xd1<\x93\xf7\xc0k-\x95\x02\xc2\x0f\x0e\x16\xc2+\x894\xf1\xff\"\xec\x15\x1f\x05\x87m\x9a\xd0\xda\x02\xe3\xa0\xf0\x96:K\xcf1}T+\x8c\x03P\xcf\x14\xfdf\xa9\x11T\xb4\xc9\xfa^\xb8\xa7\xb4\x9c\"\xbbr\xac\x91\x86.\x88\xe8S\x93\x115\x99\x13o\x10]/)\x8f\x18Z*5-=\x9a\xd3K{\xe4j\x10~p\xb0\x10^I\xa4\x89\xff\x17\xa1E|b\x0e\xae\xadҊE\xf1\xf8\xa7\xbe0\x1e\x852\xbc\xa5\xceR\x8f*\x8bǚgt.\x8c}\x9fn\xe5\xed\x97C\xed\x19y\xbbC\\K(|̹KkM\xa6q\xd4\xdc`l!4\xb4Vj\x86z4\xaf\x8b\x9d\xf2\xf9z\b?8X\bO\xceF\x9aw\x83fo\x9c\xb0\xe3\x94\xf8˶\"\xf3\xa4yPxk\x9d%\xf5\xccт{\xea\xca\xd5Ԗ\xdf/G\xe6A\xabW\x1cK |\xbb8D\x91\xc4\xd4dZ\xb6`\f-\x95\x9a\xe1\xed\xb6\x9b\xf9\v\a\xad\x83\x84\x85\xf0\x0eG\x9a\x9e\xd0Y\x96~\xe3,M\xbf\xf9\x1eTPxk\x9de\xd7\xf4\xf1\xc1\xc4C\xad\x13\xfa\xcdDC\x9aqd\xbaS\xdc\b\x88Yo#\xbcG\xeb\xa2H\"j2-[\b\r-\x95\x9aa\xe1\xbf\x10\r\xf2\xf9\xa5\x10~p\xb0\x10\xde\xe1HC\x8bJCo\xb3~\x96\xffYp\x18\x14\xdeRgym\x8aK\xee_[\xddry\u007fQk\xbe\x91hH+\xbe\xa5?|P.u=\xad\xcf}4Vx\xff\xe4\xaa\xe0\xf0\x93\x8d\x1d\xd1\xdb%\xadH\u007f9tMrG\f-\x95\x9a\x96\xbf\x1c\xe5%z\xee\xf9h<\x84\x1f\x1c,\x84'g#\r\x9d\xc9\xf9m\xf4\"K\xb3e\xb8\xce\xf2z\x99\xd8(O\xd3<a\xdaV7)\xff\xb61\xd0D\xe5\xe1\xfd\xe5\xf9\xf2з\xbc`\xe3\xf3\xe5bܮS\x81\xb34\xef\x06^J[dZ1\x99'\xe6\x18\xf7\xe1\xed\x9a\xe7yv\x96\x1a[\xb0\fC\x95\x9a\xd6\x1e\xcdS\xae\x12O}~\x8e\xfc\x11 }X\b\xefp\xa4\xd1w\xa2\xe3\xa3\x03\xb6\xa5\xd92\\gyb\\`i\x891\xe7#\xb1̜\xfc\xa0gq^q\x8dq\x02\xf2\x8c;7\xaf\xf2\x19!\x96\xdf\xca7f\x8e\xfb\xc0\x98\xe1\xcd}*\xb4\xe9\xd7\nv\x18\xf7\xe1\xedꖯ\xae\rn\xc12\fUjF\xf4h\x9e\xa9ʟ\xf8Ԯq\xa8\xd4\x1c\x14,\x84w:Ґ\u007f\x85\x16\xe7\xf3_\x89\xe8\xd2\x0e$\x9b\x12\xa0I\xab\xbd\x9dp\x82\xe5\xbd\xdax\x1f\xcc\x01\xc3\x02\v\xe1\xc9\xe1H#\xf7\xb6\xc5W)]\x9a&$\xb68ĵ\u008d\x91\x9fŌ\x01«\x82\x85\xf0\x8eG\x9aA\xe09\xe0w\xd7'\x9b\x942\x10^\x15,\x84w<ҤO\x8f\x98\xb2\xbc\xf0z\xb2Y)r\xc18&\x8d\x1e\x82L\xc0Bxr<Ҥ\x8f\xc7\xe5\xfe ٜT1\x8eI?\x89\x1e\x82L\xc0B\xf8\x91\x18i\xc0Ȅ\x85\xf0#0Ҁ\x11\n\v\xe1i\x04F\x1a02a!<\"\rP\x05\v\xe1\x11i\x80*X\bO\x884@\x11,\x84\xcft\xa4\x01 \b\v\xe13\x1di\x06Pj\x06\x02\xb0\x10\x9e2\x1ciҝ\x0fF/,\x84W\x10iҝ\x0fF),\x84W\x10iҚ\x0fF/,\x84'D\x1a\xa0\b\x16\xc2#\xd2\x00U\xb0\x10\x1e\x91\x06\xa8\x82\x85\xf0\x84H\x03\x14\xc1BxD\x1a\xa0\n\x16«\x884(5\x03\x12\x16\u0093\x9aH\x03\x00\x0f\xe1\x95D\x9a\xc4/\x0f\x94\x9ae\t,\x84W\x10ix\x96\x9a\xed/\xb0\\}2\f:\xcb2\a\v\xe1)\xf3\x91\x86g\xa9Y\xab\xcbv\u05cfβ\xcc\xc1Bx\x05\x91\x86i\xa9Y\xbc\vr\xe0jؙ\x82\x85\xf0\n\"\xcd\b+5\x83\U00019085\xf0\x94\xf9Hð\xd4\xecz\xae\x109\xb2\xce&ngY\xa8\xd4\xec\xd48!\xaa\xfc%B\xe4\xdf\"0$X\b\xaf \xd2$\x9a\xefP\xa9\x19\xb5{\xbd㍿\r\xf1:\xcbB\xa5f\xfeÞ\x9côk\xec\xae\x13\xd1\xdb\x00i\xc2Bx%\x91&\xfe|\x87J\xcd$\xb9\x810d\xdbYf-5\xf3/-\xbfZ2\xbc\xfd\xf5\xd9\t\v\xe1IE\xa4\x89?ߩR3\xb2\bo\xd7Yf-5\xa3\x9e\x87\x8b\xaap\xcdɡ\xc3Bx\x87#\x8dC\xa5f\x92\x90\xf0v\x9de\xd6R3\xf9\xb2\xb4\xdb\x00H\x13\x16\xc2;\x1ci\x1c*5\x93\xc4\bo\xed,\xb3\x96\x9aх\xc2\xfa\x92/l\xb6\x00҃\x85\xf0\xe4l\xa4q\xa8\xd4L\x12#\xbc\xb5\xb3\xccZj\xd6_^O\xcb\xdc\xc84C\x86\x85\xf0\x0eG\x1a\x87J\xcd\xfa\xdf\xf1z\xc7\xd7z\xbd7\xe2v\x96\x85J\xcdz\x0e-/\xb8@\x1dy+\x0e\xe1\xb4\xe4\x10a!\xbcÑơR\xb3\xa39\xe6\xc6v\xc4\xef,\v\x96\x9a\xb5\x19'\xf4W\b16\xd5V)\x10\a\x16\u0093Ñ\xc6\xf9R3\xa0\n\x16\xc2;\x1di\x9c/5\x03\xaa`!\xbc\xe3\x91f\x10\fo\xa9\x19P\x05\v\xe1\xc9\xe9H\x93>\xc3Zj\x06\xd4\xc1Bx\xe7#M\xfa\fg\xa9\x19P\a\v\xe1Gb\xa4\x01#\x13\x16\xc2\xd3ȋ4`\x84\xc2B\xf8\x91\x18i\xc0Ȅ\x85\xf0\x884@\x15,\x84'D\x1a\xa0\b\x16\xc2#\xd2\x00U\xb0\x10>ӑ\x06\x80 ,\x84\xa7\fG\x9a\x01\x94\x9a\x81\x00,\x84\xcft\xa4I\xf7\x05\x02F/,\x84W\x10i\xd2z\x81\x80\xd1\v\v\xe1)\xf3\x91&\xdd\x17\b\x18\xa5\xb0\x10\x1e\x91\x06\xa8\x82\x85\xf0\x884@\x15,\x84'D\x1a\xa0\b\x16\xc2#\xd2\x00U\xb0\x10\x1e\x91\x06\xa8\x82\x85\xf0\xa4 Ҡ\xd4\fHX\b\xaf(\xd2\x00\xc0Cx%\x91&\xf1n\x1d\xa5fY\x02\v\xe1)\xf3\x91\x86g\xa9YRⴞ\x81A\xc3Bx\x05\x91\x86g\xa9Y\x98\x03\xc7Ȏ8\xadg`а\x10^A\xa4aZj\x16\xe2\xd1%\xf6\xcbq\x01\xa7a\x86\x85\xf0\x94\xf9Hý\xd4l\xea\xe2\x84O\x83ႅ\xf0\n\"\r\xc3R3\xf2V\x96hEsJ\xfc\xc6\xc6$S\x88N\x8e\x13\xa2\xfeL\xcd\xc4\xdc\xca\xdb\xf1ZϮ\xd6L(^\xbdz\x82k\x10W\xc3\x04<\x84W\x10i\x12\xbd@\x1c*5;:vi\xcb\xfe\x9dE\xe26u\x1d\xf2\x96N\xd77\xfc\x81,\x94j,)\xcd+YU3\xf6\xd38\xadg\xfd\x0f\x166x\xc6\xe7\xee\xac|\x99@\xfa\xb0\x10\x9eTD\x9a\xf8/\x10\x87J\xcd\x1a\n\xe4\xb5X\x1b\xf2\x8d\x98n\x894S\x85\xfb\x06\xf9o\x98\x0fb[Ϛ\x84\xfeǦ!\x9c\xbc@Z\xb0\x10^I\xa4\x89\xff\x02q\xa8\xd4\xec\xb3\xe2\x89+v\x9e\xf0\x1b-Q\x11\xc2k\x9f\x86'Ŵ\x9eQ]>\xc9K\xd3\xe3\xec\xcd\xe0`!\xbcÑƩR\xb3\xeb;\x16O\x16E\x1bc\xf6\xf0S,sb;q^\x1e{U6$`\x0f?8X\bO\xceF\x1a\x87J\xcd\xda\xeb\xf4\x9fs\xbd1\xb7A>0\x84\xdfi\xecڧ.\xb2L\x8a\x15\xfeӜ\xcaOO\x96\x96\xe3|\xe5\xe0`!\xbcÑơR3\x8f0^;n\xa37ǭ\xaf|\xc5L=\x11g(c\x85?&\x8a\x84p'>\xab\x0f\xe2\xc2Bx\x87#\x8dC\xa5f\x1e\xe1\xaaom\xa9\x15Fo\x8eG\xdb\xd2\xe2v}F\xb7\x0f\x1b'l>\x91\xcb\xec[ώ\x8d\u07ff\xd7{\x01;\xf8A\xc2Bxr6\xd28Tj\xb6k\xba\xa7D+t\x9b=Q\xb7V\xe4\xe7No':i6\x9d\x19\u007f\x0e\xec[\xcf\x0eir\x996\x1d!~P\xb0\x10\xde\xe9H3\x92Jͮ\xb8\x96]\xb9}\xfb\xfa\xd1\x05\xf9\xe8\x1f\x19\f,\x84w:Ҍ\xa4R\xb3\x16\xf3\xbc=\xf9\x8bBG\xcf \rX\bONG\x9aA\xe0T\xa9ٱ\x1c3˜\xca9\x91d&\xb0\x83\x85\xf0\x8eG\x9a\xf4q\xac\xd4\xcc_\x9b\xbb\xac\xe9@Ӳ\xdce\xc3\xf6G#\xab`!\xbc\xf3\x91&}\x1c+5\xf3\xb7V\x16kŕ\xad\xf0}P\xb0\x10\x9eF`\xa4\x01#\x13\x16\u008f\xc0H\x03F(,\x84\x1f\x89\x91\x06\x8cLX\bO\x884@\x11,\x84G\xa4\x01\xaa`!<\"\rP\x05\v\xe1)Ñ\x06\x80 ,\x84\xcft\xa4\x19@\xa9\x19\b\xc0B\xf8LG\x1a\xfcE\x00AX\bO\x99\x8f4i\xfdE\x00\xa3\x17\x16\xc2+\x884i\xfdE\x00\xa3\x17\x16\xc2#\xd2\x00U\xb0\x10\x9e\x10i\x80\"X\b\x8fH\x03T\xc1BxD\x1a\xa0\n\x16\xc2\x13\"\rP\x04\v\xe1UD\x1a\x94\x9a\x01\t\v\xe1\x15E\x1a\x00x\bO*\"M:\xb3\xc1\xa8\x85\x85\xf0\n\"M\xdcR3\xef\xd8\xc0ŕƟ\x8c\xbb~\x98\x93s&\xe4M?Pv(y\xebY\xfc\xaa3\xe0$,\x84W\x10i▚\xdd:T8G^>o\x97H\xe1:/Ǵ\xaa\x96]\v\x8c֏d\xadg\xf1\xab\u0380\x93\xb0\x10\x9e2\x1fi\x12\x94\x9aM4.\x98\xf7Q*\xc2W\xba\xfdF#\x82\xb9\xefNR\x02\x05\xe19\xc2Bx\x05\x91&A\xa9\x99)|\xff\xb6\x1b\xf1&\x84\x99h\\z\xe9d\xa0\x8d\x00\u008f@X\b\xaf \xd2$(5\x9b\x18\xb8$jD\xa1\x18\xf9_\x99\xe2z\xb8\xc1O\xb7\x8b\xb4\xdf\x14\x17\x1fX\x91\xef\xee\"ZR(/\xfb\xe5\xdfk^\xeaݦ\xf5,\\T\xa6\v\xffT\xa8\x87\f\xb0\x81\x85\xf0\x94\xf9H\x93\xe0/\xc2\xc4ڞ\x9e\x97e?SD\xa1\xd8R\xad~o\xbdVKt O\xacr\x8b\t\x1b\x8b^&\xfa\xa4$\xa7\xd2s\xb8?\xb0\xa2M\xebY\xb8\xa8L^D{rcKт8?\x158\x03\v\xe1\x95D\x9a\xb8\u007f\x11&\xcas4\x85\xe68T(\xd6fDz㶰\x86\xf6\x8aVZ*\xff\x10\\{\xfeQM\xe4\aN\xbfش\x9eY\x8bʴ\xc2/\x88j\vb\u007f p\x10\x16\xc2+\x894q\xff\"L\xacjo_\x1a\x14>X(VkV:=\xa8\xef\xe2\v\x1b\xe9]\xd1EOט\xcf\xdc\xda_)\xf6\x1a#\x9b\xd63kQ\x99&_!\x81\xba'\xc0\x05\x16\u0093\xb3\x91F\x17\xf3\xd4Ns\x1c*\x14+7\x1bj\xaa\xf4\xa8S\xd8F\xed\xba\xb6u\xba\xf0\xedF\"\xf7\a\x9e\xb4k=\xb3\x14\x95Y\xfb\xcd\x00\x17X\b\xefp\xa4Y\x16\x1e\x87\n\xc5j'Ig\xfd\x13\x97F\b_\xb8\xc2x\xb2\xbeԸ\xb3i=\xb3\x16\x95Ax\x8e\xb0\x10\xde\xe1Hc\x15~q`\xb0W\xc8\xce\xf7F\x19^,\xc2\x17\x15_ӗ\xfa\x03/\v\x9b\xd63kQ\x19\x84\xe7\b\v\xe1\xc9\xc1Hs\xeb\x9d\xc29\x87\xccӌ\xd6B1\xaaɩk\xad\xcb\xd1%?\x95\xffrO\xa3v\xb2\xa7\xc6}\x81\x8aD\xa1\xa7\xadŝ\xfbQ\x9c\xd63KQ\x99\xb5\x87\f\xf0\x81\x85\xf0NF\x1a\xe3\xb34f\xb7\xb6\xb5P\x8c\xfc\xdb\xca\\e\r~\xf2\x17\tј'\\MḄGw\xd6\xff\xccU0O\xd6\xf5ٶ\x9eY\x8aʬ=d\x80\x0f,\x84w6Ҁl\x82\x85\xf0\xe4`\xa4\x01\xd9\x05\vᝌ4 \xbb`!<\"\rP\x05\v\xe1\t\x91\x06(\x82\x85\xf0\x884@\x15,\x84G\xa4\x01\xaa`!<!\xd2\x00E\xb0\x10\x1e\x91\x06\xa8\x82\x85\xf0\x884@\x15,\x84'D\x1a\xa0\b\x16\xc2g:\xd2P\xfa\xf3\xc1(\x85\x85\xf0\x99\x8e4\xe9\xce\a\xa3\x17\x16\xc2S\x86#M\xba\xf3\xc1腅\xf0\x884@\x15,\x84G\xa4\x01\xaa`!<!\xd2\x00E\xb0\x10\x1e\x91\x06\xa8\x82\x85\xf0\x884@\x15,\x84'D\x1a\xa0\b\x16\xc2#\xd2\x00U\xb0\x10^E\xa4A\xa9\x19\x90\xb0\x10\x9e\x14D\x9a\xb9(5\x03\xc4Dx%\x91&\xe5\x97\a\x18Ͱ\x10>ӑF\xe7\xf8\xbe\x81\xe3\u007f\xf0\x05\xfe\xbd\x9elv\xf2\xce2\vޱ\xa2\xdcO-B\x8cݟl\xaay\xad\xa7\xdad\xb3@\xe6`!<e>Ҭ\x99ֽ=\xf0\xef\xab7\x9eL\xb6B\xf2\xce2\v=\xfbE\xae\x97\xbaZ\xc4\xfe\x9edS\xe9\xf6;\x0f\x97y?K6\vd\x0e\x16\xc2+\x88\xc7O\xf3\xe3\x00\x00\x0e\xfdIDAT4\x83 I\x85S\x98.Q\xa3\xef\xb4?\x11]\xc9&J\xdc\xeed3@&a!\xbc\x82H3\b\xd2\x10~\xbf\xab\a\u008f\fX\bO\x19\x8e4\x89h\xd2C\xb5\x87<\xc2(_\r6\x99\x19\x04\x84_.rv\xd1'\x9a\x98\x1c\xd9oF\xfe]\xe5\xae\aV\xcb\x14\xd3%>\x99\xdab\n\x1f\xea7\x8b7\xd7*|h\xe9r\xa1\xedD\x01\x9a\x1aX\b\xefd\xa4\xe9\xf2\xe6\xd5_\xa1+\xf5\xf9\xde.K\x93\x99$ \xbc\xd10\xec\u007f\xb7V\x8b\xec7\xa3ڜ\x15{\xb7\x15L\xf5\x1b\xc2o\x9bc\n\x1f\xee7\x8b3\xd7*|h\xe9_\x1alj\x02\xcfo\xf3P\x80\x96yX\b\xefl\xa4\xa9]\xa2\xdf\xd4<A\x11Mfd\x894\xe1f\x03K\xbfY\xabq\x8d\xedvٛ\xa0\v\u007fu\xfcUCxK\xbf\x99\xfd\\\x8b\xf0֥Z\xbe\xbew\xafA\x01Z\xe6a!<9\x18i\xf4}qn\x0f\xf5\xb8\xbc\x14\xd1dF\xf6\u0087\xfb͖L꿭S\\k\bOs\xb6\x98\x19>\xdcof?\xd7\"\xbcu\xa9\xb6\x94\xd0\x16\xa2\x04\x16\xc2;\x19i\xf4\xb8=\xa1\x85Z\x8adܰ4\x99\x91\xbd\xf0\xe1\xf6\x9b\xb2@!\xc2<S\xf8\x96\x87\r\xe1-\xfdf\xf6s-\xc2[\x97\xa2\x1eG\x15,\x84w6\xd2Њy\xb4\xc0h+\xb34\x99Q\xb4\xf0\xf5Q\xc2\xd7L:fp\xd5\x14\xbeǵ_\no\xe97\xb3\x9f\x1b\x10\xbe\xab\xfeZ\xc4R\b\xaf\n\x16\u0093\xa3\x91\x86\x0e\x8f\xbf4\xfe\xb0\x1cX\x9a\xcc\xc8\"\xbc\xebi\xfdU\xf0h\x94\xf0m¨'\xae\xdfh\nOKk\xa4\xf0\x96~3\xfb\xb9\x01\xe1O\bo\xc4R\b\xaf\n\x16\xc2;\x1bi\xc8_\\Yl\x9e\x8a\f5\x99Y;˨\xbc`\xe3\xf3\xe5bܮS\xd6~3\xaa\x1b[\xd3\xd2R\xab\x1fx\xf6\xec\x17-]\xe4͕\u0087\xfb\xcd\xec\xe7\xde>\xfcp\x99Wg\x87.|x)\n\xd0\xd4\xc1Bx\x87#\rmѶ\x98\x83`\x93YDg\x19\x9dq\xe7\xe6U>#\xc42k\xbf\x99\xbe\xdfvOȟަ\x1f\xf4\x8e\x95\xe7\xf0\xfd\xe5\x85~K\xbf\xd9t\xfb\xb9\x81\xde4!r?\xb0,E\x01\x9a:X\bO\xceF\x1a\x90E\xb0\x10\xde\xe1H\x03\xb2\b\x16\xc2;\x1di@\xf6\xc0BxB\xa4\x01\x8a`!<\"\rP\x05\v\xe1\x11i\x80*X\bO\x884@\x11,\x84G\xa4\x01\xaa`!<\"\rP\x05\v\xe1\t\x91\x06(\x82\x85\xf0\x884@\x15,\x84G\xa4\x01\xaa`!<!\xd2\x00E\xb0\x10\x1e\x91\x06\xa8\x82\x85\xf0\x884@\x15,\x84'D\x1a\xa0\b\x16\xc2#\xd2\x00U\xb0\x10\x1e\x91\x06\xa8\x82\x85\xf0\x84H\x03\x14\xc1BxD\x1a\xa0\n\x16§\x1ci\x8e\x9f\xfd\xf0|g\xe4\x9cΏϞ?\x8b}=H\x11\x16\xc2S\xaa\x91\xc6\x17\x1a\x1d߇]<\x18\x04,\x84O9\xd2\x04\xe6\xe87\x1bf\x9eC\x86\a\xe9\xc3B\xf8\x94#Mx|\xf1\xbd\xf0\xde\x1e\x80\x94a!<\xa5\x1ai:\xa5\xf0\x03\x92s\xc7o\xca;\x9b\x95\x00H\x00\v\xe1Ӎ4}\x884`\x90\xb0\x10>\xe5H\x13\x8e1_\x9e\x8e\x9e\f@\n\xb0\x10\x9eR\x8d4\x92\x8bG\xf6\xed۷砼\xddw\xf08\x92<H\v\x16§\x1ci\xa4\xfb\u007fxlƴG\x1e\x996M\xdeTW_F\xb0\x01\xe9\xc0B\xf8\x94#\x8d\x91\xde+v\xbf\xbd\xef\xed\xf7\xce\x1f\xdc\xf7\xf6ۿ~\x04I\x1e\xa4\x05\v\xe1)\xe5H#\x85\x9f-cL\xe7A\xf9p{\xc59\x99\xebq\xb2\x06\xa4\n\v\xe1ӊ4\xf2\xfc\f\xd1}_;H8W\x03҆\x85\xf0iE\x9a\x17f|\xa8\x0f\xee\xbf\xe3\xa2~\xbb~\xe6\xd9\xe8u\x00H\x04\v\xe1)\x9dH\xf3\xdcc\x9dG\x1e\xff\xe5\xf7\xbf>\xed\xf1\xb5\x03\xdbg\\>\xbd\xa7\xef\xf4\x1e\xcb\xca\x1e\xa1\xb5\xe8w{]\xc2\x13\xb3\xbdh\x96\x8b\x9c\xa6ds\xc0肅\xf0iE\x9auմ\xe6\x8e;\xbe\xa6\xffw\xb7\xafyF\xf7\xeb\x15\xddoL;\x1b~Q\\\xadq\xc9\xda0wn\xcd\xd5\xc8-\x1d8F\xd1\x18%\xdb \xab`!|Z\x91\xe6\xb9\xc7>?\xfe\xec\xda\xff\xfb\xf5\xeag7\x0fl\x9fy\xf1\xdc\xc1\xbes\aoZV\xaa\x9b\xe3\xbaN\xd7r\xe7\xd4Em\xec\xd1%\x14\v\x84\xcf6X\bO\xe9D\x9a\x17f\xc87Y\uf2db\xe1\xebj\xdcM\xb4\xab\xb2&Z\xf8\xa9\x8bc\xa6B\xf8샅\xf0iE\x9a\r3?\xd6\a\xff\xfc\x8d\x83d\x9e\xa5\x89~\xaf\xb5\xae\xa6a\x01\xcd\xd9!\x85\xbf\xb1\xb8X+\xa9:\xa9/l\r\x94\xe7M1\xa6\x9cYT\xa4\x15ι\xa0\x8f\xb4\xa7V=઼@ [`!|Z\x91f\xc3\xec^}\xe03>K\x138\x0f\x1fA]\xcd\x05\xd7\x17\xe3/I\xe1[Ų\x03MU9\xedD]\x87\xbc\xa5ӽ^\xaf,\x8b\xa4\x03\xae)/\xee\xf7\bYU\xa9\x89ɍ-E\v\bd\v,\x84\xa7t\"͆Ƕ7\xefn>rz\xdf\xee\xe6\xe6'm\xdei\xad\xab\xa1\xb2e\x8f\x92\x14\xbe\xa7\xa9\x8b\xc8_6\xcfX\x1e\x8a4=%\x95\xb7\x88\xfa\x9b\xae\xe9c\xad\xf0\v\xa2\xda\x02\x02\xd9\x02\v\xe1ӊ4o̝9\xed\x11\x93i\xd5\vc?K\xa3\v\xff\xa2\xd8h\bOW\x1b*'\xe5\x892cyH\xf86q\"4Y[F\xa8|\xcf*X\b\x9fz\xa4ѹ|\xfc\xa0\xce\xdbo\xcb\xdb\xe36\xdf{҅\xbf\xfa\xd4\x15C\xf8\xf6\u0092\xa7[\xbc\xee(᷈\x9e\xd0d\xe3\xa0\x15\xc2g\x11,\x84\xa7\x94#M\n\xe8\xc2K\xa4\xf0\x93˥ڋ,\xc2\xef\xfc\x94h\xbf\b\x9f\x91\x87\xf0\xd9\x06\v\xe1S\x8f4)`\x11\xbed\x91>\xf0?l\n\xefv\x13]\x11M\xfa\x01l\xa1\xbb_\u007f\xbcb\x15A\xf8샅\xf0iE\x9a$|Q㾤\xdf]r\xd7|A\x1e\xb1\xb8\xe1\xf9\xa9\xa2\xe8\xc5wIj\xbd\xa5\xc5\xed\xfaL\x1f\x1d\x18\xff\xe0\x8e\xb6\x15b']\xf2j\xb5\xef\xfaO\xd4j\xdeKI\xb6\nF\v,\x84\xa7a\x8c4\x1e!\x9e\xd0\xef\x96\t\xe1!\xff\x96R\xad`\xc9k\xa5\x9a\xfc\xb0\xc1\xad\x15\xf9\xb9\xd3ۍ9\x1f-.\xce+o\x91\x9f\xa5\x11B{ߥ\xdf.O\xb8M0z`!\xfc\xb0F\x1a\x00\x12\xc0B\xf8\x94#\r\xec\aC\x84\x85\xf0\x94j\xa4\xe9L/\xcf\x03\x10\r\v\xe1S\x8e4i\x1e\xc0\x02\x10\r\v\xe1S\x8e4\x10\x1e\f\x11\x16\xc2S\xaa\x91\x06\u0083!\xc2B\xf8\x94#M7\x84\aC\x83\x85\xf0)G\x1a\x00\x86\b\v\xe1)\xd5H\x03\xc0\x10a!|ʑ\x06\x80!\xc2BxD\x1a\xa0\n\x16\xc2\x13\"\rP\x04\v\xe1\x11i\x80*X\b\x8fH\x03T\xc1BxB\xa4\x01\x8a`!<\"\rP\x05\v\xe1\x11i\x80*X\bO\x884@\x11,\x84G\xa4\x01\xaa`!<\"\rP\x05\v\xe1\t\x91\x06(\x82\x85\xf0\x884@\x15,\x84G\xa4\x01\xaa`!<!\xd2\x00E\xb0\x10\x1e\x91\x06\xa8\x82\x85\xf0\x89\"͛_\r\xf8h\xa0O\xfeî\x1e\f\x19\x16\xc2S\x82H3\xf7c\x9b'\x00\x18$,\x84O\x18i\xb0[\a\xc3\b\v\xe1\x13\x1c\x9c\x1e\xdf7p\xfc\x0f\xbe\xc0\xbf\xd7-O$-\x15N\xa7\xa1\x18d\r,\x84\xa7\xf8\x91fʹ\xee\xed\x81\u007f_\xbd\xf1\xa4幤\xa5\xc2\xe94\x14\x83\xac\x81\x85\xf0\x83;ߞ\xacc5\xad\x86b\x90%\xb0\x10~p\xe7ۓ\n\x9fNC1\xc8\x12X\bO\x83:\xdf\x1e.\x15\x0e\x17\x10\x13y+K\xb4\xa29%\xfe\x88\x86b\xf2\xef*w=\xb0\xba'\xb2\xa1غ\x1a\xc8\x12X\b?\xc8H\x13*\x15\x0e\x17\x10\xd3ѱK[\xf6\xef,\x12\xb7#\x1a\x8a\xa96g\xc5\xdem\x05S\xfd\x11\rŖ\xd5@\xb6\xc0B\xf8AF\x9aP\xa9\xb0\xa5\x80\xb8\xa1\u0dbc\xcd\xf7G4\x14\xb7\x8a]\xfa\xd2v\xd1(\xd7\v7\x14[{\x8bAv\xc0Bx\x1a\\\xa4\t\x97\n\x87\v\x88?+\x9e\xb8b\xe7\t\xbf\xac\xe9\xb34\x14/\x99\xd4\u007f[\xa7\xb8VN\x0egxko1\xc8\x0eX\b?\xc8H\x13\xaa\x9c\xb4\x16\x10_߱x\xb2(\xda\xe8\x8fh(.\v$wcg\x1e\x12>\xa2\xb7\x18d\a,\x84\x1fd\xa4\t\to) n\xaf\xd3U\xbfޘ\xdb\x10Q\xd8Z3阁qF>\xd4P\x1c\xd1[\f\xb2\x03\x16\xc2\xd3\xe0\"MHxK\x01\xb1G\xb4\xc9\xe7\xdc\xcb\"\x84o\x13ƻ\xb2\xf5\x1b\x8d\xe7\x82\r\xc5\x11\xbd\xc5 ;`!\xfc`\"\x8d\xb5T\xd8R@\xec\x11\xae\xfa֖Zq \xa2\xa1\x98\xea\xc6ִ\xe8K\xe5\xa1k\xb8\xa18\xa2\xb7\x18d\a,\x84\x1fL\xa4\xb1\x96\n[\n\x88wM\xf7\x94h\x85\xee\x03\x91\r\xc5\xfa>\xde=!\u007f\xba\xb1\xf3\x0f7\x14G\xf4\x16\x83쀅\xf04\xa8H\x03@\xfa\xb0\x10~0\x91\x06\x80\xc1\xc0B\xf8\xc1D\x1a\x00\x06\x03\v\xe1\t\x91\x06(\x82\x85\xf0\x884@\x15,\x84G\xa4\x01\xaa`!<!\xd2\x00E\xb0\x10\x1e\x91\x06\xa8\x82\x85\xf0\x884@\x15,\x84'D\x1a\xa0\b\x16\xc2#\xd2\x00U\xb0\x10\x1e\x91\x06\xa8\x82\x85\xf0\x84H\x03\x14\xc1BxD\x1a\xa0\n\x16\xc2#\xd2\x00U\xb0\x10\x9e\x10i\x80\"\xb8\b\x0f\x80\x12X\b\xaf\x87\xf7\xb7\xb7w\"Ã\xcc\xc3Bxdx\xa0\n\x16\xc2\x132<P\x04\v\xe1qZ\x12\xa8\x82\x85\xf0\x884@\x15,\x84'D\x1a\xa0\b\x16\xc2#\xd2\x00U\xb0\x10\x1e\x91\x06\xa8\x82\x85\xf0\x84H\x03\x14\xc1Bx4n\x03U\xb0\x10>\x10i\x00\xc88,\x84'4n\x03E\xb0\x10^\x8f4\aw\xf7\x1d\xd9\xec;\xf2\x92\xfe\xaf\xf7\xf8v\xeb\x93\xc7r\x8c\xf2\x8e\xd8\xee\xb1-\xe3\u007f+\xef\x92Vr\x03\x10\x86\x85\xf0\xfa\xce\xfd\x85\x857߬\xee6\xff\xed\xf9\xa5\xf5\xc9\xdb\xefx\x1b\xc4\x16\xef;\xfd\xd1k\x95iF\x95A\xd2Jn\x00°\x10^\xa7\xf7&}\xf9q\xe0_\xf7Ũ'\xdb\xc5;\xb1kt\xe5\xd4\xe4t\x19#\b\x0fR\x86\x85\xf0\xc6\x1bO\x9d\xf1\x9f\xb7\x15\xde+\x8e\x89\x03\xc6\b\u0083\x94a!\xbcq\x96\xe6\xfc@o\xbcӒ!\xe1\xc35\xdbD\x9eb*6M\xd7V<Q\x9c_u&z\x02\x00\xb1\xb0\x10\x9e\x92\xbc\xf1\x14\x14\xdeR\xb3M\xe4^D\x8bͮ\x1aMLij,s\x9d\x8a\x9a\x00@,,\x84O\xf6Y\x9a\xa0\xf0\x96\x9am\xf2\xbb\xb6\xd0\xcb.cW\xaeM\xee!\xea)-\x8f\x9c\x00\x80\r,\x84O\xf6Y\x9a\xa0\xf0\x96\x9am:)\x0e\xf5\x1c\x12'\xe5P{F\xde\xee\x10\xd7\"&\x00`\x03\v\xe1)\xc5Hc\xa9٦m\xc6\xd9\xf9mr\xa9yЪ\x1f\xc4FL\x00\xc0\x06\x16§\x1ai,5۴hJ{{\xfb\x14Y-L\xda*y\xbbS܈\x98\x00\x80\r,\x84O5\xd2Xj\xb6\xa9x\xb5~\xb3\xaaX>֊o\x11\xf5?莜\x00\x80\r,\x84\xa7D\x91&\xf0N\xeb\xe1~\xb2\xd4l\xf7\xb4\x89\xfa.\xea\xfa\x8dh\xbb%\xcf\xd2T\x1e\xde_\x9e\xff\x91u\x02\x00\xb6\xb0\x10>a\xa49\x11\xfe,M\xb8f{\xffX!\x9a\xa8E\x88\xb1\xfb\x89\x1e\xf4,\xce+\xae\x91=\xf3\xe1\t\x00\xd8\xc2B\xf8d\x91\x06\x80ႅ\xf0\x84o<\x01E\xb0\x10>\xd9Y\x1a\x00\x86\v\x16\xc2#\xd2\x00U\xb0\x10\x9e\x10i\x80\"X\b\x8fH\x03T\xc1BxD\x1a\xa0\n\x16\xc2\x13\"\rP\x04\v\xe1\x11i\x80*X\b\x8fH\x03T\xc1BxB\xa4\x01\x8a\x80\xf0 \xab`!<2<P\x05\v\xe1\x91\xe1\x81*X\bO\x884@\x11\xce\n\xbf\xc7\xd7\xd9\xeb\xeb\xeb\xd3\xff\x1d|\xb3S\xde\xf5Q_o\xaf\xaf7\xd9z\x00\f\x12g\x85?B>y\xa7g\x99M\xb3\xcf!Ҁ\xcc\xe3\xac\xf0\xbeШ\xf3\\x\f@\xc6pVxyb\xe6\xf8\xeeM\x1b\x9e[\xff\xec\xda\xf5ϭ\xdf\xf0zs7\xceՀL\xe2\xb0\xf0z\x8aٺp\xf6c\xb3fUϟ=k\xd6c\xd53.\"\u0600L\xe2\xbc\xf0\x1b\xa6\x1d9\u007f\xf6\xfcM\xba|\xf6\xfc\xf9g\xa7!Ƀ\x8c\xc2@\xf8\x8a\x9b\xfa`\xdfJ\xf9pkŹ\x81^\x94\x9a\x81\xcc\xe1\xbc\xf0/\xcc\xfcP\x1f\xfc莃\xfa\xa3\xe7f\x9eK\xb6\x06\x00C\xc1y\xe17\xcc<\xab\x0f\xee\xbfCޮ7\xc6\x00d\f\xe7\x85_?\xb7{\xf7}\xf7\xde\xfd\xb5\x1f\xdc\xf7\xf3\xbe7ft\x1e\xdc\xe0;\xbe9jV\x8b\xbc\x12\xd3\xc4\xe8+\xa4\xee/h%\x00\xd2\xc3y\xe1\xd7U\x0f\xac\xfd\xc6\xd7\xff\xee\x8eo|\xe3;\xbe\xe6\x19ݻ\xa3K\xcdt\xba\x0ey\xf3\x16\x9d\x8a^\xb7\xd5\xd5\x12\xbd\b\x80$8/\xfc\x86\x8a\x8b\x9dǏ\xdf\xfb\xf5\xed\xc7ߣ\x97f\x9e\xef>Oݗc'\x16\xad\x8e]\x86\x8bb\x83\xb4q^\xf8\x17f\x9c\xd6\a\xf7\xca\f?\xb0~V\xbc\fo'<\x00i\xe3\xbc\xf0\x1bf\xc9\x1d\xfa\xac\xefI\xed7͌wZ\xd2\x14\xde\xff\xca\x14\xd7\xc3\rr\xcf~=W\x88\x9cF\xb9l\xb9\xd0v\xaez\xc0Uy!v%\x00\xa2a |ŗ\xa1\x87\x9b+\xe2\xbd\xf1d\n\xbfT\xab\xdf[\xaf\xd5\xcaa\xbb\xd7;\xdeh\xfe\xf8K\xe38Q\xe0\xf9m\xde\x02\xdb\xf5\x00\x88\x80\x81\xf0\xf3\u05ec\u007fv\xdd\xd6ן{v\xdd\xfa\xf9\x8f\xc4\xfb\x1a\x88!|\x9b\xd1w`\xde\xea\xe4\x06\xfaY\xb5|}\xef^S`\xbb\x1e\x00\x118/\xfc\x9e'\xab\xe7Ξ]QQ1{\xf6\xdc'Wv&\x12\xbe\xd6蚧\ak\xcde!\xe1\x97\xea7\x1e\xcdv=\x00\"pXx\x9d\xde\xce\xcb:_\xf5~\xae\xdfv~\x15o\x96!|y\x951\xae*7\x97\x85\x84\x97\xf7\x10\x1e\xa4\x82\xf3\u0093\xf1!\xe1͏w\xc6\xf9`\xf0\xed\x0f\xe4A\xea\x04c\x0f?\xc9hh\x9d\xb8\xd4|\x06\u0083\xb4q^\xf8\x01\x9f\xaf\xdb\xe7{|\xda\x11_w\x9f\xcf&ϼ\"\xbcDW\x8d\x82ʽB\x9e\x97i\x14{\xcdg <H\x1b\xe7\x857\xe9\xee\x8c\xf7ŏ\x03bNˮ\xf2\t\x9f\xc9qMN]k]N\x8d>\xea\u007f\xc7\xeb\x1d_\xeb\xf5ޠK^\xad\xf6]\xff\x89Z\xcd{)\xce\x16\x00\b\xc1Bx\x1f\xd1\xf6'\xcfR\x9c/\xf9\xb5Lu\xe5W\xbdo\f\xfd\xdb\xca\\e\xc6y\xf8\xa3fՙ\xd8A\xcb\xf5[\xed}\x97~\xbb\xdc~}\x00°\x10\xbe\x97H\x8f4\x84\x8b\x15\x80\x8c\xc3BxJ\x14i\x00\x18FX\b\x8fK\xed\x01U\xb0\x10\x1e\x97\xda\x03\xaa`!<\xe1R{@\x11,\x84G\xa4\x01\xaa`!<\"\rP\x05\v\xe1\t\x91\x06(\x82\x85\xf0\x884@\x15,\x84G\xa4\x01\xaa`!<!\xd2\x00E@x\x90U\xb0\x10\x1e\x19\x1e\xa8\x82\x85\xf0\xc8\xf0@\x15,\x84'D\x1a\xa0\bg\x85G\xa9\x19P\xcc\xff\x0f\x19\x026\x1d6\x9ff\xc5\x00\x00\x00\x00IEND\xaeB`\x82",
+
+	"analysis/typeinfo-pkg.png": "\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x042\x00\x00\x03\xa2\b\x03\x00\x00\x00\xb5\xb6\a\xdf\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x03\x00PLTE!# #$\"$%#&(%()'*,),.,/0.231463685;<:>@=BDAGHF\x00f\x00JLI\x00j\x02\x03l\x04OQN\rp\nSUR\fr\x17VXU,`\xae7]\xad8^\xae\x16w\x1d[]Z8a\xaa:b\xab;b\xac<c\xad`a_=d\xae?e\xaf@f\xb0*{!bdaAg\xb2)}*Bh\xb3Ci\xb4egdEj\xb5higMj\xb0Fm\xb2/\x82/Ol\xb1Ho\xb4Pm\xb2Ip\xb5/\x858Jq\xb6molKr\xb7Ms\xb8Nt\xb9pro=\x87<Ou\xbaXv\xb6tvs@\x8b?Yx\xb8Zy\xb9@\x8dG]{\xbbxzwI\x8dH_}\xbdX\x80\xbf`~\xbeZ\x81\xc1|~{`\x81\xbbb\x80\xc0N\x92Mb\x83\xbdM\x95U\x80\x82\u007fd\x84\xbfW\x95Vf\x86\xc1h\x88\xc2Z\x98Y\x85\x87\x84i\x89\xc3j\x8a\xc4q\x8b\xc1^\x9d]\\\x9dc\x8a\x8c\x89s\x8e\xc3d\x9deu\x8fŎ\x90\x8dw\x91\xc7h\xa1hy\x93\xc9z\x94ʀ\x94Œ\x94\x91z\x97Ɓ\x95Ƃ\x96\xc7q\xa5r\x83\x97Ȗ\x98\x95\x84\x99\xca\u007f\x9cˆ\x9b̀\x9d͙\x9b\x98u\xaaw\x81\x9eΈ\x9d\u0383\xa0ψ\xa0\xcb\u007f\xabz\x9d\x9f\x9c\x8a\xa2̠\xa2\x9f\x8c\xa4\u0380\xb0\x84\x8d\xa5Ў\xa6ѣ\xa5\xa2\x82\xb2\x86\x8f\xa7Ҥ\xa6\xa3\x91\xa9Ԍ\xb4\x89\x98\xabє\xac֩\xab\xa8\x99\xacҚ\xadӍ\xb8\x93\x9b\xafԮ\xb0\xad\x9d\xb1֗\xba\x97\x9f\xb3ؠ\xb4٢\xb5ۛ\xbe\x9b\xb3\xb5\xb2\xa3\xb7ݣ\xbf\x9d\xa9\xb8٢\xc1\xa4\xaa\xbaڸ\xba\xb7\xa5\xbd۬\xbbۭ\xbcܦĨ\xae\xbdݯ\xbfߨǪ\xbd\xbf\xbc\xb1\xc0\xe1\xab\xc3\xe1\xb0Ǭ\xb2\xc1\xe2\xb6\xc1\xdc\xc0¿\xb7\xc2ݸ\xc3\u07b2\xc5\u07b9\xc4߳\xc7\xe0\xba\xc5\xe0\xb2ͷ\xc5\xc7Ļ\xc7\xe2\xbc\xc8\xe3\xb7\xca\xe3\xbbκ\xbe\xca\xe5\xb9\xcc\xe6\xc9\xcb\xc8\xc0\xcb\xe6\xc1\xcc\xe7\xc2\xcd\xe9\xbf\xcf\xe2\xc0ӿ\xbc\xd0\xe9\xcd\xcf\xcc\xc7\xcf\xe4\xc8\xd3\xc1\xc8\xd0\xe6\xca\xd1\xe7\xd1\xd3\xd0\xc8\xd7\xca\xcb\xd3\xe9\xc5\xd5\xe8\xce\xd5\xeb\xcc\xda\xce\xd5\xd7\xd4\xcf\xd7\xec\xd0\xd8\xed\xcb\xda\xee\xd5\xdb\xd0\xd4\xd9\xe9\xd6\xda\xea\xd9\xdb\xd8\xd7\xdb\xeb\xd2\xde\xec\xdc\xde\xda\xd9\xdd\xed\xd6\xe0\xdb\xd4\xe0\xee\xdb\xdf\xef\xde\xe0\xdd\xd5\xe1\xf0\xe0\xe2\xdf\xdd\xe1\xf2\xdf\xe3\xf3\xe3\xe5\xe1\xda\xe6\xf5\xe1\xe5\xf5\xde\xe7\xef\xe5\xe7\xe4\xe6\xe7\xf1\xe0\xe9\xf1\xe7\xe9\xe6\xe1\xea\xf2\xe2\xeb\xf3\xe3\xec\xf4\xe5\xee\xf6\xec\xec\xf7\xeb\xee\xea\xed\xed\xf8\xe7\xef\xf8\xe8\xf0\xf9\xf0\xf0\xfb\xed\xf2\xf5\xf0\xf2\xef\xee\xf3\xf6\xf4\xf2\xf6\xf2\xf4\xf1\xef\xf5\xf7\xf0\xf6\xf8\xf2\xf7\xf9\xf3\xf8\xfb\xf7\xf9\xf6\xf5\xfa\xfd\xfa\xfc\xf8\xfd\xfb\xff\xf7\xfd\xff\xf8\xfe\xff\xf9\xff\xff\xfe\xff\xfc\x8c\xab\xeb\xca\x00\x00 \x00IDATx^\xec\xbd\x0fpT\xd5\xdd\xff\u007fu\x8d\x80\x80\x80\x88r\x02\x99\x8d!\x85\x87\x80~ML%\xa0\x86\xca\x17j\x11\xed\xfc\x8c\xa8\x93<\x0fc\xa4\xa2\x8fm\x9c\xaf\xd16T\xa0\xea\x83X\x91g\x88\x98\x87>t(\x14\n\xa2և\xa1\x8c\xed<\x86\xe1\xa9y\x06\xa4)jU\bJ\xad\x04\x19\x89ЂR\xadB\x88$s~\xf7ܿ\xe7\xde=w\xef\x9eݻٽ\xbb\xef\x97#\xb9{\xf7s\xce\xf9\x9c\xb3{\xde{\xef\xb9w\xf7\xadP\x00\x00H\x18\xc5/\x00\x00\x00l \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t|$\xe3\x18\x00\x00p@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12\xc8H\xc6\a\xbf\xf7\xa8D\x8a\xdf6\xce\xf8?ђ\x8a;\x9ey\xdf/\x12\x00\x90u$.\x19\x9f\xb4\\\xb5Գ\x9a\x84\xd9\u007f\a1\x19\xd7\xe2\x17\f\x00\xc86\x12\x96\x8c\xdf\xcf$$u\xc9\xf8`\x06\xe1X\xe1\x17\x0e\x00\xc82\x12\x96\x8cz\x12\x84d,aJQRS?\xb7\x82mD\xff\xe0\x17\x0f\x00\xc8.\xfaY2&\xab\xb5,\xf8@\xdd8\xfc8ӌF\xbfx\x00@vѿ\x92\xb1\x9f\xe9\xc4\a\xfa\xf6lusF\xfcp\x00@\xb6\x91\xa0d4\x9a\xcb\x0f\xcf/P\xff\xb9Y\xdf\xf9[u\xb3X\x15\x80(!\x15\xc7\xf67M+.\x9b\xfb\xbcY`\u007fӍ\xe3\x8a+\xeb\xff\xcbٚ&\x19F\xcc\U000cd34dKD\xc1\x875-Yqm\xb4\xa2\x9e\xe9T\x9d\xbe\xf7\xad\xd1\xea\xf6[q\xa3?9\x06\x00H3Ғ\xc1tb\xf4~kg\xfd1]2~;Y\u007f\xbe\xfe\xb0\xf6ԆqF|\xeda\xbe\xb5O\xd8\x12Fq\xa3\xebb\xad+X\x13\x81\xc7\xd8\xe3\x9a\xff\"\xba(\xa9,e\x8f\xe3G\x1f\x03\x00\xa4\x1bi\xc98VE\xccK\x1d\x15D?dP%c\xc2D3\xe0^\xf6\xcc\xf3\xa3͇\xa4\xc6\xf1ٿT\xdfY1\xff\xb9\xb7\xac}\xee`&\x02\x13\xb4}\xab>\xb9V\xfdW\xbf\x16{\x83\xba\xb5&~\xf41\x00@\xbaIP2\xfe\xf0\xfc\xadꤼ\xf7\xf9\xe7\xf7k\xb3^;3\xf9ou\xe3*\xf6I\x1fe\x13\xb6l\xe9\xf3͕lC=a\xf8\xa0L\xfd\xfb\x9du\xbf}z\x82\xfa\xb7\x99o\xee\xf0\xcdք\xbf\xf1\x19\xfd\xf0!&\xf8\xb0\xf6t\xd1w\xa6\x16\uedcf-~ϔ\xe1\xb0O4\x00 \xdd$(\x19\xdc\xf2'[T\x18͎\x11\x9a\x88qɃI\xc6D\xb6g?ӌ\xdac\xc7V0E`b\xf2[5v\x9a\xa3\xbd\x0f\xe6[\x9aA*\xb4刘`M\x04Jԓ\x97\x9dj\x8dEFc\xec0\xe7\xff\xf9E\x03\x00ҍ\xbcd\x1c\xab!\xfa\x99\t;i\xd0V%\xa2\xd6S-\xeaV\xe9'Z\x84~\x9a\xf0\x1du\xeb\x0f\x8e\x06\x8f\xfd\xfe_\xad\x93\x98\xe8o\x8d\xea\x1c\xc1\x9a\b\xfc\xab\x11]\xabn?\xad\xee\x9bl4\x16?\x1a\x00\x90f\x92\x90\x8c_\xa8[\xb3\xf5S\x85\x1b\xb4\x1dL2\xfe[\xdbz\x8b\xcd߷\x8e1M\xa8kdLS\xb7~\xe1n\xf3\x93\xff^ZS\xa2iƵ\x9f\x1c\x8b\r\xd6D\xc0,\xf4<\xd1.\xc5\x1a\u007f\xfc\xa2\x01\x00i&\t\xc98<AӅ&kG\x94\x18\x97?\xf5\xf9\xfb{}y\xc1Bx[\xf8\xe1uS\xd9s\xffu,6X\xdb\xf3\xdff\x1c[c\xfdñ\xf9F=>\xd1\x00\x804\x93\x84d\x1c\xfbWm\xb2N3V\x19t\xc9\xf8\x83\xb6\xa5\xcdߝ\xaey\xcd\xdd\x00\xf6\x8b\xa5\x8d\xf5\xe6\xad\x1b\xfbK\xb4jb\x83\xb5=\u007f0\x8b\xb0[̗\x1c.1.\xb6\xfaE\x03\x00\xd2K2\x92\xc1.\x95\xdc\xfc\ab\xdd\t\xc1$C\x17\x02\xe3Ą\x89\x81\xeb&.\x1dv\xc7g\xbd\xf9\x80]6m:\x16\x1b|X\xafĀ\xad\xb6\xde\xf0\xbcU\xce'\x1a\x00\x90^\x92\x91\fv\x80Aء\x86\xf1\xedu&\x19\xffO\xdbb˟e\xfa\xca\xe4O\xb5\x1d\xff\xe5\x9c\xcc\xecd\xc6\xfc.\xda[\xac\xd8\nA\xb0K\x04\u0602\xe7͖P\xf8E\x03\x00\xd2J\u00921_?&\xd00n\xc8*1\xee\xecds?ʖ\x13>\x98\xaa\x1f\r\xb0\xaf\x9cMf\xe7\x11\xea\xf1H\xe9\xcd\xdc\xfd\x12\xecЄThG$\xbfg\a\x19d\xa7 X\x13\x01\xbb\xd0/\xf4\xc6*\xf5[\xc2\xfc\xa2\x01\x00i%a\xc9`G\x15\x13\x97\xfc+\xbb,z\xec\xadBm\x16\xcf7\x9e\xd2n\xe5*nZ\xb7\x82\xdd\x18J~k,S\xccx\xfe\xad\xe7\xd9ڥ\xe3>\xeez\xad`\xf9\xcds\xa7j\x1bs\x8f\t\x82]\"p\xb8L\v}\\\u007f\xe4\x17\r\x00H+\tKF\xb36q\x8d{9\xe7j\xdb\xe6\x9a\x02\x93\f\xfd\xa2)1\xceP\x9e#\x16\xe3\xfe\xc07\xf7\xfe\r\x84\xa3j\xbf(\xd8-\x02?d\x8fG\x9b\xe7\x1e~\xd1\x00\x80t\x92\xb0d\xbc\xaf߀\xa5\x9f\x9bh'\v\xe5\xe6\xb7G\xb4\xe5\xcf*}\x1a/\xd0OV\x9aM\t\xf9?\xbfu\xb6\xb7\xbfΞ\xf2s\r\x19p\x05\xbbE@;\x9b\x99k=\xf4\x89\x06\x00\xa4\x93\x84%\xe3\xd8\x1f\xea'G'\x1b\xdfng\x17=\xc9\x0f\xcdg\xb4\x8b\xac\x1f4M\x8dr_~\u007fkɌ\xb2\xa2\t7/\xfd\xe0\x98\x9b\xdf7~gr\xb4\xb8\xe2;?\xb4\xc5\xc4\x19\x1c#\x02\xec\xeb-\xeb\xec\x87>\xd1\x00\x804\x92\xb8d\xf0\xecd\xf3\xd4\xfa\n\xbb}_\x06\x00 \xc7IJ2>ak\x19\xf6\xd7\xcd \x19\x00\xe4\r\xf2\x92\xf1\x8b_<\xc7n\x95\xe0\xee\x03\x87d\x00\x907\xc8KF\xad\xbe\xf8Xa\xff\xdc\x16$\x03\x80\xbcA^2\xfeUS\x8cq\xdc7\xc1 \x19\x00\xe4\r\xf2\x92\xd129Z<\xad\x81\xbfE\x1b\x92\x01@\xde /\x19\x00\x80<\x06\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\xc0G2\x00\x00\x80\a\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90 e\xc9\xf8\xfcD\x17\x00 oHQ2\xbe\xf4\xab\x1f\x00\x90S\xa4&\x19P\f\x00\xf2\x8c\xd4$ïv\x00@\x8e\x91\x92d|\xeeW;\x00 \xc7HI2\xb0\xf2\t@\xbe\x91\x92d\xf8U\x0e\x00\xc85 \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\t\xd0\xe9\x17\x00@\xde\x00\xc9\xf0c\xef\x94A\xcax\xbf \x00\xf2\x05H\x86\x1fC\x87>\xbcr\xb7_\x10\x00\xf9BVH\xc6\xf6\xb1\x03\a\x8cZ}\xf1Z\xbf\xb8L\xb0]Y\xe9\x17\x02@\x1e\x11\xb0d\xac\xde\x14\xbbϗM\x91+\x9e\\<^Q\x9e\xf0\v\x94F&\x1d\x8f\xd8MJV*\x19\x00\x19\"`\xc9\x189)v\x9f/c/g\xffNI\x83dȤ\xe3\x11\v\xc9\x00\x80'`\xc9\x18.1G-\x86\xdc\xc6\xfeݮ<\xe9\x17(\x8dL:\x1e\xb1\x90\f\x00x\x82\x94\x8c\xe5\x8a\xcep}\xf3\xb6\xaey\xea\xbfOLWο\xff\xba\xc1\x03\xafxU\x8bytd\xc1\xd0Y\x1d\xcer\x93.ڮ\x15\xef\xe0\x03^:_\xad\xe1\xd5+\x87\x14\x8c\xed|B\xadf\x9e^\x998\xc0Q\xdbڱ\x83#\x03\xc7\x0ev\xa4\xc3\xc5NW\xce[\xdc\xf5ZD\x19\xaa\x05\xbf6~`d\xd0\xd8\xdd|\xac\x8bՐ\f\x008\x82\x94\x8c\x8e\xb5\xab\x87\x8eZ\xbdz\xf5\xabls\xf0u{\xbb\xf6\xde5`m\xc7\xf6\xc5\xe7+\x83\xe7\xcd\x1b\\\xc0ta\xcayӗ\xdf?p\xb8s\x92\xef\x1e|\xde\xd8yk\xf5}V\xc0_\x9eX<x腃g]\xa9\xec\xeeX;\xe06\xa32q\x00_\xd9&eʓ+\x1f\x1e\xa8t\xf2\xe9p\xb1\xbbWG\xeeRueJ\x84\x05\xaf.\x18~\xcfʻ\x94{\xf8X\x9eν\xabG\x0ep\t\x1c\x00yM\x90\x92\xd1\xc5\x1f\xdd\xdf\xc5>\xb0\xa7La\x9b\x91!\xea\xac\xeb\x18<\x92}\xf0?\xda\xc5f\xf5bg\xa9\x8ey##\xca\x00v\b\xe1\b\x18\xae\\\xce\n\xb2zX\xb5WN\xf1\x0e\xb0yp Ӟ\xfb\ah\x0f\xb8\x93\r;\x96IF\xd7]L2\xfe2\x98\x1d\xa1t>\xd1ኵ\x18\xaf\x1ex,\x8f\xdd\r@\xfe\x926\xc9حl\xef\xea\xbcP\xbb@\x19\xd1\xd6*\xeeW:\xba&\r\xe9d\f\x9e\x12S\xb0s\xe5X69\x1d\x01\xc3#\xe6\xf1\xc3ꂎ\xae?\x17\xac\xee\xf2\f\xb0\xd9}ѐ\xe9\x0f\xbfdܰ\xc9K\x86\x15kK\xc6r\xe5%\xbb\xa0H2v\xaf|p\xe8@\x1ce\x00`\x936\xc9\xe8\x1a;\xabk\xe5\x00m\xe6js\xb4k\xb5\xb2I\xfd\xa8\xd7q\xdeM\xb9I\x9f\xcc#\xaf\xe8r\x06\f\xb7V\x16:\a>ٵ\\;|\xf0\b\xe0\xe8xp\xd2Pe\xd0=\xda6/\x19V\xac-\x19\xf7+\u007f\xb1\xcby,\u007f\xb2\xb4\x01\x00&鐌\x875\tP\xa7\xb8~^\xd2\x15\x99\xc5\xfe}X=ʸr\xc8&\x8dw\x1d\x85.\x9a\xae\xfd\xb9mH\x973`\xb8\xad,\xd3\xc7w\x8dע\xbc\x02,6\xcdQ\xff\xe9X\\\xf0\xa0\x16`\xa7c\xc7j\x92q\x1b\x93\x8c\x951G\x19\x0f\xc7\x1c\xb6\xe0\x8a\t\x00<\x01KƨQ]]{\xf5\x1b,:\a.\x1f\xb8Z\xdb\x19\x19\xc4V\x11\x86\x8cbsT{\xea\xb6y\x8eB\x03\a\xeb\x8b\t\xe3]\x01\xdc\xe7\xfe\xda\xc8\xee\x886u\xbd\x02,\xee\xd2\xef\xd6\x1cu\x9d\xf6\xaf\x9d\x8e\x1d[\xa0\x8aJ\xe7H&\x19\x1d\x17\x8dbG.\xd3g\xb9by \x19\x00\xf0\x04,\x19wE\xeeY~y\x81\xfeQ=g\x88~^\xd2\x15Q\x86?\xf1\xf0\x90\x01\xaf\xb1}ʤ'\x96Oq-\u007f\x0eT.\xbak哗\x17\xbc\xca\at\xea\xd70^3b.\x1a{\x91\xbe\xe1\x15`r\x97Rp\xd7\xf2'\xa7(\x9aZ\x99\xe98bG\r\x9c7o\xa4r\xfe\xa3\xdbճ\x8e\v.~p\xf9t\xe5a>\xd6\x05$\x03\x00\x9e\x80%\xa3s\xfa\xc0\x82Q\xc6\xc9\xff\xab\xcau\xfaFd֔\x01\x17]\xa9Oƕ\x97\x0f\x1c0\xca\xf5\xad\x8d\x91\x0f\xdf6\xb4\xc0\xbcq\xc3\fx\xe9<m\xcdb\xac\x11s\u007f\xe4\x1ec\xcb#\xc0\xe4\xd1Q\xf3\x06G.\x1a\xa5\x1fߘ\xe98b_\x1dUp\xe1\xd8\xdb\x14\x85\x9d\xe8\xbc:i\xf0\x85#\x9ftĺ\xd8{\xfe\xa4\x97\xf6\xe2\xdb\xef\x00\x18\x04,\x19<\x1d\x11}\xde\x1a˟ae\xf9P\xf7r-\x00yL\x1a%㉁Ƈs\xb8%C=\xd0xi\xaf_\b\x00\xf9B\xba$c\xde\xea\xae\xcbM\xa5\b\xbbd\x00\x00,\xd2$\x19\u007fV\x86O\xbfH\xbf\aj\xf7\xea\xc8\x14\xac \x02\x90#\xa4I2\xba\xee*\xb8\xdc\xf8\xbe\xc6tEQ\"\xee\xeb\x1a\x00\x80p\x92.\xc9\x00\x00\xe4$\x90\f\x00\x80\x04\x90\f\x00\x80\x04\x90\f\x00\x80\x04\x90\f\x00\x80\x04\x90\f\x00\x80\x04\x90\f\x00\x80\x04\x90\f\x00\x80\x04\x99\x96\x8c;\xef\x14m\x02\x00\xb2\x94\fK\xc6\xff\x0e\xfb\x9e`3E~y\xd9\u007f\xfa\x85X\xbc\xf7ϗ\x8d\xf8\xbf\xfa\xd7\xe7\xccbw\x0e\x1b6\xec\x92\xd7\xe3\x94\xf1\xe6\xf5\x11\xc3\xfe\xc9/&3\b3\x13t\x9e\xc35\x0e\xd9\xdb7ЯdX2n\x1f\xf1'\xc1f\xa2\xfc\xeaw\xc2\xdd?\xbf\xe4Y\xe1~\x11ߺ\xec\xa9;/yO\xdb4\x8b\xfdq˖\xa7\x86m1\x9e\xf7h\u008b\xdf\xdc9\xc2/$\xbdx\xe6+\xcaL\xd0y\x0e\xc78teA\xdf@V\x90Y\xc9x}\xd8݂̈́\xb9\xfa\xbb~\x11~\xbc7\xecߺ\xba\xb8\xdf\f6\xf8\x8d5Ud\x9bx$\xc3\xd3\xca;\xdf\xd8\xcc<:\xcf\xf1\x1b^22\xde7\x90\x15dV2\ued0f,\xee\x94?Ȑ\x9eϱ\xbc>Lx\x0e\x93\x1f\x92\xe1\xd1y\x0eH\x06\x88!\xa3\x92\xf1\xfa\x88\xbb\x05\x9b\xf6\xd3\u07fdl\xc4e\xffWS\x92\xa7\xae\xbe\xe4\xea\xa7Կ\xff2l\xc4Sw\u007f\xe3\x92o\xfd\xb1\xab\xeb?\x87\xe9\\\xad\xee\xee\xf8\xee\x98\x11c\xbe\xad\x1d\x93\xbfw\x89\xbaO;\xc8\xe6b\xbb\xba\xb6|k\x8cZ\xd7\x18G\xfd\x9d\x97\xe95\xdc\xed(\xc60\xa6\n\xdfDW׳\xd7_\xf2\x8d\xef\xa9\x1fʿ\x1b1l\xd8\x0f^\xbf}̈our{\xbb\xba\xfet\xfb\x98K\xbf\x1b{\xf0n\xa6\xee,f\xf2/\xacU}\x99\xc0\x91\xafU\xef\xff\xa8ž\xdd5fذK;Հ\u007f\xbbs̥\xdf~ݫ^q\xbe\xe2\xcc<;o\x17\xe3$\x83\xabA4\x92 \x8fȨd\xdc9⏂M\x93_]r\xf5\x8f\u007f\xf9Ȱ\x9fh\xcf\xfe\xe0\xe7?\x18q{W\xd7\xff>;b\xd8e\x8f\xfc\xe4\x12\xf5\xb3\xf4\xcf[\xb6|\xe3\xfa-[\xb6\xbc\xae>\xff\xf3aw\xfe\xea\xd9o\x0f\xfb\r+\xf6\xbb-[F<\xc26\xb8خ\xdf\r\xbb\xfd\xd9_>u\xd90\xe7\x8fx\xfen˳\xc3\x1eٲ\xe5O\x8eb\fc\xaa\xf0Mt\xdd9\xec\xee\x9f\xff\xdbeWwvu>\xfb\xec\x98o\\2\xe6\xeeۇ\xfd\x91\xdb\xdb\xf5\xfa\xa5\xdfx\xea?\xbf5\xcc-\x19V\xea\x8eb\x16\u007f\xd2ZՖ\t\xf8|\xb9\xd6~\xf3\x88گ\u007f\x1f\xf6\xecﴀ1?~d\xcc%\xff\xe3Q\xaf8_\x8f\xcc<:o\x17\xeb\xb2%\x83\xabA<\x92 \u007fȤd\xfcq\xc4?\v6M:ǰ\x8f\xe3\xceg\xdf\xeb\xea\xfa\xe5\xb0_v\xb1\u007f\u007f\xae\xfe;\xe2Ru\xc6\xdd~\x99\x16b\x1d\x85\xff\xe5ٿ\xf0\x0fͷ\xbf\x1d\xfb\xd4e\xec-\xfeԥ].\x1c\xc7\xe61\x92\xd1\xc5\xd5\xf9\xf3a\xff\xae=\xa1}\x18_=\xec[\xba[#\xb7\xf7\xfao\xa89t^횘|\xeav1\x1e\xadU\xfd\x98\xdf\xce\xd7\xd1ڝ\xdf|ȍ\xf5\xd81j\xe1\xf7\xc6|ӻ^Q\xbe\xe2\xccĝw4l\x8d\x03W\x83\xd7H\x82|!\x93\x92\xf1/#^\x17l\x9a\xfc|\x98\xb5\xf8\u007f\xa7~u\xef\x9f؍\x1b#\xd8?\xc6Y\xb5}\xe2\xfe\xdeS\xdf\x1as\xa9q@\xceI\x86\x15\xfb\xc71c\xfe\xe5\xa9\xdfu\xc5|4&.\x19\xdf\x1d\xa39;\x8e\xd1n\x1e\xb9\xda<&\xb2\xf7\xbe7\x8c\x9d%t\xfd\xc051\xf9\xd4\xedb<\xbcdX\xf9:Z\xeb\xbc\xfa\xb2o\x1b\xb1\xdau视\xbd\xe7Y\xaf _\x8f\xccĝw4l\x8e\x03_\x83\xd7H\x82|!\x83\x92\xf1\xa7\x11w\n6-~b\x1f\xfb^\xafϘo\xab\x9f\xae\xfc\f\xb3\xe7\xc7o.\x1b\xf3\xbd\xff\xd8r}\x8cdر\xef=\xf5\xdd\u007f\x1avُ\xbb\\$.\x19W\x1b\xeb\x04\xda㫯\x8e\xd9\xfb;\xbd\x88{\x89\x90O\xdd.\xc6\xc3K\x86\xb5\xe9h\xad\xebY3\x1d=\xc3-\xaa\x98z\xd5+\xc8\xd7#3q\xe7\x9d\r\x1b\xe3\xe0\xa8\xc1c$A\xbe\x90Aɸ{\xd8\xeb\x82M\x8b_qG\x19\xfab\x9b\xf6\xd1\x17#\x19O\xa9\x9f\xb0\xff\xf4Mvb\xf2]o\xc9\xf8\x1d\xfbx~\xef\xd9\x11Ou9IL2X\x13\xb7\x8f\xf9\x9d\xc6{\xd6^\x86\xbd\xd7\xf8$v/\u007f\xf2\xa9\x8b/gh\xad\xfe\xc0%\x19\x8e\xd6\xfet\xd9\x0f\xc6\xe8wO\xe8k\xc4O\r\xeb\xf0\xacW\x90\xafGf\xe2\xce;\x1av\x1de\xdc\x19o$A\xbe\x909\xc9\xf09\xc8\xe8\xfa\xcbe׳Ì\xbb\xeff\xe7(\xec\xd4\xfaY}-\x83\x93\x8c\xeb\xafW˲\xe7ư\x89\xd2y\xb5\xb7d<\xa2\x9d\xfaw]\xef^1\xf1\x95\f\xab\x89_\xea\xa7\xf7?\xd0>^\xad9\xca\xed\xfd&\x9b֯\x8fpML>u\xb1d\\\xa2\xce\xc1\xceo\xba$\x83o\xad\xf3\x9b?\xe8\xbaS\xbf\xcc2\xe22U\x1a\xff<\xe6z\xefzE\xf9\x8a3\x13w\xde\xd1Mk\x1c\xb8\x1a\xbcF\x12\xe4\v\x99\x93\x8c\xef\xd9G\x16\xdc&ǯF\xfc\xd3S?\xbf[\xfb\x80\xbb}\xd8\xf7~\xfe\xbda\xb7k\x17\x18\xee\xfcM\xd7\xef\xee\x1c\xa1\xad\xf4?2\xe2'\xff\xf1\xadK\xfe\xc8\xde\xc7\xdf}\xea\xc7W\xab\x87˿\xe9\xeaܲE\x8dٲ\xa5\xc3\x11\xfbȰK\x1e\xf9\xf9\u007f\xdc9\xecW\x8e\x16\xf4\x8b\x06\xdau\x16\xbb\x98~\xd7\xe3O\xb6l\xd1\xd6\a\xac&\xd4$\xff\xbfg\xd5\x1a\x9e\xed\xea\xfc\x8dv]\xe2u\xad\nko\xd7\xff\\2\xe6\x91\x1f\\:lĿ\xff\x8f\xa3\r+uG1\x8e\xeb/\xfb\xf1\x8f\xbfɊ9\xfaf\xb7\xb6\xe5\x9f/\xfbc\xd7\xeb\x97\u07bdE\x15\x8d\x11î~\xf6\xa9o\\\xfa\xbaw\xbd\x82|=2\x13w\x9e+ƍ\x03W\x83x$A\xfe\x901\xc9\xf8\xd3%\xb7\v6\x1d\xbc\xfe\xdd1\x97|\xf3?\xb4\xcd\u007f3nB\xf8g\xf54{\xc4\xff\xb0\xdb\bا\\\xe7ݗ\x8e\xb8\x9e\xbd\xe9;\u007f\xf2\x8d\x11\x97}\xf7\xa9o\x8c\xb8^=\xef\xd6y\xca\x11\xfb\xec\xf5\x8f\x8c\x19q\xd9\xf5\xce\xf7y\xe7\xa5Z\xa4\xb6\xf2j\x17Ӿ[a\x9d\xce[M\xa8\x1f\xc0\xd7_v\xe9\xf5?\xb7B\x8d\x15Is\xaf\x9a\xee\xb7/\x1d\xf3\xbd\u007f\x1f1\xcc\xf5\xf9k\xa6\xee,f\xf3\xfa\xf5#.\xf9\xd6\x0f\xd4$\x9d}3\xeb\xfd\xe50v\xef\xc4\xdd꿿b˟w^:\xe6\xf6?ũW\x90\xaf83\x8f\xces\xc5\xf8q\xb0k\x10\x8e$\xc8#2&\x19?\x18\xf6\xbf\x82M\x10\x17\xfb\xd4\t\x80\f\x911\xc9\xc0\xb7ޓ\x00\x92\x012N\xc6$\x03$\x01$\x03d\x1cHFx\xd0\xd7G\x01\xc8(\x90\x8c\xf0\xf0\xcf\xe6r%\x00\x99\x03\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90 Pɘ\xa4\f\x9c\xb2]\xd4\n\x00 G\bT2v\xaf~t\xe8\xc0\x0eQ3\x00\x80\xdc P\xc9PY\xad\xbc$\xd8\v\x00\xc8\x11\x82\x96\x8cM\xcaZ\xc1^\x00@\x8e\x00\xc9\x00\x00H\x00\xc9\x00\x00H\x10\xb4dlWV\v\xf6\x02\x00r\x84\xa0%\xa3s\xe0ȵ\xbb\xe1\x8b\x03@\xae\x12\xb4dt\xadT\x14\xe5\n\xd1\x13\x00\x80\x1c h\xc9\xe8\x188\xe4\xfeկ\t\x9e\x00\x00\xe4\x02AK\xc6&e\xa5`/\x00 G\b^2p\xc5\x04\x80\x1c\x06\x92\x01\x00\x90 h\xc9X\v\xc9\x00 \x97\tT2:wo\x9a\x14\xd9-j\x06\x00\x90\x1b\x04*\x19\xe3\x15e\xf0rQ+\x00\x80\x1c!P\xc9\xd8\xfb\x12\x0e1\x00\xc8m\x02\x95\f\x00@\xae\x03\xc9\x00\x00H\x00\xc9\x00\x00H\x00\xc9\x00\x00H\x00\xc9\x00\x00H\x00\xc9\x00\x00H\x00\xc9\x00\x00H\x00\xc9\x00\x00H\x00\xc9\x00\x00H\x00\xc9\x00\x00H\x00\xc9\x00\x00H\x00\xc9\x00\x00H\x00\xc9\x00\x00H\x00\xc9\x00\x00H\x90\x92d\x9c\xf0\xab\x1d\x00\x90c\xa4$\x19\x9f\xfb\xd5\x0e\x00\xc81R\x92\f\x9c\x99\x00\x90o\xa4&\x19_\xfaU\x0f\x00\xc8-R\x93\fh\x06\x00yF\x8a\x92A\xe9\xe7X\x03\x05 \x8fHY2\x00\x00\xf9\x04$\x03\x00 \x01$\x03\x00 \x01$\x03\x00 \x01$\x03\x00 \x01$\x03\x00 \x01$\x03\x00 \x01$\x03\x00 \x01$\x03\x00 \x01$\x03\x00 \x01$\x03\x00 \x01$\x03\x00 \x01$\x03\x00 \x01$\x03\x00 \x01$\x03\x00 \x01$\x03\x00 \x01$\x03\x00 \x01$\x03\x00 \x01$\x03\x00 \x01$\x03\x00 \x01$\x03\x00 \x01$\x03\x00 \x01$\x03\x00 \x01$\x03\x00 \x01$\x03\x00 \x01$\x03\x00 \x01$\x03\x00 \x01$\x03\x00 \x01$\x03\x00 \x01$\x03\x00 \x01$\x03\x00 \x01$\x03\x00 \x01$\x03\x00 Aʒ\xb1\xf6\xca\xc1\x91\x01\x17߶\xd7/.\xe3t\x9e\xf5\x8b\xf0\xa0S1\xb8`Ȕ\xddlG\x87\xf182\xf8\xcaMVм\xe1\x05\x91\x8bƯu\x95\r\xcd\xe8\x00\x90 )J\xc6\xd9\xf1\xc6\xf49\xff~\xbf\xd0\f\xf3`\xc1\xe7~!\x1e\xa8\x92Q0@\xe5B\xd6\xcf\xd5Ԗ\f\xc6<=\xe6ш\xf1x,\xdfJxF\a\x80DIQ2\xe6(\x05\x0f\xbe\xfby\xe7K\xea\xdcX\xe9\x17\x9bQ\xce*J\n\x92ѡm|\xbd}\xa8\u0084G\x95\x8c\xbd\x9f\xabt\xbd:VQ^e\xcf\xccR\x94\xf1/u}\xb9\xf7\xae\x882\xeak\xbbdhF\a\x80\x84IM2>\x8f(ơ\xf8\x14eH\xfc\xd0\f\x13\x84d\xa8b\x11Q\x9e\xd0$\xa3S\u007f|v\x882E\xfd\xb3ZQ\x16\xeb;^R\x94G\xad\x82\xe1\x19\x1d\x00\x12&5\xc9xM\x89\x18\x1f\xaa{\xadi\x94\x9d\x04#\x19t\xa4r\x1b/\x19\xf4\x1ee\xb0Z\xf7 e\xba\x190\x9d\x13\x87\xf0\x8c\x0e\x00\t\x93\x9ad\xec\xb5g\xd3\xea\xed_\xb2?\x9d\xb3\x86D\x06\x8e\u007f\x89m>\xaa<\xfcҐ\x82\x91s\x94\xf1z\xc4u\xca]\xc2\x00\xb3\x06\xfb!\x17\xb3X\xb9\xe7\xdd\xf1\x03.\x1c\xb9\xdc3\x82vL\x1f\x1c\x190\xeaQ}u\xd3Q\xf4\xfe\x13\xb3\x06G\x86\xdcv\x82\x9d\"0v\xbb\x82\r\xd6N\xba(R0\xf4\xb6.W\x19\x13^2\x86+s\x1c\x92\xf1\x84r\xa1Z^Q\xfeb\x06t\xdc\xff\xaaU0\xd0\xd1\x01 ;HM2\xe8\x10e\xe8Z\xee䝾T\xa0D\x86\x0f\xd1W\x05\x1fU\xe6\\\xa0(\x05\xef*\x11\xed\xf3\xfd\xec\x85\xca^a\x809}\xad\x87|\xccbeRAd\xec\xa8\xf3\x94\xeb\xbc\"\xf6^\xa8\f\x18>TQƺ\xdb_\xac̺H\xb9p\xa0\xa2\f=K\x97OR\x94\xf1Wv:\x83\r\xa6+\xcaE\xc3\a\xa9\xff\x9cp\x961\xe1$c\xb7\xa2,wH\xc6]\xcaPJoc\xff\x88\brt\x00\xc8\x0eR\x94\x8c\xed\x11E\x190\xfe\xd1\xdd\xc6\xc3\xce\v\x959\xea\xc7\xe9\xf6\x01l\xb9\xefQ\xe5\xbc!\xab7=\xa9\x1e\xcck\x87\b\xab\x95\xe1\x1e\x01\x06\xe6CG\xccbE\x19\xf2g\xf5\x18\u007f\x00\xabD\x181^\xb9M\x9d\x96\xbb\a\xb0u\x03wѡ\xdb\xd5c\x80\x88\xf2\xa4ub\xc2\a\x1blR\nا\xfa\xf6\x02\xe5AW\x19\xb3S\x86d\x9c\xed\\>H\x19r\x96\x97\x8c\x13\x83\x94Y\x94^\xa1-h\b\brt\x00\xc8\x0eR\x94\f\xda1V;\xe4\x1f4\x87\x1d֫\xc7\xffWh{W\xb2\xcf\xddG\x15E\xbb\x1f\xe1\t\xfd3\xfdJ\xe5a\x8f\x00\x03\xf3\xa1#f\xb1\xb1s%[#\x10F\fV\xb4)\xf9\xf0\x95kc\x8bjS}:[i0$\x83\x0f6\x98\xa3\x9d\x11\xb0\xbf\xd3]e\f\xac\xfb2T\x86\xb0gU\xc9\xd8}B\xa5c\xe5\xc5J\xe4]\xb6\xc01\x87\x8a\tpt\x00\xc8\x0eR\x95\fuF=q\xa5z \xaf\\\xc8\xeej\x1a\xacݷ\xa0N\xd0\xf3ԙ\xf7\xa8\xb1\x12x\"r\xde\tv\xf9\xe0\xbc.\x8f\x00\x03\xf3\xa1#f\xb12J\u007f\x10Q\xde\x15G\x8cUFn7\x8f\xfe]E/\xd6\x1e<\xacL\xb2$\x83\x0f69\xab\x1f\xfb\xdfÎ\x15\x1ce\f,\xc98\u007f\xd2r-\x94\xbb/\xe3\xbc\xe5Z\xa5^\x92\x11\xe0\xe8\x00\x90\x1d\xa4.\x19\x8c\xbd\xf3\x06(\x05\x9d\xf4sE\xb9x\xa4FD٤\xbe\xe7\x8d\x15\x83I\xec\x12\xe4r\xf6\xc8#@\xc7x\xe8\x8cY\xcc.Q0.V\xcf%\x84\x11\xaf\xb2\xa3\xff+\x97\x9f\x10\x14\xd5?\xb3\x9f`+\x8c\x86dp\xc16g\xb7?9o\xd2`E\x97\f\xae\x8c\x81*\x19\xef~\xfd\xf5\x97\x9b\x86*c\xf5r\xa6d\\x\xf1,\xed8`\x8ar%\x8dG \xa3\x03@v\x90\xa2d|m~dw^\xa4̣]\xf6ǯz6\xfe\xa89\x93ֲ#\x85\xb1\xec\xfc\xdc#@\xc7x\xe8\x8cYl\xde_9\xd2.\xe0\x8c\xa0{\xa7\x14\xa8\x1b\xe7O\xff2\xa6\xa8~\xa4\xc0K\x06\x17l\xf1\xf0 \x16?|\x94.\x19\\\x19\x03s-\xe3\xc4`e\xb8V\xac\xc3u\xc9\xf4\x1e~\xf9\xf3%\xeeZn\x90\xa3\x03@v\x90\x9ad\x8c4\x8e\xa4U橓\xecs\xeer$\xb5\xdf\xf3g\a(\x9d'\xce+\xf8\x92z\x058\x1e:c\xac\xa3\x8c\xa1\xda\a\xaf \x82\xb2Äy\x17+\xcau1E\x05\x92a\a\x9bܣ(ӗ\xbf\xf6\xa5yb\xe2-\x19t\xbb\xa2\xafp\xb8%c7\xf7\xb8C9Ϻ\xca\x1a\xe8\xe8\x00\x90\x1d\xa4&\x19\xe3\xedk\x05\xf3\xd8\xe6@\xf3\xc6\xe8\xed\x1d_s\xef\xf9Y\xca\xe2'\xf4H\x8f\x00\r\xf3\xa1#f\xb1qx\xfeeD\x9d\x96\u0088?o7J\x9f\xff\xb5\xbbh\xacd\xf0\xc1:_\x17\xb0\x1b:)[{\xf4\x93\fvw\a\xbb\xb8\xe2\x96\f:\x98]71C\x06Z\x97E\x03\x1d\x1d\x00\xb2\x83\xd4$c\xb5\xf5\xe5\x89\xceA\xecb\xe1te\xb86\x15\xd7*\x91\x13\xdc{\xfeUe\xecXm\xb2y\x05h\x98\x0f\x1d1\x8b\x95\x886=\x17\xb3\x8b\x90\xa2\b\xf5h^\xbb\x1c\xf1\xaer\xdeYwQ\xa7d\x9c\xd0\x0e\xfd\xed`\x9d.\xe3\xc2\xc4\xe7\x17\xb1\xca\xe3K\xc6\xe7\ue2ec\x06O*\xfa\x95R\xed\xae\xae\a\xad݁\x8e\x0e\x00\xd9Aj\x92\xa1\x9e\x83+\xe3Wwt\xed~p\x90r\xb1:\x99ލ(\xd3\xd5\x0f\xf3W\a\xb2k\b\xdc{~H$2H\x9b\f^\x01\f\xf3\xa1#f\xb1\xa2\fW\xe7\xe7\xda\x02\xf5\xbcD\x1c1V\x19\xab\xca\xc0\xe7\x93\xd8ራ(?\xfd#\xca\xca/\xbfv\x04\xeb|=@\xbb\xdeѩ\xf6\xe4\n?ɠ+\x15\xe5\x1e\x81d\xa8\xc7\x13ʔ\xed\x9f\u007f\xbd\xf76\xc5\xf1\xb5\xb4`Fg\xf9\xc3\xdb)\x00\xd9B\x8a\x92\xf1\xb9\xf9\xf5nmb\xab\x1f\xac\x11傑C\x14\xe5\xf2\xb3\x8eIq\x8fb.Ix\x040\xac\x87|\xccbe\xc8\x05\xe7\xb3\x1b\"\xef\xf1\x8a\xf8\xcb@%r\xf1\xf0\x02ePGLQ~\xfa\x8fTs\xdc\xe4\f\xd6yXQ\x06_1\xf2\xbc\x01w\xb1\xeb\xab>\x92\xa1\x8a@\xa4C \x19g\xa7\x98\xc3p\x05\xffM\x96`Fgx\x9ck\xb8\x00\xf47)J\x06\xa5/\xcd\x1a: r\xd1\x15ˍ\x0f\u05ceYC\"\x05#\x1ff\x87\xfdܤ\xe8P\x14\xf3\x16Hq\x00u<\xe4b\xd49\xbc\xfb\x8a\x82\x81Wl\xf7\x8c\xa0\x9ds\x86D.\x18z\xd7\tAQm\x97>\xfd\xdf\x1du\xc1\x80\x95\xae`\x9dM\x97\x0f\x8c\xa8{>g\xab%~\x92\xd1\x11Q\x8fOb%\x83\xd2\xedӇ^\x10\xb9h\x92\xfb'v\x82\x18\x1dH\x06\xc8&R\x96\x8c4c\xcea\x00@V\x00\xc9\x00\x00H\x00\xc9\x00\x00H\x00\xc9\x00\x00H\x00\xc9\x00\x00H\x90\xed\x92\x01\x00\xc8* \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t\x82\x97\x8c\x1a\xf2S\xbf\x10\xc6*\xf2}\xbf\x10\x1f\x8e\xf7\xfaE\x00\x00\x82&\xb4\x92\xd1\xf7\\\xc9i\xbf\x18\x00@ЄV2z\b\x81d\x00\xd0\xef@2\x00\x00\x12@2\x00\x00\x12\xa4$\x19\xbb_\xb3\xd8m\xed\xd4%c\x1dY\xf5\xd7\xc6\xf2\xe2\x99\xdbhߺ\x19ъ\xa6\xd3ھ\x15\x87\xea'\x96\xde\xfa\xeb>jI\xc6\xf1\xa6\xaahY\xdd.\xeaQ\xc4\x15\xd0|\xaa\xa9\"Z\xb5\xe4\x14\xa5\x8b\b\xe3 \xa5G\x1a*\xa3\x13k\xd6`)\x14\x80~!%ɸM\xb1\x98n\xed4%\xa3q2)\x8f\x12\xb2\xad\x81\x14\x97\x13R\xa3\xed\xab/\x8d\xd6\xd6\x14\x92\x86>S2v\x8d#\xc53\xab\bY\xe6Q\xc4\x15\xd0TAJ\xcb\b\xa9\ue85b\xe7\x13R?\xff8\xfd\xb0\x94\x94\xddTM\xc8\x1d}\x82\xfc\x00\x00A\x93\x92dtEL\xc58\xaf\xc3\xdaiJ\x06\xa9\xfe\x90\xf6\xce'\xc5\xc5/\xf4\xd1W\bٯ\xed\x9b\xf61\xa5\xfb\xcb\xc8FC2\x8e\x97\x92Eݔ\xee)#\xdb\xc4Eb\x02ޤ\xb45J6X'&\xf5d\x89z\x80q`\x02i\xf5J\x12\x00\x10 )I\x86}\x98q\x9d\xbdϒ\x8cC\xea\x9f\x0f\tif;oa\xb3|\x9dv&A\xe9ˤʐ\x8cE\xa4\x8e\xea{\xaa\xc5E\xdc\x01\x1f\xb1\a\x8d\xa4ђ\x8ck\xf5*\xd7ܻ\x93\x02\x00\xd2Oj\x92a\x1efp\a\x19\x96dLc\x0f\xba\t\xf9\x80\xfd\x9dOZ\xd8>\xed\\\x83\xf6\x16\xabڠIF%yE\xdb\xd3SH\x8e\n\x8b\xb8\x02n\xd4\x1e\xb4\x90zK2\xee 5o\x9e\xa3\x00\x80~\"5ɠsb\x0e2,ɨe\x0f\xce\x11r\x92\xfd\xbdO\x97\x8cEz\xc8\f\xb2S\x93\fU\x1dfܪ\x11%m\xa2\"\xee\x00\xfd\x90c\x03'\x19oF\t\x990\u007f\xf3\xdf)\x00\xa0?HQ2\xf4\xc3\f\xfe Ò\x8cz\xf6@\x9d\xff\x9f\xb1\xbf\x86d<c\x86\xbc\xacIƧ\xc4f\x9b\xa8\x880@\x95\x8c:\xfb\"\xeb\x87\vJ\xd4'\x8b\x1a\xbb)\x00 \xfd\xa4(\x19\xfaa\x06\u007f\x90\x11W2\x1e\xd3C\xaa\xd5C\x06&\x19\xa7\t9b\x17\x14\x14\x11\x068%C=\xcfi\u007fz&!\r\x14\x00\x90~R\x95\fv\x98\xe18Ȉ+\x19ڙ\a펒\xe3\xfaZ\xc6U\xecB\bc\xcf\xc7\xe7\x84ED\x01\xbcd\xf4}\xfc\x86\xb6k\r)\u008a\x06\x00\xfd@\xaa\x92\xc1\x0e3\xa68vē\x8c\xe8q\xaa=w\x93qŤ\x91ܤ\xddO\xb1\x93\x14\x9f\x12\x16\x11\x05\xe8\x92\xd1K\xc8?(=IFk\xc1\x87H!n\xe6\x02\xa0\x1fHY2:#\x8a\xe3 #\xaed\x90\x9bT\xcd\xd8Y\xa2\x9e\x97\xe8\x92q\xa8\x98<t\x86ҷ\xcbH\x93\xb8\x88(@\x97\f\x1a%ۺ\xcf\xd1;\xc8\x1dj\xf4\xe9\xf9\xc6\x01\f\x00 \xbd\xa4,\x19t\x8e\xf3 #\xaedL-.\xbai*!+\xa8y\xf7gk\x94\x14ϞF\xc8\xdc\x1eq\x11Q\x80!\x19\xb3\tQ\xa5\xe7X\x19\x89\xde8\xb3\x84\x94\x1f\xa5\x00\x80\xf4\x93\xbadt:\x0f2\xe2JF\xfd\xc1\xbaҲ\xba=l\x8f\xf1\x1d\x93#?\xaa\x8a\x96\xccn\xe9\xf5(\"\n0$\xe3PM\xf1ė\xd9wP\xa6E\x8b\xab\x97\xe2*+\x00\xfdB꒑8\xe6\x94\a\x00\x84\x16H\x06\x00@\x02H\x06\x00@\x02H\x06\x00@\x02H\x06\x00@\x82\xfe\x94\f\x00@\xe8\x81d\x00\x00$\x80d\x00\x00$\x80d\x00\x00$\x80d\x00\x00$\x80d\x00\x00$\x80d\x00\x00$\x80d\x00\x00$\x80d\x00\x00$\x80d\x00\x00$\x80d\x00\x00$\x80d\x00\x00$\x80d\x00\x00$\x80d\x00\x00$\x80d\x00\x00$\x80d\x00\x00$\x80d\x00\x00$\x80d\x00\x00$\x80d\x00\x00$\x80d\x00\x00$\x80d\x00\x00$\x80d\x00\x00$\x80d\x00\x00$\x80d\x00\x00$\x80d\x00\x00$\x80d\x00\x00$\x80d\x00\x00$\x80d\x00\x00$\x80d\x00\x00$\x80d\x00\x00$\x80d\x00\x00$\x80d\x00\x00$\x80d\x00\x00$\x80d\x00\x00$\x80d\x00\x00$\x80dP\xfa\x842\xde/D\xe5Ae\x8a_\x88\x0f\x9dg\xfd\"L\xd0Y\xe9\x00\x00 \x00IDAT\x00\xc8z \x19\xfd&\x19\x0f\x16|\xee\x17\x02@\xd6\x03ɠt\xf7\x83\xab\xfdBh\xea\x92qVQ \x19 \xfc@2\x12\x05\x92\x01\x00\x85d$N\xe6%\xa3\xa9\xc9/\x02\x80\xb4\x13f\xc9\xd8;~Ѐ\xb1ۇo\xf7\x8b\xf3C[\xcbX\xac<\xd89}\xd0\x05\xc3W\xaa\x9b\x17G\x06\xcdb\xd3{\xb1rϻ\xe3\a\\8r9\x8b2$\xa3s\u0590\xc8\xc0\xf1/Q*.\xe2\n\xb8\xffĬ\xc1\x91!\xb7\x9d\xa0t\x8e\xc2\xd8Mi\xc7\xf4\xc1\x91\x01\xa3\x1e\x95_\n=B\x96х\xa4p\x9b_\x9c\x80\x17\b!ʹY\xfdws\x9c\xa8\xe3Q2C\xfdӨ\x86\x8d;\x1a'\x0e\xe45!\x96\x8cݑI\xabW^\xa9(+\xfd\x02\xfd0$c\xfa@ePD\xad\xee:\xe5\x82A\x8a2\x8a\xb2}\x93\n\"cG\x9d\xa7\\GM\xc9x\xa9@\x89\f\x1f\xa2(\U000e8e08+`\xd6Eʅ\x03\x15e\xe8Y\xba|\x92\xa2\x8c\xbf\xb2\x93\xee\xbdP\x190|\xa8\xa2\x8c\x8d\x93\x90\xc1\x9e\x03\x8e\x87\rŧ\xe8\xc9\xf6h\xb30\xc0\x15\xeb\xe2̋\xe4\xb9S\xf4T\vy\xf1L\x9c\xa8\xbew\x1a\xa3ꟿ\xb5\xb7\xaf'olj\x03yM\b%\xe3\xc4\xd8\x13\xda\xdf+\xb4Y7=0\xc9P\x86\xee\xa5g\xafT\"\x17,\xff\x9a\xaeV\x94״}C\xfeL\xe9k\x03\x94\xe5\x86dt^\xa8\xcc\xf9\x92\xd2\xed\x03X\xab\xa2\"1\x01\xea1\xd0ڈ\xf2\xa4ub2^\xb9\xedkU\xee\x06(k\xfdҢ5\x0f\xf0\x8f\x8e\x8e~\x8c\xfd\xe1%\x83\vp\xc6\xc6p\x88\xb4\xa9\xff\xee!\x87\xe2F\xd1\xe6\xa8\xfew\x1f$\x03x\x11B\xc9ث\xec\xd5\xfe\x0e\x99\xa7?J\xe4rG\\L\xc9`\xd5\xeeU\x94{ؾ\x91l\x96\x1b\xfb\xe8Je\x88!\x19s\x94+\xa8\xbeg\xa8\xb8\x88;\xa0\x83=\x98\xaeL\xb7$c0;9\xa1\xf4\xe1+\xfd%\xe3\xd6\xfb\xf8G\x0fE?c\u007fx\xc9\xe0\x02\x9c\xb11@2@P\x84M2\x16\x0f]ۡt\xac\x1d\xfa\x04\xa5S\x06k\xf3y\xed\x97\xec\xdf\xe5\xa3\n.\xbeK\xdd\xda}\xbezN\xd0qݐ\x82\xf1_\xafT\x14\xe5~z\xbf\xa2\x9f\xba\b\x02\xcc:\r\xc9\x18¶\xbfT\xf4)}\xa5\xf20ۧ\x9dkг\x11\xe5]]2\x06\x1b\x02u\xf6<U\fDE\\\x01\x17k\x0f\x1eV&Y\x921V\x19\xb9\xddjYc!\x89n|\xec\xc6qu\u007fc\x0f\xfa~]Sz\xe3\xe3=\x94\xee :\xb7\x18QNj\x16i\u007f\xa3K\x8dX.\x80\xdb\\H\x8a\xd65UN\xaew\xadEp\x92q\xe6\xbe\xcahU\xfdAw\xc3'\x1b*\xcb\x16h'&\x94\x93\f+\x9d\x83E\x84<s\xb4aZI\xdd9\n\xf2\x9a\xb0IF\xd7u\xcap\xf5\xbf)]\xea9\xc0\x90\xf3\xc6\xdf\xff\xaa>\xfdf\x9d7g\xed\xe2A#\xbf\xa6gW\xae\x1c2t\xc0\x90ۮS:\xbf\xdc>\xe0\x9e\x13\xf4\xc4=\x03\xb6\u007f)\x0e0\xeb4$C;\xcf\xf9ZQ\xba\xd8\xdf)\xbadܦG\\\xac\x9eF0\xc9\xf8\\Q.\x1e\xa9\x11Q6\x89\x8a\xb8\x03\xae\xb0\x1b0$\xe3Ո\xa2\f\xb8r\xf9\t\xabG\xf4\xa3\xadE\xa4\xa2\xf9g\x13\xefe\x0f~X\xb8h纊[\xfbh\xf7\x9b\xed\xd5w\xb4\xb7\xb7\x1f1\xa2\x9a\xa2\xda̦Q2ck\xeb5j,\x17\xc0m\xb2ʦ\xaej\x9e:\xeeC\xcas\x88\xec\xec\xe9\xe9ic\x92\xb1\x834\xed\xd9V_\xb8\xcf\xd9\xf0щ7\xbe\xd0ZG\xa2z\xb8%\x19V:=۶N\xad\x9eP\xf5X\xc3\xe8\xbfR\x90ׄM2(\xdd\x14Q\"\x9b\xb4\xad\xcf\xef\x1f\x15Q\x06\xb2C\x88\xb5l\xb1\x81\xbe\xa6/k\x8cT\xaeP\xe7&\x9b\x9e\xb3\u0602\xe5u\xb3\xbc\x03t\fɘĶ]\x921O\x8f\x18\xa9\x16d\x92ѥج\x14\x15\x11\x068$\x83\xee\x9dR\xa0>y\xfe\xf4/\xad\xf6i\xb4L\x95\x83\x86\n\xca\xe6\xf3\x8b\x94\xcdحl7\u007f\xb2q<\xbaЈ\xad\xf8\x87:\x93+\xa8+\xc0ތN;C\xe9\xe9\xaa\x1a\xcas\xc88\x0eQ%\xa3g[\xb7z\xf4p\xd3|-\xd6jxn\xb5z(\xd17;\xaa\x87\x9b\x92\xe1L\x87Ԟ\xa1}\xf1\xd6OA>\x106\xc9\xf8\xfc\xb6\xc8`ep\xe4.\xe3S\xfa\xecK\xe3\xd9:┡_3\x06Og\xfbFF\xcc\xe3\x87\xed\x05_ҳ\x05\xec\"\xacG\x80N\x1c\xc90\x8e2\x86\xaa\x87\f\xc6QF\x87]NPD\x18\xe0\x94\fuk\xfb\xbc\x8b\x15\xed*\x8cA\xf4!j\xac#<pC\xef9\x95k\x1b\xd9n^2\x16F\x8f\x1b\xb1M\xd4Zs\x10K\xc62\xf6\xefz\xf2\x15\xe58D~\xb6o\u07fe5\xdaZ\xc6\x17\xeb\xebn\x98Hfk\xb1fç\xc9F\xf6\xf8\x99\xa8\x1enJ\x863\x9d(\x0e0@\xf8$\xe3\xe1AO\xbe\xabt,\x1e\xf4\xa0z̠MTz\xf9$v\x14\xa0s%\xdb1r\xa4\x19\xfc\xf5\xa0\xd5t\xed v\xea\xe2\x11\xa0\x13G2\xf4K\xa1_FԳ\x18m-c\xa0y}f{\xc7\xd7\xc2\"\xa2\x00\x87d\xfcY\xbf\x8d\xe4Q\xe5|{EC[\xd2\xd4d`\xb6q4\xa0\x1d\x03p\x8ap2\xfa\xa3\x98X/\xc9\xd0\xd6Gۉ\xe3\xaa+\xb7\x96\xb1\xaf\xa2jik{\xedl+\x96Uv\x80\xb4S\x1a\xbb\xfc\xe9L\xc7y\xe0\x02\xf2\x94\xb0I\x06\xfdZ\xbbb¦\xdbEs\xb4\x1d\xf3\x86\xaa'\x1fCwkh\xc7\x1e#\xed\xbb4\xe7\\I\xafԢ\xbc\x024\xe2H\x86~<\xb2X\x19n\\1\x99\xae\f\xd7f\xfaZ%rBXD\x14`I\x86\xdaz\x97\x11\xfc\xaer\x9e}3\x97-\x03\r7\x1c\xd0\xf8\x82\xed\xd6d`\xb3\xf6Ѿ\xa4\xf0XL\xac#\xc0ތ.a\x8f7\x12\xc7\x19\x04'\x193j\xd4S\x10\xba\xc0)\x19\xff \xeb\xd9\xe3\x87\xf4z-\xc9p\xa6\xb3\x80\x02\x10>\xc9Pg\xdd@\xfd\xf0b\xd0`\xed@\x9f\t\xc0&\xfd\xb3}ރ\xe6\x0e\x83W#]\x91WنW\x80F\x1c\xc9P\x86\xab\x9a\xb1\xb6@=/\xd1%\xe3݈2]m\xf5Ձ\xca\x1cq\x11Q\x80\xf1Uو\xb2\xf2˯\xe9Xe\xac\x1a\xfd\xf9$\xfe^.[\x06ڈvs\xe7O\x9fc\xff\xd6\xd6RzJ\xdb\xf1Y\xf1C\xb1\xb1|\x00\xb7\x19\xbd\xa6\x9b\xd2\xee\x1bj\xb5\x88\xe3\xcf\xe9R\xc3IF\x15\x9b\xf9}7;%\x83\xd6T\xa9'2\x1f\x17\xeb\xf5Z\x92\xe1H\xc7\xe7:.\xc8\x13B(\x19&\x83\x94\x8b\xeeٴ\xfa\x8a\x02\xb6x0O\x99\xb2z-\xbb\xab\xeb\xebW\xb7\x0f\x1d\xbb}\xbb\xb9X1\xf8\x8a\xc1\xfa\x86W\x00#\x8ed\f\xb9\xe0|v+'\xbb\xefB\xbf\xfbsuD\xb9`\xa4\xba\xe7\xf2\xb3\xe2\"\xa2\x00C2\xd8\xc9\xd1&\xfa\x97\x81J\xe4\xe2\xe1\x05\xca k\xcd\xe3\xb3\xf6h\xe3;}\xef7F\xdb?\xa3t\xd9\xe8\xef\xbf\xd2\xdaH^fO4G״֖~\xaan=>\xfa\xa8 \x96\v\xe06\xa3\xe4\x96m\x9b\xab\xcb>\xd6\xe2\xe7\x93z\xf6\x87\xbf\xfb\xb3\x99ܷ~խ\xa4\xbc\xe5\x1d\xbe\xb2\x0f\xc7U5?3\xb9\xb0\xe8\xc5C\xf4Sv\xf7\xe7\xba\xf6vv\xc8b\xa5s\xee-\xed\xa2\xccq\n\xf2\x9d\x10Kƨ\xe5\xf3..\x184I\x9fz\x9b\xc6\x0e\x1cx\xb9z,\xb0\xfb<m\xcdb\xbc\x11\xb38\xf2\xa8\xb1\xe5\x11\xc0\x88#\x19\x93v_Q0\xf0\nm\xf9\xc1\xf8\x8eIǬ!\x91\x82\x91\x0f\xb3\xb3\n\xa1d\b\x02\f\xc9xw\xd4\x05\x03\xd4c\x9d\xce9C\"\x17\f\xbd˾ʺ\x90\x10\x12=\\\xaa\xfe\xcb.\x8a\xb4\xd5^U6\xb7M{\xa2w\xd1\xe4\x92;\xf6\xa9\x1b\u007f/i\x10\xc6Z\x01\xfcf\xf4\xf1Ɖ\x95\r\x9f\xe9\xf1/Tl\xd0\xfe\x10\xf3;&\x1biߚ\xeah\xc5\x03/TGk\x1d\x95\x1d\xad\x9f<m\xe9\x8bE\xea\xe6C\xc6\x02\x86v?\xa9\x99\xce\xc1Bm_=\x05\xf9N\x88%#\xfd\x98S>\xd3<M\x8eЄ\xe1o\x0f\x05 p \x19q\xc8\x16\xc9\xf8\x91̷\xde!\x19 \xad@2\xe2\x90-\x92!\x05$\x03\xa4\x15HF\x1cB(\x19'\xb5%M\xbf(\x00\x92\x06\x92\x11\x87\x10J\x86\xb6\xa4\x89\xeb\x1a }@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12\x04.\x19\xfb\b![\xcd\a\xa7\xa3\x84\x1c\x8a\t9ޫ\xfe\xb3\x8e\xd4\xc7<ᤙ4\xfaDhh\xb5\x01\x00\xfa\x87\xb4H\xc6|\xf3\xc1\xafI\xacd\xf4=Wr\x9a\x06&\x19Fm\x00\x80\xfe!\r\x921ztI\x8f\xf1\xa0^ \x19=\x84\x04(\x19Fm\x00\x80\xfe!\r\x92\x11\xad!\xad\xfa\xf6\x99\xe8LH\x06\x009E:$c\riз\xb7\x92fH\x06\x009EJ\x92\xb1\xfb5\x8b\xdd\xe6>U2\x8e\x93\x89\xfa\x92d=9bH\xc6\xf1\xa6\xaahY\xdd.uk\x11a\x1cd\x92\xf1YSE\xb4\xeaq}\xc6\u007f\xd8X\xa9\x06\xb4\xe9u쩛\\Z\xbb\xcf!\x19G\x1a*\xa3\x13k\xd6\xe8\xf5\xc6\xd6\x06\x00\xe8\x1fR\x92\x8c\xdb\x14\x8b\xe9\xe6>U2\xe8̈́Mg\xda]|\xd39]2v\x8d#\xc53\xab\bYF\xe9\xe6\xf9\x84\xd4\xcf?\xaeJ\xc6\xcc\nR^F\xc8\f\xb6\xf0\xf1b\x94\x94\xdeTN\xc8BV\xae\x85\x90\x8a\x99Ѣ\x1aN2>,%e7U\x13rG\x9f\xb86\x00@\xff\x90\x92dtEL\xc58\xaf\xc3\xdc\xc7$\xe39\xd2\xc46\xb7\x91U\xbad\x1c/%\x8b\xbaՃ\x872\xb2\x8d;1!SߡtG\x94l\xa6\xf4@!y\xba\x87\xf6m-&k\xd4\ad\xf4\xfa>z\xaa\x96p\x92QO\x96\xa8\a\x18\a&\xb0U\x12Qm\x00\x80\xfe!%ɰ\x0f3\xae\xb3v1\xc98J*\xd8\xd1\xc0|rT\x97\x8cE\xa4N{\xeeeR\xcdK\xc6a\xb6\xaf\x91\tC=y@\vXO&\xf7\xd2{\xc9\"\xb6}\xfa*N2\xae\xd5O>\xd6ܻS\\\x1b\x00\xa0\u007fHM2\xcc\xc3\f\xfb C\x93\f:\x93\xa8\a\x10\xdd%3\xa9.\x19\x95\xe4\x15\xed\xb9\x9eBrԖ\x8c\x19ھ5\xa4\x9e\xf6\x96\xb0x\x95\xdeR\xf2f\xdf\x04\xb2_{\xb0\x88\x93\x8c;H͛\xe7\x8cmQm\x00\x80\xfe!5ɠs\xdc\a\x19\xbad4\x93\xc7)m%ͺdt\x132\xe3V\x8d(i\xb3%\xa3V\x8bߨ\xfe\xfd\x98\x10\xe3N\x8e\x1a\xb2\xf1\x14!\xdd\xc63\xb6d\xbc\x19%d\xc2\xfc\xcd\u007fW7\x85\xb5\x01\x00\xfa\x87\x14%C?\xcc\xe0\x0e2t\xc98L\xa6R\xba\x80\x1c\xd1%\xe3Sb\xb3\xcd}\x91\x95I\xc6ARd\x94\xae%k\x8e\x10\xa2o\xb7\xf2WL>\\P\xa2\x96.j\xec\x16\xd7\x06\x00\xe8\x1fR\x94\f\xfd0\x83;\xc8\xd0%\x83V\x93\x83=\xeay\x89.\x19\xa7\x89*\x1e\x16\x02\xc9\xf8\x84?\xca\xf8\xbby\x94\xf1\xb2\xf3\xbe\x8c\xde\xf6\xa7g\x12\xd2 \xae\r\x00\xd0?\xa4*\x19\xec0\x83?\xc80$\xe3i\xb2b\x87z^b\xace\\Ům0\xf6||N$\x19\xbd\xc5\xf6ZF{_\x19yK{\xb0̖\x8c\xbe\x8f\xdf\xd0\xfe\xae!E焵\x01\x00\xfa\x87T%\x83\x1dfL\xe1\x1f\xeb\x92q\x80\xccld\a\x03\xbad4\x92\x9b\xd8\x15\x14\xba\x93\x14\x9f\xa2\xbd\x84\xfc\x83:%\x83\xd6\x1b\xf7\x8bn$\x13zh\x83\xfe\xa0\xa7ʖ\x8c\x93d\xf4g\xec\xef!R\xd8+\xac\r\x00\xd0?\xa4,\x19\x9d\x11\x85?\xc80$\x83V\x91q슈.\x19\x87\x8a\xc9Cg(}\xbbL\xbb_#J\xb6u\x9fsJ\xc6\xfe\"\xb2\xa2\x97\xd2\xd6\x12\xd2B\xe9\x91(Y\xd5G\xcf\xcc'\x8e+&w\xa8\x9aqz>\v\x16\xd5\x06\x00\xe8\x1fR\x96\f:\xc7q\x90aJ\xc6ㄝ\x97\x18\x92A[\xa3\xa4x\xf64B\xe6\xb2%\x8bل\x906\xa7d\xd0\xcdEd\xe2\xcd\x15\x844\xb1\xe3\x87mQR~s\t\xa9\xe7$\xe3X\x19\x89\xde8\xb3\x84\x94\x1f\x15\xd7\x06\x00\xe8\x1fR\x97\x8cN\xc7A\x86)\x19\xef\xe8ZaH\x06=\xf2\xa3\xaah\xc9\xec\x16\xed+\"\x87j\x8a'\xbe\xec\x92\fz\xb0\xa1\"zM}\x9b^\xc7\xfb\xf3\xcbKnm\xdb\xc6/\u007f\x1eo\x9a\x16-\xae^\xfaw*\xae\r\x00\xd0?\xa4.\x19\x00\x80<\x02\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92\x01\x00\x90\x00\x92A[kN\xf9\x85H\xf2\xd5\xdcV\xbf\x90\x14\b>\xdf~ \xbdC\x02\xfa\x91\\\x93\x8c\x85\xa4p\x9b\xc7Sǣd\x86`w\vi\xees\xee9X_>\xf1\x8e=7\xbd)\bN\x8c\xbe\x96\xc2\xe7\x84O\xac)\xfe\x99p\xbf\fz\xbe\x8d\x84\x90qG\xcd}\xbb*v\xc4+\x928\a\v\xd5z\x1b\xad\x87\x81\xd5\xeb=$ l\xe4\x8ad\xec9\xa0\xff=\xd9\x1em\xf6\b\xe9{\xa71\x1a\xbbw]\xe1\xaf]{\x0eD\xeb[_\xbe\x97\x10/\xe9I\x84\x9dE\xebD\xbbgGo\x12\xed\xf6\xc1웆\x91\xef\xdf\xda\xdbד\xb7͝;J_\x89)口^\x9dso\xdf|S\xfb\xa7\xd6Ca\xbd\x82b\x89\xe01$ l\xe4\x8ad\xd4<`nyJ\x06\xa5\xcdј]Ǣ\xcb\xcc\xcd/j\xbf\xd0\xfe\xd6ժ\x9f\xe2}\x8d)I\x06]\x11\xfd[\xec\xce\xee\u0086\xc2\xee\xd8\xdd~\xd8}s\xe4\xbbϖ\f\xea:NJ\f\xbe^\x8b\xdaZ\xfe\x91\xa8^a\xb1\x04\x10\x0e\t\b\x1d\xb9\"\x19\xb7\xdegn\xc9IFcE\x8f\xb9\xf9!\xf9P\xfb;\xed\xa7\xec߃$\xa5\x93\xef\xee\n\xfb\xf0ޢ\x9d\x1c {bw\xfba\xf7͑//\x19I\xc1\xd7k\xe1\x94\f\x11\xc2b\t \x1c\x12\x10:\xc2%\x19箉>}m\xe5\x9eEe\xb5\xecú\xef\xd75\xa57>\xaeN\xa1\x1dD\xe7\x16\x16\x13]\xfa؍\xe3\xea\xb4\x0f\xb4\xbe\r\xb7\x8c\xbby\xbd\xf6Iy\xb2\xa1\xb2lA\xec\x89I\uf125\xfaƺ\xea\x1dGȑ\x9d\xd5\x1b(}\xa0\x82IG\xdfNG\x13\a\x8b\by\xe6hô\x92\xbas\xdbԖ\x9ai3\xd1N]D\x01Z\x85+J\xac\xb9m\xd1|-\xad4\x04\xed\x93\x05\xe5ъ\xfa\x93\xceM\xab\xb2\x85\xa4h]S\xe5\xe4\xfa\xa3\xae\xbe\xd9\xf9R[2N\x97\x10R\xb8U\xdf\xf7F]U\xb4\xbc~\xaa\xe3\xe0`!\x89n\xb4\x87D8f\x1c\xb6d\b\xebu\x14\xe3\xf2\x155\x91Ȑ\x80\xd0\x11.ɠ{&\x92\xc7j\xc9U\xcf]\xb3F}\xf0\xc3\xc2E;\xd7U\xdc\xdaG\xbb\xdfl\xaf\xbe\xa3\xbd\xbd\xfd\b\v\x89\x92\x19[[\xaf\xb9\x97m>\x14}f\xe73Q\xf6\xd9vt\xe2\x8d/\xb4֑\xa8\xbb\xbe\xf7I\xbb\xbeq\xb2\x81\xccT\xff[\xa0\x9e\xc7\x1f\xaf*\xack~\xabW\xdbm5ѳm\xeb\xd4\xea\tU\x8f5\x8c\xfek\xf7\x1b\x13W\x9c\xa2\xa7V\x94\xbd\xd1-\x0e\xd0J\xbeI\xder7Fk\x17\xd0\xfb\xf4\x19\xb9\xa7\xf4\x96\x96]\xcdd\x8dsӪ죭Ed\xea\xaa\xe6\xa9\xe3>t\xf6\xcdΗrG\x19\a\xdaۋu%\xda?\xba\xe1\x95]\x1b\xcb\xc99\xbeUVYE\xf3\xcf&jC\"\x1e3\x0e\xee(CT\xaf\xa3\x98#\xdf\xd8&\x12\x19\x12\x10:B&\x19\xb4\xa2\x81\xee$;\xe8CM\xecs\xf2E\xca&\x8e\xf6Aȝ\x98T\xfcC}\xdbV\xa8[m\xa4\xcd\xfcwn\xb5\xfa\x01\xd77;\xea\xaen'\xf9\xd8\xdcl\x8b\x92h\x9b\xb6\xf5ժ\x9a()cK\x19\xce&H\xed\x19\xdawF\xdd\xfa!;\x9bo\xf8\x91w\x80\xca\xdfH\xcc\xcaa_\xe9\x1a\xba\xa6\x94\x1d\x01\xf4Tթ\x92Ի\xed+\xc7&_Yt\x9aZ\xcf\xe9\xaa\x1a\xad^\xfbL\x80\xcb\xd7qbR\xa2O\xed\xf5\x15L,֗\xb9\x96 \xa2e\xea\xc7\u007f\x03\x1b\x12\x8f1\xe3p\x9e\x98\x88굊9\xf2\xf5h\xc2gH@\xf8\b\x9ddl\xa5\xef\x90n\xba\xf4\xfb\xea\t\xc4\r\xbd\xe7T\xae\xd5ΐ9\xc9P\xd5D_\xb5\xf8\xe1Lm\xc7\xccFz\x9ald[\xcfD\xddյ\x92\xe3\xfa\xc6W\x8fE+Ie\xf1\xd2\u007f\xe8\x0f{wՑ\x9d\xee&\xa2\u007f5J\xedQ\x8f\xb0{Ʊ\xcf{\x8f\x00\xca\xe6G\xcc\xf2\xe9A\xf2fϛ\xe4 e2\xf6\x81\xb9\x93\xdb\xe4+\xd3W9\xd7\x13UI\xf8\xa9m\xe5K\x85\x92\xf1i\xe5\xb4E\x1b?\xe8\xeb\xa5N\xa2\x0fQcH<ƌC(\x19\x8ez\xadb\x8e|=\x9a\xf0\x19\x12\x10>B'\x19mt_\x94\xd2e\xaad\xcc6N\xab\xe7\xb3\xfd\xae\xe5O\xed\xcd;\xb7^\xdbQ_C\x0f\xe8\xc7\xf3\xb1˟\xef\x98Ӯ\xa5|\xc3!\xf2Ѻ\xf2\xe7ԩ\xa8\xad0\xf4\xb1\xd2\xce&j\xccR\xe7\xca[ik9\xfb\xc8\xf5\b\xa0lB\xc7\xdcױN\v]\xa7m\xf5\xd8;\xadM\xbe2}\x11\xb7\x9d\xb0\v\x9a\xdc\xd4~\x87\x93\t\x81d\xd0\xd3\x1b\xee\x9bA\xaeiq\x1feXC\xe21f\x1cB\xc9p\xd4k\x15\x8b\xc9WЄϐ\x80\xf0\x11b\xc9h\xb8ဆviT{\x1fof\x1fi\xf6\x9b\xb7\xf1\x06\xf6\x16\xef\x9b\xf6\x10\xfd\aYς\x1e\x8a\xba\xab뱮\xaf\xf4\xd2\x0f\xc9!ګ\x96\xa8X\xa4\xed\xf8i\xb5\xbb\x89\x05V\xb1E\xf3\xe9\xbdZ\x94W\x00\xcb \xe6r\xea\x82[\xf6\xed\xdbw\v\v\xdaE\xac{\x1b\xb8M\xbe\xb2\xe8\x12\xb6g#a\xc7\xf4v߸|\x85\x92q`\x99\x9a\xff\xe9\xad%\xeb\xa9\x03{H<ƌC\x97\x8c\xee\x15_i\x8fD\xf5Z\xc5\x1c\xf9z4\xe13$ |\x84X2\xda\xf4\xe3ܟjw\x15\xb2w\xfa)m\x87\xfd\xe6ݩ\x9dOoeg\x185U\xea\x14\xf8\xb88\x1aS߂j\xeb\x13\xf9\xd32\xfd\x1e\xa6\xf2J6]\xfaػ\xdd\xd1\x04\xf7\xa1\xfcV\xf1g\xc5\xdaR\x9eW\x00\xed\x9bQO\xddT>\xae\xfe\xf3X%e\xd7\x1bk\xd9A\xfe\xa2%\x8eM\xbe\xb2\xe85\xea\xf4\xea\xbeA\x9b\xbfv\xdf\x1c\xf9\n$\xa3Y[\xbd\xa1\xb5Mԁ=$\x1ecF\xe9\xf1\xe7\x8e鱺d\xbcO\xde\xd0\x1e\x89굊9\xf2\x157\xe17$ |\x84L2\x0eM^ӳ5z\xb0\xa7\xa1\xf6o\xaan\x8c\xfe\xfe+\xad\x8d\xe4e\xf6DstMkm\xe9\xa7\xf4\xb3\xf6h\xe3;}\xef7F\xdb?S?\xf0\n\x97\xedXVؠ>\xfdḪ\xe6g&\x17\x16\xbdx\xc8U\xe1\x91\u0098[\xb8\xcbIEs[km\t[h\xb4\x9a8\xf7\x96v\xa5\xc0XI諬\xabԧ\xaeG\x00]c\x1f<\x18\xf4\xb4\x91\x9fv\xd3\xee\xa7I\x9b*\x11{\x8agnh[D6S\xc7&ס(\xb9e\xdb\xe6\xea2m\xb1\xd3\xec\x1b\xc3\xcc\xf7Sv\xf7\xe7\xba\xf6v\xf5þ\xf7\xed\xf6\xf6\xe2\xc6\xf67ΰ\xa9]\xbab\x87Z\x83\xe3\xe6\x0fǐ\x88ƌ1\x9fh\xf3\xf9\xdc[7\xdfԮ\xb2A=\x93\xf3\xaa\xd7.fU&n\xc2wH@\x18\t\x97d\xf4]C\xc8\xd6\t\xa4t\x9b~\xaa\xdcV{U\xd9\xdc6\xed\x99\xdeE\x93K\xee\xd8\xc7\xee\x10 $z\xb8T\xfdw\xa1\x1a\xben\xf6\xb8\xd9\xfa}\x19G\xeb'O[\xfab\x11\xdb\xebdE\xb1\xfb\x04\xbbf\xf3Og\x94V\xcc\xd7/M\x98Mh_\xbe \xc4\xfc\x9c\\\x17]cl\x89\x03\xde(\xb1\xef\x9f0\xd85\x9a\xdd\xc8\xd1J\xc8\xe8]꣏\xef\xbbvB\x8d~\xb3\x18\xb7iw(\xfax\xe3\xc4ʆϴ\xbdf\xdf4\x8c|\x1f2V\f\x1e\xa0t\xbf\xde2\xd9@\xe9\xaf\xefh\xae\x8aV\xd4:o\x17s\f\x89h\xcc\x18/Tl`\u007f\x8c^\x10Rrij^\xae\x98Y\x99\xb8\t\xdf!\x01a$\\\x92\x91\x06\xfa\x96D\xb7\xf9\xc5H\xb3-\xda\xe8\xb85B\x1e\xefoʤ#\xdf~ \xf5!\x01\xd9A\xdeK\x06\xed[s\xed\xdf\xfdb$\xf9\xaa\u2e64\xbe\xf4\xc1\xe1}\xdb{\x1a\xf2\xed\a\x02\x18\x12\x90\x1d@2\xb2\x938ߔ\x01 \x93@2\xb2\x91\x93\xdar\xa2_\x14\x00\x19\x00\x92\x91\x8dhˉ\xf6}\x9e\x00d\x0f\x90\f\x00\x80\x04\x90\f\x00\x80\x04\x90\f\x00\x80\x04\x90\f\x00\x80\x04\x90\f\x00\x80\x04\x90\f\x00\x80\x04\x90\f\x00\x80\x04\x90\f\x00\x80\x04\x90\f\x00\x80\x04\x90\x8c4x\x9cf\x8f\x01i\xf0}\x031d\xcf\xcb\xdd/\xe4\x9add\xaf'\xeb\vĴ?\xd9,(bb$\xe9\xb4\\5\xe0jh-2~ע\xa8\x95\xdbl\x1b\xcd\xfeN\xae?b\x96\x88훈\x98bn\xe2\f\xaa\x1fɺ\xbaƼX\xbe9d\xae\x17y\xe67\x9b+\x92\x91\xfd\x9e\xacg^$ϝ\xa2\xa7ZȋgD%\f\x8c$\x9d\x96\xab\x06\\\r-\xc4\xf8U\xae\xd1-\xdcfϛ\xd1\xc6\xf6=\xeb\xaaK>\xd2\v\xc4\xf6M\x88\xbb\x98E\x02\x83j\xe1\xe1Ԛ\x9c[\xac\xe0\xc5\xf2\xcd!\x93\xbd\xc8+\xbf\xd9\\\x91\x8c\x10x\xb2\x1e\xd2~@s\x0fq\xff\x96\xa0\v3I\x81\u007f\xa2]ú\xa8\x11P\xb2\x8e\xdb4:\xdf]Y\xa7\x85s}\xf3\xc1Q\xcc&\xa1A5\xf0rjM\xe0(GL̋\xe5\x9bC\x06{\x91O~\xb3\xb9\"\x19!\xf0d\rR2z?1\x02>\xe9\xe56\xcd\xce7\x97hoq\xaeo>8\x8a\xd9$4\xa8\x06\xc9:\xb5z\x92\xa4dd\xa6\x17\xf9\xe47\x1b.\xc9\b\xb5'+'\x19g\ueaccV\xd53\x13$\x87\x9b\xa9#IK2\xac&\\\xa2\xc3i\x8a\xb5\xa9O\x8a\x96\"\xf6\xa3\xe5f߸\xcc8\xafWʛ\xc1\xda\xc5\xec̼\x06\x95C\xe4\xd4ʏ\x83\xed\xea\xea\xe8\xe6\x17\rW]\xfb\xf8\xe3W\x95z\x1e\xc6q\xe3`w\x9eF\x17\xfdHO}!)|\xd9Z\xec\xe0*\xcbd/\xf2\xc8o6\\\x92\x11jO\xd6CdgOOO\x1b\x9b\xf0;HӞm\xf5\x85\xfb\x9c\x86\xa9\xce$-\x19\xb0\x9a\xe0k\xa0q$\xa3\xef\x96\xd9l\xdb\xec\x1b\x97\x19\xe7\xf5\xea0\x83\xb5\x8bٙy\r\xaa\x8dЩ\xd51\x0e\x96\xab+\xdf\xcdޙ\x15뛋K6י\xbf\xb8\xec\x86\x1f\a\xbb\xf3ڏ\xaeo\x9d\xad\xa6\xae-J\x18\x8b\x1d|e\x99\xecE\x1e\xf9͆L2\xc2\xec\xc9z\xc8\xf8\x10;\xc4ޑ\xaa\xda\xf4ݤ\x19\x8a\xd9n\xa6\xce$M\x19\xe0\x9a\xe0j\xa0\x1e\x92\xb1\xa2\xa7\xe7ང\xfd\x869\xdf7;3\xdb\xeb\x953\x83\xe5\x8a\xf1\x99\t\a\x95C\xec\xd4\xea\x1a\a\xd3o\xcd\xee\xe66\xe61\xb9>\xce\xf9\x197\x0e\x0e\xdb\xd7\x19\xea\xee\x9ej\xe6\xbff\xbb\xa6\xf0\x95e\xb2\x17y\xe47\x1b:\xc9\b\xaf'\xeb!\xf2\xb3}\xfb\xf6\xad\xd1\xdee_\xac\xaf\xbba\"\xd1\x0e\x06,7SW\x92\xa6\fpM\xf05xH\x06S\x94r}\x15\x86\xf3o\xb53\xb3\xbd^93X\xbe\x18\x97\x99pP9\xc4N\xad\xaeq\xb0&\x9beں\xacL\xfd\xe7c\xef\xa5\"~\x1c\x1c\xb6\xafO\xb3\xdd\x1b\x98M\xad-\x19|e\x99\xecE\x1e\xf9͆N2\xc2\xeb\xc9ʭD쫨Z\xda\xda^\xabK\x86\x99\xaf+IS\x06\xb8&\x12X\xcbhڷ\xef\x13c\xf9\x8f\xf3o\xb53\xd3\xcf\xf7\x99\xd7+g\x06\xcb\x15\xe33\x13\x0e*\x8fЩ\xd55\x0e\xd6d\xb3jX3\xfa\vv\xec\xf7!\xf5\x80\x1f\a\x0f\x9bZqe\x99\xecE\x1e\xf9͆X2\xc2\xe6\xc9\xcaM\xf8\x195l\xba.pJ\x86+IS\x06\xb8&\x12\x90\f\xb3;\xd4\xe1\xdfjgf{\xbdrf\xb0\\1>3\xe1\xa0r\x88\x9dZ]\xe3\x10;\xd9\xfeZX\xf7׃\xd5s=\xaf[\xf2\xe3\x10kS\xbb\x99\xd9\xd4j\x95=\xe3\xae,\x93\xbd\xc8#\xbf\xd9\x10KF\xd8<Y\xb9\t_\xc5ގ}7;%Õ\xa4)\x03\\\x13r\x92\xc1\xf5\x8d\xfb\xa0\xb5\xbc^93X\xae\x18\x9f\x99pP9\xc4N\xad\xceq\x10L\xb6\x03\xe4\x1aBjO\x1a\xcf\x1fo\x8e\xb9{\x8a\x1b\a\x87\xed\xeb\xb5l\xede&\xf3\x8c\x1d\xb7TM\xb2\xc6]Y\x06{\x91O~\xb3!\x93\x8c\x10{\xb2\xf2w\u007f6\x93\xfb֯\xba\x95\x94\xb7\xbc\xc3\xe7\xcb%\xc9Y\xae\xdaM8\xef\x1f}_\r0\xda07\xd9\r\x90\xdc\xfd\xd2F\xdf\x1c\x99q^\xaf\x96\x19,_\xccΌz\f\xaa\x8dЩ\x95o\xcdvu\xe5k8P\xbckg\xfbIS\xcd\xeaI\xe9i\xea\x84\u007f\xb1\x1c6\xb5uo\xed\xaa\xd1R\x9f[Ѳ\xaa\x86\xb0\x00\xbb\xb2\x8c\xf6\"\x9f\xfcf\xc3%\x19a\xf6d\xb5\xbf!\xb2\x91\xf6\xad\xa9\x8eV<\xf0Bu\xb4֑\xaf\x9d$g\xb9j7\xc1\xd7@{X\x99\x12mA\xdf\xdalS\xff\xce\xe4\x9a\xd4\xfb\xe6Ȍ\xf7z5\xcd`\xf9bvf\xd4cPm\x84N\xad|k\xb6\xab+_Û\xda2e\xf4\x0e}\x19`s)\xd9G]\xf0/\x96\xfd\x1a\xcfl\xbeo\x82\x91\xfa\xd1ڒ\tuO;+\xcbd/\xf2\xcao6\\\x92\x91\x06\xd2\xe2q\x9a%\x06\xa4\x82\xbe9\xce\\2©ҦS\xe7Ν\xde\u007f\xefd\xfd袕\xb8\x8f2$pW\xd6o8\x1aΒ\x97\xbb\x9f\xc8{\xc9H\x87\xc7i\xd6\x18\x90\xc6\xf6-\xf3\x92Ѫ\xdf\x01A\xfb\xca\xdbؿ/\x965\xc5\r\x8f\x8f\xb3\xb2~\x84o8k^\xee\xfe\x01\x92\x91_d^2\x0e\x14\xeag$\x1f\x16\xb2\xfbBN\x96/\xe9\x8d\x1f\x1f\x17ge\xfdH\xc6\x1a\xce<\x90\x8c|\"\x1b\xbc^\xfb\x1aK\x9a\xb6\xed\xd9\xd6T\xd2\x14@\"\x81V&C\xc6\x1a\xce<\x90\x8c|\"+\xbc^\xfbv\xd4UF+\xebv\x042\xd7\x02\xadL\x86\x8c5\x9cq \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\x00\x00\t \x19\xa0\x1f\xe9\xeb\xd3\xff\a\xe1\x05\x92\x01\xfa\x8b\xcf\x1a+Ƚ\x94>@\xca\x1b\xbd\u007f\xf8\x13d;\x90\x8c4\xf8\x96f¤3\xf8^\x04Mߌ\x19\x1bw\x1dW\x95\xa3\xfd\x85\x19W\xe9?\"\x98\x89\x81\x02)\x92k\x92\x91ݞ\xac\xa4\xbc\xee}A\xbcM\xb2\x16\xa6\t\xba\xafz\x93d\xc3\xffh\xba\xa6\xa4>\xc1\x86\x0f\xea?\u007f\xc5\xd8\xc3~\x9e\x9bz\f\x14\xc8nrE2\x120\xde\xcc\x02O\xd6\xf6\x17jF\xef\x11ś\b\xcd?=\x8cBy\x12t_\xf5&Ɇk+6<T\x92\xe0OU\xec'o\x98\x9b\xf6o\x10敛in\x90+\x92\x91\x90\xf1f̏K\xf7\xbf'k\xdf\xdcjA\xb4\x8d\xe8\x13\xdb\xcb(\xd4&q\xf7UO\x92j\xf8+\xb2\x8e\xf6%\xfa;\xb9\xa2\xdf*\xcd/7\xd3\xdc W$#!\xe3M\x81d\xf4\xbb'+\xef\x05\x90 \xfeF\xa1\x89\xbb\xafJ\xe1\xdb\xf0Q\"q:#\x96\x8c|r3\xcd\r\xc2%\x199\xe0\xc9\xdaPI\xf9zyoO\xdb\xfcSl\x14\xeaٚ\xc0}\x95ږ\xab\\\xbe\xee$\r\x84\xae\xa3\xbe\r\xf7^\xa5\a<Fy\x93Y\xca{\xbdr\xddd\v\x18\xef\x98\r\x1e$\xf6\xe9\x99\xc0\xcdTԚ#u\xeb\x85\xf5\xe8\x10H#ᒌ\xd0{\xb2\x1eYJV9\xeaux{Z\xe6\x9fb\xa3P\xcf\xd6\x04\ueadc\xe5*\x97\xaf;I\x13\x91\xeb\xa8\u007f\xc3\x1f\xb4o%\xcd\xed\xda\xefu\xdb&\xa8\x0e\xafW\xbb\x9b\xe7\xfe\xbe\xa7\xa6\xcc҆ޫj\xde\xfc\xd48\x15\x12\xb8\x99\x8aZs\xa4n\xbd\xb0^\x1d\x02\xe9#d\x92\x11~Oֆ>g1\x97\xb7\xa7a\x98!6\n\xf5jM\xe4\xbe\xca[\xae\xda\xf9\xba\x92\xe4\x88u\x1dM\xa0a\xebĄ3A\xe5\x1a\xe6\x8a\xcdW\xbbΝİ\x9f\x037~\x8c=v\xa0\xbcZ\xb36\xb9\x17ֻC M\x84N2B\xed\xc9\xfaΎ\x9a\x92\xe3\xceb.oOc抍B\xbdZ\x13\xb9\xaf\xf2\x96\xabv\xbe\xae$9b]G\x13h\xd8^˰MP\xb9\x86\xb9b\u007fm\xdb0c\xb2\xb5P\xda]1m\xdd.#\xe7\u0601\xf2j\xcdڴ_X\xea\xdd!\x90&B'\x19!\xf7d=]\xb8\xc1Y\xcc\xe5\xedi\xce\\\xa1Q\xa8Wk\"\xf7U~\x99\xd5\xceו$G\xac\x1fX\x02\r[\x92\xc1\x99\xa0r\r;\x8a\xd1v۰d\x9f\xeeMol\xbb\aʫ5k\xd3~a\xa9w\x87@\x9a\b\xb1d\x84ӓu\xe2\ng1\x97\xb7\xa71s\xc5F\xa1^\xad\x89\xdcWy\xcbU;_W\x92\x1c\x9e\x92\x11\xafaK28\x13T\xaeaG1\x8f+&\x82\x81\xf2j\xcdڴ_X\xea\xdd!\x90&B,\x19\xe1\xf4d\xadXrp\x15_\xcc\xe9\xedi\xce\\\xb1Q\xa8gk\x02\xf7U\xder\xd5\xce\xd7Y\x8cG$\x19\xbe\r[\x92\xc1\x99\xa0r\r;\x8ayH\x86`\xa0\xbcZ\xb36\xb9\x17ֻC M\x84L2B\xec\xc9j\xdc0][\xdfx\x13\x9f:\xe7\xedi\x9b\u007f\x8a\x8dB\xbd[\x13\xb9\xafZ\x96\xab\xd4\xce\xd7U\xccD\xec:\xea۰~\xc5D39\xe0MP\xb9\x86\xf9WH\x15G\xeb\f\xe4\x1d\xfbz\xab\xc8\xcdTԚ#u\xeb\x85\xf5\xe8\x10H#ᒌ0{\xb2\xb2\xdb#ZԸ\xea\xf2\x1d\\1\xde\xdb\xd36\xff\x14\x1b\x85z\xb6&t_\xb5,W\x19F\xbe\xeeb\x06b\xd7Q\xbf\x86{˴\xcd\"v\x15\xd6a\x82\xca5̽B\xf4\xefE\xf7\x1d\xfc\x8c]V\xfe\xec\xfd\x05Q\xd3IY\xecf*h͑\xba\xf5\xc2zt\b\xa4\x91pIF\x1aȰ'k@\xa6\xa2i\xe9Eд\xceԔ~>!S\xcd\vD\x89\x0f\x14\xc8\x16\xf2^22\xec\xc9\x1a\x94\xa9h\x1az\x91\x06N\x1dT\x8f.>;\xf0\xa9\xf9Xb\xa0@\xb6\x00\xc9\xc8,y\xec\xed\t\xc2\t$#\xb3䱷'\b'\x90\x8c\f\x93\xbfޞ \x9c@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00H\x04\xd8\xc9\x1a@2\x00\xf0\x05v\xb26\x90\x8c4\xb8\x99f\xbb\xd5h\xf0=\xceq`'ˑk\x92\x91\u007f\x9e\xac\xed\xa3\xc9\xdc>\xfa\n!\xa3\xed\xdfӌO\xaa\xfe\xad\xbe$ы\x14H\xb25\xd8\xc9&I\xaeHF\xfez\xb2\xf6\xec\"%\xed\xb4\xfb\x15\xb2+\xc6BHL\xca\xfe\xad6\x1e\x99\t{\x916\x92\x183\x06\xecd\x93$W$#\x8f=Y\xbbIC\xa3z\fE\x12\xf4F\r\xc0\xbf\xd5\xc2+\xb3\x04?\xbc\x03\"\x891\x83\x9dl\xf2\xe4\x8ad\xe4\xb1'k7\xd9\xf7\xbad\xee\x00\x00 \x00IDATUړ\xb8d\x04\xe9ߚ\xbd?\xd5\xeb\x9b\x19\xecd\x93%\\\x92\x01OVAk\xdd\xe4\xf8\xad\xaf\xe8\x92aY\xa3z\f\x14\xb5{̹\xaf&R\xccF\x94\x19\x9f\x8e\xd0\xe0\x95\xef\xa6\x10\xd8Ɇ\x86pI\x06<Y\x05\xad\xa9\x92\xb1\xae^\x97\f\xdb\x1aU<P\xd4\xee1羚H1\vaf\x8e\u038b\f^\x1d\xdd\x14\x01;\xd9\xd0\x102ɀ'klk\xaad\xfc\xbd\xf8\xef\x9adp֨^\x03e\xf7\xd8v_M\xa0\x98\x8583W\xe7c\r^]\xdd\x14\x01;\xd9p\x10:ɀ'\xab\xbb5U2h\xfd:}-öF\xf5\x1a(ۿ\x95s_\xf5/f!\xce\xcc\xd5\xf9X\x83WW7E\xc0N6\x1c\x84N2\xe0\xc9\xean\x8dI\xc6+7k\x92\xc1Y\xa3z\r\x94\xed\xdfj\x0fT\x02\xc5l\x84\x99\xb9:\x1fk\xbd\xe6\xea\xa6\b\xd8Ɇ\x83\x10K\x06<Yu\x98d\xf4\x94\xeeb\x92\xc1Y\xa3z\r\x94\xddc{\xa0\x12(f!\xce\xcc\xd5\xf9\xd8I\xec\xea\xa6\b\xd8Ɇ\x83\x10K\x06<Yu\x98dЇ\x1a\x98dp֨^\x03e\xf7\xd8\x1e\xa8D\x8a\x99\x883sv^0\x89\x9d\xdd<\xde,\xb8\xd3\nv\xb2\xe1 d\x92\x01O֘\xd6zv\x91W\xbai{\t\x93\f\xdb\x1a\xd5s\xa0\xcc\x1e\xf3\x03\x95H1\x13af|\xe7\xc5\x06\xaf\\7U\xeaI\xa9\xeb\xbeK\xd8Ɇ\x86pI\x06<Yc[\xdb3\x9a\xdd \xd2WS\xa1\xf6ӲF\x9d\xeb9Pf\x8f\xf9\x81J\xa8\x98\x8103\xbe\xf3b\x83W\xae\x9b*\x9bK\xed\xc5\x01\x1d\xd8Ɇ\x86pIF\x1aH\x8b\x9bi\xe2V\xa3\x01y\xb2ʐ\x96\x1e\xfb\xe0\xeef+\xe9\xb7\xee\x06\x02\xecdm\xf2^2\xd2\xe1f*a5\x1a\x94'\xab\fi\xe8\xb1\x1f\xcen\xf6\xbdX\xd6\x147<\v\x81\x9d\xac\t$#\xb3\xe4\x89'\xab\xb3\x9b'˗\xf4Ə\a\xd9\v$#\xb3\xe4\x89'k\x9et3/\x80dd\x98<\xf1d͓n\xe6\x03\x90\f\x00\x80\x04\x90\f\x00\x80\x04\x90\f\x00\x80\x04\x90\f\x00\x80\x04\x90\f\x00\x80\x04\x90\f\x00\x80\x04\x90\f\x00\x80\x04\x90\f\x00\x80\x04\x90\f\x00\x80\x04\x90\x8c48\x94f\x8f_g\xf0}\xeb_\xb2g$\x81I\xaeIF\xf6z\xb2&_\uf87aҊ\x86=\x151\x93ߣC\x1c~\xee\xab\xfe5\x18$\x9b:GR\xbd\xc8_\xe7\xd3\xec%W$#\xfb=Y\x93\xae\xb7\xad\xb4f\xe3\xd6ل\x1cq?!\xee\x10\x87\xaf\xfb\xaao\r\x06ɦΑl/\xf2\xd5\xf94{\xc9\x15\xc9\b\x81'k\x92\xf5~5q~/\xa5\xddձ\x93M\xd8!\x8eD\xdcW\xe3\xd7`\x92d\xea\x1c\xc9\xf7\"O\x9dO\xb3\x97\\\x91\x8c\x10x\xb2&Y\xef\xb2\x12\xed\x97\xe3\xd6\xc8O\xb6D\xdcW\x13\x93\x8c$S\xe7H\xbe\x17y\xea|\x9a\xbd\x84K2B\xedɚ\\\xbd\xb4Z\xb7\n\xfbbM\xafW\x87x\xfbP\xdbT\xd4\xee\x9b\xc3jT\xa6\x06\x8b\xe4R\xe7\x87$\xe9^\b\x9dOA\x06\t\x97d\x84ړ5\xb9z{\v\xb9syq\x878\xefT\xceT\xd4\xee\x1b\xbfW\xaa\x06\x8b\xe4R\xe7\x02\x92\xef\x85\xd0\xf9\x14d\x90\x90IF\x98=Y\x93\xab\xf78w6 \xee\x10W\x19\xeffj\xf7\x8d\xdb+W\x83MR\xa9s\x01\xc9\xf7B8\x92 \x83\x84N2\xc2\xeb\xc9ʐ\xaf\xb7\xb7\xc8\xfe\xc0\x17w\x88\xab\x8cw3\xb5\xfb\xc6핫\xc1\x81|\xea\\@\xf2\xbd\xf0\x1aI\x90)B'\x19\xe1\xf5dM\xb2^c\x15\xa0\xb7ͫC\\,\xeffj\xf7\x8d\xdb+W\x83E\x92\xa9s\x01I\xf7B4\x92 \x93\x84X2\xc2\xe6ɚd\xbd\xcbJ4\a\x81m\xe4\x94G\x87\xb8X\x87\x9b\xa9\xd57n\xaf\\\r\x16I\xa6\xce\x05$\xdd\v\xd1H\x82L\x12b\xc9\b\x9b'k\x92\xf5~5\xf1^v\x95\xa1v\x9aW\x87\xb8X\x87\x9b\xa9\xd57n\xafd\r&I\xa6\xce\x05$\xdf\v\xc1H\x82L\x122\xc9\b\xb3'kr\xf5\xaa\x93i\xdc\xdc\x17[\xeb\x8a\xd8ѹ\xb8C\\,\xeffj\xf7\x8d\xdb+W\x83Ir\xa9;\x02\x92\xee\x85\xc8\xf9\x14d\x90pIF\x98=Y\x93\xac\x97\xb2og\x8c\xbbf\xfea\xb6\xe5\xd1!.\x96w3\xb5\xfbf\uf56c\xc1 \xb9ԝ\x01I\xf6B\xec|\n2G\xb8$#\r\xa4š4K\xfc:\xd3ҷ\xfe%KF\x12\xd8\xe4\xbdd\xa4á4k\xfc:\xd3з\xfe%kF\x12X@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\xd2\xe0[\x9aa'\xd1\xe0;\x1462\xfc\x02\xe46\xb9&\x19\xf9\xe4\xc9ꁟ\x11\xab\x1f\xbb*vx?\xf9\x02\xfb\x05\x8c\xf2\xba\xf7\xbd#\x18\xfaP7\x11\xcdW`\r!M\xae\xe7\xe36A\xb9\x1e7\xaa\xad\x8d;\x1a7V\x04\xac\\\xd3H\xaeHF>z\xb2\x8a\xf15b\xf5cGi\x1c\x13\x803/\x92\xe7\xda_\xa8\x19\xbd\xc7;\x84\x9aC\xfdii\v\xfb\xfd\xbf\xafZ&|\xeaz\xdenb\x8f\xe8'\xb7\xec\x1e\xff\xad\xbd}\xbd\xf9\xab\xc7R\xc0\xca5m\xe4\x8ad\xe4\xa7'\xab\x80D\x8cX}\x88{\x8cr\x88\xf9\x8f\xf4ͭ\x8e\x17C\x8d\xa1\xbeI\xff)\xbeͳc\x9e\xb6\x9a\xb0_7\x1bg\x8f\xf7%%\x19\xb0rM\x1b\xb9\"\x19\xf9\xe9\xc9* \x11#\xd6T\xd0$\xc3û\x80C\x1b\xea{\x9fѶ\u007fz\xafw\x1c\xff\x13\xcb&\xce\x1e')\x19\xb0rM\x17\xe1\x92\fx\xb2\x1a\x1dZH\xa2\x1b\x8dnr\x9b|\x87\x84F\xac\x9e\xc5,N\x97\x10R\xb8U\xdf\xe6\x86\xcfF\x97\x8c\x86J-\xc0J\xf2\xcc}\x95Ѫ\xfa\x83Z\x84=\xd4\xcb\xf4C\x88\a\x969F\xc7n\xc2\xf1\xba\x89{\xccI\x06\x97\xce\x1buU\xd1\xf2\xfa\xa9}T<\x92Z8\xac\\\xd3D\xb8$\x03\x9e\xacF\x87>\xdaZD*\x9a\u007f6\xf1^\xc7&\xf53b\xf5,fs\xa0\xbd\xbd\xb8\xd9\xd5\x1a\xcf!\xb2\xb3\xe7\xc8R\xb2\x8am\xdb6\xaa;HӞm\xf5\x85\xfb\xa8c\xa87\xd7\xd0w\xaaަ\xb7nt\x8e\x8eՄ\xe3u\x13\xf7\x98\x93\f;\x9d\xfd\xa3\x1b^ٵ\xb1\x9c\x9c\xa3R/\x00\b\x84\x90I\x06<Y\xcd\u007f\xa3e\xea\xf1A\x03\xeb&\xbf\xe9g\xc4\xeaU\xccA\x89.\x19|1\x9bC\xdaqA\x03\xfb\x80\xe7mT\xb7\xa92\xd7w\x13\xfb\xd9wn\xa8\xdb\xcb\xe9\xd2\xe8RZ\xae\xa9\x98ctJ̳G\xebu\x13\xf7\x98ڒ\xc1\xa5\xb3\xbe\x82\x89\xc5\xfa\xb2>\xc9\x17\x00\x04A\xe8$\x03\x9e\xac\xacCj7\x1f\xa2\xe6\xe2\f\xb7\xe9c\xc4\xeaÝ1\x9f\xf9b6\x87\xc8\xcf\xde\xd9QS\xc2Z\xe1{\xf1\xc5\xfa\xba\x1b&\x92\xd9\xd41\xd4\u007f%=w4\xcc\xed\xd6Sr\x8cN\xacd\x88{Lm\xc9\xe0\xd2\xf9\xb4rڢ\x8d\x1f\xf4\xf5R\xf9\x17\x00\xa4L\xe8$\x03\x9e\xac\xacC|7\xf9M\x1f#V\xcfb\x0e\x8c\xf9\xcc\x17\xb3\xd1\xd62N\x17n\xa0\x8e$\xf7UT-mm\xafU%\x83\x1f\xea\xbe臥\aJ?\x8cj\xeb\x0f\x8eщ\x95\fq\x8f\xa9-\x19|:\xa77\xdc7\x83\\\xd3\xd2'\xf7\x02\x80@\b\xb1d\xe4\xb3'\xab\xe7\u070fo\xc4*%\x19|1\x1b}\xf9s\xe2\n\xeaHrF\r\x13\xa8\x05\xaad8\x86\xba\xba\xa5\x92V\xae\xd1/\xc8:F\xc7)\x19\xecu\x13\xf7\x98ڒ\xc1\xa5s`\x99\xbayzk\xc9z\xb9\x17\x00\x04B\x88%#\xaf=Y=\xe7~|#V\x19\xc9\xe0\x8bQz\xfc\xb9c\xda_]2*\x96\x1c\\\xc5'Y\xc5&k\xdfͪd8\x86\xba\xae\xe6^z\xef\xdc:\xad\xa0\xe3r\xaa%\x19\xd6\xeb&\xee1\xb5%\x83K\xa7Y__\xa9m\x92{\x01@ \x84L2\xe0ɪw\x88릣\xc7>F\xac\xde\xc5Lz\xdfno/nl\u007f\xe3\f_\x8c1\xdf0J<\xa8M\xd7\xda\xfaƛ\xf8$\x9b\xc9}\xebW\xddJ\xca[\xdeq\f\xf5\x92\xd1-\xb4e\xb4z\xdc\xc4w\x93o\xc2z\xdd<z\xfc)\xbb\xfbs]{\xfb_\x1d\xe94\x93\xd2\x15;\xd4\xd8=T\xea\x05\x00\x81\x10.ɀ'\xab\xd1!\xae\x9b\x8e\x1e\xd3\xf8F\xacq\x8a\x19\xec\xd7\xf3!\x1b\xa8c\xf8(}\xa1\x82\xed\xa2\xec\xe6\x91\x165\xed\xear\xf6-\x11+ɾ5\xd5ъ\a^\xa8\x8e\xd6:\x86z縃\xf4Pi\xab\xb3\x9b|\x13\xd6\xebF\xc5=~H\x0f%\x0f8\xd2\xf9\xf5\x1d\xcdUъ\xda=\x8eb\xfe/\x00\b\x84pIF\x1aH\x8boi&\x9dD\xd3ҡ\xb0\x91\xc9\x17 \xd7\xc9{\xc9H\x87oif\x9dD\xd3С\xb0\x91\xd9\x17 ǁd\x00\x00$\x80d\x00\x00$\x80d\x00\x00$\x80d\x00\x00$\x80d\x00\x00$\x80d\x00\x00$\x80d\x00\x00$\x80d\x00\x00$\x80d\x00\x00$\x80d\x00\x00$\x80d\x00\x00$\x80d\x00\x00$\x80d\xa4\xc1\xc24Ö\xa0\x01t\xa8\xc9m\x89\b\x92$[F2\xb8\xf7d\xaeIF\xcey\xb22\x13T\xdd\xdddsk\x91\xf1\xeb\x11E\xad\xdcf\xdbh\xf6wr\xfd\x11\xb3D\xaa\x9e\xac*GȲx#\x19\x8f\xc4L[\xe5I\xde\xe05\xa3d\xcdH\x06gS\x9b+\x92\x91\xb3\x9e\xac\xcc\x04\xf5\x14=\xd5B^<\xd3B\x8cߨ\x1a\xdd\xc2m\xf6\xbc\x19ml߳\xae\xba\xe4#\xbd@R\x9e\xac.kԆ\xe2S\xae\x91\xe4\x02\x846\xaa\x16\x89\x99\xb6ʓ\xb4\xc1k?\x93e#\xc95\x11\x94Mm\xaeHF\xeez\xb2\xea?\xb6\xb9\x87\x1c\xa2\xeb\xa2\xc6/a\x96\xac\xe36\x8d\x1ewW\xea?\xb1\x99\x9c'\xab\xd3\x1a\xf5\xe8\xe8\xc7\xd8\x1f~$\xb9\x00\x91\x8d*G\x82\xa6\xad\xd2$i\xf0\x1a4\xe6\xbbċ,\x1bI\xbe\x89\x80ljsE2rדՖ\x8c\xdeO\f\x9d\xf8\xa4\x97\xdb4{\xdc\\\xa2M\x9d\xe4<Y\x9d֨\x0fE\xb5\xdf\x03\xe5G\x92\v\x10٨r$h\xda*M\x92\x06\xafAc\xbeK\xbcȲ\x91\xe4\x9b\bȦ6\\\x92\x91\x8f\x9e\xac\xb6d08SckS\u007fC\xb6\x14\xb1_\x147;\xb4B\xadf+ݪ\xfe\xbb\xc2\xce\xc0i\xc4*\x1e>\x95\xe3E\xba}\x825\x92\\\x00\xb7\xb9\x90\x14\xadk\xaa\x9c\\\u007f\x94:\x10\x9b\xb6\xda6\xaa\x8eb\"\xb7X\xb1\xe5j\x92\x06\xaf\xee\x97%\x06G\x00\x97o\xf7\xd2\x19\xa5w\xbc}m\x9b#\xd8~\x97dp$\xad\xcc\x16\x92\u0097\xad\x15:\xd1P\xbb\xd3\tƦ6\\\x92\x91\x87\x9e\xac\x9a\tjOO\x9b\x9fd\xf4ݢ\x1d\xb1\x9b\x1d:\xf5\xfd\x1a\xb5\x9a\xee7\xe76\xf0?\xea\xe70b\x15\x0f\x9fJ\x93q\x00k\x8d$\x17\xc0m\xb2ʦ\xaej\x9e:\xce\xf9\xb1+6m\xb5mT\x1d\xc5Dn\xb1b\xcb\xd5$\r^\xdd/K\f\x8e\x00\xbb\xb5\xd37\x94\xafi[h\xfc\xa6\xb1\x85\xfd.\xc9\xdcHڙik$\xe6\n\x9dh\xa8\xdd\xe9\x04cS\x1b2\xc9\xc8?OV\xc3\x04\x95ē\x8c\x15==\a\xef%\xbbضա_\xebW\x87f\xba\xd6Bm#V\x8f\xe1cW\x96\x8c\xdf\x1c\xb7G\xd2\xe3p::M\xcd\xfat\x95\xdbN\x8d\xe16m\xe5lT\xb9bb\xb7X\xb1\xe5jr\x06\xaf\xeeX\x11V\x00W\xac\xb1\x8cy\xdb-qI\x06\xff.\xc9\xd4H\xf2\x99\xd9V4\x1eC\xed<\xf7\tƦ6t\x92\x91o\x9e\xac\xcc\x04u\u07fe}k\xe2I\x06{g\x95\xebK$V\x87\x0e\x16\xf6\xf6\xfc\xfa\xf4\xb9\xe8A\xea\xc06b\xf5\x18>\xf509jTa\x8f\xa4\xd7\x1b][i]O\xbe\xa2\x1cb\xd3V\xceF\x95+&v\x8b\x15[\xae&g\xf0\xea\x8e\x15a\x05\xd8\xc5\xfa\xc6iu~\xe4\x92\f\xfe]\x92\xa1\x91tdfK\x86\xc7P\xbb%C\xf4\x9e\x94%t\x92іo\x9e\xac\t\xace4\xed\xdb\xf7\x89q\xd9\xc0\xeaPo\xd1\xc15dő\xc2^\xea\xc0\x1e\x1d\x8f\xe1\xa3'\xa3?\x8a\x89\xf5z\xa3k\xef\xdev\xa7ɐش\x95\xb3Q\xe5\x8ay\xb8\xc5\n-W\x934xuŊ\xb0\x02\xecb\u007f\xd3\x17\xa9\xbb]\x92\xc1\xbdK25\x92\x8e\xcc\xc49pC플`ljC,\x19y\xe2ɚ\x80d\x98}\xa0|\x87fl\xad\x9d;\xa3\xd5}\xf3\x9a=:\x1e\xc3G\x97\x14\x1e\x8b\x89u\x04pC\xbd\x84=\xdeH\x1c\a\xfdb\xd3V\xceF\x95+&v\x8b\xf5\xb0\\M\xce\xe0\xd5\x15+\xc2\n\xb0\x8b\xf5\xe9u\x1ev\x9f\x98\xd8\xef\x92L\x8d\xa4#3\xad\xdeg\xa2\xd4s\xa8\xf9\xd6D\xef\xc9d\b\xb1d\xe4\x89'\xab\x9cd\xd8\x1d\xfa\xfe\xa2h\x1bY\xf8\x00ub\x8f\x8e\xc7\xf0}Vl\xd96\xf3ot;\x80\x1f\xeakԷ`\xf7\r\xb5ZD|\xd3V\xceF\x95+&v\x8b\xf5\xb0\\M\xce\xe0\xd5\x19{\xbcYp\xf7\x94\x15\xc0\x15[P\xaeN\xbe\xbe\x86\x98\xb5\f\xeb]\x92\xb1\x91\xe43\x1b\xb7Tݬa\xf5z\f5\xdfZP6\xb5!\x93\x8c\xfc\xf3d\xe5\xee\xfeTw\xbf\xbf\x9e\xac3*67\xd9ݟ\xd6\xcd\xe2\\\x87\x9e\x1b7\xb1\xaf\xbad\x15\xe5q\x8c\x8eh\xf8(}|\xf4QA,\x17\xc0mF\xc9-\xdb6W\x97\xe9\v\xae~\xa6\xad\xb6\x8d*WL\xe4\x16+\xb6\\M\xd2\xe0\xd5\xf5\xb2ԓ\xd2\xd3ԁ#\xc0n\xed\xb3\x8a\xaa\xf5\xad\xf3\x8bc%\xc3 s#\xc9g6\xb7\xa2eU\r\xd1\xde\xd5\xe2\xa1\xe6[\vʦ6\\\x92\x91\x87\x9e\xac\xf6wL6\xaa\xf2\xc0:V\xa2M\x0fk\xb3M\xfd;\x93k\xc6\xecЁ\xb2\x15\xb4\xa5t\x1f\xe5q\x1a\xb1\n\x86\x8f\xfe\xbd\xa4A\x18\xcby\xa7ڛ\xd1\xc7\x1b'V6\x186\xd0\xf1M[y\x1bU\xae\x98\xc8-Vl\xb9\x9a\xa4\xc1\xabk|7\x97\x12爸\x02\xec־h\xac*\xa9=\xe0)\x19\x99\x1bI>\xb3\xa3\xb5%\x13\xea\x9ev\xe5\xe0\x18>\xae\xb5\xa0lj\xc3%\x19i -\x16\xa6\x99\xb4\x04M\xadCO\x13\xee\x88\xc5\x0f\xc7\x19Q\xe2$Y,\x10Z\x89\xeb(#.\xee\xe5O\x19\xd2;\x92\xf2\x99\x05\xf6\x9e\xcc{\xc9H\x87\x85if-AS\xeaЏ\x9a\xfc\"8\xa4\xdf\xe8:I\x16\v\x80\xbe\x17\xcbd\xfa\x97\xc4ĴI\xefHJg\x16\xdc{\x12\x92\x01\x92F\xfa\x8d\xae\x93d\xb1\x008Y\xbe\xc4u\xd19>\xd2\x133Y\xa4\x87\xa4\xdf2\x8b\x05\x92\x01\x92䤶\xaa\xe7\x17\x15C\x92\xc52\xc1\xd16\xf2\xd8[\xfd\x90\xaa\xfc\x90\xf4Wf\" \x19 I\xb4U\xbd\xe3T\x96$\x8be\x82\xb9j\xaaE\xae\uf2a5\x03\xf9!\xe9\xaf\xccD@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x00\x00\x12@2\x82\xb00u\x11\x9c\xffez\b\xbe\xc7\xfdK\xb6\x8fon\x93k\x92\x91\x93\x9e\xac\xc19sj\xf8\x99\xb6z\fT,Iu\xc8ɡ\xbaҊ\x86=\x151\x12\x167\x87\xe0\xfcE\x81<\xb9\"\x199\xed\xc9\x1a\xa43g\x02\xa6\xad⁊%\xb9\x0e9h+\xadٸu6\x89\xfdi\t\x9f\x1c\x82\xf2\x17\x05\xf2\xe4\x8ad\xe4\xb8'k\x80Μ\x89\x98\xb6\n\x06J@\x92\x1d\xe2\xf8j\xe2\xfc^J\xbb\xabE\xbfF\x13?\x87\x80\xfcE\x81<\xb9\"\x19\xee\xdfw\x17\"x\x17\x86œ58g\xceDL[\x13\x93\x8c$;ı\xacD\xfb\xed\xba5\xf2\x92\x11\x90\xbf(\x90'\\\x92\x91\xbf\x9e\xac\x819sZ=\xa6\xf4\x93\x05\xe5ъz\xe6\xae\"\x1e(\xae2.\xd6&\xb9\x0e\xf1\x03U\xad\x1b}|\xb1\xa6W:\a\x81\xbf\xa8\xa8\t\xa7\xe5\xaaل\xafS+\xf0&\\\x92\x91\xaf\x9e\xac\x01:sZ=\xa6{Joi\xd9\xd5L\xd8H\x8a\aʮ\x8c\x8f\xb5I\xaeC\\@o!\xb7\"!\x99\x83\xc0_TԄ\xe3e\xb1\x9a\xf0uj\x05ބL2\xf2֓50gN\xab\xc7=Uu\xeal\xef\xdd\xf6\x95\xd7@q\x95q\xb1<\xc9u\xc8\x0e8Ν\xd3\xc8\xe6\x10;\xbe^\xaf\x85\xb5\xc9;\xc0\xfa;\xb5\x02\x0fB'\x19\xf9\xe8\xc9\x1a\xa43\xa7\xd5\xe36\xf2\x81\xb9O<P\\e\\\xac\x8b$:d\a\xf4\x16ه-\xb29Ď\xaf\xd7kam\xf2\x0e\xb0\xfeN\xad\xc0\x83\xd0IF~z\xb2\x06\xe7\xcci\xf5\x98[P\x15\x0f\x14W\x99x\xf15\xc9\x0eq\x01\xc6ZFo\x9b|\x0e\xb1\xe3\xeb\xf5ZX\x9b\xbc\x03\xac\xbfS+\xf0 Ē\x91W\x9e\xac\x819sZ=\xdee{g\x89\a\x8a\xabl\x97\xd0g+\xc9\x0eq\x01\xcbJ4\xfb\x84m\xe4\x94t\x0e\xb1\xe3땃\xb5\xc9;\xc0\xfa;\xb5\x02\x0fB,\x19y\xe5\xc9\x1a\x9c3\xa7\xd9\xe3\xee\x8aZvֲh\x89\xd7@q\x95q\xb1\x1cIv\x88\v\xf8j\xe2\xbd\xecZI\xed4\xe9\x1c\x04\xe3땃\xb5\xc9;\xc0:]]\x81\x04!\x93\x8c\xfc\xf3d\rܙ\xd3\xea\xf1\x9e\xe2\x99\x1b\xda\x16\x91\xcd\xd4k\xa0\xb8\xf1\xe5bm\x92\xeb\x90#\xa0m\xdc\xdc\x17[\xeb\x8aޔ\xceA\xe4/*j\xc2њՄ\xeb\xc5\x022\x84K2\xf2Г5hgN\xae\xc7\x1f\xdfw\xed\x84\x1amM\xc4c\xa0\xb8\xf1\xb5cm\x92\xeb\x903\xe0Pݸk\xe6\x1ff[R9\x88\xfdE\x05M8Z\xb3\x9ap%\td\b\x97d\xa4\x81\xd4,L=\b\xcc\xff҇\xa4<\xb3\xd2\xd2\xe3\xfe\xa5\xbf\xc6\x17\b\xc8{\xc9H\xcd\xc2TLp\xfe\x97>$%\x19\xe9\xe8q\xff\xd2o\xe3\v\x04@2\xc2Lr\x92\x01@\n@2BL&\x9d9A\xbe\x02\xc9\b1\x99t\xe6\x04\xf9\n$\x03\x00 \x01$\x03\x00 \x01$\x03\x00 \x01$\x03\x00 \x01$\x03\x00 \x01$\x03\x00 \x01$\x03\x00 \x01$\x03\x00 \x01$\x03\x00 \x01$#\r\x0e\xa5Y\xe9\x19\x1a|7\x93$+G\a$L\xaeIF6{\xb2R\xfa\x8f\xa6kJ\xea\x13\xf8RH\x06\x8cX\xe3\x11l:pT\r7\xb9\"\x19!\xf0dU\xa9\xad\xd8\xf0P\xc9i\xd13N2`\xc4\x1a\x8f\xa0Ӂ\xa3j\x98\xc9\x15\xc9\b\x81'\xabzHN\xd6\xd1>\xf7\xaf\xdc\nɄ\x11\xab\x00sH\x82N\a\x8e\xaa!&W$#\x04\x9e\xac\x94\x1e%;bw\nɄ\x11\xab\x00sH\x82N\a\x8e\xaa!&\\\x92\x11fO\xd6ޫ\xf4$\x1fs\xc5r\xae\xa3i7b\xf5jت\x97\x87\x1b\x92\x80\xd3\x11:\xaa\x82\x90\x10.\xc9\b\xb5'\xeb\a\xed[Is;\xfb\xe5sG,\xe7:\x9av#V\x8f\x86\xedzy\xb8!\t8\x1d\xa1\xa3*\b\t!\x93\x8cP{\xb2\xf2'&V,WC?\x18\xb1\x8a\x1b\xe6\xeb屆$\xe0tģ\x03\xc2A\xe8$#̞\xac\xbcd\x98\xb1\\\r\xfd`\xc4*l\xd8Q\xaf\r7$\x01\xa7\xe3\xe5X\v\xc2@\xe8$#\xbc\x9e\xacN\xc90c\xb9\x1a\xfa\xc1\x88Uذ\xa3^\x1bnH\x02NG<: \x1c\x84X2\xc2\xe6\xc9\xea\x94\f3\x96\xab\xa1\x1f\x8cX\x85\r;\xea將$\xe0tģ\x03\xc2A\x88%#l\x9e\xacN\xc90c\xb9\x1a\xfa\xc1\x88U\xdc0_\xaf\x03sH\x82NG8: \x1c\x84L2\xc2\xecɪ_1y\xa7\xcfe\t\xca\xf5\"\xedF\xac\x1e\r\xf3\xf5\n\t:\x1d\x91\xa3*\b\tᒌ0{\xb2\xf6\x96i\x01EGܱ\\/\xd2m\xc4\xea\xd50W\xaf\x88\xa0\xd3\x11;\xaa\x82p\x10.\xc9H\x03iq(M\xabghR\x16i\tt3\xa9z\x93)\x96\xd6\xd1\x01\xe9&\xef%#\x1d\x0e\xa5\xe9\xf5\f\x95\x9f\xa3\f\xffn&W\xaf|\xb1\xf4\x8e\x0eH7\x90\x8c\xd0!=G\x13$\xc9z\x93,\x06\xc2\n$#l\xa4ˈ5\xc9z\x93,\x06B\v$#l\xa4ˈ5\xc9z\x93,\x06B\v$\x03\x00 \x01$\x03\x00 \x01$\x03\x00 \x01$\x03\x00 \x01$\x03\x00 \x01$\x03\x00 \x01$\x03\x00 \x01$\x03\x00 \x01$\x03\x00 \x01$#\rf\xa5\xd9\xee:\x1a|\x8f\x03%ۇ/\xcf\xc95ɀ'\xab?\xa9سr\xa4-I\x98\xb6f5\xb9\"\x19\xf0dM\x98\x94\xecY9Ҙ$L[\xb3\x98\\\x91\fx\xb2&J\x92\xf6\xac\x1cA:\xb5z\x00\xd3\xd6\xec%W$\x03\x9e\xac\x89\x92\xa4=+G\x90N\xad\x1e\xc0\xb45{\t\x97d\xe4\xbb'\xab\xe5q\xba\x90\x14\xadk\xaa\x9c\\\xaf}\xeb\xdc\xea\xe6B\x12\xddhuފu\xd4\xe0k\xcf*n\xc2\xc6ߩ5\x80$aښńK2\xf2ܓ\xd5\xf68\xfdhk\x11\x99\xba\xaay\xea8\xa6nV7\xd9ފ\xe6\x9fMd\x9d\xb7c\x1dM\xf8ٳz4a\xe3\xeb\xd4\x1aD\x920m\xcdbB&\x19\xf9\xed\xc9\xca{\x9cF\xa7\xa9\x85OW\xd58\xbaI\xa3e\xea\x87w\x03\xeb<\x17\xebH\xd2ǞU܄\x03\x1f\xa7\xd6 \x92\x84ik\x16\x13:\xc9\xc8cOV\x87ǩ\xbe\x88\xb9\x9e|\xc5uS\xdd\xfb\x105:\xcf\xc5:\x92\x8co\xcf\xea\xd1\x04\x87\x9fSk I´5\x8b\t\x9dd\xe4\xb1'\xab\xc3\xe3T_\xe5m'\a\xb8n\xf2\x9d\xe7b\x1dIƷg\xf5h\x82\xc3ϩ5\x90$aښńX2\xf2Γ\xd5\xe1q\x1a]\xc2Jo$g\xb8n\xf2\x9d\xe7b\x1dIƷg\xf5h\x82\xc7ǩ5\x90$aښńX2\xf2ϓ\x95\xf78\x8d^\xa3Ω\xee\x1bj\x1d\xdd\xe4:\xcf\xc5:\x92\xf4\xb1g\x157\xe1$\xbeSk I´5{\t\x99d\xe4\xb7'+\xefq\x1a%\xb7l\xdb\\]ƒ\xb4\xba\xc9w\x9e\x8f\xe5\a\xcaǞգ\t!iL\x12\xa6\xad\xd9K\xb8$#\xcf=Yy\x8f\xd3\xe8\xe3\x8d\x13+\x1b>c\x9bV7\xf9\xce;\xfcP\xb9&|\xecY=\x9a\x10\x91\xc6$aښńK2\xd2@\x02f\xa5\xf2\xf4\x83\xebh\x9c\x9b\\}H\xb8\xc7\xc97a\x92d\r\xfd0| i\xf2^2\x120+\x95\xa6?\\G\x93\x9c\x8d\x8cD{\x9cB\x13\x06\xc9\xd5\xd0\x1f\xc3\a\x92\x06\x92\x11R\x92\x9b\x8dR\xa4\xdeD\xea5\x80\xac\x03\x92\x11JNjk\x88~Q)\x91z\x13\xa9\xd7\x00\xb2\x10HF(\xd1\xd6\x10\x8f\xd3t\x92z\x13\xa9\xd7\x00\xb2\x10H\x06\x00@\x02H\x06\x00@\x02H\x06\x00@\x02H\x06\x00@\x02H\x06\x00@\x02H\x06\x00@\x02H\x06\x00@\x02H\x06\x00@\x02H\x06\x00@\x02HF\x1a\x1cJ\xb3\xc7TT\xeb[\xf6\xa4\x03r\x80\\\x93\x8c\xec\xf6d\x8dK\x1a<N\xf5\xbe\xf9\xa5\x93\x86\x86A\xee\x92+\x92\x11\x0eOV!f\xea\x81x\x9c\xee\xe1\u007f\xcd\xca\xea[\xfct\x82o\x18\xe40\xb9\"\x19\xa1\xf0d\x15c\xa5\x1e\x84ǩ=\x0e\x8e\xbe\x89\xd3\t\xd2\\\x95o\x18\xe42\xb9\"\x19\xa1\xf0d\x15c\xa5\x1e\x84\xc7)\xff\x93\xc5\\\xdf\xc4\xe9\x04i\xae\xca7\fr\x99pIF\x98=Y\xd5\x0f\xf5\x86\xab\xae}\xfc\xf1\xabJ\xb7y\xa4\xee\xe1qڽtF\xe9\x1do_\xdb\xc6\xd6i^\xb6VdD&\xa8\x8eq\xb0\xfbƈM\xc7\xdf\\5نAN\x13.\xc9\b\xb5'k\xef̊\xf5\xcd\xc5%\x9b\xeb\xd6x\xa4.\xf68=}C\xf9\x9a\xb6\x85\x84l\xd0\xd7i\xcc\x15\x19\x91\t\xaac\x1c쾉\xd3\xf15WM\xbaa\x90ӄL2\xc2\xecɺ\x8d\x1cdf\x83\x87b\x8a\xd9'&\f\xb7\xc7ic\x19so[\xa2\xce\\\xde\x01\xc4\xc3\x04\x95??\xe0\xfa&\xf68\xf51WM\xbaa\x90ӄN2\xc2\xebɺ\xacL\xfd\xe7cm\x89D\x9c\xba\xd0\xe3\xb4o\x9c\xb66\xf3\x91k\xe6z\x98\xa0\xf23\x97s_\x15\xa5\xe3g\xae\x9a|\xc3 \xa7\t\x9dd\x84דu\xcd\xe8/\xd81χ1\xc5\x1c˟n\x8fӿ\xe9˰ݮ\x99\xeba\x82\xca\xcf\\\xce}U\x94\x8e\x9f\xb9j\xf2\r\x83\x9c&Ē\x116Oֿ\x16\xd6\xfd\xf5`\xf5ܾ\x98bf\xeaB\x8fӾ\x12-\xc3\xc3\xf6\xccՎ\x95<LP\xb9q\xe0\xddW\x85\x1e\xa7>\xe6\xaa\xc97\fr\x9a\x10KF\xd8<Y\x0f\x90k\b\xa9=\x19S\xccJ]\xecq\xba\xa0\\\x9d\x9d}\r\xda\xcc\x1d\xb7Tݬ\x89:k\xe0MP\xb9qp\xf4M\xecq\x1a\xdf\\5\xf9\x86A.\x132\xc9\b\xb3'\xeb\x81\xe2];\xdbO\xba\x8aQ;u\x0f\x8f\xd3\xcf*\xaaַ\xce/\xd6f\xee܊\x96U5D\xeb\x85\xd8\x04ծ\x8c:\xfa\x16\xdf\xe34\xe8\x86A.\x13.\xc9\b\xb3'+}3\xca\x02\xa2w|\xc8\x17\xa3v\xea\x1e\x1e\xa7\xf4\x8bƪ\x92\xda\x03\xda\xcc=Z[2\xa1\xeei\xadob\x13T\xab2\r\xabo\xf1=N\x83o\x18\xe40ᒌ4\x90\xb0C\xa9\f\"S\xd1S\xa5M\xa7Ν;\xbd\xff\xdeɧEE|\xd0W!%1\xfb\x96\x8a\xc7iR\r\x83\x1c&\xef%#a\x87R\t\x84\xa6\xa2\xad\xfa\xfd\v\xb4\xaf\xbc-\xe69\u007f\x92\x9b\xb9z\xdfR\xf28M\xaea\x90\xbb@2\xfa\x8b\x03\x85\xfa\x17:>,\xfc\xc0'RD\xc6fn\xc6\x1a\x06Y\n$\xa3\xbf\xe8k,iڶg[SIS\x12\x1f\xf9G\xdb\xc8co%Q.e2\xd60\xc8V \x19\xfdFߎ\xba\xcaheݎd&\xe0\\BH\xd1Q\xbf\xa84\x90\xb1\x86A\xb6\x02\xc9\x00\x00H\x00\xc9\x00\x00H\x00\xc9\x00\x00H\x00\xc9\x00\x00H\x00\xc9\x00\x00H\x00\xc9\x00\x00H\x00\xc9\x00\x00H\x00\xc9\x00\x00H\x00\xc9\x00\x00H\x00\xc9\xc8iOV\x0eس\x82@\xc85ɀ'\xab\a\xb0g\x05\xc1\x90+\x92\x01O\xd6\xf8\xf4\xa7=+\xc8irE2\xe0\xc9\x1a\x97~\xb5g\x059M\xaeH\x06<Y\xe3ү\xf6\xac \xa7\t\x97d\xe4\xa5'\xab\xe5|\xba\x90\x14\xadk\xaa\x9c\\\xaf}\x17\xdd\xea\xdbB\x12\xddh\xf5؊uԐ\xba=k\x009\x80\x1c!\\\x92\x91\x8f\x9e\xac\xb6\xf3\xe9G[\x8b\xc8\xd4U\xcdS\xc71I\xb3\xfa\xc6\xf6V4\xffl\"\xeb\xb1\x1d\xcbא\xba=k\x109\x80\x1c!d\x92\x91\x87\x9e\xac\xbc\xf3it\x9aZ\xfb\xe9\xaa\x1aG\xdfh\xb4L\xfdto`=\xe6b\x1dM\xa4j\xcf\x1aD\x0e G\b\x9dd\xe4\x9b'\xab\xc3\xf9T_\xc4\\O\xbe\xe2\xfa\xa6\xee}\x88\x1a=\xe6b\x1dM\xa4h\xcf\x1aH\x0e G\b\x9dd\xe4\x9b'\xab\xc3\xf9T_\xdam'\a\xb8\xbe\xf1=\xe6b\x1dM\xa4h\xcf\x1aH\x0e G\b\xb1d\xe4\x87'\xab\xc3\xf94\xba\x84\x15\xd8H\xcep}\xe3{\xcc\xc5:\x9aHў5\x90\x1c@\x8e\x10b\xc9\xc8\x13OV\xde\xf94z\x8d:ۻo\xa8u\xf4\x8d\xeb1\x17\xebh\"U{\xd6@r\x00\xb9A\xc8$#\x0f=Yy\xe7\xd3(\xb9e\xdb\xe6\xea2\x96\x99\xd57\xbe\xc7|,\xdfD\xaa\xf6\xac\x81\xe4\x00r\x83pIF>z\xb2\xf2Χ\xd1\xc7\x1b'V6|\xc66\xad\xbe\xf1=v\xb8\xa4rM\xa4j\xcf\x1aL\x0e '\b\x97d\xa4\x81\x90x\xb2\xeaĹ\xb3Շ \xecYu\x92\xcf\x01\xe4\x04y/\x19!\xf1d\xd5Ia\xba\x06`Ϫ\x93B\x0e \x17\x80d\xf4\x17\xa9y\xb2\xead\xc3t͆\x1c@\x06\x81d\xf4\x17)y\xb2j\x9c\xd4\x16\x19\xfd\xa2\xd2K6\xe4\x002\n$\xa3\xdfHœUC[d\xe4n\xe3\xcc\x04ِ\x03\xc8(\x90\f\x00\x80\x04\x90\f\x00\x80\x04\x90\f\x00\x80\x04\x90\f\x00\x80\x04\x90\f\x00\x80\x04\x90\f\x00\x80\x04\x90\f\x00\x80\x04\x90\f\x00\x80\x04\x90\f\x00\x80\x04\x90\x8c\xbc\xf2d\r1\xf1\x065\xec}\v\x15\xb9&\x19!\xf6d\xd5ГL\x835jl7\x9dx\x8cN,)\x8f\x0e\xa5\x87\xeaJ+\x1a\xf6T\xc4L\xf3\xb89\xc4\x19T\xbf\xbe\t\xd9U\xb1\xc3/$U\xfa\xa1\x89\xd4\xf0\x9d-\xadE\xc6Ϸ\x16\xd9z\x9d+\x92\x11bOV\az\x92\x81X\xa3\xee\xe1\u007f}+\xb6\x9b.ģ\x13K\x00\xa3\xd3VZ\xb3q\xeblB\x8e\xb8\x9f\xf0\xc9\xc1kP}\xfb&dGi\xac7C\xc0\xa4\xdcĞx?\xa0\x96\x02\tϖ\x16\xd2\u07be\x9e\xacko\x1f\xddb=\x93+\x92\x11bOV\x17Z\x92AX\xa3\xdaC\xe2\xe8\xa6'\x82\xd1\x11\x90\xfa\xe8|5q~/\xa5\xddձ\x92ᗃxP\x13\xe9\x9b\b\x89\x03\x13\xf3\xad!\x8bD\x13B\xf8\x97P\x06\xbf|\x13\x9e-\xeb\xa2\xec\x17\xe9ߦ\xb4\xc4V\xeb\\\x91\x8c\x10{\xb2\xba\xb0%#EkT\xfe\u05cb\xb9nz\x92\x98d\xa4>:\xcbJ\xb4_\x01\\#/\x19\xe2AM\xa4o)b\xbe5\xfa\x1b\xfe%\x94\xc1/߄gK\xef'\x86d|\xd2k\xed\x0f\x97d\x84ٓ\xd5\x11`\x9b\x95\x9e\xb9\xaf2ZU\u007fP\v\xb1\x93\xf4\xb0F\xed^:\xa3\U0010edefmc'\xa1/[\xa7\xfe\"\xefTǐ\U0001eb1f,(\x8fVԳ\xdf9\x17\x8f\x0eo\xa3j\xc7ڤ>:\xd5?\xd2*\xfabM\xaft\x0e\x02\xa3[\xaeo\"3X\x8f\xccN\x97\x10Rh\x9a\xb8qC\"\xf2\x90\xe5\xde\x1a\xe9j\u0082\u007f\x83s/!\xdb|Z\xaf\xd7i\x8a\x1b7߀f\xcb>\xdd\x04\xc7\xca!\\\x92\x11fOVG\x80mV\xba\x834\xed\xd9V_\xb8\x8f:\x92\x14[\xa3\x9e\xbe\xa1|M\xdbBB6\xe8'\xa1橿\xc8;\xd51$\x9c'\xeb\x9e\xd2[Zv5\x136|\xe2\xd1\xe1lT\xb9X\x9b\x94G\xa7\xb7\x90[\x91\x90\xcc!\xd6N\x96\xeb\x9b\xd0\f\xd6+\xb3\x03\xed\xed\xc5\xc6\a,ׄ\xd0C\x96{k\xa4\xab\t\x1b\xee\rν\x84=oV5\xb1z'\xbe\xd1\xed0\xc5\xf5\xc97\x98\xd9bH\x86\x95C\xc8$#̞\xac\\\x00W\xacg\x9b\xfa\xee껉\xfd`:\x97\xa4\xd8\x1a\xb5\xb1\x8c}N-Q%\x837\x0e\xf1\xf0N\xe5\x8fj\xadn\xf6Tթ\xb3\xbdw\xdbW^\xa3\xc3gf\xc7\xf2\xa4::ǹs\x1a\xd9\x1cD\x83j\xf5\xcd\xcb\fV\x94\x19\xa3D\x9f\xcf\\\x13^\x1e\xb2\xd6[#}MXpop\xfe%lf\xc7\x04\r\xday\x99m\x8a\xeb\x9bo \xb3e\x9fi\xb5g\xe4\x10:\xc9\b\xaf'+\x17\xc0\x17\xfbb}\xdd\r\x13\xc9l\xeaHRh\x8d\xda7N{\a~\xe4\x92\f\x0f\xefT^2\xacn\xb6\x11\xeb\x87Gţ\xc3U\xc6źHitz\x8b\xec\xc3\x16\xd9\x1cD\x83j\xf5\xcd\xcb\fV\x94\x19Ø\xcf\\\x13b\x0fY\ueb51\xae&8\xb878\xff\x12\xfem\xf4a\xda;q\x17۴Mq}\xf3\rd\xb6X\x92a\xe4\x10:\xc9\b\xaf'+\x17\xc0\x15\xdbWQ\xb5\xb4\xb5\xbdv6u$)\xb4F\xfd\x9b\xfe\xf9\xdc\xed\x92\f\x0f\xefT^2\xacnr\v\xaa\xe2\xd1\xe1*\x13/\xbe\xa6>:\xc6ZFo\x9b|\x0e\xa2A\xb5\xfdf=\xcc`E\x991\x8c\xf9\xcc5!\xf6\x90\xe5\xde\x1a\xe9j\x82\x83{\x83;^º\xc7i[\x99\ue8edU\xcaLq}\xf3\rd\xb6X\x92a\xe4\x10b\xc9\b\x9b'+\x17\xc0\x15\x9bQ\xc3\xdeN\vT\xc9\xe0\x93\x14Z\xa3\xf6\xe9\xef\xc0ödh\x1f\x04\x1eީܐ\xd8\xdd\xdce[\xa5\x89G\x87\xabl\x97\xd0V-\xf5\xd1YV\xa2\x99@l#\xa7\xa4s\x10\r\xaa\xd57/3XQf\fc>sMxx\xc8\xdao\x8d\xb45a\x13+\x19\xfaK\xb8\xa3\xbc\xf7\xa1\x1fj\x11\xb6)\xaeo\xbe\x81\xcc\x16[2\xf4\x1cB,\x19a\xf3d\xe5\x02\xb8bU\xec\xdd\xd6w\xb3*\x19|\x92bk\xd4\x05\xe5\xea\v\xdeנIƸ\x85CSm\x00\x00\x11\xbeIDAT\xa5\xeafM\xd4Y\x19\xef\x9d\xca\r\x89\xdd\xcd\xee\x8aZ\xf6I\xb5h\x89\xd7\xe8p\x95q\xb1\x1c\xa9\x8f\xceW\x13\xefe\xd7Jj\xa7I\xe7 \xb6\x935\xfb\xe6e\x06+ʌa\xccg\xae\tO\x0fY\xf3\xad\x11t\x13ǛcT\xd9!\x19\xdcK\xd8[\xbec\xb2v^\u0099\xe2\xfa\xe6\x1b\xc8l\xb1%C\xcf!d\x92\x11bOVG\x00owz\xdf\xfaU\xb7\x92\xf2\x96w\xf8$\xc5֨\x9fUT\xado\x9d_\xacI\xc6܊\x96U5D\xeb\x90\xd8;\xd5\xf6z\xa5\\7\xf7\x14\xcf\xdcж\x88l\xa6^\xa3\xc3\r*\x17k\x13\xc0贍\x9b\xfbbk]ћ\xd29\x88\xedd;\t\xcd`=2\xeb}\xbb\xbd\xbd\xb8\xb1\xfd\x8d3\xce&\xfc<d\x83n\xa2\x9e\x94\xba\xac\xf3\x1cop\xc7K\xb8\xec\x862\xfd\xf2=g\x8a\xeb\x93o \xb3\xe5\xfd\xf5d\x9d9\xecZ\x0eᒌ0{\xb2:\x03\xac\xd4\xfb\xd6TG+\x1ex\xa1:Z\xcb%\xe9a\x8dJ\xbfh\xac*\xa9=\xa0I\xc6\xd1ڒ\tuOk\xdd\x14{\xa7ZC\xa2au\xf3\xe3\xfb\xae\x9dP\xa3\xad\x89x\x8c\x0e7\xa8v\xacM\x10\xa3s\xa8n\xdc5\xf3\x0f\xb3-\xa9\x1c\xbc\xecd\x8d\xbe\t\xcd`=2ۯ\xef\xd6F\x92o\xc2\xc7C6\xe8&6\x97\x12\xf3\x05\xd2q\xbd\xc1\xf9\x97\xf0cҤop\xa6\xb8\xf1\xf3\rd\xb6\xf4\xb0gK\xce\xfc\xff\xed\x9d\xcdk\x1cG\x1a\x87\xff\r\x95\xc1\x8c\x91\x05\x8bE\x10h\x1c\x82\x1d\x88\x0f\xc6\x106d/\xc29\x8cN\xc2$\x81\b\x1d,ؕ!\x98\x18\x82ذ>\fYC\xf0\xc5Ɔ\x80C \xe8\xe0\x93M\x0e\x02\x81\x18\x88\xcd\x06\a\x13\xb3X\x84\xb0\x868Ƒ\x8dM\x1c!\xa2\xa1v\xfac\xba\xde\xeayk\xaa\xab\xa7{F\xd5\xf3{ \xc90\xe9\xa9z\xab\xde\xd6o4\x1f\xea'\x1a1\xac\xc1\xaf\xc8(\x81\xa19Y\v#z\xfbӑR\x969\\\x8c\x9b\xea\xf1\xdan\x89̂ޝZ\xfc\x17G#\xd4Յ5\x8c}d\f\xcd\xc9Z\x18\xb9\"\xa3\x8ce\x0e\x97>\x9b\xea\xeb\xda\xda_M\xaf؎IX\x9b\x89\x03s\x84\x91\x11ր\xc8\xf0\x8e|\x91\x01\xf6\x1fOg\xcf\xefَ\x89hn\xb6\x1b\x17\xe3ۣ\x8a\x8cn\r\x88\f\xdfx\xb4.>\xb9[\xe2/1`\xff\xb1+\xde=W\x8f^\u008cL\x8a\x9bԀ\xc8\xf0\x8d\xd3B\x88\x83\x8flG\x81Jќj\xfc\x1c\xdd\x1a\x9d\x14\xb7[\x03\"\x03\x00\xe0\x00\"\x03\x00\xe0\x00\"\x03\x00\xe0\x00\"\x03\x00\xe0\x00\"\x03\x00\xe0\x00\"\x03\x00\xe0\x00\"\x03\x00\xe0\x00\"\x03\x00\xe0\x00\"\x03\x00\xe0\x00\"\xa3\x04\xa1\xe7\xbet\xb2\x0eN\xf1\x1b5\\`u-\x84\xaaE\x86\xd52\xd9C坬\xc1`\x91\\C\xbfX\x8e\x8e\xdd\xc9j3\x9f\xdaG\x88\x19x\u007fau\x1d%U\x89\x8c̖\xc94\xd5w\xb2\x06\x83=\x93\xcf.\x89\xaf\xfe\xe8s\xb4\xd5\xc9j5\x9fZG\x88)`\u007fau\xcdJ\tVתDFf\xcbd\x8aqp\xb2F\x17\x12\xdd\x14\xe9\x8b\x18\xa6`v\x87\x90\xc5|\xda\u007f\x84.\x83\xef/\xac\xae\x99)\xc1\xeaZ\x95\xc8\xc8l\x99L1\x0eN\xd6B\"#\x8b\xf94[d\f\xbe\xbf\xb0\xbaf\xa6\x04\xab\xab_\x91Q\x90eR1\x16NV\x1a\x19\xb6\x89M\v\x82\xd5u\x00\xe5j\xb5\xac\xae~EFA\x96I\xc5X8Y\x83\xc1vw\xd7\xc3ȰMlZ\x10\xac\xae\x03(W\xabeu\xf5,2\x8a\xb1L*\xc6\xc2ɺ\x15?\xd9le\x98ش X]\aR\xaeV\xc9\xea\xea]d\x14a\x99T\x8c\x85\x93\xb53ؽ{\xf7.\a\x91a\x9dش X]C\xf2)W\xabeu\xf5.2\x8a\xb0L*\xc6\xc2\xc9J\xde˰NlZ\x10\xac\xae!\xf9\x94\xabղ\xbaz\x1c\x19\xf9-\x93\x8a\xb1p\xb2\x92ȰNlZ\x10\xac\xae\x11\xf9\x94\xab\x95\xb2\xbaz\x1c\x19\xf9-\x93\x84qp\xb2\x92ȰNl\\\x10\xac\xae!N\xcaUB\x85\xac\xae\x9eEF!\x96I\xca\x188Y\xb5o\u007f\xda&6.\bV\xd7\x10'\xe5*C\xd1S\x8c\xc0\xea\xeaWd\x14b\x99ԩ\xbe\x93U\xfd\x8d\xc9u\xeb\xc4ҸbX]#\\\x94\xab\fEO1\x02\xab\xab_\x91Q\x02\xa5\b=\xf7\x9f\x93upJ٨\xe1\x02\xabktc0\xdf\xda\xd8GF\x19B\xcf\xfd\xe8d\x1d\x9c\x126j\xb8\xc0\xea\x1a\a&\"c\xcc\x18Ud\x80\xfd\xc7(\xac\xae\x88\f߀\x93\x15\xb8S\xa0\xd5\x15\x91\xe1\x1bp\xb2\x82\x1c\x14guEd\x00\x00\x1c@d\x00\x00\x1c@d\x00\x00\x1c@d\x00\x00\x1c@d\x00\x00\x1c@d\x00\x00\x1c@d\x00\x00\x1c@d\x80!\xd2nG\xff\x00\u007fAd\x80a\xb1\xbd\\\x17\xefK\xf9\x91\x98]N_\x83\x00\xf8\x03\"\xa3\x04\x1d\xe7(\x9c\xaců\xa2h\xda'O^\xdfx\xdcI\x8e֍\x933\xa6k\xea\x03\x96Q\x9cQ&\xaa\x16\x19\x9e;Ys;8sIE\t9'~\xb9rtr!\xe3\xc4\xd1e\x83B6Ń>\a\x96H\xcee\xf6\xa55!N\xb7\xe5M!&6l\x87R\xfa\x9c\xa91\xcbB\x88\xc3џ\x06\xe4?\xa3\x8a\xa7*\x91Q\x11'+\xeb\xe0\xcc\xe0\xd5\xcc'\x15%䜸Q\xbfvv2\xe3\x05\x1b~\x10\xdfuo\xdeK.\xd0[\x16\x86\xd2\av\x9c2\xecn\x88ɖܹ)6\x9c~u\xeas\xa6\xc6<i\xb5\xae&\x1b\x95\xf7\x8c*\x9e\xaaDFU\x9c\xac\xdc3\xb6ݫ\x99W*J\xc85\xf1\xef\xe2\x8al\xf7^\u007f\x97\x87\xe4D\xf9\x91a*=\xe3oDN\xec\x88@\x0f\xf2Xd݈.\xb6Ȑ\xdaF\xe5=\xa3\n\xa7*\x91Q\x1d'k/v\xaffIRQ\xebď\x84\xc3\xef\xf9C\x8d\fk\xe9\x05\xb2#6\xa6vK\x8f\x8c\"Ϩ\x81\xf0+2*\xe8d\x95/\x96f\u07b8pafJwp\xb2rU\x9b0U\xbf\xb7k\xf1$\xf5\xa6\x8b\x8cQ\x13\x9f\x13\xb5\xeb\xf1\xf6Y'ޛ\x89\x0e\xf8D\xea\x82W\x93>tS|ߝ\xf0\x81ؔFH\rj\\C\xe75\xb8=\xa3+f\x97I\x1b\xc0\xa2\xe9o9\xa3j'2\x1e\xff\xedf\x14\x19N\xf5\xd6>\xfeG\xa2FUg*\xb9\xa9g+\xa3\x93\xe5ڢ\x9fg\xdd\xc1\f\x9dσ_\x91QA'\xebީ\xfa\xd5\xe6\xa1\xc9/\xe7/S\a'/W\xb5\tS\xb5{\x13\x8b'\xa97]d\x97d\xe2\xc0\xd7Yo~q\xa4\xb3}\xf6\x89\xff\xdb\xfaF4[\xc1\xa5\xdc%\x11\xbc\xf2\xfa\xd0?\x9fo\xceM'\xa7\xfc\xde\xccܝ\xdfL\xaf\x11H\rd\\\xbe\xf3\x14vϴ\x15s\xcb\xd4\x1a\xc0A\xf5\xb7\xacQ5\x88\x8c+\vQd\xb8\xd4\x1b^\xe8\xfb\x9b\xbf\x86jTu\xa6қzd0:Y\xae-ڊ\x93\xc1L\x9dρg\x91Q='\xebZ\xf0\xe1\xc1U\xd1\xfd\xa2B\xec\xad\xe0\xe5\xaaVa*\xb9\x97\xbaH\xa9\xe6S+\x92\x10O,kӝ\xa7ޥzt\xacm\xe2\xe4\x85\t\x11\xbc\xf2\xfa\xd03\x9d'}\xf2\"f]\x90k\x97\xf7\xa0j \xe3\x9a:\x9f\xc0\xefYjŽ\xcbL5\x80A\x99qx\xa3j'2\x9e\x1fz\x1eF\x86K\xbd\xb2v\xb2sR\ue798\xd3\xceTrS\xea\x91\xd1{F\x99ڒ\xdc\xd4\x063u\xde\x15\xef\"\xa3jN\xd6\xd5i\x19\\.\xbe\xfb\xc6I|J\xf3rU\xab0\x95\xdcK]\xa4T\xf3\xa9\x15IH~\x96\xce\xca\xe4M\x1f\xeb\xc4꽌D\xf0jЇ\xfe\xba~\xed\xe4kɋ\xfd\x9d\xfa\x9bW6\xcc\x17\x86\"5\xa8qM\x9dO\xe0\xf7,\xb5\xe2\xdee\xa6\x1a\xc0\xa0\"\x837\xaav\"C.\\\x89\xde\xcbp\xa8W\xd6>\v\xfe}M\xfcN\xceTzS\xa6##}F\x99ڒ\xdc\xd4\x063u\xde\x15\xef\"\xa3\xd7\x11\x199-}u\xb2^\x9ex\x11\xfc\x98=\x8c\xffO\xf7\x94f\xe5\xaaVa*\xb9\x97\xbaH\xa9\xe6S+\x92\x90\xfc,%ۗa\xe2$2\x94\xe0լ\x0fm)\xe3\xc6=\xd1\xf7+\f\xaa\x062\xae\xa9\xf3\nv\xcfR+\xee]f\xaa\x01\fdKX\xa3j\x10\x197\xdf\t#é^\xa5FUg*\xbd)\xf5\xc8\xe8=\xa3LmInj\x83\x99:\xef\x8aǑQ\r'\xeb\xaf\a\xe6\u007f}p\xe2t\xf7en|J\xf3rU\xab0\x95ܫ\xb9H\x89\xe6S+\x92`\x8c\x8c~\x13'\x91\xa1\x04\xaff}h\xf6OLT\rd\\S\xe7\x13\xf8=K\xad\xb8w\x99\xa9\x060(\xfd-oT\r\"cwj#\x88\f\x97zc5\xea\x97\xe2\x0fr\xa6қRߨ\xde3\xcaԖ\xe4\xa66\x98\xa9\xf3\xaex\x1c\x19\xd5p\xb2\xde\x17G\x85h<\xed\x1e\x12\x9fҼ\\\xd5*L%\xf7j.R\xa2\xf94}\xfa\xc8E\x86u\xe2$2\x88\xe0ը\x0f\xe5#\x83\x91\x8a\x92\x1aȸ\xa6\xce'\xf0{\x96Zq\xef2\xf5\x06p\xe5(\xfd-oT\r\"C\x9e]\n\"å^Y{#x\xd3\xe7TC;S\xc9M\xa9m\x14sF\x99ڒ\xdc\xd4\x06+\xeasg\xcf\"\xa3zN\xd6\xfb\x876\xbem=\r\a#\x0eNV\xaej\x15\xa6j\xf7R\x17i\xb7\xde\xd4ú\xa8\x89\xb5\xed\xb3M\x1c}b\x12^ߞ\b^\x8d\xfa\xd0\xfb\xea\x17\xeb\xef\xd5筽RQZ\x83\x1a\xd7\xd8\xf9\x04v\xcfh\xbd\xfc2I\x03\xd8r\xa8\xfe\x965\xaa\xeen\x88\x9b;\xb25\x19D\x86K\xbd\xb2&\xe6\xefn̅jTu\xa6\x92\x9b\xbf\x05\xdf\xfe\xbc\xd2jEoAp:Y\xae-Z\x8f\x93\xc1\f\x9dσ_\x91QA'\xeb\x9dZpo\xed\xbd\x87\x9a\x83\x93\x95\xab\x1ag\xeb\xaeB\xbf\x97\xfaP\xe3z\xd3\x0f\x8bQ\x13k\xdbg\x99xo:\xbcy0\xf8\x14\x96\n^M\xfa\xd0\xe7\a?|\xb0\xddi\xc6\xde\xf6\x8f\x1fԶ\xbbs\xf7HE\xb5\x1a\x92qO\x1b;\x9f\xc0\xee\x19]1\xbfL\xd2\x00ɕC\xf5\xb7\xacQus\"\xf8\x86N{\xaeޖN\xf5\xcaS\xcd\x0f\xff\x12\xabQə\xaan\x9e\x8d\xca\x15\x1f\x05w\xf3:Y\xa6-Z\x8f\x93\xc1\f\x9dσ_\x91Q\x02\xa5\xe88\xb3;Y\x9fM\xad<\xfb\xf3\xcfW?\xbc\xffZƿ\xd4\xe0)e\x15Es\xebT\xf8\xf3sF\x88\xe3\xe4\xf3\t\a\xa9h\x19\xa4\x1b0\xe2rLd?\xa3Jg\xec#\xa3\f\x1d\xa7\x83\x93\xf5V\xf45\x02ٞ]\xef\u007f\xa0\x85\x12VQ\x02\xcf\x1et\x9eS\xb7\xef\xff\xa6\xeeq\x92\x8a\x96\x81ހ\x91\x97c\xc0\xe1\x8c*\x1dD\xc6h\xb9\u007f \xfa\x85\xf8\xe1\x01\xf55\x8aq\"\xbbT\xb4$\xf4\x06\x8c\xbc\x1c\x0f@d\x8c\x96\xf6\xf2\xe4\xca\xda\xe6\xda\xca\xe4ʾy\x16\x19/\xd0\x00W\x10\x19#\xa6}{\xfe\xf5\xda\xeb\xf3\xb7q\u008e\b4\xc0\x11D\x06\x00\xc0\x01D\x06\x00\xc0\x01D\x06\x00\xc0\x01D\x06\x00\xc0\x01D\x06\x00\xc0\x01D\x06\x00\xc0\x01D\x06\x00\xc0\x01D\x06\x00\xc0\x02u\xe9\"2\x00\x00\xfdH\xb9t\x11\x19%\xd8L\xf7\x93A\x93\xa3\xf8\x15\x83\xea\x92v\xe9V-2<w\xb2\xc6E\xde\b\xaem0;\xff\xa3\xed\xe8|8\xf8[՞\x95a3\xe5i\x8aZ\x90\xb8\xdf\x1e\x16Mۡ\xa5Qn\x032B\x9c\xacFr\xb6e\x10\x97nU\"\xa3\"Nָ\xc8?\xbe\x12\xffnݘ\x9b\xe8#\bʏ\x8b\xbfU\xedY\x196S\x9e\x17\x8b\x87\x83\v\xf54&\x17S\xd7ʴ+b\v\xa3\x90\x06\fZ\xaf\xe6d50\x02\x97nU\"\xa3*Nָȭ \xd9ۧOX\x8e̓\xa3\xbf5ٳ\x8c\xcfI\x01ݝ\xcc\xc9\xea\xc2\xe1W\xf2\xf7Ʌt\x9dVEl\x01tK/\xa2\x01\x05\xd4k7Qrm\xb1N<\x90K\xb7*\x91Q\x1d'\xab\x8a\fM,P\x18\x8e\xfeVfϬ<\xecw\x89\u007f;\xab\x8b\x8d5\xf9\xf5\xfcb:2\x8a\xba\xdem?\xba\xa5\x17р\x02\xea\xb5G\x06\x87u\xe2\x81\\\xba~E\x86\xcfNV^\xe8\xa9\xd9AU\x91\xd1\x19\xbb\xf4\xba\xa4ǒ\x11Ή\x83WVz\x84\x9e\xda`\xac>\x94\xacإ\x1c\x17\x9b)\xd9Iݒ\xfaY\xb4g\xda\b\xc4ߪX]\xbc\xfa\xbe\\\xb8։\f\xe2C\xd5z\x9cԻ\xd5\xd9\xf5\x85\xf61!\xa6\rW\xc61\x99pw>=9\xf5\xde\u007f\xdeX\xd7\x0e&\xa5\x1b\x1a\x90<L3\xb5r\x1d\xd2\xea\xe5\xe0+\xd3\x1a\x9b\xfc\xb8\x92\xed\xa3C\x8cƥ\xebWd\xf8\xecd兞\xd4\x0eJ\x8a\xdc\x12\xdf\xee\xfe\xfc\xa9\xf8\\\xab\x81\x8c\x10<\xec\xf8\xe7\xcd\xe3\xbaГ\x0e\xc6\xebCɊ]\xcaq\xb1\x99\x92\x9dTS\xec\xde9\xb6\x12\xecّ\xefv\xe8\b\xd4ߪX]|2\xf5\xf2\xd0v'2\x88\x0f\x95WĶ\xef6\x0fܕ_O|m\xba\xa6\x99\xc1\x84\xfb\xea\xad\xd9\xcb\xeb\xe7\xc2+3\x13H\xe9|\x03\xd4è\xa9\x95\xed\x90V/\a_\x99\xd6\xd8$2\xc8\xf6ic\x8cĥ\xebYd\xf8\xecd兞\xc4\x0eJ\x8a\xdc\n\x9f\a\x96\xda\xfa\x14\xd4:Z{\xb33ѫc\xbaГ\ff\x98M\xadإ\x9c\x80\xec6\xd3d'i\xbd\xcd\xe0YoiY\x1f\x81\x8ac\x15\xab\x8b\xf2\xed\x959\x19\xbe0a\xe5m\xb4\xde\xf6ٹ\x17\xc7\xfa~>řp\x97\xa7\x83'\xd3\xf3\xa9\xc8 \xa5\xf3\r\xa0\x0fS\x95\x19:d\u007f}\xc0UF\x1a+ɋ\x02\xb2}:\xc3w\xe9z\x17\x19\xfe:Yy\xa1\xa7\xb2\x83\xd2\"\xb7\xc4\x17\xdfߞ\x9b|\xac\x1fK\xad\xa3ћ\x98Wu\xa1'Q\x8d\x1afS+v)' \xab͔\xec$\xad\xf7\xc9\xc4Or\xefȆ>\x02\x15\xc7*:\x91qI\\\xea\x13\x19ڂv\xdf9\xda\xff\xe3BƄ\xdb>\x1c=7\xa7\"\x83\x94\xce6@{\x98\xaa\xccС\f\x91\xc18zIc%\x89\f\xb2}:\xc3w\xe9z\x17\x19\xeb\xbc\xe9\xd2\a'++\xf4T\xf5\xd2\"×ү\x0e\\\x93\xfa\xb1\xc4:\xca\n=\xad\xfaP\xeaou(' \xab͔\xec\xa4fI\x9d\xbf ףw\x1c\xd4\b\xfcۋ\x9d\xe6\xbe\xf8\xf4Y\x9f\xc8\xd0\x1d\xa77\x19\xfb-\x851\xe1>\x89rn'\x15\x19\xa4t\xb6\x01\xda\xc3Te\x86\x0ee\x88\f\xc6\xd1K\x1a+\xe9[\x8fj\xfbt\x86\xef\xd2\xf582|s\xb2\xf2BOU/-2z\xf7\xed\xc8E\xa9\x1dK\xad\xa3\x91\xd0\xf3\xba.\xf4\xa4\xde@~6\xb5b\x97r\x022\xdbL\xd5Nj\x96\xd4۳{g\xff\x9e\x1aa\x831\x80E\xcd\xed\xa0\"\xe3_\xb5\xf0\x0e^\x11\xfb\xb4\xfe\xcf\xe3/\x99Q\x12\x18\x13n;Z\xccO\xe9\x17&\xaat\xb6\x01\xda\xc3Te\x86\x0eQ/,\x0f\xe7\xe8%\x8d\x9542\xd4\xf6\xe9\fߥ\xebqd\xf8\xe6d兞\xa4^Rdt\xc6\xd6\xcf?\xf8\x9c\x1eK\xad\xa3\xb5\xa3\x9dH\xday\xab\xa1\x8b7\xd5`\x86\xd9Ԋ]\xca\t\xb0\xd9L\tݝ\xd4,\xa9{\xb3\xb7_\xdbH\x8d\xa0\x89c\xe5\xe3\u007f\xff\x12\xfe\x97F\x86\xf2\xa1\x1a\x14\xb1{s\x17\xe5J#n\"gTeM\xb8\x1f\xccv~\x1c\xdaK=\xefe$\xa5\xf3\r\xa0\x0fS\x95\x19:D\xbd\xb0\xd9+#\x8d\x95\xf4\xc7Um\x9f\xce\xf0]\xba\x9eE\x86\xc7NV^\xe8I\xeb%EF_\xd2m,,\xbfM\x97IG\xa8\x89w\u05fe<\xa1\v=u\x9b)3[@w\xc5.\xe5d\xb1\x992h\x96T\xb9\xfa\xd6t\xf0ޠ\xd6!*\x8e\x95g\"\xff\xdf˥F\xf0f\xfevc\xe9%\xf5\xa1\xaa\x1eS\x1f\xea\x9ds\xf5'\xf2\x97#\xe7\uf13f\xb3\xf7\x1aU\r&\xdc\xed\xfa\xb1\xab\xb7\xce\x1cꍌ.|\x03\xe8\xc3He|\x87H\xbd\x0e\x95\x91\xc6\xeaN\xd6x\xfb(\xa3q\xe9\xfa\x15\x19>;Yy\xa1\xa7VoRd\xf0ՏK\x9d1O\xcc\xde&\xc7j#\xd4.,\x1fI\v=\xe9`\xecl!\xf1\x8a\x1d\xca\xc9d3eЦ\x90\xff\x13\xe1s\xaf\xae}\xa5\xe2\xd8\x1b\xf5k\xc1\u007f\x9aB\x04\x1fF\xad\x04\xdf~!>TV\x11\x1b\xbc\x83\u007f^~,D\xf4\xd5\xee^\xa3\xaa\xc1\x84+_,\x1f\x9bl\xdc7F\x86\xa1\x01\xf4a\xb42\xb6C\xb4^\x87\xcaTc5'kw\xfb(\xa3q\xe9\xfa\x15\x19%P\x8a\xcdt\b\x06\xcd\xe4M\x18g\x8aZ\xb1\xabNv\xa76\xd0_ld\xc2ͨ\x9a~\xfb3#\xb9\x1e\x96\xb92Sc\x87\xb1}<)\x97\xee\xd8GF\x196\xd3a\x184\xf3GFQ+v\xd5ɮ͔\x1d\xa3\xaeF\xd5\\?\xfb\xb9\x1e\xe6P\x99\xa9\xb1\xe5o\x9f\x19ͥ\x8b\xc8\xf0\x94\x01\"\xa3 \x9ct\xb2\xcd\xcdv\xe3\xa2\xed\xa0Aq5\xaa\xe6\xf8\xd9\x0f\xc8\xf10\x87\xca\xd8\xc6\x0ee\xfb2\x82\xc8\xf0\x92\xa7\xe1\xdb]\xb6\xa3\xca\xc5\xc5f\xba+\xde=W\xcf\xf8\x9b\xf9\xd0x\xb4.>\xb9k\xaf=M·e\x83o\xec\xbe\xda>D\x86\x97\x84ow=\x96\xa3\xc5\xc5fڜj\x18\xff\xdabT\x9c\x0e\xde\x04\xb4\\\u0086!\xe7òah\xec~\xda>D\x06\x00\xc0\x01D\x06\x00\xc0\x01D\x06\x00\xc0\x01D\x06\x00\xc0\x01D\x06\x00\xc0\x01D\x06\x00\xc0\x01D\x06\x00\xc0\x01D\x06\x00\xc0\x01D\x06\x00\xc0\x01D\x06\x00\xc0\x01D\x06\x00\xc0\x01D\x06\x00\xc0\x01D\x06\x00\xc0\x01D\x06\x00\xc0\x01D\x06\x00\xc0\x01D\x06\x00\xc0\x01D\x06\x00\xc0\x01D\x06\x00\xc0\x01D\x06\x00\xc0\x01D\x06\x00\xc0\x01D\x06\x00\xc0\x01D\x06\x00\xc0\x01D\x06\x00\xc0\x01D\x06\x00\xc0\x01D\x06\x00\xc0\x81\xff\x03&\xf2B\xcdI\x1b+\x96\x00\x00\x00\x00IEND\xaeB`\x82",
+
+	"analysis/typeinfo-src.png": "\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x02\xc1\x00\x00\x01\xb3\b\x03\x00\x00\x00\xf9m:\x11\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x02\xfdPLTE\x00\x01\x00\n\x03\x01\x05\a\x03\x02\r\x14\n\f\b\x10\x12\x0e\x0f\x13\x1e\x1b\x1a\x14 \x1f\x19\x1c \"\x17!;!# #$\"$%#&'%'(&+)\x1e()'\x18-T*,)/,!-/,12053'35386*6758:7<:.<>;>@=CA5&CxAB@EFDIJH\x00g\x00KLJ\x00j\x026NzNOM0R\x95\x06m\x06UP?PRO>V\x82\x0fq\vTVS\rr\x17\\WEVXU,`\xae7]\xad\x15w\x1c[]Z8`\xaa\x19y\x1e;b\xac_a^=d\xae?f\xb0*{!bdaSe\x84)}+Bh\xb3efdDi\xb4ghfLj\xafpiQEm\xb1ikh0\x820Ol\xb2Ip\xb4lnkTp\xa3Kr\xb7npm6\x869Nt\xb9zs[Wu\xb5>\x89=strZx\xb9vwt]{\xbbG\x8eHy{xX\x80\xbf^\u007f\xb9\x85}ea\u007f\xbf}\u007f|O\x93N\u007f\x81~c\x84\xbeW\x95V\x82\x84\x81m\x87\xbch\x88Ð\x86h[\x99Zj\x8ać\x88\x85q\x8b\xc1\x8a\x8c\x89`\x9dd\x96\x8cnt\x8e\xc4z\x8f\xbf\x8f\x91\x8eg\xa1hy\x93\xc9~\x93\xc4x\x95Ē\x94\x91\x81\x95Ɵ\x95w{\x98ǃ\x98ɂ\x9aė\x99\x96u\xa8v\x86\x9b̀\x9d̙\x9b\x98\xa5\x9b|\x85\x9eȂ\xa0ϙ\x9e\xa0\x9c\x9e\x9b\x89\xa1˞\xa0\x9d\xab\xa1\x82\xa0\xa2\x9f\xa1\xa3\xa0\x81\xb0\x83\x91\xa5ʕ\xa5Ď\xa6ѣ\xa5\xa2\x91\xa9Դ\xa7\x83\x95\xa9Χ\xa9\xa6\x8c\xb4\x8a\x94\xac֪\xac\xa9\x99\xadҟ\xaeλ\xae\x89\xad\xaf\xac\x9d\xb1֯\xb1\xae\x98\xbb\x97\xa3\xb3ӡ\xb5ڧ\xb6ֱ\xb5Ĵ\xb6\xb3\xa3\xbf\x9d\xac\xb7\xd2ķ\x92\xaa\xb9ڢ\xc1\xa4\xb7\xb9\xb6\xb3\xbcĭ\xbcܺ\xbc\xb9\xa6Ũ\xb1\xbd\u05fd\xbf\xbb\xb1\xc0\xe1\xb8\xc0կǫ\xcd\xc0\x9a\xc0¾\xb7\xc2ݻ\xc3ؽ\xc4ڲ̷\xc4\xc6ú\xc6\xe1\xc0\xc8\xdd\xc7\xc9żκ\xd8ɝ\xc6\xca\xda\xc0\xcb\xe6\xc9\xcc\xc8\xc2\xcd\xe8\xbf\xcf\xe2\xcd\xcf\xcc\xc4\xd0\xde\xcb\xcf\xdf\xc8\xd3\xc1\xc8\xd0\xe5\xe1ѥ\xd0\xd2\xce\xc8\xd7\xca\xcb\xd3\xe9\xd2\xd4\xd1\xd2\xd3\xdd\xce\xd6\xdf\xdfש\xce\xd6\xec\xcc\xda\xce\xe6֪\xd6\xd8\xd5\xcb\xdb\xee\xd5\xdc\xd1\xd3\xdb\xe4\xd6\xda\xea\xd9\xda\xe4\xda\xdc\xd9\xd2\xde\xec\xd9\xdd\xed\xdc\xdd\xe7\xd7\xe1\xdc\xe0\xde\xe2\xdd\xe0\xdc\xdb\xe0\xe2\xf0\xe0\xb3\xd6\xe2\xf0\xdd\xe1\xf1\xe0\xe2\xdf\xde\xe3\xe6\xe0\xe4\xf4\xe3\xe5\xe2\xe1\xe6\xe9\xde\xe7\xef\xe8\xe5\xea\xe5\xe7\xe4\xe6\xe7\xf2\xe4\xe9\xeb\xe7\xe9\xe6\xe2\xea\xf3\xeb\xee\xea\xec\xed\xf7\xe6\xef\xf7\xe8\xf0\xf9\xf0\xf0\xfb\xf0\xf2\xef\xf4\xf2\xf6\xef\xf4\xf7\xf4\xf6\xf3\xf2\xf8\xfa\xf8\xfb\xf7\xf6\xfb\xfe\xfd\xfb\xff\xf9\xff\xff\xfe\xff\xfc\x11\n֍\x00\x00 \x00IDATx^\xed\x9d\r\\T\xe7\xbd\xe7\xef\xb2\xcd&\xbb\x0f\xcc4w.s?e\x8a\xbd\xbc\xe8z-[\xb2z>\x8c#\xd6-h\x16#,6\xd7\x17\xbc\x94+\x95h\xae\xa2\xb7Jbȍ\x8e\x91\xd8\x05\nac\x12r'\x161vg\xbd)+\x91\x98b,\ti41\xb9\x96H,-\x9b\x17\x92\xb6c\x1a-&\xd4\x13\x93[\xaf\n\xfd\x9c\xcf>/g\xe6<g\xe6\x9cy\x81\xe1\f\a\xfeߴ\xe3\x993\xcfy\xce\x19\xf8\xce3\xff\xf3\xf6\xe3Ϥq#\x02@\xe2\xf9\xb3H\x9e\xea\x13\xa9k\x000\x000\x1807`0`n\xc0`\xc0܀\xc1\x80\xb9\x01\x83\x01sc\xb4\xc1\xde\xde\xc0d\x8f\xdbC\xff\xf5u\xec\xaf\xdb\xdf\xe1\xd3[\x02\x00\xc2a\xb0\xc1\x83\xee.\xff\xe4P]G#\xfd\xb7\xb1\xb5\xb7\xafw\u007f\xe3\x90\xeeB\x00\xa0\x8f\xb1\x06\xf77+\x06{\xda\xfb\xa8\xc1\xde\xe6a\xfc8\xdcܡ\xb7\x10\x00\x84\xc1P\x83\xbdno]\x97<\xddS\xef\xeb\xa7\x06\xb7\xb7\xd2\xe7\xad\xed:\v\x01@8\f5\xd8\xe7\x13\x1b\xbb\xe4ɺ\xd3b\xbf\\Ex\x87\x86\x87\xbcPE\x00\xe3\xc2P\x831~\x83=x\xc8e\x06\x8b\xbev\xb7\xdb\xdd\x06{r\xc0\xb8H\x90\xc1\xbd\xf5>\xbf\xc1\xc3\xedͽ\xfd\xbd\xcd\xed\xc3\xe1\x16\x03\x00\x1d\x12c\xb0\xaf\xaewdd\xa4\xafq\x04Ow4_\x14aO\x0e\x18/\x891\xf8\x8c\xdbO\xbfX\xd7M_\xe8\xae\v\xb7\x18\x00\xe8\x90\x18\x83\xc5ABO\xfd\xe0\xa0\b\x06\x03\x13\"A\x06S\xe4\xa3i\xb4\x8a\xb8\xd8\fGӀ\xf1`\xa8\xc1\xbe\xfe\xfezo\xff {2\xd2\xdfS\xdf?\x84g67\xf7\xf4\xf547\xc3\xc1\b`<\x18jp\x17\xab}\x99\xab\xfdd\xb2\tO\fw\xee\xafo\xed\x84C\x11\xc0\xb80\xd4`\x00\x88;`0`n\xc0`\xc0܀\xc1\x80\xb9\x01\x83\x01s\x03\x06\x03\xe6\x06\f\x06\xcc\r\x18\f\x98\x1b0\x1807`0`n\xc0`\xc0܀\xc1\xa6`$R\x83\x99\v\x18<\x0eF\x86GF\xf0\xff#5\x8b\x17\xfd%ihI\xa4F3\x1608fzggf\xe6eef\x96\x1bu=hf\xa6\xbb\xbd/R\xa3\x19\x8b\xd1\x06k\xa4N\x8dt\xb7ֵ*\xb3\x8d\xe2!A8\xa2\xf3\xd2y\xa7\xb0J\x14\x8f9\x05\x86S\xd5n\u0602rs\x93l\xb9s\x936\x1a\xa3p\x0fj\x8b\xd4d&c\xb0\xc1\x1a\xa9S\xa2\xa7\xbe\xbb\xaf+\x90\x84\xa2\x857܋\xb1\xf2\xe2\xab\xec\xdf\xf7O:[t\x9a\\y\xf9\x01\x97(>)\x9c<y@8p\xf2\xe4\x82'\xf9\x17}\xb7l\x93\xa4\xdek\xd2\xe8\x97\x16E\x11q\x11˦\xeb\xb4\xedBp\x13l\x18\x8c5X+u\xaa\xbb\x8e\x88p\xba.̀6\xb7P\xff\xb5\x98\xa9\xd8\xee\x9fr\xe9\x19,\x8a-\xd8\xe0\x03NQ|UxY\x14\xf3\x0f\xf0/\xf92\x93\x92\x92\xc4¤\xa4/UGap,\x9b\xaeӶ\x13uj\xce\a(\x86\x1a\xac\x99:\xe5aߑ\xfc\rt\xc1̎A\x83\x88\xac\x8b\xd6\xe0\xcb\xe7e\x83\xcf_V\xbd\xd6_\x96\x85\r\xbeeѶ\xde(\xee+\x89e\xd3uڂ\xc1a1\xd4`\xcdԩV/\x9d\xd1\xea\xd1Yȃ\x18\xb3\xd9\xe4\x06\xb1\x1a?6\x97\xa1\x94ڕ\x0e\xfb\xa2ӴMc\x8e-C\xbdc\xf5\xe9\ngCqы\xbb\v\xaa.\xe1gW~T\x91\xbfj7\x9e:&\x97\xb6\x15\xa4\x8dk\xdf\xeeU\xf9\x9b\xde'\x93W\x0eT\xe4\xaf;p\x85L\xbe\xbf\xa3\xa8`+\xa9\"\b\xd4`\xb6X\x83\u0602\x1f\x8f<$8\xff\xd7\u007f\xc3\x06\xffǮ\xc1a\xa5_\x15\x1dy\x0e\x8b=/]\xb5\xe9\xdd)\bm<\xbd<ݖ7\\\x86\x92\x1b\xc53\x16\x94I\x1b\x9f)\xb4[\xd2\xf2\xfa\xf9\xb6Ax\xc1\xe0p\x18j\xb0\xa8\x95:\xd5\xd1H\x86\xb2\x8b\xf5\xfbu\x96\xf0ux3r\xbd^\xb2\v\xe8\xebp\xac\x19\x14\a\xabS;|\xbdM)(}[u\xba\xad\a7)I.\xf3\xd4\xdag\xab\x0eo\xbdX \xec\xae\x12\xee|r\x05)\x01v\n\xbb\x8f\x1f(ZwE\xbc\xf4\xf2\xc9UU'O\x9e|\x9b4q\t\xab\x8e\x1c[\xb1\x95L\xeet5\x1cop\xed\xc0S\xe7\vV=sl\x93\xa06\xf8\xd2\xcb\xc5\x0f\xfcZ\xfcuK\xc1\xc9Ko\x1eq\n\xff\x19\x1b\xfc\x1f\xfe\xf70\xd7/O\x17*\xd9\xdf\ueda3aզ77\xa5g\xa4:ʗ\xa3\xbe~\xaf\xa5\x1a\x8f\xac%V\xd2\xd8k\x9b]\xd3^\x8dj\xf8\xb6<Ã\u07b9vc\xf6\x18MJ\x82\f\xe6R\xa7|\xf5\x9eA_\u007f\xab\xbbY\u007f!\xe5뵚\fQ%%dҚ\x8e\xbb\x18r䐡\xae^$_\xb6\xea\x1e\x8av\x88Džc\xe2\xce\a\xc9\x10\xfa\x8cHl\xa4\xc7\x14\xb8*\xa2\xe8\xb7X\xc2\"<u\\8\xee\u007f\xacZ\x85\x87\xd4+k\xd5\x06㲂\x8c\xda;v\xd2\xc5J\xff'1\xf8\u007f\f\xab\xfb\rඓ\x8fdm*}\xc2U\x06\xb3\xd1|\xbc\xc5\xc4F+6X\xac&\x06\xfb\x1cy\x17I`\xd1PP\xdb\x00K\xf0\xb0\xac\xf7\xed\x04\x10\x12c0\x9f:%\x0ey\xdcnw\xa7\xa7U\u007f!\xe5Wۇzċ\xa94Zº\x81<֢!q٬a\x82\xa3D\xb5P\xd1\x11\xec\xd6%q\x1f\x1eXw\x94^\xfe\x14SL\x05\xe4\f\xc6rӊWܹ\x96\xceX\xf5\x80x\x81J)6\x04\x1b\xfc\xfe\x827\xc4\xcb\x05/\xd2\xc5\x1a\x9aI\x15\xf1\xd7\x17\xd4\xfd\x06\xe8s\xa4\x97\xb9\xbbEV$\xf3\x06[\xfd\au\x15\x83=\xa8[YP\xcb\xe0\xbe6w&\x8c\xc1\xe1H\x8c\xc1|\xea\x14\xc674\"6\x869d\xc4\xfdj\xf3\xca\xc56:\xc61\rp\x91\xd8%f\xc9%\xa4\xfa\xbcU\xd1q\xf1U\xa7H\r^+W\xbf\x9b\xc8\xfc\xa0=9jp\x05}E\xdcT\x81\x95=)\xfa犜\xc1\xe2\xa6}\xe2\xf1\x82\xcbl1f\xf0\xab\xea~\x15\x86܅\x99(\xad\x86N\xf3\x06\xcf\xf5O)\x06\xd7\"\xceN\x9d=9\xa8\x83Ò\x18\x83\xf9\xd4)6X\x9df.kC\u007f\xb5ut\x04\xf3؇Y\x11!Z\xcbȣ\x1b+\xb0|V\x17eP\xb5\x101\xd8%\xcac\xf0\xab\x94\vd>5\xf8\x99wE\xde\xe0\x9d\xa5\xa4\x94\xbdR\xbaS\xfc\xad@\x0f\x9d\xed\f1\xf8\xd8\xd2\xcb;\xd9X\xebڭ\x8c\xc1\\\xbf\x01\xba*ER\xf7\xda\xdc\xe4\t\xb7銠\xd4\xe0\x8d\xc4\xe0\xf6\x901\xb8.\xe4\xec\x1b\x1c\x8b\bK\x82\f\xa6\xb0:\xb8\u05cd\xcd\xf35yu\x16 \xe4\xe6b\xe7Y\x99;l\xf7\xd8Y>\x955\x8dT\x95\xb3\xf0Km\xec\xa5\r\xdbT\vq\x06\x1fg\x95j\x03=3QU%\x8a\xbf\xa63\x14\x83Y\x83#\xa4\x0e\xae(\xc6>\xbe\xed\n1\xf8\xf2\x9dǖ\xd2\"Bt\xad\xf0\xd7\xc1\xaa~\x03T\xb3sh\xb9k裲\xe9\x8a\xc16\xec\xf8\xc8\\Z\a\xa7\xe5\x92\x0fpYYP[\x1e08,\x86\x1a\xac\x99:u\xda\xdd\xd5\xd7\xdd\xe8\tW\xebU[kZ\xe7\xdb\xd8\xe0T9\x8b\x15\x11\xa2\x15\xcdn\xae˰\x9f!\xf3в\xfd\xad%\xa8\x91_\xe6ͥ\a.\x1dq\xbeyiG\xd5\xfbX\xe3\x05;\x8e\x1c\xdb\xc9|kq\x1d8V\x95\xff\xae\xf8\xeeI\xe7\x03/_y\xe3\x01\xe7I<\x1e\xef\x10\xf6\x1d\xdb'\x90c\x11o\xe6\x17\xb74,\x15\x9cϼ\x89\x9f\xbcq@8 \x9f\xc2\x13\xf7\x95\x16|J'\\\xc2\u007f!\x06\xff\xdfau\xbf\x01\xaa\x91\xadڃ7\x87~&\xfd\x9b>\xdcI\x0f5\x9c\xa1-r\xec۶堔\xfa^\\\"ܞ\xe9\xf6\x94\xa1:\xbem\x10pN.,\x86\x1a\xac\x9d:ս\xbf\xde\xc3}\x97jp\xb1\xccn˕\a\xa2\xd3h%\x9b\xb0\x96\x97\xa4:\x96\xb3ڣ-\xd7n\xcfU]=pe\x85 \x1cY,\xe4\x1f\x11\x04r\xb8\xecx՝\x05U\xc7\xe9+\x97w/uU\xbdJ\xaf\x8b\x10\x9co\xe4\xe3LJ\xc8\xf1\xe0\xb5\xf9k\xd9\xf1\xe0\U000db596\xee{\xc6I\xe6^\"\xaf\xe6\xcb5\xc2\xdb\u0083lµ\x9b\x1e\x0f>=\xac\xee7@cn\xb5Ò\x96˾T\xfc\x9bޝLK\xf5<:\xf3t\xae-5o\x03Bd\xe4=]\xe8H\xcdiU\xb5\rb0\xa5\xb0{а\v\xe1L\x87\xa1\x06\xc7\x03\x9fU\xae7؞\x9cq\\r\xb1\"BޓK9\x1d\xc5\x19\xb9\xf8К\x19\xbc\x97\n(\x98\xce\xe0f\xb9\x880\xdc\xe0#w\xb2\"\xc2x\x83\xf10\xdc\x1df?w\x86c.\x83\xab\xbd\xe2|\xbf\xb8\x11\f\x16&\x91\xbf\"u\xf0_\xf3s\xc2n\n0\x99\x98\xca`\x1f\x9a]\x96\xc6.\b\xeb\xf7ZJ\xc2\xee\xa2\xeb\xd97q\x9c\u007f\xf5\xe7\xd8\xe0\u007f\xff\xe7\u007f\xedT\xe6\x85\xdb\x12`R1\x95\xc1b\xb5-W\xben\xa0\f\xef\x16Y΄o\x1dGZ\xf2\xab\xdefS\x0f\t\xff\xc9\u007fu\xe5~\x03\xeb\b@\x0fs\x19<\x15\xa0W\xb8_\x95\xa4\xd1[\x96Dq}00ـ\xc1\xb1\xe2C(7\xf7\x96\xb4ܹI+\xc1\xe0)\x00\x18\x1c+\xc3^\x87\xdd>\xcbn\xb7\xcf\xef\x82+n\xa6\x00`p\xcc\\\xec?s\xfa̙ӧ\xfb@\xe0\xa9\x00\x18<\x0eHV\x84\x81y\x11@8\xc0`\xc0܀\xc1\x80\xb9\x01\x83\x01s\x03\x06'\x8c͛\xb5&\x81\x181\xda`\xf9^\\_=\xbdβ\x9e\x9e\xd5\xeao\xado3͕+-\x82\xf3\x18\xfe\xe7x\xbe\xa0\x9f6\x11\x15\xff\x92}\x9f\xc6$\x10+\x06\x1b\xecO\x9d\x1arw\xf7c\xe8\xc5\xee}u\xde3\xdeЛk\xa6(\x17v\xe4W\xe1\u007f\xaa\\;\xd4\xf7\x16\x05Ҭ\xa2\xe5\x9e9\xefhLF\xcbs\xafL\xb4A,ĵ\xb38c\xac\xc1\x81ԩ!w\xc0ؑ&r\vBG\x93Y\x0eN\xed۔\u007fA\xbc\xe0ڴ/h\xbe\x92f\x15\x15o)\xe3\xee[\xe3\x18\x82\xef\xfa\xeeD\x1b\xc4B\\;\x8b3\x86\x1a\xac\xa4Nq\x06\xf7\xd2\xc44_\x9d\xf1\xe9\x95\xe3cߎ\xaa#\xe2\x8f6\xed\b6x]l\x06oV\xc6\xddͱ\x0f\xc1\x91\x9d\x8a\xd8 \x16\xe2\xdaY\x9c1\xd4`%u\x8a3\xb8\x9d\xdd\x1d\xe4\tw\xab\xe7\xe4prS\xb1\xf3\xceM\xc5W\x82B\xa5\x9e\tdQ\x89\xe7\xb7\xde\xe9,\x92\xa7\xfd\xec\xdbq`\xab\xb8\xe9\x006\x98\xe6\xb7\xcaI\xad\xf2U\x964\xcd*\x90E\xf5\xa6S\x106])\x16\x84\x02u\xf2\x9a\x18~\b\xfe\x87\xec\xecG7/\xfc\xc6w\xdf\x12\xc5W\xb2\xb3\xb3\xf7\xbcu\xcf\xc29\xab\xc9W\xd4Swͻ\xeb)\xfc\xef\xff\xc9f\xdcE\x9b\x1fZ=\xef\x9b\xf7\xb1\xf3\x83o}\xf7\x8e\xec;\xfe\xf6\x1du\x83\x17V/\xc43\x17\x8aA\xf8\xdbr\xfd\xe2\x15\x1f\u009b\x93\xfd-:\xf9\xd4}ߜ\xb7\xfa\x97zkSm\x99\xce*\f\xc1P\x83EQ1\xb8}\xbf\xbb\xa9\x83\xfc\xdc[\xd9}\x8c\x1da\x12O&\x877\x16\xec8r\xfc\x99;\x85O\x83C\xa5\x8aZ\x9e,\xa0YT/\xe6W<y\xbcEPEWb\x83\xdf\xcf\xff\xad\xeb]l0\xcdoeI\xad\xaa4\xab@\x16Օ\xd7[\x84\xd7\xc5\x1f-\xf8\xd1\x1b!+ߜ\xfdK\x8dIƿ\x1c\xca\xce^\xb8g\xcf\xc2y\xaf\x88\x17\x0f\x1dZ\xf8\xcdy\vﻇ\xb4\xd9<gϏ\xf7̹\a\x8f\x04/\xbc\xf0\xcd\xd5/\xbc\xf0\xc2[l\xf1\xfb~\xfc\xe8\x1dw\x11ß\x9bwף\xcf\xed\xc9~T\xd5\xe0\x95\xec{\x0e=\xf7\xd4\x1d\xd9AUZ\xa0-\xd7\xef;/d\xef\x11şn\x9eö\xe1\x8e=\x8f\xce\xfb\xae\xde\xda\xf8-\xd3Y\x851$\xc8`\x9f\xbb\xb1\xa7\xafw\u007f\xf3\xc5\xc0\x9c.՝\xc6Fp\xa0\x88\xdc6t\xa0\x80\xdc\xdfɇJ\x15\xe01w\aɢ\xba\\\xbc\t\x8f\x9d\x97\x8f\xa8w\xd9\xf6\xed\x10\xd7>P!\xd2*B\xb9_\x9f\xab\"\xf8,\xaa+;+.\x14\xaboƧ\xfc2{\xb3\xc6d\x809\v\xf1g\xfb7\v\xbfM\xa6\xef\xca^\xcdª\x9e\xcb~N$\x8f?\xa6s\xfd\xdf\xeb?\xc6\xc3&\xb6\x8e<^\\\xb8zX\x14\x87\x0f\xfdF\xd5\xe0\xa9;\xe8\xf0=O\xbd\x06\xae-\xdf\xef\x1cl\xb0\xb8g\x0ei1\xe7\x1b\xf8Cs\xcf\x1d\xa2\xaa3nmܖi\xaf\xc2 \x12d\xb0\xd8C\x8b\xdf\xfa\xce@v\xa5\xd7\xf01\xf8ݢ\xd2\xddϼq\x85~\xc1\xf3\xa1R\xc4c9E\"t\xec\xa4\x06?)<\x19\xc6`U\x16\xd5\xe5u+6\xa9\x83\x01)\xff\x90\xfd\x96\xc6d\x809\xb4\xaex*\x9b\xb8x\xd7\x1cy\x88\xde\xfc-\xfaϷ\xa8\xf0\x01\xa7\xbe\xbb\x90\xfcQ\x8f\x91\x85\x9b\x89^\xdc!\x83@\x83_ޱ\xf0\x1f\x9ezE\f\xba\x1a\x9fk\xcb\xf7\xcb\x1b\xbc90\xa9\xb96n˴Wa\x10\x892\x98AJ\x87v\x16l\xd7ڮ\xd5|R\xb9\xf0\xcc\xf6U\u008a'\xa9`|\xa8\x94([y@\b)_Ej\xf0\x85}\xbf\x0ec\xb0:\x8b\xeaH 3\x85\xe3\x9d9\x9b5&\x15\xa8H\xe2\vԲ\xbb\xee\x92g\xaef\x1a\xfd-\x1b\x99\xfdN\xdd%W\xa9\xf8\xf9\xa3\xd9\x17\x95.\x94\x9d\xaf\xdf<\xf5\xddoe\xdf\U00068a02k\xcb\xf7\xcb\x1b\xacLj\xae\x8d\xdb2\xedU\x18D\x82\f\x96\xb5\xf5zHf\x0f\x1d\x8e݆\x1f\x8bxu\x1fv\xf7\xc2\x11\x17-s\xb9P\xa9\x80\x95/\nZ\x87xI\b\x10F1\xb8\x813\x98\xa4Y\xa9\xb2\xa8\xde/j(\xfemH\x1f\xf7)\xe3\xee}\x1aCp`\f&?\x99\x80=\x9bٞ\xd2Be\f~\x8a|\xcf/|\x85Bˁ\xe01\x984x\x85\xf4\xf5\x9bCs\x9e\x12y\xb8\xb6|\xbf\xe1\f\x0eZ\x1b\xb7eګ0\x88\x04\x19\xec\xa1i\xc1C\xf5\xdd\xe4x0)#\xbc\xc6\x1f\x0fn\xa1\x91\xabb\xd5\x03\xe4\x91\v\x95\n\x18|\xa9\xa8\x8a\f»w\xd3\xf9}\xdb\xd8my\xbc\xc1\xf9\xf8\xe1J\x0538\x90f\xc5gQ]\xaeh\x11\x1f\xa8\n.#\"\r\xc1\xe2\x9c;H\x81\xb9p5\x99\x0e\xaaA\x0f\xb1:x5~\xed\x1d2\xe39V\x93\xee\xc1\xbe\xf9\xee \xb5\xadx\xdf}\xaa\x06{h\x99+\xaeV\xaf\x87k\xcb\xf7;\x0f?\x1f\xf9v\x88\xc1Zk\xe3\xb6L{\x15\x06a\xa8\xc1J\xeaT\x9f\xbb\xedt_W\x1d\x1d\x89\x13uN\xaeE\xc8o9vl\xa7\xc0ĕC\xa5TYT/\xbaV\x1d8\xbe\x9b届\x8bX\xe0\xceowT\x91\xd4\xc0w\xabv\u0875\xa2\xe8ɖ\n9\xa1ʟf\xc5eQ]~\xf9\xa1\xa2\xf7\xc5\xf3\x05\xbb_V\x97#\x91\x86`qN\xf6]\x87\x9e\xfa\xe67\xde\x12G~J\x8f\x03\xb06\xf7d\xdf\xf7\xe3\xfb\xb2\xef\xa1\xd3{\xe6<zh\xf5\xbc_\xd2\x1e\xee9th35\xeb\xb99\xdfz\n\xb7xJ\xd5`O\xf6\xbc=?\xc6\r\x9eS\xaf\x82k\xcb\xf5\xbb\xfa\x8eG\xf7|;;\xfb\xd0+0\xbd\xf9\xa7\xe2+\x9b\xb3_xG{m\xfc\x96\xe9\xac\xc2\x18\f5\x98K\x9d\x1alo\xaa\xf7\xf4\xb0\xd9\xfdmu\xad\t\xb8.\xe2GU-\xc5\u03a2*9\x89G\x0e\x95ReQ\x89oo/^\\q\x8c5\xa8\xb7\xd30\xca\x16A \xd5\xc6\x03\x02\xb9.\xe2|\x95k\xf1\xa6\x06\xd6֟f%*YT\xc7q7\xbb\xc5݂\xb0\xe0E~\xc5\xef̻Gc\x92g\xce}\x9b\xe7\xddq\xcf;\xec\xa8+\xe6o\xd9\xecG\xe5㶘\xe1\xfb\xbe1g\xf5O\xe9\xe4s\xab\xef\xf8\xc6j:0\x8bo}w\xe1\xbco\x1fR78\xb4z\xcf\xc2\xec;V\x87\xd8ŵU\xfa}k\xf5\x9cy\xab\xf7dgo\xdeLV\xfb\xca<\xfc\xb0Y{m\xfc\x96\xe9\xad\xc2\x10\f5x*\x13\b\x95\x9a|\xf6d\xff\x8b\xc6$\x0fۓ\x03\xa2\x01\f\x96\t\x84JM>\x91/\xab\x04\x83\xa3\a\f&\xb4\xbcx\xa5j\x82\x17K\xc6\x1508z\xc0`\xcc%\xa1\xe2\xa1\"\xf5\x99\xb7D\xc2\xf6\xa2\x80\xe8\x00\x83\tJ\xa8\xd4T\x80\xeeEi\x1d\xa2\x004\x00\x83\x01s\x03\x06\x03\xe6\x06\f\x8e+I\xe6\"\xd2\xdb1\x03`p\\I\xfa\xc8L\x80\xc1@0`\xb0\xe1\x80\xc1q\x05\f6\x1c08\xae\x80\xc1\x86\x03\x06Ǖ\xa8\f\xe6\x1b=rk\xd0\"!3\"\xa1\xd7<\x8an\xc0` \x98\xa4h\xcc\xe1[\xdc\xf6à\x17Cf\x84!)\xf0\xa0\xf9b\xe0\x90\x83N\v0x<h\xa5N\x05\xe6N-\xcaPr\xc8\xdf8\x969cA\x99\x9a/De0OH\xebX\x16\x8f`p\xb8Wً\x81\xedf\x99\x01\xa6\xc4`\x83\xb5R\xa7\x94\xb9S\x03o\x17\xfb\xb7\xdfk\xd1\xfd\x93u\x9d%V\xcd\xf9\xf2\xc0w\xeb/\xb0\x1f\xbf\xba\xe5\xe7I\u007f\u007fۿ\xbb\xed{D\x96G\xbe\x9ct\xdb\xdf\xf8\xc5\xc1\xff\xfbǿH\xba\xe5\xeb?\xff\x88\x8d\x90\xa4\xd5\xdf˯\xa9f$\xfd\x9d\\S\xe0\x8e\x92\xbe\xfc\xc3\xefݖ\xf4\x95\x9f(\x9d\xb1\xf1\xd5\xdf\x15\xd7\xcd\xf7Ȅ\xdf\xe0\x9f\xe8o\x8cb0\xcb\f0%\xc6\x1a\xac\x95:\xc5͝\x1a\xcc\r\xfc\r\xfa0\u007ft\xb1Z\xcf`:\xea}\x8d\x88\xf2\xbd\xff\xfaQҭO\xfc\xea\x89[\u007f\xf0\xd1G?\xfc\xf2\x0f\u007f\xf5\x93\xaf\xfd\x8db\xf0mO\xfc\xeag_\xff:k\xfdȭO\xfc\xe2\x89[\x1f\t\xbc\xa8\xccH\xfa\xea\xcf\xe4\xb9_\xf9ɯ\xfe\xfb\x97\xc8\xc3\u05f8\xce\xd8\x18\xec\xef*\xb0\xd4\x0f\xe8Z\x03c\xb0\xfe\xc6\xf0UD\v\x18\x1c\x05\x9a\xa9S\xdcܩ\xc1\xec\x89\x1b\xfc\xc4m\xf8\xe1\xab\xff\xfcQ\x12\xd1\xf2\x91\xaf\xe2iR\xdd\xfe\xec6\xc5\xe0\u007f&\xcfoa\xad\xff\x92\xb6\xfaK\xc5\xe0\xc0\fڌ\xce\xc5C\xef\xcf\xe9×\xb8Θ\xc1\xfe\xae\x02K}\x85N\x04\f\xd6\xdf\x1808V4S\xa7\xb8\xb9F2\x9cf\xd9\xe0px\xcbRsi`Sc\x8e-\xa3\x1cOy\x10c6\x99i-/ϰ\xe5\xb1-u϶e\xd1ی\xc4\xfe\xe5\x0e{\xa1n\x15\xc1\xb4\xfa\x8bG>\xfa\xc9W\xf04\xf9r\xff9\xb6\xeb\x16~\x97*P,\xcb\x13\xb7\xf8[\xc9\xf3\x94\x19I\xbf\xf8H\x99\x1bx\bt\xa6̥\xb3\x03+\xa3\x13\x81\xf9\xfa\x1b\x93t\x80ރ\xfa\xfe\x8e\xa2\x82\xadPEDIh\xea\x147\xd7P\xbc\xa9\xa8|>\xb2oK\xab\xc1OJ\x92\xcb<\xb5\xf6\xd9#\xa2\xafÛ\x91\xeb\xf5\xb2]K+\xcaljM[B&K\xac\x1b=\x1b\xad\xcb\xf1\xd4\xe9Ԍ\xfa\xd6<\x14\xde\xe0\u007f\xfc\xcaG\u007f\xf3\x8f\x9c4Ir5\xe0\xb7*Z\x83\xb9E\x94\x87@gQ\x1a\xac\xbb1I.r\xdf\xf5\xf9\x82U\xcf\x1c\xdb$\x80\xc1\xd1\x11\x9a:\xc5\xcd5\x96\xb4\xe5x\xc4\xf5\x88%+\xc9\xc8[\x8fgt\"z쁫\"\xc8\x1fq.\xb1\xe3\xa96\xd4\xe6\u007f̝\x85?w#Y\xe1\r\xfe\xe8\xd6\x1f\x92\xaa \xe9\x11\xfc\xf0\b\x1e\xff\xfeR\xdeQ\xf3[\xa528L\x15\xc1-\xa2<\x04:S\x1b\xacWE\xe8oL\xd2q\x128P\xb5\xea\x12ޕ[\v\x06GGh\xea\x14?\xd7PҚ\xb1\xb3>\xb1r\x99(.\x9b5Lp\x94\x90\xf9\x9c\xc1XnV\U00056c03g\x99%\xe2\x10\xa2\xb5\xc4F]\x83o\xfb\x01\x91\xe3\xef\xd8ξ\u007f\xe7\xe9\x89[\xbe\xf7\xf3_=\xf1\xb5\x80x*\x83\x1f\xa1\xad\x1e\t\xbc\xa8\xcc\xd068\xd0\x19]U\xa0\xab\xc0RA{r\xfa\x1b\x93$\xaez@\xbc\xc0\xd2\x04\x1a\xc0\xe0\xe8\bM\x9d\n\x9dk\x10imb\xa7E\xa4\x06g\xc9\xd5/-\x18\x82\xf6\xe4\xa8\xc19\x8b茼\x1c\xb1\vќ7\xfd=\xb9Gn#%\xe6/\xbeD\xbe\xaa\xc9A0v\x00뉯~)\xe9\xabO\x04tT\x19\xfc\x11i\xa5\x1aW\xfd3\xb4\r\x0etFW\xa5\x98\x1a\xe8\xe6{\xb7rG\xd3>\xd2ߘ$qS\x85\xf8\xaap\x92l9\xec\xc9EIh\xea\x147\xd7X\x88\xc1Vf\xf0\xf2Y]\x14z|\x9a\x1aL\x13X\x14\x83Kf\xd1E\xd2\x03c\xb0\xfe\x9e\x1c㑯\a\xfcI<z\x1b\x93t\xa5t\xa7\xf8[\x96.\xbb\x13\f\x8e\x8e\xd0\xd4)n\xae\xb1p\x06\xb7\xb1\nx\xc36\xf2\x98\x9b+\x8a\x83t\x86b\xb0\x87>o\xc6e\xb3\x98\xe3\xc0\xc5\xf1\xe9\xdb\xc3\x1b\xfc\xb3/\xffL[\x9aD\xa0\xbb1IGH\x1d\\Q|A\x14\xdfv\x81\xc1Q\xa0\x9d:\xa5\xcc5\x94^{\x8d\xaf\xd9\xd2\xe3[\x96\x8b\x87\xdbJ\xb4l\u007fk\t\xa2\x19\xc6\xd5֚\xd6\xf9\xb6>rN\xae\xa4S\xec*\xb1x\xfb\xf1(\x9d\\\xe9\xa9L&\xc7\"zl\x8e\xea\x8d\xf6\xe4\x94z\xad3\xe1\xb2%I_\xfa\xc1G\xda\xd2$\x00\xfd\x8dI\x12ȱ\x887\xf3\x8b[\x1a\x96\xca\xd9Y\xe6\xc3P\x83\xb5S\xa7\xb8\xb9\x062\x92\x86PS*\xb25\xb3\xea\xb7-\xd7n\xcfe\u007f\x0f\xe1b\x99ݖ\xdbI\xae\x8b@\xc8\xd2cÏexnm\x96-\xab\x96\xbe~z\x91=\xbd\xbc>\x85\xce\rfJ(\x1b5\xf2\xf1\xe0\U000db596\xee{\xc6I\xb3\xb3̇\xa1\x06O\u007fLfp\xa4\xb7c\x06\xc0ฒd.\"\xbd\x1d3\x00\x06\x03\xe6\x06\f\x06\xcc\r\x18\f\x98\x1b0\x1807`0`n\xc0`\xc0܀\xc1\x80\xb9\x01\x83\x01s\x03\x06\x03\xe6\x06\f\x06\xcc\r\x18\f\x98\x1b0\x1807F\x1b\xac\x91:\xe5\xf36\u05f5v\x0f\x87_nr\xa8\xb1\xd6\xe8\xbfؚ\"\xdf{\x94\xb2_\xbfQ\\\xf9\xed\x03+\\\x9b\xae\xd0?\x18*䟏\xd4:\x98cN\x81\xe1<\x12\xa9\xe9t\xc2`\x835R\xa7|\xf5\xad=}]\xf5\xad\x89P8˒\xa5\xffb\r\xf2zkQ\xad\u05cb\xc2h\x1eW\xaa\x8a\x0e\xec̿ \x8a\xef\x9f<y@x9l\xd3\x17_\r\x99\xf5\xa4@\x16;p\xf2\xe4\x82'5\x16\x98\xb6\x18k\xb0V\xeaT{3\xf9\xab\xf6C\x89\x88\xed\xf1%/Oֿ\xb0\xbe\xd6Bn\xc0\xef\x14E[\xadn\x9b\xb8rA8 ^\xb9Ħ_\x8d`p\xc5\xf6\x90Y\a\x9c\xf2b\xf9\a4\x16\x98\xb6\x18j\xb0f\xeaT+\xfb\x8e\xf6\xdf\xf4i$^\xd4\xcd\xee<\xd6\xe4\xe2\x19\xd9\xe03\x17u\xdbĕ\xf3±\xc0t$\x83ׅ\x1a|\xf9\xbc\xbc\xd8\xf9ˡ\xed\xa7/\x86\x1a\xac\x99:\xd5Ϧ:\x8c*69\xaa\x1d\xa2\x83\xdc\xccٍ+ލ\xa7\x97\xa7\xdb\xf2p)3\xb8\xdc\xee(/\xb7\xdb轟\xd4`\x96E\xb5A\xacƏ\xcde(\xa5v\xa5þ\xe84\xed\xc1\x1fV\x15\vo\xe2z\xb5\xe1\xfc\x8eRצOE\xf1ʏ*\xf2W\xed\xc6\x03\xef\xe5;Y\x11\xbb\x9b5\n\x18\x1ch\x809\xbf\xf5NgѦ\xf7\xc5cr\xc1[\x11ҷ\xbc\x18i\xd0 \xb6\xe0\xc7#\x0f\t\xce\x03\x0f\x16-\xddt>\xb8\xb3邡\x06\x8bz\xa9S\xa28Ҥ?\x18N\x1a\xf3\v\xc5\xc2\\\xfc\xaf\xaf\xb9)=#\xd5Q\xbe\x1c\xf5\x89Ùi\xb5\xd5V[]\x1e-~e\x83}\x1d\x8e5\x83\xe2`uj\x87\xaf\xb7)\x05\xa5o\xabN\xb7\x91\x9b\xfc\x02aU\xb1p\xf9ȑ\xe2U\x8b\x8bw\xefX\xf0\xae(\xee\x14v\x1f?P\xb4\x0eᄑq\xf2\x88\xd0r\xf2们Q\xc0`\xa5\x81\xf8b~œ\xc7[p\xa9q\xe9哫\xaaN\x9e<\x19\xfawH\xe5\xc5.\xbd\\\xfc\xc0\xaf\xc5_\xb7\x14\x9c\xbc\xf4\xe6\x11\xa7P\xdc\xd2R\x9c\xff\xa6\xba\xb3iC\x82\f\x0eJ\x9d\xc2Cp\xfd\x90\xde\"\x93ƈ\xadF\xac\xb11\xfdf\xa3\xf9\xf8\xe3\xe4#w\xd4w\xe3\x12\x18\xb1\x9bP\xfd\x06\xe3\xe1\x9aD\x01\x96\xd0L\x1fk:n6\xe4\xc8\t\n\xab\x8a\x85uB\xd5\x05\xf1\xca\x052X>#\x12\xef\xe8\xd1\x03\xad*\x82kp\xb9x\xd3e\xe2?\xfd\x03\xd0\x1aU\x04\xbf\x98\xd8B\xc6\xe7\x1d;ɤ\xab\x14/q\xa1\xb8\"hmӅ\x04\x19\x1c\x94:%v\xf2y\xc2Fэ:|\x1d\x88EV̶\xca\x1bPIb\xd2N#9L(`p\x1fv\xfabj;\x99\xb4n \x8f\xb5hH\x1dV\x15\v\xeb\\\xf2P\xbb\xa3\xf4\xf2\xa7\x98b\xaa\x9a\x96\xc1\\\x83\xe3\xc2\x1b\\\x0f\x11\f~\u007f\xc1\x1b\xe2\xe5\x82\x17ɤ\xab\x81<\x1e\x10.\xa8\xd76]H\x94\xc1\f9uj\xd8\xebNğ!\xa8\xa5G{ف\x86\xd9s\xe5\x995h\x90$\xa0\x04\x8f\xc1b^\xb9\xd8f\xa7G\xfcX\xaa\xb0\x17u\xa9êba\x9d\xbf\x82]+W\xb4\x9b\xc8\x13-\x83\xb9\x06\a\x04n\x0f-\x92\xc1\xe2\xa6}\xe2\xf1\x02\xba\x80\xab\x85<\x9e\x14^U\xafm\xba\x90 \x83U\xa9S>Oc\xbf\xee\x02\x93H\xe1\xec\xce\xceN9%-\x10\x96֗\x9c\xd7ם\x91#?S\f\xf6؇Y\x11!ZiP\x84\x1b\xf9\xd4aU\xb1\xb0n\xab<\xb1\xa3\xf4U\n\xad\f\xb4\xc7\xe0@\x83\x17\x05\xee\x1805\xf8\x99w\xc5 \x14\x83\x8f-\xbd\xbc\x93\x8d\xb5.\xbas\xf8\f\x1d\x83\xb9\xb5M\x17\x12d0\x9f:5Լ\x9f\x96\x14\xfa\vM\x12\x8er\xfcP\xee\xa0\xd3\x01\x83\xbbP\x1aB\xb9\xfeO\x94b\xf0\xb0\xddc\xa7E\x84hM#\x15\xf3\xacܠ\xb0\xaaX\b\x8c\xa0\xc7YM\xda@\xcfAh\x19\xcc5\xb8TTE\xc6\xd4\xddTȪ*Q\xfc\xb5\\\xd0\xf6m;\x13\xbc\x189\xb6ql)-\"D\u05caKx\xe1Ҫ\xa0\xb5M\x17\f5X3u\xaa\xaf\xae\xb9\xaf\xbf\xbf\xbf#\xe6ݡ\t\xe2\xf3\xa0\r>ѷ\x01\xb5]\x1c\ue931\xd7ԃnk\xbb\xc7\xeb\x17\xb8\xab\x16\xd5v\xc9ӕ\xb3X\x11!Z\xd1\xec\xe6\xba\f;i͇UEͧ\xaf\xd3#\t\xe7\xe9\x93}\vv\x1c9\xb6\x93\x98ŎE\xbcL\x8e\x13\xbc+\x9f\\{W\xd5@|ѵ\xea\xc0\xf1\xdd,,\xb5\xc5u\xe0XU>\x1b\x83\x17\xa1<\xb9\xeb7\xf0b\xfe\x81z_i\xc1\xa7t\xc2%T\x1cyfU\xc1\xdb\xeaΦ\r\x86\x1a\xac\x99:\xd5\xc6f\xba\x8d>\xa3\xd1N\x8e\xee\x8a\xfb\xf1c{w2-g\xa9\a\x1d\x162i\xc9%\xdb\xe6#\x91S6\xf9\xcb\xe14Z\xc9&\xac\xe5%\xa9\x8e\xe5Lr.\xac*j\xdeT\x15\xa3ǫ\xee,\xa8:\x8e\xc7\xcc\x02:\xd7ID\xdb)\u05eb\xdb\xf9\x06\x98\xb7\xb7\x17/\xae`\xe3\xf4\xe5\xddK]U\xb2\xac\xf5v\xf6\xe7\x11\xc4K\xf9x\xa1|\xb9Fx[x\x90M\xb8v\xef,(\xda\xf1\xaejm\xd3\bC\r6\x01\x83\xb65\x83\xc3\xc3C]K\xec\xc1U\x8d\xcf*\x1f\xb1\x0e\xf3\xf7a\xa6\x12\x97\\\xac\x88\x90\xf7\xe4\xa6-`\xb0\x9aV\xbb<a\x0f\xfeNh\x96\x8b\b\xb3\x18|\xe4NVD\x80\xc1\xbaD\xeaڔt%\xb3\xe3h=\xc9\xdd\xfc\xecj\xaf8\xdf/\xae\x19\fny\xf1J\x95_\\0X\x8fH]\x9b\x93\x12ۚfo\xf3\x1a\xdbJ~\xa6\x0f\xcd.Kc'\rY\xaa\xf0\x14\xe7\x92P\xf1P\x11\xab\x87\xdf?\xe9|\xe0\xe5iu\x1a9\b08\x18O\x9e\xc3\xe2\xc8\v\xaa!\xaam\xb9\xf29\x17\x9a*\x1c8z5Uiɯ\x92/\x9ax\x88\xec\x1e\x9e\x0f\xdb\xd8܀\xc1\x80\xb9\x01\x83\x01s\x03\x06\x03\xe6\x06\f\x06\xcc\r\x18\f\x98\x1b0\x1807`0`n\xc0`\xc0܀\xc1\x80\xb91\xda`\x8dԩ\xfe\xb6\xa6\xba\xe6\x0e\xc3/p\xaf'WQ\xda\xf3\xba\xf4[\x94\x90k+O\a͜\xcc,*H\x9d\x1a\a\x06\x1b\xac\x91:5\xe8\xf6\xf4\xf6\xf5\xeeo2Za_=\xda\xe6\xad\xcf\t\x13y\xd2GR\xa7\x82\xaf\x81\x98\xcc,*H\x9d\x1a\a\xc6\x1a\xac\x95:u\x86N\xfa\x8c\xbf׳\a\x91K\xd3s3µ\xe9\f1x\x12\xb3\xa8 uj<\x18j\xb0f\xea\x14\xbbAn\xd0m\xf8͞\xcc\xe0Z\x14n\xf0\x0f5x\x12\xb3\xa8 uj<\x18j\xb0f\xea\x14}\xa1\xaf\xd9蛌\xfc\x06/gwz\xfa\xe3\xa3ԡR~\x83\xb9\xd4)\xed\xb9\xb1dQA\xeaT\\1\xd4`Q;uj\x90\xec\xd3\x19]\x06\x13\x83=\xbe\xdeJDo4\x0e\xc4G\xa9B\xa5\xb4R\xa7\xb4\xe7ƒE\x05\xa9Sq%A\x06\xabS\xa7\x06\xfb{\x9a\rߓ\xc3\x06\x13\x96\x93I>>J\t\x95\x12\xb5S\xa7\xe2\x90E\x05\xa9S\xf1#A\x06\a\xa7N\x89\xc3\xcd\xed\xda\vL\x1e=\xa8\xa6ӓc#W\xab\xf3\xf1QJ\xa8\x94\xa8\x9d:\x15\x87,*H\x9d\x8a\x1f\x892\x98AR\xa7\xe4\x1d\xa2n\xb7F\xebI\x85\xd6\xc1C\xc9d\xbd||\x94\x12*%j\xa7N\xc5!\x8b\nR\xa7\xe2G\x82\f\xe6R\xa7\x1a\xd9\x01\xd9\xee:\xbdE&\v\xb6'\x97J\xcc\xe3㣔P)Q;u*\x0eYT\x90:\x15?\x12d0\x97:\xd5D\x03C\x12RE\x905\xa7\x95\xf7lS\xc5G)\xa1R\xa2v\xeaT\x1c\xb2\xa8 u*~\x18j\xb0f\xea\xd4iw{o_oB\xf6\xe4\xe8\x19\x8d\xbc\x92,U|\x94\x12*\xd5'\x9f}c\a\xfe\x02\xa9S\x13͢\x82ԩ\xb8b\xa8\xc1\x9a\xa9Sb\u007f{s]kg\xdc\xcf\x0fD\xa2\x19\x97\xaa5\xd8\xe3\f\x9am\xa2\xc4G)\xa1R%rA\xcbB\x01\x03\xa9S\x13͢\x82ԩ\xb8b\xa8\xc1\xa6@/\xd0$\x90:\xa5=w\xca\xe5\xa0@\xeaTD\"umR\xf4T\f\xa4Niϝr\x06C\xeaTD\"umR4U\xe4S\xa7\xb4\xe7N-\x83!u*\x1a\"umJ\xb4C\xa5\xb8\xd4)\xed\xb9S,\x8b\nR\xa7\xa2\"RצD'TJI\x9dҞ;ղ\xa8 u*\x1a\"u\r\x00\x06\x00\x06\x03\xe6\x06\f\x06\xcc\r\x18\f\x98\x1b0\x1807`0`n\xc0`\xc0܀\xc1\x80\xb9\x01\x83\x01sc\xb4\xc1\x1a\xa9S\x98\x1e\xc3\xff\xa2gt\xf4\xe4\xd9Җy\xd3Tw[pYT\x9a\xb1T\xb1\xd2\x1e\xf2\x97\xeb\x80X0\xd8`\x8d\xd4)\xf2\xac\xae#\xb6?Ml\x10m\xb6\xb9\xee\xe6,\x84T'\x94\xb9,*\xcdX\xaaX\xf1\xd84\x02ؼ]\xa1\xf3\x00M\x8c5X+u\n\xe3i\uf6ca\x06\x0f\xa5.\xb9H\xee\x1cB\xc1\x97DpI>\xa1\xa1>qana\xa4\x16\x80\x8c\xa1\x06k\xa7N\x89=\xf5\xbe\xfe\xa9hp\xa5\x8d~GԠ\xe0Ba\xf2\r\x9e\r\x06G\x8b\xa1\x06k\xa7N\xf9\xeaN\x8b\t0\xb8\fY\xdc\xe5\x19\xb6\xbc>2\x99\xdc(\x9e\xb1\xa0Lq8Ͳ\xc1\xe1\xf0\x96\xa5\xe6\xfaDq\x16\xbb\x81h\xb0\xe6\xa2\xe8+tX\x1c\x8b\xfc\u007f\xa8V\xcb\xe0\x8e<\x87Ş\x97\x1e\xbc\x16\r\x94\xb5ៃ\r\xa1\xe4&67\xb09\x1e\xf9\xee\xa6\xd9\x11:\x02\b\x86\x1a,j\xa6Ny\xda\xc5D\x18L\x82\xa2\xec\xd55\xa9K\xe8ս\xd5X\xc6\x12+\xfe\x9aHE\xe5\xf3\x91}[Z\x8dx1YI\xa7\xf4\xa0\x95\xde\xe6Eɲ\xad\x1a\x06w\xa1\x92\xfd\xedn;Һ\x8f#\bnmx9\xaf\x97]\x1b\xcfm\x8e\xafÛ\x91\xeb\xf5z\rO\xf34%\t2\x98K\x9d\xea%\x91i\t0X\x14\xadv<\xe0-\xa7\u007f̞ZTM\x9cJ[\x8eu\xf5\x88%+\xc5>\xd4\x1ah\xeak&\x1f\xb6\xac%왆\xc1nz\xb7Qm\xaa\x18\r\xca\xda\b6\xf9\xee\x0ens\xa0\x8a\x88\x9e\x04\x19\xac\xa4N\xf9\xeazGFF\xfa\x1a\xf5r\xf2&\x11+\xc9*a\"q\x067c+}b\xe52q8\x85˸\x1et\xe7\xcdJEY쉆\xc1}\x8e\xf42w\xb7\x18\xc5\x10,\xea\x1a\xacl\x0e\x18\x1c=\x892\x98\xd1\xd1*\x9eq\xfb1<@\x98\x13\x893\xb8M초\xc4`\u007f\x1d<܆EMsT\xb6zs\xf5\r\xc6uQa&J\x8b.\xd7]\xc7`n.\x18\x1c5\t2\x98K\x9d\x1a$\xf4\xd4\x0f\x86\ti\x9a$\x82\r\xde\xe87\xd8\xca\f\x96\x8fE4\xa3A13\x87|g\x14\xea\x1b\xdcU2\x10U\xbe\x00\x00\x1e\xa0IDAT)\x92Z\xc3\x16U\xfa\x9b\xb26\x82\xae\xc1u\xaa\x8ce@\x9b\x04\x19̥NQ\x12S\a+\xcaذ\x80#s\x83\f\x1eJ]\x82\xab\x82\x91\xdctQt\x10\xa3F\xb2\xf4\r\xae\xa6\x01@b\xee\x1a1\n\x94\xb5\xd1g\x1a\x06\xe7\xe6\xe2\x8fv\xb8\xfcV\xc0\x8f\xa1\x06k\xa6NaF\xfa{\xea\xfbCn\x05\x9ed\xd8\xed\xc5]%\x16/._r\xec۶堔\xfa\xde^{\x8d\xaf\xd9\xd2\xe3[\x96\xdbG\xce\xc9\xe5Է\xe6\xa5t\x10A\v\xdd\xdbf#{M'\x9fE\xc5MV#[\xb5\xa7\xb5$\xccߕ\xe1\b\xacM\x1c\xee\xf4z\xad%\xde\x0e\x9fzs\xb0\xc85\xad\xf3m0\x06G\x81\xa1\x06k\xa7Na\x99\xc8ܦpKN\x02\xf4\xf6\xe2\x1e\x92 U&\x8a\xa7sm\xa9y\x1b\x10Z\x93\x86PS*\xb25\xb3\xf0Tr]\xc4\"\xb2\x95#5\x19V\xfb\xb2\xfaY\x96\\>\x8b\x8a\x9bḽvX\xd2r\xa3\x128\xb0\xb62\xb1+\x99\xf5\xe0Vo\x8ex\xb1\xccn˝\x94s%\xd3\x0eC\r\x06\x80\xb8\x03\x06\x03\xe6\x06\f\x06\xcc\r\x18\f\x98\x1b0\x1807`0`n\xc0`\xc0܀\xc1\x80\xb9\x01\x83\x01s\x03\x06\x03\xe6\x06\f\x06\xcc\r\x18\f\x98\x1b\x13\x18\\\x88\xec\xcb\xe1\x961@\a\x13\x18\xdc\xef\xadϴ\x1b\xfe\x17?\x01\x93`\xb4\xc1\xa1\xa9SA\x01T\xdaK\xa1n\x11\x00\xb40\xd8`\x8d\xd4)u\x00\x956\x93\x94+\x02L\x03\x8c5X+uJ\x1d@\xa5\r\x18\f\xe8a\xa8\xc1\x9a\xa9S`00\x11\f5X3u*\x1a\x83{\xa2\xbb\xff\f\x98\x81\x18j\xb0\xa8\x95:\xc5\aP\xe91l\xcf\xe9\xe8K@&\n0\xf5I\x90\xc1\\\xea\x147\xa9O\x1bBhQ\xb8\x06\xc0L%A\x06+\xa9S\xaaI=|\xf6\xf4\xda\xf6\xc8\xc5\x060\x03I\x94\xc1\x8c\x8eV\xad\xc9P:Q{\x98W\x81\x99L\x82\f\xe6R\xa7\xb8I]\xe0X\x04\xa0G\x82\f\xe6R\xa7\x82\x03\xa8\xb4\x00\x83\x01=\f5X3uJ\x1d@\xa5\r\x18\f\xe8a\xa8\xc1کS\xaa\x00*\r\x86\xfb\xbb\n\xad\x86G\xb3\x02&\xc1P\x83\xc7\xc7\x12\x84\xd2\xc3\xed\xe6\x013\x1a\x13\x18\xdc\xdf\r\xc7\xd1\x00]L`0\x00\x84\x01\f\x06\xcc\r\x18\f\x98\x1b0\x1807`0`n\xc0`\xc0܀\xc1\x80\xb9\x01\x83\x01s\x03\x06\x03\xe6\x06\f\x06\xcc\r\x18\f\x98\x1b0\x1807F\x1b\x1c\x9a:\x85\xe9m\xabo\xee\n\xb3\x10\x00\xe8b\xb0\xc1\x1a\xa9S\xe2p\xbb\xbb\xf3L\x97\xfbL\xb8\xe5\x00@\ac\r\xd6J\x9d\x12\xdb\xeb\xfa\x89\xda\x10\xb0\n\x8c\aC\r\xd6L\x9d\xeaw\xd3;\xe4 ^\x15\x18\x17\x86\x1a\xac\x99:\xd5Y\x17.w\x15\x00\xc2c\xa8\xc1\xa2V\xeaT\xab\xa7\xb75R\xea\x14\x00\xe8\x91 \x83\xb9\xa8\xa9f:\xd9\xd4\f#10\x1e\x12d0\x175婋\x9c:\x05\x00z$\xca`\x06\x89\x9a\xf2\xb2\xfb\x90\xbdp;20\x1e\x12d0\x175\xd5U?\xc2\xcd\x01\x80\xd8H\x90\xc1\\\xd4\xd4\x10=\x9a\xe6\x93\x0f\xb3\x01@l\x18j\xb0f\xea\x94\xd8U\xd7\xd5\xd7\xd3\xd8\n{r\xc0x0\xd4`\xed\xd4)\xf1Lk\xfd\xfe.\x10\x18\x18\x17\x86\x1a\f\x00q\a\f\x06\xcc\r\x18\f\x98\x1b0\x1807`0`n\xc0`\xc0܀\xc1\x80\xb9\x01\x83\x01s\x03\x06\x03\xe6\x06\f\x06\xcc\r\x18\f\x98\x1b0x*0\x12\xa9\x01\xa0\v\x18\x9cp\xfaK\xd2ВH\x8d\x00=\xc0\xe0\x84\x93\x99\xe9n\x87\xbf76n\x8c68$uj\xb8\x91]r\xe9n\x8a\xb0\xe4$s\xbc\xe8X\xa4&\x93C\x0fj\x8b\xd4\x04\b\x83\xc1\x06\x87\xa6N\xf9\xdc]d\xaa\xcb\x1d\xe6/\x83{\xbb\xf4_\x8b\x17\xc7\xf2\x8fDj\xa2A,[\xa6Ӷ\vuh\xce\a\xa2\xc3X\x83\xb5R\xa7\xd8]ˍ\xe1~\x8ds\vü\x18/\xaeDj\xa0E,[\xa6\xd3\x16\xfe\xea\xf9\xc40\xd4`\xcd\xd4)\x8ag\u007f\xb8{4f\xc7\xe0\x89\xb1IJe:m\xc1\xe0\x89\xf1g\x1b\x00\xc0\xccL`\f\x06\x80)\x00\x18\f\x98\x1b0\x1807`0`n\xc0`\xc0܀\xc1\x80\xb9\x01\x83\x01s\x03\x06\x03\xe6\x06\f\x06\xcc\r\x18\f\x98\x1b0\x1807`0`n\xc0`\xc0܀\xc1\x80\xb9\x01\x83\x01s\x03\x06\x03\xe6\x06\f\x06\xcc\r\x18\f\x98\x1b0\x1807`0`n\xc0`\xc0܀\xc1\x80\xb9\x01\x83\x01s\x03\x06\x03\xe6\x06\f\x06\xcc\r\x18\f\x98\x1b0\x1807`0`n\xc0`\xc0܀\xc1\x80\xb9\x01\x83\x01s\x03\x06\x03\xe6\x06\f\x06\xccMX\x83\xeb\x11O\u007f\xb8\xa6\x00\x90\x18\xc0`\xc0܄5x\xf4\x1aa.\xaa\xa6\xff\x8e\x86k\n\x00\x89!\x8a:8\a\xd5DjbjJJ\xf8gː\xa8\xd7P\xcdU\xbb\x9b\xfd[\x9e~{\xa6\x9b}\xbc\xdbsli\x85C\xfa\xcb,B\xa3Ѯ\xe0Z\xa5\xc3⨼\x86\xa7jr\"\xb5\x9dр\xc1]\xd6a\xfei\x94\x82I\xa3\xf3\x115\xf8j:*\xac\x9e\x8b\n\xc9\xf46\x94Q]\x92\x92\xea\xd3](z\x83G\xb3Pn\xf5|\x94uC\x92n\xa4\xd5Gj=\x93\x89\xc5\xe0F\x94\xc9&jP\x99Ԅj\x86\nSSs<l\xd6\xc5\xf2t\x8b}I\xb7v\x0f\x9aT\xa2\xe4v\x9d\x97.ZȚ\xbc)r\x01\x9e\xe2\xd5iǓ\x89*#5\xd1d4]\xbdܵh\xfc\x92$1\a1\x83+Q\xabD\xbc\xc7o\xbd\x0f\xe5b\xe1:\x91jLWA\f\x8en\x05\xfbQ9~܀\x1a\xf1c\xbd-\xaaEf(\xb1\x18|Ղ\x06\xe9D\x06\xea\xc5\x06\x17ڬy\xb9\xc9h\r\x99\xd3mC֬t\x84\xb6\xe9\xf6\x12\xa0\xa7\x8f\xfd+\xf6Zj\xf5ڜ.\xb3J\x92\x1b\xf5\xf66\xa3\xc6\xde^\xa6J\x04\xc6k\xb0\a\x85\xf9\xd6\xd7e\u007f*\xcac\x9bU\x92E\x1e\xdb\x11~/k\x10\x1d}+\xf5\xbf\xb2\x88\xc1\xd1Q\x89\u007f\xc4\xe43Q\x86\x1f\xaf٢\xf8\xb1\xceXb1X*d\x86\xf6\xa1t\t\x1b\x8c2\xf0/\xac\xcfNƠ\x8b\xa9\xa8\x12\x0f?=v\xa47\xac*\xe4\x04\x86(\xab\xae\xc1R-6\xb8\xd1\"Ig\xd0iI\xb25\xea\xb6S\xf0\xb8{\"5\xd1$k.\xfd\xa76˖\x9a\xd7%\xd1*\xe2\x8c\xff\xe8\v\xee\xf1Zu:.G\xaf\xe2\x17\x1c\xfe\xb9\x1b\xf1\x93̌\x9e\x0e\xfe\x83UM\u07b8}\xae\xd6\n$\xa9\xbf\xc4aI\xcd픸*·2Ͷh0\x13W\xb8\x85i\xbe\xe5vkNW\xd0\x1a\xdch\xbfD>\x18\xf4\a^\x92zC\xbbg F\x83;\x88\xba\xe4\xbbm\x1b5\x98\x1e^k#\xf3*\xd1\"\x89=\xc9\xd0\xee\x83#j\x83G}\xb2\xc1\xbeh\a\xaeq0\xc8\x1cو\xe6W\x97\xa7\xa2.j\xb0XO\u0600\xec\xa2t-\x13\x97\xa3˓ӱ\xc2e\x852\xa4j\xe8\x1e\x95\x14\x83\xaf\xf5W\xa3\x9cQ\xe9**'uղ\xe02\xf8\xcc\xed\xb65\xd5\xcbRH\x9d\xe17ؗ\x86\x96T\xceJ\xb5\x13\x83mi\x8bZ\xdd\xf6\xe4~\xf5\x1a\xae\xa6\xa7\xb6\x0ez\xec\x0eZ?xP\x87\x04\xe8\x10\x93\xc1\xa3\xa9D\xa8\xd14\xf2\xc5ۄr\xd9<+~\xe6@\xacT\xbd\x91\x8c\xe4\xdf\xdfh\x9ae[\xba\xa3g\x83=\x8f\xecNK\x9e\\[\xe6\xc6\x1b\xe43\xc0\xa0\xbb\xd7\xd6ꍙ\xb6E#\xb4\xfd\xfe\x1c\xdb\xdc\xfdtJ\\\xe3\xb0/'U\x04\x81\x1aLjKR\xa0\xd4\xe2\xc7\xf6J\x94\xd2T\x9en/d\xeb\xf1\xf7;n\x9a\xa9\x1c7R\xf2$b\xf3\"eO\xeeFV\n\xfe\x1e/\xa7\xef]\xb3\xb4U\f\xaeDȁ\u007f\"\xfdhIj\xfa\xf2,d\x0fR8\x0f\x91\xba\xc9K\n\x02\xbf\xc1\x85\xa8\r\xaf!\x97\xfc\x18\ni\xa1\xd0\x15R\x03\r\xcf\xc2\xef\xd6\xc1\xba\x1aD\x1b$@\x87\x98\fƿ\xd0J\xf2\xd3&ߖM\xfe\x9fj\x16꼆PV\x0e\xc5B\x861JO*ژ\x87\xecn\xba#]\x96\\\xd9ٔ\x86ǩ\x1b\xbd\xbd\x99y\xbd\xbd\xbd\xf47cEYm\x1di\xcb\xc9d\x99u[\xe76+\xf9]\xfaR3=\x1d\x8b\x90\xda\xe0\x1b\xbd\xe9\xe5W\xa5\xab5\xa9\xbd7\x86\xdaR\xd0,w\xed,\xdb \xdf\xef\xb8)\xa3\x1f\xb9\x1bɳ\x88\xb7d\xb0\xf7\x1b\xbc\x8c\xecD\x8d\xdeN\xbft\xa4\x9c\x94\xd0O\x89bpWG\x8d\xcd\xd6+\x9dFh\xd9(\xd9\xcd]\xa2n\xd8Iwv\xaf\x92ٲ\xc1ג\xe9'\xb8\x8f\x19L\xde\xe15\x94\xa7^h(ͺѳ\xd1\xca\x14\x1eMΕ\x00\x1db3\xf8\fJ\x1b\x95V\xd2\x1d\xe4&\xff^[\x0ej\x13\x91B\xa0\x10v\xac\xc1cW\x87TVN\xc60\x0f]\xb8\x8d\xb6W\xaa\b\a\xf9rN\x93ȇ\xa2\xcb\xff8?\x03\xcb2:Wm0.+\xc8L\x8c.6\v\x0f\xeb\xd7\xd2s\x83\xfa\x1d\x1fK\x10\xa9q\xb1Ȗ\xf9n\xba\x9b*\x1b\\C\xf7P\xfbQF\ra6:#\x95-\x91ieK\xaa\xea\xe0^\\>\x9dA\x16\xd2\xd7\xe8\xac\xe4k\xeauHW{=\xd59d\x80\x97\r\ue875\xb4$Y\xa8\xc1d}\xa3h\xbe\xa4ZC.):p\xb7\xecXpj\xe4\xe2l\xc6\x12\x9b\xc1R\x06\xea\x19\xb5\xa5\x90_T\x93\xfc[\x902Q\x17\x1e\x83Cw\xe8\x1dm\xf8wzC\xaa^)I+3F\t\xe9T@\xce`r\xc0\xa8\x86\xb8ZFw襬2<\x18QA\xb6\x05\x1b<\x82\x06q\x11C\x8f\xd6Y\xe9G\xa7\x19]S\xf7;>r\xd9с\xd1\xc6,\xfc\xe9\xcb\xea\xf3\x1b܁\xe6\x92\xf9\xbd\x81\x0ff\x97zON\n2X\x9a\x8b\x86\x87䃍\xcb\xe5#6~\x86\x97\x93z\xa0\x843\xb8]^4\x9d\x1aL\xb5'\x06sk\xb8*\xab\xbb\bу\xd5\x0e\xbb\x04\xe8\x10\xa3\xc15\xa8\xb2\x8b}K6\xc9\xdf{7,\xf8\x87\x1c8\x06ѣ\xecu9\xba\xa43\x16\x89\x1a<W\xfe\xcd,\xa3\xdd)\x06\x93~\xc9>\x9b4\x9f\x9e\x10\x90\ns\xf17k/]O\xb0\xc1Ғj\xa9\xcbN;g;\x80=\xb8\xbaT\xf5;>\x98@\x04ѳ\x04\xd9o0\x83\amvjN\x1fZ\xa9\xbb$3\xf8\x86\x87\xed\x01,A\xfd\xa3\xc9l\xa4\\\x8eT\x85\xf0h&\xaa\xec\xc5%\x10gp\x97\xfc\xfd\x95\xaa6\x98cH\xae\xbc\xcb\xf1\xe0\x8f\xb19$@\x87\x18\r\xbe\x88\xd2+\x99\xadM\xc8r\x91\xfcیf\x93/a:d\xe1\xafu\xab_\bj\xb0\x95\x19\xbc&\xa3\x8fB_\xa3\x06{\x88 TEjp\x19\xfb\xddg\x94\xe1_4ݟ+\v1\xb8#m\x94\x15\x11\x92\x95\x0e\x82\xadx\fV\xf5;>\xca\xe9\x80髦\xe5{!\xfeT\x10\x83\xaf\xa6\xa7\xb0Cs7,\xe9\xf4}5\xd6\x06\x17\x06\x01\x83-T\xaeQ\x87\xe5\x1a\xfeA\xd1\x02$#UU\x97\x9fa\xe7\xebz\xc9'^6Xd\xbe\xfa\x90\xae\xc1\xd7\x10\xfbV\x9a\x8fF\xe8\xabP\a\xeb\x12\xa3\xc1\xf8[\xd7\xc6\x0eN6!4\x1bk\xd8i#\xc5\xeb\x90\x15\x95\xe1\xdf\xf1i;=\x93\xc4\xe0\f\xeeb\xd2o\xa3ߝyyd\xb7\x86\xccP\f\ue925l\x1b\xea\xc4+H\xc7\x1d\xf9n\x0f1x4\xad\xc3\xceN\xf9Y\xd3ȩ\u058c<u\xbf\xe3<\x1e\xdcL\x8f\xa2\x88h6\xb6ntv\xf2U\"\xd8\xe8|\xe4?\x02\xbd\x92\x8e\x96\xbd\xc9\x1au\xa8\\E,\xa7\xffT\x93\xc1\xdaC\xf7\xe4\x1a\xc9\xde\xee\xe8Հ\xf2\xfdT\xbf\x1b\xb9\x9c\xc1x\xc4\xc6k\x1d]\xa2o0nA\xaa)/S\xb7o\x9cgkf\x04\xb1\x1a܊\x10\x1b\t\x9bЬ\xdbSf\xcfB\xecE\xaf\x15\xdd>\x17?\xc9\r\f?C\xf6\xfa\x1bm\x96\xfe\x1b+\xf3F\xe8/\xb8\xbd\xa3\x8c\xedq\xd5X\xeb;\x16\xd9DrN\xae\xec\xb4\xd4Wf\xe9\xc5#ך\xe4\xea\xce\xead\xb2\xf34hK\xaf\xddfON\xf1\x90ʺ\xaf\x195ʧ\xf0\xa4\xea\fVDHV\x94\xd3ޚI\x8fYq\xfd\x8e\xf3\x9c\xdcEvHe#\x9a\xb5ac\x16)q\xb1`5\xc8QS\xbd\x11\xd3A\xaez\xc8ٸ\xd2z\xbb\xffs\xc4!\x1b<\xec@y\x1bsP&\xf1p\x19ʪ^\x82f]%\x9f\xbc\x1c\u007f\xbb\xd1\xd9h\x91\xbbڑ\x99\x96\xc5\x1d\x0fNEK*3\xec\xc4O\x1d\x83\x87\xd3\xd0\"\xdc\x17;2\xd7\bǃ\xf5\x89\xd5\xe0kVV\xa8\x92\xb3\xca\xfd\x8bl\xf6E\xf2\xc8\xe7+O\xb7\xd8\xe6\xd6\x05\x04\x1eMC\xa8-\x15\xd9\xdaY\x95ڕg\xb7\xcfg\a\xdaF+\xed\xb6\xbc3\xf4(*\xb2\f\xda\xf0#Q\xafy\xaemn3\xeb\xa9\xd0>\xabړB\xe6\xdeHů\xda\xe4\xd1\xcc\xe7\x1f߭\x1b\xcbR\x1dk\xd81/\xa5\xdfq\x1a,e\xd1\xe1ut\xff\xdcT\xdb\\v\x85\x83X\xe6ߣ\xc2=^ݘnq,W\xef\x9a1\xfc{rbY\x9a%\xbd\x9an\xe4h}\xa6\xd5QN\x8c\xe4\f&\a\xb8\xad\x99\xb57\x96\xe1\x82 pNn\xa80նd\x88\f\xcb:\x06Kb\xb9ÒV\xc6.:Z\xa2\xaeK\x00\x9e(\fV\xe1c\xa7\xe5\xa8\xc1\xe1[ƛ\x1bV\xf9\xc3\x12\xe6T\xde8\xf0\xb0}\xa5x\xd3\x1dt|W\r\xdb\xdf\x15Qt\aQĔm\x91\x9a\xcc`b5\xb8\xc6? \x1bnp\xbb\\D\xc4\xd9\xe0\t\x1d\x8bӧ,\xec\x15\xa9v\xba\x83\xb81\xca\x03ٵ\xb6\t\xec\xaaN{b2xh\xb8\xfdv\xab|\xa5\x9f\xb1\x06\xd7\xf6H\x8b\xfcN\xc4\xd7`ɛ\xa2\u007f=︹X\x18\xf6Tw5\xca\xd8X\x9d\x1b|\x1eN\x87k\xf6h\xae͛\xb1\xc4d094\xef\xf7\xc8P\x83o\xa0\x9cJ\a\xab\x87\xd9\x0e`<Y\xbe<R\x8b\xf8\xe3\xc9I\xb5e\xd5FW\xddn\x9b\xc8Y\xf3\xe9OL\x06\xd7\xd9\xd2\x02_\x8e\x86\x1a,դ\xe6\xc9#%\xdd\x01\xbc\x18\xbe50\x83\x88\xc9`\x00\x98r\x80\xc1\x80\xb9\x01\x83\x01s\x03\x06\x03\xe6\x06\f\x06\xcc\xcd\xd46x\u007f\xf0\xfd\x0e\x9a\xb8\xc3\\\x03\x19\x1d\x17\xe1x\x95i\x01\x831n[\xe8œ\x80I\x98\xda\x06\xf7\xbb\xa3\t;\x99\xa8\xc1\xa3\b\x81\xc1\xa6ej\x1b\x1c\x1d`\xf0L\x06\f\x06\x83\xcdM\xdc\f\x8es\f\x1a\x83\xd6\xc1M\xc8=\\\x96v{\x16\xee\xbe)ӚVNlS\xa5\xb6\xc9\x06s\xd1mZ\x8b\x045\xa8\xbdZ\uec24o\xbc\xca\xceS\xd3\xf8\x16_Y\xba%5\xa7~\xc2{u\x1f\n\x98\xbda\x1a\x1c\x15\x84\x13a^\x06ba\xc2\x06OR\f\x1aC6\xb8̎Ҭ\b\xb5\xafA\xb7\xa7!z\xe3\x8d*\xb5\x8d\x19\xccG\xb7i-\x12Ԡ܁R\xed\beސZ\x97!T\xb8\xec\xa24\x98\x8a\xecs3P\x94W\x8c\x85\xe1O\xef}g\xfd\xc0\x17a\x1a\\\x1f\xa8:\x18\xe6e \x16\"\x1a|5/\xfcũQ\x87H\xc5\x16\x83Ɛ\rF\x99\x83\xd2\xe82d\xbd\xdd3*\xb5#\x12\x81\xa3Jm\xa3\x06\xab\xa2۴\x16\tn\x90\xd1+I\x1d\x16rc\xa9\\E,A\x1b\xf1\xf0ۗ\x1a\x87[z\xb6l\x89\xd0`;\x18\x1c/\"\x1a<\x88\xb4n\xb1Q\x88\xda\xe0\xf1Ġ\xf9\r&\x9b0(_ٙC\xa4S\xa5\xb6Q\x83U\xd1mZ\x8b\x047\xa0\t\x17e\xe46\t\xd9\xe0t\xd6e\xdd\xf2Ni\xa2\x80\xc1\xc6\x11\xde\xe0\xa6\xcc\xce!\xe4\xeb\xccܟ\xa0\x184\xd9`z+\xdb\rY\xdae\xa8NR\xa7\xb6Q\x83U\xd1mZ\x8b\x045`\xe9$u\xe4\x1aQ\xd9\xe0<\x94\xd3\x1b\xfc\xe1\x1a\xd8Z\xea\\\xb1\xbdtLz\r\x97\xb6\xff$\x1dď/5\b\xce\xe7\x1f[\x9b\xbf\xf5s\xda\xe2\xb3\xfbW8\x8b\xb6\u007f\xae^\x8c3x\xechE\xfew\x8e\x8e\x05\xb5\xc5\x067\xe0\xbe\\\xd7q\x83\x13U\x8b\xd7>\x86\x1b|\xe8\x14\x84\xa7?\xd9uw\xfe\xd6?I@Ԅ7X\\\x83\xb2\xf0\u007f%b\x82b\xd0d\x83ie\x8a=\xa3\xb7\x87\x94\x90:\x9aOm\xa3\x06\xab\xa3\xdb4\x16\tn\xb0HY\x81lp\xaf\x05\xa1\xd4e\xad|\xd1\xf4\xc1\x82\x87O\x9d}~\x85\xf0'il\xa0\xf4\xfb\u007f\x94\xfex\xb0`\xe0\xe6\xefO8\x85\xa2\x83\x87\v\xee'-\xce-\xae8|\xf6\xa0𬤂3\xf8a\xd7ӯ?\xed\xda\x1b\xd4\x16\x1b\xfc\xf9.\xe1\xd9\x0f\xf1\xe4^\xa1\xe1\xf5\xa3E\xebǤ\xb1\x97N\x94\xae*(}lׂp54\x10D\xa4*\xa2˂,\xf4^\xe0\x84Ġ\xc9\x06\xd3k\xe9\x83\fVRۨ\xc1\xea\xe86\x8dE4\x1b\xa8\f\x96\x06Kȝ\xd3)eʗ\xc0\xd1\"2\x1c\x1e]J\x86Ѓ\x15\xf8\xe1a\xaa\xa2k)\x1eGw\x15ᩱҭ\xf8\xb5\xb1\x97\xaeK*\x14\x83\xcf\ng\xfd\x8f|[l\xf0\xb3\xae\xd7H\x83\xd7\xe8a\x89\x0f\xd9\xc1\x89\xf5\u0096\x9b\xd2\xd8M\t\x88\x9e\xf0\x06_\xdbhIG\x0ek\xf5\xd5\x04Š\x851XIm\xf3\x8f\xc1\\t\x9b\xc6\"\x9a\r\xd4\x06㩞mY\x88;\xba\xfcE\xf1\xdd\r\xcf\xffn\x8c\xd6\x00\x9f/\xf8\x9d4V@|\x94\\\x0f㇃.\x89\xa8\xf9;I\x03\xc5\xe0\xbd\xeb\xe8?\xeb\xf6\xaa\xdbn?\xf8\xb4p\x8aN=x\xf7؟0\xa5\xf4\xa3\xb1\xde\x05\xc3o\xac\x847\u061d\xb6\u007f\b\r5\xa7\xb9\x13\x14\x83\x16\xc6`.\xb5\x8d\xd6\xc1\xaa\xe86\xadE\xb4\x1a\xa8\f\xf6\xb1 \x8cF\x94\xa2\x941\u05cf>\xb8VXq\x98*\xbc\xf51\xe9,\x1d\x8d%\x17\xd9\x0f\xa3\x06?+\x8cI\x1a(\x06\u07fb\x9d\xfe\xb3\xbdJ\xddv{Q\xc1\xda\xfb\xe9\xd3\xf5\x02\x83\xd6$\xeb\xab$ F\"T\x11\xa3\xf4X\x04\xf9\x8d&$\x06-\x8c\xc1\\j\x1b5X\x15ݦ\xb5\x88V\x83\x80\xc1WIz\x03k<\x84\x92\x03\x06\u007f\xf88\xb6\xec\xfa\x89\xfc\xa3\xe4ɩ\x15c\xac\x88\xe0\f>+|(i\xc0\f\xbe\xf9\xf4ui\xef\xdd\xc4ӱ\xbb\x1fV\xb7\xdd^\xf4\xf1g\x05\xb4x\xdeu\xf7\x87\x14Z\x87\xac\xbf_\xa33 ,\x91\xea`I\xb4\xb3\xdb\xeb\r\x8eAc\x841\x98Km\xa3\x06\xab\xa2۴\x16\xd1j _\xfcfA\xed7F\xa5<\x94\x87[_[Ɲ\xd28H\xabXi\xcb\xf7\xc9\xe3؊SK\xe9S\xce\xe0\x9b\xc5[\x88\xa1\r\x8f\xd1\xf9\x9f\x1d\xfe\x8c-\xc7\f\xfe@\x18\x90^\xa7\x05\xee\t\xe1uu[r4\xed\xac\x93\x18}Vx\x89\xb4}\xf20y\\\xff\xa0\x04\xc4HD\x83e\x8c\x8eAc\x841\x98Kmc\xe7\xe4\xf8\xe86\xadE\xb4\x1a\xc8\x06\x93\xf2\xa5K\xf2ّ%3ˆҔ\xfc\x88\x83\xc2⃯\x9d\xda+\x9c\xa3\xcf\x1e\xbf{)ٱ\xfb\xd7\x01\xe7\xde\xf7\xc6>\xd8\xeb\x1c\xf8WI:\xe7Zw\xf4l\x83\xf0<mp\xbf@k\x86?\xfd\xbf\xef\xac\x1f\xc0\x1c\xc5\x06K\xbb\x84\xc7_{\\\xd8E\xe6\a\xda^\x1f\xa8\xc2=\xdc\xdc^|\ue3f8\xd7\x05\x0f\x9e«8\x81\x17\x1bXu\xef\xc0\xc0g\x12\x10\vQ\x1alx\f\x1a#\x8c\xc1\\j\x9b|]\x04\x17ݦi\xb0F\x03\xd9\xe0\xa1\xdc\xdbS\xdb\xc8u\x13\x19\x96\xdb3\xab\xb9\xc3i'\xee=X\xea,\xde\xc2\x04\x96\xfe\xc0.v \ar\x9d\xbf[\x8c\x1f\x1b\xc8\xcc\aK\v\xaa\xd8N\x99\xf4|\x11-7>\x96K[!\xff\x13r<x}\xfez\xf9x\xb0\xbf\xedQ\xf2\xe2\a'\xf0\xc3\xd3x\xee\xd9-w.\xbd\xf7\xac|9\x85\xc0>\x04@\xd4Dip\xfc\x99X\f\x9a\xb1i\x1527]\xe7\"5\x01\f'a\x06O,\x06-!\x06\xbft'\x9c,\x9bz$\xc6\xe0\tǠ\x19o\xf0\xc1sc[\xe0b\x86)HB\f\x9ex\f\x9a\xe1\x06\x8f\t\x15\r\xc5Agހ\xa9@B\f\x9ex\f\x9a\xe1\x06K\a\x17o\xf9$R\x1b \x01$\xc6`\x00\x88\x17`0`n\xc0`\xc0܀\xc1\x80\xb9\x01\x83\x01s\x03\x06\x03\xe6\x06\f\x06\xcc\r\x18\f\x98\x1b0\x1807\x86\x1b|\xaaꏑ\x9aL\"\xd7\xef=\x15\xa9IT\xd0w\x11\xaf\u0380\x8901\x83\x1b\x04v\x87\x81\x06\x9f9\x85\xb5\x1a\xb3\x0f\v\a5\xef,\xd3%\xe2*N9\xe5\xabq\x9dQ\xf84vX8\x1c23\xf6\x9c3\xf6.4;\x03\ff|\x06\x9f\x93\xef\xf8\xfa|\xc0\xa9w\xbd\xd6\xd8{{]\xa1s\x8fF\x1dy\x17\xf5*\x0e\v\xe4n\x88g\a\x06\x16D\xa5\xd3\xebΣ\xc1\xb3b\xce9\v\xbc\v\x8d\xce\x00\x83\x19\x9f\xc1U\x81\xfb\xb9\\\xfaW\x1c\x1e\f5\xf83\xe7\xe3\xfe\xc9\xeb[\xc2_\xe9\x15\xf5*\x9eu\x92Q\xf4=I\xca\x0f\x8a\x1d\xd1\xe1iWP\xc0\x8e\x14kJ\x14\xf7.\xb4:\x03\fe|\x06\xaf\x8fV\xaf \xf6\x16\aJ\x88\x8f\x85\x8fC^\xe6\x89z\x15c\x9f\xc9\x06\u007f\x16]yr\xb38\xb4`\x88\xcd`\xee]hu\x06\x18J8\x83\xff\xb4\xc2\xf9O\xa5\xc5\xe7\x1a\x96n!)2\x81|\xafSr\xddI2l$\xd7c\x81\b1.!\xec\xf3]\xc5K\xef\x0f\xad\"\xc6\n\xe4\xc1\xeb\xe8\xaa\xd7>\x11>y}\xd5\xd18\xad\x82\x1a,\x05\x85\x9b\x1d\xdd[\xbct;\xbd\"2\xd0/\xe5\xe9\xfc\x10\xd5c\xc99S\xde\x05A\xa33\xc0P\u008e\xc1\xe7\n\x84Ƕ\bw\x1e^A\xbe\x9f\x03\xf9^7\a\xe8=\xb5\x03T\x0e\x97\xb0\xf6ĩ\x154\xe6@I\b\xfb\xa4`\xed\xf3\xa7\xb6\n!\x06\x93\xdb\xcf)\x9f\xef\x12\xd6\xe1\xff\xee\xff\"N\xab\x90\r\x0e\n7+=x\xb04\xffc\xbe_ʀ\xf0\xff\xa4 b\xc99S\xde\x05A\xa33\xc0P\xc2W\x11Ż\xa4ׅS4-L\x9d\xef\xa5|\xc5\x17\xfd\x1b6\x84D\x88q\ta\xf7\xae\"{\xea\xebC\f~]\xf8\x83\u007f\xf2\xacSp\xd2\xf0\x85\xb8\xacB6X\x1dnv7\x1e֯\x97V\x05\xf5\x8b?>B\xc8A\x8b\x18r\xceT\xefB\xb33\xc0P\"\x18|BzO\xb8)=\xfe`p\xbe\x97\xa2\x17yN+^%!\xec:\x8bOx:\xc4\xe0S\x82\x1c\x86p\xfd1g\xb1P\xecz\xec\xdfⴊ\x80\xc1|\xb8\x19\xfd\xae?*\\W\xf7K\xa4\v9<\x17C\xce\x19\xf7.\b\x1a\x9d\x01\x86\x12\xc1\xe0\xb3҇xW\x9f\xe8\xa5\xce\xf7R\xeffQ\xbd\x94\x84\xb0\x0f\xd9\xd7l\xe8\x9e\xdc{~\xd1\x0e\xaf8\xfa{\xe1\xf7GW\x1c\x8e\xd3*\x02\x06\a\x87\x9b\xe1o\xf9\x0f\xd5\xfdJ\xfeeyb\xc89\xe3\xde\x05A\xa33\xc0P\"\x1b\xecbz\xa9\xf3\xbd\x88^ϓC\xa8\x8a^JBؿ\t\xf4(\xe9á{r\x81\xc3\nc\xf4X\x04\t\x85\x8c\xcb*\x14\x83\xb9p3\x9a\x04\xf5<\x1e\xdfU\xfd⮜7\xa5 b\xc89\xe3߅\xa4\xd9\x19`(Q\x1b\xac\xca\xf7\"\xbf\xf1?\xd2\x19\x8a^\\BXU)\x96\xe5\x0f\xae\x10\x83\xa5\xfbW\x05\x86\xb5/\x96~\x11\xbfU(\x06s\xe1f+\xb0[7\xef\xde\x12ԯ4\xb664\x15'\x86\x9c3I\xf5.\xb4:\x03\f%\xac\xc1\xbf_\xfa\xec\xd8\t\xe7\xc7c\xbb\xb6|\xce\xe5{IħgOmY\xfc\x85:BLI\b\xfb8\xbf\xf4\xe0\xd3K\x05\xe7\x89\xdf\au\xf8I\xc8iظ\xac⃣\xf2a\x02)\x10nF\x0eaT\xbc\xf4\xfc\xaa\xa5d\xaf\x8b\xef\x17\x17\a\xca\xd0ʈ-\xe7L\xf5.B;\x03\f&\x9c\xc1c+\x04\xe1D\x81\xb0\xf8%VB\xfa\xf3\xbd\xc8+\rK\xf3\xef\xfd0(B\x8cK\b\xfbd\xfbһ\x1f;\xe1\xa4\xc1b*\x9ev\xa9\xcbƸ\xacb\x8c\xbc\x9a/\u007f\x9b\xff\xc1\u007f\x85\x83뱽\x05Ż\xfe\x95Ns\xfd\x0e\xe4?&\x05\x11c\xce\x19\xf7.4:\x03\ff|\xe7\xe4\xc6\xcdX\x83s\x92\xf7\xdd\x03\xe1fڧ\xf2^r\xee\x9dxt\x94\xff]ĥ3`b\x18l\xb04\xf6l\xe9\xf5Hm&D \xdcL\xd3\xe0\xebŇ\x95\x03\fㇽ\x8b8u\x06L\b\xa3\r\x9e\\\xf8p\xb30\x97S\x00ӈie0\x17n\xf69\xdd\x01\x8c\xd0\x1e\x98\x06L+\x83\xb9p3\xba\x03\bq\xe83\x80\xe9e00\xf3\x00\x83\x01s\x03\x06\x03\xe6\x06\f\x06\xcc\r\x18\f\x98\x1b0\x1807`0`n\xc0`\xc0܀\xc1\x80\xb91\xdc\xe0鑛\x16\v\x113\xd6\xe2\xf4#I\xc4{\x9b\x02L\xcc\xe0\x88\xa1f!L\xc5ܴs\v\x84{\xc7HFł\xb3\x1a\x8b0>\u07ba\xb8x\u05f9b\x95j{\xe5K\x8aՓ\xc1D\xccX\x8b\xfeGr\xb6(\xdc[\x9c\xa11n\xe338\xeaP\xb3`\xa6dn\xda\xd8Y!\u007f@\xbayJ8\xabk\xd2\xd9\xc5UϟX/\b*I?'+~/x2\x88\x88\x19k\xd1\xffH\xa4\xd7\x16k\x18\xec\xffAI34\xc6m|\x06G\x1dj\x16\xc4\x14\xcdM\xbb)\xecڋ7Nнi\xf3z\x01\xb9Q\xf9\xe6*!x\x98Un\xd0\xe3'9\"f\xacq\r\"\xa3\xf5\tS~P33\xc6m|\x06G\x1dj\x16\xc4\x14\xcdM\xbb)\x9c]<\x16\xce\xe0\xc7\xf3\xe9\xddJ\xcf\xc6npČ5\xae\xc1\xf8X\xcf\x19<\x13c\xdc 7M\"\x06\u007f\xb6\xfe\x145\xb8\x81$\x05\xd3\xfaZ\xb5e\xab\x1e\xa6\xed\xae?;&\xdd|\xb0\xd8Y\xba\xdd\xffͭe\xf0\xc0\xd6R\xe7\x8a\xed\xa5t%\x113\xd6\xfc\r\xf0\xf6>\x1fx\x9b\x01\x94\xcd\xc1+\xcf\x17\xe4\x18c\xae\xad\xea\a%\xcd\xc8\x187\xc8M\x93\xa8\xc1G\xb7S\x83i\xd5\xcd\xeakn\xcb\xc6\x04\xa5@yM\xd8{\xee\xa5\xed\xfe[\x945\f\xfe`\xc1ç\xce>\xbfB\xa07;E\xccX\xf37 \xdb[t\xf0p\xc1\xfd\xaaW\xb9\xcd\xc1+\x18\x18`_G\\[\xd5\x0fJ\x9a\x911n\x90\x9b&Q\x83\xaf\xbb\xae\xb3*BI\xa7P\xb6\xec3n\x89\xb1\x97n\x92\x15\a\xf2\u007fB\f>ZD\xdc=ʂ\x83\"f\xac)\r\\K\U00058eab(\xe8ues\b\xf9\aC\xdb\xf2U\xc4L\x8cq\x83\xdc4\x89\x1a,m\u007f6\xc4\xe0\xc0\x96\x8d9\xb9\x9d\xc4\xebG\xb7\xde] \xacgO4\f\xfe\xa2\xf8\xee\x86\xe7\u007f7\xc6\x06\xfc\x88\x19kJ\x03\xd7Òƾ\x83\x8e\xc1\\\xdb \x83CW1͉\x9c\xd9\xe3\x9ch\xa8\x99\xc2T\xcdM#\x06\x9f\xfaN\x88\xc1ʖ\xc9u\xf0\x18\xfeh|XT\xfa\xf8\xa9\x81-\xeb\xfd}\x85\xd6\xc1\u05cf>\xb8VX\xc1nc\x8e\x98\xb1\xa64P\xbb\xeaG\xc7`n\xae\xca\xe0\x19\x18\xe3\x16\xd9`\xd7DC\xcd\x14\xa6jn\x1a1xl\xf1Y\xc5\xe0\xa7\xfd\x06\xcb[\xf6x>]\xf6%\xe1\x8f\xd2\xda*\xb2\r\xf7\xafgKj\x18\xfc\xe1\xe3\xb8\xc1\xf5\x13\xf9t\x03#f\xac)\r\xc2\x18\x1c\xf86\xd35\xf8y\xf9π\xcc\xc0\x18\xb7\xa8\r\x1e\u007f\xa8\x19\xc7\x14\xcdM#\x06K\x0f\xef\xa2\x06\xe7\xe3\xe2c\xac*\xc8`v<xl\xcbݒTJF\xf2\xb1\xef\xacgKj\x18|\x90\x16\xebҖ\xef\xd3g\x113\xd6\x02\r\xb4\rV6\x87>\xd30X\xf9A\xe9\xadbz\x03\xb9i\xf4\x9cܩ\x9bҹ|j\xf0\xbdE\x87\x0fV\x91~U[v6\xff\xde\x13\xa7\xb6:\a\x88\xa0\x0f\x1e=\xb8\x1eW\t\xefI_\xc8'\x03\xf1G\x91\x9b<(,>\xf8\x1a^\x1b\x8b\x0e\x8a\x98\xb1&7P\xbdM\x8e\xc0\xe6Hc\xef\r\f\xb8\xf6\x0e\f\xdc\fj\xeb\xffA\x11fb\x8c\x1b\xe4\xa6\xd1\xeb\"\xf0\x186VE\xcf-|\xb2%\xbf`\xeb?\t\xc2^\xf5\x96}\xbc5\u007f\xc5\xfd$\x11{\xec\xd9U\xae\xa2\a\x9f_\xe5\xdc\"=,\xd7\xd7x\x90\xe6&O\xdc{\xb0\xd4Y\xbcEξ\x8a\x9c\xb1\xc6\x1a\xa8\xde&\x87\u007fs\x1a\xa4\x0f\xe4U\x1c\rj\xeb\xffAI34\xc6m|\xe7\xe4\xc6\xcd\xf4\xc8M\x8b\x85\x88\x19k\xf1\xfb\x91\x18\xfeަ\x04\x06\x1b<Mr\xd3b!b\xc6Z\xbc~$\txoS\x01\xa3\r\x9e\\ 7m\xe61\xad\f\x86ܴ\x19ȴ2\x18r\xd3f \xd3\xcb``\xe6\x01\x06\x03\xe6\x06\f\x06\xcc\r\x18\f\x98\x1b0\x1807`0`n\xc0`\xc0܀\xc1\x80\xb9\x01\x83\x01sc\xb8\xc1q\n\t\x1b'\x93\x9b-\x161!\r\x88?\x1338b\xa8Y\bч\x84\xc9D\\\xc5\xc4s\xd3\xee\x15H\x10\xc3\t\xfcx/?;L\x16\x1a\xe5\xa8\x10\x94\x17\x151!\r\x98\x04\xc6gpԡf\xc1D\x1f\x12\x16\xf5*&\x9e\x9b\xf6I\x83p\xee\xa6ts@hЋE\xd3\xe4\xfa@\x95j\xcb\"&\xa4\x01\x93\xc1\xf8\f\x8e:\xd4,\x88)\x9a\x9bvT \xdf\v\u007f\x12B\xc4\xd3N\x92\n\xb0\x9d߲\x88\ti\xc0\xa40>\x83\xa3\x0e5\vb\x8a\xe6\xa6\xc5\xc5\xe0\x88\ti\xc0\xa4\x00\xb9i\x12opP|Y\xc0`n\xc5\xd2g\xf7\xafp\x16m'-\xb0\xc1\xe4*N\x17\xf96\x89\x98\x90\x06L\x0e\x90\x9b&\xf1\x06\aŗ\x05\fVV,\x9d[\\q\xf8\xecA\x9a\xa4\x86\r\xc6\xef\x84\xdd&\x1d1!\r\x98\x1c 7MRW\x11\xaa\xf82\u007f\xbf܊\xc7J\xb7\x925\xbfD\xc6]l\xf0\xb3\xae\xd7Xӈ\ti\xc0\xe4\x00\xb9iR\x90\xc1\x0fK\xa1iVʊ\xb1ƿ\v,\xb7\xfd\xe0\xd3\x01U#&\xa4\x01\x93C\xe4\xcc\x1e\xe7DC\xcd\x14\xa6jn\x1aќ$\xf7\x1c\x95\xf8\xb5IJ\xbfʊ\xa5g\x05\xa5\xc4\xdd^T\xb0\xf6~\xf9iĄ4`r\x88l\xb0k\xa2\xa1f\nS57m\x80FݰJV\xd3`e\xc5x\f\xfe0\xb0\xdc\xf6\xa2\x8f?+\x90\x8f\xe1ELH\x03&\x87\xa8\r\x1e\u007f\xa8\x19\xc7T\xcdM[J\xa4\u07fb\x94h\xa7i0\xb7\xe2\x9b\xc5[\xc8{h \x9f\x0fr4\xed\xacS6:bB\x1a0)@n\x1a\xe1\x84\xd0p\xf6\xfb\xe4u~m\\\x16\x1a\xb7b\xe9\x9ck\xddѳ\r\xb8\x0e\xbf>P\x85\xdb\xde\xdc^|\x8e^\xe9\x111!\r\x98\x14 7\x8d5\xa8Z\\E^\xe7\xd7\xc6e\xa1\xf1+\x96\xfe\xf0`iA\xd5)z]\x84 |p\x02?<M\xe7GLH\x03&\x83\xf1\x9d\x93\x1b7\xf1\v\t\xd3#q\xb9i\x11\x13Ҁ\xc9\xc0`\x83\xe3\x16\x12\xa6K\x02s\xd3\"&\xa4\x01\x93\x80\xd1\x06O.\x90\x9b6\xf3\x98V\x06Cn\xda\fdZ\x19\f\xb9i3\x90\xe9e00\xf3\x00\x83\x01s\x03\x06\x03\xe6\x06\f\x06\xcc\r\x18\f\x98\x1b0\x1807`0`n\xc0`\xc0܀\xc1\x80\xb9\x01\x83\x01s\x03\x06\x03\xe6\x06\f\x06\xcc\xcd\xff\aڧC\xea]\xae?U\x00\x00\x00\x00IEND\xaeB`\x82",
+
+	"callgraph.html": `<div class="toggle" style="display: none">
+	<div class="collapsed">
+		<p class="exampleHeading toggleButton">▹ <span class="text">Internal call graph</span></p>
+	</div>
+	<div class="expanded">
+		<p class="exampleHeading toggleButton">▾ <span class="text">Internal call graph</span></p>
+		<p>
+		  This viewer shows the portion of the internal call
+		  graph of this package that is reachable from this function.
+		  See the <a href='#pkg-callgraph'>package's call
+		  graph</a> for more information.
+		</p>
+		<ul style="margin-left: 0.5in" id="callgraph-{{.Index}}" class="treeview"></ul>
+	</div>
+</div>
+`,
+
+	"codewalk.html": `<!--
+	Copyright 2010 The Go Authors. All rights reserved.
+	Use of this source code is governed by a BSD-style
+	license that can be found in the LICENSE file.
+-->
+
+<style type='text/css'>@import "/doc/codewalk/codewalk.css";</style>
+<script type="text/javascript" src="/doc/codewalk/codewalk.js"></script>
+
+<div id="codewalk-main">
+  <div class="left" id="code-column">
+    <div id='sizer'></div>
+    <div id="code-area">
+      <div id="code-header" align="center">
+        <a id="code-popout-link" href="" target="_blank">
+          <img title="View code in new window" alt="Pop Out Code" src="/doc/codewalk/popout.png" style="display: block; float: right;"/>
+        </a>
+        <select id="code-selector">
+          {{range .File}}
+          <option value="/doc/codewalk/?fileprint=/{{urlquery .}}">{{html .}}</option>
+          {{end}}
+        </select>
+      </div>
+      <div id="code">
+        <iframe class="code-display" name="code-display" id="code-display"></iframe>
+      </div>
+    </div>
+    <div id="code-options" class="setting">
+      <span>code on <a id="set-code-left" class="selected" href="#">left</a> &bull; <a id="set-code-right" href="#">right</a></span>
+      <span>code width <span id="code-column-width">70%</span></span>
+      <span>filepaths <a id="show-filepaths" class="selected" href="#">shown</a> &bull; <a id="hide-filepaths" href="#">hidden</a></span>
+    </div>
+  </div>
+  <div class="right" id="comment-column">
+    <div id="comment-area">
+      {{range .Step}}
+      <div class="comment first last">
+        <a class="comment-link" href="/doc/codewalk/?fileprint=/{{urlquery .File}}&amp;lo={{urlquery .Lo}}&amp;hi={{urlquery .Hi}}#mark" target="code-display"></a>
+        <div class="comment-title">{{html .Title}}</div>
+        <div class="comment-text">
+	{{with .Err}}
+	ERROR LOADING FILE: {{html .}}<br/><br/>
+	{{end}}
+        {{.XML}}
+        </div>
+        <div class="comment-text file-name"><span class="path-file">{{html .}}</span></div>
+      </div>
+      {{end}}
+    </div>
+    <div id="comment-options" class="setting">
+      <a id="prev-comment" href="#"><span class="hotkey">p</span>revious step</a>
+      &bull;
+      <a id="next-comment" href="#"><span class="hotkey">n</span>ext step</a>
+    </div>
+  </div>
+</div>
+`,
+
+	"codewalkdir.html": `<!--
+	Copyright 2010 The Go Authors. All rights reserved.
+	Use of this source code is governed by a BSD-style
+	license that can be found in the LICENSE file.
+-->
+
+<table class="layout">
+{{range .}}
+<tr>
+	{{$name_html := html .Name}}
+	<td><a href="{{$name_html}}">{{$name_html}}</a></td>
+	<td width="25">&nbsp;</td>
+	<td>{{html .Title}}</td>
+</tr>
+{{end}}
+</table>
+`,
+
+	"dirlist.html": `<!--
+	Copyright 2009 The Go Authors. All rights reserved.
+	Use of this source code is governed by a BSD-style
+	license that can be found in the LICENSE file.
+-->
+
+<p>
+<table class="layout">
+<tr>
+	<th align="left">File</th>
+	<td width="25">&nbsp;</td>
+	<th align="right">Bytes</th>
+	<td width="25">&nbsp;</td>
+	<th align="left">Modified</th>
+</tr>
+<tr>
+	<td><a href="..">..</a></td>
+</tr>
+{{range .}}
+<tr>
+	{{$name_html := fileInfoName . | html}}
+	<td align="left"><a href="{{$name_html}}">{{$name_html}}</a></td>
+	<td></td>
+	<td align="right">{{html .Size}}</td>
+	<td></td>
+	<td align="left">{{fileInfoTime . | html}}</td>
+</tr>
+{{end}}
+
+</table>
+</p>
+`,
+
+	"error.html": `<!--
+	Copyright 2009 The Go Authors. All rights reserved.
+	Use of this source code is governed by a BSD-style
+	license that can be found in the LICENSE file.
+-->
+
+<p>
+<span class="alert" style="font-size:120%">{{html .}}</span>
+</p>
+`,
+
+	"example.html": `<div id="example_{{.Name}}" class="toggle">
+	<div class="collapsed">
+		<p class="exampleHeading toggleButton">▹ <span class="text">Example{{example_suffix .Name}}</span></p>
+	</div>
+	<div class="expanded">
+		<p class="exampleHeading toggleButton">▾ <span class="text">Example{{example_suffix .Name}}</span></p>
+		{{with .Doc}}<p>{{html .}}</p>{{end}}
+		{{$output := .Output}}
+		{{with .Play}}
+			<div class="play">
+				<div class="input"><textarea class="code">{{html .}}</textarea></div>
+				<div class="output"><pre>{{html $output}}</pre></div>
+				<div class="buttons">
+					<a class="run" title="Run this code [shift-enter]">Run</a>
+					<a class="fmt" title="Format this code">Format</a>
+					<a class="share" title="Share this code">Share</a>
+				</div>
+			</div>
+		{{else}}
+			<p>Code:</p>
+			<pre class="code">{{.Code}}</pre>
+			{{with .Output}}
+			<p>Output:</p>
+			<pre class="output">{{html .}}</pre>
+			{{end}}
+		{{end}}
+	</div>
+</div>
+`,
+
+	"godoc.html": `<!DOCTYPE html>
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<meta name="viewport" content="width=device-width, initial-scale=1">
+<meta name="theme-color" content="#375EAB">
+{{with .Tabtitle}}
+  <title>{{html .}} - The Go Programming Language</title>
+{{else}}
+  <title>The Go Programming Language</title>
+{{end}}
+<link type="text/css" rel="stylesheet" href="/lib/godoc/style.css">
+{{if .SearchBox}}
+<link rel="search" type="application/opensearchdescription+xml" title="godoc" href="/opensearch.xml" />
+{{end}}
+<link rel="stylesheet" href="/lib/godoc/jquery.treeview.css">
+<script type="text/javascript">window.initFuncs = [];</script>
+</head>
+<body>
+
+<div id='lowframe' style="position: fixed; bottom: 0; left: 0; height: 0; width: 100%; border-top: thin solid grey; background-color: white; overflow: auto;">
+...
+</div><!-- #lowframe -->
+
+<div id="topbar"{{if .Title}} class="wide"{{end}}><div class="container">
+<div class="top-heading" id="heading-wide"><a href="/">The Go Programming Language</a></div>
+<div class="top-heading" id="heading-narrow"><a href="/">Go</a></div>
+<a href="#" id="menu-button"><span id="menu-button-arrow">&#9661;</span></a>
+<form method="GET" action="/search">
+<div id="menu">
+<a href="/doc/">Documents</a>
+<a href="/pkg/">Packages</a>
+<a href="/project/">The Project</a>
+<a href="/help/">Help</a>
+<a href="/blog/">Blog</a>
+{{if .Playground}}
+<a id="playgroundButton" href="http://play.golang.org/" title="Show Go Playground">Play</a>
+{{end}}
+<input type="text" id="search" name="q" class="inactive" value="Search" placeholder="Search">
+</div>
+</form>
+
+</div></div>
+
+{{if .Playground}}
+<div id="playground" class="play">
+	<div class="input"><textarea class="code">package main
+
+import "fmt"
+
+func main() {
+	fmt.Println("Hello, 世界")
+}</textarea></div>
+	<div class="output"></div>
+	<div class="buttons">
+		<a class="run" title="Run this code [shift-enter]">Run</a>
+		<a class="fmt" title="Format this code">Format</a>
+		<a class="share" title="Share this code">Share</a>
+	</div>
+</div>
+{{end}}
+
+<div id="page"{{if .Title}} class="wide"{{end}}>
+<div class="container">
+
+{{with .Title}}
+  <h1>{{html .}}</h1>
+{{end}}
+{{with .Subtitle}}
+  <h2>{{html .}}</h2>
+{{end}}
+
+{{/* The Table of Contents is automatically inserted in this <div>.
+     Do not delete this <div>. */}}
+<div id="nav"></div>
+
+{{/* Body is HTML-escaped elsewhere */}}
+{{printf "%s" .Body}}
+
+<div id="footer">
+Build version {{html .Version}}.<br>
+Except as <a href="https://developers.google.com/site-policies#restrictions">noted</a>,
+the content of this page is licensed under the
+Creative Commons Attribution 3.0 License,
+and code is licensed under a <a href="/LICENSE">BSD license</a>.<br>
+<a href="/doc/tos.html">Terms of Service</a> | 
+<a href="http://www.google.com/intl/en/policies/privacy/">Privacy Policy</a>
+</div>
+
+</div><!-- .container -->
+</div><!-- #page -->
+
+<!-- TODO(adonovan): load these from <head> using "defer" attribute? -->
+<script type="text/javascript" src="/lib/godoc/jquery.js"></script>
+<script type="text/javascript" src="/lib/godoc/jquery.treeview.js"></script>
+<script type="text/javascript" src="/lib/godoc/jquery.treeview.edit.js"></script>
+
+{{if .Playground}}
+<script type="text/javascript" src="/lib/godoc/playground.js"></script>
+{{end}}
+<script type="text/javascript" src="/lib/godoc/godocs.js"></script>
+
+</body>
+</html>
+
+`,
+
+	"godocs.js": `// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+/* A little code to ease navigation of these documents.
+ *
+ * On window load we:
+ *  + Bind search box hint placeholder show/hide events (bindSearchEvents)
+ *  + Generate a table of contents (generateTOC)
+ *  + Bind foldable sections (bindToggles)
+ *  + Bind links to foldable sections (bindToggleLinks)
+ */
+
+(function() {
+'use strict';
+
+// Mobile-friendly topbar menu
+$(function() {
+  var menu = $('#menu');
+  var menuButton = $('#menu-button');
+  var menuButtonArrow = $('#menu-button-arrow');
+  menuButton.click(function(event) {
+    menu.toggleClass('menu-visible');
+    menuButtonArrow.toggleClass('vertical-flip');
+    event.preventDefault();
+    return false;
+  });
+});
+
+function bindSearchEvents() {
+
+  var search = $('#search');
+  if (search.length === 0) {
+    return; // no search box
+  }
+
+  function clearInactive() {
+    if (search.is('.inactive')) {
+      search.val('');
+      search.removeClass('inactive');
+    }
+  }
+
+  function restoreInactive() {
+    if (search.val() !== '') {
+      return;
+    }
+    search.val(search.attr('placeholder'));
+    search.addClass('inactive');
+  }
+
+  search.on('focus', clearInactive);
+  search.on('blur', restoreInactive);
+
+  restoreInactive();
+}
+
+/* Generates a table of contents: looks for h2 and h3 elements and generates
+ * links. "Decorates" the element with id=="nav" with this table of contents.
+ */
+function generateTOC() {
+  if ($('#manual-nav').length > 0) {
+    return;
+  }
+
+  var nav = $('#nav');
+  if (nav.length === 0) {
+    return;
+  }
+
+  var toc_items = [];
+  $(nav).nextAll('h2, h3').each(function() {
+    var node = this;
+    if (node.id == '')
+      node.id = 'tmp_' + toc_items.length;
+    var link = $('<a/>').attr('href', '#' + node.id).text($(node).text());
+    var item;
+    if ($(node).is('h2')) {
+      item = $('<dt/>');
+    } else { // h3
+      item = $('<dd class="indent"/>');
+    }
+    item.append(link);
+    toc_items.push(item);
+  });
+  if (toc_items.length <= 1) {
+    return;
+  }
+
+  var dl1 = $('<dl/>');
+  var dl2 = $('<dl/>');
+
+  var split_index = (toc_items.length / 2) + 1;
+  if (split_index < 8) {
+    split_index = toc_items.length;
+  }
+  for (var i = 0; i < split_index; i++) {
+    dl1.append(toc_items[i]);
+  }
+  for (/* keep using i */; i < toc_items.length; i++) {
+    dl2.append(toc_items[i]);
+  }
+
+  var tocTable = $('<table class="unruled"/>').appendTo(nav);
+  var tocBody = $('<tbody/>').appendTo(tocTable);
+  var tocRow = $('<tr/>').appendTo(tocBody);
+
+  // 1st column
+  $('<td class="first"/>').appendTo(tocRow).append(dl1);
+  // 2nd column
+  $('<td/>').appendTo(tocRow).append(dl2);
+}
+
+function bindToggle(el) {
+  $('.toggleButton', el).click(function() {
+    if ($(el).is('.toggle')) {
+      $(el).addClass('toggleVisible').removeClass('toggle');
+    } else {
+      $(el).addClass('toggle').removeClass('toggleVisible');
+    }
+  });
+}
+function bindToggles(selector) {
+  $(selector).each(function(i, el) {
+    bindToggle(el);
+  });
+}
+
+function bindToggleLink(el, prefix) {
+  $(el).click(function() {
+    var href = $(el).attr('href');
+    var i = href.indexOf('#'+prefix);
+    if (i < 0) {
+      return;
+    }
+    var id = '#' + prefix + href.slice(i+1+prefix.length);
+    if ($(id).is('.toggle')) {
+      $(id).find('.toggleButton').first().click();
+    }
+  });
+}
+function bindToggleLinks(selector, prefix) {
+  $(selector).each(function(i, el) {
+    bindToggleLink(el, prefix);
+  });
+}
+
+function setupDropdownPlayground() {
+  if (!$('#page').is('.wide')) {
+    return; // don't show on front page
+  }
+  var button = $('#playgroundButton');
+  var div = $('#playground');
+  var setup = false;
+  button.toggle(function() {
+    button.addClass('active');
+    div.show();
+    if (setup) {
+      return;
+    }
+    setup = true;
+    playground({
+      'codeEl': $('.code', div),
+      'outputEl': $('.output', div),
+      'runEl': $('.run', div),
+      'fmtEl': $('.fmt', div),
+      'shareEl': $('.share', div),
+      'shareRedirect': '//play.golang.org/p/'
+    });
+  },
+  function() {
+    button.removeClass('active');
+    div.hide();
+  });
+  button.show();
+  $('#menu').css('min-width', '+=60');
+}
+
+function setupInlinePlayground() {
+	'use strict';
+	// Set up playground when each element is toggled.
+	$('div.play').each(function (i, el) {
+		// Set up playground for this example.
+		var setup = function() {
+			var code = $('.code', el);
+			playground({
+				'codeEl':   code,
+				'outputEl': $('.output', el),
+				'runEl':    $('.run', el),
+				'fmtEl':    $('.fmt', el),
+				'shareEl':  $('.share', el),
+				'shareRedirect': '//play.golang.org/p/'
+			});
+
+			// Make the code textarea resize to fit content.
+			var resize = function() {
+				code.height(0);
+				var h = code[0].scrollHeight;
+				code.height(h+20); // minimize bouncing.
+				code.closest('.input').height(h);
+			};
+			code.on('keydown', resize);
+			code.on('keyup', resize);
+			code.keyup(); // resize now.
+		};
+		
+		// If example already visible, set up playground now.
+		if ($(el).is(':visible')) {
+			setup();
+			return;
+		}
+
+		// Otherwise, set up playground when example is expanded.
+		var built = false;
+		$(el).closest('.toggle').click(function() {
+			// Only set up once.
+			if (!built) {
+				setup();
+				built = true;
+			}
+		});
+	});
+}
+
+// fixFocus tries to put focus to div#page so that keyboard navigation works.
+function fixFocus() {
+  var page = $('div#page');
+  var topbar = $('div#topbar');
+  page.css('outline', 0); // disable outline when focused
+  page.attr('tabindex', -1); // and set tabindex so that it is focusable
+  $(window).resize(function (evt) {
+    // only focus page when the topbar is at fixed position (that is, it's in
+    // front of page, and keyboard event will go to the former by default.)
+    // by focusing page, keyboard event will go to page so that up/down arrow,
+    // space, etc. will work as expected.
+    if (topbar.css('position') == "fixed")
+      page.focus();
+  }).resize();
+}
+
+function toggleHash() {
+    var hash = $(window.location.hash);
+    if (hash.is('.toggle')) {
+      hash.find('.toggleButton').first().click();
+    }
+}
+
+function personalizeInstallInstructions() {
+  var prefix = '?download=';
+  var s = window.location.search;
+  if (!s.startsWith(prefix)) {
+    // No 'download' query string; bail.
+    return;
+  }
+
+  var filename = s.substr(prefix.length);
+  var filenameRE = /^go1\.\d+(\.\d+)?([a-z0-9]+)?\.([a-z0-9]+)(-[a-z0-9]+)?(-osx10\.[68])?\.([a-z.]+)$/;
+  $('.downloadFilename').text(filename);
+  $('.hideFromDownload').hide();
+  var m = filenameRE.exec(filename);
+  if (!m) {
+    // Can't interpret file name; bail.
+    return;
+  }
+
+  var os = m[3];
+  var ext = m[6];
+  if (ext != 'tar.gz') {
+    $('#tarballInstructions').hide();
+  }
+  if (os != 'darwin' || ext != 'pkg') {
+    $('#darwinPackageInstructions').hide();
+  }
+  if (os != 'windows') {
+    $('#windowsInstructions').hide();
+  } else {
+    if (ext != 'msi') {
+      $('#windowsInstallerInstructions').hide();
+    }
+    if (ext != 'zip') {
+      $('#windowsZipInstructions').hide();
+    }
+  }
+
+  var download = "https://storage.googleapis.com/golang/" + filename;
+
+  var message = $('<p class="downloading">'+
+    'Your download should begin shortly. '+
+    'If it does not, click <a>this link</a>.</p>');
+  message.find('a').attr('href', download);
+  message.insertAfter('#nav');
+
+  window.location = download;
+}
+
+$(document).ready(function() {
+  bindSearchEvents();
+  generateTOC();
+  bindToggles(".toggle");
+  bindToggles(".toggleVisible");
+  bindToggleLinks(".exampleLink", "example_");
+  bindToggleLinks(".overviewLink", "");
+  bindToggleLinks(".examplesLink", "");
+  bindToggleLinks(".indexLink", "");
+  setupDropdownPlayground();
+  setupInlinePlayground();
+  fixFocus();
+  setupTypeInfo();
+  setupCallgraphs();
+  toggleHash();
+  personalizeInstallInstructions();
+
+  // godoc.html defines window.initFuncs in the <head> tag, and root.html and
+  // codewalk.js push their on-page-ready functions to the list.
+  // We execute those functions here, to avoid loading jQuery until the page
+  // content is loaded.
+  for (var i = 0; i < window.initFuncs.length; i++) window.initFuncs[i]();
+});
+
+// -- analysis ---------------------------------------------------------
+
+// escapeHTML returns HTML for s, with metacharacters quoted.
+// It is safe for use in both elements and attributes
+// (unlike the "set innerText, read innerHTML" trick).
+function escapeHTML(s) {
+    return s.replace(/&/g, '&amp;').
+             replace(/\"/g, '&quot;').
+             replace(/\'/g, '&#39;').
+             replace(/</g, '&lt;').
+             replace(/>/g, '&gt;');
+}
+
+// makeAnchor returns HTML for an <a> element, given an anchorJSON object.
+function makeAnchor(json) {
+  var html = escapeHTML(json.Text);
+  if (json.Href != "") {
+      html = "<a href='" + escapeHTML(json.Href) + "'>" + html + "</a>";
+  }
+  return html;
+}
+
+function showLowFrame(html) {
+  var lowframe = document.getElementById('lowframe');
+  lowframe.style.height = "200px";
+  lowframe.innerHTML = "<p style='text-align: left;'>" + html + "</p>\n" +
+      "<div onclick='hideLowFrame()' style='position: absolute; top: 0; right: 0; cursor: pointer;'>✘</div>"
+};
+
+document.hideLowFrame = function() {
+  var lowframe = document.getElementById('lowframe');
+  lowframe.style.height = "0px";
+}
+
+// onClickCallers is the onclick action for the 'func' tokens of a
+// function declaration.
+document.onClickCallers = function(index) {
+  var data = document.ANALYSIS_DATA[index]
+  if (data.Callers.length == 1 && data.Callers[0].Sites.length == 1) {
+    document.location = data.Callers[0].Sites[0].Href; // jump to sole caller
+    return;
+  }
+
+  var html = "Callers of <code>" + escapeHTML(data.Callee) + "</code>:<br/>\n";
+  for (var i = 0; i < data.Callers.length; i++) {
+    var caller = data.Callers[i];
+    html += "<code>" + escapeHTML(caller.Func) + "</code>";
+    var sites = caller.Sites;
+    if (sites != null && sites.length > 0) {
+      html += " at line ";
+      for (var j = 0; j < sites.length; j++) {
+        if (j > 0) {
+          html += ", ";
+        }
+        html += "<code>" + makeAnchor(sites[j]) + "</code>";
+      }
+    }
+    html += "<br/>\n";
+  }
+  showLowFrame(html);
+};
+
+// onClickCallees is the onclick action for the '(' token of a function call.
+document.onClickCallees = function(index) {
+  var data = document.ANALYSIS_DATA[index]
+  if (data.Callees.length == 1) {
+    document.location = data.Callees[0].Href; // jump to sole callee
+    return;
+  }
+
+  var html = "Callees of this " + escapeHTML(data.Descr) + ":<br/>\n";
+  for (var i = 0; i < data.Callees.length; i++) {
+    html += "<code>" + makeAnchor(data.Callees[i]) + "</code><br/>\n";
+  }
+  showLowFrame(html);
+};
+
+// onClickTypeInfo is the onclick action for identifiers declaring a named type.
+document.onClickTypeInfo = function(index) {
+  var data = document.ANALYSIS_DATA[index];
+  var html = "Type <code>" + data.Name + "</code>: " +
+  "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<small>(size=" + data.Size + ", align=" + data.Align + ")</small><br/>\n";
+  html += implementsHTML(data);
+  html += methodsetHTML(data);
+  showLowFrame(html);
+};
+
+// implementsHTML returns HTML for the implements relation of the
+// specified TypeInfoJSON value.
+function implementsHTML(info) {
+  var html = "";
+  if (info.ImplGroups != null) {
+    for (var i = 0; i < info.ImplGroups.length; i++) {
+      var group = info.ImplGroups[i];
+      var x = "<code>" + escapeHTML(group.Descr) + "</code> ";
+      for (var j = 0; j < group.Facts.length; j++) {
+        var fact = group.Facts[j];
+        var y = "<code>" + makeAnchor(fact.Other) + "</code>";
+        if (fact.ByKind != null) {
+          html += escapeHTML(fact.ByKind) + " type " + y + " implements " + x;
+        } else {
+          html += x + " implements " + y;
+        }
+        html += "<br/>\n";
+      }
+    }
+  }
+  return html;
+}
+
+
+// methodsetHTML returns HTML for the methodset of the specified
+// TypeInfoJSON value.
+function methodsetHTML(info) {
+  var html = "";
+  if (info.Methods != null) {
+    for (var i = 0; i < info.Methods.length; i++) {
+      html += "<code>" + makeAnchor(info.Methods[i]) + "</code><br/>\n";
+    }
+  }
+  return html;
+}
+
+// onClickComm is the onclick action for channel "make" and "<-"
+// send/receive tokens.
+document.onClickComm = function(index) {
+  var ops = document.ANALYSIS_DATA[index].Ops
+  if (ops.length == 1) {
+    document.location = ops[0].Op.Href; // jump to sole element
+    return;
+  }
+
+  var html = "Operations on this channel:<br/>\n";
+  for (var i = 0; i < ops.length; i++) {
+    html += makeAnchor(ops[i].Op) + " by <code>" + escapeHTML(ops[i].Fn) + "</code><br/>\n";
+  }
+  if (ops.length == 0) {
+    html += "(none)<br/>\n";
+  }
+  showLowFrame(html);
+};
+
+$(window).load(function() {
+    // Scroll window so that first selection is visible.
+    // (This means we don't need to emit id='L%d' spans for each line.)
+    // TODO(adonovan): ideally, scroll it so that it's under the pointer,
+    // but I don't know how to get the pointer y coordinate.
+    var elts = document.getElementsByClassName("selection");
+    if (elts.length > 0) {
+	elts[0].scrollIntoView()
+    }
+});
+
+// setupTypeInfo populates the "Implements" and "Method set" toggle for
+// each type in the package doc.
+function setupTypeInfo() {
+  for (var i in document.ANALYSIS_DATA) {
+    var data = document.ANALYSIS_DATA[i];
+
+    var el = document.getElementById("implements-" + i);
+    if (el != null) {
+      // el != null => data is TypeInfoJSON.
+      if (data.ImplGroups != null) {
+        el.innerHTML = implementsHTML(data);
+        el.parentNode.parentNode.style.display = "block";
+      }
+    }
+
+    var el = document.getElementById("methodset-" + i);
+    if (el != null) {
+      // el != null => data is TypeInfoJSON.
+      if (data.Methods != null) {
+        el.innerHTML = methodsetHTML(data);
+        el.parentNode.parentNode.style.display = "block";
+      }
+    }
+  }
+}
+
+function setupCallgraphs() {
+  if (document.CALLGRAPH == null) {
+    return
+  }
+  document.getElementById("pkg-callgraph").style.display = "block";
+
+  var treeviews = document.getElementsByClassName("treeview");
+  for (var i = 0; i < treeviews.length; i++) {
+    var tree = treeviews[i];
+    if (tree.id == null || tree.id.indexOf("callgraph-") != 0) {
+      continue;
+    }
+    var id = tree.id.substring("callgraph-".length);
+    $(tree).treeview({collapsed: true, animated: "fast"});
+    document.cgAddChildren(tree, tree, [id]);
+    tree.parentNode.parentNode.style.display = "block";
+  }
+}
+
+document.cgAddChildren = function(tree, ul, indices) {
+  if (indices != null) {
+    for (var i = 0; i < indices.length; i++) {
+      var li = cgAddChild(tree, ul, document.CALLGRAPH[indices[i]]);
+      if (i == indices.length - 1) {
+        $(li).addClass("last");
+      }
+    }
+  }
+  $(tree).treeview({animated: "fast", add: ul});
+}
+
+// cgAddChild adds an <li> element for document.CALLGRAPH node cgn to
+// the parent <ul> element ul. tree is the tree's root <ul> element.
+function cgAddChild(tree, ul, cgn) {
+   var li = document.createElement("li");
+   ul.appendChild(li);
+   li.className = "closed";
+
+   var code = document.createElement("code");
+
+   if (cgn.Callees != null) {
+     $(li).addClass("expandable");
+
+     // Event handlers and innerHTML updates don't play nicely together,
+     // hence all this explicit DOM manipulation.
+     var hitarea = document.createElement("div");
+     hitarea.className = "hitarea expandable-hitarea";
+     li.appendChild(hitarea);
+
+     li.appendChild(code);
+
+     var childUL = document.createElement("ul");
+     li.appendChild(childUL);
+     childUL.setAttribute('style', "display: none;");
+
+     var onClick = function() {
+       document.cgAddChildren(tree, childUL, cgn.Callees);
+       hitarea.removeEventListener('click', onClick)
+     };
+     hitarea.addEventListener('click', onClick);
+
+   } else {
+     li.appendChild(code);
+   }
+   code.innerHTML += "&nbsp;" + makeAnchor(cgn.Func);
+   return li
+}
+
+})();
+`,
+
+	"images/minus.gif": "GIF89a\t\x00\t\x00\xf7\x00\x00\x00\x00\x00\x80\x80\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00!\xf9\x04\x01\x00\x00\xff\x00,\x00\x00\x00\x00\t\x00\t\x00\x00\b\"\x00\x03\b\x1cH\xf0\x9f\xc1\x83\xff\x04\"<\xa8pa\xc2\x00\xff\x00H\x94\xf8\xd0aE\x87\r\x17\x12\xdc\x18  \x00;",
+
+	"images/plus.gif": "GIF89a\t\x00\t\x00\xf7\x00\x00\x00\x00\x00\x80\x80\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00!\xf9\x04\x01\x00\x00\xff\x00,\x00\x00\x00\x00\t\x00\t\x00\x00\b&\x00\x03\b\x1cH\xf0\x9f\xc1\x83\xff\x04\x1e\x04pP\xa1A\x86\x06\x15\x02\x9881a\x80\x85\r/>̈0#A\x82\x01\x01\x00;",
+
+	"images/treeview-black-line.gif": "GIF89a\x10\x00\xf0\x06\xf7\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00!\xf9\x04\x01\x00\x00\xff\x00,\x00\x00\x00\x00\x10\x00\xf0\x06\x00\b\xff\x00\xff\t\x1c\xf8\x0f\x00\xc1\x83\b\r\"\\X\x90\xe1B\x85\x0e\tB\x8c(p\"E\x8b\x111:\xd4\xc8\x10\x80Ǐ\x1f\x1fR\x948r G\x91%\x1b\xa6<\x990\xa5ʒ,\x0f\xc6$\xb9\xd2\xe5L\x936s\xd6\xdc\tSgO\x9e#oV\xf4\x19\x94\xe8E\xa3\x19\x91nTڑ)ʟP\x8b\x02=:5iեW\x9bf}*5*U\xafV\xc1b\x15\xab\x95,\u05ef]Ӣ]\x1bVm[\xb6c\xddƅ[Vn]\xbag\xdfꝻ\xf7n\u07fc|\x03\xfb\x15\fx\xb0\xe1\u0088[nUl\x96\xb1\xdd\xc42\x9d:\xc6;\xf9oe\u0097\x0fg\x86L\xb3q\xe4ş=w~\xbc\xb9thҧ)\xa7\xb6\xbc\x1askͯ9\xe3\x04=Zumַ]熽[\xf6PڳE\aG\xdd\xdbt\xf1\xd8Ƈ\xdbV\x8e\x9b\xb9n缡\xfb~Iܥ\xf5\xebسk\xdfν{\xf4\xdf\xc2\xc1W\xff\x17\xbf\x9c|s\xf3\xcf\xd1\u007f\xa7^\x9e\xfdy\xf7\xe9\xe1\xaf\x17*\u007f:\xfd\xfb\x92\x91\xeb?\xce_zr\xf5\xf6\xe5\xd7\x1f\x80\xff\xd5W ~\xc0\x11\xb8\x9f\u007f\v*8\xa0\x81\rB\xf8 \x82\xe1I\xc8\xe0\x84\x02^\xa8\xa1\x83\x1bZ\xc8\xe1\x87\x1e\x86H\xe1x\"f\b\xe2\x88\xed\xa1\xf8\x9e\x8a\xf1\xb18\x9f\x89%&\x18c\x85.\x06(c\x8d\a\u0088c\x84;bx\xa3\x8e@\xfe($\x8dA\x129$\x89=v\x98\xe4\x89E\"\xd9d\x8aO\xae\x18e\x8bS\xbex$\x94WJ\x99%\x95[Zi\xe4\x97Nvi#\x98X\x92\xa9\xa5\x99\\\xa2\xe9e\x98j\x8e\xc9\xe6\x9be\xc2y\xa6\x9ciҹf\x9cxΙg\x9d{ީ\xe7\x9f|\x02\xeag\xa0\x84\x0ej\xa8\x9b}\"*\xa8\xa2\x852zh\x8ebBڦ\xa4v:j)\xa5\x89b\xba\xa8\xa6\x8dr\xfa(\x8fU^\nj\xa4\xa3NZj\xa5\x9e\x8a꣩\xab\xa2zj\xa6\xafn\xff\x1ak\xa7\xb3~\xda*\xac\xb7ʚ+\xad\xbbڪd\xa8\xa9\x06[\xab\xaa\xbf\x92\xda+\xb1L\x1a[,\xab˺z\xac\xb0\xcf\x0e\vm\xb3\xb8R\xab\xab\xb5\xbcb\xebk\xb2\xccr묶\xc8\xce\xf8\xad\xb7Ւ{\xad\xb9٢\xbb\xad\xb8\xe5\xb2{\xae\xbb\xe9»\xee\x92\xf2\x86K\xef\xbd\xc0J\xabo\xb4\xfc\x82;\xad\xba\xf6\xe6\xdb/\xc0\xff\xd6[0\xbe\xca\x12\xbc\xaf\xbf\v+<\xb0\xc1\rC\xfc0\xc2\xddJ\xcc\xf0\xc4\x02_\xac\xb1\xc3\x1b[\xcc\xf1\xc7\x1e\x87L\xf1\xb8\"g\f\xf2\xc8\xed\xa2\xfc\xae\xca\xf1\xb2<\xaf\xc9%'\x1cs\xc5.\a,s\xcd\aÌs\xc4;c|\xb3\xce@\xff,4\xcdA\x13=4\xc9=w\x9c\xf4\xc9E#\xddt\xcaO\xaf\x1cu\xcbS\xbf|4\xd4WK\x9d5\xd5[[m\xf4\xd7Nwm3\xd8X\x93\xad\xb5\xd9\\\xa3\xedu\xd8j\x8f\xcd\xf6\xdbe\xc3}\xb6\xdciӽv\xdcxϝw\xdd{\xdf\xff\xad\xf7\xdf|\x03\xeew\xe0\x84\x0fn\xb8\xdb}#.\xb8\xe2\x853~x\xcebC\u07b6\xe4v;n9\xe5\x89c\xbe\xb8\xe6\x8ds\xfe8\xcfU_\x0ez\xe4\xa3O^z型\xee\xb3髣~z\xe6\xafo\x1e{\xe7\xb3\u007f\xde:\xec\xb7˞;\xed\xbbۮt\xe8\xa9\a_\xbb꿓\xde;\xf1L\x1b_<\xeb˻~\xbc\xf0\xcf\x0f\x0f}\xf3\xb8S\xaf\xbb\xf5\xbcc\xef{\xf2\xccs\xef\xbc\xf6\xc8\xcf\xfc\xbd\xf7Փ\u007f\xbd\xf9٣\xbf\xbd\xf8\xe5\xb3\u007f\xbe\xfb\xe9ÿ\xfe\xd2\xf2\x87O\xff\xfd\xc0K\xaf\u007f\xf4\xfc\x83?\xbd\xfa\xf6\xcb_\xff\x00\xf8\xbf\xfa\x15\x10\u007f\xca#\xe0\xfe\xfc\xb7@\x05\x0eЀ\r\x84\xe0\x03\x11\xd8=\t2p\x82\x02\xbc\xa0\x06\x1d\xb8A\vr\xf0\x83\x1e\f!\x05\xc7'\xc2\f\x82p\x84\xedC\xe1\xfbT\x18?\x16\xceτ%L`\f+\xe8\xc2\x00ʰ\x86\a\x84!\x0e#\xb8C\f\xdeP\x87@\xfc\xa1\x102i\x18D\"\x0e\x91\x84=\xec`\x12OXD$61\x85O\\a\x14[8\xc5\x17\x1e\x11\x8aW\x94b\x16\xa9\xb8E+\x1a\xf1\x8bN\xec\xa2\ri\b\x12\x90\x04\x04\x00;",
+
+	"images/treeview-black.gif": "GIF89a`\x00\x85\x00\xa1\x01\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff!\xf9\x04\x01\x00\x00\x02\x00,\x00\x00\x00\x00`\x00\x85\x00\x00\x02\xfe\x94\x8f\xa9\xcb\xed\x0fE\x98\xc1ш\xb3ި\xf2\x0f\x86\x9a'\x96\xa6I\x9e\xeaʶ\xee\nIJ\xfc\xd6&\xb0\xe0\xf6\xfe\xe9\x82\xef\xe3\t#\xc0Cp\x88d\xe0f\xcbY\xf2\x89(\x1a\x8eP\xa8\xf4W\xcdNs\xda,\xd3\xd9\xedR\xc3^\xb2yl~\xa2\xd3\xc85[\xe8~\xabRF9\x8f\xbe\xb5o.\x96\tW?R\x12\a\x98\x80Gx\x88\x98\b\xf8E\xa3\xa826\xe8\x88\x01)yBY)\xf8\xe3Ą\xd9\xf3\xd7\tr\t\xea\xa9\x109\x9a\xc3hzڠ\xba\xfa\xd0\xea\xca\x1a{3\x9bY\x1b\x02\xebj\x98\xbb\xba\x1b\xcb\xd7\x00\x1c\xf5k\xdb{{\x8c\x9c\xac\x8cʸ\xac\xf4\xe9<\x9c\x87\x15\x9dp\xc5{\xdaD\xc3Y}]m]7\xfdM\r>>\x95j\x9e\xae\xbe\xceގd\xb8\x0e\xff+\xac@\u007f뛎o\xae?\xce\xef\x8e\x1d+\x15@P\xa2\xc6yKwМ\xb6\x18\x9a\x1aEKh0\x1c\xb9\x88\xa5\xd4\tt\x871\xa3\xc6d\x8d\x06\xe4\xe5\xdb豗\x9f>!O\x95\xfcv\xb2ZJ\x8e,\r\xa2C\b\xed[A\x991\xbb5d\xc8\xedaM\x9d\x15a\xf6T\xf8\xb2\xa5СDG\xadtvtY\xd2J\xf6:\x8cT\xb8q`-\xa9\xb3\xa8\x06\xfc\x17\x94b9\xa8?\xb5J\x83\xca)\xa7\xb3\x996\xbb\xd24\xdb-kѵlۺ}\v7.\x82\x02\x00;",
+
+	"images/treeview-default-line.gif": "GIF89a\x10\x00\xf0\x06\xf7\x00\x00\x00\x00\x00\x80\x80\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00!\xf9\x04\x01\x00\x00\xff\x00,\x00\x00\x00\x00\x10\x00\xf0\x06\x00\b\xff\x00\xff\t\x1cH\xb0\xa0A\x81\x01\x0e*\\x0!Ç\v\x1dB\x9cHP\"E\x8a\t3\xfe\xd3x\xb1aNj\x16?2\f)R!ɒ\x06O\xa2\xac\xb8rdˈ/M\xc6\xf48\xb3\xa0ʗ7[\xe6\\\xb9\x13eϒ?E\x06\xfd8\xb4cQ\x905m&e\xb9\x14aS\xa7O\x8fb|\xba\x91\xaaԉW!f}\xb8\xd5eT\xab`\xbf\x8am\xda\x15\xe6إee\x9eM\x9a\x96&ٰo\xd7\xd6l\x9b\x12.Z\xbbl\xf1\xce\xd5;\x93\xaeR\xb9}\xf9\xc6\xf4\xcb4\xaeỀ\a\vƹXgc\x9e\x8f}F\x06:Yhe\xa2\x97\xa9j\xde̹3\xd7\xccH\x133\x16\xed\x984dӒQSVm\x995f\xd7FAO\x85\x1d\xfap^ڳm\xefōUvo\xdeZ}\a\a\xfe\x99\xb8W݁\x8d\x9bE\xaeX\xb9Z棡\x97\x96~\x9azj뫱\xb7\xd6\xfe\x9a{l\xe7n\x11{\xff\xaf-\xbe\xfc\xed\xf1\xb9\xcd\xefF\xff\x9b\xfdp\xf7\xc5\xe1\x1fW\x9f\\\xfer\xfa\xcd\xed?\xc7\x1f\x9d\xfft\xff\xd5\x01x\x9d\x80\xd9\x11\xb8\x9d\x81\xdd!\xf8\x9d~ᝧ y\x0eF\xb8ރ\xe9IX\x1f\x85\xeda\xf8\x9e\x86\xf1q8\x9f\x85\xf9yx\x1f\x88\xfd\x91\xf8\x9f\x89\x01\xa28\xa0\x8a\x05\xb2x\xa0\x8b\t¸\xa0\x88\xfb\xc9\b\xe1\x846V\x88\xe3\x8e\x17昡\x8f\x1b\x02١\x90\x1f\xf2\x18\"\x91#\x1aY\xa2\x92'2\x99\xa2\x93+B٢\x94/R\x19\xa3\x953\"Y#\x967\xf6ȥ\x8e^\x86y\xe4\x97?\x92\x19\xa4\x99C\xa2Y\xa4\x98K\xb2٤\x9bO\xc2\x19\xa5\x9cS\xd2Y\xa5\x9dW♥\x9aI\xea\xd9\xe5\x98~\x82\t\xe8\xa0m\x12\xfa\xa6\xa1q\":\xa7\xa2u2z\xa7\xa3yB\xbag\xa0eRz\xa6\xa5ib\xba\xa6\xa4\u007f\x16\xea顟&\x1aꢣ6Z꣧F\x9aꤜ\n\xbaj\xa7\xa0\xc6\xff*\xaa\xac\xa4\xd2j\xaa\xad\xa8⪪\xae\xac\xbe\xea*\xaf\xb0\xce*l\xad\xc3\xdeZl\xae\xc7\xee\x9al\xaf\xc0\xfe\xbal\xb0\xc4Fk\xac\xb4\xc8R\xab\xac\xb5\xcc>\xeb,\xb6\xd0N\xebm\xb5\xdf^\x1bn\xb6\xdcn;n\xb7\xe0\xa6+\xae\xba\xe4\x9ek.\xbb\xe8\xae+o\xbb\xf0\xbe;o\xbc\xf4\xdeko\xbe\xfc\xe2\xeb\xef\xbe\xffVڪ\xc0\xbe\x12ܬ\xc1\xda\"\\\xae\xc2\xee2\\\xaf\xc3\xfaB\xdc/\xc0\x14K\x1c\xf0\xa5\x03c\\\xb0\xc6\as\x9c\xb0\xc7\v\x83ܰ\xc8\x0f\x93\x1c\xb1\xc9\x13[\\1\xca\x17g\x9a\xb1\xcb\x1b\xc3ܱ\xcc\x1f\xd3\x1c\xb2\xcd#\xe3\\\xb2\xce'\xf3\x9c2\xcb+\xfb\xdc\xf2\xa61\x13=\xb3\xd15#}\xb3\xd293\xbd\xb3\xd3=C\xfd\xb3\xd0AK=t\x9f/[]5\xd6Es}\xb4\xd7I\x83\xbd\xb4\xd8M\x93\xfd\xb4\xd9Q\xa3=\xb5\xd6*\xb7\r\xb4\xdbT\xc3\xcd\xf6\xdbt\xc7]\xf7\xdcv\xe7\x8d\xf7\xdej_\xff\xbd\xa5\xa6}o\xfdwց\xcb]\xf8݇\xeb\x9d8߃w\xdd\xf8\u05cf\x87\x1d\xf9ؓ\x97]\xf9ٗ\xa7\x9d\xf9ڋw\xbe\xb9\xdf\r\xf2\xf9\xb9\xe0\xa1\x03>\xba\xe1\xa7#\x9e\xba\xe2\xab3^:\xe1\xad{\xfe\xba\xe3\xb3C^\xbb\xe4\xb7S\x9e\xbb\xe5\xbbc\u07bb\xe6\xbfs\x1e\xfb\xf0\xc1\x83^\x17x\xc73\x98<\x8dœ\xbe\xbc\x96ͣ\x1e\xbd\xeaӳ^\xbd\xebϋ~\xbd\xecٛ\xbe=\xf1\xdd\xc3\xfe\xfd\xf8\xe1\xd3^\xbe\xed\xe7㞾\xee\xeb\xf3\u07be\xef\xef\x03\x1f\xbf\xf0\xe4\xff\xa5\xbc\xfd\xcc\xcfo<\xfe\xd0\xeb\xef<\xff\xda\xf3\x9f\xf4\x04H=\x02Zπ\xd8\x03\xa0\xf7\x10\xc8=\x05\x8a\x8f\x81\xe0s\xa0\xf9$\x88>\n\xaaς\xecà\xfb4\b?\x0e\xcaσ\xf4\x83`\xfd\n\x93?\x10\ue3c4\xfd3\xe1\xffP\x18@\x15\x0eЅ\x05\x84\xe1\x01e\x98@\x16.\x90\x86\r\xb4\xe1\x03q\x18A\x1dNЇ\x15\x04\xe2\x05\xa6\x85\x98A\"nЈ\x1dD\xe2\a\x95\x18B\x1e\x8ep \x84\x81\xa2pf\xc8\xc4\x13J\x11yN\x14\xa1\x16\xb3\xc8\xc5*\xae\xf0\x8a\xf7\xf3\xe2\v\xc5\x18C2R\x11\x8c%4c\rјB5損-tc\x0f\xe1xC9>\x11*a\xa4\xe3\x0e\xed\xb8E>vQ\x8f?\x04d\x10\x059DB\x16ѐGDd\x12\x15\xb9DF6я\x90t\xa4\x15\xf1\x98FI~\x91\x92m\xb4\xe4\x185YFN\x9e\x11\x93q\xf4\xe4\x1aAYGQ\xbe\x91\x94{4\xe5\x1cQ\x19HV\x0eҕ\x85\x84\xe5!e\x99HZ.\xd2)\x1a\xc9H@\x00\x00;",
+
+	"images/treeview-default.gif": "GIF89a`\x00\x85\x00\xa1\x03\x00\x00\x00\x00\x80\x80\x80\xbc\xbc\xbc\xff\xff\xff!\xf9\x04\x01\x00\x00\x03\x00,\x00\x00\x00\x00`\x00\x85\x00\x00\x02\xfe\x9c\x8f\xa9\xcb\xed\x0f\a\x98\xc0ш\xb3ި\xf2\x0f\x86\x9a'\x96\xa6I\x9e\xeaʶ\xee\x1aIJ\xfc\xd6f\xb0\xe0\xf6\xfe\xe9\xd2\xe1\xe3\t#>Rp\x88d\xe0(\x93\x01\ue64c\"\x8a@\xa9uz0^\xb7GCw;\x9c\x89\xc1\xe4\xb2\xd9yN\xab\xa5ߵ\xfb}j\xc3M\x82y\xb2\xae\x90\xdb\x13\x82\xfe\xa3\x8f\xb7\xf7\x11\b\xa2'h@x\xa8\xb8\xc8\xc8&F\xd3(\xf2e\x18\xf90Y\x19r\x89\xd9#\xc1\x84\x06\xb5\x89\xa1\x19\xaa1J*\x9asZ\xfa\x18\xa3\xeajE\xf9*\xeb\x12;k\x1bwې\x98\xfb\x97J\n\xf8\xe7w\xbb\xbbQkG̛\xac\xbc\xfc\xc6\xda\xca\xec\xe5\vM\x15\r\x8df\xa0e\xbd\xe4\te\xbcI}=\x9dU\xa5-\xcd\xec\xecm\xad\xbe\xce\xde\ueb81\xac\x1e\xff\v\xac+l;\x0fM\x9c\xfe\xfb~\xb0\xef/ :u\xa6\x96\x81\xe3\x17\xea \xc1N\x17\xba\x19\x1cWM\x1c6r\x12\x13 \xfc\xe6,\xa0\xc6b\x8d\x1c\xf5i\xcc\xc7\f$\xa6z\xf6DV2\x99\f%/\x95\x1d[\xde\x1aX.\xcfB\x991-.dR\xc1\xa1\xb2\x82;\xcd=\xa49-\xa3ˡD\x8b\x1eb9\xec\xe3\xca{\vH\x1a\x9du\xf1i\xa5\xa8R\x0f\xc1\xac\x88\xa5fV\xac\x14\xcf1l\xa23\x19O\xb1>{\x02='\xb4\xaaڵlۺ}˫\x00\x00;",
+
+	"images/treeview-gray-line.gif": "GIF89a\x10\x00\xf0\x06\xf7\x00\x00\x00\x00\x00\x80\x80\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00!\xf9\x04\x01\x00\x00\xff\x00,\x00\x00\x00\x00\x10\x00\xf0\x06\x00\b\xff\x00\xff\t\x1c\xf8/\x00\xc1\x83\b\r\"\\X\x90\xe1B\x85\x0e\tB\x8c(p\"E\x8b\x111:\xd4\xc80\x80Ǐ\x1f\x1fR\x948r G\x91%\x1b\xa6<\x990\xa5ʒ,\x0f\xc6$\xb9\xd2\xe5L\x936s\xd6\xdc\tSgO\x9e#oV\xf4\x19\x94\xe8E\xa3\x19\x91nTڑ)ʟP\x8b\x02=:5iեW\x9bf}*5*U\xafV\xc1b\x15\xab\x95,\u05ef]Ӣ]\x1bVm[\xb6c\xddƅ[Vn]\xbag\xdfꝻ\xf7n\u07fc|\x03\xfb\x15\fx\xb0\xe1\u0088[nUl\x96\xb1\xdd\xc42\x9d:\xc6;\xf9oe\u0097\x0fg\x86L\xb3q\xe4ş=w~\xbc\xb9thҧ)\xa7\xb6\xbc\x1askͯ9\xe3\x04=Zumַ]熽[\xf6PڳE\aG\xdd\xdbt\xf1\xd8Ƈ\xdbV\x8e\x9b\xb9n缡\xfb~Iܥ\xf5\xebسk\xdfν{\xf4\xdf\xc2\xc1W\xff\x17\xbf\x9c|s\xf3\xcf\xd1\u007f\xa7^\x9e\xfdy\xf7\xe9\xe1\xaf\x17*\u007f:\xfd\xfb\x92\x91\xeb?\xce_zr\xf5\xf6\xe5\xd7\x1f\x80\xff\xd5W ~\xc0\x11\xb8\x9f\u007f\v*8\xa0\x81\rB\xf8 \x82\xe1I\xc8\xe0\x84\x02^\xa8\xa1\x83\x1bZ\xc8\xe1\x87\x1e\x86H\xe1x\"f\b\xe2\x88\xed\xa1\xf8\x9e\x8a\xf1\xb18\x9f\x89%&\x18c\x85.\x06(c\x8d\a\u0088c\x84;bx\xa3\x8e@\xfe($\x8dA\x129$\x89=v\x98\xe4\x89E\"\xd9d\x8aO\xae\x18e\x8bS\xbex$\x94WJ\x99%\x95[Zi\xe4\x97Nvi#\x98X\x92\xa9\xa5\x99\\\xa2\xe9e\x98j\x8e\xc9\xe6\x9be\xc2y\xa6\x9ciҹf\x9cxΙg\x9d{ީ\xe7\x9f|\x02\xeag\xa0\x84\x0ej\xa8\x9b}\"*\xa8\xa2\x852zh\x8ebBڦ\xa4v:j)\xa5\x89b\xba\xa8\xa6\x8dr\xfa(\x8fU^\nj\xa4\xa3NZj\xa5\x9e\x8a꣩\xab\xa2zj\xa6\xafn\xff\x1ak\xa7\xb3~\xda*\xac\xb7ʚ+\xad\xbbڪd\xa8\xa9\x06[\xab\xaa\xbf\x92\xda+\xb1L\x1a[,\xab˺z\xac\xb0\xcf\x0e\vm\xb3\xb8R\xab\xab\xb5\xbcb\xebk\xb2\xccr묶\xc8\xce\xf8\xad\xb7Ւ{\xad\xb9٢\xbb\xad\xb8\xe5\xb2{\xae\xbb\xe9»\xee\x92\xf2\x86K\xef\xbd\xc0J\xabo\xb4\xfc\x82;\xad\xba\xf6\xe6\xdb/\xc0\xff\xd6[0\xbe\xca\x12\xbc\xaf\xbf\v+<\xb0\xc1\rC\xfc0\xc2\xddJ\xcc\xf0\xc4\x02_\xac\xb1\xc3\x1b[\xcc\xf1\xc7\x1e\x87L\xf1\xb8\"g\f\xf2\xc8\xed\xa2\xfc\xae\xca\xf1\xb2<\xaf\xc9%'\x1cs\xc5.\a,s\xcd\aÌs\xc4;c|\xb3\xce@\xff,4\xcdA\x13=4\xc9=w\x9c\xf4\xc9E#\xddt\xcaO\xaf\x1cu\xcbS\xbf|4\xd4WK\x9d5\xd5[[m\xf4\xd7Nwm3\xd8X\x93\xad\xb5\xd9\\\xa3\xedu\xd8j\x8f\xcd\xf6\xdbe\xc3}\xb6\xdciӽv\xdcxϝw\xdd{\xdf\xff\xad\xf7\xdf|\x03\xeew\xe0\x84\x0fn\xb8\xdb}#.\xb8\xe2\x853~x\xcebC\u07b6\xe4v;n9\xe5\x89c\xbe\xb8\xe6\x8ds\xfe8\xcfU_\x0ez\xe4\xa3O^z型\xee\xb3髣~z\xe6\xafo\x1e{\xe7\xb3\u007f\xde:\xec\xb7˞;\xed\xbbۮt\xe8\xa9\a_\xbb꿓\xde;\xf1L\x1b_<\xeb˻~\xbc\xf0\xcf\x0f\x0f}\xf3\xb8S\xaf\xbb\xf5\xbcc\xef{\xf2\xccs\xef\xbc\xf6\xc8\xcf\xfc\xbd\xf7Փ\u007f\xbd\xf9٣\xbf\xbd\xf8\xe5\xb3\u007f\xbe\xfb\xe9ÿ\xfe\xd2\xf2\x87O\xff\xfd\xc0K\xaf\u007f\xf4\xfc\x83?\xbd\xfa\xf6\xcb_\xff\x00\xf8\xbf\xfa\x15\x10\u007f\xca#\xe0\xfe\xfc\xb7@\x05\x0eЀ\r\x84\xe0\x03\x11\xd8=\t2p\x82\x02\xbc\xa0\x06\x1d\xb8A\vr\xf0\x83\x1e\f!\x05\xc7'\xc2\f\x82p\x84\xedC\xe1\xfbT\x18?\x16\xceτ%L`\f+\xe8\xc2\x00ʰ\x86\a\x84!\x0e#\xb8C\f\xdeP\x87@\xfc\xa1\x102i\x18D\"\x0e\x91\x84=\xec`\x12OXD$61\x85O\\a\x14[8\xc5\x17\x1e\x11\x8aW\x94b\x16\xa9\xb8E+\x1a\xf1\x8bN\xec\xa2\ri\b\x12\x90\x04\x04\x00;",
+
+	"images/treeview-gray.gif": "GIF89a`\x00\x85\x00\xa1\x03\x00\x00\x00\x00\x80\x80\x80\xbc\xbc\xbc\xff\xff\xff!\xf9\x04\x01\x00\x00\x03\x00,\x00\x00\x00\x00`\x00\x85\x00\x00\x02\xfe\x9c\x8f\xa9\xcb\xed\x0f\x87\x98\xc2ш\xb3ި\xf2\x0f\x86\x9a'\x96\xa6I\x9e\xeaʶ\xee\x1aIJ\xfc\xd6f\xb0\xe0\xf6\xfe\xe9\x03p\xf0\xf1\x86\x11\x1f\xd0 $*\x198\x80\xd39\x98%\x97Kc\x90\x8aUX\x91\xd9.W\xeb\xedJg\xe1\xf2\xb4,F\xab\xcfj*\xbb\xad|Ç\xf2\xb9*u\xb5\xef\xf0_\xfdh\xf2p\x01\xe67RRG\x98\xc0\x87\xb8\xc8\xd8H8F\xe3\xa8rv(\x89Aiy\x82\x99i\xf8\xf3\x04$\xc5ٓ#*\xb2Y::\x88\xca\x01\x19\xb3\xda\xf9\xaa\x19+;\v[\x1bRyې{\xab\xc8[\xeb;+\xd80\x8c\xf0K\xa8\xa8q여\xeb\xfc\f\rݺ\xfcz\x1a\xadz\x14u\xcdt\x90M\xbd\xda\xf4\x19E\xb6\xdd\xe7]\x8e\x9d\x87\xaen\xbcn\xdc\xea\x1e/?O_\xef\xd5,\x8f\xffJ\x81_\xec\x1c\x9c\x8fT@U\xee\x00\xdac7oZB\x81\xf1\xb6h\x93\xe7\xf0\x1b\xaapO\xc6E*\x17q\xa1\x81ms\x10\x19\xbaSx0\xa4ȑ$%\x90\xd4W\xf0\x9a?\x05+{\x9d|Y2fL\x90\r=\xae\xb3v\xd3&:\x8aPB\xedԉ\x11\xe86\x9c;\xe1\xc9<\x8a4\xe9*\x94똢sZ\xaa\xe5\x01\xa9\xd7$\xea\xb2z\vk-\xad\xb3\xb8\x96\xa2\xf9QhU\xb1ш\x06\xfd\x04\x8a\\P\x829\xd9\xfet\x8bѨҹt\xebڽ\x8b7\xaf\x82\x02\x00;",
+
+	"implements.html": `<div class="toggle" style="display: none">
+	<div class="collapsed">
+		<p class="exampleHeading toggleButton">▹ <span class="text">Implements</span></p>
+	</div>
+	<div class="expanded">
+		<p class="exampleHeading toggleButton">▾ <span class="text">Implements</span></p>
+		<div style="margin-left: 1in" id='implements-{{.Index}}'>...</div>
+	</div>
+</div>
+`,
+
+	"jquery.js": `/*! jQuery v1.8.2 jquery.com | jquery.org/license */
+(function(a,b){function G(a){var b=F[a]={};return p.each(a.split(s),function(a,c){b[c]=!0}),b}function J(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(I,"-$1").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:+d+""===d?+d:H.test(d)?p.parseJSON(d):d}catch(f){}p.data(a,c,d)}else d=b}return d}function K(a){var b;for(b in a){if(b==="data"&&p.isEmptyObject(a[b]))continue;if(b!=="toJSON")return!1}return!0}function ba(){return!1}function bb(){return!0}function bh(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function bi(a,b){do a=a[b];while(a&&a.nodeType!==1);return a}function bj(a,b,c){b=b||0;if(p.isFunction(b))return p.grep(a,function(a,d){var e=!!b.call(a,d,a);return e===c});if(b.nodeType)return p.grep(a,function(a,d){return a===b===c});if(typeof b=="string"){var d=p.grep(a,function(a){return a.nodeType===1});if(be.test(b))return p.filter(b,d,!c);b=p.filter(b,d)}return p.grep(a,function(a,d){return p.inArray(a,b)>=0===c})}function bk(a){var b=bl.split("|"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}function bC(a,b){return a.getElementsByTagName(b)[0]||a.appendChild(a.ownerDocument.createElement(b))}function bD(a,b){if(b.nodeType!==1||!p.hasData(a))return;var c,d,e,f=p._data(a),g=p._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;d<e;d++)p.event.add(b,c,h[c][d])}g.data&&(g.data=p.extend({},g.data))}function bE(a,b){var c;if(b.nodeType!==1)return;b.clearAttributes&&b.clearAttributes(),b.mergeAttributes&&b.mergeAttributes(a),c=b.nodeName.toLowerCase(),c==="object"?(b.parentNode&&(b.outerHTML=a.outerHTML),p.support.html5Clone&&a.innerHTML&&!p.trim(b.innerHTML)&&(b.innerHTML=a.innerHTML)):c==="input"&&bv.test(a.type)?(b.defaultChecked=b.checked=a.checked,b.value!==a.value&&(b.value=a.value)):c==="option"?b.selected=a.defaultSelected:c==="input"||c==="textarea"?b.defaultValue=a.defaultValue:c==="script"&&b.text!==a.text&&(b.text=a.text),b.removeAttribute(p.expando)}function bF(a){return typeof a.getElementsByTagName!="undefined"?a.getElementsByTagName("*"):typeof a.querySelectorAll!="undefined"?a.querySelectorAll("*"):[]}function bG(a){bv.test(a.type)&&(a.defaultChecked=a.checked)}function bY(a,b){if(b in a)return b;var c=b.charAt(0).toUpperCase()+b.slice(1),d=b,e=bW.length;while(e--){b=bW[e]+c;if(b in a)return b}return d}function bZ(a,b){return a=b||a,p.css(a,"display")==="none"||!p.contains(a.ownerDocument,a)}function b$(a,b){var c,d,e=[],f=0,g=a.length;for(;f<g;f++){c=a[f];if(!c.style)continue;e[f]=p._data(c,"olddisplay"),b?(!e[f]&&c.style.display==="none"&&(c.style.display=""),c.style.display===""&&bZ(c)&&(e[f]=p._data(c,"olddisplay",cc(c.nodeName)))):(d=bH(c,"display"),!e[f]&&d!=="none"&&p._data(c,"olddisplay",d))}for(f=0;f<g;f++){c=a[f];if(!c.style)continue;if(!b||c.style.display==="none"||c.style.display==="")c.style.display=b?e[f]||"":"none"}return a}function b_(a,b,c){var d=bP.exec(b);return d?Math.max(0,d[1]-(c||0))+(d[2]||"px"):b}function ca(a,b,c,d){var e=c===(d?"border":"content")?4:b==="width"?1:0,f=0;for(;e<4;e+=2)c==="margin"&&(f+=p.css(a,c+bV[e],!0)),d?(c==="content"&&(f-=parseFloat(bH(a,"padding"+bV[e]))||0),c!=="margin"&&(f-=parseFloat(bH(a,"border"+bV[e]+"Width"))||0)):(f+=parseFloat(bH(a,"padding"+bV[e]))||0,c!=="padding"&&(f+=parseFloat(bH(a,"border"+bV[e]+"Width"))||0));return f}function cb(a,b,c){var d=b==="width"?a.offsetWidth:a.offsetHeight,e=!0,f=p.support.boxSizing&&p.css(a,"boxSizing")==="border-box";if(d<=0||d==null){d=bH(a,b);if(d<0||d==null)d=a.style[b];if(bQ.test(d))return d;e=f&&(p.support.boxSizingReliable||d===a.style[b]),d=parseFloat(d)||0}return d+ca(a,b,c||(f?"border":"content"),e)+"px"}function cc(a){if(bS[a])return bS[a];var b=p("<"+a+">").appendTo(e.body),c=b.css("display");b.remove();if(c==="none"||c===""){bI=e.body.appendChild(bI||p.extend(e.createElement("iframe"),{frameBorder:0,width:0,height:0}));if(!bJ||!bI.createElement)bJ=(bI.contentWindow||bI.contentDocument).document,bJ.write("<!doctype html><html><body>"),bJ.close();b=bJ.body.appendChild(bJ.createElement(a)),c=bH(b,"display"),e.body.removeChild(bI)}return bS[a]=c,c}function ci(a,b,c,d){var e;if(p.isArray(b))p.each(b,function(b,e){c||ce.test(a)?d(a,e):ci(a+"["+(typeof e=="object"?b:"")+"]",e,c,d)});else if(!c&&p.type(b)==="object")for(e in b)ci(a+"["+e+"]",b[e],c,d);else d(a,b)}function cz(a){return function(b,c){typeof b!="string"&&(c=b,b="*");var d,e,f,g=b.toLowerCase().split(s),h=0,i=g.length;if(p.isFunction(c))for(;h<i;h++)d=g[h],f=/^\+/.test(d),f&&(d=d.substr(1)||"*"),e=a[d]=a[d]||[],e[f?"unshift":"push"](c)}}function cA(a,c,d,e,f,g){f=f||c.dataTypes[0],g=g||{},g[f]=!0;var h,i=a[f],j=0,k=i?i.length:0,l=a===cv;for(;j<k&&(l||!h);j++)h=i[j](c,d,e),typeof h=="string"&&(!l||g[h]?h=b:(c.dataTypes.unshift(h),h=cA(a,c,d,e,h,g)));return(l||!h)&&!g["*"]&&(h=cA(a,c,d,e,"*",g)),h}function cB(a,c){var d,e,f=p.ajaxSettings.flatOptions||{};for(d in c)c[d]!==b&&((f[d]?a:e||(e={}))[d]=c[d]);e&&p.extend(!0,a,e)}function cC(a,c,d){var e,f,g,h,i=a.contents,j=a.dataTypes,k=a.responseFields;for(f in k)f in d&&(c[k[f]]=d[f]);while(j[0]==="*")j.shift(),e===b&&(e=a.mimeType||c.getResponseHeader("content-type"));if(e)for(f in i)if(i[f]&&i[f].test(e)){j.unshift(f);break}if(j[0]in d)g=j[0];else{for(f in d){if(!j[0]||a.converters[f+" "+j[0]]){g=f;break}h||(h=f)}g=g||h}if(g)return g!==j[0]&&j.unshift(g),d[g]}function cD(a,b){var c,d,e,f,g=a.dataTypes.slice(),h=g[0],i={},j=0;a.dataFilter&&(b=a.dataFilter(b,a.dataType));if(g[1])for(c in a.converters)i[c.toLowerCase()]=a.converters[c];for(;e=g[++j];)if(e!=="*"){if(h!=="*"&&h!==e){c=i[h+" "+e]||i["* "+e];if(!c)for(d in i){f=d.split(" ");if(f[1]===e){c=i[h+" "+f[0]]||i["* "+f[0]];if(c){c===!0?c=i[d]:i[d]!==!0&&(e=f[0],g.splice(j--,0,e));break}}}if(c!==!0)if(c&&a["throws"])b=c(b);else try{b=c(b)}catch(k){return{state:"parsererror",error:c?k:"No conversion from "+h+" to "+e}}}h=e}return{state:"success",data:b}}function cL(){try{return new a.XMLHttpRequest}catch(b){}}function cM(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function cU(){return setTimeout(function(){cN=b},0),cN=p.now()}function cV(a,b){p.each(b,function(b,c){var d=(cT[b]||[]).concat(cT["*"]),e=0,f=d.length;for(;e<f;e++)if(d[e].call(a,b,c))return})}function cW(a,b,c){var d,e=0,f=0,g=cS.length,h=p.Deferred().always(function(){delete i.elem}),i=function(){var b=cN||cU(),c=Math.max(0,j.startTime+j.duration-b),d=1-(c/j.duration||0),e=0,f=j.tweens.length;for(;e<f;e++)j.tweens[e].run(d);return h.notifyWith(a,[j,d,c]),d<1&&f?c:(h.resolveWith(a,[j]),!1)},j=h.promise({elem:a,props:p.extend({},b),opts:p.extend(!0,{specialEasing:{}},c),originalProperties:b,originalOptions:c,startTime:cN||cU(),duration:c.duration,tweens:[],createTween:function(b,c,d){var e=p.Tween(a,j.opts,b,c,j.opts.specialEasing[b]||j.opts.easing);return j.tweens.push(e),e},stop:function(b){var c=0,d=b?j.tweens.length:0;for(;c<d;c++)j.tweens[c].run(1);return b?h.resolveWith(a,[j,b]):h.rejectWith(a,[j,b]),this}}),k=j.props;cX(k,j.opts.specialEasing);for(;e<g;e++){d=cS[e].call(j,a,k,j.opts);if(d)return d}return cV(j,k),p.isFunction(j.opts.start)&&j.opts.start.call(a,j),p.fx.timer(p.extend(i,{anim:j,queue:j.opts.queue,elem:a})),j.progress(j.opts.progress).done(j.opts.done,j.opts.complete).fail(j.opts.fail).always(j.opts.always)}function cX(a,b){var c,d,e,f,g;for(c in a){d=p.camelCase(c),e=b[d],f=a[c],p.isArray(f)&&(e=f[1],f=a[c]=f[0]),c!==d&&(a[d]=f,delete a[c]),g=p.cssHooks[d];if(g&&"expand"in g){f=g.expand(f),delete a[d];for(c in f)c in a||(a[c]=f[c],b[c]=e)}else b[d]=e}}function cY(a,b,c){var d,e,f,g,h,i,j,k,l=this,m=a.style,n={},o=[],q=a.nodeType&&bZ(a);c.queue||(j=p._queueHooks(a,"fx"),j.unqueued==null&&(j.unqueued=0,k=j.empty.fire,j.empty.fire=function(){j.unqueued||k()}),j.unqueued++,l.always(function(){l.always(function(){j.unqueued--,p.queue(a,"fx").length||j.empty.fire()})})),a.nodeType===1&&("height"in b||"width"in b)&&(c.overflow=[m.overflow,m.overflowX,m.overflowY],p.css(a,"display")==="inline"&&p.css(a,"float")==="none"&&(!p.support.inlineBlockNeedsLayout||cc(a.nodeName)==="inline"?m.display="inline-block":m.zoom=1)),c.overflow&&(m.overflow="hidden",p.support.shrinkWrapBlocks||l.done(function(){m.overflow=c.overflow[0],m.overflowX=c.overflow[1],m.overflowY=c.overflow[2]}));for(d in b){f=b[d];if(cP.exec(f)){delete b[d];if(f===(q?"hide":"show"))continue;o.push(d)}}g=o.length;if(g){h=p._data(a,"fxshow")||p._data(a,"fxshow",{}),q?p(a).show():l.done(function(){p(a).hide()}),l.done(function(){var b;p.removeData(a,"fxshow",!0);for(b in n)p.style(a,b,n[b])});for(d=0;d<g;d++)e=o[d],i=l.createTween(e,q?h[e]:0),n[e]=h[e]||p.style(a,e),e in h||(h[e]=i.start,q&&(i.end=i.start,i.start=e==="width"||e==="height"?1:0))}}function cZ(a,b,c,d,e){return new cZ.prototype.init(a,b,c,d,e)}function c$(a,b){var c,d={height:a},e=0;b=b?1:0;for(;e<4;e+=2-b)c=bV[e],d["margin"+c]=d["padding"+c]=a;return b&&(d.opacity=d.width=a),d}function da(a){return p.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}var c,d,e=a.document,f=a.location,g=a.navigator,h=a.jQuery,i=a.$,j=Array.prototype.push,k=Array.prototype.slice,l=Array.prototype.indexOf,m=Object.prototype.toString,n=Object.prototype.hasOwnProperty,o=String.prototype.trim,p=function(a,b){return new p.fn.init(a,b,c)},q=/[\-+]?(?:\d*\.|)\d+(?:[eE][\-+]?\d+|)/.source,r=/\S/,s=/\s+/,t=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,u=/^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,v=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,w=/^[\],:{}\s]*$/,x=/(?:^|:|,)(?:\s*\[)+/g,y=/\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,z=/"[^"\\\r\n]*"|true|false|null|-?(?:\d\d*\.|)\d+(?:[eE][\-+]?\d+|)/g,A=/^-ms-/,B=/-([\da-z])/gi,C=function(a,b){return(b+"").toUpperCase()},D=function(){e.addEventListener?(e.removeEventListener("DOMContentLoaded",D,!1),p.ready()):e.readyState==="complete"&&(e.detachEvent("onreadystatechange",D),p.ready())},E={};p.fn=p.prototype={constructor:p,init:function(a,c,d){var f,g,h,i;if(!a)return this;if(a.nodeType)return this.context=this[0]=a,this.length=1,this;if(typeof a=="string"){a.charAt(0)==="<"&&a.charAt(a.length-1)===">"&&a.length>=3?f=[null,a,null]:f=u.exec(a);if(f&&(f[1]||!c)){if(f[1])return c=c instanceof p?c[0]:c,i=c&&c.nodeType?c.ownerDocument||c:e,a=p.parseHTML(f[1],i,!0),v.test(f[1])&&p.isPlainObject(c)&&this.attr.call(a,c,!0),p.merge(this,a);g=e.getElementById(f[2]);if(g&&g.parentNode){if(g.id!==f[2])return d.find(a);this.length=1,this[0]=g}return this.context=e,this.selector=a,this}return!c||c.jquery?(c||d).find(a):this.constructor(c).find(a)}return p.isFunction(a)?d.ready(a):(a.selector!==b&&(this.selector=a.selector,this.context=a.context),p.makeArray(a,this))},selector:"",jquery:"1.8.2",length:0,size:function(){return this.length},toArray:function(){return k.call(this)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=p.merge(this.constructor(),a);return d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")"),d},each:function(a,b){return p.each(this,a,b)},ready:function(a){return p.ready.promise().done(a),this},eq:function(a){return a=+a,a===-1?this.slice(a):this.slice(a,a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(k.apply(this,arguments),"slice",k.call(arguments).join(","))},map:function(a){return this.pushStack(p.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:j,sort:[].sort,splice:[].splice},p.fn.init.prototype=p.fn,p.extend=p.fn.extend=function(){var a,c,d,e,f,g,h=arguments[0]||{},i=1,j=arguments.length,k=!1;typeof h=="boolean"&&(k=h,h=arguments[1]||{},i=2),typeof h!="object"&&!p.isFunction(h)&&(h={}),j===i&&(h=this,--i);for(;i<j;i++)if((a=arguments[i])!=null)for(c in a){d=h[c],e=a[c];if(h===e)continue;k&&e&&(p.isPlainObject(e)||(f=p.isArray(e)))?(f?(f=!1,g=d&&p.isArray(d)?d:[]):g=d&&p.isPlainObject(d)?d:{},h[c]=p.extend(k,g,e)):e!==b&&(h[c]=e)}return h},p.extend({noConflict:function(b){return a.$===p&&(a.$=i),b&&a.jQuery===p&&(a.jQuery=h),p},isReady:!1,readyWait:1,holdReady:function(a){a?p.readyWait++:p.ready(!0)},ready:function(a){if(a===!0?--p.readyWait:p.isReady)return;if(!e.body)return setTimeout(p.ready,1);p.isReady=!0;if(a!==!0&&--p.readyWait>0)return;d.resolveWith(e,[p]),p.fn.trigger&&p(e).trigger("ready").off("ready")},isFunction:function(a){return p.type(a)==="function"},isArray:Array.isArray||function(a){return p.type(a)==="array"},isWindow:function(a){return a!=null&&a==a.window},isNumeric:function(a){return!isNaN(parseFloat(a))&&isFinite(a)},type:function(a){return a==null?String(a):E[m.call(a)]||"object"},isPlainObject:function(a){if(!a||p.type(a)!=="object"||a.nodeType||p.isWindow(a))return!1;try{if(a.constructor&&!n.call(a,"constructor")&&!n.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}var d;for(d in a);return d===b||n.call(a,d)},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},error:function(a){throw new Error(a)},parseHTML:function(a,b,c){var d;return!a||typeof a!="string"?null:(typeof b=="boolean"&&(c=b,b=0),b=b||e,(d=v.exec(a))?[b.createElement(d[1])]:(d=p.buildFragment([a],b,c?null:[]),p.merge([],(d.cacheable?p.clone(d.fragment):d.fragment).childNodes)))},parseJSON:function(b){if(!b||typeof b!="string")return null;b=p.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(w.test(b.replace(y,"@").replace(z,"]").replace(x,"")))return(new Function("return "+b))();p.error("Invalid JSON: "+b)},parseXML:function(c){var d,e;if(!c||typeof c!="string")return null;try{a.DOMParser?(e=new DOMParser,d=e.parseFromString(c,"text/xml")):(d=new ActiveXObject("Microsoft.XMLDOM"),d.async="false",d.loadXML(c))}catch(f){d=b}return(!d||!d.documentElement||d.getElementsByTagName("parsererror").length)&&p.error("Invalid XML: "+c),d},noop:function(){},globalEval:function(b){b&&r.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(A,"ms-").replace(B,C)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,c,d){var e,f=0,g=a.length,h=g===b||p.isFunction(a);if(d){if(h){for(e in a)if(c.apply(a[e],d)===!1)break}else for(;f<g;)if(c.apply(a[f++],d)===!1)break}else if(h){for(e in a)if(c.call(a[e],e,a[e])===!1)break}else for(;f<g;)if(c.call(a[f],f,a[f++])===!1)break;return a},trim:o&&!o.call("` + "\xEF\xBB\xBF" + ` ")?function(a){return a==null?"":o.call(a)}:function(a){return a==null?"":(a+"").replace(t,"")},makeArray:function(a,b){var c,d=b||[];return a!=null&&(c=p.type(a),a.length==null||c==="string"||c==="function"||c==="regexp"||p.isWindow(a)?j.call(d,a):p.merge(d,a)),d},inArray:function(a,b,c){var d;if(b){if(l)return l.call(b,a,c);d=b.length,c=c?c<0?Math.max(0,d+c):c:0;for(;c<d;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,c){var d=c.length,e=a.length,f=0;if(typeof d=="number")for(;f<d;f++)a[e++]=c[f];else while(c[f]!==b)a[e++]=c[f++];return a.length=e,a},grep:function(a,b,c){var d,e=[],f=0,g=a.length;c=!!c;for(;f<g;f++)d=!!b(a[f],f),c!==d&&e.push(a[f]);return e},map:function(a,c,d){var e,f,g=[],h=0,i=a.length,j=a instanceof p||i!==b&&typeof i=="number"&&(i>0&&a[0]&&a[i-1]||i===0||p.isArray(a));if(j)for(;h<i;h++)e=c(a[h],h,d),e!=null&&(g[g.length]=e);else for(f in a)e=c(a[f],f,d),e!=null&&(g[g.length]=e);return g.concat.apply([],g)},guid:1,proxy:function(a,c){var d,e,f;return typeof c=="string"&&(d=a[c],c=a,a=d),p.isFunction(a)?(e=k.call(arguments,2),f=function(){return a.apply(c,e.concat(k.call(arguments)))},f.guid=a.guid=a.guid||p.guid++,f):b},access:function(a,c,d,e,f,g,h){var i,j=d==null,k=0,l=a.length;if(d&&typeof d=="object"){for(k in d)p.access(a,c,k,d[k],1,g,e);f=1}else if(e!==b){i=h===b&&p.isFunction(e),j&&(i?(i=c,c=function(a,b,c){return i.call(p(a),c)}):(c.call(a,e),c=null));if(c)for(;k<l;k++)c(a[k],d,i?e.call(a[k],k,c(a[k],d)):e,h);f=1}return f?a:j?c.call(a):l?c(a[0],d):g},now:function(){return(new Date).getTime()}}),p.ready.promise=function(b){if(!d){d=p.Deferred();if(e.readyState==="complete")setTimeout(p.ready,1);else if(e.addEventListener)e.addEventListener("DOMContentLoaded",D,!1),a.addEventListener("load",p.ready,!1);else{e.attachEvent("onreadystatechange",D),a.attachEvent("onload",p.ready);var c=!1;try{c=a.frameElement==null&&e.documentElement}catch(f){}c&&c.doScroll&&function g(){if(!p.isReady){try{c.doScroll("left")}catch(a){return setTimeout(g,50)}p.ready()}}()}}return d.promise(b)},p.each("Boolean Number String Function Array Date RegExp Object".split(" "),function(a,b){E["[object "+b+"]"]=b.toLowerCase()}),c=p(e);var F={};p.Callbacks=function(a){a=typeof a=="string"?F[a]||G(a):p.extend({},a);var c,d,e,f,g,h,i=[],j=!a.once&&[],k=function(b){c=a.memory&&b,d=!0,h=f||0,f=0,g=i.length,e=!0;for(;i&&h<g;h++)if(i[h].apply(b[0],b[1])===!1&&a.stopOnFalse){c=!1;break}e=!1,i&&(j?j.length&&k(j.shift()):c?i=[]:l.disable())},l={add:function(){if(i){var b=i.length;(function d(b){p.each(b,function(b,c){var e=p.type(c);e==="function"&&(!a.unique||!l.has(c))?i.push(c):c&&c.length&&e!=="string"&&d(c)})})(arguments),e?g=i.length:c&&(f=b,k(c))}return this},remove:function(){return i&&p.each(arguments,function(a,b){var c;while((c=p.inArray(b,i,c))>-1)i.splice(c,1),e&&(c<=g&&g--,c<=h&&h--)}),this},has:function(a){return p.inArray(a,i)>-1},empty:function(){return i=[],this},disable:function(){return i=j=c=b,this},disabled:function(){return!i},lock:function(){return j=b,c||l.disable(),this},locked:function(){return!j},fireWith:function(a,b){return b=b||[],b=[a,b.slice?b.slice():b],i&&(!d||j)&&(e?j.push(b):k(b)),this},fire:function(){return l.fireWith(this,arguments),this},fired:function(){return!!d}};return l},p.extend({Deferred:function(a){var b=[["resolve","done",p.Callbacks("once memory"),"resolved"],["reject","fail",p.Callbacks("once memory"),"rejected"],["notify","progress",p.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return p.Deferred(function(c){p.each(b,function(b,d){var f=d[0],g=a[b];e[d[1]](p.isFunction(g)?function(){var a=g.apply(this,arguments);a&&p.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f+"With"](this===e?c:this,[a])}:c[f])}),a=null}).promise()},promise:function(a){return a!=null?p.extend(a,d):d}},e={};return d.pipe=d.then,p.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[a^1][2].disable,b[2][2].lock),e[f[0]]=g.fire,e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=k.call(arguments),d=c.length,e=d!==1||a&&p.isFunction(a.promise)?d:0,f=e===1?a:p.Deferred(),g=function(a,b,c){return function(d){b[a]=this,c[a]=arguments.length>1?k.call(arguments):d,c===h?f.notifyWith(b,c):--e||f.resolveWith(b,c)}},h,i,j;if(d>1){h=new Array(d),i=new Array(d),j=new Array(d);for(;b<d;b++)c[b]&&p.isFunction(c[b].promise)?c[b].promise().done(g(b,j,c)).fail(f.reject).progress(g(b,i,h)):--e}return e||f.resolveWith(j,c),f.promise()}}),p.support=function(){var b,c,d,f,g,h,i,j,k,l,m,n=e.createElement("div");n.setAttribute("className","t"),n.innerHTML="  <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",c=n.getElementsByTagName("*"),d=n.getElementsByTagName("a")[0],d.style.cssText="top:1px;float:left;opacity:.5";if(!c||!c.length)return{};f=e.createElement("select"),g=f.appendChild(e.createElement("option")),h=n.getElementsByTagName("input")[0],b={leadingWhitespace:n.firstChild.nodeType===3,tbody:!n.getElementsByTagName("tbody").length,htmlSerialize:!!n.getElementsByTagName("link").length,style:/top/.test(d.getAttribute("style")),hrefNormalized:d.getAttribute("href")==="/a",opacity:/^0.5/.test(d.style.opacity),cssFloat:!!d.style.cssFloat,checkOn:h.value==="on",optSelected:g.selected,getSetAttribute:n.className!=="t",enctype:!!e.createElement("form").enctype,html5Clone:e.createElement("nav").cloneNode(!0).outerHTML!=="<:nav></:nav>",boxModel:e.compatMode==="CSS1Compat",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0,boxSizingReliable:!0,pixelPosition:!1},h.checked=!0,b.noCloneChecked=h.cloneNode(!0).checked,f.disabled=!0,b.optDisabled=!g.disabled;try{delete n.test}catch(o){b.deleteExpando=!1}!n.addEventListener&&n.attachEvent&&n.fireEvent&&(n.attachEvent("onclick",m=function(){b.noCloneEvent=!1}),n.cloneNode(!0).fireEvent("onclick"),n.detachEvent("onclick",m)),h=e.createElement("input"),h.value="t",h.setAttribute("type","radio"),b.radioValue=h.value==="t",h.setAttribute("checked","checked"),h.setAttribute("name","t"),n.appendChild(h),i=e.createDocumentFragment(),i.appendChild(n.lastChild),b.checkClone=i.cloneNode(!0).cloneNode(!0).lastChild.checked,b.appendChecked=h.checked,i.removeChild(h),i.appendChild(n);if(n.attachEvent)for(k in{submit:!0,change:!0,focusin:!0})j="on"+k,l=j in n,l||(n.setAttribute(j,"return;"),l=typeof n[j]=="function"),b[k+"Bubbles"]=l;return p(function(){var c,d,f,g,h="padding:0;margin:0;border:0;display:block;overflow:hidden;",i=e.getElementsByTagName("body")[0];if(!i)return;c=e.createElement("div"),c.style.cssText="visibility:hidden;border:0;width:0;height:0;position:static;top:0;margin-top:1px",i.insertBefore(c,i.firstChild),d=e.createElement("div"),c.appendChild(d),d.innerHTML="<table><tr><td></td><td>t</td></tr></table>",f=d.getElementsByTagName("td"),f[0].style.cssText="padding:0;margin:0;border:0;display:none",l=f[0].offsetHeight===0,f[0].style.display="",f[1].style.display="none",b.reliableHiddenOffsets=l&&f[0].offsetHeight===0,d.innerHTML="",d.style.cssText="box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;",b.boxSizing=d.offsetWidth===4,b.doesNotIncludeMarginInBodyOffset=i.offsetTop!==1,a.getComputedStyle&&(b.pixelPosition=(a.getComputedStyle(d,null)||{}).top!=="1%",b.boxSizingReliable=(a.getComputedStyle(d,null)||{width:"4px"}).width==="4px",g=e.createElement("div"),g.style.cssText=d.style.cssText=h,g.style.marginRight=g.style.width="0",d.style.width="1px",d.appendChild(g),b.reliableMarginRight=!parseFloat((a.getComputedStyle(g,null)||{}).marginRight)),typeof d.style.zoom!="undefined"&&(d.innerHTML="",d.style.cssText=h+"width:1px;padding:1px;display:inline;zoom:1",b.inlineBlockNeedsLayout=d.offsetWidth===3,d.style.display="block",d.style.overflow="visible",d.innerHTML="<div></div>",d.firstChild.style.width="5px",b.shrinkWrapBlocks=d.offsetWidth!==3,c.style.zoom=1),i.removeChild(c),c=d=f=g=null}),i.removeChild(n),c=d=f=g=h=i=n=null,b}();var H=/(?:\{[\s\S]*\}|\[[\s\S]*\])$/,I=/([A-Z])/g;p.extend({cache:{},deletedIds:[],uuid:0,expando:"jQuery"+(p.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){return a=a.nodeType?p.cache[a[p.expando]]:a[p.expando],!!a&&!K(a)},data:function(a,c,d,e){if(!p.acceptData(a))return;var f,g,h=p.expando,i=typeof c=="string",j=a.nodeType,k=j?p.cache:a,l=j?a[h]:a[h]&&h;if((!l||!k[l]||!e&&!k[l].data)&&i&&d===b)return;l||(j?a[h]=l=p.deletedIds.pop()||p.guid++:l=h),k[l]||(k[l]={},j||(k[l].toJSON=p.noop));if(typeof c=="object"||typeof c=="function")e?k[l]=p.extend(k[l],c):k[l].data=p.extend(k[l].data,c);return f=k[l],e||(f.data||(f.data={}),f=f.data),d!==b&&(f[p.camelCase(c)]=d),i?(g=f[c],g==null&&(g=f[p.camelCase(c)])):g=f,g},removeData:function(a,b,c){if(!p.acceptData(a))return;var d,e,f,g=a.nodeType,h=g?p.cache:a,i=g?a[p.expando]:p.expando;if(!h[i])return;if(b){d=c?h[i]:h[i].data;if(d){p.isArray(b)||(b in d?b=[b]:(b=p.camelCase(b),b in d?b=[b]:b=b.split(" ")));for(e=0,f=b.length;e<f;e++)delete d[b[e]];if(!(c?K:p.isEmptyObject)(d))return}}if(!c){delete h[i].data;if(!K(h[i]))return}g?p.cleanData([a],!0):p.support.deleteExpando||h!=h.window?delete h[i]:h[i]=null},_data:function(a,b,c){return p.data(a,b,c,!0)},acceptData:function(a){var b=a.nodeName&&p.noData[a.nodeName.toLowerCase()];return!b||b!==!0&&a.getAttribute("classid")===b}}),p.fn.extend({data:function(a,c){var d,e,f,g,h,i=this[0],j=0,k=null;if(a===b){if(this.length){k=p.data(i);if(i.nodeType===1&&!p._data(i,"parsedAttrs")){f=i.attributes;for(h=f.length;j<h;j++)g=f[j].name,g.indexOf("data-")||(g=p.camelCase(g.substring(5)),J(i,g,k[g]));p._data(i,"parsedAttrs",!0)}}return k}return typeof a=="object"?this.each(function(){p.data(this,a)}):(d=a.split(".",2),d[1]=d[1]?"."+d[1]:"",e=d[1]+"!",p.access(this,function(c){if(c===b)return k=this.triggerHandler("getData"+e,[d[0]]),k===b&&i&&(k=p.data(i,a),k=J(i,a,k)),k===b&&d[1]?this.data(d[0]):k;d[1]=c,this.each(function(){var b=p(this);b.triggerHandler("setData"+e,d),p.data(this,a,c),b.triggerHandler("changeData"+e,d)})},null,c,arguments.length>1,null,!1))},removeData:function(a){return this.each(function(){p.removeData(this,a)})}}),p.extend({queue:function(a,b,c){var d;if(a)return b=(b||"fx")+"queue",d=p._data(a,b),c&&(!d||p.isArray(c)?d=p._data(a,b,p.makeArray(c)):d.push(c)),d||[]},dequeue:function(a,b){b=b||"fx";var c=p.queue(a,b),d=c.length,e=c.shift(),f=p._queueHooks(a,b),g=function(){p.dequeue(a,b)};e==="inprogress"&&(e=c.shift(),d--),e&&(b==="fx"&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return p._data(a,c)||p._data(a,c,{empty:p.Callbacks("once memory").add(function(){p.removeData(a,b+"queue",!0),p.removeData(a,c,!0)})})}}),p.fn.extend({queue:function(a,c){var d=2;return typeof a!="string"&&(c=a,a="fx",d--),arguments.length<d?p.queue(this[0],a):c===b?this:this.each(function(){var b=p.queue(this,a,c);p._queueHooks(this,a),a==="fx"&&b[0]!=="inprogress"&&p.dequeue(this,a)})},dequeue:function(a){return this.each(function(){p.dequeue(this,a)})},delay:function(a,b){return a=p.fx?p.fx.speeds[a]||a:a,b=b||"fx",this.queue(b,function(b,c){var d=setTimeout(b,a);c.stop=function(){clearTimeout(d)}})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,c){var d,e=1,f=p.Deferred(),g=this,h=this.length,i=function(){--e||f.resolveWith(g,[g])};typeof a!="string"&&(c=a,a=b),a=a||"fx";while(h--)d=p._data(g[h],a+"queueHooks"),d&&d.empty&&(e++,d.empty.add(i));return i(),f.promise(c)}});var L,M,N,O=/[\t\r\n]/g,P=/\r/g,Q=/^(?:button|input)$/i,R=/^(?:button|input|object|select|textarea)$/i,S=/^a(?:rea|)$/i,T=/^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,U=p.support.getSetAttribute;p.fn.extend({attr:function(a,b){return p.access(this,p.attr,a,b,arguments.length>1)},removeAttr:function(a){return this.each(function(){p.removeAttr(this,a)})},prop:function(a,b){return p.access(this,p.prop,a,b,arguments.length>1)},removeProp:function(a){return a=p.propFix[a]||a,this.each(function(){try{this[a]=b,delete this[a]}catch(c){}})},addClass:function(a){var b,c,d,e,f,g,h;if(p.isFunction(a))return this.each(function(b){p(this).addClass(a.call(this,b,this.className))});if(a&&typeof a=="string"){b=a.split(s);for(c=0,d=this.length;c<d;c++){e=this[c];if(e.nodeType===1)if(!e.className&&b.length===1)e.className=a;else{f=" "+e.className+" ";for(g=0,h=b.length;g<h;g++)f.indexOf(" "+b[g]+" ")<0&&(f+=b[g]+" ");e.className=p.trim(f)}}}return this},removeClass:function(a){var c,d,e,f,g,h,i;if(p.isFunction(a))return this.each(function(b){p(this).removeClass(a.call(this,b,this.className))});if(a&&typeof a=="string"||a===b){c=(a||"").split(s);for(h=0,i=this.length;h<i;h++){e=this[h];if(e.nodeType===1&&e.className){d=(" "+e.className+" ").replace(O," ");for(f=0,g=c.length;f<g;f++)while(d.indexOf(" "+c[f]+" ")>=0)d=d.replace(" "+c[f]+" "," ");e.className=a?p.trim(d):""}}}return this},toggleClass:function(a,b){var c=typeof a,d=typeof b=="boolean";return p.isFunction(a)?this.each(function(c){p(this).toggleClass(a.call(this,c,this.className,b),b)}):this.each(function(){if(c==="string"){var e,f=0,g=p(this),h=b,i=a.split(s);while(e=i[f++])h=d?h:!g.hasClass(e),g[h?"addClass":"removeClass"](e)}else if(c==="undefined"||c==="boolean")this.className&&p._data(this,"__className__",this.className),this.className=this.className||a===!1?"":p._data(this,"__className__")||""})},hasClass:function(a){var b=" "+a+" ",c=0,d=this.length;for(;c<d;c++)if(this[c].nodeType===1&&(" "+this[c].className+" ").replace(O," ").indexOf(b)>=0)return!0;return!1},val:function(a){var c,d,e,f=this[0];if(!arguments.length){if(f)return c=p.valHooks[f.type]||p.valHooks[f.nodeName.toLowerCase()],c&&"get"in c&&(d=c.get(f,"value"))!==b?d:(d=f.value,typeof d=="string"?d.replace(P,""):d==null?"":d);return}return e=p.isFunction(a),this.each(function(d){var f,g=p(this);if(this.nodeType!==1)return;e?f=a.call(this,d,g.val()):f=a,f==null?f="":typeof f=="number"?f+="":p.isArray(f)&&(f=p.map(f,function(a){return a==null?"":a+""})),c=p.valHooks[this.type]||p.valHooks[this.nodeName.toLowerCase()];if(!c||!("set"in c)||c.set(this,f,"value")===b)this.value=f})}}),p.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c,d,e,f=a.selectedIndex,g=[],h=a.options,i=a.type==="select-one";if(f<0)return null;c=i?f:0,d=i?f+1:h.length;for(;c<d;c++){e=h[c];if(e.selected&&(p.support.optDisabled?!e.disabled:e.getAttribute("disabled")===null)&&(!e.parentNode.disabled||!p.nodeName(e.parentNode,"optgroup"))){b=p(e).val();if(i)return b;g.push(b)}}return i&&!g.length&&h.length?p(h[f]).val():g},set:function(a,b){var c=p.makeArray(b);return p(a).find("option").each(function(){this.selected=p.inArray(p(this).val(),c)>=0}),c.length||(a.selectedIndex=-1),c}}},attrFn:{},attr:function(a,c,d,e){var f,g,h,i=a.nodeType;if(!a||i===3||i===8||i===2)return;if(e&&p.isFunction(p.fn[c]))return p(a)[c](d);if(typeof a.getAttribute=="undefined")return p.prop(a,c,d);h=i!==1||!p.isXMLDoc(a),h&&(c=c.toLowerCase(),g=p.attrHooks[c]||(T.test(c)?M:L));if(d!==b){if(d===null){p.removeAttr(a,c);return}return g&&"set"in g&&h&&(f=g.set(a,d,c))!==b?f:(a.setAttribute(c,d+""),d)}return g&&"get"in g&&h&&(f=g.get(a,c))!==null?f:(f=a.getAttribute(c),f===null?b:f)},removeAttr:function(a,b){var c,d,e,f,g=0;if(b&&a.nodeType===1){d=b.split(s);for(;g<d.length;g++)e=d[g],e&&(c=p.propFix[e]||e,f=T.test(e),f||p.attr(a,e,""),a.removeAttribute(U?e:c),f&&c in a&&(a[c]=!1))}},attrHooks:{type:{set:function(a,b){if(Q.test(a.nodeName)&&a.parentNode)p.error("type property can't be changed");else if(!p.support.radioValue&&b==="radio"&&p.nodeName(a,"input")){var c=a.value;return a.setAttribute("type",b),c&&(a.value=c),b}}},value:{get:function(a,b){return L&&p.nodeName(a,"button")?L.get(a,b):b in a?a.value:null},set:function(a,b,c){if(L&&p.nodeName(a,"button"))return L.set(a,b,c);a.value=b}}},propFix:{tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},prop:function(a,c,d){var e,f,g,h=a.nodeType;if(!a||h===3||h===8||h===2)return;return g=h!==1||!p.isXMLDoc(a),g&&(c=p.propFix[c]||c,f=p.propHooks[c]),d!==b?f&&"set"in f&&(e=f.set(a,d,c))!==b?e:a[c]=d:f&&"get"in f&&(e=f.get(a,c))!==null?e:a[c]},propHooks:{tabIndex:{get:function(a){var c=a.getAttributeNode("tabindex");return c&&c.specified?parseInt(c.value,10):R.test(a.nodeName)||S.test(a.nodeName)&&a.href?0:b}}}}),M={get:function(a,c){var d,e=p.prop(a,c);return e===!0||typeof e!="boolean"&&(d=a.getAttributeNode(c))&&d.nodeValue!==!1?c.toLowerCase():b},set:function(a,b,c){var d;return b===!1?p.removeAttr(a,c):(d=p.propFix[c]||c,d in a&&(a[d]=!0),a.setAttribute(c,c.toLowerCase())),c}},U||(N={name:!0,id:!0,coords:!0},L=p.valHooks.button={get:function(a,c){var d;return d=a.getAttributeNode(c),d&&(N[c]?d.value!=="":d.specified)?d.value:b},set:function(a,b,c){var d=a.getAttributeNode(c);return d||(d=e.createAttribute(c),a.setAttributeNode(d)),d.value=b+""}},p.each(["width","height"],function(a,b){p.attrHooks[b]=p.extend(p.attrHooks[b],{set:function(a,c){if(c==="")return a.setAttribute(b,"auto"),c}})}),p.attrHooks.contenteditable={get:L.get,set:function(a,b,c){b===""&&(b="false"),L.set(a,b,c)}}),p.support.hrefNormalized||p.each(["href","src","width","height"],function(a,c){p.attrHooks[c]=p.extend(p.attrHooks[c],{get:function(a){var d=a.getAttribute(c,2);return d===null?b:d}})}),p.support.style||(p.attrHooks.style={get:function(a){return a.style.cssText.toLowerCase()||b},set:function(a,b){return a.style.cssText=b+""}}),p.support.optSelected||(p.propHooks.selected=p.extend(p.propHooks.selected,{get:function(a){var b=a.parentNode;return b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex),null}})),p.support.enctype||(p.propFix.enctype="encoding"),p.support.checkOn||p.each(["radio","checkbox"],function(){p.valHooks[this]={get:function(a){return a.getAttribute("value")===null?"on":a.value}}}),p.each(["radio","checkbox"],function(){p.valHooks[this]=p.extend(p.valHooks[this],{set:function(a,b){if(p.isArray(b))return a.checked=p.inArray(p(a).val(),b)>=0}})});var V=/^(?:textarea|input|select)$/i,W=/^([^\.]*|)(?:\.(.+)|)$/,X=/(?:^|\s)hover(\.\S+|)\b/,Y=/^key/,Z=/^(?:mouse|contextmenu)|click/,$=/^(?:focusinfocus|focusoutblur)$/,_=function(a){return p.event.special.hover?a:a.replace(X,"mouseenter$1 mouseleave$1")};p.event={add:function(a,c,d,e,f){var g,h,i,j,k,l,m,n,o,q,r;if(a.nodeType===3||a.nodeType===8||!c||!d||!(g=p._data(a)))return;d.handler&&(o=d,d=o.handler,f=o.selector),d.guid||(d.guid=p.guid++),i=g.events,i||(g.events=i={}),h=g.handle,h||(g.handle=h=function(a){return typeof p!="undefined"&&(!a||p.event.triggered!==a.type)?p.event.dispatch.apply(h.elem,arguments):b},h.elem=a),c=p.trim(_(c)).split(" ");for(j=0;j<c.length;j++){k=W.exec(c[j])||[],l=k[1],m=(k[2]||"").split(".").sort(),r=p.event.special[l]||{},l=(f?r.delegateType:r.bindType)||l,r=p.event.special[l]||{},n=p.extend({type:l,origType:k[1],data:e,handler:d,guid:d.guid,selector:f,needsContext:f&&p.expr.match.needsContext.test(f),namespace:m.join(".")},o),q=i[l];if(!q){q=i[l]=[],q.delegateCount=0;if(!r.setup||r.setup.call(a,e,m,h)===!1)a.addEventListener?a.addEventListener(l,h,!1):a.attachEvent&&a.attachEvent("on"+l,h)}r.add&&(r.add.call(a,n),n.handler.guid||(n.handler.guid=d.guid)),f?q.splice(q.delegateCount++,0,n):q.push(n),p.event.global[l]=!0}a=null},global:{},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,n,o,q,r=p.hasData(a)&&p._data(a);if(!r||!(m=r.events))return;b=p.trim(_(b||"")).split(" ");for(f=0;f<b.length;f++){g=W.exec(b[f])||[],h=i=g[1],j=g[2];if(!h){for(h in m)p.event.remove(a,h+b[f],c,d,!0);continue}n=p.event.special[h]||{},h=(d?n.delegateType:n.bindType)||h,o=m[h]||[],k=o.length,j=j?new RegExp("(^|\\.)"+j.split(".").sort().join("\\.(?:.*\\.|)")+"(\\.|$)"):null;for(l=0;l<o.length;l++)q=o[l],(e||i===q.origType)&&(!c||c.guid===q.guid)&&(!j||j.test(q.namespace))&&(!d||d===q.selector||d==="**"&&q.selector)&&(o.splice(l--,1),q.selector&&o.delegateCount--,n.remove&&n.remove.call(a,q));o.length===0&&k!==o.length&&((!n.teardown||n.teardown.call(a,j,r.handle)===!1)&&p.removeEvent(a,h,r.handle),delete m[h])}p.isEmptyObject(m)&&(delete r.handle,p.removeData(a,"events",!0))},customEvent:{getData:!0,setData:!0,changeData:!0},trigger:function(c,d,f,g){if(!f||f.nodeType!==3&&f.nodeType!==8){var h,i,j,k,l,m,n,o,q,r,s=c.type||c,t=[];if($.test(s+p.event.triggered))return;s.indexOf("!")>=0&&(s=s.slice(0,-1),i=!0),s.indexOf(".")>=0&&(t=s.split("."),s=t.shift(),t.sort());if((!f||p.event.customEvent[s])&&!p.event.global[s])return;c=typeof c=="object"?c[p.expando]?c:new p.Event(s,c):new p.Event(s),c.type=s,c.isTrigger=!0,c.exclusive=i,c.namespace=t.join("."),c.namespace_re=c.namespace?new RegExp("(^|\\.)"+t.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,m=s.indexOf(":")<0?"on"+s:"";if(!f){h=p.cache;for(j in h)h[j].events&&h[j].events[s]&&p.event.trigger(c,d,h[j].handle.elem,!0);return}c.result=b,c.target||(c.target=f),d=d!=null?p.makeArray(d):[],d.unshift(c),n=p.event.special[s]||{};if(n.trigger&&n.trigger.apply(f,d)===!1)return;q=[[f,n.bindType||s]];if(!g&&!n.noBubble&&!p.isWindow(f)){r=n.delegateType||s,k=$.test(r+s)?f:f.parentNode;for(l=f;k;k=k.parentNode)q.push([k,r]),l=k;l===(f.ownerDocument||e)&&q.push([l.defaultView||l.parentWindow||a,r])}for(j=0;j<q.length&&!c.isPropagationStopped();j++)k=q[j][0],c.type=q[j][1],o=(p._data(k,"events")||{})[c.type]&&p._data(k,"handle"),o&&o.apply(k,d),o=m&&k[m],o&&p.acceptData(k)&&o.apply&&o.apply(k,d)===!1&&c.preventDefault();return c.type=s,!g&&!c.isDefaultPrevented()&&(!n._default||n._default.apply(f.ownerDocument,d)===!1)&&(s!=="click"||!p.nodeName(f,"a"))&&p.acceptData(f)&&m&&f[s]&&(s!=="focus"&&s!=="blur"||c.target.offsetWidth!==0)&&!p.isWindow(f)&&(l=f[m],l&&(f[m]=null),p.event.triggered=s,f[s](),p.event.triggered=b,l&&(f[m]=l)),c.result}return},dispatch:function(c){c=p.event.fix(c||a.event);var d,e,f,g,h,i,j,l,m,n,o=(p._data(this,"events")||{})[c.type]||[],q=o.delegateCount,r=k.call(arguments),s=!c.exclusive&&!c.namespace,t=p.event.special[c.type]||{},u=[];r[0]=c,c.delegateTarget=this;if(t.preDispatch&&t.preDispatch.call(this,c)===!1)return;if(q&&(!c.button||c.type!=="click"))for(f=c.target;f!=this;f=f.parentNode||this)if(f.disabled!==!0||c.type!=="click"){h={},j=[];for(d=0;d<q;d++)l=o[d],m=l.selector,h[m]===b&&(h[m]=l.needsContext?p(m,this).index(f)>=0:p.find(m,this,null,[f]).length),h[m]&&j.push(l);j.length&&u.push({elem:f,matches:j})}o.length>q&&u.push({elem:this,matches:o.slice(q)});for(d=0;d<u.length&&!c.isPropagationStopped();d++){i=u[d],c.currentTarget=i.elem;for(e=0;e<i.matches.length&&!c.isImmediatePropagationStopped();e++){l=i.matches[e];if(s||!c.namespace&&!l.namespace||c.namespace_re&&c.namespace_re.test(l.namespace))c.data=l.data,c.handleObj=l,g=((p.event.special[l.origType]||{}).handle||l.handler).apply(i.elem,r),g!==b&&(c.result=g,g===!1&&(c.preventDefault(),c.stopPropagation()))}}return t.postDispatch&&t.postDispatch.call(this,c),c.result},props:"attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(a,b){return a.which==null&&(a.which=b.charCode!=null?b.charCode:b.keyCode),a}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(a,c){var d,f,g,h=c.button,i=c.fromElement;return a.pageX==null&&c.clientX!=null&&(d=a.target.ownerDocument||e,f=d.documentElement,g=d.body,a.pageX=c.clientX+(f&&f.scrollLeft||g&&g.scrollLeft||0)-(f&&f.clientLeft||g&&g.clientLeft||0),a.pageY=c.clientY+(f&&f.scrollTop||g&&g.scrollTop||0)-(f&&f.clientTop||g&&g.clientTop||0)),!a.relatedTarget&&i&&(a.relatedTarget=i===a.target?c.toElement:i),!a.which&&h!==b&&(a.which=h&1?1:h&2?3:h&4?2:0),a}},fix:function(a){if(a[p.expando])return a;var b,c,d=a,f=p.event.fixHooks[a.type]||{},g=f.props?this.props.concat(f.props):this.props;a=p.Event(d);for(b=g.length;b;)c=g[--b],a[c]=d[c];return a.target||(a.target=d.srcElement||e),a.target.nodeType===3&&(a.target=a.target.parentNode),a.metaKey=!!a.metaKey,f.filter?f.filter(a,d):a},special:{load:{noBubble:!0},focus:{delegateType:"focusin"},blur:{delegateType:"focusout"},beforeunload:{setup:function(a,b,c){p.isWindow(this)&&(this.onbeforeunload=c)},teardown:function(a,b){this.onbeforeunload===b&&(this.onbeforeunload=null)}}},simulate:function(a,b,c,d){var e=p.extend(new p.Event,c,{type:a,isSimulated:!0,originalEvent:{}});d?p.event.trigger(e,null,b):p.event.dispatch.call(b,e),e.isDefaultPrevented()&&c.preventDefault()}},p.event.handle=p.event.dispatch,p.removeEvent=e.removeEventListener?function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c,!1)}:function(a,b,c){var d="on"+b;a.detachEvent&&(typeof a[d]=="undefined"&&(a[d]=null),a.detachEvent(d,c))},p.Event=function(a,b){if(this instanceof p.Event)a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||a.returnValue===!1||a.getPreventDefault&&a.getPreventDefault()?bb:ba):this.type=a,b&&p.extend(this,b),this.timeStamp=a&&a.timeStamp||p.now(),this[p.expando]=!0;else return new p.Event(a,b)},p.Event.prototype={preventDefault:function(){this.isDefaultPrevented=bb;var a=this.originalEvent;if(!a)return;a.preventDefault?a.preventDefault():a.returnValue=!1},stopPropagation:function(){this.isPropagationStopped=bb;var a=this.originalEvent;if(!a)return;a.stopPropagation&&a.stopPropagation(),a.cancelBubble=!0},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=bb,this.stopPropagation()},isDefaultPrevented:ba,isPropagationStopped:ba,isImmediatePropagationStopped:ba},p.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){p.event.special[a]={delegateType:b,bindType:b,handle:function(a){var c,d=this,e=a.relatedTarget,f=a.handleObj,g=f.selector;if(!e||e!==d&&!p.contains(d,e))a.type=f.origType,c=f.handler.apply(this,arguments),a.type=b;return c}}}),p.support.submitBubbles||(p.event.special.submit={setup:function(){if(p.nodeName(this,"form"))return!1;p.event.add(this,"click._submit keypress._submit",function(a){var c=a.target,d=p.nodeName(c,"input")||p.nodeName(c,"button")?c.form:b;d&&!p._data(d,"_submit_attached")&&(p.event.add(d,"submit._submit",function(a){a._submit_bubble=!0}),p._data(d,"_submit_attached",!0))})},postDispatch:function(a){a._submit_bubble&&(delete a._submit_bubble,this.parentNode&&!a.isTrigger&&p.event.simulate("submit",this.parentNode,a,!0))},teardown:function(){if(p.nodeName(this,"form"))return!1;p.event.remove(this,"._submit")}}),p.support.changeBubbles||(p.event.special.change={setup:function(){if(V.test(this.nodeName)){if(this.type==="checkbox"||this.type==="radio")p.event.add(this,"propertychange._change",function(a){a.originalEvent.propertyName==="checked"&&(this._just_changed=!0)}),p.event.add(this,"click._change",function(a){this._just_changed&&!a.isTrigger&&(this._just_changed=!1),p.event.simulate("change",this,a,!0)});return!1}p.event.add(this,"beforeactivate._change",function(a){var b=a.target;V.test(b.nodeName)&&!p._data(b,"_change_attached")&&(p.event.add(b,"change._change",function(a){this.parentNode&&!a.isSimulated&&!a.isTrigger&&p.event.simulate("change",this.parentNode,a,!0)}),p._data(b,"_change_attached",!0))})},handle:function(a){var b=a.target;if(this!==b||a.isSimulated||a.isTrigger||b.type!=="radio"&&b.type!=="checkbox")return a.handleObj.handler.apply(this,arguments)},teardown:function(){return p.event.remove(this,"._change"),!V.test(this.nodeName)}}),p.support.focusinBubbles||p.each({focus:"focusin",blur:"focusout"},function(a,b){var c=0,d=function(a){p.event.simulate(b,a.target,p.event.fix(a),!0)};p.event.special[b]={setup:function(){c++===0&&e.addEventListener(a,d,!0)},teardown:function(){--c===0&&e.removeEventListener(a,d,!0)}}}),p.fn.extend({on:function(a,c,d,e,f){var g,h;if(typeof a=="object"){typeof c!="string"&&(d=d||c,c=b);for(h in a)this.on(h,c,d,a[h],f);return this}d==null&&e==null?(e=c,d=c=b):e==null&&(typeof c=="string"?(e=d,d=b):(e=d,d=c,c=b));if(e===!1)e=ba;else if(!e)return this;return f===1&&(g=e,e=function(a){return p().off(a),g.apply(this,arguments)},e.guid=g.guid||(g.guid=p.guid++)),this.each(function(){p.event.add(this,a,e,d,c)})},one:function(a,b,c,d){return this.on(a,b,c,d,1)},off:function(a,c,d){var e,f;if(a&&a.preventDefault&&a.handleObj)return e=a.handleObj,p(a.delegateTarget).off(e.namespace?e.origType+"."+e.namespace:e.origType,e.selector,e.handler),this;if(typeof a=="object"){for(f in a)this.off(f,c,a[f]);return this}if(c===!1||typeof c=="function")d=c,c=b;return d===!1&&(d=ba),this.each(function(){p.event.remove(this,a,d,c)})},bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},live:function(a,b,c){return p(this.context).on(a,this.selector,b,c),this},die:function(a,b){return p(this.context).off(a,this.selector||"**",b),this},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return arguments.length===1?this.off(a,"**"):this.off(b,a||"**",c)},trigger:function(a,b){return this.each(function(){p.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0])return p.event.trigger(a,b,this[0],!0)},toggle:function(a){var b=arguments,c=a.guid||p.guid++,d=0,e=function(c){var e=(p._data(this,"lastToggle"+a.guid)||0)%d;return p._data(this,"lastToggle"+a.guid,e+1),c.preventDefault(),b[e].apply(this,arguments)||!1};e.guid=c;while(d<b.length)b[d++].guid=c;return this.click(e)},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}}),p.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(a,b){p.fn[b]=function(a,c){return c==null&&(c=a,a=null),arguments.length>0?this.on(b,null,a,c):this.trigger(b)},Y.test(b)&&(p.event.fixHooks[b]=p.event.keyHooks),Z.test(b)&&(p.event.fixHooks[b]=p.event.mouseHooks)}),function(a,b){function bc(a,b,c,d){c=c||[],b=b||r;var e,f,i,j,k=b.nodeType;if(!a||typeof a!="string")return c;if(k!==1&&k!==9)return[];i=g(b);if(!i&&!d)if(e=P.exec(a))if(j=e[1]){if(k===9){f=b.getElementById(j);if(!f||!f.parentNode)return c;if(f.id===j)return c.push(f),c}else if(b.ownerDocument&&(f=b.ownerDocument.getElementById(j))&&h(b,f)&&f.id===j)return c.push(f),c}else{if(e[2])return w.apply(c,x.call(b.getElementsByTagName(a),0)),c;if((j=e[3])&&_&&b.getElementsByClassName)return w.apply(c,x.call(b.getElementsByClassName(j),0)),c}return bp(a.replace(L,"$1"),b,c,d,i)}function bd(a){return function(b){var c=b.nodeName.toLowerCase();return c==="input"&&b.type===a}}function be(a){return function(b){var c=b.nodeName.toLowerCase();return(c==="input"||c==="button")&&b.type===a}}function bf(a){return z(function(b){return b=+b,z(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function bg(a,b,c){if(a===b)return c;var d=a.nextSibling;while(d){if(d===b)return-1;d=d.nextSibling}return 1}function bh(a,b){var c,d,f,g,h,i,j,k=C[o][a];if(k)return b?0:k.slice(0);h=a,i=[],j=e.preFilter;while(h){if(!c||(d=M.exec(h)))d&&(h=h.slice(d[0].length)),i.push(f=[]);c=!1;if(d=N.exec(h))f.push(c=new q(d.shift())),h=h.slice(c.length),c.type=d[0].replace(L," ");for(g in e.filter)(d=W[g].exec(h))&&(!j[g]||(d=j[g](d,r,!0)))&&(f.push(c=new q(d.shift())),h=h.slice(c.length),c.type=g,c.matches=d);if(!c)break}return b?h.length:h?bc.error(a):C(a,i).slice(0)}function bi(a,b,d){var e=b.dir,f=d&&b.dir==="parentNode",g=u++;return b.first?function(b,c,d){while(b=b[e])if(f||b.nodeType===1)return a(b,c,d)}:function(b,d,h){if(!h){var i,j=t+" "+g+" ",k=j+c;while(b=b[e])if(f||b.nodeType===1){if((i=b[o])===k)return b.sizset;if(typeof i=="string"&&i.indexOf(j)===0){if(b.sizset)return b}else{b[o]=k;if(a(b,d,h))return b.sizset=!0,b;b.sizset=!1}}}else while(b=b[e])if(f||b.nodeType===1)if(a(b,d,h))return b}}function bj(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function bk(a,b,c,d,e){var f,g=[],h=0,i=a.length,j=b!=null;for(;h<i;h++)if(f=a[h])if(!c||c(f,d,e))g.push(f),j&&b.push(h);return g}function bl(a,b,c,d,e,f){return d&&!d[o]&&(d=bl(d)),e&&!e[o]&&(e=bl(e,f)),z(function(f,g,h,i){if(f&&e)return;var j,k,l,m=[],n=[],o=g.length,p=f||bo(b||"*",h.nodeType?[h]:h,[],f),q=a&&(f||!b)?bk(p,m,a,h,i):p,r=c?e||(f?a:o||d)?[]:g:q;c&&c(q,r,h,i);if(d){l=bk(r,n),d(l,[],h,i),j=l.length;while(j--)if(k=l[j])r[n[j]]=!(q[n[j]]=k)}if(f){j=a&&r.length;while(j--)if(k=r[j])f[m[j]]=!(g[m[j]]=k)}else r=bk(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):w.apply(g,r)})}function bm(a){var b,c,d,f=a.length,g=e.relative[a[0].type],h=g||e.relative[" "],i=g?1:0,j=bi(function(a){return a===b},h,!0),k=bi(function(a){return y.call(b,a)>-1},h,!0),m=[function(a,c,d){return!g&&(d||c!==l)||((b=c).nodeType?j(a,c,d):k(a,c,d))}];for(;i<f;i++)if(c=e.relative[a[i].type])m=[bi(bj(m),c)];else{c=e.filter[a[i].type].apply(null,a[i].matches);if(c[o]){d=++i;for(;d<f;d++)if(e.relative[a[d].type])break;return bl(i>1&&bj(m),i>1&&a.slice(0,i-1).join("").replace(L,"$1"),c,i<d&&bm(a.slice(i,d)),d<f&&bm(a=a.slice(d)),d<f&&a.join(""))}m.push(c)}return bj(m)}function bn(a,b){var d=b.length>0,f=a.length>0,g=function(h,i,j,k,m){var n,o,p,q=[],s=0,u="0",x=h&&[],y=m!=null,z=l,A=h||f&&e.find.TAG("*",m&&i.parentNode||i),B=t+=z==null?1:Math.E;y&&(l=i!==r&&i,c=g.el);for(;(n=A[u])!=null;u++){if(f&&n){for(o=0;p=a[o];o++)if(p(n,i,j)){k.push(n);break}y&&(t=B,c=++g.el)}d&&((n=!p&&n)&&s--,h&&x.push(n))}s+=u;if(d&&u!==s){for(o=0;p=b[o];o++)p(x,q,i,j);if(h){if(s>0)while(u--)!x[u]&&!q[u]&&(q[u]=v.call(k));q=bk(q)}w.apply(k,q),y&&!h&&q.length>0&&s+b.length>1&&bc.uniqueSort(k)}return y&&(t=B,l=z),x};return g.el=0,d?z(g):g}function bo(a,b,c,d){var e=0,f=b.length;for(;e<f;e++)bc(a,b[e],c,d);return c}function bp(a,b,c,d,f){var g,h,j,k,l,m=bh(a),n=m.length;if(!d&&m.length===1){h=m[0]=m[0].slice(0);if(h.length>2&&(j=h[0]).type==="ID"&&b.nodeType===9&&!f&&e.relative[h[1].type]){b=e.find.ID(j.matches[0].replace(V,""),b,f)[0];if(!b)return c;a=a.slice(h.shift().length)}for(g=W.POS.test(a)?-1:h.length-1;g>=0;g--){j=h[g];if(e.relative[k=j.type])break;if(l=e.find[k])if(d=l(j.matches[0].replace(V,""),R.test(h[0].type)&&b.parentNode||b,f)){h.splice(g,1),a=d.length&&h.join("");if(!a)return w.apply(c,x.call(d,0)),c;break}}}return i(a,m)(d,b,f,c,R.test(a)),c}function bq(){}var c,d,e,f,g,h,i,j,k,l,m=!0,n="undefined",o=("sizcache"+Math.random()).replace(".",""),q=String,r=a.document,s=r.documentElement,t=0,u=0,v=[].pop,w=[].push,x=[].slice,y=[].indexOf||function(a){var b=0,c=this.length;for(;b<c;b++)if(this[b]===a)return b;return-1},z=function(a,b){return a[o]=b==null||b,a},A=function(){var a={},b=[];return z(function(c,d){return b.push(c)>e.cacheLength&&delete a[b.shift()],a[c]=d},a)},B=A(),C=A(),D=A(),E="[\\x20\\t\\r\\n\\f]",F="(?:\\\\.|[-\\w]|[^\\x00-\\xa0])+",G=F.replace("w","w#"),H="([*^$|!~]?=)",I="\\["+E+"*("+F+")"+E+"*(?:"+H+E+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+G+")|)|)"+E+"*\\]",J=":("+F+")(?:\\((?:(['\"])((?:\\\\.|[^\\\\])*?)\\2|([^()[\\]]*|(?:(?:"+I+")|[^:]|\\\\.)*|.*))\\)|)",K=":(even|odd|eq|gt|lt|nth|first|last)(?:\\("+E+"*((?:-\\d)?\\d*)"+E+"*\\)|)(?=[^-]|$)",L=new RegExp("^"+E+"+|((?:^|[^\\\\])(?:\\\\.)*)"+E+"+$","g"),M=new RegExp("^"+E+"*,"+E+"*"),N=new RegExp("^"+E+"*([\\x20\\t\\r\\n\\f>+~])"+E+"*"),O=new RegExp(J),P=/^(?:#([\w\-]+)|(\w+)|\.([\w\-]+))$/,Q=/^:not/,R=/[\x20\t\r\n\f]*[+~]/,S=/:not\($/,T=/h\d/i,U=/input|select|textarea|button/i,V=/\\(?!\\)/g,W={ID:new RegExp("^#("+F+")"),CLASS:new RegExp("^\\.("+F+")"),NAME:new RegExp("^\\[name=['\"]?("+F+")['\"]?\\]"),TAG:new RegExp("^("+F.replace("w","w*")+")"),ATTR:new RegExp("^"+I),PSEUDO:new RegExp("^"+J),POS:new RegExp(K,"i"),CHILD:new RegExp("^:(only|nth|first|last)-child(?:\\("+E+"*(even|odd|(([+-]|)(\\d*)n|)"+E+"*(?:([+-]|)"+E+"*(\\d+)|))"+E+"*\\)|)","i"),needsContext:new RegExp("^"+E+"*[>+~]|"+K,"i")},X=function(a){var b=r.createElement("div");try{return a(b)}catch(c){return!1}finally{b=null}},Y=X(function(a){return a.appendChild(r.createComment("")),!a.getElementsByTagName("*").length}),Z=X(function(a){return a.innerHTML="<a href='#'></a>",a.firstChild&&typeof a.firstChild.getAttribute!==n&&a.firstChild.getAttribute("href")==="#"}),$=X(function(a){a.innerHTML="<select></select>";var b=typeof a.lastChild.getAttribute("multiple");return b!=="boolean"&&b!=="string"}),_=X(function(a){return a.innerHTML="<div class='hidden e'></div><div class='hidden'></div>",!a.getElementsByClassName||!a.getElementsByClassName("e").length?!1:(a.lastChild.className="e",a.getElementsByClassName("e").length===2)}),ba=X(function(a){a.id=o+0,a.innerHTML="<a name='"+o+"'></a><div name='"+o+"'></div>",s.insertBefore(a,s.firstChild);var b=r.getElementsByName&&r.getElementsByName(o).length===2+r.getElementsByName(o+0).length;return d=!r.getElementById(o),s.removeChild(a),b});try{x.call(s.childNodes,0)[0].nodeType}catch(bb){x=function(a){var b,c=[];for(;b=this[a];a++)c.push(b);return c}}bc.matches=function(a,b){return bc(a,null,null,b)},bc.matchesSelector=function(a,b){return bc(b,null,null,[a]).length>0},f=bc.getText=function(a){var b,c="",d=0,e=a.nodeType;if(e){if(e===1||e===9||e===11){if(typeof a.textContent=="string")return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=f(a)}else if(e===3||e===4)return a.nodeValue}else for(;b=a[d];d++)c+=f(b);return c},g=bc.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?b.nodeName!=="HTML":!1},h=bc.contains=s.contains?function(a,b){var c=a.nodeType===9?a.documentElement:a,d=b&&b.parentNode;return a===d||!!(d&&d.nodeType===1&&c.contains&&c.contains(d))}:s.compareDocumentPosition?function(a,b){return b&&!!(a.compareDocumentPosition(b)&16)}:function(a,b){while(b=b.parentNode)if(b===a)return!0;return!1},bc.attr=function(a,b){var c,d=g(a);return d||(b=b.toLowerCase()),(c=e.attrHandle[b])?c(a):d||$?a.getAttribute(b):(c=a.getAttributeNode(b),c?typeof a[b]=="boolean"?a[b]?b:null:c.specified?c.value:null:null)},e=bc.selectors={cacheLength:50,createPseudo:z,match:W,attrHandle:Z?{}:{href:function(a){return a.getAttribute("href",2)},type:function(a){return a.getAttribute("type")}},find:{ID:d?function(a,b,c){if(typeof b.getElementById!==n&&!c){var d=b.getElementById(a);return d&&d.parentNode?[d]:[]}}:function(a,c,d){if(typeof c.getElementById!==n&&!d){var e=c.getElementById(a);return e?e.id===a||typeof e.getAttributeNode!==n&&e.getAttributeNode("id").value===a?[e]:b:[]}},TAG:Y?function(a,b){if(typeof b.getElementsByTagName!==n)return b.getElementsByTagName(a)}:function(a,b){var c=b.getElementsByTagName(a);if(a==="*"){var d,e=[],f=0;for(;d=c[f];f++)d.nodeType===1&&e.push(d);return e}return c},NAME:ba&&function(a,b){if(typeof b.getElementsByName!==n)return b.getElementsByName(name)},CLASS:_&&function(a,b,c){if(typeof b.getElementsByClassName!==n&&!c)return b.getElementsByClassName(a)}},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(V,""),a[3]=(a[4]||a[5]||"").replace(V,""),a[2]==="~="&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),a[1]==="nth"?(a[2]||bc.error(a[0]),a[3]=+(a[3]?a[4]+(a[5]||1):2*(a[2]==="even"||a[2]==="odd")),a[4]=+(a[6]+a[7]||a[2]==="odd")):a[2]&&bc.error(a[0]),a},PSEUDO:function(a){var b,c;if(W.CHILD.test(a[0]))return null;if(a[3])a[2]=a[3];else if(b=a[4])O.test(b)&&(c=bh(b,!0))&&(c=b.indexOf(")",b.length-c)-b.length)&&(b=b.slice(0,c),a[0]=a[0].slice(0,c)),a[2]=b;return a.slice(0,3)}},filter:{ID:d?function(a){return a=a.replace(V,""),function(b){return b.getAttribute("id")===a}}:function(a){return a=a.replace(V,""),function(b){var c=typeof b.getAttributeNode!==n&&b.getAttributeNode("id");return c&&c.value===a}},TAG:function(a){return a==="*"?function(){return!0}:(a=a.replace(V,"").toLowerCase(),function(b){return b.nodeName&&b.nodeName.toLowerCase()===a})},CLASS:function(a){var b=B[o][a];return b||(b=B(a,new RegExp("(^|"+E+")"+a+"("+E+"|$)"))),function(a){return b.test(a.className||typeof a.getAttribute!==n&&a.getAttribute("class")||"")}},ATTR:function(a,b,c){return function(d,e){var f=bc.attr(d,a);return f==null?b==="!=":b?(f+="",b==="="?f===c:b==="!="?f!==c:b==="^="?c&&f.indexOf(c)===0:b==="*="?c&&f.indexOf(c)>-1:b==="$="?c&&f.substr(f.length-c.length)===c:b==="~="?(" "+f+" ").indexOf(c)>-1:b==="|="?f===c||f.substr(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d){return a==="nth"?function(a){var b,e,f=a.parentNode;if(c===1&&d===0)return!0;if(f){e=0;for(b=f.firstChild;b;b=b.nextSibling)if(b.nodeType===1){e++;if(a===b)break}}return e-=d,e===c||e%c===0&&e/c>=0}:function(b){var c=b;switch(a){case"only":case"first":while(c=c.previousSibling)if(c.nodeType===1)return!1;if(a==="first")return!0;c=b;case"last":while(c=c.nextSibling)if(c.nodeType===1)return!1;return!0}}},PSEUDO:function(a,b){var c,d=e.pseudos[a]||e.setFilters[a.toLowerCase()]||bc.error("unsupported pseudo: "+a);return d[o]?d(b):d.length>1?(c=[a,a,"",b],e.setFilters.hasOwnProperty(a.toLowerCase())?z(function(a,c){var e,f=d(a,b),g=f.length;while(g--)e=y.call(a,f[g]),a[e]=!(c[e]=f[g])}):function(a){return d(a,0,c)}):d}},pseudos:{not:z(function(a){var b=[],c=[],d=i(a.replace(L,"$1"));return d[o]?z(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)if(f=g[h])a[h]=!(b[h]=f)}):function(a,e,f){return b[0]=a,d(b,null,f,c),!c.pop()}}),has:z(function(a){return function(b){return bc(a,b).length>0}}),contains:z(function(a){return function(b){return(b.textContent||b.innerText||f(b)).indexOf(a)>-1}}),enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&!!a.checked||b==="option"&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},parent:function(a){return!e.pseudos.empty(a)},empty:function(a){var b;a=a.firstChild;while(a){if(a.nodeName>"@"||(b=a.nodeType)===3||b===4)return!1;a=a.nextSibling}return!0},header:function(a){return T.test(a.nodeName)},text:function(a){var b,c;return a.nodeName.toLowerCase()==="input"&&(b=a.type)==="text"&&((c=a.getAttribute("type"))==null||c.toLowerCase()===b)},radio:bd("radio"),checkbox:bd("checkbox"),file:bd("file"),password:bd("password"),image:bd("image"),submit:be("submit"),reset:be("reset"),button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&a.type==="button"||b==="button"},input:function(a){return U.test(a.nodeName)},focus:function(a){var b=a.ownerDocument;return a===b.activeElement&&(!b.hasFocus||b.hasFocus())&&(!!a.type||!!a.href)},active:function(a){return a===a.ownerDocument.activeElement},first:bf(function(a,b,c){return[0]}),last:bf(function(a,b,c){return[b-1]}),eq:bf(function(a,b,c){return[c<0?c+b:c]}),even:bf(function(a,b,c){for(var d=0;d<b;d+=2)a.push(d);return a}),odd:bf(function(a,b,c){for(var d=1;d<b;d+=2)a.push(d);return a}),lt:bf(function(a,b,c){for(var d=c<0?c+b:c;--d>=0;)a.push(d);return a}),gt:bf(function(a,b,c){for(var d=c<0?c+b:c;++d<b;)a.push(d);return a})}},j=s.compareDocumentPosition?function(a,b){return a===b?(k=!0,0):(!a.compareDocumentPosition||!b.compareDocumentPosition?a.compareDocumentPosition:a.compareDocumentPosition(b)&4)?-1:1}:function(a,b){if(a===b)return k=!0,0;if(a.sourceIndex&&b.sourceIndex)return a.sourceIndex-b.sourceIndex;var c,d,e=[],f=[],g=a.parentNode,h=b.parentNode,i=g;if(g===h)return bg(a,b);if(!g)return-1;if(!h)return 1;while(i)e.unshift(i),i=i.parentNode;i=h;while(i)f.unshift(i),i=i.parentNode;c=e.length,d=f.length;for(var j=0;j<c&&j<d;j++)if(e[j]!==f[j])return bg(e[j],f[j]);return j===c?bg(a,f[j],-1):bg(e[j],b,1)},[0,0].sort(j),m=!k,bc.uniqueSort=function(a){var b,c=1;k=m,a.sort(j);if(k)for(;b=a[c];c++)b===a[c-1]&&a.splice(c--,1);return a},bc.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},i=bc.compile=function(a,b){var c,d=[],e=[],f=D[o][a];if(!f){b||(b=bh(a)),c=b.length;while(c--)f=bm(b[c]),f[o]?d.push(f):e.push(f);f=D(a,bn(e,d))}return f},r.querySelectorAll&&function(){var a,b=bp,c=/'|\\/g,d=/\=[\x20\t\r\n\f]*([^'"\]]*)[\x20\t\r\n\f]*\]/g,e=[":focus"],f=[":active",":focus"],h=s.matchesSelector||s.mozMatchesSelector||s.webkitMatchesSelector||s.oMatchesSelector||s.msMatchesSelector;X(function(a){a.innerHTML="<select><option selected=''></option></select>",a.querySelectorAll("[selected]").length||e.push("\\["+E+"*(?:checked|disabled|ismap|multiple|readonly|selected|value)"),a.querySelectorAll(":checked").length||e.push(":checked")}),X(function(a){a.innerHTML="<p test=''></p>",a.querySelectorAll("[test^='']").length&&e.push("[*^$]="+E+"*(?:\"\"|'')"),a.innerHTML="<input type='hidden'/>",a.querySelectorAll(":enabled").length||e.push(":enabled",":disabled")}),e=new RegExp(e.join("|")),bp=function(a,d,f,g,h){if(!g&&!h&&(!e||!e.test(a))){var i,j,k=!0,l=o,m=d,n=d.nodeType===9&&a;if(d.nodeType===1&&d.nodeName.toLowerCase()!=="object"){i=bh(a),(k=d.getAttribute("id"))?l=k.replace(c,"\\$&"):d.setAttribute("id",l),l="[id='"+l+"'] ",j=i.length;while(j--)i[j]=l+i[j].join("");m=R.test(a)&&d.parentNode||d,n=i.join(",")}if(n)try{return w.apply(f,x.call(m.querySelectorAll(n),0)),f}catch(p){}finally{k||d.removeAttribute("id")}}return b(a,d,f,g,h)},h&&(X(function(b){a=h.call(b,"div");try{h.call(b,"[test!='']:sizzle"),f.push("!=",J)}catch(c){}}),f=new RegExp(f.join("|")),bc.matchesSelector=function(b,c){c=c.replace(d,"='$1']");if(!g(b)&&!f.test(c)&&(!e||!e.test(c)))try{var i=h.call(b,c);if(i||a||b.document&&b.document.nodeType!==11)return i}catch(j){}return bc(c,null,null,[b]).length>0})}(),e.pseudos.nth=e.pseudos.eq,e.filters=bq.prototype=e.pseudos,e.setFilters=new bq,bc.attr=p.attr,p.find=bc,p.expr=bc.selectors,p.expr[":"]=p.expr.pseudos,p.unique=bc.uniqueSort,p.text=bc.getText,p.isXMLDoc=bc.isXML,p.contains=bc.contains}(a);var bc=/Until$/,bd=/^(?:parents|prev(?:Until|All))/,be=/^.[^:#\[\.,]*$/,bf=p.expr.match.needsContext,bg={children:!0,contents:!0,next:!0,prev:!0};p.fn.extend({find:function(a){var b,c,d,e,f,g,h=this;if(typeof a!="string")return p(a).filter(function(){for(b=0,c=h.length;b<c;b++)if(p.contains(h[b],this))return!0});g=this.pushStack("","find",a);for(b=0,c=this.length;b<c;b++){d=g.length,p.find(a,this[b],g);if(b>0)for(e=d;e<g.length;e++)for(f=0;f<d;f++)if(g[f]===g[e]){g.splice(e--,1);break}}return g},has:function(a){var b,c=p(a,this),d=c.length;return this.filter(function(){for(b=0;b<d;b++)if(p.contains(this,c[b]))return!0})},not:function(a){return this.pushStack(bj(this,a,!1),"not",a)},filter:function(a){return this.pushStack(bj(this,a,!0),"filter",a)},is:function(a){return!!a&&(typeof a=="string"?bf.test(a)?p(a,this.context).index(this[0])>=0:p.filter(a,this).length>0:this.filter(a).length>0)},closest:function(a,b){var c,d=0,e=this.length,f=[],g=bf.test(a)||typeof a!="string"?p(a,b||this.context):0;for(;d<e;d++){c=this[d];while(c&&c.ownerDocument&&c!==b&&c.nodeType!==11){if(g?g.index(c)>-1:p.find.matchesSelector(c,a)){f.push(c);break}c=c.parentNode}}return f=f.length>1?p.unique(f):f,this.pushStack(f,"closest",a)},index:function(a){return a?typeof a=="string"?p.inArray(this[0],p(a)):p.inArray(a.jquery?a[0]:a,this):this[0]&&this[0].parentNode?this.prevAll().length:-1},add:function(a,b){var c=typeof a=="string"?p(a,b):p.makeArray(a&&a.nodeType?[a]:a),d=p.merge(this.get(),c);return this.pushStack(bh(c[0])||bh(d[0])?d:p.unique(d))},addBack:function(a){return this.add(a==null?this.prevObject:this.prevObject.filter(a))}}),p.fn.andSelf=p.fn.addBack,p.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return p.dir(a,"parentNode")},parentsUntil:function(a,b,c){return p.dir(a,"parentNode",c)},next:function(a){return bi(a,"nextSibling")},prev:function(a){return bi(a,"previousSibling")},nextAll:function(a){return p.dir(a,"nextSibling")},prevAll:function(a){return p.dir(a,"previousSibling")},nextUntil:function(a,b,c){return p.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return p.dir(a,"previousSibling",c)},siblings:function(a){return p.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return p.sibling(a.firstChild)},contents:function(a){return p.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:p.merge([],a.childNodes)}},function(a,b){p.fn[a]=function(c,d){var e=p.map(this,b,c);return bc.test(a)||(d=c),d&&typeof d=="string"&&(e=p.filter(d,e)),e=this.length>1&&!bg[a]?p.unique(e):e,this.length>1&&bd.test(a)&&(e=e.reverse()),this.pushStack(e,a,k.call(arguments).join(","))}}),p.extend({filter:function(a,b,c){return c&&(a=":not("+a+")"),b.length===1?p.find.matchesSelector(b[0],a)?[b[0]]:[]:p.find.matches(a,b)},dir:function(a,c,d){var e=[],f=a[c];while(f&&f.nodeType!==9&&(d===b||f.nodeType!==1||!p(f).is(d)))f.nodeType===1&&e.push(f),f=f[c];return e},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var bl="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",bm=/ jQuery\d+="(?:null|\d+)"/g,bn=/^\s+/,bo=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,bp=/<([\w:]+)/,bq=/<tbody/i,br=/<|&#?\w+;/,bs=/<(?:script|style|link)/i,bt=/<(?:script|object|embed|option|style)/i,bu=new RegExp("<(?:"+bl+")[\\s/>]","i"),bv=/^(?:checkbox|radio)$/,bw=/checked\s*(?:[^=]|=\s*.checked.)/i,bx=/\/(java|ecma)script/i,by=/^\s*<!(?:\[CDATA\[|\-\-)|[\]\-]{2}>\s*$/g,bz={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]},bA=bk(e),bB=bA.appendChild(e.createElement("div"));bz.optgroup=bz.option,bz.tbody=bz.tfoot=bz.colgroup=bz.caption=bz.thead,bz.th=bz.td,p.support.htmlSerialize||(bz._default=[1,"X<div>","</div>"]),p.fn.extend({text:function(a){return p.access(this,function(a){return a===b?p.text(this):this.empty().append((this[0]&&this[0].ownerDocument||e).createTextNode(a))},null,a,arguments.length)},wrapAll:function(a){if(p.isFunction(a))return this.each(function(b){p(this).wrapAll(a.call(this,b))});if(this[0]){var b=p(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){return p.isFunction(a)?this.each(function(b){p(this).wrapInner(a.call(this,b))}):this.each(function(){var b=p(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=p.isFunction(a);return this.each(function(c){p(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){p.nodeName(this,"body")||p(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){(this.nodeType===1||this.nodeType===11)&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){(this.nodeType===1||this.nodeType===11)&&this.insertBefore(a,this.firstChild)})},before:function(){if(!bh(this[0]))return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=p.clean(arguments);return this.pushStack(p.merge(a,this),"before",this.selector)}},after:function(){if(!bh(this[0]))return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=p.clean(arguments);return this.pushStack(p.merge(this,a),"after",this.selector)}},remove:function(a,b){var c,d=0;for(;(c=this[d])!=null;d++)if(!a||p.filter(a,[c]).length)!b&&c.nodeType===1&&(p.cleanData(c.getElementsByTagName("*")),p.cleanData([c])),c.parentNode&&c.parentNode.removeChild(c);return this},empty:function(){var a,b=0;for(;(a=this[b])!=null;b++){a.nodeType===1&&p.cleanData(a.getElementsByTagName("*"));while(a.firstChild)a.removeChild(a.firstChild)}return this},clone:function(a,b){return a=a==null?!1:a,b=b==null?a:b,this.map(function(){return p.clone(this,a,b)})},html:function(a){return p.access(this,function(a){var c=this[0]||{},d=0,e=this.length;if(a===b)return c.nodeType===1?c.innerHTML.replace(bm,""):b;if(typeof a=="string"&&!bs.test(a)&&(p.support.htmlSerialize||!bu.test(a))&&(p.support.leadingWhitespace||!bn.test(a))&&!bz[(bp.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(bo,"<$1></$2>");try{for(;d<e;d++)c=this[d]||{},c.nodeType===1&&(p.cleanData(c.getElementsByTagName("*")),c.innerHTML=a);c=0}catch(f){}}c&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(a){return bh(this[0])?this.length?this.pushStack(p(p.isFunction(a)?a():a),"replaceWith",a):this:p.isFunction(a)?this.each(function(b){var c=p(this),d=c.html();c.replaceWith(a.call(this,b,d))}):(typeof a!="string"&&(a=p(a).detach()),this.each(function(){var b=this.nextSibling,c=this.parentNode;p(this).remove(),b?p(b).before(a):p(c).append(a)}))},detach:function(a){return this.remove(a,!0)},domManip:function(a,c,d){a=[].concat.apply([],a);var e,f,g,h,i=0,j=a[0],k=[],l=this.length;if(!p.support.checkClone&&l>1&&typeof j=="string"&&bw.test(j))return this.each(function(){p(this).domManip(a,c,d)});if(p.isFunction(j))return this.each(function(e){var f=p(this);a[0]=j.call(this,e,c?f.html():b),f.domManip(a,c,d)});if(this[0]){e=p.buildFragment(a,this,k),g=e.fragment,f=g.firstChild,g.childNodes.length===1&&(g=f);if(f){c=c&&p.nodeName(f,"tr");for(h=e.cacheable||l-1;i<l;i++)d.call(c&&p.nodeName(this[i],"table")?bC(this[i],"tbody"):this[i],i===h?g:p.clone(g,!0,!0))}g=f=null,k.length&&p.each(k,function(a,b){b.src?p.ajax?p.ajax({url:b.src,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0}):p.error("no ajax"):p.globalEval((b.text||b.textContent||b.innerHTML||"").replace(by,"")),b.parentNode&&b.parentNode.removeChild(b)})}return this}}),p.buildFragment=function(a,c,d){var f,g,h,i=a[0];return c=c||e,c=!c.nodeType&&c[0]||c,c=c.ownerDocument||c,a.length===1&&typeof i=="string"&&i.length<512&&c===e&&i.charAt(0)==="<"&&!bt.test(i)&&(p.support.checkClone||!bw.test(i))&&(p.support.html5Clone||!bu.test(i))&&(g=!0,f=p.fragments[i],h=f!==b),f||(f=c.createDocumentFragment(),p.clean(a,c,f,d),g&&(p.fragments[i]=h&&f)),{fragment:f,cacheable:g}},p.fragments={},p.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){p.fn[a]=function(c){var d,e=0,f=[],g=p(c),h=g.length,i=this.length===1&&this[0].parentNode;if((i==null||i&&i.nodeType===11&&i.childNodes.length===1)&&h===1)return g[b](this[0]),this;for(;e<h;e++)d=(e>0?this.clone(!0):this).get(),p(g[e])[b](d),f=f.concat(d);return this.pushStack(f,a,g.selector)}}),p.extend({clone:function(a,b,c){var d,e,f,g;p.support.html5Clone||p.isXMLDoc(a)||!bu.test("<"+a.nodeName+">")?g=a.cloneNode(!0):(bB.innerHTML=a.outerHTML,bB.removeChild(g=bB.firstChild));if((!p.support.noCloneEvent||!p.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!p.isXMLDoc(a)){bE(a,g),d=bF(a),e=bF(g);for(f=0;d[f];++f)e[f]&&bE(d[f],e[f])}if(b){bD(a,g);if(c){d=bF(a),e=bF(g);for(f=0;d[f];++f)bD(d[f],e[f])}}return d=e=null,g},clean:function(a,b,c,d){var f,g,h,i,j,k,l,m,n,o,q,r,s=b===e&&bA,t=[];if(!b||typeof b.createDocumentFragment=="undefined")b=e;for(f=0;(h=a[f])!=null;f++){typeof h=="number"&&(h+="");if(!h)continue;if(typeof h=="string")if(!br.test(h))h=b.createTextNode(h);else{s=s||bk(b),l=b.createElement("div"),s.appendChild(l),h=h.replace(bo,"<$1></$2>"),i=(bp.exec(h)||["",""])[1].toLowerCase(),j=bz[i]||bz._default,k=j[0],l.innerHTML=j[1]+h+j[2];while(k--)l=l.lastChild;if(!p.support.tbody){m=bq.test(h),n=i==="table"&&!m?l.firstChild&&l.firstChild.childNodes:j[1]==="<table>"&&!m?l.childNodes:[];for(g=n.length-1;g>=0;--g)p.nodeName(n[g],"tbody")&&!n[g].childNodes.length&&n[g].parentNode.removeChild(n[g])}!p.support.leadingWhitespace&&bn.test(h)&&l.insertBefore(b.createTextNode(bn.exec(h)[0]),l.firstChild),h=l.childNodes,l.parentNode.removeChild(l)}h.nodeType?t.push(h):p.merge(t,h)}l&&(h=l=s=null);if(!p.support.appendChecked)for(f=0;(h=t[f])!=null;f++)p.nodeName(h,"input")?bG(h):typeof h.getElementsByTagName!="undefined"&&p.grep(h.getElementsByTagName("input"),bG);if(c){q=function(a){if(!a.type||bx.test(a.type))return d?d.push(a.parentNode?a.parentNode.removeChild(a):a):c.appendChild(a)};for(f=0;(h=t[f])!=null;f++)if(!p.nodeName(h,"script")||!q(h))c.appendChild(h),typeof h.getElementsByTagName!="undefined"&&(r=p.grep(p.merge([],h.getElementsByTagName("script")),q),t.splice.apply(t,[f+1,0].concat(r)),f+=r.length)}return t},cleanData:function(a,b){var c,d,e,f,g=0,h=p.expando,i=p.cache,j=p.support.deleteExpando,k=p.event.special;for(;(e=a[g])!=null;g++)if(b||p.acceptData(e)){d=e[h],c=d&&i[d];if(c){if(c.events)for(f in c.events)k[f]?p.event.remove(e,f):p.removeEvent(e,f,c.handle);i[d]&&(delete i[d],j?delete e[h]:e.removeAttribute?e.removeAttribute(h):e[h]=null,p.deletedIds.push(d))}}}}),function(){var a,b;p.uaMatch=function(a){a=a.toLowerCase();var b=/(chrome)[ \/]([\w.]+)/.exec(a)||/(webkit)[ \/]([\w.]+)/.exec(a)||/(opera)(?:.*version|)[ \/]([\w.]+)/.exec(a)||/(msie) ([\w.]+)/.exec(a)||a.indexOf("compatible")<0&&/(mozilla)(?:.*? rv:([\w.]+)|)/.exec(a)||[];return{browser:b[1]||"",version:b[2]||"0"}},a=p.uaMatch(g.userAgent),b={},a.browser&&(b[a.browser]=!0,b.version=a.version),b.chrome?b.webkit=!0:b.webkit&&(b.safari=!0),p.browser=b,p.sub=function(){function a(b,c){return new a.fn.init(b,c)}p.extend(!0,a,this),a.superclass=this,a.fn=a.prototype=this(),a.fn.constructor=a,a.sub=this.sub,a.fn.init=function c(c,d){return d&&d instanceof p&&!(d instanceof a)&&(d=a(d)),p.fn.init.call(this,c,d,b)},a.fn.init.prototype=a.fn;var b=a(e);return a}}();var bH,bI,bJ,bK=/alpha\([^)]*\)/i,bL=/opacity=([^)]*)/,bM=/^(top|right|bottom|left)$/,bN=/^(none|table(?!-c[ea]).+)/,bO=/^margin/,bP=new RegExp("^("+q+")(.*)$","i"),bQ=new RegExp("^("+q+")(?!px)[a-z%]+$","i"),bR=new RegExp("^([-+])=("+q+")","i"),bS={},bT={position:"absolute",visibility:"hidden",display:"block"},bU={letterSpacing:0,fontWeight:400},bV=["Top","Right","Bottom","Left"],bW=["Webkit","O","Moz","ms"],bX=p.fn.toggle;p.fn.extend({css:function(a,c){return p.access(this,function(a,c,d){return d!==b?p.style(a,c,d):p.css(a,c)},a,c,arguments.length>1)},show:function(){return b$(this,!0)},hide:function(){return b$(this)},toggle:function(a,b){var c=typeof a=="boolean";return p.isFunction(a)&&p.isFunction(b)?bX.apply(this,arguments):this.each(function(){(c?a:bZ(this))?p(this).show():p(this).hide()})}}),p.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=bH(a,"opacity");return c===""?"1":c}}}},cssNumber:{fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":p.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,c,d,e){if(!a||a.nodeType===3||a.nodeType===8||!a.style)return;var f,g,h,i=p.camelCase(c),j=a.style;c=p.cssProps[i]||(p.cssProps[i]=bY(j,i)),h=p.cssHooks[c]||p.cssHooks[i];if(d===b)return h&&"get"in h&&(f=h.get(a,!1,e))!==b?f:j[c];g=typeof d,g==="string"&&(f=bR.exec(d))&&(d=(f[1]+1)*f[2]+parseFloat(p.css(a,c)),g="number");if(d==null||g==="number"&&isNaN(d))return;g==="number"&&!p.cssNumber[i]&&(d+="px");if(!h||!("set"in h)||(d=h.set(a,d,e))!==b)try{j[c]=d}catch(k){}},css:function(a,c,d,e){var f,g,h,i=p.camelCase(c);return c=p.cssProps[i]||(p.cssProps[i]=bY(a.style,i)),h=p.cssHooks[c]||p.cssHooks[i],h&&"get"in h&&(f=h.get(a,!0,e)),f===b&&(f=bH(a,c)),f==="normal"&&c in bU&&(f=bU[c]),d||e!==b?(g=parseFloat(f),d||p.isNumeric(g)?g||0:f):f},swap:function(a,b,c){var d,e,f={};for(e in b)f[e]=a.style[e],a.style[e]=b[e];d=c.call(a);for(e in b)a.style[e]=f[e];return d}}),a.getComputedStyle?bH=function(b,c){var d,e,f,g,h=a.getComputedStyle(b,null),i=b.style;return h&&(d=h[c],d===""&&!p.contains(b.ownerDocument,b)&&(d=p.style(b,c)),bQ.test(d)&&bO.test(c)&&(e=i.width,f=i.minWidth,g=i.maxWidth,i.minWidth=i.maxWidth=i.width=d,d=h.width,i.width=e,i.minWidth=f,i.maxWidth=g)),d}:e.documentElement.currentStyle&&(bH=function(a,b){var c,d,e=a.currentStyle&&a.currentStyle[b],f=a.style;return e==null&&f&&f[b]&&(e=f[b]),bQ.test(e)&&!bM.test(b)&&(c=f.left,d=a.runtimeStyle&&a.runtimeStyle.left,d&&(a.runtimeStyle.left=a.currentStyle.left),f.left=b==="fontSize"?"1em":e,e=f.pixelLeft+"px",f.left=c,d&&(a.runtimeStyle.left=d)),e===""?"auto":e}),p.each(["height","width"],function(a,b){p.cssHooks[b]={get:function(a,c,d){if(c)return a.offsetWidth===0&&bN.test(bH(a,"display"))?p.swap(a,bT,function(){return cb(a,b,d)}):cb(a,b,d)},set:function(a,c,d){return b_(a,c,d?ca(a,b,d,p.support.boxSizing&&p.css(a,"boxSizing")==="border-box"):0)}}}),p.support.opacity||(p.cssHooks.opacity={get:function(a,b){return bL.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?.01*parseFloat(RegExp.$1)+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=p.isNumeric(b)?"alpha(opacity="+b*100+")":"",f=d&&d.filter||c.filter||"";c.zoom=1;if(b>=1&&p.trim(f.replace(bK,""))===""&&c.removeAttribute){c.removeAttribute("filter");if(d&&!d.filter)return}c.filter=bK.test(f)?f.replace(bK,e):f+" "+e}}),p(function(){p.support.reliableMarginRight||(p.cssHooks.marginRight={get:function(a,b){return p.swap(a,{display:"inline-block"},function(){if(b)return bH(a,"marginRight")})}}),!p.support.pixelPosition&&p.fn.position&&p.each(["top","left"],function(a,b){p.cssHooks[b]={get:function(a,c){if(c){var d=bH(a,b);return bQ.test(d)?p(a).position()[b]+"px":d}}}})}),p.expr&&p.expr.filters&&(p.expr.filters.hidden=function(a){return a.offsetWidth===0&&a.offsetHeight===0||!p.support.reliableHiddenOffsets&&(a.style&&a.style.display||bH(a,"display"))==="none"},p.expr.filters.visible=function(a){return!p.expr.filters.hidden(a)}),p.each({margin:"",padding:"",border:"Width"},function(a,b){p.cssHooks[a+b]={expand:function(c){var d,e=typeof c=="string"?c.split(" "):[c],f={};for(d=0;d<4;d++)f[a+bV[d]+b]=e[d]||e[d-2]||e[0];return f}},bO.test(a)||(p.cssHooks[a+b].set=b_)});var cd=/%20/g,ce=/\[\]$/,cf=/\r?\n/g,cg=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,ch=/^(?:select|textarea)/i;p.fn.extend({serialize:function(){return p.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?p.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||ch.test(this.nodeName)||cg.test(this.type))}).map(function(a,b){var c=p(this).val();return c==null?null:p.isArray(c)?p.map(c,function(a,c){return{name:b.name,value:a.replace(cf,"\r\n")}}):{name:b.name,value:c.replace(cf,"\r\n")}}).get()}}),p.param=function(a,c){var d,e=[],f=function(a,b){b=p.isFunction(b)?b():b==null?"":b,e[e.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=p.ajaxSettings&&p.ajaxSettings.traditional);if(p.isArray(a)||a.jquery&&!p.isPlainObject(a))p.each(a,function(){f(this.name,this.value)});else for(d in a)ci(d,a[d],c,f);return e.join("&").replace(cd,"+")};var cj,ck,cl=/#.*$/,cm=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,cn=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,co=/^(?:GET|HEAD)$/,cp=/^\/\//,cq=/\?/,cr=/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,cs=/([?&])_=[^&]*/,ct=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/,cu=p.fn.load,cv={},cw={},cx=["*/"]+["*"];try{ck=f.href}catch(cy){ck=e.createElement("a"),ck.href="",ck=ck.href}cj=ct.exec(ck.toLowerCase())||[],p.fn.load=function(a,c,d){if(typeof a!="string"&&cu)return cu.apply(this,arguments);if(!this.length)return this;var e,f,g,h=this,i=a.indexOf(" ");return i>=0&&(e=a.slice(i,a.length),a=a.slice(0,i)),p.isFunction(c)?(d=c,c=b):c&&typeof c=="object"&&(f="POST"),p.ajax({url:a,type:f,dataType:"html",data:c,complete:function(a,b){d&&h.each(d,g||[a.responseText,b,a])}}).done(function(a){g=arguments,h.html(e?p("<div>").append(a.replace(cr,"")).find(e):a)}),this},p.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){p.fn[b]=function(a){return this.on(b,a)}}),p.each(["get","post"],function(a,c){p[c]=function(a,d,e,f){return p.isFunction(d)&&(f=f||e,e=d,d=b),p.ajax({type:c,url:a,data:d,success:e,dataType:f})}}),p.extend({getScript:function(a,c){return p.get(a,b,c,"script")},getJSON:function(a,b,c){return p.get(a,b,c,"json")},ajaxSetup:function(a,b){return b?cB(a,p.ajaxSettings):(b=a,a=p.ajaxSettings),cB(a,b),a},ajaxSettings:{url:ck,isLocal:cn.test(cj[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded; charset=UTF-8",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":cx},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":p.parseJSON,"text xml":p.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:cz(cv),ajaxTransport:cz(cw),ajax:function(a,c){function y(a,c,f,i){var k,s,t,u,w,y=c;if(v===2)return;v=2,h&&clearTimeout(h),g=b,e=i||"",x.readyState=a>0?4:0,f&&(u=cC(l,x,f));if(a>=200&&a<300||a===304)l.ifModified&&(w=x.getResponseHeader("Last-Modified"),w&&(p.lastModified[d]=w),w=x.getResponseHeader("Etag"),w&&(p.etag[d]=w)),a===304?(y="notmodified",k=!0):(k=cD(l,u),y=k.state,s=k.data,t=k.error,k=!t);else{t=y;if(!y||a)y="error",a<0&&(a=0)}x.status=a,x.statusText=(c||y)+"",k?o.resolveWith(m,[s,y,x]):o.rejectWith(m,[x,y,t]),x.statusCode(r),r=b,j&&n.trigger("ajax"+(k?"Success":"Error"),[x,l,k?s:t]),q.fireWith(m,[x,y]),j&&(n.trigger("ajaxComplete",[x,l]),--p.active||p.event.trigger("ajaxStop"))}typeof a=="object"&&(c=a,a=b),c=c||{};var d,e,f,g,h,i,j,k,l=p.ajaxSetup({},c),m=l.context||l,n=m!==l&&(m.nodeType||m instanceof p)?p(m):p.event,o=p.Deferred(),q=p.Callbacks("once memory"),r=l.statusCode||{},t={},u={},v=0,w="canceled",x={readyState:0,setRequestHeader:function(a,b){if(!v){var c=a.toLowerCase();a=u[c]=u[c]||a,t[a]=b}return this},getAllResponseHeaders:function(){return v===2?e:null},getResponseHeader:function(a){var c;if(v===2){if(!f){f={};while(c=cm.exec(e))f[c[1].toLowerCase()]=c[2]}c=f[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){return v||(l.mimeType=a),this},abort:function(a){return a=a||w,g&&g.abort(a),y(0,a),this}};o.promise(x),x.success=x.done,x.error=x.fail,x.complete=q.add,x.statusCode=function(a){if(a){var b;if(v<2)for(b in a)r[b]=[r[b],a[b]];else b=a[x.status],x.always(b)}return this},l.url=((a||l.url)+"").replace(cl,"").replace(cp,cj[1]+"//"),l.dataTypes=p.trim(l.dataType||"*").toLowerCase().split(s),l.crossDomain==null&&(i=ct.exec(l.url.toLowerCase())||!1,l.crossDomain=i&&i.join(":")+(i[3]?"":i[1]==="http:"?80:443)!==cj.join(":")+(cj[3]?"":cj[1]==="http:"?80:443)),l.data&&l.processData&&typeof l.data!="string"&&(l.data=p.param(l.data,l.traditional)),cA(cv,l,c,x);if(v===2)return x;j=l.global,l.type=l.type.toUpperCase(),l.hasContent=!co.test(l.type),j&&p.active++===0&&p.event.trigger("ajaxStart");if(!l.hasContent){l.data&&(l.url+=(cq.test(l.url)?"&":"?")+l.data,delete l.data),d=l.url;if(l.cache===!1){var z=p.now(),A=l.url.replace(cs,"$1_="+z);l.url=A+(A===l.url?(cq.test(l.url)?"&":"?")+"_="+z:"")}}(l.data&&l.hasContent&&l.contentType!==!1||c.contentType)&&x.setRequestHeader("Content-Type",l.contentType),l.ifModified&&(d=d||l.url,p.lastModified[d]&&x.setRequestHeader("If-Modified-Since",p.lastModified[d]),p.etag[d]&&x.setRequestHeader("If-None-Match",p.etag[d])),x.setRequestHeader("Accept",l.dataTypes[0]&&l.accepts[l.dataTypes[0]]?l.accepts[l.dataTypes[0]]+(l.dataTypes[0]!=="*"?", "+cx+"; q=0.01":""):l.accepts["*"]);for(k in l.headers)x.setRequestHeader(k,l.headers[k]);if(!l.beforeSend||l.beforeSend.call(m,x,l)!==!1&&v!==2){w="abort";for(k in{success:1,error:1,complete:1})x[k](l[k]);g=cA(cw,l,c,x);if(!g)y(-1,"No Transport");else{x.readyState=1,j&&n.trigger("ajaxSend",[x,l]),l.async&&l.timeout>0&&(h=setTimeout(function(){x.abort("timeout")},l.timeout));try{v=1,g.send(t,y)}catch(B){if(v<2)y(-1,B);else throw B}}return x}return x.abort()},active:0,lastModified:{},etag:{}});var cE=[],cF=/\?/,cG=/(=)\?(?=&|$)|\?\?/,cH=p.now();p.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var a=cE.pop()||p.expando+"_"+cH++;return this[a]=!0,a}}),p.ajaxPrefilter("json jsonp",function(c,d,e){var f,g,h,i=c.data,j=c.url,k=c.jsonp!==!1,l=k&&cG.test(j),m=k&&!l&&typeof i=="string"&&!(c.contentType||"").indexOf("application/x-www-form-urlencoded")&&cG.test(i);if(c.dataTypes[0]==="jsonp"||l||m)return f=c.jsonpCallback=p.isFunction(c.jsonpCallback)?c.jsonpCallback():c.jsonpCallback,g=a[f],l?c.url=j.replace(cG,"$1"+f):m?c.data=i.replace(cG,"$1"+f):k&&(c.url+=(cF.test(j)?"&":"?")+c.jsonp+"="+f),c.converters["script json"]=function(){return h||p.error(f+" was not called"),h[0]},c.dataTypes[0]="json",a[f]=function(){h=arguments},e.always(function(){a[f]=g,c[f]&&(c.jsonpCallback=d.jsonpCallback,cE.push(f)),h&&p.isFunction(g)&&g(h[0]),h=g=b}),"script"}),p.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){return p.globalEval(a),a}}}),p.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),p.ajaxTransport("script",function(a){if(a.crossDomain){var c,d=e.head||e.getElementsByTagName("head")[0]||e.documentElement;return{send:function(f,g){c=e.createElement("script"),c.async="async",a.scriptCharset&&(c.charset=a.scriptCharset),c.src=a.url,c.onload=c.onreadystatechange=function(a,e){if(e||!c.readyState||/loaded|complete/.test(c.readyState))c.onload=c.onreadystatechange=null,d&&c.parentNode&&d.removeChild(c),c=b,e||g(200,"success")},d.insertBefore(c,d.firstChild)},abort:function(){c&&c.onload(0,1)}}}});var cI,cJ=a.ActiveXObject?function(){for(var a in cI)cI[a](0,1)}:!1,cK=0;p.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&cL()||cM()}:cL,function(a){p.extend(p.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(p.ajaxSettings.xhr()),p.support.ajax&&p.ajaxTransport(function(c){if(!c.crossDomain||p.support.cors){var d;return{send:function(e,f){var g,h,i=c.xhr();c.username?i.open(c.type,c.url,c.async,c.username,c.password):i.open(c.type,c.url,c.async);if(c.xhrFields)for(h in c.xhrFields)i[h]=c.xhrFields[h];c.mimeType&&i.overrideMimeType&&i.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(h in e)i.setRequestHeader(h,e[h])}catch(j){}i.send(c.hasContent&&c.data||null),d=function(a,e){var h,j,k,l,m;try{if(d&&(e||i.readyState===4)){d=b,g&&(i.onreadystatechange=p.noop,cJ&&delete cI[g]);if(e)i.readyState!==4&&i.abort();else{h=i.status,k=i.getAllResponseHeaders(),l={},m=i.responseXML,m&&m.documentElement&&(l.xml=m);try{l.text=i.responseText}catch(a){}try{j=i.statusText}catch(n){j=""}!h&&c.isLocal&&!c.crossDomain?h=l.text?200:404:h===1223&&(h=204)}}}catch(o){e||f(-1,o)}l&&f(h,j,l,k)},c.async?i.readyState===4?setTimeout(d,0):(g=++cK,cJ&&(cI||(cI={},p(a).unload(cJ)),cI[g]=d),i.onreadystatechange=d):d()},abort:function(){d&&d(0,1)}}}});var cN,cO,cP=/^(?:toggle|show|hide)$/,cQ=new RegExp("^(?:([-+])=|)("+q+")([a-z%]*)$","i"),cR=/queueHooks$/,cS=[cY],cT={"*":[function(a,b){var c,d,e=this.createTween(a,b),f=cQ.exec(b),g=e.cur(),h=+g||0,i=1,j=20;if(f){c=+f[2],d=f[3]||(p.cssNumber[a]?"":"px");if(d!=="px"&&h){h=p.css(e.elem,a,!0)||c||1;do i=i||".5",h=h/i,p.style(e.elem,a,h+d);while(i!==(i=e.cur()/g)&&i!==1&&--j)}e.unit=d,e.start=h,e.end=f[1]?h+(f[1]+1)*c:c}return e}]};p.Animation=p.extend(cW,{tweener:function(a,b){p.isFunction(a)?(b=a,a=["*"]):a=a.split(" ");var c,d=0,e=a.length;for(;d<e;d++)c=a[d],cT[c]=cT[c]||[],cT[c].unshift(b)},prefilter:function(a,b){b?cS.unshift(a):cS.push(a)}}),p.Tween=cZ,cZ.prototype={constructor:cZ,init:function(a,b,c,d,e,f){this.elem=a,this.prop=c,this.easing=e||"swing",this.options=b,this.start=this.now=this.cur(),this.end=d,this.unit=f||(p.cssNumber[c]?"":"px")},cur:function(){var a=cZ.propHooks[this.prop];return a&&a.get?a.get(this):cZ.propHooks._default.get(this)},run:function(a){var b,c=cZ.propHooks[this.prop];return this.options.duration?this.pos=b=p.easing[this.easing](a,this.options.duration*a,0,1,this.options.duration):this.pos=b=a,this.now=(this.end-this.start)*b+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),c&&c.set?c.set(this):cZ.propHooks._default.set(this),this}},cZ.prototype.init.prototype=cZ.prototype,cZ.propHooks={_default:{get:function(a){var b;return a.elem[a.prop]==null||!!a.elem.style&&a.elem.style[a.prop]!=null?(b=p.css(a.elem,a.prop,!1,""),!b||b==="auto"?0:b):a.elem[a.prop]},set:function(a){p.fx.step[a.prop]?p.fx.step[a.prop](a):a.elem.style&&(a.elem.style[p.cssProps[a.prop]]!=null||p.cssHooks[a.prop])?p.style(a.elem,a.prop,a.now+a.unit):a.elem[a.prop]=a.now}}},cZ.propHooks.scrollTop=cZ.propHooks.scrollLeft={set:function(a){a.elem.nodeType&&a.elem.parentNode&&(a.elem[a.prop]=a.now)}},p.each(["toggle","show","hide"],function(a,b){var c=p.fn[b];p.fn[b]=function(d,e,f){return d==null||typeof d=="boolean"||!a&&p.isFunction(d)&&p.isFunction(e)?c.apply(this,arguments):this.animate(c$(b,!0),d,e,f)}}),p.fn.extend({fadeTo:function(a,b,c,d){return this.filter(bZ).css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){var e=p.isEmptyObject(a),f=p.speed(b,c,d),g=function(){var b=cW(this,p.extend({},a),f);e&&b.stop(!0)};return e||f.queue===!1?this.each(g):this.queue(f.queue,g)},stop:function(a,c,d){var e=function(a){var b=a.stop;delete a.stop,b(d)};return typeof a!="string"&&(d=c,c=a,a=b),c&&a!==!1&&this.queue(a||"fx",[]),this.each(function(){var b=!0,c=a!=null&&a+"queueHooks",f=p.timers,g=p._data(this);if(c)g[c]&&g[c].stop&&e(g[c]);else for(c in g)g[c]&&g[c].stop&&cR.test(c)&&e(g[c]);for(c=f.length;c--;)f[c].elem===this&&(a==null||f[c].queue===a)&&(f[c].anim.stop(d),b=!1,f.splice(c,1));(b||!d)&&p.dequeue(this,a)})}}),p.each({slideDown:c$("show"),slideUp:c$("hide"),slideToggle:c$("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){p.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),p.speed=function(a,b,c){var d=a&&typeof a=="object"?p.extend({},a):{complete:c||!c&&b||p.isFunction(a)&&a,duration:a,easing:c&&b||b&&!p.isFunction(b)&&b};d.duration=p.fx.off?0:typeof d.duration=="number"?d.duration:d.duration in p.fx.speeds?p.fx.speeds[d.duration]:p.fx.speeds._default;if(d.queue==null||d.queue===!0)d.queue="fx";return d.old=d.complete,d.complete=function(){p.isFunction(d.old)&&d.old.call(this),d.queue&&p.dequeue(this,d.queue)},d},p.easing={linear:function(a){return a},swing:function(a){return.5-Math.cos(a*Math.PI)/2}},p.timers=[],p.fx=cZ.prototype.init,p.fx.tick=function(){var a,b=p.timers,c=0;for(;c<b.length;c++)a=b[c],!a()&&b[c]===a&&b.splice(c--,1);b.length||p.fx.stop()},p.fx.timer=function(a){a()&&p.timers.push(a)&&!cO&&(cO=setInterval(p.fx.tick,p.fx.interval))},p.fx.interval=13,p.fx.stop=function(){clearInterval(cO),cO=null},p.fx.speeds={slow:600,fast:200,_default:400},p.fx.step={},p.expr&&p.expr.filters&&(p.expr.filters.animated=function(a){return p.grep(p.timers,function(b){return a===b.elem}).length});var c_=/^(?:body|html)$/i;p.fn.offset=function(a){if(arguments.length)return a===b?this:this.each(function(b){p.offset.setOffset(this,a,b)});var c,d,e,f,g,h,i,j={top:0,left:0},k=this[0],l=k&&k.ownerDocument;if(!l)return;return(d=l.body)===k?p.offset.bodyOffset(k):(c=l.documentElement,p.contains(c,k)?(typeof k.getBoundingClientRect!="undefined"&&(j=k.getBoundingClientRect()),e=da(l),f=c.clientTop||d.clientTop||0,g=c.clientLeft||d.clientLeft||0,h=e.pageYOffset||c.scrollTop,i=e.pageXOffset||c.scrollLeft,{top:j.top+h-f,left:j.left+i-g}):j)},p.offset={bodyOffset:function(a){var b=a.offsetTop,c=a.offsetLeft;return p.support.doesNotIncludeMarginInBodyOffset&&(b+=parseFloat(p.css(a,"marginTop"))||0,c+=parseFloat(p.css(a,"marginLeft"))||0),{top:b,left:c}},setOffset:function(a,b,c){var d=p.css(a,"position");d==="static"&&(a.style.position="relative");var e=p(a),f=e.offset(),g=p.css(a,"top"),h=p.css(a,"left"),i=(d==="absolute"||d==="fixed")&&p.inArray("auto",[g,h])>-1,j={},k={},l,m;i?(k=e.position(),l=k.top,m=k.left):(l=parseFloat(g)||0,m=parseFloat(h)||0),p.isFunction(b)&&(b=b.call(a,c,f)),b.top!=null&&(j.top=b.top-f.top+l),b.left!=null&&(j.left=b.left-f.left+m),"using"in b?b.using.call(a,j):e.css(j)}},p.fn.extend({position:function(){if(!this[0])return;var a=this[0],b=this.offsetParent(),c=this.offset(),d=c_.test(b[0].nodeName)?{top:0,left:0}:b.offset();return c.top-=parseFloat(p.css(a,"marginTop"))||0,c.left-=parseFloat(p.css(a,"marginLeft"))||0,d.top+=parseFloat(p.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(p.css(b[0],"borderLeftWidth"))||0,{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||e.body;while(a&&!c_.test(a.nodeName)&&p.css(a,"position")==="static")a=a.offsetParent;return a||e.body})}}),p.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(a,c){var d=/Y/.test(c);p.fn[a]=function(e){return p.access(this,function(a,e,f){var g=da(a);if(f===b)return g?c in g?g[c]:g.document.documentElement[e]:a[e];g?g.scrollTo(d?p(g).scrollLeft():f,d?f:p(g).scrollTop()):a[e]=f},a,e,arguments.length,null)}}),p.each({Height:"height",Width:"width"},function(a,c){p.each({padding:"inner"+a,content:c,"":"outer"+a},function(d,e){p.fn[e]=function(e,f){var g=arguments.length&&(d||typeof e!="boolean"),h=d||(e===!0||f===!0?"margin":"border");return p.access(this,function(c,d,e){var f;return p.isWindow(c)?c.document.documentElement["client"+a]:c.nodeType===9?(f=c.documentElement,Math.max(c.body["scroll"+a],f["scroll"+a],c.body["offset"+a],f["offset"+a],f["client"+a])):e===b?p.css(c,d,e,h):p.style(c,d,e,h)},c,g?e:b,g,null)}})}),a.jQuery=a.$=p,typeof define=="function"&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return p})})(window);`,
+
+	"jquery.treeview.css": `/* https://github.com/jzaefferer/jquery-treeview/blob/master/jquery.treeview.css */
+/* License: MIT. */
+.treeview, .treeview ul {
+	padding: 0;
+	margin: 0;
+	list-style: none;
+}
+
+.treeview ul {
+	background-color: white;
+	margin-top: 4px;
+}
+
+.treeview .hitarea {
+	background: url(images/treeview-default.gif) -64px -25px no-repeat;
+	height: 16px;
+	width: 16px;
+	margin-left: -16px;
+	float: left;
+	cursor: pointer;
+}
+/* fix for IE6 */
+* html .hitarea {
+	display: inline;
+	float:none;
+}
+
+.treeview li {
+	margin: 0;
+	padding: 3px 0pt 3px 16px;
+}
+
+.treeview a.selected {
+	background-color: #eee;
+}
+
+#treecontrol { margin: 1em 0; display: none; }
+
+.treeview .hover { color: red; cursor: pointer; }
+
+.treeview li { background: url(images/treeview-default-line.gif) 0 0 no-repeat; }
+.treeview li.collapsable, .treeview li.expandable { background-position: 0 -176px; }
+
+.treeview .expandable-hitarea { background-position: -80px -3px; }
+
+.treeview li.last { background-position: 0 -1766px }
+.treeview li.lastCollapsable, .treeview li.lastExpandable { background-image: url(images/treeview-default.gif); }
+.treeview li.lastCollapsable { background-position: 0 -111px }
+.treeview li.lastExpandable { background-position: -32px -67px }
+
+.treeview div.lastCollapsable-hitarea, .treeview div.lastExpandable-hitarea { background-position: 0; }
+
+.treeview-red li { background-image: url(images/treeview-red-line.gif); }
+.treeview-red .hitarea, .treeview-red li.lastCollapsable, .treeview-red li.lastExpandable { background-image: url(images/treeview-red.gif); }
+
+.treeview-black li { background-image: url(images/treeview-black-line.gif); }
+.treeview-black .hitarea, .treeview-black li.lastCollapsable, .treeview-black li.lastExpandable { background-image: url(images/treeview-black.gif); }
+
+.treeview-gray li { background-image: url(images/treeview-gray-line.gif); }
+.treeview-gray .hitarea, .treeview-gray li.lastCollapsable, .treeview-gray li.lastExpandable { background-image: url(images/treeview-gray.gif); }
+
+.treeview-famfamfam li { background-image: url(images/treeview-famfamfam-line.gif); }
+.treeview-famfamfam .hitarea, .treeview-famfamfam li.lastCollapsable, .treeview-famfamfam li.lastExpandable { background-image: url(images/treeview-famfamfam.gif); }
+
+.treeview .placeholder {
+	background: url(images/ajax-loader.gif) 0 0 no-repeat;
+	height: 16px;
+	width: 16px;
+	display: block;
+}
+
+.filetree li { padding: 3px 0 2px 16px; }
+.filetree span.folder, .filetree span.file { padding: 1px 0 1px 16px; display: block; }
+.filetree span.folder { background: url(images/folder.gif) 0 0 no-repeat; }
+.filetree li.expandable span.folder { background: url(images/folder-closed.gif) 0 0 no-repeat; }
+.filetree span.file { background: url(images/file.gif) 0 0 no-repeat; }
+`,
+
+	"jquery.treeview.edit.js": `/* https://github.com/jzaefferer/jquery-treeview/blob/master/jquery.treeview.edit.js */
+/* License: MIT. */
+(function($) {
+	var CLASSES = $.treeview.classes;
+	var proxied = $.fn.treeview;
+	$.fn.treeview = function(settings) {
+		settings = $.extend({}, settings);
+		if (settings.add) {
+			return this.trigger("add", [settings.add]);
+		}
+		if (settings.remove) {
+			return this.trigger("remove", [settings.remove]);
+		}
+		return proxied.apply(this, arguments).bind("add", function(event, branches) {
+			$(branches).prev()
+				.removeClass(CLASSES.last)
+				.removeClass(CLASSES.lastCollapsable)
+				.removeClass(CLASSES.lastExpandable)
+			.find(">.hitarea")
+				.removeClass(CLASSES.lastCollapsableHitarea)
+				.removeClass(CLASSES.lastExpandableHitarea);
+			$(branches).find("li").andSelf().prepareBranches(settings).applyClasses(settings, $(this).data("toggler"));
+		}).bind("remove", function(event, branches) {
+			var prev = $(branches).prev();
+			var parent = $(branches).parent();
+			$(branches).remove();
+			prev.filter(":last-child").addClass(CLASSES.last)
+				.filter("." + CLASSES.expandable).replaceClass(CLASSES.last, CLASSES.lastExpandable).end()
+				.find(">.hitarea").replaceClass(CLASSES.expandableHitarea, CLASSES.lastExpandableHitarea).end()
+				.filter("." + CLASSES.collapsable).replaceClass(CLASSES.last, CLASSES.lastCollapsable).end()
+				.find(">.hitarea").replaceClass(CLASSES.collapsableHitarea, CLASSES.lastCollapsableHitarea);
+			if (parent.is(":not(:has(>))") && parent[0] != this) {
+				parent.parent().removeClass(CLASSES.collapsable).removeClass(CLASSES.expandable)
+				parent.siblings(".hitarea").andSelf().remove();
+			}
+		});
+	};
+	
+})(jQuery);
+`,
+
+	"jquery.treeview.js": `/*
+ * Treeview 1.4.1 - jQuery plugin to hide and show branches of a tree
+ * 
+ * http://bassistance.de/jquery-plugins/jquery-plugin-treeview/
+ * http://docs.jquery.com/Plugins/Treeview
+ *
+ * Copyright (c) 2007 Jörn Zaefferer
+ *
+ * Dual licensed under the MIT and GPL licenses:
+ *   http://www.opensource.org/licenses/mit-license.php
+ *   http://www.gnu.org/licenses/gpl.html
+ *
+ * Revision: $Id: jquery.treeview.js 5759 2008-07-01 07:50:28Z joern.zaefferer $
+ *
+ */
+
+;(function($) {
+
+	// TODO rewrite as a widget, removing all the extra plugins
+	$.extend($.fn, {
+		swapClass: function(c1, c2) {
+			var c1Elements = this.filter('.' + c1);
+			this.filter('.' + c2).removeClass(c2).addClass(c1);
+			c1Elements.removeClass(c1).addClass(c2);
+			return this;
+		},
+		replaceClass: function(c1, c2) {
+			return this.filter('.' + c1).removeClass(c1).addClass(c2).end();
+		},
+		hoverClass: function(className) {
+			className = className || "hover";
+			return this.hover(function() {
+				$(this).addClass(className);
+			}, function() {
+				$(this).removeClass(className);
+			});
+		},
+		heightToggle: function(animated, callback) {
+			animated ?
+				this.animate({ height: "toggle" }, animated, callback) :
+				this.each(function(){
+					jQuery(this)[ jQuery(this).is(":hidden") ? "show" : "hide" ]();
+					if(callback)
+						callback.apply(this, arguments);
+				});
+		},
+		heightHide: function(animated, callback) {
+			if (animated) {
+				this.animate({ height: "hide" }, animated, callback);
+			} else {
+				this.hide();
+				if (callback)
+					this.each(callback);				
+			}
+		},
+		prepareBranches: function(settings) {
+			if (!settings.prerendered) {
+				// mark last tree items
+				this.filter(":last-child:not(ul)").addClass(CLASSES.last);
+				// collapse whole tree, or only those marked as closed, anyway except those marked as open
+				this.filter((settings.collapsed ? "" : "." + CLASSES.closed) + ":not(." + CLASSES.open + ")").find(">ul").hide();
+			}
+			// return all items with sublists
+			return this.filter(":has(>ul)");
+		},
+		applyClasses: function(settings, toggler) {
+			// TODO use event delegation
+			this.filter(":has(>ul):not(:has(>a))").find(">span").unbind("click.treeview").bind("click.treeview", function(event) {
+				// don't handle click events on children, eg. checkboxes
+				if ( this == event.target )
+					toggler.apply($(this).next());
+			}).add( $("a", this) ).hoverClass();
+			
+			if (!settings.prerendered) {
+				// handle closed ones first
+				this.filter(":has(>ul:hidden)")
+						.addClass(CLASSES.expandable)
+						.replaceClass(CLASSES.last, CLASSES.lastExpandable);
+						
+				// handle open ones
+				this.not(":has(>ul:hidden)")
+						.addClass(CLASSES.collapsable)
+						.replaceClass(CLASSES.last, CLASSES.lastCollapsable);
+						
+	            // create hitarea if not present
+				var hitarea = this.find("div." + CLASSES.hitarea);
+				if (!hitarea.length)
+					hitarea = this.prepend("<div class=\"" + CLASSES.hitarea + "\"/>").find("div." + CLASSES.hitarea);
+				hitarea.removeClass().addClass(CLASSES.hitarea).each(function() {
+					var classes = "";
+					$.each($(this).parent().attr("class").split(" "), function() {
+						classes += this + "-hitarea ";
+					});
+					$(this).addClass( classes );
+				})
+			}
+			
+			// apply event to hitarea
+			this.find("div." + CLASSES.hitarea).click( toggler );
+		},
+		treeview: function(settings) {
+			
+			settings = $.extend({
+				cookieId: "treeview"
+			}, settings);
+			
+			if ( settings.toggle ) {
+				var callback = settings.toggle;
+				settings.toggle = function() {
+					return callback.apply($(this).parent()[0], arguments);
+				};
+			}
+		
+			// factory for treecontroller
+			function treeController(tree, control) {
+				// factory for click handlers
+				function handler(filter) {
+					return function() {
+						// reuse toggle event handler, applying the elements to toggle
+						// start searching for all hitareas
+						toggler.apply( $("div." + CLASSES.hitarea, tree).filter(function() {
+							// for plain toggle, no filter is provided, otherwise we need to check the parent element
+							return filter ? $(this).parent("." + filter).length : true;
+						}) );
+						return false;
+					};
+				}
+				// click on first element to collapse tree
+				$("a:eq(0)", control).click( handler(CLASSES.collapsable) );
+				// click on second to expand tree
+				$("a:eq(1)", control).click( handler(CLASSES.expandable) );
+				// click on third to toggle tree
+				$("a:eq(2)", control).click( handler() ); 
+			}
+		
+			// handle toggle event
+			function toggler() {
+				$(this)
+					.parent()
+					// swap classes for hitarea
+					.find(">.hitarea")
+						.swapClass( CLASSES.collapsableHitarea, CLASSES.expandableHitarea )
+						.swapClass( CLASSES.lastCollapsableHitarea, CLASSES.lastExpandableHitarea )
+					.end()
+					// swap classes for parent li
+					.swapClass( CLASSES.collapsable, CLASSES.expandable )
+					.swapClass( CLASSES.lastCollapsable, CLASSES.lastExpandable )
+					// find child lists
+					.find( ">ul" )
+					// toggle them
+					.heightToggle( settings.animated, settings.toggle );
+				if ( settings.unique ) {
+					$(this).parent()
+						.siblings()
+						// swap classes for hitarea
+						.find(">.hitarea")
+							.replaceClass( CLASSES.collapsableHitarea, CLASSES.expandableHitarea )
+							.replaceClass( CLASSES.lastCollapsableHitarea, CLASSES.lastExpandableHitarea )
+						.end()
+						.replaceClass( CLASSES.collapsable, CLASSES.expandable )
+						.replaceClass( CLASSES.lastCollapsable, CLASSES.lastExpandable )
+						.find( ">ul" )
+						.heightHide( settings.animated, settings.toggle );
+				}
+			}
+			this.data("toggler", toggler);
+			
+			function serialize() {
+				function binary(arg) {
+					return arg ? 1 : 0;
+				}
+				var data = [];
+				branches.each(function(i, e) {
+					data[i] = $(e).is(":has(>ul:visible)") ? 1 : 0;
+				});
+				$.cookie(settings.cookieId, data.join(""), settings.cookieOptions );
+			}
+			
+			function deserialize() {
+				var stored = $.cookie(settings.cookieId);
+				if ( stored ) {
+					var data = stored.split("");
+					branches.each(function(i, e) {
+						$(e).find(">ul")[ parseInt(data[i]) ? "show" : "hide" ]();
+					});
+				}
+			}
+			
+			// add treeview class to activate styles
+			this.addClass("treeview");
+			
+			// prepare branches and find all tree items with child lists
+			var branches = this.find("li").prepareBranches(settings);
+			
+			switch(settings.persist) {
+			case "cookie":
+				var toggleCallback = settings.toggle;
+				settings.toggle = function() {
+					serialize();
+					if (toggleCallback) {
+						toggleCallback.apply(this, arguments);
+					}
+				};
+				deserialize();
+				break;
+			case "location":
+				var current = this.find("a").filter(function() {
+					return this.href.toLowerCase() == location.href.toLowerCase();
+				});
+				if ( current.length ) {
+					// TODO update the open/closed classes
+					var items = current.addClass("selected").parents("ul, li").add( current.next() ).show();
+					if (settings.prerendered) {
+						// if prerendered is on, replicate the basic class swapping
+						items.filter("li")
+							.swapClass( CLASSES.collapsable, CLASSES.expandable )
+							.swapClass( CLASSES.lastCollapsable, CLASSES.lastExpandable )
+							.find(">.hitarea")
+								.swapClass( CLASSES.collapsableHitarea, CLASSES.expandableHitarea )
+								.swapClass( CLASSES.lastCollapsableHitarea, CLASSES.lastExpandableHitarea );
+					}
+				}
+				break;
+			}
+			
+			branches.applyClasses(settings, toggler);
+				
+			// if control option is set, create the treecontroller and show it
+			if ( settings.control ) {
+				treeController(this, settings.control);
+				$(settings.control).show();
+			}
+			
+			return this;
+		}
+	});
+	
+	// classes used by the plugin
+	// need to be styled via external stylesheet, see first example
+	$.treeview = {};
+	var CLASSES = ($.treeview.classes = {
+		open: "open",
+		closed: "closed",
+		expandable: "expandable",
+		expandableHitarea: "expandable-hitarea",
+		lastExpandableHitarea: "lastExpandable-hitarea",
+		collapsable: "collapsable",
+		collapsableHitarea: "collapsable-hitarea",
+		lastCollapsableHitarea: "lastCollapsable-hitarea",
+		lastCollapsable: "lastCollapsable",
+		lastExpandable: "lastExpandable",
+		last: "last",
+		hitarea: "hitarea"
+	});
+	
+})(jQuery);
+`,
+
+	"methodset.html": `<div class="toggle" style="display: none">
+	<div class="collapsed">
+		<p class="exampleHeading toggleButton">▹ <span class="text">Method set</span></p>
+	</div>
+	<div class="expanded">
+		<p class="exampleHeading toggleButton">▾ <span class="text">Method set</span></p>
+		<div style="margin-left: 1in" id='methodset-{{.Index}}'>...</div>
+	</div>
+</div>
+`,
+
+	"opensearch.xml": `<?xml version="1.0" encoding="UTF-8"?>
+<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/">
+  <ShortName>godoc</ShortName>
+  <Description>The Go Programming Language</Description>
+  <Tags>go golang</Tags>
+  <Contact />
+  <Url type="text/html" template="{{.BaseURL}}/search?q={searchTerms}" />
+  <Image height="15" width="16" type="image/x-icon">/favicon.ico</Image>
+  <OutputEncoding>UTF-8</OutputEncoding>
+  <InputEncoding>UTF-8</InputEncoding>
+</OpenSearchDescription>
+`,
+
+	"package.html": `<!--
+	Copyright 2009 The Go Authors. All rights reserved.
+	Use of this source code is governed by a BSD-style
+	license that can be found in the LICENSE file.
+-->
+<!--
+	Note: Static (i.e., not template-generated) href and id
+	attributes start with "pkg-" to make it impossible for
+	them to conflict with generated attributes (some of which
+	correspond to Go identifiers).
+-->
+{{with .PDoc}}
+	<script type='text/javascript'>
+	document.ANALYSIS_DATA = {{$.AnalysisData}};
+	document.CALLGRAPH = {{$.CallGraph}};
+	</script>
+
+	{{if $.IsMain}}
+		{{/* command documentation */}}
+		{{comment_html .Doc}}
+	{{else}}
+		{{/* package documentation */}}
+		<div id="short-nav">
+			<dl>
+			<dd><code>import "{{html .ImportPath}}"</code></dd>
+			</dl>
+			<dl>
+			<dd><a href="#pkg-overview" class="overviewLink">Overview</a></dd>
+			<dd><a href="#pkg-index" class="indexLink">Index</a></dd>
+			{{if $.Examples}}
+				<dd><a href="#pkg-examples" class="examplesLink">Examples</a></dd>
+			{{end}}
+			{{if $.Dirs}}
+				<dd><a href="#pkg-subdirectories">Subdirectories</a></dd>
+			{{end}}
+			</dl>
+		</div>
+		<!-- The package's Name is printed as title by the top-level template -->
+		<div id="pkg-overview" class="toggleVisible">
+			<div class="collapsed">
+				<h2 class="toggleButton" title="Click to show Overview section">Overview ▹</h2>
+			</div>
+			<div class="expanded">
+				<h2 class="toggleButton" title="Click to hide Overview section">Overview ▾</h2>
+				{{comment_html .Doc}}
+			</div>
+		</div>
+		{{example_html $ ""}}
+
+		<div id="pkg-index" class="toggleVisible">
+		<div class="collapsed">
+			<h2 class="toggleButton" title="Click to show Index section">Index ▹</h2>
+		</div>
+		<div class="expanded">
+			<h2 class="toggleButton" title="Click to hide Index section">Index ▾</h2>
+
+		<!-- Table of contents for API; must be named manual-nav to turn off auto nav. -->
+			<div id="manual-nav">
+			<dl>
+			{{if .Consts}}
+				<dd><a href="#pkg-constants">Constants</a></dd>
+			{{end}}
+			{{if .Vars}}
+				<dd><a href="#pkg-variables">Variables</a></dd>
+			{{end}}
+			{{range .Funcs}}
+				{{$name_html := html .Name}}
+				<dd><a href="#{{$name_html}}">{{node_html $ .Decl false | sanitize}}</a></dd>
+			{{end}}
+			{{range .Types}}
+				{{$tname_html := html .Name}}
+				<dd><a href="#{{$tname_html}}">type {{$tname_html}}</a></dd>
+				{{range .Funcs}}
+					{{$name_html := html .Name}}
+					<dd>&nbsp; &nbsp; <a href="#{{$name_html}}">{{node_html $ .Decl false | sanitize}}</a></dd>
+				{{end}}
+				{{range .Methods}}
+					{{$name_html := html .Name}}
+					<dd>&nbsp; &nbsp; <a href="#{{$tname_html}}.{{$name_html}}">{{node_html $ .Decl false | sanitize}}</a></dd>
+				{{end}}
+			{{end}}
+			{{if $.Notes}}
+				{{range $marker, $item := $.Notes}}
+				<dd><a href="#pkg-note-{{$marker}}">{{noteTitle $marker | html}}s</a></dd>
+				{{end}}
+			{{end}}
+			</dl>
+			</div><!-- #manual-nav -->
+
+		{{if $.Examples}}
+		<div id="pkg-examples">
+			<h4>Examples</h4>
+			<dl>
+			{{range $.Examples}}
+			<dd><a class="exampleLink" href="#example_{{.Name}}">{{example_name .Name}}</a></dd>
+			{{end}}
+			</dl>
+		</div>
+		{{end}}
+
+		{{with .Filenames}}
+			<h4>Package files</h4>
+			<p>
+			<span style="font-size:90%">
+			{{range .}}
+				<a href="{{.|srcLink|html}}">{{.|filename|html}}</a>
+			{{end}}
+			</span>
+			</p>
+		{{end}}
+		</div><!-- .expanded -->
+		</div><!-- #pkg-index -->
+
+		<div id="pkg-callgraph" class="toggle" style="display: none">
+		<div class="collapsed">
+			<h2 class="toggleButton" title="Click to show Internal Call Graph section">Internal call graph ▹</h2>
+		</div> <!-- .expanded -->
+		<div class="expanded">
+			<h2 class="toggleButton" title="Click to hide Internal Call Graph section">Internal call graph ▾</h2>
+			<p>
+			  In the call graph viewer below, each node
+			  is a function belonging to this package
+			  and its children are the functions it
+			  calls&mdash;perhaps dynamically.
+			</p>
+			<p>
+			  The root nodes are the entry points of the
+			  package: functions that may be called from
+			  outside the package.
+			  There may be non-exported or anonymous
+			  functions among them if they are called
+			  dynamically from another package.
+			</p>
+			<p>
+			  Click a node to visit that function's source code.
+			  From there you can visit its callers by
+			  clicking its declaring <code>func</code>
+			  token.
+			</p>
+			<p>
+			  Functions may be omitted if they were
+			  determined to be unreachable in the
+			  particular programs or tests that were
+			  analyzed.
+			</p>
+			<!-- Zero means show all package entry points. -->
+			<ul style="margin-left: 0.5in" id="callgraph-0" class="treeview"></ul>
+		</div>
+		</div> <!-- #pkg-callgraph -->
+
+		{{with .Consts}}
+			<h2 id="pkg-constants">Constants</h2>
+			{{range .}}
+				<pre>{{node_html $ .Decl true}}</pre>
+				{{comment_html .Doc}}
+			{{end}}
+		{{end}}
+		{{with .Vars}}
+			<h2 id="pkg-variables">Variables</h2>
+			{{range .}}
+				<pre>{{node_html $ .Decl true}}</pre>
+				{{comment_html .Doc}}
+			{{end}}
+		{{end}}
+		{{range .Funcs}}
+			{{/* Name is a string - no need for FSet */}}
+			{{$name_html := html .Name}}
+			<h2 id="{{$name_html}}">func <a href="{{posLink_url $ .Decl}}">{{$name_html}}</a></h2>
+			<pre>{{node_html $ .Decl true}}</pre>
+			{{comment_html .Doc}}
+			{{example_html $ .Name}}
+			{{callgraph_html $ "" .Name}}
+
+		{{end}}
+		{{range .Types}}
+			{{$tname := .Name}}
+			{{$tname_html := html .Name}}
+			<h2 id="{{$tname_html}}">type <a href="{{posLink_url $ .Decl}}">{{$tname_html}}</a></h2>
+			<pre>{{node_html $ .Decl true}}</pre>
+			{{comment_html .Doc}}
+
+			{{range .Consts}}
+				<pre>{{node_html $ .Decl true}}</pre>
+				{{comment_html .Doc}}
+			{{end}}
+
+			{{range .Vars}}
+				<pre>{{node_html $ .Decl true}}</pre>
+				{{comment_html .Doc}}
+			{{end}}
+
+			{{example_html $ $tname}}
+			{{implements_html $ $tname}}
+			{{methodset_html $ $tname}}
+
+			{{range .Funcs}}
+				{{$name_html := html .Name}}
+				<h3 id="{{$name_html}}">func <a href="{{posLink_url $ .Decl}}">{{$name_html}}</a></h3>
+				<pre>{{node_html $ .Decl true}}</pre>
+				{{comment_html .Doc}}
+				{{example_html $ .Name}}
+				{{callgraph_html $ "" .Name}}
+			{{end}}
+
+			{{range .Methods}}
+				{{$name_html := html .Name}}
+				<h3 id="{{$tname_html}}.{{$name_html}}">func ({{html .Recv}}) <a href="{{posLink_url $ .Decl}}">{{$name_html}}</a></h3>
+				<pre>{{node_html $ .Decl true}}</pre>
+				{{comment_html .Doc}}
+				{{$name := printf "%s_%s" $tname .Name}}
+				{{example_html $ $name}}
+				{{callgraph_html $ .Recv .Name}}
+			{{end}}
+		{{end}}
+	{{end}}
+
+	{{with $.Notes}}
+		{{range $marker, $content := .}}
+			<h2 id="pkg-note-{{$marker}}">{{noteTitle $marker | html}}s</h2>
+			<ul style="list-style: none; padding: 0;">
+			{{range .}}
+			<li><a href="{{posLink_url $ .}}">&#x261e;</a> {{html .Body}}</li>
+			{{end}}
+			</ul>
+		{{end}}
+	{{end}}
+{{end}}
+
+{{with .PAst}}
+	{{range $filename, $ast := .}}
+		<a href="{{$filename|srcLink|html}}">{{$filename|filename|html}}</a>:<pre>{{node_html $ $ast false}}</pre>
+	{{end}}
+{{end}}
+
+{{with .Dirs}}
+	{{/* DirList entries are numbers and strings - no need for FSet */}}
+	{{if $.PDoc}}
+		<h2 id="pkg-subdirectories">Subdirectories</h2>
+	{{end}}
+	{{if eq $.Dirname "/src"}}
+		<div id="manual-nav">
+			<dl>
+				<dt><a href="#stdlib">Standard library</a></dt>
+				<dt><a href="#other">Other packages</a></dt>
+				<dd><a href="#subrepo">Sub-repositories</a></dd>
+				<dd><a href="#community">Community</a></dd>
+			</dl>
+		</div>
+		<h2 id="stdlib">Standard library</h2>
+		<img class="gopher" src="/doc/gopher/pkg.png"/>
+	{{end}}
+
+
+	<div class="pkg-dir">
+		<table>
+			<tr>
+				<th class="pkg-name">Name</th>
+				<th class="pkg-synopsis">Synopsis</th>
+			</tr>
+
+			{{if not (or (eq $.Dirname "/src") (eq $.Dirname "/src/cmd") $.DirFlat)}}
+			<tr>
+				<td colspan="2"><a href="..">..</a></td>
+			</tr>
+			{{end}}
+
+			{{range .List}}
+				{{if $.DirFlat}}
+					{{if .HasPkg}}
+						<tr>
+							<td class="pkg-name">
+								<a href="{{html .Path}}/">{{html .Path}}</a>
+							</td>
+							<td class="pkg-synopsis">
+								{{html .Synopsis}}
+							</td>
+						</tr>
+					{{end}}
+				{{else}}
+					<tr>
+						<td class="pkg-name" style="padding-left: {{multiply .Depth 20}}px;">
+							<a href="{{html .Path}}/">{{html .Name}}</a>
+						</td>
+						<td class="pkg-synopsis">
+							{{html .Synopsis}}
+						</td>
+					</tr>
+				{{end}}
+			{{end}}
+		</table>
+	</div>
+
+
+	{{if eq $.Dirname "/src"}}
+	<h2 id="other">Other packages</h2>
+
+	<h3 id="subrepo">Sub-repositories</h3>
+	<p>
+	These packages are part of the Go Project but outside the main Go tree.
+	They are developed under looser <a href="/doc/go1compat">compatibility requirements</a> than the Go core.
+	Install them with "<a href="/cmd/go/#hdr-Download_and_install_packages_and_dependencies">go get</a>".
+	</p>
+	<ul>
+		<li><a href="//godoc.org/golang.org/x/benchmarks">benchmarks</a> — benchmarks to measure Go as it is developed.</li>
+		<li><a href="//godoc.org/golang.org/x/blog">blog</a> — <a href="//blog.golang.org">blog.golang.org</a>'s implementation.</li>
+		<li><a href="//godoc.org/golang.org/x/build">build</a> — <a href="//build.golang.org">build.golang.org</a>'s implementation.</li>
+		<li><a href="//godoc.org/golang.org/x/crypto">crypto</a> — additional cryptography packages.</li>
+		<li><a href="//godoc.org/golang.org/x/debug">debug</a> — an experimental debugger for Go.</li>
+		<li><a href="//godoc.org/golang.org/x/image">image</a> — additional imaging packages.</li>
+		<li><a href="//godoc.org/golang.org/x/mobile">mobile</a> — experimental support for Go on mobile platforms.</li>
+		<li><a href="//godoc.org/golang.org/x/net">net</a> — additional networking packages.</li>
+		<li><a href="//godoc.org/golang.org/x/sys">sys</a> — packages for making system calls.</li>
+		<li><a href="//godoc.org/golang.org/x/text">text</a> — packages for working with text.</li>
+		<li><a href="//godoc.org/golang.org/x/tools">tools</a> — godoc, goimports, gorename, and other tools.</li>
+		<li><a href="//godoc.org/golang.org/x/tour">tour</a> — <a href="//tour.golang.org">tour.golang.org</a>'s implementation.</li>
+		<li><a href="//godoc.org/golang.org/x/exp">exp</a> — experimental and deprecated packages (handle with care; may change without warning).</li>
+	</ul>
+
+	<h3 id="community">Community</h3>
+	<p>
+	These services can help you find Open Source packages provided by the community.
+	</p>
+	<ul>
+		<li><a href="//godoc.org">GoDoc</a> - a package index and search engine.</li>
+		<li><a href="http://go-search.org">Go Search</a> - a code search engine.</li>
+		<li><a href="/wiki/Projects">Projects at the Go Wiki</a> - a curated list of Go projects.</li>
+	</ul>
+	{{end}}
+{{end}}
+`,
+
+	"package.txt": `{{$info := .}}{{$filtered := .IsFiltered}}{{/*
+
+---------------------------------------
+
+*/}}{{if $filtered}}{{range .PAst}}{{range .Decls}}{{node $info .}}
+
+{{end}}{{end}}{{else}}{{with .PAst}}{{range $filename, $ast := .}}{{$filename}}:
+{{node $ $ast}}{{end}}{{end}}{{end}}{{/*
+
+---------------------------------------
+
+*/}}{{if and $filtered (not (or .PDoc .PAst))}}No match found.
+{{end}}{{with .PDoc}}{{if $.IsMain}}COMMAND DOCUMENTATION
+
+{{comment_text .Doc "    " "\t"}}
+{{else}}{{if not $filtered}}PACKAGE DOCUMENTATION
+
+package {{.Name}}
+    import "{{.ImportPath}}"
+
+{{comment_text .Doc "    " "\t"}}
+{{example_text $ "" "    "}}{{end}}{{/*
+
+---------------------------------------
+
+*/}}{{with .Consts}}{{if not $filtered}}CONSTANTS
+
+{{end}}{{range .}}{{node $ .Decl}}
+{{comment_text .Doc "    " "\t"}}
+{{end}}{{end}}{{/*
+
+---------------------------------------
+
+*/}}{{with .Vars}}{{if not $filtered}}VARIABLES
+
+{{end}}{{range .}}{{node $ .Decl}}
+{{comment_text .Doc "    " "\t"}}
+{{end}}{{end}}{{/*
+
+---------------------------------------
+
+*/}}{{with .Funcs}}{{if not $filtered}}FUNCTIONS
+
+{{end}}{{range .}}{{node $ .Decl}}
+{{comment_text .Doc "    " "\t"}}
+{{example_text $ .Name "    "}}{{end}}{{end}}{{/*
+
+---------------------------------------
+
+*/}}{{with .Types}}{{if not $filtered}}TYPES
+
+{{end}}{{range .}}{{$tname := .Name}}{{node $ .Decl}}
+{{comment_text .Doc "    " "\t"}}
+{{/*
+
+---------------------------------------
+
+*/}}{{if .Consts}}{{range .Consts}}{{node $ .Decl}}
+{{comment_text .Doc "    " "\t"}}
+{{end}}{{end}}{{/*
+
+---------------------------------------
+
+*/}}{{if .Vars}}{{range .Vars}}{{node $ .Decl}}
+{{comment_text .Doc "    " "\t"}}
+{{range $name := .Names}}{{example_text $ $name "    "}}{{end}}{{end}}{{end}}{{/*
+
+---------------------------------------
+
+*/}}{{if .Funcs}}{{range .Funcs}}{{node $ .Decl}}
+{{comment_text .Doc "    " "\t"}}
+{{example_text $ .Name "    "}}{{end}}{{end}}{{/*
+
+---------------------------------------
+
+*/}}{{if .Methods}}{{range .Methods}}{{node $ .Decl}}
+{{comment_text .Doc "    " "\t"}}
+{{$name := printf "%s_%s" $tname .Name}}{{example_text $ $name "    "}}{{end}}{{end}}{{/*
+
+---------------------------------------
+
+*/}}{{end}}{{end}}{{/*
+
+---------------------------------------
+
+*/}}{{if and $filtered (not (or .Consts (or .Vars (or .Funcs .Types))))}}No match found.
+{{end}}{{/*
+
+---------------------------------------
+
+*/}}{{end}}{{/*
+
+---------------------------------------
+
+*/}}{{with $.Notes}}
+{{range $marker, $content := .}}
+{{$marker}}S
+
+{{range $content}}{{comment_text .Body "   " "\t"}}
+{{end}}{{end}}{{end}}{{end}}{{/*
+
+---------------------------------------
+
+*/}}{{if not $filtered}}{{with .Dirs}}SUBDIRECTORIES
+{{if $.DirFlat}}{{range .List}}{{if .HasPkg}}
+	{{.Path}}{{end}}{{end}}
+{{else}}{{range .List}}
+	{{repeat ` + "`" + `. ` + "`" + ` .Depth}}{{.Name}}{{end}}
+{{end}}{{end}}{{/*
+
+---------------------------------------
+
+*/}}{{end}}{{/*
+Make sure there is no newline at the end of this file.
+perl -i -pe 'chomp if eof' package.txt
+*/}}
+`,
+
+	"play.js": `// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+function initPlayground(transport) {
+	"use strict";
+
+	function text(node) {
+		var s = "";
+		for (var i = 0; i < node.childNodes.length; i++) {
+			var n = node.childNodes[i];
+			if (n.nodeType === 1) {
+				if (n.tagName === "BUTTON") continue
+				if (n.tagName === "SPAN" && n.className === "number") continue;
+				if (n.tagName === "DIV" || n.tagName == "BR") {
+					s += "\n";
+				}
+				s += text(n);
+				continue;
+			}
+			if (n.nodeType === 3) {
+				s += n.nodeValue;
+			}
+		}
+		return s.replace("\xA0", " "); // replace non-breaking spaces
+	}
+
+	function init(code) {
+		var output = document.createElement('div');
+		var outpre = document.createElement('pre');
+		var running;
+
+		if ($ && $(output).resizable) {
+			$(output).resizable({
+				handles: "n,w,nw",
+				minHeight:	27,
+				minWidth:	135,
+				maxHeight: 608,
+				maxWidth:	990
+			});
+		}
+
+		function onKill() {
+			if (running) running.Kill();
+		}
+
+		function onRun(e) {
+			onKill();
+			output.style.display = "block";
+			outpre.innerHTML = "";
+			run1.style.display = "none";
+			var options = {Race: e.shiftKey};
+			running = transport.Run(text(code), PlaygroundOutput(outpre), options);
+		}
+
+		function onClose() {
+			onKill();
+			output.style.display = "none";
+			run1.style.display = "inline-block";
+		}
+
+		var run1 = document.createElement('button');
+		run1.innerHTML = 'Run';
+		run1.className = 'run';
+		run1.addEventListener("click", onRun, false);
+		var run2 = document.createElement('button');
+		run2.className = 'run';
+		run2.innerHTML = 'Run';
+		run2.addEventListener("click", onRun, false);
+		var kill = document.createElement('button');
+		kill.className = 'kill';
+		kill.innerHTML = 'Kill';
+		kill.addEventListener("click", onKill, false);
+		var close = document.createElement('button');
+		close.className = 'close';
+		close.innerHTML = 'Close';
+		close.addEventListener("click", onClose, false);
+
+		var button = document.createElement('div');
+		button.classList.add('buttons');
+		button.appendChild(run1);
+		// Hack to simulate insertAfter
+		code.parentNode.insertBefore(button, code.nextSibling);
+
+		var buttons = document.createElement('div');
+		buttons.classList.add('buttons');
+		buttons.appendChild(run2);
+		buttons.appendChild(kill);
+		buttons.appendChild(close);
+
+		output.classList.add('output');
+		output.appendChild(buttons);
+		output.appendChild(outpre);
+		output.style.display = "none";
+		code.parentNode.insertBefore(output, button.nextSibling);
+	}
+
+	var play = document.querySelectorAll('div.playground');
+	for (var i = 0; i < play.length; i++) {
+		init(play[i]);
+	}
+}
+
+`,
+
+	"playground.js": `// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+/*
+In the absence of any formal way to specify interfaces in JavaScript,
+here's a skeleton implementation of a playground transport.
+
+        function Transport() {
+                // Set up any transport state (eg, make a websocket connection).
+                return {
+                        Run: function(body, output, options) {
+                                // Compile and run the program 'body' with 'options'.
+				// Call the 'output' callback to display program output.
+                                return {
+                                        Kill: function() {
+                                                // Kill the running program.
+                                        }
+                                };
+                        }
+                };
+        }
+
+	// The output callback is called multiple times, and each time it is
+	// passed an object of this form.
+        var write = {
+                Kind: 'string', // 'start', 'stdout', 'stderr', 'end'
+                Body: 'string'  // content of write or end status message
+        }
+
+	// The first call must be of Kind 'start' with no body.
+	// Subsequent calls may be of Kind 'stdout' or 'stderr'
+	// and must have a non-null Body string.
+	// The final call should be of Kind 'end' with an optional
+	// Body string, signifying a failure ("killed", for example).
+
+	// The output callback must be of this form.
+	// See PlaygroundOutput (below) for an implementation.
+        function outputCallback(write) {
+        }
+*/
+
+function HTTPTransport() {
+	'use strict';
+
+	// TODO(adg): support stderr
+
+	function playback(output, events) {
+		var timeout;
+		output({Kind: 'start'});
+		function next() {
+			if (!events || events.length === 0) {
+				output({Kind: 'end'});
+				return;
+			}
+			var e = events.shift();
+			if (e.Delay === 0) {
+				output({Kind: 'stdout', Body: e.Message});
+				next();
+				return;
+			}
+			timeout = setTimeout(function() {
+				output({Kind: 'stdout', Body: e.Message});
+				next();
+			}, e.Delay / 1000000);
+		}
+		next();
+		return {
+			Stop: function() {
+				clearTimeout(timeout);
+			}
+		}
+	}
+
+	function error(output, msg) {
+		output({Kind: 'start'});
+		output({Kind: 'stderr', Body: msg});
+		output({Kind: 'end'});
+	}
+
+	var seq = 0;
+	return {
+		Run: function(body, output, options) {
+			seq++;
+			var cur = seq;
+			var playing;
+			$.ajax('/compile', {
+				type: 'POST',
+				data: {'version': 2, 'body': body},
+				dataType: 'json',
+				success: function(data) {
+					if (seq != cur) return;
+					if (!data) return;
+					if (playing != null) playing.Stop();
+					if (data.Errors) {
+						error(output, data.Errors);
+						return;
+					}
+					playing = playback(output, data.Events);
+				},
+				error: function() {
+					error(output, 'Error communicating with remote server.');
+				}
+			});
+			return {
+				Kill: function() {
+					if (playing != null) playing.Stop();
+					output({Kind: 'end', Body: 'killed'});
+				}
+			};
+		}
+	};
+}
+
+function SocketTransport() {
+	'use strict';
+
+	var id = 0;
+	var outputs = {};
+	var started = {};
+	var websocket = new WebSocket('ws://' + window.location.host + '/socket');
+
+	websocket.onclose = function() {
+		console.log('websocket connection closed');
+	}
+
+	websocket.onmessage = function(e) {
+		var m = JSON.parse(e.data);
+		var output = outputs[m.Id];
+		if (output === null)
+			return;
+		if (!started[m.Id]) {
+			output({Kind: 'start'});
+			started[m.Id] = true;
+		}
+		output({Kind: m.Kind, Body: m.Body});
+	}
+
+	function send(m) {
+		websocket.send(JSON.stringify(m));
+	}
+
+	return {
+		Run: function(body, output, options) {
+			var thisID = id+'';
+			id++;
+			outputs[thisID] = output;
+			send({Id: thisID, Kind: 'run', Body: body, Options: options});
+			return {
+				Kill: function() {
+					send({Id: thisID, Kind: 'kill'});
+				}
+			};
+		}
+	};
+}
+
+function PlaygroundOutput(el) {
+	'use strict';
+
+	return function(write) {
+		if (write.Kind == 'start') {
+			el.innerHTML = '';
+			return;
+		}
+
+		var cl = 'system';
+		if (write.Kind == 'stdout' || write.Kind == 'stderr')
+			cl = write.Kind;
+
+		var m = write.Body;
+		if (write.Kind == 'end') 
+			m = '\nProgram exited' + (m?(': '+m):'.');
+
+		if (m.indexOf('IMAGE:') === 0) {
+			// TODO(adg): buffer all writes before creating image
+			var url = 'data:image/png;base64,' + m.substr(6);
+			var img = document.createElement('img');
+			img.src = url;
+			el.appendChild(img);
+			return;
+		}
+
+		// ^L clears the screen.
+		var s = m.split('\x0c');
+		if (s.length > 1) {
+			el.innerHTML = '';
+			m = s.pop();
+		}
+
+		m = m.replace(/&/g, '&amp;');
+		m = m.replace(/</g, '&lt;');
+		m = m.replace(/>/g, '&gt;');
+
+		var needScroll = (el.scrollTop + el.offsetHeight) == el.scrollHeight;
+
+		var span = document.createElement('span');
+		span.className = cl;
+		span.innerHTML = m;
+		el.appendChild(span);
+
+		if (needScroll)
+			el.scrollTop = el.scrollHeight - el.offsetHeight;
+	}
+}
+
+(function() {
+  function lineHighlight(error) {
+    var regex = /prog.go:([0-9]+)/g;
+    var r = regex.exec(error);
+    while (r) {
+      $(".lines div").eq(r[1]-1).addClass("lineerror");
+      r = regex.exec(error);
+    }
+  }
+  function highlightOutput(wrappedOutput) {
+    return function(write) {
+      if (write.Body) lineHighlight(write.Body);
+      wrappedOutput(write);
+    }
+  }
+  function lineClear() {
+    $(".lineerror").removeClass("lineerror");
+  }
+
+  // opts is an object with these keys
+  //  codeEl - code editor element
+  //  outputEl - program output element
+  //  runEl - run button element
+  //  fmtEl - fmt button element (optional)
+  //  fmtImportEl - fmt "imports" checkbox element (optional)
+  //  shareEl - share button element (optional)
+  //  shareURLEl - share URL text input element (optional)
+  //  shareRedirect - base URL to redirect to on share (optional)
+  //  toysEl - toys select element (optional)
+  //  enableHistory - enable using HTML5 history API (optional)
+  //  transport - playground transport to use (default is HTTPTransport)
+  function playground(opts) {
+    var code = $(opts.codeEl);
+    var transport = opts['transport'] || new HTTPTransport();
+    var running;
+  
+    // autoindent helpers.
+    function insertTabs(n) {
+      // find the selection start and end
+      var start = code[0].selectionStart;
+      var end   = code[0].selectionEnd;
+      // split the textarea content into two, and insert n tabs
+      var v = code[0].value;
+      var u = v.substr(0, start);
+      for (var i=0; i<n; i++) {
+        u += "\t";
+      }
+      u += v.substr(end);
+      // set revised content
+      code[0].value = u;
+      // reset caret position after inserted tabs
+      code[0].selectionStart = start+n;
+      code[0].selectionEnd = start+n;
+    }
+    function autoindent(el) {
+      var curpos = el.selectionStart;
+      var tabs = 0;
+      while (curpos > 0) {
+        curpos--;
+        if (el.value[curpos] == "\t") {
+          tabs++;
+        } else if (tabs > 0 || el.value[curpos] == "\n") {
+          break;
+        }
+      }
+      setTimeout(function() {
+        insertTabs(tabs);
+      }, 1);
+    }
+  
+    function keyHandler(e) {
+      if (e.keyCode == 9 && !e.ctrlKey) { // tab (but not ctrl-tab)
+        insertTabs(1);
+        e.preventDefault();
+        return false;
+      }
+      if (e.keyCode == 13) { // enter
+        if (e.shiftKey) { // +shift
+          run();
+          e.preventDefault();
+          return false;
+        } if (e.ctrlKey) { // +control
+          fmt();
+          e.preventDefault();
+        } else {
+          autoindent(e.target);
+        }
+      }
+      return true;
+    }
+    code.unbind('keydown').bind('keydown', keyHandler);
+    var outdiv = $(opts.outputEl).empty();
+    var output = $('<pre/>').appendTo(outdiv);
+  
+    function body() {
+      return $(opts.codeEl).val();
+    }
+    function setBody(text) {
+      $(opts.codeEl).val(text);
+    }
+    function origin(href) {
+      return (""+href).split("/").slice(0, 3).join("/");
+    }
+  
+    var pushedEmpty = (window.location.pathname == "/");
+    function inputChanged() {
+      if (pushedEmpty) {
+        return;
+      }
+      pushedEmpty = true;
+      $(opts.shareURLEl).hide();
+      window.history.pushState(null, "", "/");
+    }
+    function popState(e) {
+      if (e === null) {
+        return;
+      }
+      if (e && e.state && e.state.code) {
+        setBody(e.state.code);
+      }
+    }
+    var rewriteHistory = false;
+    if (window.history && window.history.pushState && window.addEventListener && opts.enableHistory) {
+      rewriteHistory = true;
+      code[0].addEventListener('input', inputChanged);
+      window.addEventListener('popstate', popState);
+    }
+
+    function setError(error) {
+      if (running) running.Kill();
+      lineClear();
+      lineHighlight(error);
+      output.empty().addClass("error").text(error);
+    }
+    function loading() {
+      lineClear();
+      if (running) running.Kill();
+      output.removeClass("error").text('Waiting for remote server...');
+    }
+    function run() {
+      loading();
+      running = transport.Run(body(), highlightOutput(PlaygroundOutput(output[0])));
+    }
+
+    function fmt() {
+      loading();
+      var data = {"body": body()}; 
+      if ($(opts.fmtImportEl).is(":checked")) {
+        data["imports"] = "true";
+      }
+      $.ajax("/fmt", {
+        data: data,
+        type: "POST",
+        dataType: "json",
+        success: function(data) {
+          if (data.Error) {
+            setError(data.Error);
+          } else {
+            setBody(data.Body);
+            setError("");
+          }
+        }
+      });
+    }
+
+    $(opts.runEl).click(run);
+    $(opts.fmtEl).click(fmt);
+
+    if (opts.shareEl !== null && (opts.shareURLEl !== null || opts.shareRedirect !== null)) {
+      var shareURL;
+      if (opts.shareURLEl) {
+        shareURL = $(opts.shareURLEl).hide();
+      }
+      var sharing = false;
+      $(opts.shareEl).click(function() {
+        if (sharing) return;
+        sharing = true;
+        var sharingData = body();
+        $.ajax("/share", {
+          processData: false,
+          data: sharingData,
+          type: "POST",
+          complete: function(xhr) {
+            sharing = false;
+            if (xhr.status != 200) {
+              alert("Server error; try again.");
+              return;
+            }
+            if (opts.shareRedirect) {
+              window.location = opts.shareRedirect + xhr.responseText;
+            }
+            if (shareURL) {
+              var path = "/p/" + xhr.responseText;
+              var url = origin(window.location) + path;
+              shareURL.show().val(url).focus().select();
+  
+              if (rewriteHistory) {
+                var historyData = {"code": sharingData};
+                window.history.pushState(historyData, "", path);
+                pushedEmpty = false;
+              }
+            }
+          }
+        });
+      });
+    }
+  
+    if (opts.toysEl !== null) {
+      $(opts.toysEl).bind('change', function() {
+        var toy = $(this).val();
+        $.ajax("/doc/play/"+toy, {
+          processData: false,
+          type: "GET",
+          complete: function(xhr) {
+            if (xhr.status != 200) {
+              alert("Server error; try again.");
+              return;
+            }
+            setBody(xhr.responseText);
+          }
+        });
+      });
+    }
+  }
+
+  window.playground = playground;
+})();
+`,
+
+	"search.html": `<!--
+	Copyright 2009 The Go Authors. All rights reserved.
+	Use of this source code is governed by a BSD-style
+	license that can be found in the LICENSE file.
+-->
+{{with .Alert}}
+	<p>
+	<span class="alert" style="font-size:120%">{{html .}}</span>
+	</p>
+{{end}}
+{{with .Alt}}
+	<p>
+	<span class="alert" style="font-size:120%">Did you mean: </span>
+	{{range .Alts}}
+		<a href="search?q={{urlquery .}}" style="font-size:120%">{{html .}}</a>
+	{{end}}
+	</p>
+{{end}}
+`,
+
+	"search.txt": `QUERY
+	{{.Query}}
+
+{{with .Alert}}{{.}}
+{{end}}{{/* .Alert */}}{{/*
+
+---------------------------------------
+
+*/}}{{with .Alt}}DID YOU MEAN
+
+{{range .Alts}}	{{.}}
+{{end}}
+{{end}}{{/* .Alt */}}{{/*
+
+---------------------------------------
+
+*/}}{{with .Pak}}PACKAGE {{$.Query}}
+
+{{range .}}	{{pkgLink .Pak.Path}}
+{{end}}
+{{end}}{{/* .Pak */}}{{/*
+
+---------------------------------------
+
+*/}}{{range $key, $val := .Idents}}{{if $val}}{{$key.Name}}
+{{range $val}}    {{.Path}}.{{.Name}}
+{{end}}
+{{end}}{{end}}{{/* .Idents */}}{{/*
+
+---------------------------------------
+
+*/}}{{with .Hit}}{{with .Decls}}PACKAGE-LEVEL DECLARATIONS
+
+{{range .}}package {{.Pak.Name}}
+{{range $file := .Files}}{{range .Groups}}{{range .}}	{{srcLink $file.File.Path}}:{{infoLine .}}{{end}}
+{{end}}{{end}}{{/* .Files */}}
+{{end}}{{end}}{{/* .Decls */}}{{/*
+
+---------------------------------------
+
+*/}}{{with .Others}}LOCAL DECLARATIONS AND USES
+
+{{range .}}package {{.Pak.Name}}
+{{range $file := .Files}}{{range .Groups}}{{range .}}	{{srcLink $file.File.Path}}:{{infoLine .}}
+{{end}}{{end}}{{end}}{{/* .Files */}}
+{{end}}{{end}}{{/* .Others */}}{{end}}{{/* .Hit */}}{{/*
+
+---------------------------------------
+
+*/}}{{if .Textual}}{{if .Complete}}{{.Found}} TEXTUAL OCCURRENCES{{else}}MORE THAN {{.Found}} TEXTUAL OCCURRENCES{{end}}
+
+{{range .Textual}}{{len .Lines}}	{{srcLink .Filename}}
+{{end}}{{if not .Complete}}...	...
+{{end}}{{end}}
+`,
+
+	"searchcode.html": `<!--
+	Copyright 2009 The Go Authors. All rights reserved.
+	Use of this source code is governed by a BSD-style
+	license that can be found in the LICENSE file.
+-->
+{{$query_url := urlquery .Query}}
+{{if not .Idents}}
+	{{with .Pak}}
+		<h2 id="Packages">Package {{html $.Query}}</h2>
+		<p>
+		<table class="layout">
+		{{range .}}
+			{{$pkg_html := pkgLink .Pak.Path | html}}
+			<tr><td><a href="/{{$pkg_html}}">{{$pkg_html}}</a></td></tr>
+		{{end}}
+		</table>
+		</p>
+	{{end}}
+{{end}}
+{{with .Hit}}
+	{{with .Decls}}
+		<h2 id="Global">Package-level declarations</h2>
+		{{range .}}
+			{{$pkg_html := pkgLink .Pak.Path | html}}
+			<h3 id="Global_{{$pkg_html}}">package <a href="/{{$pkg_html}}">{{html .Pak.Name}}</a></h3>
+			{{range .Files}}
+				{{$file := .File.Path}}
+				{{range .Groups}}
+					{{range .}}
+						{{$line := infoLine .}}
+						<a href="{{queryLink $file $query_url $line | html}}">{{$file}}:{{$line}}</a>
+						{{infoSnippet_html .}}
+					{{end}}
+				{{end}}
+			{{end}}
+		{{end}}
+	{{end}}
+	{{with .Others}}
+		<h2 id="Local">Local declarations and uses</h2>
+		{{range .}}
+			{{$pkg_html := pkgLink .Pak.Path | html}}
+			<h3 id="Local_{{$pkg_html}}">package <a href="/{{$pkg_html}}">{{html .Pak.Name}}</a></h3>
+			{{range .Files}}
+				{{$file := .File.Path}}
+				<a href="{{queryLink $file $query_url 0 | html}}">{{$file}}</a>
+				<table class="layout">
+				{{range .Groups}}
+					<tr>
+					<td width="25"></td>
+					<th align="left" valign="top">{{index . 0 | infoKind_html}}</th>
+					<td align="left" width="4"></td>
+					<td>
+					{{range .}}
+						{{$line := infoLine .}}
+						<a href="{{queryLink $file $query_url $line | html}}">{{$line}}</a>
+					{{end}}
+					</td>
+					</tr>
+				{{end}}
+				</table>
+			{{end}}
+		{{end}}
+	{{end}}
+{{end}}
+`,
+
+	"searchdoc.html": `<!--
+	Copyright 2009 The Go Authors. All rights reserved.
+	Use of this source code is governed by a BSD-style
+	license that can be found in the LICENSE file.
+-->
+{{range $key, $val := .Idents}}
+	{{if $val}}
+		<h2 id="{{$key.Name}}">{{$key.Name}}</h2>
+		{{range $val}}
+			{{$pkg_html := pkgLink .Path | html}}
+			{{if eq "Packages" $key.Name}}
+				<a href="/{{$pkg_html}}">{{html .Path}}</a>
+			{{else}}
+				{{$doc_html := docLink .Path .Name| html}}
+				<a href="/{{$pkg_html}}">{{html .Package}}</a>.<a href="{{$doc_html}}">{{.Name}}</a>
+			{{end}}
+			{{if .Doc}}
+				<p>{{comment_html .Doc}}</p>
+			{{else}}
+				<p><em>No documentation available</em></p>
+			{{end}}
+		{{end}}
+	{{end}}
+{{end}}
+`,
+
+	"searchtxt.html": `<!--
+	Copyright 2009 The Go Authors. All rights reserved.
+	Use of this source code is governed by a BSD-style
+	license that can be found in the LICENSE file.
+-->
+{{$query_url := urlquery .Query}}
+{{with .Textual}}
+	{{if $.Complete}}
+		<h2 id="Textual">{{html $.Found}} textual occurrences</h2>
+	{{else}}
+		<h2 id="Textual">More than {{html $.Found}} textual occurrences</h2>
+		<p>
+		<span class="alert" style="font-size:120%">Not all files or lines containing "{{html $.Query}}" are shown.</span>
+		</p>
+	{{end}}
+	<p>
+	<table class="layout">
+	{{range .}}
+		{{$file := .Filename}}
+		<tr>
+		<td align="left" valign="top">
+		<a href="{{queryLink $file $query_url 0}}">{{$file}}</a>:
+		</td>
+		<td align="left" width="4"></td>
+		<th align="left" valign="top">{{len .Lines}}</th>
+		<td align="left" width="4"></td>
+		<td align="left">
+		{{range .Lines}}
+			<a href="{{queryLink $file $query_url .}}">{{html .}}</a>
+		{{end}}
+		{{if not $.Complete}}
+			...
+		{{end}}
+		</td>
+		</tr>
+	{{end}}
+	{{if not $.Complete}}
+		<tr><td align="left">...</td></tr>
+	{{end}}
+	</table>
+	</p>
+{{end}}
+`,
+
+	"style.css": `body {
+	margin: 0;
+	font-family: Arial, sans-serif;
+	font-size: 16px;
+	background-color: #fff;
+	line-height: 1.3em;
+}
+pre,
+code {
+	font-family: Menlo, monospace;
+	font-size: 14px;
+}
+pre {
+	line-height: 1.4em;
+	overflow-x: auto;
+}
+pre .comment {
+	color: #006600;
+}
+pre .highlight,
+pre .highlight-comment,
+pre .selection-highlight,
+pre .selection-highlight-comment {
+	background: #FFFF00;
+}
+pre .selection,
+pre .selection-comment {
+	background: #FF9632;
+}
+pre .ln {
+	color: #999;
+}
+body {
+	color: #222;
+}
+a,
+.exampleHeading .text {
+	color: #375EAB;
+	text-decoration: none;
+}
+a:hover,
+.exampleHeading .text:hover {
+	text-decoration: underline;
+}
+p {
+	max-width: 800px;
+	word-wrap: break-word;
+}
+p,
+pre,
+ul,
+ol {
+	margin: 20px;
+}
+pre {
+	background: #EFEFEF;
+	padding: 10px;
+
+	-webkit-border-radius: 5px;
+	-moz-border-radius: 5px;
+	border-radius: 5px;
+}
+
+h1,
+h2,
+h3,
+h4,
+.rootHeading {
+	margin: 20px 0 20px;
+	padding: 0;
+	color: #375EAB;
+	font-weight: bold;
+}
+h1 {
+	font-size: 28px;
+	line-height: 1;
+}
+h2 {
+	font-size: 20px;
+	background: #E0EBF5;
+	padding: 8px;
+	line-height: 1.25;
+	font-weight: normal;
+}
+h2 a {
+	font-weight: bold;
+}
+h3 {
+	font-size: 20px;
+}
+h3,
+h4 {
+	margin: 20px 5px;
+}
+h4 {
+	font-size: 16px;
+}
+.rootHeading {
+	font-size: 20px;
+	margin: 0;
+}
+
+dl {
+	margin: 20px;
+}
+dd {
+	margin: 0;
+}
+dd.indent {
+	margin: 0 20px;
+}
+dl,
+dd {
+	font-size: 14px;
+}
+div#nav table td {
+	vertical-align: top;
+}
+
+
+.pkg-dir {
+	padding: 0 10px;
+}
+.pkg-dir table {
+	border-collapse: collapse;
+	border-spacing: 0;
+}
+.pkg-name {
+	padding-right: 10px;
+}
+.alert {
+	color: #AA0000;
+}
+
+.top-heading {
+	float: left;
+	padding: 21px 0;
+	font-size: 20px;
+	font-weight: normal;
+}
+.top-heading a {
+	color: #222;
+	text-decoration: none;
+}
+
+div#topbar {
+	background: #E0EBF5;
+	height: 64px;
+	overflow: hidden;
+}
+
+body {
+	text-align: center;
+}
+div#page {
+	width: 100%;
+}
+div#page > .container,
+div#topbar > .container {
+	text-align: left;
+	margin-left: auto;
+	margin-right: auto;
+	padding: 0 20px;
+}
+div#topbar > .container,
+div#page > .container {
+	max-width: 950px;
+}
+div#page.wide > .container,
+div#topbar.wide > .container {
+	max-width: none;
+}
+div#plusone {
+	float: right;
+	clear: right;
+	margin-top: 5px;
+}
+
+div#footer {
+	text-align: center;
+	color: #666;
+	font-size: 14px;
+	margin: 40px 0;
+}
+
+div#menu > a,
+div#menu > input,
+div#learn .buttons a,
+div.play .buttons a,
+div#blog .read a,
+#menu-button {
+	padding: 10px;
+
+	text-decoration: none;
+	font-size: 16px;
+
+	-webkit-border-radius: 5px;
+	-moz-border-radius: 5px;
+	border-radius: 5px;
+}
+div#playground .buttons a,
+div#menu > a,
+div#menu > input,
+#menu-button {
+	border: 1px solid #375EAB;
+}
+div#playground .buttons a,
+div#menu > a,
+#menu-button {
+	color: white;
+	background: #375EAB;
+}
+#playgroundButton.active {
+	background: white;
+	color: #375EAB;
+}
+a#start,
+div#learn .buttons a,
+div.play .buttons a,
+div#blog .read a {
+	color: #222;
+	border: 1px solid #375EAB;
+	background: #E0EBF5;
+}
+.download {
+	width: 150px;
+}
+
+div#menu {
+	text-align: right;
+	padding: 10px;
+	white-space: nowrap;
+	max-height: 0;
+	-moz-transition: max-height .25s linear;
+	transition: max-height .25s linear;
+	width: 100%;
+}
+div#menu.menu-visible {
+	max-height: 500px;
+}
+div#menu > a,
+#menu-button {
+	margin: 10px 2px;
+	padding: 10px;
+}
+div#menu > input {
+	position: relative;
+	top: 1px;
+	width: 140px;
+	background: white;
+	color: #222;
+	box-sizing: border-box;
+}
+div#menu > input.inactive {
+	color: #999;
+}
+
+#menu-button {
+	display: none;
+	position: absolute;
+	right: 5px;
+	top: 0;
+	margin-right: 5px;
+}
+#menu-button-arrow {
+	display: inline-block;
+}
+.vertical-flip {
+	transform: rotate(-180deg);
+}
+
+div.left {
+	float: left;
+	clear: left;
+	margin-right: 2.5%;
+}
+div.right {
+	float: right;
+	clear: right;
+	margin-left: 2.5%;
+}
+div.left,
+div.right {
+	width: 45%;
+}
+
+div#learn,
+div#about {
+	padding-top: 20px;
+}
+div#learn h2,
+div#about {
+	margin: 0;
+}
+div#about {
+	font-size: 20px;
+	margin: 0 auto 30px;
+}
+div#gopher {
+	background: url(/doc/gopher/frontpage.png) no-repeat;
+	background-position: center top;
+	height: 155px;
+}
+a#start {
+	display: block;
+	padding: 10px;
+
+	text-align: center;
+	text-decoration: none;
+
+	-webkit-border-radius: 5px;
+	-moz-border-radius: 5px;
+	border-radius: 5px;
+}
+a#start .big {
+	display: block;
+	font-weight: bold;
+	font-size: 20px;
+}
+a#start .desc {
+	display: block;
+	font-size: 14px;
+	font-weight: normal;
+	margin-top: 5px;
+}
+
+div#learn .popout {
+	float: right;
+	display: block;
+	cursor: pointer;
+	font-size: 12px;
+	background: url(/doc/share.png) no-repeat;
+	background-position: right top;
+	padding: 5px 27px;
+}
+div#learn pre,
+div#learn textarea {
+	padding: 0;
+	margin: 0;
+	font-family: Menlo, monospace;
+	font-size: 14px;
+}
+div#learn .input {
+	padding: 10px;
+	margin-top: 10px;
+	height: 150px;
+
+	-webkit-border-top-left-radius: 5px;
+	-webkit-border-top-right-radius: 5px;
+	-moz-border-radius-topleft: 5px;
+	-moz-border-radius-topright: 5px;
+	border-top-left-radius: 5px;
+	border-top-right-radius: 5px;
+}
+div#learn .input textarea {
+	width: 100%;
+	height: 100%;
+	border: none;
+	outline: none;
+	resize: none;
+}
+div#learn .output {
+	border-top: none !important;
+
+	padding: 10px;
+	height: 59px;
+	overflow: auto;
+
+	-webkit-border-bottom-right-radius: 5px;
+	-webkit-border-bottom-left-radius: 5px;
+	-moz-border-radius-bottomright: 5px;
+	-moz-border-radius-bottomleft: 5px;
+	border-bottom-right-radius: 5px;
+	border-bottom-left-radius: 5px;
+}
+div#learn .output pre {
+	padding: 0;
+
+	-webkit-border-radius: 0;
+	-moz-border-radius: 0;
+	border-radius: 0;
+}
+div#learn .input,
+div#learn .input textarea,
+div#learn .output,
+div#learn .output pre {
+	background: #FFFFD8;
+}
+div#learn .input,
+div#learn .output {
+	border: 1px solid #375EAB;
+}
+div#learn .buttons {
+	float: right;
+	padding: 20px 0 10px 0;
+	text-align: right;
+}
+div#learn .buttons a {
+	height: 16px;
+	margin-left: 5px;
+	padding: 10px;
+}
+div#learn .toys {
+	margin-top: 8px;
+}
+div#learn .toys select {
+	border: 1px solid #375EAB;
+	margin: 0;
+}
+div#learn .output .exit {
+	display: none;
+}
+
+div#video {
+	max-width: 100%;
+}
+div#blog,
+div#video {
+	margin-top: 40px;
+}
+div#blog > a,
+div#blog > div,
+div#blog > h2,
+div#video > a,
+div#video > div,
+div#video > h2 {
+	margin-bottom: 10px;
+}
+div#blog .title,
+div#video .title {
+	display: block;
+	font-size: 20px;
+}
+div#blog .when {
+	color: #666;
+	font-size: 14px;
+}
+div#blog .read {
+	text-align: right;
+}
+
+.toggleButton { cursor: pointer; }
+.toggle .collapsed { display: block; }
+.toggle .expanded { display: none; }
+.toggleVisible .collapsed { display: none; }
+.toggleVisible .expanded { display: block; }
+
+table.codetable { margin-left: auto; margin-right: auto; border-style: none; }
+table.codetable td { padding-right: 10px; }
+hr { border-style: none; border-top: 1px solid black; }
+
+img.gopher {
+	float: right;
+	margin-left: 10px;
+	margin-bottom: 10px;
+	z-index: -1;
+}
+h2 { clear: right; }
+
+/* example and drop-down playground */
+div.play {
+	padding: 0 20px 40px 20px;
+}
+div.play pre,
+div.play textarea,
+div.play .lines {
+	padding: 0;
+	margin: 0;
+	font-family: Menlo, monospace;
+	font-size: 14px;
+}
+div.play .input {
+	padding: 10px;
+	margin-top: 10px;
+
+	-webkit-border-top-left-radius: 5px;
+	-webkit-border-top-right-radius: 5px;
+	-moz-border-radius-topleft: 5px;
+	-moz-border-radius-topright: 5px;
+	border-top-left-radius: 5px;
+	border-top-right-radius: 5px;
+
+	overflow: hidden;
+}
+div.play .input textarea {
+	width: 100%;
+	height: 100%;
+	border: none;
+	outline: none;
+	resize: none;
+
+	overflow: hidden;
+}
+div#playground .input textarea {
+	overflow: auto;
+	resize: auto;
+}
+div.play .output {
+	border-top: none !important;
+
+	padding: 10px;
+	max-height: 200px;
+	overflow: auto;
+
+	-webkit-border-bottom-right-radius: 5px;
+	-webkit-border-bottom-left-radius: 5px;
+	-moz-border-radius-bottomright: 5px;
+	-moz-border-radius-bottomleft: 5px;
+	border-bottom-right-radius: 5px;
+	border-bottom-left-radius: 5px;
+}
+div.play .output pre {
+	padding: 0;
+
+	-webkit-border-radius: 0;
+	-moz-border-radius: 0;
+	border-radius: 0;
+}
+div.play .input,
+div.play .input textarea,
+div.play .output,
+div.play .output pre {
+	background: #FFFFD8;
+}
+div.play .input,
+div.play .output {
+	border: 1px solid #375EAB;
+}
+div.play .buttons {
+	float: right;
+	padding: 20px 0 10px 0;
+	text-align: right;
+}
+div.play .buttons a {
+	height: 16px;
+	margin-left: 5px;
+	padding: 10px;
+	cursor: pointer;
+}
+.output .stderr {
+	color: #933;
+}
+.output .system {
+	color: #999;
+}
+
+/* drop-down playground */
+#playgroundButton,
+div#playground {
+	/* start hidden; revealed by javascript */
+	display: none;
+}
+div#playground {
+	position: absolute;
+	top: 63px;
+	right: 20px;
+	padding: 0 10px 10px 10px;
+	z-index: 1;
+	text-align: left;
+	background: #E0EBF5;
+
+	border: 1px solid #B0BBC5;
+	border-top: none;
+
+	-webkit-border-bottom-left-radius: 5px;
+	-webkit-border-bottom-right-radius: 5px;
+	-moz-border-radius-bottomleft: 5px;
+	-moz-border-radius-bottomright: 5px;
+	border-bottom-left-radius: 5px;
+	border-bottom-right-radius: 5px;
+}
+div#playground .code {
+	width: 520px;
+	height: 200px;
+}
+div#playground .output {
+	height: 100px;
+}
+
+/* Inline runnable snippets (play.js/initPlayground) */
+#content .code pre, #content .playground pre, #content .output pre {
+        margin: 0;
+        padding: 0;
+        background: none;
+        border: none;
+	outline: 0px solid transparent;
+        overflow: auto;
+}
+#content .playground .number, #content .code .number {
+        color: #999;
+}
+#content .code, #content .playground, #content .output {
+	width: auto;
+        margin: 20px;
+        padding: 10px;
+        -webkit-border-radius: 5px;
+        -moz-border-radius: 5px;
+        border-radius: 5px;
+}
+#content .code, #content .playground {
+        background: #e9e9e9;
+}
+#content .output {
+        background: #202020;
+}
+#content .output .stdout, #content .output pre {
+        color: #e6e6e6;
+}
+#content .output .stderr, #content .output .error {
+        color: rgb(244, 74, 63);
+}
+#content .output .system, #content .output .exit {
+        color: rgb(255, 209, 77)
+}
+#content .buttons {
+        position: relative;
+        float: right;
+        top: -50px;
+        right: 30px;
+}
+#content .output .buttons {
+        top: -60px;
+        right: 0;
+        height: 0;
+}
+#content .buttons .kill {
+        display: none;
+        visibility: hidden;
+}
+a.error {
+	font-weight: bold;
+        color: white;
+	background-color: darkred;
+        border-bottom-left-radius: 4px;
+        border-bottom-right-radius: 4px;
+        border-top-left-radius: 4px;
+        border-top-right-radius: 4px;
+        padding: 2px 4px 2px 4px; /* TRBL */
+}
+
+
+#heading-narrow {
+	display: none;
+}
+
+.downloading {
+	background: #F9F9BE;
+	padding: 10px;
+	text-align: center;
+	border-radius: 5px;
+}
+
+@media (max-width: 930px) {
+	#heading-wide {
+		display: none;
+	}
+	#heading-narrow {
+		display: block;
+	}
+}
+
+
+@media (max-width: 760px) {
+	.container .left,
+	.container .right {
+		width: auto;
+		float: none;
+	}
+
+	div#about {
+		max-width: 500px;
+		text-align: center;
+	}
+}
+
+@media (min-width: 700px) and (max-width: 1000px) {
+	div#menu > a {
+		margin: 5px 0;
+		font-size: 14px;
+	}
+
+	div#menu > input {
+		font-size: 14px;
+	}
+}
+
+@media (max-width: 700px) {
+	body {
+		font-size: 15px;
+	}
+
+	pre,
+	code {
+		font-size: 13px;
+	}
+
+	div#page > .container {
+		padding: 0 10px;
+	}
+
+	div#topbar {
+		height: auto;
+		padding: 10px;
+	}
+
+	div#topbar > .container {
+		padding: 0;
+	}
+
+	#heading-wide {
+		display: block;
+	}
+	#heading-narrow {
+		display: none;
+	}
+
+	.top-heading {
+		float: none;
+		display: inline-block;
+		padding: 12px;
+	}
+
+	div#menu {
+		padding: 0;
+		min-width: 0;
+		text-align: left;
+		float: left;
+	}
+
+	div#menu > a,
+	div#menu > input {
+		display: block;
+		margin-left: 0;
+		margin-right: 0;
+	}
+
+	div#menu > input {
+		width: 100%;
+	}
+
+	#menu-button {
+		display: inline-block;
+	}
+
+	p,
+	pre,
+	ul,
+	ol {
+		margin: 10px;
+	}
+
+	.pkg-synopsis {
+		display: none;
+	}
+
+	img.gopher {
+		display: none;
+	}
+}
+
+@media (max-width: 480px) {
+	#heading-wide {
+		display: none;
+	}
+	#heading-narrow {
+		display: block;
+	}
+}
+
+@media print {
+	pre {
+		background: #FFF;
+		border: 1px solid #BBB;
+		white-space: pre-wrap;
+	}
+}
+`,
+}
diff --git a/godoc/static/style.css b/godoc/static/style.css
new file mode 100644
index 0000000..4d2b07a
--- /dev/null
+++ b/godoc/static/style.css
@@ -0,0 +1,776 @@
+body {
+	margin: 0;
+	font-family: Arial, sans-serif;
+	font-size: 16px;
+	background-color: #fff;
+	line-height: 1.3em;
+}
+pre,
+code {
+	font-family: Menlo, monospace;
+	font-size: 14px;
+}
+pre {
+	line-height: 1.4em;
+	overflow-x: auto;
+}
+pre .comment {
+	color: #006600;
+}
+pre .highlight,
+pre .highlight-comment,
+pre .selection-highlight,
+pre .selection-highlight-comment {
+	background: #FFFF00;
+}
+pre .selection,
+pre .selection-comment {
+	background: #FF9632;
+}
+pre .ln {
+	color: #999;
+}
+body {
+	color: #222;
+}
+a,
+.exampleHeading .text {
+	color: #375EAB;
+	text-decoration: none;
+}
+a:hover,
+.exampleHeading .text:hover {
+	text-decoration: underline;
+}
+p {
+	max-width: 800px;
+	word-wrap: break-word;
+}
+p,
+pre,
+ul,
+ol {
+	margin: 20px;
+}
+pre {
+	background: #EFEFEF;
+	padding: 10px;
+
+	-webkit-border-radius: 5px;
+	-moz-border-radius: 5px;
+	border-radius: 5px;
+}
+
+h1,
+h2,
+h3,
+h4,
+.rootHeading {
+	margin: 20px 0 20px;
+	padding: 0;
+	color: #375EAB;
+	font-weight: bold;
+}
+h1 {
+	font-size: 28px;
+	line-height: 1;
+}
+h2 {
+	font-size: 20px;
+	background: #E0EBF5;
+	padding: 8px;
+	line-height: 1.25;
+	font-weight: normal;
+}
+h2 a {
+	font-weight: bold;
+}
+h3 {
+	font-size: 20px;
+}
+h3,
+h4 {
+	margin: 20px 5px;
+}
+h4 {
+	font-size: 16px;
+}
+.rootHeading {
+	font-size: 20px;
+	margin: 0;
+}
+
+dl {
+	margin: 20px;
+}
+dd {
+	margin: 0;
+}
+dd.indent {
+	margin: 0 20px;
+}
+dl,
+dd {
+	font-size: 14px;
+}
+div#nav table td {
+	vertical-align: top;
+}
+
+
+.pkg-dir {
+	padding: 0 10px;
+}
+.pkg-dir table {
+	border-collapse: collapse;
+	border-spacing: 0;
+}
+.pkg-name {
+	padding-right: 10px;
+}
+.alert {
+	color: #AA0000;
+}
+
+.top-heading {
+	float: left;
+	padding: 21px 0;
+	font-size: 20px;
+	font-weight: normal;
+}
+.top-heading a {
+	color: #222;
+	text-decoration: none;
+}
+
+div#topbar {
+	background: #E0EBF5;
+	height: 64px;
+	overflow: hidden;
+}
+
+body {
+	text-align: center;
+}
+div#page {
+	width: 100%;
+}
+div#page > .container,
+div#topbar > .container {
+	text-align: left;
+	margin-left: auto;
+	margin-right: auto;
+	padding: 0 20px;
+}
+div#topbar > .container,
+div#page > .container {
+	max-width: 950px;
+}
+div#page.wide > .container,
+div#topbar.wide > .container {
+	max-width: none;
+}
+div#plusone {
+	float: right;
+	clear: right;
+	margin-top: 5px;
+}
+
+div#footer {
+	text-align: center;
+	color: #666;
+	font-size: 14px;
+	margin: 40px 0;
+}
+
+div#menu > a,
+div#menu > input,
+div#learn .buttons a,
+div.play .buttons a,
+div#blog .read a,
+#menu-button {
+	padding: 10px;
+
+	text-decoration: none;
+	font-size: 16px;
+
+	-webkit-border-radius: 5px;
+	-moz-border-radius: 5px;
+	border-radius: 5px;
+}
+div#playground .buttons a,
+div#menu > a,
+div#menu > input,
+#menu-button {
+	border: 1px solid #375EAB;
+}
+div#playground .buttons a,
+div#menu > a,
+#menu-button {
+	color: white;
+	background: #375EAB;
+}
+#playgroundButton.active {
+	background: white;
+	color: #375EAB;
+}
+a#start,
+div#learn .buttons a,
+div.play .buttons a,
+div#blog .read a {
+	color: #222;
+	border: 1px solid #375EAB;
+	background: #E0EBF5;
+}
+.download {
+	width: 150px;
+}
+
+div#menu {
+	text-align: right;
+	padding: 10px;
+	white-space: nowrap;
+	max-height: 0;
+	-moz-transition: max-height .25s linear;
+	transition: max-height .25s linear;
+	width: 100%;
+}
+div#menu.menu-visible {
+	max-height: 500px;
+}
+div#menu > a,
+#menu-button {
+	margin: 10px 2px;
+	padding: 10px;
+}
+div#menu > input {
+	position: relative;
+	top: 1px;
+	width: 140px;
+	background: white;
+	color: #222;
+	box-sizing: border-box;
+}
+div#menu > input.inactive {
+	color: #999;
+}
+
+#menu-button {
+	display: none;
+	position: absolute;
+	right: 5px;
+	top: 0;
+	margin-right: 5px;
+}
+#menu-button-arrow {
+	display: inline-block;
+}
+.vertical-flip {
+	transform: rotate(-180deg);
+}
+
+div.left {
+	float: left;
+	clear: left;
+	margin-right: 2.5%;
+}
+div.right {
+	float: right;
+	clear: right;
+	margin-left: 2.5%;
+}
+div.left,
+div.right {
+	width: 45%;
+}
+
+div#learn,
+div#about {
+	padding-top: 20px;
+}
+div#learn h2,
+div#about {
+	margin: 0;
+}
+div#about {
+	font-size: 20px;
+	margin: 0 auto 30px;
+}
+div#gopher {
+	background: url(/doc/gopher/frontpage.png) no-repeat;
+	background-position: center top;
+	height: 155px;
+}
+a#start {
+	display: block;
+	padding: 10px;
+
+	text-align: center;
+	text-decoration: none;
+
+	-webkit-border-radius: 5px;
+	-moz-border-radius: 5px;
+	border-radius: 5px;
+}
+a#start .big {
+	display: block;
+	font-weight: bold;
+	font-size: 20px;
+}
+a#start .desc {
+	display: block;
+	font-size: 14px;
+	font-weight: normal;
+	margin-top: 5px;
+}
+
+div#learn .popout {
+	float: right;
+	display: block;
+	cursor: pointer;
+	font-size: 12px;
+	background: url(/doc/share.png) no-repeat;
+	background-position: right top;
+	padding: 5px 27px;
+}
+div#learn pre,
+div#learn textarea {
+	padding: 0;
+	margin: 0;
+	font-family: Menlo, monospace;
+	font-size: 14px;
+}
+div#learn .input {
+	padding: 10px;
+	margin-top: 10px;
+	height: 150px;
+
+	-webkit-border-top-left-radius: 5px;
+	-webkit-border-top-right-radius: 5px;
+	-moz-border-radius-topleft: 5px;
+	-moz-border-radius-topright: 5px;
+	border-top-left-radius: 5px;
+	border-top-right-radius: 5px;
+}
+div#learn .input textarea {
+	width: 100%;
+	height: 100%;
+	border: none;
+	outline: none;
+	resize: none;
+}
+div#learn .output {
+	border-top: none !important;
+
+	padding: 10px;
+	height: 59px;
+	overflow: auto;
+
+	-webkit-border-bottom-right-radius: 5px;
+	-webkit-border-bottom-left-radius: 5px;
+	-moz-border-radius-bottomright: 5px;
+	-moz-border-radius-bottomleft: 5px;
+	border-bottom-right-radius: 5px;
+	border-bottom-left-radius: 5px;
+}
+div#learn .output pre {
+	padding: 0;
+
+	-webkit-border-radius: 0;
+	-moz-border-radius: 0;
+	border-radius: 0;
+}
+div#learn .input,
+div#learn .input textarea,
+div#learn .output,
+div#learn .output pre {
+	background: #FFFFD8;
+}
+div#learn .input,
+div#learn .output {
+	border: 1px solid #375EAB;
+}
+div#learn .buttons {
+	float: right;
+	padding: 20px 0 10px 0;
+	text-align: right;
+}
+div#learn .buttons a {
+	height: 16px;
+	margin-left: 5px;
+	padding: 10px;
+}
+div#learn .toys {
+	margin-top: 8px;
+}
+div#learn .toys select {
+	border: 1px solid #375EAB;
+	margin: 0;
+}
+div#learn .output .exit {
+	display: none;
+}
+
+div#video {
+	max-width: 100%;
+}
+div#blog,
+div#video {
+	margin-top: 40px;
+}
+div#blog > a,
+div#blog > div,
+div#blog > h2,
+div#video > a,
+div#video > div,
+div#video > h2 {
+	margin-bottom: 10px;
+}
+div#blog .title,
+div#video .title {
+	display: block;
+	font-size: 20px;
+}
+div#blog .when {
+	color: #666;
+	font-size: 14px;
+}
+div#blog .read {
+	text-align: right;
+}
+
+.toggleButton { cursor: pointer; }
+.toggle .collapsed { display: block; }
+.toggle .expanded { display: none; }
+.toggleVisible .collapsed { display: none; }
+.toggleVisible .expanded { display: block; }
+
+table.codetable { margin-left: auto; margin-right: auto; border-style: none; }
+table.codetable td { padding-right: 10px; }
+hr { border-style: none; border-top: 1px solid black; }
+
+img.gopher {
+	float: right;
+	margin-left: 10px;
+	margin-bottom: 10px;
+	z-index: -1;
+}
+h2 { clear: right; }
+
+/* example and drop-down playground */
+div.play {
+	padding: 0 20px 40px 20px;
+}
+div.play pre,
+div.play textarea,
+div.play .lines {
+	padding: 0;
+	margin: 0;
+	font-family: Menlo, monospace;
+	font-size: 14px;
+}
+div.play .input {
+	padding: 10px;
+	margin-top: 10px;
+
+	-webkit-border-top-left-radius: 5px;
+	-webkit-border-top-right-radius: 5px;
+	-moz-border-radius-topleft: 5px;
+	-moz-border-radius-topright: 5px;
+	border-top-left-radius: 5px;
+	border-top-right-radius: 5px;
+
+	overflow: hidden;
+}
+div.play .input textarea {
+	width: 100%;
+	height: 100%;
+	border: none;
+	outline: none;
+	resize: none;
+
+	overflow: hidden;
+}
+div#playground .input textarea {
+	overflow: auto;
+	resize: auto;
+}
+div.play .output {
+	border-top: none !important;
+
+	padding: 10px;
+	max-height: 200px;
+	overflow: auto;
+
+	-webkit-border-bottom-right-radius: 5px;
+	-webkit-border-bottom-left-radius: 5px;
+	-moz-border-radius-bottomright: 5px;
+	-moz-border-radius-bottomleft: 5px;
+	border-bottom-right-radius: 5px;
+	border-bottom-left-radius: 5px;
+}
+div.play .output pre {
+	padding: 0;
+
+	-webkit-border-radius: 0;
+	-moz-border-radius: 0;
+	border-radius: 0;
+}
+div.play .input,
+div.play .input textarea,
+div.play .output,
+div.play .output pre {
+	background: #FFFFD8;
+}
+div.play .input,
+div.play .output {
+	border: 1px solid #375EAB;
+}
+div.play .buttons {
+	float: right;
+	padding: 20px 0 10px 0;
+	text-align: right;
+}
+div.play .buttons a {
+	height: 16px;
+	margin-left: 5px;
+	padding: 10px;
+	cursor: pointer;
+}
+.output .stderr {
+	color: #933;
+}
+.output .system {
+	color: #999;
+}
+
+/* drop-down playground */
+#playgroundButton,
+div#playground {
+	/* start hidden; revealed by javascript */
+	display: none;
+}
+div#playground {
+	position: absolute;
+	top: 63px;
+	right: 20px;
+	padding: 0 10px 10px 10px;
+	z-index: 1;
+	text-align: left;
+	background: #E0EBF5;
+
+	border: 1px solid #B0BBC5;
+	border-top: none;
+
+	-webkit-border-bottom-left-radius: 5px;
+	-webkit-border-bottom-right-radius: 5px;
+	-moz-border-radius-bottomleft: 5px;
+	-moz-border-radius-bottomright: 5px;
+	border-bottom-left-radius: 5px;
+	border-bottom-right-radius: 5px;
+}
+div#playground .code {
+	width: 520px;
+	height: 200px;
+}
+div#playground .output {
+	height: 100px;
+}
+
+/* Inline runnable snippets (play.js/initPlayground) */
+#content .code pre, #content .playground pre, #content .output pre {
+        margin: 0;
+        padding: 0;
+        background: none;
+        border: none;
+	outline: 0px solid transparent;
+        overflow: auto;
+}
+#content .playground .number, #content .code .number {
+        color: #999;
+}
+#content .code, #content .playground, #content .output {
+	width: auto;
+        margin: 20px;
+        padding: 10px;
+        -webkit-border-radius: 5px;
+        -moz-border-radius: 5px;
+        border-radius: 5px;
+}
+#content .code, #content .playground {
+        background: #e9e9e9;
+}
+#content .output {
+        background: #202020;
+}
+#content .output .stdout, #content .output pre {
+        color: #e6e6e6;
+}
+#content .output .stderr, #content .output .error {
+        color: rgb(244, 74, 63);
+}
+#content .output .system, #content .output .exit {
+        color: rgb(255, 209, 77)
+}
+#content .buttons {
+        position: relative;
+        float: right;
+        top: -50px;
+        right: 30px;
+}
+#content .output .buttons {
+        top: -60px;
+        right: 0;
+        height: 0;
+}
+#content .buttons .kill {
+        display: none;
+        visibility: hidden;
+}
+a.error {
+	font-weight: bold;
+        color: white;
+	background-color: darkred;
+        border-bottom-left-radius: 4px;
+        border-bottom-right-radius: 4px;
+        border-top-left-radius: 4px;
+        border-top-right-radius: 4px;
+        padding: 2px 4px 2px 4px; /* TRBL */
+}
+
+
+#heading-narrow {
+	display: none;
+}
+
+.downloading {
+	background: #F9F9BE;
+	padding: 10px;
+	text-align: center;
+	border-radius: 5px;
+}
+
+@media (max-width: 930px) {
+	#heading-wide {
+		display: none;
+	}
+	#heading-narrow {
+		display: block;
+	}
+}
+
+
+@media (max-width: 760px) {
+	.container .left,
+	.container .right {
+		width: auto;
+		float: none;
+	}
+
+	div#about {
+		max-width: 500px;
+		text-align: center;
+	}
+}
+
+@media (min-width: 700px) and (max-width: 1000px) {
+	div#menu > a {
+		margin: 5px 0;
+		font-size: 14px;
+	}
+
+	div#menu > input {
+		font-size: 14px;
+	}
+}
+
+@media (max-width: 700px) {
+	body {
+		font-size: 15px;
+	}
+
+	pre,
+	code {
+		font-size: 13px;
+	}
+
+	div#page > .container {
+		padding: 0 10px;
+	}
+
+	div#topbar {
+		height: auto;
+		padding: 10px;
+	}
+
+	div#topbar > .container {
+		padding: 0;
+	}
+
+	#heading-wide {
+		display: block;
+	}
+	#heading-narrow {
+		display: none;
+	}
+
+	.top-heading {
+		float: none;
+		display: inline-block;
+		padding: 12px;
+	}
+
+	div#menu {
+		padding: 0;
+		min-width: 0;
+		text-align: left;
+		float: left;
+	}
+
+	div#menu > a,
+	div#menu > input {
+		display: block;
+		margin-left: 0;
+		margin-right: 0;
+	}
+
+	div#menu > input {
+		width: 100%;
+	}
+
+	#menu-button {
+		display: inline-block;
+	}
+
+	p,
+	pre,
+	ul,
+	ol {
+		margin: 10px;
+	}
+
+	.pkg-synopsis {
+		display: none;
+	}
+
+	img.gopher {
+		display: none;
+	}
+}
+
+@media (max-width: 480px) {
+	#heading-wide {
+		display: none;
+	}
+	#heading-narrow {
+		display: block;
+	}
+}
+
+@media print {
+	pre {
+		background: #FFF;
+		border: 1px solid #BBB;
+		white-space: pre-wrap;
+	}
+}
diff --git a/godoc/tab.go b/godoc/tab.go
new file mode 100644
index 0000000..d314ac7
--- /dev/null
+++ b/godoc/tab.go
@@ -0,0 +1,82 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// TODO(bradfitz,adg): move to util
+
+package godoc
+
+import "io"
+
+var spaces = []byte("                                ") // 32 spaces seems like a good number
+
+const (
+	indenting = iota
+	collecting
+)
+
+// A tconv is an io.Writer filter for converting leading tabs into spaces.
+type tconv struct {
+	output io.Writer
+	state  int // indenting or collecting
+	indent int // valid if state == indenting
+	p      *Presentation
+}
+
+func (p *tconv) writeIndent() (err error) {
+	i := p.indent
+	for i >= len(spaces) {
+		i -= len(spaces)
+		if _, err = p.output.Write(spaces); err != nil {
+			return
+		}
+	}
+	// i < len(spaces)
+	if i > 0 {
+		_, err = p.output.Write(spaces[0:i])
+	}
+	return
+}
+
+func (p *tconv) Write(data []byte) (n int, err error) {
+	if len(data) == 0 {
+		return
+	}
+	pos := 0 // valid if p.state == collecting
+	var b byte
+	for n, b = range data {
+		switch p.state {
+		case indenting:
+			switch b {
+			case '\t':
+				p.indent += p.p.TabWidth
+			case '\n':
+				p.indent = 0
+				if _, err = p.output.Write(data[n : n+1]); err != nil {
+					return
+				}
+			case ' ':
+				p.indent++
+			default:
+				p.state = collecting
+				pos = n
+				if err = p.writeIndent(); err != nil {
+					return
+				}
+			}
+		case collecting:
+			if b == '\n' {
+				p.state = indenting
+				p.indent = 0
+				if _, err = p.output.Write(data[pos : n+1]); err != nil {
+					return
+				}
+			}
+		}
+	}
+	n = len(data)
+	if pos < n && p.state == collecting {
+		_, err = p.output.Write(data[pos:])
+	}
+	return
+}
diff --git a/godoc/template.go b/godoc/template.go
new file mode 100644
index 0000000..eda5874
--- /dev/null
+++ b/godoc/template.go
@@ -0,0 +1,179 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Template support for writing HTML documents.
+// Documents that include Template: true in their
+// metadata are executed as input to text/template.
+//
+// This file defines functions for those templates to invoke.
+
+// The template uses the function "code" to inject program
+// source into the output by extracting code from files and
+// injecting them as HTML-escaped <pre> blocks.
+//
+// The syntax is simple: 1, 2, or 3 space-separated arguments:
+//
+// Whole file:
+//	{{code "foo.go"}}
+// One line (here the signature of main):
+//	{{code "foo.go" `/^func.main/`}}
+// Block of text, determined by start and end (here the body of main):
+//	{{code "foo.go" `/^func.main/` `/^}/`
+//
+// Patterns can be `/regular expression/`, a decimal number, or "$"
+// to signify the end of the file. In multi-line matches,
+// lines that end with the four characters
+//	OMIT
+// are omitted from the output, making it easy to provide marker
+// lines in the input that will not appear in the output but are easy
+// to identify by pattern.
+
+package godoc
+
+import (
+	"bytes"
+	"fmt"
+	"log"
+	"regexp"
+	"strings"
+
+	"golang.org/x/tools/godoc/vfs"
+)
+
+// Functions in this file panic on error, but the panic is recovered
+// to an error by 'code'.
+
+// contents reads and returns the content of the named file
+// (from the virtual file system, so for example /doc refers to $GOROOT/doc).
+func (c *Corpus) contents(name string) string {
+	file, err := vfs.ReadFile(c.fs, name)
+	if err != nil {
+		log.Panic(err)
+	}
+	return string(file)
+}
+
+// stringFor returns a textual representation of the arg, formatted according to its nature.
+func stringFor(arg interface{}) string {
+	switch arg := arg.(type) {
+	case int:
+		return fmt.Sprintf("%d", arg)
+	case string:
+		if len(arg) > 2 && arg[0] == '/' && arg[len(arg)-1] == '/' {
+			return fmt.Sprintf("%#q", arg)
+		}
+		return fmt.Sprintf("%q", arg)
+	default:
+		log.Panicf("unrecognized argument: %v type %T", arg, arg)
+	}
+	return ""
+}
+
+func (p *Presentation) code(file string, arg ...interface{}) (s string, err error) {
+	defer func() {
+		if r := recover(); r != nil {
+			err = fmt.Errorf("%v", r)
+		}
+	}()
+
+	text := p.Corpus.contents(file)
+	var command string
+	switch len(arg) {
+	case 0:
+		// text is already whole file.
+		command = fmt.Sprintf("code %q", file)
+	case 1:
+		command = fmt.Sprintf("code %q %s", file, stringFor(arg[0]))
+		text = p.Corpus.oneLine(file, text, arg[0])
+	case 2:
+		command = fmt.Sprintf("code %q %s %s", file, stringFor(arg[0]), stringFor(arg[1]))
+		text = p.Corpus.multipleLines(file, text, arg[0], arg[1])
+	default:
+		return "", fmt.Errorf("incorrect code invocation: code %q %q", file, arg)
+	}
+	// Trim spaces from output.
+	text = strings.Trim(text, "\n")
+	// Replace tabs by spaces, which work better in HTML.
+	text = strings.Replace(text, "\t", "    ", -1)
+	var buf bytes.Buffer
+	// HTML-escape text and syntax-color comments like elsewhere.
+	FormatText(&buf, []byte(text), -1, true, "", nil)
+	// Include the command as a comment.
+	text = fmt.Sprintf("<pre><!--{{%s}}\n-->%s</pre>", command, buf.Bytes())
+	return text, nil
+}
+
+// parseArg returns the integer or string value of the argument and tells which it is.
+func parseArg(arg interface{}, file string, max int) (ival int, sval string, isInt bool) {
+	switch n := arg.(type) {
+	case int:
+		if n <= 0 || n > max {
+			log.Panicf("%q:%d is out of range", file, n)
+		}
+		return n, "", true
+	case string:
+		return 0, n, false
+	}
+	log.Panicf("unrecognized argument %v type %T", arg, arg)
+	return
+}
+
+// oneLine returns the single line generated by a two-argument code invocation.
+func (c *Corpus) oneLine(file, text string, arg interface{}) string {
+	lines := strings.SplitAfter(c.contents(file), "\n")
+	line, pattern, isInt := parseArg(arg, file, len(lines))
+	if isInt {
+		return lines[line-1]
+	}
+	return lines[match(file, 0, lines, pattern)-1]
+}
+
+// multipleLines returns the text generated by a three-argument code invocation.
+func (c *Corpus) multipleLines(file, text string, arg1, arg2 interface{}) string {
+	lines := strings.SplitAfter(c.contents(file), "\n")
+	line1, pattern1, isInt1 := parseArg(arg1, file, len(lines))
+	line2, pattern2, isInt2 := parseArg(arg2, file, len(lines))
+	if !isInt1 {
+		line1 = match(file, 0, lines, pattern1)
+	}
+	if !isInt2 {
+		line2 = match(file, line1, lines, pattern2)
+	} else if line2 < line1 {
+		log.Panicf("lines out of order for %q: %d %d", text, line1, line2)
+	}
+	for k := line1 - 1; k < line2; k++ {
+		if strings.HasSuffix(lines[k], "OMIT\n") {
+			lines[k] = ""
+		}
+	}
+	return strings.Join(lines[line1-1:line2], "")
+}
+
+// match identifies the input line that matches the pattern in a code invocation.
+// If start>0, match lines starting there rather than at the beginning.
+// The return value is 1-indexed.
+func match(file string, start int, lines []string, pattern string) int {
+	// $ matches the end of the file.
+	if pattern == "$" {
+		if len(lines) == 0 {
+			log.Panicf("%q: empty file", file)
+		}
+		return len(lines)
+	}
+	// /regexp/ matches the line that matches the regexp.
+	if len(pattern) > 2 && pattern[0] == '/' && pattern[len(pattern)-1] == '/' {
+		re, err := regexp.Compile(pattern[1 : len(pattern)-1])
+		if err != nil {
+			log.Panic(err)
+		}
+		for i := start; i < len(lines); i++ {
+			if re.MatchString(lines[i]) {
+				return i + 1
+			}
+		}
+		log.Panicf("%s: no match for %#q", file, pattern)
+	}
+	log.Panicf("unrecognized pattern: %q", pattern)
+	return 0
+}
diff --git a/godoc/util/throttle.go b/godoc/util/throttle.go
new file mode 100644
index 0000000..53d9ba6
--- /dev/null
+++ b/godoc/util/throttle.go
@@ -0,0 +1,88 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package util
+
+import "time"
+
+// A Throttle permits throttling of a goroutine by
+// calling the Throttle method repeatedly.
+//
+type Throttle struct {
+	f  float64       // f = (1-r)/r for 0 < r < 1
+	dt time.Duration // minimum run time slice; >= 0
+	tr time.Duration // accumulated time running
+	ts time.Duration // accumulated time stopped
+	tt time.Time     // earliest throttle time (= time Throttle returned + tm)
+}
+
+// NewThrottle creates a new Throttle with a throttle value r and
+// a minimum allocated run time slice of dt:
+//
+//	r == 0: "empty" throttle; the goroutine is always sleeping
+//	r == 1: full throttle; the goroutine is never sleeping
+//
+// A value of r == 0.6 throttles a goroutine such that it runs
+// approx. 60% of the time, and sleeps approx. 40% of the time.
+// Values of r < 0 or r > 1 are clamped down to values between 0 and 1.
+// Values of dt < 0 are set to 0.
+//
+func NewThrottle(r float64, dt time.Duration) *Throttle {
+	var f float64
+	switch {
+	case r <= 0:
+		f = -1 // indicates always sleep
+	case r >= 1:
+		f = 0 // assume r == 1 (never sleep)
+	default:
+		// 0 < r < 1
+		f = (1 - r) / r
+	}
+	if dt < 0 {
+		dt = 0
+	}
+	return &Throttle{f: f, dt: dt, tt: time.Now().Add(dt)}
+}
+
+// Throttle calls time.Sleep such that over time the ratio tr/ts between
+// accumulated run (tr) and sleep times (ts) approximates the value 1/(1-r)
+// where r is the throttle value. Throttle returns immediately (w/o sleeping)
+// if less than tm ns have passed since the last call to Throttle.
+//
+func (p *Throttle) Throttle() {
+	if p.f < 0 {
+		select {} // always sleep
+	}
+
+	t0 := time.Now()
+	if t0.Before(p.tt) {
+		return // keep running (minimum time slice not exhausted yet)
+	}
+
+	// accumulate running time
+	p.tr += t0.Sub(p.tt) + p.dt
+
+	// compute sleep time
+	// Over time we want:
+	//
+	//	tr/ts = r/(1-r)
+	//
+	// Thus:
+	//
+	//	ts = tr*f with f = (1-r)/r
+	//
+	// After some incremental run time δr added to the total run time
+	// tr, the incremental sleep-time δs to get to the same ratio again
+	// after waking up from time.Sleep is:
+	if δs := time.Duration(float64(p.tr)*p.f) - p.ts; δs > 0 {
+		time.Sleep(δs)
+	}
+
+	// accumulate (actual) sleep time
+	t1 := time.Now()
+	p.ts += t1.Sub(t0)
+
+	// set earliest next throttle time
+	p.tt = t1.Add(p.dt)
+}
diff --git a/godoc/util/util.go b/godoc/util/util.go
new file mode 100644
index 0000000..feedb76
--- /dev/null
+++ b/godoc/util/util.go
@@ -0,0 +1,89 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package util contains utility types and functions for godoc.
+package util // import "golang.org/x/tools/godoc/util"
+
+import (
+	pathpkg "path"
+	"sync"
+	"time"
+	"unicode/utf8"
+
+	"golang.org/x/tools/godoc/vfs"
+)
+
+// An RWValue wraps a value and permits mutually exclusive
+// access to it and records the time the value was last set.
+type RWValue struct {
+	mutex     sync.RWMutex
+	value     interface{}
+	timestamp time.Time // time of last set()
+}
+
+func (v *RWValue) Set(value interface{}) {
+	v.mutex.Lock()
+	v.value = value
+	v.timestamp = time.Now()
+	v.mutex.Unlock()
+}
+
+func (v *RWValue) Get() (interface{}, time.Time) {
+	v.mutex.RLock()
+	defer v.mutex.RUnlock()
+	return v.value, v.timestamp
+}
+
+// IsText reports whether a significant prefix of s looks like correct UTF-8;
+// that is, if it is likely that s is human-readable text.
+func IsText(s []byte) bool {
+	const max = 1024 // at least utf8.UTFMax
+	if len(s) > max {
+		s = s[0:max]
+	}
+	for i, c := range string(s) {
+		if i+utf8.UTFMax > len(s) {
+			// last char may be incomplete - ignore
+			break
+		}
+		if c == 0xFFFD || c < ' ' && c != '\n' && c != '\t' && c != '\f' {
+			// decoding error or control character - not a text file
+			return false
+		}
+	}
+	return true
+}
+
+// textExt[x] is true if the extension x indicates a text file, and false otherwise.
+var textExt = map[string]bool{
+	".css": false, // must be served raw
+	".js":  false, // must be served raw
+}
+
+// IsTextFile reports whether the file has a known extension indicating
+// a text file, or if a significant chunk of the specified file looks like
+// correct UTF-8; that is, if it is likely that the file contains human-
+// readable text.
+func IsTextFile(fs vfs.Opener, filename string) bool {
+	// if the extension is known, use it for decision making
+	if isText, found := textExt[pathpkg.Ext(filename)]; found {
+		return isText
+	}
+
+	// the extension is not known; read an initial chunk
+	// of the file and check if it looks like text
+	f, err := fs.Open(filename)
+	if err != nil {
+		return false
+	}
+	defer f.Close()
+
+	var buf [1024]byte
+	n, err := f.Read(buf[0:])
+	if err != nil {
+		return false
+	}
+
+	return IsText(buf[0:n])
+}
diff --git a/godoc/vfs/gatefs/gatefs.go b/godoc/vfs/gatefs/gatefs.go
new file mode 100644
index 0000000..7045a5c
--- /dev/null
+++ b/godoc/vfs/gatefs/gatefs.go
@@ -0,0 +1,89 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package gatefs provides an implementation of the FileSystem
+// interface that wraps another FileSystem and limits its concurrency.
+package gatefs // import "golang.org/x/tools/godoc/vfs/gatefs"
+
+import (
+	"fmt"
+	"os"
+
+	"golang.org/x/tools/godoc/vfs"
+)
+
+// New returns a new FileSystem that delegates to fs.
+// If gateCh is non-nil and buffered, it's used as a gate
+// to limit concurrency on calls to fs.
+func New(fs vfs.FileSystem, gateCh chan bool) vfs.FileSystem {
+	if cap(gateCh) == 0 {
+		return fs
+	}
+	return gatefs{fs, gate(gateCh)}
+}
+
+type gate chan bool
+
+func (g gate) enter() { g <- true }
+func (g gate) leave() { <-g }
+
+type gatefs struct {
+	fs vfs.FileSystem
+	gate
+}
+
+func (fs gatefs) String() string {
+	return fmt.Sprintf("gated(%s, %d)", fs.fs.String(), cap(fs.gate))
+}
+
+func (fs gatefs) Open(p string) (vfs.ReadSeekCloser, error) {
+	fs.enter()
+	defer fs.leave()
+	rsc, err := fs.fs.Open(p)
+	if err != nil {
+		return nil, err
+	}
+	return gatef{rsc, fs.gate}, nil
+}
+
+func (fs gatefs) Lstat(p string) (os.FileInfo, error) {
+	fs.enter()
+	defer fs.leave()
+	return fs.fs.Lstat(p)
+}
+
+func (fs gatefs) Stat(p string) (os.FileInfo, error) {
+	fs.enter()
+	defer fs.leave()
+	return fs.fs.Stat(p)
+}
+
+func (fs gatefs) ReadDir(p string) ([]os.FileInfo, error) {
+	fs.enter()
+	defer fs.leave()
+	return fs.fs.ReadDir(p)
+}
+
+type gatef struct {
+	rsc vfs.ReadSeekCloser
+	gate
+}
+
+func (f gatef) Read(p []byte) (n int, err error) {
+	f.enter()
+	defer f.leave()
+	return f.rsc.Read(p)
+}
+
+func (f gatef) Seek(offset int64, whence int) (ret int64, err error) {
+	f.enter()
+	defer f.leave()
+	return f.rsc.Seek(offset, whence)
+}
+
+func (f gatef) Close() error {
+	f.enter()
+	defer f.leave()
+	return f.rsc.Close()
+}
diff --git a/godoc/vfs/httpfs/httpfs.go b/godoc/vfs/httpfs/httpfs.go
new file mode 100644
index 0000000..f232f03
--- /dev/null
+++ b/godoc/vfs/httpfs/httpfs.go
@@ -0,0 +1,94 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package httpfs implements http.FileSystem using a godoc vfs.FileSystem.
+package httpfs // import "golang.org/x/tools/godoc/vfs/httpfs"
+
+import (
+	"fmt"
+	"io"
+	"net/http"
+	"os"
+
+	"golang.org/x/tools/godoc/vfs"
+)
+
+func New(fs vfs.FileSystem) http.FileSystem {
+	return &httpFS{fs}
+}
+
+type httpFS struct {
+	fs vfs.FileSystem
+}
+
+func (h *httpFS) Open(name string) (http.File, error) {
+	fi, err := h.fs.Stat(name)
+	if err != nil {
+		return nil, err
+	}
+	if fi.IsDir() {
+		return &httpDir{h.fs, name, nil}, nil
+	}
+	f, err := h.fs.Open(name)
+	if err != nil {
+		return nil, err
+	}
+	return &httpFile{h.fs, f, name}, nil
+}
+
+// httpDir implements http.File for a directory in a FileSystem.
+type httpDir struct {
+	fs      vfs.FileSystem
+	name    string
+	pending []os.FileInfo
+}
+
+func (h *httpDir) Close() error               { return nil }
+func (h *httpDir) Stat() (os.FileInfo, error) { return h.fs.Stat(h.name) }
+func (h *httpDir) Read([]byte) (int, error) {
+	return 0, fmt.Errorf("cannot Read from directory %s", h.name)
+}
+
+func (h *httpDir) Seek(offset int64, whence int) (int64, error) {
+	if offset == 0 && whence == 0 {
+		h.pending = nil
+		return 0, nil
+	}
+	return 0, fmt.Errorf("unsupported Seek in directory %s", h.name)
+}
+
+func (h *httpDir) Readdir(count int) ([]os.FileInfo, error) {
+	if h.pending == nil {
+		d, err := h.fs.ReadDir(h.name)
+		if err != nil {
+			return nil, err
+		}
+		if d == nil {
+			d = []os.FileInfo{} // not nil
+		}
+		h.pending = d
+	}
+
+	if len(h.pending) == 0 && count > 0 {
+		return nil, io.EOF
+	}
+	if count <= 0 || count > len(h.pending) {
+		count = len(h.pending)
+	}
+	d := h.pending[:count]
+	h.pending = h.pending[count:]
+	return d, nil
+}
+
+// httpFile implements http.File for a file (not directory) in a FileSystem.
+type httpFile struct {
+	fs vfs.FileSystem
+	vfs.ReadSeekCloser
+	name string
+}
+
+func (h *httpFile) Stat() (os.FileInfo, error) { return h.fs.Stat(h.name) }
+func (h *httpFile) Readdir(int) ([]os.FileInfo, error) {
+	return nil, fmt.Errorf("cannot Readdir from file %s", h.name)
+}
diff --git a/godoc/vfs/mapfs/mapfs.go b/godoc/vfs/mapfs/mapfs.go
new file mode 100644
index 0000000..660b1ca
--- /dev/null
+++ b/godoc/vfs/mapfs/mapfs.go
@@ -0,0 +1,152 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package mapfs file provides an implementation of the FileSystem
+// interface based on the contents of a map[string]string.
+package mapfs // import "golang.org/x/tools/godoc/vfs/mapfs"
+
+import (
+	"io"
+	"os"
+	pathpkg "path"
+	"sort"
+	"strings"
+	"time"
+
+	"golang.org/x/tools/godoc/vfs"
+)
+
+// New returns a new FileSystem from the provided map.
+// Map keys should be forward slash-separated pathnames
+// and not contain a leading slash.
+func New(m map[string]string) vfs.FileSystem {
+	return mapFS(m)
+}
+
+// mapFS is the map based implementation of FileSystem
+type mapFS map[string]string
+
+func (fs mapFS) String() string { return "mapfs" }
+
+func (fs mapFS) Close() error { return nil }
+
+func filename(p string) string {
+	return strings.TrimPrefix(p, "/")
+}
+
+func (fs mapFS) Open(p string) (vfs.ReadSeekCloser, error) {
+	b, ok := fs[filename(p)]
+	if !ok {
+		return nil, os.ErrNotExist
+	}
+	return nopCloser{strings.NewReader(b)}, nil
+}
+
+func fileInfo(name, contents string) os.FileInfo {
+	return mapFI{name: pathpkg.Base(name), size: len(contents)}
+}
+
+func dirInfo(name string) os.FileInfo {
+	return mapFI{name: pathpkg.Base(name), dir: true}
+}
+
+func (fs mapFS) Lstat(p string) (os.FileInfo, error) {
+	b, ok := fs[filename(p)]
+	if ok {
+		return fileInfo(p, b), nil
+	}
+	ents, _ := fs.ReadDir(p)
+	if len(ents) > 0 {
+		return dirInfo(p), nil
+	}
+	return nil, os.ErrNotExist
+}
+
+func (fs mapFS) Stat(p string) (os.FileInfo, error) {
+	return fs.Lstat(p)
+}
+
+// slashdir returns path.Dir(p), but special-cases paths not beginning
+// with a slash to be in the root.
+func slashdir(p string) string {
+	d := pathpkg.Dir(p)
+	if d == "." {
+		return "/"
+	}
+	if strings.HasPrefix(p, "/") {
+		return d
+	}
+	return "/" + d
+}
+
+func (fs mapFS) ReadDir(p string) ([]os.FileInfo, error) {
+	p = pathpkg.Clean(p)
+	var ents []string
+	fim := make(map[string]os.FileInfo) // base -> fi
+	for fn, b := range fs {
+		dir := slashdir(fn)
+		isFile := true
+		var lastBase string
+		for {
+			if dir == p {
+				base := lastBase
+				if isFile {
+					base = pathpkg.Base(fn)
+				}
+				if fim[base] == nil {
+					var fi os.FileInfo
+					if isFile {
+						fi = fileInfo(fn, b)
+					} else {
+						fi = dirInfo(base)
+					}
+					ents = append(ents, base)
+					fim[base] = fi
+				}
+			}
+			if dir == "/" {
+				break
+			} else {
+				isFile = false
+				lastBase = pathpkg.Base(dir)
+				dir = pathpkg.Dir(dir)
+			}
+		}
+	}
+	if len(ents) == 0 {
+		return nil, os.ErrNotExist
+	}
+
+	sort.Strings(ents)
+	var list []os.FileInfo
+	for _, dir := range ents {
+		list = append(list, fim[dir])
+	}
+	return list, nil
+}
+
+// mapFI is the map-based implementation of FileInfo.
+type mapFI struct {
+	name string
+	size int
+	dir  bool
+}
+
+func (fi mapFI) IsDir() bool        { return fi.dir }
+func (fi mapFI) ModTime() time.Time { return time.Time{} }
+func (fi mapFI) Mode() os.FileMode {
+	if fi.IsDir() {
+		return 0755 | os.ModeDir
+	}
+	return 0444
+}
+func (fi mapFI) Name() string     { return pathpkg.Base(fi.name) }
+func (fi mapFI) Size() int64      { return int64(fi.size) }
+func (fi mapFI) Sys() interface{} { return nil }
+
+type nopCloser struct {
+	io.ReadSeeker
+}
+
+func (nc nopCloser) Close() error { return nil }
diff --git a/godoc/vfs/mapfs/mapfs_test.go b/godoc/vfs/mapfs/mapfs_test.go
new file mode 100644
index 0000000..6b7db29
--- /dev/null
+++ b/godoc/vfs/mapfs/mapfs_test.go
@@ -0,0 +1,111 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package mapfs
+
+import (
+	"io/ioutil"
+	"os"
+	"reflect"
+	"testing"
+)
+
+func TestOpenRoot(t *testing.T) {
+	fs := New(map[string]string{
+		"foo/bar/three.txt": "a",
+		"foo/bar.txt":       "b",
+		"top.txt":           "c",
+		"other-top.txt":     "d",
+	})
+	tests := []struct {
+		path string
+		want string
+	}{
+		{"/foo/bar/three.txt", "a"},
+		{"foo/bar/three.txt", "a"},
+		{"foo/bar.txt", "b"},
+		{"top.txt", "c"},
+		{"/top.txt", "c"},
+		{"other-top.txt", "d"},
+		{"/other-top.txt", "d"},
+	}
+	for _, tt := range tests {
+		rsc, err := fs.Open(tt.path)
+		if err != nil {
+			t.Errorf("Open(%q) = %v", tt.path, err)
+			continue
+		}
+		slurp, err := ioutil.ReadAll(rsc)
+		if err != nil {
+			t.Error(err)
+		}
+		if string(slurp) != tt.want {
+			t.Errorf("Read(%q) = %q; want %q", tt.path, tt.want, slurp)
+		}
+		rsc.Close()
+	}
+
+	_, err := fs.Open("/xxxx")
+	if !os.IsNotExist(err) {
+		t.Errorf("ReadDir /xxxx = %v; want os.IsNotExist error", err)
+	}
+}
+
+func TestReaddir(t *testing.T) {
+	fs := New(map[string]string{
+		"foo/bar/three.txt": "333",
+		"foo/bar.txt":       "22",
+		"top.txt":           "top.txt file",
+		"other-top.txt":     "other-top.txt file",
+	})
+	tests := []struct {
+		dir  string
+		want []os.FileInfo
+	}{
+		{
+			dir: "/",
+			want: []os.FileInfo{
+				mapFI{name: "foo", dir: true},
+				mapFI{name: "other-top.txt", size: len("other-top.txt file")},
+				mapFI{name: "top.txt", size: len("top.txt file")},
+			},
+		},
+		{
+			dir: "/foo",
+			want: []os.FileInfo{
+				mapFI{name: "bar", dir: true},
+				mapFI{name: "bar.txt", size: 2},
+			},
+		},
+		{
+			dir: "/foo/",
+			want: []os.FileInfo{
+				mapFI{name: "bar", dir: true},
+				mapFI{name: "bar.txt", size: 2},
+			},
+		},
+		{
+			dir: "/foo/bar",
+			want: []os.FileInfo{
+				mapFI{name: "three.txt", size: 3},
+			},
+		},
+	}
+	for _, tt := range tests {
+		fis, err := fs.ReadDir(tt.dir)
+		if err != nil {
+			t.Errorf("ReadDir(%q) = %v", tt.dir, err)
+			continue
+		}
+		if !reflect.DeepEqual(fis, tt.want) {
+			t.Errorf("ReadDir(%q) = %#v; want %#v", tt.dir, fis, tt.want)
+			continue
+		}
+	}
+
+	_, err := fs.ReadDir("/xxxx")
+	if !os.IsNotExist(err) {
+		t.Errorf("ReadDir /xxxx = %v; want os.IsNotExist error", err)
+	}
+}
diff --git a/godoc/vfs/namespace.go b/godoc/vfs/namespace.go
new file mode 100644
index 0000000..dbba20c
--- /dev/null
+++ b/godoc/vfs/namespace.go
@@ -0,0 +1,381 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package vfs
+
+import (
+	"fmt"
+	"io"
+	"os"
+	pathpkg "path"
+	"sort"
+	"strings"
+	"time"
+)
+
+// Setting debugNS = true will enable debugging prints about
+// name space translations.
+const debugNS = false
+
+// A NameSpace is a file system made up of other file systems
+// mounted at specific locations in the name space.
+//
+// The representation is a map from mount point locations
+// to the list of file systems mounted at that location.  A traditional
+// Unix mount table would use a single file system per mount point,
+// but we want to be able to mount multiple file systems on a single
+// mount point and have the system behave as if the union of those
+// file systems were present at the mount point.
+// For example, if the OS file system has a Go installation in
+// c:\Go and additional Go path trees in  d:\Work1 and d:\Work2, then
+// this name space creates the view we want for the godoc server:
+//
+//	NameSpace{
+//		"/": {
+//			{old: "/", fs: OS(`c:\Go`), new: "/"},
+//		},
+//		"/src/pkg": {
+//			{old: "/src/pkg", fs: OS(`c:\Go`), new: "/src/pkg"},
+//			{old: "/src/pkg", fs: OS(`d:\Work1`), new: "/src"},
+//			{old: "/src/pkg", fs: OS(`d:\Work2`), new: "/src"},
+//		},
+//	}
+//
+// This is created by executing:
+//
+//	ns := NameSpace{}
+//	ns.Bind("/", OS(`c:\Go`), "/", BindReplace)
+//	ns.Bind("/src/pkg", OS(`d:\Work1`), "/src", BindAfter)
+//	ns.Bind("/src/pkg", OS(`d:\Work2`), "/src", BindAfter)
+//
+// A particular mount point entry is a triple (old, fs, new), meaning that to
+// operate on a path beginning with old, replace that prefix (old) with new
+// and then pass that path to the FileSystem implementation fs.
+//
+// Given this name space, a ReadDir of /src/pkg/code will check each prefix
+// of the path for a mount point (first /src/pkg/code, then /src/pkg, then /src,
+// then /), stopping when it finds one.  For the above example, /src/pkg/code
+// will find the mount point at /src/pkg:
+//
+//	{old: "/src/pkg", fs: OS(`c:\Go`), new: "/src/pkg"},
+//	{old: "/src/pkg", fs: OS(`d:\Work1`), new: "/src"},
+//	{old: "/src/pkg", fs: OS(`d:\Work2`), new: "/src"},
+//
+// ReadDir will when execute these three calls and merge the results:
+//
+//	OS(`c:\Go`).ReadDir("/src/pkg/code")
+//	OS(`d:\Work1').ReadDir("/src/code")
+//	OS(`d:\Work2').ReadDir("/src/code")
+//
+// Note that the "/src/pkg" in "/src/pkg/code" has been replaced by
+// just "/src" in the final two calls.
+//
+// OS is itself an implementation of a file system: it implements
+// OS(`c:\Go`).ReadDir("/src/pkg/code") as ioutil.ReadDir(`c:\Go\src\pkg\code`).
+//
+// Because the new path is evaluated by fs (here OS(root)), another way
+// to read the mount table is to mentally combine fs+new, so that this table:
+//
+//	{old: "/src/pkg", fs: OS(`c:\Go`), new: "/src/pkg"},
+//	{old: "/src/pkg", fs: OS(`d:\Work1`), new: "/src"},
+//	{old: "/src/pkg", fs: OS(`d:\Work2`), new: "/src"},
+//
+// reads as:
+//
+//	"/src/pkg" -> c:\Go\src\pkg
+//	"/src/pkg" -> d:\Work1\src
+//	"/src/pkg" -> d:\Work2\src
+//
+// An invariant (a redundancy) of the name space representation is that
+// ns[mtpt][i].old is always equal to mtpt (in the example, ns["/src/pkg"]'s
+// mount table entries always have old == "/src/pkg").  The 'old' field is
+// useful to callers, because they receive just a []mountedFS and not any
+// other indication of which mount point was found.
+//
+type NameSpace map[string][]mountedFS
+
+// A mountedFS handles requests for path by replacing
+// a prefix 'old' with 'new' and then calling the fs methods.
+type mountedFS struct {
+	old string
+	fs  FileSystem
+	new string
+}
+
+// hasPathPrefix returns true if x == y or x == y + "/" + more
+func hasPathPrefix(x, y string) bool {
+	return x == y || strings.HasPrefix(x, y) && (strings.HasSuffix(y, "/") || strings.HasPrefix(x[len(y):], "/"))
+}
+
+// translate translates path for use in m, replacing old with new.
+//
+// mountedFS{"/src/pkg", fs, "/src"}.translate("/src/pkg/code") == "/src/code".
+func (m mountedFS) translate(path string) string {
+	path = pathpkg.Clean("/" + path)
+	if !hasPathPrefix(path, m.old) {
+		panic("translate " + path + " but old=" + m.old)
+	}
+	return pathpkg.Join(m.new, path[len(m.old):])
+}
+
+func (NameSpace) String() string {
+	return "ns"
+}
+
+// Fprint writes a text representation of the name space to w.
+func (ns NameSpace) Fprint(w io.Writer) {
+	fmt.Fprint(w, "name space {\n")
+	var all []string
+	for mtpt := range ns {
+		all = append(all, mtpt)
+	}
+	sort.Strings(all)
+	for _, mtpt := range all {
+		fmt.Fprintf(w, "\t%s:\n", mtpt)
+		for _, m := range ns[mtpt] {
+			fmt.Fprintf(w, "\t\t%s %s\n", m.fs, m.new)
+		}
+	}
+	fmt.Fprint(w, "}\n")
+}
+
+// clean returns a cleaned, rooted path for evaluation.
+// It canonicalizes the path so that we can use string operations
+// to analyze it.
+func (NameSpace) clean(path string) string {
+	return pathpkg.Clean("/" + path)
+}
+
+type BindMode int
+
+const (
+	BindReplace BindMode = iota
+	BindBefore
+	BindAfter
+)
+
+// Bind causes references to old to redirect to the path new in newfs.
+// If mode is BindReplace, old redirections are discarded.
+// If mode is BindBefore, this redirection takes priority over existing ones,
+// but earlier ones are still consulted for paths that do not exist in newfs.
+// If mode is BindAfter, this redirection happens only after existing ones
+// have been tried and failed.
+func (ns NameSpace) Bind(old string, newfs FileSystem, new string, mode BindMode) {
+	old = ns.clean(old)
+	new = ns.clean(new)
+	m := mountedFS{old, newfs, new}
+	var mtpt []mountedFS
+	switch mode {
+	case BindReplace:
+		mtpt = append(mtpt, m)
+	case BindAfter:
+		mtpt = append(mtpt, ns.resolve(old)...)
+		mtpt = append(mtpt, m)
+	case BindBefore:
+		mtpt = append(mtpt, m)
+		mtpt = append(mtpt, ns.resolve(old)...)
+	}
+
+	// Extend m.old, m.new in inherited mount point entries.
+	for i := range mtpt {
+		m := &mtpt[i]
+		if m.old != old {
+			if !hasPathPrefix(old, m.old) {
+				// This should not happen.  If it does, panic so
+				// that we can see the call trace that led to it.
+				panic(fmt.Sprintf("invalid Bind: old=%q m={%q, %s, %q}", old, m.old, m.fs.String(), m.new))
+			}
+			suffix := old[len(m.old):]
+			m.old = pathpkg.Join(m.old, suffix)
+			m.new = pathpkg.Join(m.new, suffix)
+		}
+	}
+
+	ns[old] = mtpt
+}
+
+// resolve resolves a path to the list of mountedFS to use for path.
+func (ns NameSpace) resolve(path string) []mountedFS {
+	path = ns.clean(path)
+	for {
+		if m := ns[path]; m != nil {
+			if debugNS {
+				fmt.Printf("resolve %s: %v\n", path, m)
+			}
+			return m
+		}
+		if path == "/" {
+			break
+		}
+		path = pathpkg.Dir(path)
+	}
+	return nil
+}
+
+// Open implements the FileSystem Open method.
+func (ns NameSpace) Open(path string) (ReadSeekCloser, error) {
+	var err error
+	for _, m := range ns.resolve(path) {
+		if debugNS {
+			fmt.Printf("tx %s: %v\n", path, m.translate(path))
+		}
+		r, err1 := m.fs.Open(m.translate(path))
+		if err1 == nil {
+			return r, nil
+		}
+		if err == nil {
+			err = err1
+		}
+	}
+	if err == nil {
+		err = &os.PathError{Op: "open", Path: path, Err: os.ErrNotExist}
+	}
+	return nil, err
+}
+
+// stat implements the FileSystem Stat and Lstat methods.
+func (ns NameSpace) stat(path string, f func(FileSystem, string) (os.FileInfo, error)) (os.FileInfo, error) {
+	var err error
+	for _, m := range ns.resolve(path) {
+		fi, err1 := f(m.fs, m.translate(path))
+		if err1 == nil {
+			return fi, nil
+		}
+		if err == nil {
+			err = err1
+		}
+	}
+	if err == nil {
+		err = &os.PathError{Op: "stat", Path: path, Err: os.ErrNotExist}
+	}
+	return nil, err
+}
+
+func (ns NameSpace) Stat(path string) (os.FileInfo, error) {
+	return ns.stat(path, FileSystem.Stat)
+}
+
+func (ns NameSpace) Lstat(path string) (os.FileInfo, error) {
+	return ns.stat(path, FileSystem.Lstat)
+}
+
+// dirInfo is a trivial implementation of os.FileInfo for a directory.
+type dirInfo string
+
+func (d dirInfo) Name() string       { return string(d) }
+func (d dirInfo) Size() int64        { return 0 }
+func (d dirInfo) Mode() os.FileMode  { return os.ModeDir | 0555 }
+func (d dirInfo) ModTime() time.Time { return startTime }
+func (d dirInfo) IsDir() bool        { return true }
+func (d dirInfo) Sys() interface{}   { return nil }
+
+var startTime = time.Now()
+
+// ReadDir implements the FileSystem ReadDir method.  It's where most of the magic is.
+// (The rest is in resolve.)
+//
+// Logically, ReadDir must return the union of all the directories that are named
+// by path.  In order to avoid misinterpreting Go packages, of all the directories
+// that contain Go source code, we only include the files from the first,
+// but we include subdirectories from all.
+//
+// ReadDir must also return directory entries needed to reach mount points.
+// If the name space looks like the example in the type NameSpace comment,
+// but c:\Go does not have a src/pkg subdirectory, we still want to be able
+// to find that subdirectory, because we've mounted d:\Work1 and d:\Work2
+// there.  So if we don't see "src" in the directory listing for c:\Go, we add an
+// entry for it before returning.
+//
+func (ns NameSpace) ReadDir(path string) ([]os.FileInfo, error) {
+	path = ns.clean(path)
+
+	var (
+		haveGo   = false
+		haveName = map[string]bool{}
+		all      []os.FileInfo
+		err      error
+		first    []os.FileInfo
+	)
+
+	for _, m := range ns.resolve(path) {
+		dir, err1 := m.fs.ReadDir(m.translate(path))
+		if err1 != nil {
+			if err == nil {
+				err = err1
+			}
+			continue
+		}
+
+		if dir == nil {
+			dir = []os.FileInfo{}
+		}
+
+		if first == nil {
+			first = dir
+		}
+
+		// If we don't yet have Go files in 'all' and this directory
+		// has some, add all the files from this directory.
+		// Otherwise, only add subdirectories.
+		useFiles := false
+		if !haveGo {
+			for _, d := range dir {
+				if strings.HasSuffix(d.Name(), ".go") {
+					useFiles = true
+					haveGo = true
+					break
+				}
+			}
+		}
+
+		for _, d := range dir {
+			name := d.Name()
+			if (d.IsDir() || useFiles) && !haveName[name] {
+				haveName[name] = true
+				all = append(all, d)
+			}
+		}
+	}
+
+	// We didn't find any directories containing Go files.
+	// If some directory returned successfully, use that.
+	if !haveGo {
+		for _, d := range first {
+			if !haveName[d.Name()] {
+				haveName[d.Name()] = true
+				all = append(all, d)
+			}
+		}
+	}
+
+	// Built union.  Add any missing directories needed to reach mount points.
+	for old := range ns {
+		if hasPathPrefix(old, path) && old != path {
+			// Find next element after path in old.
+			elem := old[len(path):]
+			elem = strings.TrimPrefix(elem, "/")
+			if i := strings.Index(elem, "/"); i >= 0 {
+				elem = elem[:i]
+			}
+			if !haveName[elem] {
+				haveName[elem] = true
+				all = append(all, dirInfo(elem))
+			}
+		}
+	}
+
+	if len(all) == 0 {
+		return nil, err
+	}
+
+	sort.Sort(byName(all))
+	return all, nil
+}
+
+// byName implements sort.Interface.
+type byName []os.FileInfo
+
+func (f byName) Len() int           { return len(f) }
+func (f byName) Less(i, j int) bool { return f[i].Name() < f[j].Name() }
+func (f byName) Swap(i, j int)      { f[i], f[j] = f[j], f[i] }
diff --git a/godoc/vfs/os.go b/godoc/vfs/os.go
new file mode 100644
index 0000000..fa98142
--- /dev/null
+++ b/godoc/vfs/os.go
@@ -0,0 +1,65 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package vfs
+
+import (
+	"fmt"
+	"io/ioutil"
+	"os"
+	pathpkg "path"
+	"path/filepath"
+)
+
+// OS returns an implementation of FileSystem reading from the
+// tree rooted at root.  Recording a root is convenient everywhere
+// but necessary on Windows, because the slash-separated path
+// passed to Open has no way to specify a drive letter.  Using a root
+// lets code refer to OS(`c:\`), OS(`d:\`) and so on.
+func OS(root string) FileSystem {
+	return osFS(root)
+}
+
+type osFS string
+
+func (root osFS) String() string { return "os(" + string(root) + ")" }
+
+func (root osFS) resolve(path string) string {
+	// Clean the path so that it cannot possibly begin with ../.
+	// If it did, the result of filepath.Join would be outside the
+	// tree rooted at root.  We probably won't ever see a path
+	// with .. in it, but be safe anyway.
+	path = pathpkg.Clean("/" + path)
+
+	return filepath.Join(string(root), path)
+}
+
+func (root osFS) Open(path string) (ReadSeekCloser, error) {
+	f, err := os.Open(root.resolve(path))
+	if err != nil {
+		return nil, err
+	}
+	fi, err := f.Stat()
+	if err != nil {
+		f.Close()
+		return nil, err
+	}
+	if fi.IsDir() {
+		f.Close()
+		return nil, fmt.Errorf("Open: %s is a directory", path)
+	}
+	return f, nil
+}
+
+func (root osFS) Lstat(path string) (os.FileInfo, error) {
+	return os.Lstat(root.resolve(path))
+}
+
+func (root osFS) Stat(path string) (os.FileInfo, error) {
+	return os.Stat(root.resolve(path))
+}
+
+func (root osFS) ReadDir(path string) ([]os.FileInfo, error) {
+	return ioutil.ReadDir(root.resolve(path)) // is sorted
+}
diff --git a/godoc/vfs/vfs.go b/godoc/vfs/vfs.go
new file mode 100644
index 0000000..ad06b1a
--- /dev/null
+++ b/godoc/vfs/vfs.go
@@ -0,0 +1,45 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package vfs defines types for abstract file system access and provides an
+// implementation accessing the file system of the underlying OS.
+package vfs // import "golang.org/x/tools/godoc/vfs"
+
+import (
+	"io"
+	"io/ioutil"
+	"os"
+)
+
+// The FileSystem interface specifies the methods godoc is using
+// to access the file system for which it serves documentation.
+type FileSystem interface {
+	Opener
+	Lstat(path string) (os.FileInfo, error)
+	Stat(path string) (os.FileInfo, error)
+	ReadDir(path string) ([]os.FileInfo, error)
+	String() string
+}
+
+// Opener is a minimal virtual filesystem that can only open regular files.
+type Opener interface {
+	Open(name string) (ReadSeekCloser, error)
+}
+
+// A ReadSeekCloser can Read, Seek, and Close.
+type ReadSeekCloser interface {
+	io.Reader
+	io.Seeker
+	io.Closer
+}
+
+// ReadFile reads the file named by path from fs and returns the contents.
+func ReadFile(fs Opener, path string) ([]byte, error) {
+	rc, err := fs.Open(path)
+	if err != nil {
+		return nil, err
+	}
+	defer rc.Close()
+	return ioutil.ReadAll(rc)
+}
diff --git a/godoc/vfs/zipfs/zipfs.go b/godoc/vfs/zipfs/zipfs.go
new file mode 100644
index 0000000..87eaf8d
--- /dev/null
+++ b/godoc/vfs/zipfs/zipfs.go
@@ -0,0 +1,237 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package zipfs file provides an implementation of the FileSystem
+// interface based on the contents of a .zip file.
+//
+// Assumptions:
+//
+// - The file paths stored in the zip file must use a slash ('/') as path
+//   separator; and they must be relative (i.e., they must not start with
+//   a '/' - this is usually the case if the file was created w/o special
+//   options).
+// - The zip file system treats the file paths found in the zip internally
+//   like absolute paths w/o a leading '/'; i.e., the paths are considered
+//   relative to the root of the file system.
+// - All path arguments to file system methods must be absolute paths.
+package zipfs // import "golang.org/x/tools/godoc/vfs/zipfs"
+
+import (
+	"archive/zip"
+	"fmt"
+	"io"
+	"os"
+	"path"
+	"sort"
+	"strings"
+	"time"
+
+	"golang.org/x/tools/godoc/vfs"
+)
+
+// zipFI is the zip-file based implementation of FileInfo
+type zipFI struct {
+	name string    // directory-local name
+	file *zip.File // nil for a directory
+}
+
+func (fi zipFI) Name() string {
+	return fi.name
+}
+
+func (fi zipFI) Size() int64 {
+	if f := fi.file; f != nil {
+		return int64(f.UncompressedSize)
+	}
+	return 0 // directory
+}
+
+func (fi zipFI) ModTime() time.Time {
+	if f := fi.file; f != nil {
+		return f.ModTime()
+	}
+	return time.Time{} // directory has no modified time entry
+}
+
+func (fi zipFI) Mode() os.FileMode {
+	if fi.file == nil {
+		// Unix directories typically are executable, hence 555.
+		return os.ModeDir | 0555
+	}
+	return 0444
+}
+
+func (fi zipFI) IsDir() bool {
+	return fi.file == nil
+}
+
+func (fi zipFI) Sys() interface{} {
+	return nil
+}
+
+// zipFS is the zip-file based implementation of FileSystem
+type zipFS struct {
+	*zip.ReadCloser
+	list zipList
+	name string
+}
+
+func (fs *zipFS) String() string {
+	return "zip(" + fs.name + ")"
+}
+
+func (fs *zipFS) Close() error {
+	fs.list = nil
+	return fs.ReadCloser.Close()
+}
+
+func zipPath(name string) string {
+	name = path.Clean(name)
+	if !path.IsAbs(name) {
+		panic(fmt.Sprintf("stat: not an absolute path: %s", name))
+	}
+	return name[1:] // strip leading '/'
+}
+
+func (fs *zipFS) stat(abspath string) (int, zipFI, error) {
+	i, exact := fs.list.lookup(abspath)
+	if i < 0 {
+		// abspath has leading '/' stripped - print it explicitly
+		return -1, zipFI{}, fmt.Errorf("file not found: /%s", abspath)
+	}
+	_, name := path.Split(abspath)
+	var file *zip.File
+	if exact {
+		file = fs.list[i] // exact match found - must be a file
+	}
+	return i, zipFI{name, file}, nil
+}
+
+func (fs *zipFS) Open(abspath string) (vfs.ReadSeekCloser, error) {
+	_, fi, err := fs.stat(zipPath(abspath))
+	if err != nil {
+		return nil, err
+	}
+	if fi.IsDir() {
+		return nil, fmt.Errorf("Open: %s is a directory", abspath)
+	}
+	r, err := fi.file.Open()
+	if err != nil {
+		return nil, err
+	}
+	return &zipSeek{fi.file, r}, nil
+}
+
+type zipSeek struct {
+	file *zip.File
+	io.ReadCloser
+}
+
+func (f *zipSeek) Seek(offset int64, whence int) (int64, error) {
+	if whence == 0 && offset == 0 {
+		r, err := f.file.Open()
+		if err != nil {
+			return 0, err
+		}
+		f.Close()
+		f.ReadCloser = r
+		return 0, nil
+	}
+	return 0, fmt.Errorf("unsupported Seek in %s", f.file.Name)
+}
+
+func (fs *zipFS) Lstat(abspath string) (os.FileInfo, error) {
+	_, fi, err := fs.stat(zipPath(abspath))
+	return fi, err
+}
+
+func (fs *zipFS) Stat(abspath string) (os.FileInfo, error) {
+	_, fi, err := fs.stat(zipPath(abspath))
+	return fi, err
+}
+
+func (fs *zipFS) ReadDir(abspath string) ([]os.FileInfo, error) {
+	path := zipPath(abspath)
+	i, fi, err := fs.stat(path)
+	if err != nil {
+		return nil, err
+	}
+	if !fi.IsDir() {
+		return nil, fmt.Errorf("ReadDir: %s is not a directory", abspath)
+	}
+
+	var list []os.FileInfo
+	dirname := path + "/"
+	prevname := ""
+	for _, e := range fs.list[i:] {
+		if !strings.HasPrefix(e.Name, dirname) {
+			break // not in the same directory anymore
+		}
+		name := e.Name[len(dirname):] // local name
+		file := e
+		if i := strings.IndexRune(name, '/'); i >= 0 {
+			// We infer directories from files in subdirectories.
+			// If we have x/y, return a directory entry for x.
+			name = name[0:i] // keep local directory name only
+			file = nil
+		}
+		// If we have x/y and x/z, don't return two directory entries for x.
+		// TODO(gri): It should be possible to do this more efficiently
+		// by determining the (fs.list) range of local directory entries
+		// (via two binary searches).
+		if name != prevname {
+			list = append(list, zipFI{name, file})
+			prevname = name
+		}
+	}
+
+	return list, nil
+}
+
+func New(rc *zip.ReadCloser, name string) vfs.FileSystem {
+	list := make(zipList, len(rc.File))
+	copy(list, rc.File) // sort a copy of rc.File
+	sort.Sort(list)
+	return &zipFS{rc, list, name}
+}
+
+type zipList []*zip.File
+
+// zipList implements sort.Interface
+func (z zipList) Len() int           { return len(z) }
+func (z zipList) Less(i, j int) bool { return z[i].Name < z[j].Name }
+func (z zipList) Swap(i, j int)      { z[i], z[j] = z[j], z[i] }
+
+// lookup returns the smallest index of an entry with an exact match
+// for name, or an inexact match starting with name/. If there is no
+// such entry, the result is -1, false.
+func (z zipList) lookup(name string) (index int, exact bool) {
+	// look for exact match first (name comes before name/ in z)
+	i := sort.Search(len(z), func(i int) bool {
+		return name <= z[i].Name
+	})
+	if i >= len(z) {
+		return -1, false
+	}
+	// 0 <= i < len(z)
+	if z[i].Name == name {
+		return i, true
+	}
+
+	// look for inexact match (must be in z[i:], if present)
+	z = z[i:]
+	name += "/"
+	j := sort.Search(len(z), func(i int) bool {
+		return name <= z[i].Name
+	})
+	if j >= len(z) {
+		return -1, false
+	}
+	// 0 <= j < len(z)
+	if strings.HasPrefix(z[j].Name, name) {
+		return i + j, false
+	}
+
+	return -1, false
+}
diff --git a/imports/fix.go b/imports/fix.go
new file mode 100644
index 0000000..3ccee0e
--- /dev/null
+++ b/imports/fix.go
@@ -0,0 +1,387 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package imports
+
+import (
+	"fmt"
+	"go/ast"
+	"go/build"
+	"go/parser"
+	"go/token"
+	"os"
+	"path"
+	"path/filepath"
+	"strings"
+	"sync"
+
+	"golang.org/x/tools/go/ast/astutil"
+)
+
+// importToGroup is a list of functions which map from an import path to
+// a group number.
+var importToGroup = []func(importPath string) (num int, ok bool){
+	func(importPath string) (num int, ok bool) {
+		if strings.HasPrefix(importPath, "appengine") {
+			return 2, true
+		}
+		return
+	},
+	func(importPath string) (num int, ok bool) {
+		if strings.Contains(importPath, ".") {
+			return 1, true
+		}
+		return
+	},
+}
+
+func importGroup(importPath string) int {
+	for _, fn := range importToGroup {
+		if n, ok := fn(importPath); ok {
+			return n
+		}
+	}
+	return 0
+}
+
+func fixImports(fset *token.FileSet, f *ast.File) (added []string, err error) {
+	// refs are a set of possible package references currently unsatisfied by imports.
+	// first key: either base package (e.g. "fmt") or renamed package
+	// second key: referenced package symbol (e.g. "Println")
+	refs := make(map[string]map[string]bool)
+
+	// decls are the current package imports. key is base package or renamed package.
+	decls := make(map[string]*ast.ImportSpec)
+
+	// collect potential uses of packages.
+	var visitor visitFn
+	visitor = visitFn(func(node ast.Node) ast.Visitor {
+		if node == nil {
+			return visitor
+		}
+		switch v := node.(type) {
+		case *ast.ImportSpec:
+			if v.Name != nil {
+				decls[v.Name.Name] = v
+			} else {
+				local := importPathToName(strings.Trim(v.Path.Value, `\"`))
+				decls[local] = v
+			}
+		case *ast.SelectorExpr:
+			xident, ok := v.X.(*ast.Ident)
+			if !ok {
+				break
+			}
+			if xident.Obj != nil {
+				// if the parser can resolve it, it's not a package ref
+				break
+			}
+			pkgName := xident.Name
+			if refs[pkgName] == nil {
+				refs[pkgName] = make(map[string]bool)
+			}
+			if decls[pkgName] == nil {
+				refs[pkgName][v.Sel.Name] = true
+			}
+		}
+		return visitor
+	})
+	ast.Walk(visitor, f)
+
+	// Nil out any unused ImportSpecs, to be removed in following passes
+	unusedImport := map[string]bool{}
+	for pkg, is := range decls {
+		if refs[pkg] == nil && pkg != "_" && pkg != "." {
+			unusedImport[strings.Trim(is.Path.Value, `"`)] = true
+		}
+	}
+	for ipath := range unusedImport {
+		if ipath == "C" {
+			// Don't remove cgo stuff.
+			continue
+		}
+		astutil.DeleteImport(fset, f, ipath)
+	}
+
+	// Search for imports matching potential package references.
+	searches := 0
+	type result struct {
+		ipath string
+		name  string
+		err   error
+	}
+	results := make(chan result)
+	for pkgName, symbols := range refs {
+		if len(symbols) == 0 {
+			continue // skip over packages already imported
+		}
+		go func(pkgName string, symbols map[string]bool) {
+			ipath, rename, err := findImport(pkgName, symbols)
+			r := result{ipath: ipath, err: err}
+			if rename {
+				r.name = pkgName
+			}
+			results <- r
+		}(pkgName, symbols)
+		searches++
+	}
+	for i := 0; i < searches; i++ {
+		result := <-results
+		if result.err != nil {
+			return nil, result.err
+		}
+		if result.ipath != "" {
+			if result.name != "" {
+				astutil.AddNamedImport(fset, f, result.name, result.ipath)
+			} else {
+				astutil.AddImport(fset, f, result.ipath)
+			}
+			added = append(added, result.ipath)
+		}
+	}
+
+	return added, nil
+}
+
+// importPathToName returns the package name for the given import path.
+var importPathToName = importPathToNameGoPath
+
+// importPathToNameBasic assumes the package name is the base of import path.
+func importPathToNameBasic(importPath string) (packageName string) {
+	return path.Base(importPath)
+}
+
+// importPathToNameGoPath finds out the actual package name, as declared in its .go files.
+// If there's a problem, it falls back to using importPathToNameBasic.
+func importPathToNameGoPath(importPath string) (packageName string) {
+	if buildPkg, err := build.Import(importPath, "", 0); err == nil {
+		return buildPkg.Name
+	} else {
+		return importPathToNameBasic(importPath)
+	}
+}
+
+type pkg struct {
+	importpath string // full pkg import path, e.g. "net/http"
+	dir        string // absolute file path to pkg directory e.g. "/usr/lib/go/src/fmt"
+}
+
+var pkgIndexOnce sync.Once
+
+var pkgIndex struct {
+	sync.Mutex
+	m map[string][]pkg // shortname => []pkg, e.g "http" => "net/http"
+}
+
+// gate is a semaphore for limiting concurrency.
+type gate chan struct{}
+
+func (g gate) enter() { g <- struct{}{} }
+func (g gate) leave() { <-g }
+
+// fsgate protects the OS & filesystem from too much concurrency.
+// Too much disk I/O -> too many threads -> swapping and bad scheduling.
+var fsgate = make(gate, 8)
+
+func loadPkgIndex() {
+	pkgIndex.Lock()
+	pkgIndex.m = make(map[string][]pkg)
+	pkgIndex.Unlock()
+
+	var wg sync.WaitGroup
+	for _, path := range build.Default.SrcDirs() {
+		fsgate.enter()
+		f, err := os.Open(path)
+		if err != nil {
+			fsgate.leave()
+			fmt.Fprint(os.Stderr, err)
+			continue
+		}
+		children, err := f.Readdir(-1)
+		f.Close()
+		fsgate.leave()
+		if err != nil {
+			fmt.Fprint(os.Stderr, err)
+			continue
+		}
+		for _, child := range children {
+			if child.IsDir() {
+				wg.Add(1)
+				go func(path, name string) {
+					defer wg.Done()
+					loadPkg(&wg, path, name)
+				}(path, child.Name())
+			}
+		}
+	}
+	wg.Wait()
+}
+
+func loadPkg(wg *sync.WaitGroup, root, pkgrelpath string) {
+	importpath := filepath.ToSlash(pkgrelpath)
+	dir := filepath.Join(root, importpath)
+
+	fsgate.enter()
+	defer fsgate.leave()
+	pkgDir, err := os.Open(dir)
+	if err != nil {
+		return
+	}
+	children, err := pkgDir.Readdir(-1)
+	pkgDir.Close()
+	if err != nil {
+		return
+	}
+	// hasGo tracks whether a directory actually appears to be a
+	// Go source code directory. If $GOPATH == $HOME, and
+	// $HOME/src has lots of other large non-Go projects in it,
+	// then the calls to importPathToName below can be expensive.
+	hasGo := false
+	for _, child := range children {
+		// Avoid .foo, _foo, and testdata directory trees.
+		name := child.Name()
+		if name == "" || name[0] == '.' || name[0] == '_' || name == "testdata" {
+			continue
+		}
+		if strings.HasSuffix(name, ".go") {
+			hasGo = true
+		}
+		if child.IsDir() {
+			wg.Add(1)
+			go func(root, name string) {
+				defer wg.Done()
+				loadPkg(wg, root, name)
+			}(root, filepath.Join(importpath, name))
+		}
+	}
+	if hasGo {
+		shortName := importPathToName(importpath)
+		pkgIndex.Lock()
+		pkgIndex.m[shortName] = append(pkgIndex.m[shortName], pkg{
+			importpath: importpath,
+			dir:        dir,
+		})
+		pkgIndex.Unlock()
+	}
+
+}
+
+// loadExports returns a list exports for a package.
+var loadExports = loadExportsGoPath
+
+func loadExportsGoPath(dir string) map[string]bool {
+	exports := make(map[string]bool)
+	buildPkg, err := build.ImportDir(dir, 0)
+	if err != nil {
+		if strings.Contains(err.Error(), "no buildable Go source files in") {
+			return nil
+		}
+		fmt.Fprintf(os.Stderr, "could not import %q: %v\n", dir, err)
+		return nil
+	}
+	fset := token.NewFileSet()
+	for _, files := range [...][]string{buildPkg.GoFiles, buildPkg.CgoFiles} {
+		for _, file := range files {
+			f, err := parser.ParseFile(fset, filepath.Join(dir, file), nil, 0)
+			if err != nil {
+				fmt.Fprintf(os.Stderr, "could not parse %q: %v\n", file, err)
+				continue
+			}
+			for name := range f.Scope.Objects {
+				if ast.IsExported(name) {
+					exports[name] = true
+				}
+			}
+		}
+	}
+	return exports
+}
+
+// findImport searches for a package with the given symbols.
+// If no package is found, findImport returns "".
+// Declared as a variable rather than a function so goimports can be easily
+// extended by adding a file with an init function.
+var findImport = findImportGoPath
+
+func findImportGoPath(pkgName string, symbols map[string]bool) (string, bool, error) {
+	// Fast path for the standard library.
+	// In the common case we hopefully never have to scan the GOPATH, which can
+	// be slow with moving disks.
+	if pkg, rename, ok := findImportStdlib(pkgName, symbols); ok {
+		return pkg, rename, nil
+	}
+
+	// TODO(sameer): look at the import lines for other Go files in the
+	// local directory, since the user is likely to import the same packages
+	// in the current Go file.  Return rename=true when the other Go files
+	// use a renamed package that's also used in the current file.
+
+	pkgIndexOnce.Do(loadPkgIndex)
+
+	// Collect exports for packages with matching names.
+	var wg sync.WaitGroup
+	var pkgsMu sync.Mutex // guards pkgs
+	// full importpath => exported symbol => True
+	// e.g. "net/http" => "Client" => True
+	pkgs := make(map[string]map[string]bool)
+	pkgIndex.Lock()
+	for _, pkg := range pkgIndex.m[pkgName] {
+		wg.Add(1)
+		go func(importpath, dir string) {
+			defer wg.Done()
+			exports := loadExports(dir)
+			if exports != nil {
+				pkgsMu.Lock()
+				pkgs[importpath] = exports
+				pkgsMu.Unlock()
+			}
+		}(pkg.importpath, pkg.dir)
+	}
+	pkgIndex.Unlock()
+	wg.Wait()
+
+	// Filter out packages missing required exported symbols.
+	for symbol := range symbols {
+		for importpath, exports := range pkgs {
+			if !exports[symbol] {
+				delete(pkgs, importpath)
+			}
+		}
+	}
+	if len(pkgs) == 0 {
+		return "", false, nil
+	}
+
+	// If there are multiple candidate packages, the shortest one wins.
+	// This is a heuristic to prefer the standard library (e.g. "bytes")
+	// over e.g. "github.com/foo/bar/bytes".
+	shortest := ""
+	for importPath := range pkgs {
+		if shortest == "" || len(importPath) < len(shortest) {
+			shortest = importPath
+		}
+	}
+	return shortest, false, nil
+}
+
+type visitFn func(node ast.Node) ast.Visitor
+
+func (fn visitFn) Visit(node ast.Node) ast.Visitor {
+	return fn(node)
+}
+
+func findImportStdlib(shortPkg string, symbols map[string]bool) (importPath string, rename, ok bool) {
+	for symbol := range symbols {
+		path := stdlib[shortPkg+"."+symbol]
+		if path == "" {
+			return "", false, false
+		}
+		if importPath != "" && importPath != path {
+			// Ambiguous. Symbols pointed to different things.
+			return "", false, false
+		}
+		importPath = path
+	}
+	return importPath, false, importPath != ""
+}
diff --git a/imports/fix_test.go b/imports/fix_test.go
new file mode 100644
index 0000000..f087bc7
--- /dev/null
+++ b/imports/fix_test.go
@@ -0,0 +1,862 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package imports
+
+import (
+	"flag"
+	"go/build"
+	"io/ioutil"
+	"os"
+	"path/filepath"
+	"sync"
+	"testing"
+)
+
+var only = flag.String("only", "", "If non-empty, the fix test to run")
+
+var tests = []struct {
+	name    string
+	in, out string
+}{
+	// Adding an import to an existing parenthesized import
+	{
+		name: "factored_imports_add",
+		in: `package foo
+import (
+  "fmt"
+)
+func bar() {
+var b bytes.Buffer
+fmt.Println(b.String())
+}
+`,
+		out: `package foo
+
+import (
+	"bytes"
+	"fmt"
+)
+
+func bar() {
+	var b bytes.Buffer
+	fmt.Println(b.String())
+}
+`,
+	},
+
+	// Adding an import to an existing parenthesized import,
+	// verifying it goes into the first section.
+	{
+		name: "factored_imports_add_first_sec",
+		in: `package foo
+import (
+  "fmt"
+
+  "appengine"
+)
+func bar() {
+var b bytes.Buffer
+_ = appengine.IsDevServer
+fmt.Println(b.String())
+}
+`,
+		out: `package foo
+
+import (
+	"bytes"
+	"fmt"
+
+	"appengine"
+)
+
+func bar() {
+	var b bytes.Buffer
+	_ = appengine.IsDevServer
+	fmt.Println(b.String())
+}
+`,
+	},
+
+	// Adding an import to an existing parenthesized import,
+	// verifying it goes into the first section. (test 2)
+	{
+		name: "factored_imports_add_first_sec_2",
+		in: `package foo
+import (
+  "fmt"
+
+  "appengine"
+)
+func bar() {
+_ = math.NaN
+_ = fmt.Sprintf
+_ = appengine.IsDevServer
+}
+`,
+		out: `package foo
+
+import (
+	"fmt"
+	"math"
+
+	"appengine"
+)
+
+func bar() {
+	_ = math.NaN
+	_ = fmt.Sprintf
+	_ = appengine.IsDevServer
+}
+`,
+	},
+
+	// Adding a new import line, without parens
+	{
+		name: "add_import_section",
+		in: `package foo
+func bar() {
+var b bytes.Buffer
+}
+`,
+		out: `package foo
+
+import "bytes"
+
+func bar() {
+	var b bytes.Buffer
+}
+`,
+	},
+
+	// Adding two new imports, which should make a parenthesized import decl.
+	{
+		name: "add_import_paren_section",
+		in: `package foo
+func bar() {
+_, _ := bytes.Buffer, zip.NewReader
+}
+`,
+		out: `package foo
+
+import (
+	"archive/zip"
+	"bytes"
+)
+
+func bar() {
+	_, _ := bytes.Buffer, zip.NewReader
+}
+`,
+	},
+
+	// Make sure we don't add things twice
+	{
+		name: "no_double_add",
+		in: `package foo
+func bar() {
+_, _ := bytes.Buffer, bytes.NewReader
+}
+`,
+		out: `package foo
+
+import "bytes"
+
+func bar() {
+	_, _ := bytes.Buffer, bytes.NewReader
+}
+`,
+	},
+
+	// Remove unused imports, 1 of a factored block
+	{
+		name: "remove_unused_1_of_2",
+		in: `package foo
+import (
+"bytes"
+"fmt"
+)
+
+func bar() {
+_, _ := bytes.Buffer, bytes.NewReader
+}
+`,
+		out: `package foo
+
+import "bytes"
+
+func bar() {
+	_, _ := bytes.Buffer, bytes.NewReader
+}
+`,
+	},
+
+	// Remove unused imports, 2 of 2
+	{
+		name: "remove_unused_2_of_2",
+		in: `package foo
+import (
+"bytes"
+"fmt"
+)
+
+func bar() {
+}
+`,
+		out: `package foo
+
+func bar() {
+}
+`,
+	},
+
+	// Remove unused imports, 1 of 1
+	{
+		name: "remove_unused_1_of_1",
+		in: `package foo
+
+import "fmt"
+
+func bar() {
+}
+`,
+		out: `package foo
+
+func bar() {
+}
+`,
+	},
+
+	// Don't remove empty imports.
+	{
+		name: "dont_remove_empty_imports",
+		in: `package foo
+import (
+_ "image/png"
+_ "image/jpeg"
+)
+`,
+		out: `package foo
+
+import (
+	_ "image/jpeg"
+	_ "image/png"
+)
+`,
+	},
+
+	// Don't remove dot imports.
+	{
+		name: "dont_remove_dot_imports",
+		in: `package foo
+import (
+. "foo"
+. "bar"
+)
+`,
+		out: `package foo
+
+import (
+	. "bar"
+	. "foo"
+)
+`,
+	},
+
+	// Skip refs the parser can resolve.
+	{
+		name: "skip_resolved_refs",
+		in: `package foo
+
+func f() {
+	type t struct{ Println func(string) }
+	fmt := t{Println: func(string) {}}
+	fmt.Println("foo")
+}
+`,
+		out: `package foo
+
+func f() {
+	type t struct{ Println func(string) }
+	fmt := t{Println: func(string) {}}
+	fmt.Println("foo")
+}
+`,
+	},
+
+	// Do not add a package we already have a resolution for.
+	{
+		name: "skip_template",
+		in: `package foo
+
+import "html/template"
+
+func f() { t = template.New("sometemplate") }
+`,
+		out: `package foo
+
+import "html/template"
+
+func f() { t = template.New("sometemplate") }
+`,
+	},
+
+	// Don't touch cgo
+	{
+		name: "cgo",
+		in: `package foo
+
+/*
+#include <foo.h>
+*/
+import "C"
+`,
+		out: `package foo
+
+/*
+#include <foo.h>
+*/
+import "C"
+`,
+	},
+
+	// Put some things in their own section
+	{
+		name: "make_sections",
+		in: `package foo
+
+import (
+"os"
+)
+
+func foo () {
+_, _ = os.Args, fmt.Println
+_, _ = appengine.FooSomething, user.Current
+}
+`,
+		out: `package foo
+
+import (
+	"fmt"
+	"os"
+
+	"appengine"
+	"appengine/user"
+)
+
+func foo() {
+	_, _ = os.Args, fmt.Println
+	_, _ = appengine.FooSomething, user.Current
+}
+`,
+	},
+
+	// Delete existing empty import block
+	{
+		name: "delete_empty_import_block",
+		in: `package foo
+
+import ()
+`,
+		out: `package foo
+`,
+	},
+
+	// Use existing empty import block
+	{
+		name: "use_empty_import_block",
+		in: `package foo
+
+import ()
+
+func f() {
+	_ = fmt.Println
+}
+`,
+		out: `package foo
+
+import "fmt"
+
+func f() {
+	_ = fmt.Println
+}
+`,
+	},
+
+	// Blank line before adding new section.
+	{
+		name: "blank_line_before_new_group",
+		in: `package foo
+
+import (
+	"fmt"
+	"net"
+)
+
+func f() {
+	_ = net.Dial
+	_ = fmt.Printf
+	_ = snappy.Foo
+}
+`,
+		out: `package foo
+
+import (
+	"fmt"
+	"net"
+
+	"code.google.com/p/snappy-go/snappy"
+)
+
+func f() {
+	_ = net.Dial
+	_ = fmt.Printf
+	_ = snappy.Foo
+}
+`,
+	},
+
+	// Blank line between standard library and third-party stuff.
+	{
+		name: "blank_line_separating_std_and_third_party",
+		in: `package foo
+
+import (
+	"code.google.com/p/snappy-go/snappy"
+	"fmt"
+	"net"
+)
+
+func f() {
+	_ = net.Dial
+	_ = fmt.Printf
+	_ = snappy.Foo
+}
+`,
+		out: `package foo
+
+import (
+	"fmt"
+	"net"
+
+	"code.google.com/p/snappy-go/snappy"
+)
+
+func f() {
+	_ = net.Dial
+	_ = fmt.Printf
+	_ = snappy.Foo
+}
+`,
+	},
+
+	// golang.org/issue/6884
+	{
+		name: "issue 6884",
+		in: `package main
+
+// A comment
+func main() {
+	fmt.Println("Hello, world")
+}
+`,
+		out: `package main
+
+import "fmt"
+
+// A comment
+func main() {
+	fmt.Println("Hello, world")
+}
+`,
+	},
+
+	// golang.org/issue/7132
+	{
+		name: "issue 7132",
+		in: `package main
+
+import (
+"fmt"
+
+"gu"
+"github.com/foo/bar"
+)
+
+var (
+a = bar.a
+b = gu.a
+c = fmt.Printf
+)
+`,
+		out: `package main
+
+import (
+	"fmt"
+
+	"gu"
+
+	"github.com/foo/bar"
+)
+
+var (
+	a = bar.a
+	b = gu.a
+	c = fmt.Printf
+)
+`,
+	},
+
+	{
+		name: "renamed package",
+		in: `package main
+
+var _ = str.HasPrefix
+`,
+		out: `package main
+
+import str "strings"
+
+var _ = str.HasPrefix
+`,
+	},
+
+	{
+		name: "fragment with main",
+		in:   `func main(){fmt.Println("Hello, world")}`,
+		out: `package main
+
+import "fmt"
+
+func main() { fmt.Println("Hello, world") }
+`,
+	},
+
+	{
+		name: "fragment without main",
+		in:   `func notmain(){fmt.Println("Hello, world")}`,
+		out: `import "fmt"
+
+func notmain() { fmt.Println("Hello, world") }`,
+	},
+
+	// Remove first import within in a 2nd/3rd/4th/etc. section.
+	// golang.org/issue/7679
+	{
+		name: "issue 7679",
+		in: `package main
+
+import (
+	"fmt"
+
+	"github.com/foo/bar"
+	"github.com/foo/qux"
+)
+
+func main() {
+	var _ = fmt.Println
+	//var _ = bar.A
+	var _ = qux.B
+}
+`,
+		out: `package main
+
+import (
+	"fmt"
+
+	"github.com/foo/qux"
+)
+
+func main() {
+	var _ = fmt.Println
+	//var _ = bar.A
+	var _ = qux.B
+}
+`,
+	},
+
+	// Blank line can be added before all types of import declarations.
+	// golang.org/issue/7866
+	{
+		name: "issue 7866",
+		in: `package main
+
+import (
+	"fmt"
+	renamed_bar "github.com/foo/bar"
+
+	. "github.com/foo/baz"
+	"io"
+
+	_ "github.com/foo/qux"
+	"strings"
+)
+
+func main() {
+	_, _, _, _, _ = fmt.Errorf, io.Copy, strings.Contains, renamed_bar.A, B
+}
+`,
+		out: `package main
+
+import (
+	"fmt"
+
+	renamed_bar "github.com/foo/bar"
+
+	"io"
+
+	. "github.com/foo/baz"
+
+	"strings"
+
+	_ "github.com/foo/qux"
+)
+
+func main() {
+	_, _, _, _, _ = fmt.Errorf, io.Copy, strings.Contains, renamed_bar.A, B
+}
+`,
+	},
+
+	// Non-idempotent comment formatting
+	// golang.org/issue/8035
+	{
+		name: "issue 8035",
+		in: `package main
+
+import (
+	"fmt"                     // A
+	"go/ast"                  // B
+	_ "launchpad.net/gocheck" // C
+)
+
+func main() { _, _ = fmt.Print, ast.Walk }
+`,
+		out: `package main
+
+import (
+	"fmt"    // A
+	"go/ast" // B
+
+	_ "launchpad.net/gocheck" // C
+)
+
+func main() { _, _ = fmt.Print, ast.Walk }
+`,
+	},
+
+	// Failure to delete all duplicate imports
+	// golang.org/issue/8459
+	{
+		name: "issue 8459",
+		in: `package main
+
+import (
+	"fmt"
+	"log"
+	"log"
+	"math"
+)
+
+func main() { fmt.Println("pi:", math.Pi) }
+`,
+		out: `package main
+
+import (
+	"fmt"
+	"math"
+)
+
+func main() { fmt.Println("pi:", math.Pi) }
+`,
+	},
+
+	// Too aggressive prefix matching
+	// golang.org/issue/9961
+	{
+		name: "issue 9961",
+		in: `package p
+
+import (
+	"zip"
+
+	"rsc.io/p"
+)
+
+var (
+	_ = fmt.Print
+	_ = zip.Store
+	_ p.P
+	_ = regexp.Compile
+)
+`,
+		out: `package p
+
+import (
+	"fmt"
+	"regexp"
+	"zip"
+
+	"rsc.io/p"
+)
+
+var (
+	_ = fmt.Print
+	_ = zip.Store
+	_ p.P
+	_ = regexp.Compile
+)
+`,
+	},
+
+	// Unused named import is mistaken for unnamed import
+	// golang.org/issue/8149
+	{
+		name: "issue 8149",
+		in: `package main
+
+import foo "fmt"
+
+func main() { fmt.Println() }
+`,
+		out: `package main
+
+import "fmt"
+
+func main() { fmt.Println() }
+`,
+	},
+}
+
+func TestFixImports(t *testing.T) {
+	simplePkgs := map[string]string{
+		"appengine": "appengine",
+		"bytes":     "bytes",
+		"fmt":       "fmt",
+		"math":      "math",
+		"os":        "os",
+		"p":         "rsc.io/p",
+		"regexp":    "regexp",
+		"snappy":    "code.google.com/p/snappy-go/snappy",
+		"str":       "strings",
+		"user":      "appengine/user",
+		"zip":       "archive/zip",
+	}
+	findImport = func(pkgName string, symbols map[string]bool) (string, bool, error) {
+		return simplePkgs[pkgName], pkgName == "str", nil
+	}
+
+	options := &Options{
+		TabWidth:  8,
+		TabIndent: true,
+		Comments:  true,
+		Fragment:  true,
+	}
+
+	for _, tt := range tests {
+		if *only != "" && tt.name != *only {
+			continue
+		}
+		buf, err := Process(tt.name+".go", []byte(tt.in), options)
+		if err != nil {
+			t.Errorf("error on %q: %v", tt.name, err)
+			continue
+		}
+		if got := string(buf); got != tt.out {
+			t.Errorf("results diff on %q\nGOT:\n%s\nWANT:\n%s\n", tt.name, got, tt.out)
+		}
+	}
+}
+
+func TestFindImportGoPath(t *testing.T) {
+	goroot, err := ioutil.TempDir("", "goimports-")
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer os.RemoveAll(goroot)
+
+	pkgIndexOnce = sync.Once{}
+
+	origStdlib := stdlib
+	defer func() {
+		stdlib = origStdlib
+	}()
+	stdlib = nil
+
+	// Test against imaginary bits/bytes package in std lib
+	bytesDir := filepath.Join(goroot, "src", "pkg", "bits", "bytes")
+	for _, tag := range build.Default.ReleaseTags {
+		// Go 1.4 rearranged the GOROOT tree to remove the "pkg" path component.
+		if tag == "go1.4" {
+			bytesDir = filepath.Join(goroot, "src", "bits", "bytes")
+		}
+	}
+	if err := os.MkdirAll(bytesDir, 0755); err != nil {
+		t.Fatal(err)
+	}
+	bytesSrcPath := filepath.Join(bytesDir, "bytes.go")
+	bytesPkgPath := "bits/bytes"
+	bytesSrc := []byte(`package bytes
+
+type Buffer2 struct {}
+`)
+	if err := ioutil.WriteFile(bytesSrcPath, bytesSrc, 0775); err != nil {
+		t.Fatal(err)
+	}
+	oldGOROOT := build.Default.GOROOT
+	oldGOPATH := build.Default.GOPATH
+	build.Default.GOROOT = goroot
+	build.Default.GOPATH = ""
+	defer func() {
+		build.Default.GOROOT = oldGOROOT
+		build.Default.GOPATH = oldGOPATH
+	}()
+
+	got, rename, err := findImportGoPath("bytes", map[string]bool{"Buffer2": true})
+	if err != nil {
+		t.Fatal(err)
+	}
+	if got != bytesPkgPath || rename {
+		t.Errorf(`findImportGoPath("bytes", Buffer2 ...)=%q, %t, want "%s", false`, got, rename, bytesPkgPath)
+	}
+
+	got, rename, err = findImportGoPath("bytes", map[string]bool{"Missing": true})
+	if err != nil {
+		t.Fatal(err)
+	}
+	if got != "" || rename {
+		t.Errorf(`findImportGoPath("bytes", Missing ...)=%q, %t, want "", false`, got, rename)
+	}
+}
+
+func TestFindImportStdlib(t *testing.T) {
+	tests := []struct {
+		pkg     string
+		symbols []string
+		want    string
+	}{
+		{"http", []string{"Get"}, "net/http"},
+		{"http", []string{"Get", "Post"}, "net/http"},
+		{"http", []string{"Get", "Foo"}, ""},
+		{"bytes", []string{"Buffer"}, "bytes"},
+		{"ioutil", []string{"Discard"}, "io/ioutil"},
+	}
+	for _, tt := range tests {
+		got, rename, ok := findImportStdlib(tt.pkg, strSet(tt.symbols))
+		if (got != "") != ok {
+			t.Error("findImportStdlib return value inconsistent")
+		}
+		if got != tt.want || rename {
+			t.Errorf("findImportStdlib(%q, %q) = %q, %t; want %q, false", tt.pkg, tt.symbols, got, rename, tt.want)
+		}
+	}
+}
+
+func strSet(ss []string) map[string]bool {
+	m := make(map[string]bool)
+	for _, s := range ss {
+		m[s] = true
+	}
+	return m
+}
diff --git a/imports/imports.go b/imports/imports.go
new file mode 100644
index 0000000..e30946b
--- /dev/null
+++ b/imports/imports.go
@@ -0,0 +1,279 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package imports implements a Go pretty-printer (like package "go/format")
+// that also adds or removes import statements as necessary.
+package imports // import "golang.org/x/tools/imports"
+
+import (
+	"bufio"
+	"bytes"
+	"fmt"
+	"go/ast"
+	"go/format"
+	"go/parser"
+	"go/printer"
+	"go/token"
+	"io"
+	"regexp"
+	"strconv"
+	"strings"
+
+	"golang.org/x/tools/go/ast/astutil"
+)
+
+// Options specifies options for processing files.
+type Options struct {
+	Fragment  bool // Accept fragment of a source file (no package statement)
+	AllErrors bool // Report all errors (not just the first 10 on different lines)
+
+	Comments  bool // Print comments (true if nil *Options provided)
+	TabIndent bool // Use tabs for indent (true if nil *Options provided)
+	TabWidth  int  // Tab width (8 if nil *Options provided)
+}
+
+// Process formats and adjusts imports for the provided file.
+// If opt is nil the defaults are used.
+func Process(filename string, src []byte, opt *Options) ([]byte, error) {
+	if opt == nil {
+		opt = &Options{Comments: true, TabIndent: true, TabWidth: 8}
+	}
+
+	fileSet := token.NewFileSet()
+	file, adjust, err := parse(fileSet, filename, src, opt)
+	if err != nil {
+		return nil, err
+	}
+
+	_, err = fixImports(fileSet, file)
+	if err != nil {
+		return nil, err
+	}
+
+	sortImports(fileSet, file)
+	imps := astutil.Imports(fileSet, file)
+
+	var spacesBefore []string // import paths we need spaces before
+	for _, impSection := range imps {
+		// Within each block of contiguous imports, see if any
+		// import lines are in different group numbers. If so,
+		// we'll need to put a space between them so it's
+		// compatible with gofmt.
+		lastGroup := -1
+		for _, importSpec := range impSection {
+			importPath, _ := strconv.Unquote(importSpec.Path.Value)
+			groupNum := importGroup(importPath)
+			if groupNum != lastGroup && lastGroup != -1 {
+				spacesBefore = append(spacesBefore, importPath)
+			}
+			lastGroup = groupNum
+		}
+
+	}
+
+	printerMode := printer.UseSpaces
+	if opt.TabIndent {
+		printerMode |= printer.TabIndent
+	}
+	printConfig := &printer.Config{Mode: printerMode, Tabwidth: opt.TabWidth}
+
+	var buf bytes.Buffer
+	err = printConfig.Fprint(&buf, fileSet, file)
+	if err != nil {
+		return nil, err
+	}
+	out := buf.Bytes()
+	if adjust != nil {
+		out = adjust(src, out)
+	}
+	if len(spacesBefore) > 0 {
+		out = addImportSpaces(bytes.NewReader(out), spacesBefore)
+	}
+
+	out, err = format.Source(out)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+// parse parses src, which was read from filename,
+// as a Go source file or statement list.
+func parse(fset *token.FileSet, filename string, src []byte, opt *Options) (*ast.File, func(orig, src []byte) []byte, error) {
+	parserMode := parser.Mode(0)
+	if opt.Comments {
+		parserMode |= parser.ParseComments
+	}
+	if opt.AllErrors {
+		parserMode |= parser.AllErrors
+	}
+
+	// Try as whole source file.
+	file, err := parser.ParseFile(fset, filename, src, parserMode)
+	if err == nil {
+		return file, nil, nil
+	}
+	// If the error is that the source file didn't begin with a
+	// package line and we accept fragmented input, fall through to
+	// try as a source fragment.  Stop and return on any other error.
+	if !opt.Fragment || !strings.Contains(err.Error(), "expected 'package'") {
+		return nil, nil, err
+	}
+
+	// If this is a declaration list, make it a source file
+	// by inserting a package clause.
+	// Insert using a ;, not a newline, so that the line numbers
+	// in psrc match the ones in src.
+	psrc := append([]byte("package main;"), src...)
+	file, err = parser.ParseFile(fset, filename, psrc, parserMode)
+	if err == nil {
+		// If a main function exists, we will assume this is a main
+		// package and leave the file.
+		if containsMainFunc(file) {
+			return file, nil, nil
+		}
+
+		adjust := func(orig, src []byte) []byte {
+			// Remove the package clause.
+			// Gofmt has turned the ; into a \n.
+			src = src[len("package main\n"):]
+			return matchSpace(orig, src)
+		}
+		return file, adjust, nil
+	}
+	// If the error is that the source file didn't begin with a
+	// declaration, fall through to try as a statement list.
+	// Stop and return on any other error.
+	if !strings.Contains(err.Error(), "expected declaration") {
+		return nil, nil, err
+	}
+
+	// If this is a statement list, make it a source file
+	// by inserting a package clause and turning the list
+	// into a function body.  This handles expressions too.
+	// Insert using a ;, not a newline, so that the line numbers
+	// in fsrc match the ones in src.
+	fsrc := append(append([]byte("package p; func _() {"), src...), '}')
+	file, err = parser.ParseFile(fset, filename, fsrc, parserMode)
+	if err == nil {
+		adjust := func(orig, src []byte) []byte {
+			// Remove the wrapping.
+			// Gofmt has turned the ; into a \n\n.
+			src = src[len("package p\n\nfunc _() {"):]
+			src = src[:len(src)-len("}\n")]
+			// Gofmt has also indented the function body one level.
+			// Remove that indent.
+			src = bytes.Replace(src, []byte("\n\t"), []byte("\n"), -1)
+			return matchSpace(orig, src)
+		}
+		return file, adjust, nil
+	}
+
+	// Failed, and out of options.
+	return nil, nil, err
+}
+
+// containsMainFunc checks if a file contains a function declaration with the
+// function signature 'func main()'
+func containsMainFunc(file *ast.File) bool {
+	for _, decl := range file.Decls {
+		if f, ok := decl.(*ast.FuncDecl); ok {
+			if f.Name.Name != "main" {
+				continue
+			}
+
+			if len(f.Type.Params.List) != 0 {
+				continue
+			}
+
+			if f.Type.Results != nil && len(f.Type.Results.List) != 0 {
+				continue
+			}
+
+			return true
+		}
+	}
+
+	return false
+}
+
+func cutSpace(b []byte) (before, middle, after []byte) {
+	i := 0
+	for i < len(b) && (b[i] == ' ' || b[i] == '\t' || b[i] == '\n') {
+		i++
+	}
+	j := len(b)
+	for j > 0 && (b[j-1] == ' ' || b[j-1] == '\t' || b[j-1] == '\n') {
+		j--
+	}
+	if i <= j {
+		return b[:i], b[i:j], b[j:]
+	}
+	return nil, nil, b[j:]
+}
+
+// matchSpace reformats src to use the same space context as orig.
+// 1) If orig begins with blank lines, matchSpace inserts them at the beginning of src.
+// 2) matchSpace copies the indentation of the first non-blank line in orig
+//    to every non-blank line in src.
+// 3) matchSpace copies the trailing space from orig and uses it in place
+//   of src's trailing space.
+func matchSpace(orig []byte, src []byte) []byte {
+	before, _, after := cutSpace(orig)
+	i := bytes.LastIndex(before, []byte{'\n'})
+	before, indent := before[:i+1], before[i+1:]
+
+	_, src, _ = cutSpace(src)
+
+	var b bytes.Buffer
+	b.Write(before)
+	for len(src) > 0 {
+		line := src
+		if i := bytes.IndexByte(line, '\n'); i >= 0 {
+			line, src = line[:i+1], line[i+1:]
+		} else {
+			src = nil
+		}
+		if len(line) > 0 && line[0] != '\n' { // not blank
+			b.Write(indent)
+		}
+		b.Write(line)
+	}
+	b.Write(after)
+	return b.Bytes()
+}
+
+var impLine = regexp.MustCompile(`^\s+(?:[\w\.]+\s+)?"(.+)"`)
+
+func addImportSpaces(r io.Reader, breaks []string) []byte {
+	var out bytes.Buffer
+	sc := bufio.NewScanner(r)
+	inImports := false
+	done := false
+	for sc.Scan() {
+		s := sc.Text()
+
+		if !inImports && !done && strings.HasPrefix(s, "import") {
+			inImports = true
+		}
+		if inImports && (strings.HasPrefix(s, "var") ||
+			strings.HasPrefix(s, "func") ||
+			strings.HasPrefix(s, "const") ||
+			strings.HasPrefix(s, "type")) {
+			done = true
+			inImports = false
+		}
+		if inImports && len(breaks) > 0 {
+			if m := impLine.FindStringSubmatch(s); m != nil {
+				if m[1] == string(breaks[0]) {
+					out.WriteByte('\n')
+					breaks = breaks[1:]
+				}
+			}
+		}
+
+		fmt.Fprintln(&out, s)
+	}
+	return out.Bytes()
+}
diff --git a/imports/mkindex.go b/imports/mkindex.go
new file mode 100644
index 0000000..755e239
--- /dev/null
+++ b/imports/mkindex.go
@@ -0,0 +1,173 @@
+// +build ignore
+
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Command mkindex creates the file "pkgindex.go" containing an index of the Go
+// standard library. The file is intended to be built as part of the imports
+// package, so that the package may be used in environments where a GOROOT is
+// not available (such as App Engine).
+package main
+
+import (
+	"bytes"
+	"fmt"
+	"go/ast"
+	"go/build"
+	"go/format"
+	"go/parser"
+	"go/token"
+	"io/ioutil"
+	"log"
+	"os"
+	"path"
+	"path/filepath"
+	"strings"
+)
+
+var (
+	pkgIndex = make(map[string][]pkg)
+	exports  = make(map[string]map[string]bool)
+)
+
+func main() {
+	// Don't use GOPATH.
+	ctx := build.Default
+	ctx.GOPATH = ""
+
+	// Populate pkgIndex global from GOROOT.
+	for _, path := range ctx.SrcDirs() {
+		f, err := os.Open(path)
+		if err != nil {
+			log.Print(err)
+			continue
+		}
+		children, err := f.Readdir(-1)
+		f.Close()
+		if err != nil {
+			log.Print(err)
+			continue
+		}
+		for _, child := range children {
+			if child.IsDir() {
+				loadPkg(path, child.Name())
+			}
+		}
+	}
+	// Populate exports global.
+	for _, ps := range pkgIndex {
+		for _, p := range ps {
+			e := loadExports(p.dir)
+			if e != nil {
+				exports[p.dir] = e
+			}
+		}
+	}
+
+	// Construct source file.
+	var buf bytes.Buffer
+	fmt.Fprint(&buf, pkgIndexHead)
+	fmt.Fprintf(&buf, "var pkgIndexMaster = %#v\n", pkgIndex)
+	fmt.Fprintf(&buf, "var exportsMaster = %#v\n", exports)
+	src := buf.Bytes()
+
+	// Replace main.pkg type name with pkg.
+	src = bytes.Replace(src, []byte("main.pkg"), []byte("pkg"), -1)
+	// Replace actual GOROOT with "/go".
+	src = bytes.Replace(src, []byte(ctx.GOROOT), []byte("/go"), -1)
+	// Add some line wrapping.
+	src = bytes.Replace(src, []byte("}, "), []byte("},\n"), -1)
+	src = bytes.Replace(src, []byte("true, "), []byte("true,\n"), -1)
+
+	var err error
+	src, err = format.Source(src)
+	if err != nil {
+		log.Fatal(err)
+	}
+
+	// Write out source file.
+	err = ioutil.WriteFile("pkgindex.go", src, 0644)
+	if err != nil {
+		log.Fatal(err)
+	}
+}
+
+const pkgIndexHead = `package imports
+
+func init() {
+	pkgIndexOnce.Do(func() {
+		pkgIndex.m = pkgIndexMaster
+	})
+	loadExports = func(dir string) map[string]bool {
+		return exportsMaster[dir]
+	}
+}
+`
+
+type pkg struct {
+	importpath string // full pkg import path, e.g. "net/http"
+	dir        string // absolute file path to pkg directory e.g. "/usr/lib/go/src/fmt"
+}
+
+var fset = token.NewFileSet()
+
+func loadPkg(root, importpath string) {
+	shortName := path.Base(importpath)
+	if shortName == "testdata" {
+		return
+	}
+
+	dir := filepath.Join(root, importpath)
+	pkgIndex[shortName] = append(pkgIndex[shortName], pkg{
+		importpath: importpath,
+		dir:        dir,
+	})
+
+	pkgDir, err := os.Open(dir)
+	if err != nil {
+		return
+	}
+	children, err := pkgDir.Readdir(-1)
+	pkgDir.Close()
+	if err != nil {
+		return
+	}
+	for _, child := range children {
+		name := child.Name()
+		if name == "" {
+			continue
+		}
+		if c := name[0]; c == '.' || ('0' <= c && c <= '9') {
+			continue
+		}
+		if child.IsDir() {
+			loadPkg(root, filepath.Join(importpath, name))
+		}
+	}
+}
+
+func loadExports(dir string) map[string]bool {
+	exports := make(map[string]bool)
+	buildPkg, err := build.ImportDir(dir, 0)
+	if err != nil {
+		if strings.Contains(err.Error(), "no buildable Go source files in") {
+			return nil
+		}
+		log.Printf("could not import %q: %v", dir, err)
+		return nil
+	}
+	for _, file := range buildPkg.GoFiles {
+		f, err := parser.ParseFile(fset, filepath.Join(dir, file), nil, 0)
+		if err != nil {
+			log.Printf("could not parse %q: %v", file, err)
+			continue
+		}
+		for name := range f.Scope.Objects {
+			if ast.IsExported(name) {
+				exports[name] = true
+			}
+		}
+	}
+	return exports
+}
diff --git a/imports/mkstdlib.go b/imports/mkstdlib.go
new file mode 100644
index 0000000..c43d325
--- /dev/null
+++ b/imports/mkstdlib.go
@@ -0,0 +1,90 @@
+// +build ignore
+
+// mkstdlib generates the zstdlib.go file, containing the Go standard
+// library API symbols. It's baked into the binary to avoid scanning
+// GOPATH in the common case.
+package main
+
+import (
+	"bufio"
+	"bytes"
+	"fmt"
+	"go/format"
+	"io"
+	"log"
+	"os"
+	"path"
+	"path/filepath"
+	"regexp"
+	"sort"
+	"strings"
+)
+
+func mustOpen(name string) io.Reader {
+	f, err := os.Open(name)
+	if err != nil {
+		log.Fatal(err)
+	}
+	return f
+}
+
+func api(base string) string {
+	return filepath.Join(os.Getenv("GOROOT"), "api", base)
+}
+
+var sym = regexp.MustCompile(`^pkg (\S+).*?, (?:var|func|type|const) ([A-Z]\w*)`)
+
+func main() {
+	var buf bytes.Buffer
+	outf := func(format string, args ...interface{}) {
+		fmt.Fprintf(&buf, format, args...)
+	}
+	outf("// AUTO-GENERATED BY mkstdlib.go\n\n")
+	outf("package imports\n")
+	outf("var stdlib = map[string]string{\n")
+	f := io.MultiReader(
+		mustOpen(api("go1.txt")),
+		mustOpen(api("go1.1.txt")),
+		mustOpen(api("go1.2.txt")),
+	)
+	sc := bufio.NewScanner(f)
+	fullImport := map[string]string{} // "zip.NewReader" => "archive/zip"
+	ambiguous := map[string]bool{}
+	var keys []string
+	for sc.Scan() {
+		l := sc.Text()
+		has := func(v string) bool { return strings.Contains(l, v) }
+		if has("struct, ") || has("interface, ") || has(", method (") {
+			continue
+		}
+		if m := sym.FindStringSubmatch(l); m != nil {
+			full := m[1]
+			key := path.Base(full) + "." + m[2]
+			if exist, ok := fullImport[key]; ok {
+				if exist != full {
+					ambiguous[key] = true
+				}
+			} else {
+				fullImport[key] = full
+				keys = append(keys, key)
+			}
+		}
+	}
+	if err := sc.Err(); err != nil {
+		log.Fatal(err)
+	}
+	sort.Strings(keys)
+	for _, key := range keys {
+		if ambiguous[key] {
+			outf("\t// %q is ambiguous\n", key)
+		} else {
+			outf("\t%q: %q,\n", key, fullImport[key])
+		}
+	}
+	outf("}\n")
+	fmtbuf, err := format.Source(buf.Bytes())
+	if err != nil {
+		log.Fatal(err)
+	}
+	os.Stdout.Write(fmtbuf)
+}
diff --git a/imports/sortimports.go b/imports/sortimports.go
new file mode 100644
index 0000000..68b3dc4
--- /dev/null
+++ b/imports/sortimports.go
@@ -0,0 +1,214 @@
+// +build go1.2
+
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Hacked up copy of go/ast/import.go
+
+package imports
+
+import (
+	"go/ast"
+	"go/token"
+	"sort"
+	"strconv"
+)
+
+// sortImports sorts runs of consecutive import lines in import blocks in f.
+// It also removes duplicate imports when it is possible to do so without data loss.
+func sortImports(fset *token.FileSet, f *ast.File) {
+	for i, d := range f.Decls {
+		d, ok := d.(*ast.GenDecl)
+		if !ok || d.Tok != token.IMPORT {
+			// Not an import declaration, so we're done.
+			// Imports are always first.
+			break
+		}
+
+		if len(d.Specs) == 0 {
+			// Empty import block, remove it.
+			f.Decls = append(f.Decls[:i], f.Decls[i+1:]...)
+		}
+
+		if !d.Lparen.IsValid() {
+			// Not a block: sorted by default.
+			continue
+		}
+
+		// Identify and sort runs of specs on successive lines.
+		i := 0
+		specs := d.Specs[:0]
+		for j, s := range d.Specs {
+			if j > i && fset.Position(s.Pos()).Line > 1+fset.Position(d.Specs[j-1].End()).Line {
+				// j begins a new run.  End this one.
+				specs = append(specs, sortSpecs(fset, f, d.Specs[i:j])...)
+				i = j
+			}
+		}
+		specs = append(specs, sortSpecs(fset, f, d.Specs[i:])...)
+		d.Specs = specs
+
+		// Deduping can leave a blank line before the rparen; clean that up.
+		if len(d.Specs) > 0 {
+			lastSpec := d.Specs[len(d.Specs)-1]
+			lastLine := fset.Position(lastSpec.Pos()).Line
+			if rParenLine := fset.Position(d.Rparen).Line; rParenLine > lastLine+1 {
+				fset.File(d.Rparen).MergeLine(rParenLine - 1)
+			}
+		}
+	}
+}
+
+func importPath(s ast.Spec) string {
+	t, err := strconv.Unquote(s.(*ast.ImportSpec).Path.Value)
+	if err == nil {
+		return t
+	}
+	return ""
+}
+
+func importName(s ast.Spec) string {
+	n := s.(*ast.ImportSpec).Name
+	if n == nil {
+		return ""
+	}
+	return n.Name
+}
+
+func importComment(s ast.Spec) string {
+	c := s.(*ast.ImportSpec).Comment
+	if c == nil {
+		return ""
+	}
+	return c.Text()
+}
+
+// collapse indicates whether prev may be removed, leaving only next.
+func collapse(prev, next ast.Spec) bool {
+	if importPath(next) != importPath(prev) || importName(next) != importName(prev) {
+		return false
+	}
+	return prev.(*ast.ImportSpec).Comment == nil
+}
+
+type posSpan struct {
+	Start token.Pos
+	End   token.Pos
+}
+
+func sortSpecs(fset *token.FileSet, f *ast.File, specs []ast.Spec) []ast.Spec {
+	// Can't short-circuit here even if specs are already sorted,
+	// since they might yet need deduplication.
+	// A lone import, however, may be safely ignored.
+	if len(specs) <= 1 {
+		return specs
+	}
+
+	// Record positions for specs.
+	pos := make([]posSpan, len(specs))
+	for i, s := range specs {
+		pos[i] = posSpan{s.Pos(), s.End()}
+	}
+
+	// Identify comments in this range.
+	// Any comment from pos[0].Start to the final line counts.
+	lastLine := fset.Position(pos[len(pos)-1].End).Line
+	cstart := len(f.Comments)
+	cend := len(f.Comments)
+	for i, g := range f.Comments {
+		if g.Pos() < pos[0].Start {
+			continue
+		}
+		if i < cstart {
+			cstart = i
+		}
+		if fset.Position(g.End()).Line > lastLine {
+			cend = i
+			break
+		}
+	}
+	comments := f.Comments[cstart:cend]
+
+	// Assign each comment to the import spec preceding it.
+	importComment := map[*ast.ImportSpec][]*ast.CommentGroup{}
+	specIndex := 0
+	for _, g := range comments {
+		for specIndex+1 < len(specs) && pos[specIndex+1].Start <= g.Pos() {
+			specIndex++
+		}
+		s := specs[specIndex].(*ast.ImportSpec)
+		importComment[s] = append(importComment[s], g)
+	}
+
+	// Sort the import specs by import path.
+	// Remove duplicates, when possible without data loss.
+	// Reassign the import paths to have the same position sequence.
+	// Reassign each comment to abut the end of its spec.
+	// Sort the comments by new position.
+	sort.Sort(byImportSpec(specs))
+
+	// Dedup. Thanks to our sorting, we can just consider
+	// adjacent pairs of imports.
+	deduped := specs[:0]
+	for i, s := range specs {
+		if i == len(specs)-1 || !collapse(s, specs[i+1]) {
+			deduped = append(deduped, s)
+		} else {
+			p := s.Pos()
+			fset.File(p).MergeLine(fset.Position(p).Line)
+		}
+	}
+	specs = deduped
+
+	// Fix up comment positions
+	for i, s := range specs {
+		s := s.(*ast.ImportSpec)
+		if s.Name != nil {
+			s.Name.NamePos = pos[i].Start
+		}
+		s.Path.ValuePos = pos[i].Start
+		s.EndPos = pos[i].End
+		for _, g := range importComment[s] {
+			for _, c := range g.List {
+				c.Slash = pos[i].End
+			}
+		}
+	}
+
+	sort.Sort(byCommentPos(comments))
+
+	return specs
+}
+
+type byImportSpec []ast.Spec // slice of *ast.ImportSpec
+
+func (x byImportSpec) Len() int      { return len(x) }
+func (x byImportSpec) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
+func (x byImportSpec) Less(i, j int) bool {
+	ipath := importPath(x[i])
+	jpath := importPath(x[j])
+
+	igroup := importGroup(ipath)
+	jgroup := importGroup(jpath)
+	if igroup != jgroup {
+		return igroup < jgroup
+	}
+
+	if ipath != jpath {
+		return ipath < jpath
+	}
+	iname := importName(x[i])
+	jname := importName(x[j])
+
+	if iname != jname {
+		return iname < jname
+	}
+	return importComment(x[i]) < importComment(x[j])
+}
+
+type byCommentPos []*ast.CommentGroup
+
+func (x byCommentPos) Len() int           { return len(x) }
+func (x byCommentPos) Swap(i, j int)      { x[i], x[j] = x[j], x[i] }
+func (x byCommentPos) Less(i, j int) bool { return x[i].Pos() < x[j].Pos() }
diff --git a/imports/sortimports_compat.go b/imports/sortimports_compat.go
new file mode 100644
index 0000000..295f237
--- /dev/null
+++ b/imports/sortimports_compat.go
@@ -0,0 +1,14 @@
+// +build !go1.2
+
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package imports
+
+import "go/ast"
+
+// Go 1.1 users don't get fancy package grouping.
+// But this is still gofmt-compliant:
+
+var sortImports = ast.SortImports
diff --git a/imports/zstdlib.go b/imports/zstdlib.go
new file mode 100644
index 0000000..6cdc033
--- /dev/null
+++ b/imports/zstdlib.go
@@ -0,0 +1,8374 @@
+// AUTO-GENERATED BY mkstdlib.go
+
+package imports
+
+var stdlib = map[string]string{
+	"adler32.Checksum":                        "hash/adler32",
+	"adler32.New":                             "hash/adler32",
+	"adler32.Size":                            "hash/adler32",
+	"aes.BlockSize":                           "crypto/aes",
+	"aes.KeySizeError":                        "crypto/aes",
+	"aes.NewCipher":                           "crypto/aes",
+	"ascii85.CorruptInputError":               "encoding/ascii85",
+	"ascii85.Decode":                          "encoding/ascii85",
+	"ascii85.Encode":                          "encoding/ascii85",
+	"ascii85.MaxEncodedLen":                   "encoding/ascii85",
+	"ascii85.NewDecoder":                      "encoding/ascii85",
+	"ascii85.NewEncoder":                      "encoding/ascii85",
+	"asn1.BitString":                          "encoding/asn1",
+	"asn1.Enumerated":                         "encoding/asn1",
+	"asn1.Flag":                               "encoding/asn1",
+	"asn1.Marshal":                            "encoding/asn1",
+	"asn1.ObjectIdentifier":                   "encoding/asn1",
+	"asn1.RawContent":                         "encoding/asn1",
+	"asn1.RawValue":                           "encoding/asn1",
+	"asn1.StructuralError":                    "encoding/asn1",
+	"asn1.SyntaxError":                        "encoding/asn1",
+	"asn1.Unmarshal":                          "encoding/asn1",
+	"asn1.UnmarshalWithParams":                "encoding/asn1",
+	"ast.ArrayType":                           "go/ast",
+	"ast.AssignStmt":                          "go/ast",
+	"ast.Bad":                                 "go/ast",
+	"ast.BadDecl":                             "go/ast",
+	"ast.BadExpr":                             "go/ast",
+	"ast.BadStmt":                             "go/ast",
+	"ast.BasicLit":                            "go/ast",
+	"ast.BinaryExpr":                          "go/ast",
+	"ast.BlockStmt":                           "go/ast",
+	"ast.BranchStmt":                          "go/ast",
+	"ast.CallExpr":                            "go/ast",
+	"ast.CaseClause":                          "go/ast",
+	"ast.ChanDir":                             "go/ast",
+	"ast.ChanType":                            "go/ast",
+	"ast.CommClause":                          "go/ast",
+	"ast.Comment":                             "go/ast",
+	"ast.CommentGroup":                        "go/ast",
+	"ast.CommentMap":                          "go/ast",
+	"ast.CompositeLit":                        "go/ast",
+	"ast.Con":                                 "go/ast",
+	"ast.DeclStmt":                            "go/ast",
+	"ast.DeferStmt":                           "go/ast",
+	"ast.Ellipsis":                            "go/ast",
+	"ast.EmptyStmt":                           "go/ast",
+	"ast.ExprStmt":                            "go/ast",
+	"ast.Field":                               "go/ast",
+	"ast.FieldFilter":                         "go/ast",
+	"ast.FieldList":                           "go/ast",
+	"ast.File":                                "go/ast",
+	"ast.FileExports":                         "go/ast",
+	"ast.Filter":                              "go/ast",
+	"ast.FilterDecl":                          "go/ast",
+	"ast.FilterFile":                          "go/ast",
+	"ast.FilterFuncDuplicates":                "go/ast",
+	"ast.FilterImportDuplicates":              "go/ast",
+	"ast.FilterPackage":                       "go/ast",
+	"ast.FilterUnassociatedComments":          "go/ast",
+	"ast.ForStmt":                             "go/ast",
+	"ast.Fprint":                              "go/ast",
+	"ast.Fun":                                 "go/ast",
+	"ast.FuncDecl":                            "go/ast",
+	"ast.FuncLit":                             "go/ast",
+	"ast.FuncType":                            "go/ast",
+	"ast.GenDecl":                             "go/ast",
+	"ast.GoStmt":                              "go/ast",
+	"ast.Ident":                               "go/ast",
+	"ast.IfStmt":                              "go/ast",
+	"ast.ImportSpec":                          "go/ast",
+	"ast.Importer":                            "go/ast",
+	"ast.IncDecStmt":                          "go/ast",
+	"ast.IndexExpr":                           "go/ast",
+	"ast.Inspect":                             "go/ast",
+	"ast.InterfaceType":                       "go/ast",
+	"ast.IsExported":                          "go/ast",
+	"ast.KeyValueExpr":                        "go/ast",
+	"ast.LabeledStmt":                         "go/ast",
+	"ast.Lbl":                                 "go/ast",
+	"ast.MapType":                             "go/ast",
+	"ast.MergeMode":                           "go/ast",
+	"ast.MergePackageFiles":                   "go/ast",
+	"ast.NewCommentMap":                       "go/ast",
+	"ast.NewIdent":                            "go/ast",
+	"ast.NewObj":                              "go/ast",
+	"ast.NewPackage":                          "go/ast",
+	"ast.NewScope":                            "go/ast",
+	"ast.Node":                                "go/ast",
+	"ast.NotNilFilter":                        "go/ast",
+	"ast.ObjKind":                             "go/ast",
+	"ast.Object":                              "go/ast",
+	"ast.Package":                             "go/ast",
+	"ast.PackageExports":                      "go/ast",
+	"ast.ParenExpr":                           "go/ast",
+	"ast.Pkg":                                 "go/ast",
+	"ast.Print":                               "go/ast",
+	"ast.RECV":                                "go/ast",
+	"ast.RangeStmt":                           "go/ast",
+	"ast.ReturnStmt":                          "go/ast",
+	"ast.SEND":                                "go/ast",
+	"ast.Scope":                               "go/ast",
+	"ast.SelectStmt":                          "go/ast",
+	"ast.SelectorExpr":                        "go/ast",
+	"ast.SendStmt":                            "go/ast",
+	"ast.SliceExpr":                           "go/ast",
+	"ast.SortImports":                         "go/ast",
+	"ast.StarExpr":                            "go/ast",
+	"ast.StructType":                          "go/ast",
+	"ast.SwitchStmt":                          "go/ast",
+	"ast.Typ":                                 "go/ast",
+	"ast.TypeAssertExpr":                      "go/ast",
+	"ast.TypeSpec":                            "go/ast",
+	"ast.TypeSwitchStmt":                      "go/ast",
+	"ast.UnaryExpr":                           "go/ast",
+	"ast.ValueSpec":                           "go/ast",
+	"ast.Var":                                 "go/ast",
+	"ast.Visitor":                             "go/ast",
+	"ast.Walk":                                "go/ast",
+	"atomic.AddInt32":                         "sync/atomic",
+	"atomic.AddInt64":                         "sync/atomic",
+	"atomic.AddUint32":                        "sync/atomic",
+	"atomic.AddUint64":                        "sync/atomic",
+	"atomic.AddUintptr":                       "sync/atomic",
+	"atomic.CompareAndSwapInt32":              "sync/atomic",
+	"atomic.CompareAndSwapInt64":              "sync/atomic",
+	"atomic.CompareAndSwapPointer":            "sync/atomic",
+	"atomic.CompareAndSwapUint32":             "sync/atomic",
+	"atomic.CompareAndSwapUint64":             "sync/atomic",
+	"atomic.CompareAndSwapUintptr":            "sync/atomic",
+	"atomic.LoadInt32":                        "sync/atomic",
+	"atomic.LoadInt64":                        "sync/atomic",
+	"atomic.LoadPointer":                      "sync/atomic",
+	"atomic.LoadUint32":                       "sync/atomic",
+	"atomic.LoadUint64":                       "sync/atomic",
+	"atomic.LoadUintptr":                      "sync/atomic",
+	"atomic.StoreInt32":                       "sync/atomic",
+	"atomic.StoreInt64":                       "sync/atomic",
+	"atomic.StorePointer":                     "sync/atomic",
+	"atomic.StoreUint32":                      "sync/atomic",
+	"atomic.StoreUint64":                      "sync/atomic",
+	"atomic.StoreUintptr":                     "sync/atomic",
+	"atomic.SwapInt32":                        "sync/atomic",
+	"atomic.SwapInt64":                        "sync/atomic",
+	"atomic.SwapPointer":                      "sync/atomic",
+	"atomic.SwapUint32":                       "sync/atomic",
+	"atomic.SwapUint64":                       "sync/atomic",
+	"atomic.SwapUintptr":                      "sync/atomic",
+	"base32.CorruptInputError":                "encoding/base32",
+	"base32.Encoding":                         "encoding/base32",
+	"base32.HexEncoding":                      "encoding/base32",
+	"base32.NewDecoder":                       "encoding/base32",
+	"base32.NewEncoder":                       "encoding/base32",
+	"base32.NewEncoding":                      "encoding/base32",
+	"base32.StdEncoding":                      "encoding/base32",
+	"base64.CorruptInputError":                "encoding/base64",
+	"base64.Encoding":                         "encoding/base64",
+	"base64.NewDecoder":                       "encoding/base64",
+	"base64.NewEncoder":                       "encoding/base64",
+	"base64.NewEncoding":                      "encoding/base64",
+	"base64.StdEncoding":                      "encoding/base64",
+	"base64.URLEncoding":                      "encoding/base64",
+	"big.Int":                                 "math/big",
+	"big.MaxBase":                             "math/big",
+	"big.NewInt":                              "math/big",
+	"big.NewRat":                              "math/big",
+	"big.Rat":                                 "math/big",
+	"big.Word":                                "math/big",
+	"binary.BigEndian":                        "encoding/binary",
+	"binary.ByteOrder":                        "encoding/binary",
+	"binary.LittleEndian":                     "encoding/binary",
+	"binary.MaxVarintLen16":                   "encoding/binary",
+	"binary.MaxVarintLen32":                   "encoding/binary",
+	"binary.MaxVarintLen64":                   "encoding/binary",
+	"binary.PutUvarint":                       "encoding/binary",
+	"binary.PutVarint":                        "encoding/binary",
+	"binary.Read":                             "encoding/binary",
+	"binary.ReadUvarint":                      "encoding/binary",
+	"binary.ReadVarint":                       "encoding/binary",
+	"binary.Size":                             "encoding/binary",
+	"binary.Uvarint":                          "encoding/binary",
+	"binary.Varint":                           "encoding/binary",
+	"binary.Write":                            "encoding/binary",
+	"bufio.ErrAdvanceTooFar":                  "bufio",
+	"bufio.ErrBufferFull":                     "bufio",
+	"bufio.ErrInvalidUnreadByte":              "bufio",
+	"bufio.ErrInvalidUnreadRune":              "bufio",
+	"bufio.ErrNegativeAdvance":                "bufio",
+	"bufio.ErrNegativeCount":                  "bufio",
+	"bufio.ErrTooLong":                        "bufio",
+	"bufio.MaxScanTokenSize":                  "bufio",
+	"bufio.NewReadWriter":                     "bufio",
+	"bufio.NewReader":                         "bufio",
+	"bufio.NewReaderSize":                     "bufio",
+	"bufio.NewScanner":                        "bufio",
+	"bufio.NewWriter":                         "bufio",
+	"bufio.NewWriterSize":                     "bufio",
+	"bufio.ReadWriter":                        "bufio",
+	"bufio.Reader":                            "bufio",
+	"bufio.ScanBytes":                         "bufio",
+	"bufio.ScanLines":                         "bufio",
+	"bufio.ScanRunes":                         "bufio",
+	"bufio.ScanWords":                         "bufio",
+	"bufio.Scanner":                           "bufio",
+	"bufio.SplitFunc":                         "bufio",
+	"bufio.Writer":                            "bufio",
+	"build.AllowBinary":                       "go/build",
+	"build.ArchChar":                          "go/build",
+	"build.Context":                           "go/build",
+	"build.Default":                           "go/build",
+	"build.FindOnly":                          "go/build",
+	"build.Import":                            "go/build",
+	"build.ImportDir":                         "go/build",
+	"build.ImportMode":                        "go/build",
+	"build.IsLocalImport":                     "go/build",
+	"build.NoGoError":                         "go/build",
+	"build.Package":                           "go/build",
+	"build.ToolDir":                           "go/build",
+	"bytes.Buffer":                            "bytes",
+	"bytes.Compare":                           "bytes",
+	"bytes.Contains":                          "bytes",
+	"bytes.Count":                             "bytes",
+	"bytes.Equal":                             "bytes",
+	"bytes.EqualFold":                         "bytes",
+	"bytes.ErrTooLarge":                       "bytes",
+	"bytes.Fields":                            "bytes",
+	"bytes.FieldsFunc":                        "bytes",
+	"bytes.HasPrefix":                         "bytes",
+	"bytes.HasSuffix":                         "bytes",
+	"bytes.Index":                             "bytes",
+	"bytes.IndexAny":                          "bytes",
+	"bytes.IndexByte":                         "bytes",
+	"bytes.IndexFunc":                         "bytes",
+	"bytes.IndexRune":                         "bytes",
+	"bytes.Join":                              "bytes",
+	"bytes.LastIndex":                         "bytes",
+	"bytes.LastIndexAny":                      "bytes",
+	"bytes.LastIndexFunc":                     "bytes",
+	"bytes.Map":                               "bytes",
+	"bytes.MinRead":                           "bytes",
+	"bytes.NewBuffer":                         "bytes",
+	"bytes.NewBufferString":                   "bytes",
+	"bytes.NewReader":                         "bytes",
+	"bytes.Reader":                            "bytes",
+	"bytes.Repeat":                            "bytes",
+	"bytes.Replace":                           "bytes",
+	"bytes.Runes":                             "bytes",
+	"bytes.Split":                             "bytes",
+	"bytes.SplitAfter":                        "bytes",
+	"bytes.SplitAfterN":                       "bytes",
+	"bytes.SplitN":                            "bytes",
+	"bytes.Title":                             "bytes",
+	"bytes.ToLower":                           "bytes",
+	"bytes.ToLowerSpecial":                    "bytes",
+	"bytes.ToTitle":                           "bytes",
+	"bytes.ToTitleSpecial":                    "bytes",
+	"bytes.ToUpper":                           "bytes",
+	"bytes.ToUpperSpecial":                    "bytes",
+	"bytes.Trim":                              "bytes",
+	"bytes.TrimFunc":                          "bytes",
+	"bytes.TrimLeft":                          "bytes",
+	"bytes.TrimLeftFunc":                      "bytes",
+	"bytes.TrimPrefix":                        "bytes",
+	"bytes.TrimRight":                         "bytes",
+	"bytes.TrimRightFunc":                     "bytes",
+	"bytes.TrimSpace":                         "bytes",
+	"bytes.TrimSuffix":                        "bytes",
+	"bzip2.NewReader":                         "compress/bzip2",
+	"bzip2.StructuralError":                   "compress/bzip2",
+	"cgi.Handler":                             "net/http/cgi",
+	"cgi.Request":                             "net/http/cgi",
+	"cgi.RequestFromMap":                      "net/http/cgi",
+	"cgi.Serve":                               "net/http/cgi",
+	"cipher.AEAD":                             "crypto/cipher",
+	"cipher.Block":                            "crypto/cipher",
+	"cipher.BlockMode":                        "crypto/cipher",
+	"cipher.NewCBCDecrypter":                  "crypto/cipher",
+	"cipher.NewCBCEncrypter":                  "crypto/cipher",
+	"cipher.NewCFBDecrypter":                  "crypto/cipher",
+	"cipher.NewCFBEncrypter":                  "crypto/cipher",
+	"cipher.NewCTR":                           "crypto/cipher",
+	"cipher.NewGCM":                           "crypto/cipher",
+	"cipher.NewOFB":                           "crypto/cipher",
+	"cipher.Stream":                           "crypto/cipher",
+	"cipher.StreamReader":                     "crypto/cipher",
+	"cipher.StreamWriter":                     "crypto/cipher",
+	"cmplx.Abs":                               "math/cmplx",
+	"cmplx.Acos":                              "math/cmplx",
+	"cmplx.Acosh":                             "math/cmplx",
+	"cmplx.Asin":                              "math/cmplx",
+	"cmplx.Asinh":                             "math/cmplx",
+	"cmplx.Atan":                              "math/cmplx",
+	"cmplx.Atanh":                             "math/cmplx",
+	"cmplx.Conj":                              "math/cmplx",
+	"cmplx.Cos":                               "math/cmplx",
+	"cmplx.Cosh":                              "math/cmplx",
+	"cmplx.Cot":                               "math/cmplx",
+	"cmplx.Exp":                               "math/cmplx",
+	"cmplx.Inf":                               "math/cmplx",
+	"cmplx.IsInf":                             "math/cmplx",
+	"cmplx.IsNaN":                             "math/cmplx",
+	"cmplx.Log":                               "math/cmplx",
+	"cmplx.Log10":                             "math/cmplx",
+	"cmplx.NaN":                               "math/cmplx",
+	"cmplx.Phase":                             "math/cmplx",
+	"cmplx.Polar":                             "math/cmplx",
+	"cmplx.Pow":                               "math/cmplx",
+	"cmplx.Rect":                              "math/cmplx",
+	"cmplx.Sin":                               "math/cmplx",
+	"cmplx.Sinh":                              "math/cmplx",
+	"cmplx.Sqrt":                              "math/cmplx",
+	"cmplx.Tan":                               "math/cmplx",
+	"cmplx.Tanh":                              "math/cmplx",
+	"color.Alpha":                             "image/color",
+	"color.Alpha16":                           "image/color",
+	"color.Alpha16Model":                      "image/color",
+	"color.AlphaModel":                        "image/color",
+	"color.Black":                             "image/color",
+	"color.Color":                             "image/color",
+	"color.Gray":                              "image/color",
+	"color.Gray16":                            "image/color",
+	"color.Gray16Model":                       "image/color",
+	"color.GrayModel":                         "image/color",
+	"color.Model":                             "image/color",
+	"color.ModelFunc":                         "image/color",
+	"color.NRGBA":                             "image/color",
+	"color.NRGBA64":                           "image/color",
+	"color.NRGBA64Model":                      "image/color",
+	"color.NRGBAModel":                        "image/color",
+	"color.Opaque":                            "image/color",
+	"color.Palette":                           "image/color",
+	"color.RGBA":                              "image/color",
+	"color.RGBA64":                            "image/color",
+	"color.RGBA64Model":                       "image/color",
+	"color.RGBAModel":                         "image/color",
+	"color.RGBToYCbCr":                        "image/color",
+	"color.Transparent":                       "image/color",
+	"color.White":                             "image/color",
+	"color.YCbCr":                             "image/color",
+	"color.YCbCrModel":                        "image/color",
+	"color.YCbCrToRGB":                        "image/color",
+	"cookiejar.Jar":                           "net/http/cookiejar",
+	"cookiejar.New":                           "net/http/cookiejar",
+	"cookiejar.Options":                       "net/http/cookiejar",
+	"cookiejar.PublicSuffixList":              "net/http/cookiejar",
+	"crc32.Castagnoli":                        "hash/crc32",
+	"crc32.Checksum":                          "hash/crc32",
+	"crc32.ChecksumIEEE":                      "hash/crc32",
+	"crc32.IEEE":                              "hash/crc32",
+	"crc32.IEEETable":                         "hash/crc32",
+	"crc32.Koopman":                           "hash/crc32",
+	"crc32.MakeTable":                         "hash/crc32",
+	"crc32.New":                               "hash/crc32",
+	"crc32.NewIEEE":                           "hash/crc32",
+	"crc32.Size":                              "hash/crc32",
+	"crc32.Table":                             "hash/crc32",
+	"crc32.Update":                            "hash/crc32",
+	"crc64.Checksum":                          "hash/crc64",
+	"crc64.ECMA":                              "hash/crc64",
+	"crc64.ISO":                               "hash/crc64",
+	"crc64.MakeTable":                         "hash/crc64",
+	"crc64.New":                               "hash/crc64",
+	"crc64.Size":                              "hash/crc64",
+	"crc64.Table":                             "hash/crc64",
+	"crc64.Update":                            "hash/crc64",
+	"crypto.Hash":                             "crypto",
+	"crypto.MD4":                              "crypto",
+	"crypto.MD5":                              "crypto",
+	"crypto.MD5SHA1":                          "crypto",
+	"crypto.PrivateKey":                       "crypto",
+	"crypto.PublicKey":                        "crypto",
+	"crypto.RIPEMD160":                        "crypto",
+	"crypto.RegisterHash":                     "crypto",
+	"crypto.SHA1":                             "crypto",
+	"crypto.SHA224":                           "crypto",
+	"crypto.SHA256":                           "crypto",
+	"crypto.SHA384":                           "crypto",
+	"crypto.SHA512":                           "crypto",
+	"csv.ErrBareQuote":                        "encoding/csv",
+	"csv.ErrFieldCount":                       "encoding/csv",
+	"csv.ErrQuote":                            "encoding/csv",
+	"csv.ErrTrailingComma":                    "encoding/csv",
+	"csv.NewReader":                           "encoding/csv",
+	"csv.NewWriter":                           "encoding/csv",
+	"csv.ParseError":                          "encoding/csv",
+	"csv.Reader":                              "encoding/csv",
+	"csv.Writer":                              "encoding/csv",
+	"debug.FreeOSMemory":                      "runtime/debug",
+	"debug.GCStats":                           "runtime/debug",
+	"debug.PrintStack":                        "runtime/debug",
+	"debug.ReadGCStats":                       "runtime/debug",
+	"debug.SetGCPercent":                      "runtime/debug",
+	"debug.SetMaxStack":                       "runtime/debug",
+	"debug.SetMaxThreads":                     "runtime/debug",
+	"debug.Stack":                             "runtime/debug",
+	"des.BlockSize":                           "crypto/des",
+	"des.KeySizeError":                        "crypto/des",
+	"des.NewCipher":                           "crypto/des",
+	"des.NewTripleDESCipher":                  "crypto/des",
+	"doc.AllDecls":                            "go/doc",
+	"doc.AllMethods":                          "go/doc",
+	"doc.Example":                             "go/doc",
+	"doc.Examples":                            "go/doc",
+	"doc.Filter":                              "go/doc",
+	"doc.Func":                                "go/doc",
+	"doc.IllegalPrefixes":                     "go/doc",
+	"doc.Mode":                                "go/doc",
+	"doc.New":                                 "go/doc",
+	"doc.Note":                                "go/doc",
+	"doc.Package":                             "go/doc",
+	"doc.Synopsis":                            "go/doc",
+	"doc.ToHTML":                              "go/doc",
+	"doc.ToText":                              "go/doc",
+	"doc.Type":                                "go/doc",
+	"doc.Value":                               "go/doc",
+	"draw.Draw":                               "image/draw",
+	"draw.DrawMask":                           "image/draw",
+	"draw.Drawer":                             "image/draw",
+	"draw.FloydSteinberg":                     "image/draw",
+	"draw.Image":                              "image/draw",
+	"draw.Op":                                 "image/draw",
+	"draw.Over":                               "image/draw",
+	"draw.Quantizer":                          "image/draw",
+	"draw.Src":                                "image/draw",
+	"driver.Bool":                             "database/sql/driver",
+	"driver.ColumnConverter":                  "database/sql/driver",
+	"driver.Conn":                             "database/sql/driver",
+	"driver.DefaultParameterConverter":        "database/sql/driver",
+	"driver.Driver":                           "database/sql/driver",
+	"driver.ErrBadConn":                       "database/sql/driver",
+	"driver.ErrSkip":                          "database/sql/driver",
+	"driver.Execer":                           "database/sql/driver",
+	"driver.Int32":                            "database/sql/driver",
+	"driver.IsScanValue":                      "database/sql/driver",
+	"driver.IsValue":                          "database/sql/driver",
+	"driver.NotNull":                          "database/sql/driver",
+	"driver.Null":                             "database/sql/driver",
+	"driver.Queryer":                          "database/sql/driver",
+	"driver.Result":                           "database/sql/driver",
+	"driver.ResultNoRows":                     "database/sql/driver",
+	"driver.Rows":                             "database/sql/driver",
+	"driver.RowsAffected":                     "database/sql/driver",
+	"driver.Stmt":                             "database/sql/driver",
+	"driver.String":                           "database/sql/driver",
+	"driver.Tx":                               "database/sql/driver",
+	"driver.Value":                            "database/sql/driver",
+	"driver.ValueConverter":                   "database/sql/driver",
+	"driver.Valuer":                           "database/sql/driver",
+	"dsa.ErrInvalidPublicKey":                 "crypto/dsa",
+	"dsa.GenerateKey":                         "crypto/dsa",
+	"dsa.GenerateParameters":                  "crypto/dsa",
+	"dsa.L1024N160":                           "crypto/dsa",
+	"dsa.L2048N224":                           "crypto/dsa",
+	"dsa.L2048N256":                           "crypto/dsa",
+	"dsa.L3072N256":                           "crypto/dsa",
+	"dsa.ParameterSizes":                      "crypto/dsa",
+	"dsa.Parameters":                          "crypto/dsa",
+	"dsa.PrivateKey":                          "crypto/dsa",
+	"dsa.PublicKey":                           "crypto/dsa",
+	"dsa.Sign":                                "crypto/dsa",
+	"dsa.Verify":                              "crypto/dsa",
+	"dwarf.AddrType":                          "debug/dwarf",
+	"dwarf.ArrayType":                         "debug/dwarf",
+	"dwarf.Attr":                              "debug/dwarf",
+	"dwarf.AttrAbstractOrigin":                "debug/dwarf",
+	"dwarf.AttrAccessibility":                 "debug/dwarf",
+	"dwarf.AttrAddrClass":                     "debug/dwarf",
+	"dwarf.AttrAllocated":                     "debug/dwarf",
+	"dwarf.AttrArtificial":                    "debug/dwarf",
+	"dwarf.AttrAssociated":                    "debug/dwarf",
+	"dwarf.AttrBaseTypes":                     "debug/dwarf",
+	"dwarf.AttrBitOffset":                     "debug/dwarf",
+	"dwarf.AttrBitSize":                       "debug/dwarf",
+	"dwarf.AttrByteSize":                      "debug/dwarf",
+	"dwarf.AttrCallColumn":                    "debug/dwarf",
+	"dwarf.AttrCallFile":                      "debug/dwarf",
+	"dwarf.AttrCallLine":                      "debug/dwarf",
+	"dwarf.AttrCalling":                       "debug/dwarf",
+	"dwarf.AttrCommonRef":                     "debug/dwarf",
+	"dwarf.AttrCompDir":                       "debug/dwarf",
+	"dwarf.AttrConstValue":                    "debug/dwarf",
+	"dwarf.AttrContainingType":                "debug/dwarf",
+	"dwarf.AttrCount":                         "debug/dwarf",
+	"dwarf.AttrDataLocation":                  "debug/dwarf",
+	"dwarf.AttrDataMemberLoc":                 "debug/dwarf",
+	"dwarf.AttrDeclColumn":                    "debug/dwarf",
+	"dwarf.AttrDeclFile":                      "debug/dwarf",
+	"dwarf.AttrDeclLine":                      "debug/dwarf",
+	"dwarf.AttrDeclaration":                   "debug/dwarf",
+	"dwarf.AttrDefaultValue":                  "debug/dwarf",
+	"dwarf.AttrDescription":                   "debug/dwarf",
+	"dwarf.AttrDiscr":                         "debug/dwarf",
+	"dwarf.AttrDiscrList":                     "debug/dwarf",
+	"dwarf.AttrDiscrValue":                    "debug/dwarf",
+	"dwarf.AttrEncoding":                      "debug/dwarf",
+	"dwarf.AttrEntrypc":                       "debug/dwarf",
+	"dwarf.AttrExtension":                     "debug/dwarf",
+	"dwarf.AttrExternal":                      "debug/dwarf",
+	"dwarf.AttrFrameBase":                     "debug/dwarf",
+	"dwarf.AttrFriend":                        "debug/dwarf",
+	"dwarf.AttrHighpc":                        "debug/dwarf",
+	"dwarf.AttrIdentifierCase":                "debug/dwarf",
+	"dwarf.AttrImport":                        "debug/dwarf",
+	"dwarf.AttrInline":                        "debug/dwarf",
+	"dwarf.AttrIsOptional":                    "debug/dwarf",
+	"dwarf.AttrLanguage":                      "debug/dwarf",
+	"dwarf.AttrLocation":                      "debug/dwarf",
+	"dwarf.AttrLowerBound":                    "debug/dwarf",
+	"dwarf.AttrLowpc":                         "debug/dwarf",
+	"dwarf.AttrMacroInfo":                     "debug/dwarf",
+	"dwarf.AttrName":                          "debug/dwarf",
+	"dwarf.AttrNamelistItem":                  "debug/dwarf",
+	"dwarf.AttrOrdering":                      "debug/dwarf",
+	"dwarf.AttrPriority":                      "debug/dwarf",
+	"dwarf.AttrProducer":                      "debug/dwarf",
+	"dwarf.AttrPrototyped":                    "debug/dwarf",
+	"dwarf.AttrRanges":                        "debug/dwarf",
+	"dwarf.AttrReturnAddr":                    "debug/dwarf",
+	"dwarf.AttrSegment":                       "debug/dwarf",
+	"dwarf.AttrSibling":                       "debug/dwarf",
+	"dwarf.AttrSpecification":                 "debug/dwarf",
+	"dwarf.AttrStartScope":                    "debug/dwarf",
+	"dwarf.AttrStaticLink":                    "debug/dwarf",
+	"dwarf.AttrStmtList":                      "debug/dwarf",
+	"dwarf.AttrStride":                        "debug/dwarf",
+	"dwarf.AttrStrideSize":                    "debug/dwarf",
+	"dwarf.AttrStringLength":                  "debug/dwarf",
+	"dwarf.AttrTrampoline":                    "debug/dwarf",
+	"dwarf.AttrType":                          "debug/dwarf",
+	"dwarf.AttrUpperBound":                    "debug/dwarf",
+	"dwarf.AttrUseLocation":                   "debug/dwarf",
+	"dwarf.AttrUseUTF8":                       "debug/dwarf",
+	"dwarf.AttrVarParam":                      "debug/dwarf",
+	"dwarf.AttrVirtuality":                    "debug/dwarf",
+	"dwarf.AttrVisibility":                    "debug/dwarf",
+	"dwarf.AttrVtableElemLoc":                 "debug/dwarf",
+	"dwarf.BasicType":                         "debug/dwarf",
+	"dwarf.BoolType":                          "debug/dwarf",
+	"dwarf.CharType":                          "debug/dwarf",
+	"dwarf.CommonType":                        "debug/dwarf",
+	"dwarf.ComplexType":                       "debug/dwarf",
+	"dwarf.Data":                              "debug/dwarf",
+	"dwarf.DecodeError":                       "debug/dwarf",
+	"dwarf.DotDotDotType":                     "debug/dwarf",
+	"dwarf.Entry":                             "debug/dwarf",
+	"dwarf.EnumType":                          "debug/dwarf",
+	"dwarf.EnumValue":                         "debug/dwarf",
+	"dwarf.Field":                             "debug/dwarf",
+	"dwarf.FloatType":                         "debug/dwarf",
+	"dwarf.FuncType":                          "debug/dwarf",
+	"dwarf.IntType":                           "debug/dwarf",
+	"dwarf.New":                               "debug/dwarf",
+	"dwarf.Offset":                            "debug/dwarf",
+	"dwarf.PtrType":                           "debug/dwarf",
+	"dwarf.QualType":                          "debug/dwarf",
+	"dwarf.Reader":                            "debug/dwarf",
+	"dwarf.StructField":                       "debug/dwarf",
+	"dwarf.StructType":                        "debug/dwarf",
+	"dwarf.Tag":                               "debug/dwarf",
+	"dwarf.TagAccessDeclaration":              "debug/dwarf",
+	"dwarf.TagArrayType":                      "debug/dwarf",
+	"dwarf.TagBaseType":                       "debug/dwarf",
+	"dwarf.TagCatchDwarfBlock":                "debug/dwarf",
+	"dwarf.TagClassType":                      "debug/dwarf",
+	"dwarf.TagCommonDwarfBlock":               "debug/dwarf",
+	"dwarf.TagCommonInclusion":                "debug/dwarf",
+	"dwarf.TagCompileUnit":                    "debug/dwarf",
+	"dwarf.TagConstType":                      "debug/dwarf",
+	"dwarf.TagConstant":                       "debug/dwarf",
+	"dwarf.TagDwarfProcedure":                 "debug/dwarf",
+	"dwarf.TagEntryPoint":                     "debug/dwarf",
+	"dwarf.TagEnumerationType":                "debug/dwarf",
+	"dwarf.TagEnumerator":                     "debug/dwarf",
+	"dwarf.TagFileType":                       "debug/dwarf",
+	"dwarf.TagFormalParameter":                "debug/dwarf",
+	"dwarf.TagFriend":                         "debug/dwarf",
+	"dwarf.TagImportedDeclaration":            "debug/dwarf",
+	"dwarf.TagImportedModule":                 "debug/dwarf",
+	"dwarf.TagImportedUnit":                   "debug/dwarf",
+	"dwarf.TagInheritance":                    "debug/dwarf",
+	"dwarf.TagInlinedSubroutine":              "debug/dwarf",
+	"dwarf.TagInterfaceType":                  "debug/dwarf",
+	"dwarf.TagLabel":                          "debug/dwarf",
+	"dwarf.TagLexDwarfBlock":                  "debug/dwarf",
+	"dwarf.TagMember":                         "debug/dwarf",
+	"dwarf.TagModule":                         "debug/dwarf",
+	"dwarf.TagMutableType":                    "debug/dwarf",
+	"dwarf.TagNamelist":                       "debug/dwarf",
+	"dwarf.TagNamelistItem":                   "debug/dwarf",
+	"dwarf.TagNamespace":                      "debug/dwarf",
+	"dwarf.TagPackedType":                     "debug/dwarf",
+	"dwarf.TagPartialUnit":                    "debug/dwarf",
+	"dwarf.TagPointerType":                    "debug/dwarf",
+	"dwarf.TagPtrToMemberType":                "debug/dwarf",
+	"dwarf.TagReferenceType":                  "debug/dwarf",
+	"dwarf.TagRestrictType":                   "debug/dwarf",
+	"dwarf.TagSetType":                        "debug/dwarf",
+	"dwarf.TagStringType":                     "debug/dwarf",
+	"dwarf.TagStructType":                     "debug/dwarf",
+	"dwarf.TagSubprogram":                     "debug/dwarf",
+	"dwarf.TagSubrangeType":                   "debug/dwarf",
+	"dwarf.TagSubroutineType":                 "debug/dwarf",
+	"dwarf.TagTemplateTypeParameter":          "debug/dwarf",
+	"dwarf.TagTemplateValueParameter":         "debug/dwarf",
+	"dwarf.TagThrownType":                     "debug/dwarf",
+	"dwarf.TagTryDwarfBlock":                  "debug/dwarf",
+	"dwarf.TagTypedef":                        "debug/dwarf",
+	"dwarf.TagUnionType":                      "debug/dwarf",
+	"dwarf.TagUnspecifiedParameters":          "debug/dwarf",
+	"dwarf.TagUnspecifiedType":                "debug/dwarf",
+	"dwarf.TagVariable":                       "debug/dwarf",
+	"dwarf.TagVariant":                        "debug/dwarf",
+	"dwarf.TagVariantPart":                    "debug/dwarf",
+	"dwarf.TagVolatileType":                   "debug/dwarf",
+	"dwarf.TagWithStmt":                       "debug/dwarf",
+	"dwarf.Type":                              "debug/dwarf",
+	"dwarf.TypedefType":                       "debug/dwarf",
+	"dwarf.UcharType":                         "debug/dwarf",
+	"dwarf.UintType":                          "debug/dwarf",
+	"dwarf.VoidType":                          "debug/dwarf",
+	"ecdsa.GenerateKey":                       "crypto/ecdsa",
+	"ecdsa.PrivateKey":                        "crypto/ecdsa",
+	"ecdsa.PublicKey":                         "crypto/ecdsa",
+	"ecdsa.Sign":                              "crypto/ecdsa",
+	"ecdsa.Verify":                            "crypto/ecdsa",
+	"elf.ARM_MAGIC_TRAMP_NUMBER":              "debug/elf",
+	"elf.Class":                               "debug/elf",
+	"elf.DF_BIND_NOW":                         "debug/elf",
+	"elf.DF_ORIGIN":                           "debug/elf",
+	"elf.DF_STATIC_TLS":                       "debug/elf",
+	"elf.DF_SYMBOLIC":                         "debug/elf",
+	"elf.DF_TEXTREL":                          "debug/elf",
+	"elf.DT_BIND_NOW":                         "debug/elf",
+	"elf.DT_DEBUG":                            "debug/elf",
+	"elf.DT_ENCODING":                         "debug/elf",
+	"elf.DT_FINI":                             "debug/elf",
+	"elf.DT_FINI_ARRAY":                       "debug/elf",
+	"elf.DT_FINI_ARRAYSZ":                     "debug/elf",
+	"elf.DT_FLAGS":                            "debug/elf",
+	"elf.DT_HASH":                             "debug/elf",
+	"elf.DT_HIOS":                             "debug/elf",
+	"elf.DT_HIPROC":                           "debug/elf",
+	"elf.DT_INIT":                             "debug/elf",
+	"elf.DT_INIT_ARRAY":                       "debug/elf",
+	"elf.DT_INIT_ARRAYSZ":                     "debug/elf",
+	"elf.DT_JMPREL":                           "debug/elf",
+	"elf.DT_LOOS":                             "debug/elf",
+	"elf.DT_LOPROC":                           "debug/elf",
+	"elf.DT_NEEDED":                           "debug/elf",
+	"elf.DT_NULL":                             "debug/elf",
+	"elf.DT_PLTGOT":                           "debug/elf",
+	"elf.DT_PLTREL":                           "debug/elf",
+	"elf.DT_PLTRELSZ":                         "debug/elf",
+	"elf.DT_PREINIT_ARRAY":                    "debug/elf",
+	"elf.DT_PREINIT_ARRAYSZ":                  "debug/elf",
+	"elf.DT_REL":                              "debug/elf",
+	"elf.DT_RELA":                             "debug/elf",
+	"elf.DT_RELAENT":                          "debug/elf",
+	"elf.DT_RELASZ":                           "debug/elf",
+	"elf.DT_RELENT":                           "debug/elf",
+	"elf.DT_RELSZ":                            "debug/elf",
+	"elf.DT_RPATH":                            "debug/elf",
+	"elf.DT_RUNPATH":                          "debug/elf",
+	"elf.DT_SONAME":                           "debug/elf",
+	"elf.DT_STRSZ":                            "debug/elf",
+	"elf.DT_STRTAB":                           "debug/elf",
+	"elf.DT_SYMBOLIC":                         "debug/elf",
+	"elf.DT_SYMENT":                           "debug/elf",
+	"elf.DT_SYMTAB":                           "debug/elf",
+	"elf.DT_TEXTREL":                          "debug/elf",
+	"elf.DT_VERNEED":                          "debug/elf",
+	"elf.DT_VERNEEDNUM":                       "debug/elf",
+	"elf.DT_VERSYM":                           "debug/elf",
+	"elf.Data":                                "debug/elf",
+	"elf.Dyn32":                               "debug/elf",
+	"elf.Dyn64":                               "debug/elf",
+	"elf.DynFlag":                             "debug/elf",
+	"elf.DynTag":                              "debug/elf",
+	"elf.EI_ABIVERSION":                       "debug/elf",
+	"elf.EI_CLASS":                            "debug/elf",
+	"elf.EI_DATA":                             "debug/elf",
+	"elf.EI_NIDENT":                           "debug/elf",
+	"elf.EI_OSABI":                            "debug/elf",
+	"elf.EI_PAD":                              "debug/elf",
+	"elf.EI_VERSION":                          "debug/elf",
+	"elf.ELFCLASS32":                          "debug/elf",
+	"elf.ELFCLASS64":                          "debug/elf",
+	"elf.ELFCLASSNONE":                        "debug/elf",
+	"elf.ELFDATA2LSB":                         "debug/elf",
+	"elf.ELFDATA2MSB":                         "debug/elf",
+	"elf.ELFDATANONE":                         "debug/elf",
+	"elf.ELFMAG":                              "debug/elf",
+	"elf.ELFOSABI_86OPEN":                     "debug/elf",
+	"elf.ELFOSABI_AIX":                        "debug/elf",
+	"elf.ELFOSABI_ARM":                        "debug/elf",
+	"elf.ELFOSABI_FREEBSD":                    "debug/elf",
+	"elf.ELFOSABI_HPUX":                       "debug/elf",
+	"elf.ELFOSABI_HURD":                       "debug/elf",
+	"elf.ELFOSABI_IRIX":                       "debug/elf",
+	"elf.ELFOSABI_LINUX":                      "debug/elf",
+	"elf.ELFOSABI_MODESTO":                    "debug/elf",
+	"elf.ELFOSABI_NETBSD":                     "debug/elf",
+	"elf.ELFOSABI_NONE":                       "debug/elf",
+	"elf.ELFOSABI_NSK":                        "debug/elf",
+	"elf.ELFOSABI_OPENBSD":                    "debug/elf",
+	"elf.ELFOSABI_OPENVMS":                    "debug/elf",
+	"elf.ELFOSABI_SOLARIS":                    "debug/elf",
+	"elf.ELFOSABI_STANDALONE":                 "debug/elf",
+	"elf.ELFOSABI_TRU64":                      "debug/elf",
+	"elf.EM_386":                              "debug/elf",
+	"elf.EM_486":                              "debug/elf",
+	"elf.EM_68HC12":                           "debug/elf",
+	"elf.EM_68K":                              "debug/elf",
+	"elf.EM_860":                              "debug/elf",
+	"elf.EM_88K":                              "debug/elf",
+	"elf.EM_960":                              "debug/elf",
+	"elf.EM_ALPHA":                            "debug/elf",
+	"elf.EM_ALPHA_STD":                        "debug/elf",
+	"elf.EM_ARC":                              "debug/elf",
+	"elf.EM_ARM":                              "debug/elf",
+	"elf.EM_COLDFIRE":                         "debug/elf",
+	"elf.EM_FR20":                             "debug/elf",
+	"elf.EM_H8S":                              "debug/elf",
+	"elf.EM_H8_300":                           "debug/elf",
+	"elf.EM_H8_300H":                          "debug/elf",
+	"elf.EM_H8_500":                           "debug/elf",
+	"elf.EM_IA_64":                            "debug/elf",
+	"elf.EM_M32":                              "debug/elf",
+	"elf.EM_ME16":                             "debug/elf",
+	"elf.EM_MIPS":                             "debug/elf",
+	"elf.EM_MIPS_RS3_LE":                      "debug/elf",
+	"elf.EM_MIPS_RS4_BE":                      "debug/elf",
+	"elf.EM_MIPS_X":                           "debug/elf",
+	"elf.EM_MMA":                              "debug/elf",
+	"elf.EM_NCPU":                             "debug/elf",
+	"elf.EM_NDR1":                             "debug/elf",
+	"elf.EM_NONE":                             "debug/elf",
+	"elf.EM_PARISC":                           "debug/elf",
+	"elf.EM_PCP":                              "debug/elf",
+	"elf.EM_PPC":                              "debug/elf",
+	"elf.EM_PPC64":                            "debug/elf",
+	"elf.EM_RCE":                              "debug/elf",
+	"elf.EM_RH32":                             "debug/elf",
+	"elf.EM_S370":                             "debug/elf",
+	"elf.EM_S390":                             "debug/elf",
+	"elf.EM_SH":                               "debug/elf",
+	"elf.EM_SPARC":                            "debug/elf",
+	"elf.EM_SPARC32PLUS":                      "debug/elf",
+	"elf.EM_SPARCV9":                          "debug/elf",
+	"elf.EM_ST100":                            "debug/elf",
+	"elf.EM_STARCORE":                         "debug/elf",
+	"elf.EM_TINYJ":                            "debug/elf",
+	"elf.EM_TRICORE":                          "debug/elf",
+	"elf.EM_V800":                             "debug/elf",
+	"elf.EM_VPP500":                           "debug/elf",
+	"elf.EM_X86_64":                           "debug/elf",
+	"elf.ET_CORE":                             "debug/elf",
+	"elf.ET_DYN":                              "debug/elf",
+	"elf.ET_EXEC":                             "debug/elf",
+	"elf.ET_HIOS":                             "debug/elf",
+	"elf.ET_HIPROC":                           "debug/elf",
+	"elf.ET_LOOS":                             "debug/elf",
+	"elf.ET_LOPROC":                           "debug/elf",
+	"elf.ET_NONE":                             "debug/elf",
+	"elf.ET_REL":                              "debug/elf",
+	"elf.EV_CURRENT":                          "debug/elf",
+	"elf.EV_NONE":                             "debug/elf",
+	"elf.File":                                "debug/elf",
+	"elf.FileHeader":                          "debug/elf",
+	"elf.FormatError":                         "debug/elf",
+	"elf.Header32":                            "debug/elf",
+	"elf.Header64":                            "debug/elf",
+	"elf.ImportedSymbol":                      "debug/elf",
+	"elf.Machine":                             "debug/elf",
+	"elf.NT_FPREGSET":                         "debug/elf",
+	"elf.NT_PRPSINFO":                         "debug/elf",
+	"elf.NT_PRSTATUS":                         "debug/elf",
+	"elf.NType":                               "debug/elf",
+	"elf.NewFile":                             "debug/elf",
+	"elf.OSABI":                               "debug/elf",
+	"elf.Open":                                "debug/elf",
+	"elf.PF_MASKOS":                           "debug/elf",
+	"elf.PF_MASKPROC":                         "debug/elf",
+	"elf.PF_R":                                "debug/elf",
+	"elf.PF_W":                                "debug/elf",
+	"elf.PF_X":                                "debug/elf",
+	"elf.PT_DYNAMIC":                          "debug/elf",
+	"elf.PT_HIOS":                             "debug/elf",
+	"elf.PT_HIPROC":                           "debug/elf",
+	"elf.PT_INTERP":                           "debug/elf",
+	"elf.PT_LOAD":                             "debug/elf",
+	"elf.PT_LOOS":                             "debug/elf",
+	"elf.PT_LOPROC":                           "debug/elf",
+	"elf.PT_NOTE":                             "debug/elf",
+	"elf.PT_NULL":                             "debug/elf",
+	"elf.PT_PHDR":                             "debug/elf",
+	"elf.PT_SHLIB":                            "debug/elf",
+	"elf.PT_TLS":                              "debug/elf",
+	"elf.Prog":                                "debug/elf",
+	"elf.Prog32":                              "debug/elf",
+	"elf.Prog64":                              "debug/elf",
+	"elf.ProgFlag":                            "debug/elf",
+	"elf.ProgHeader":                          "debug/elf",
+	"elf.ProgType":                            "debug/elf",
+	"elf.R_386":                               "debug/elf",
+	"elf.R_386_32":                            "debug/elf",
+	"elf.R_386_COPY":                          "debug/elf",
+	"elf.R_386_GLOB_DAT":                      "debug/elf",
+	"elf.R_386_GOT32":                         "debug/elf",
+	"elf.R_386_GOTOFF":                        "debug/elf",
+	"elf.R_386_GOTPC":                         "debug/elf",
+	"elf.R_386_JMP_SLOT":                      "debug/elf",
+	"elf.R_386_NONE":                          "debug/elf",
+	"elf.R_386_PC32":                          "debug/elf",
+	"elf.R_386_PLT32":                         "debug/elf",
+	"elf.R_386_RELATIVE":                      "debug/elf",
+	"elf.R_386_TLS_DTPMOD32":                  "debug/elf",
+	"elf.R_386_TLS_DTPOFF32":                  "debug/elf",
+	"elf.R_386_TLS_GD":                        "debug/elf",
+	"elf.R_386_TLS_GD_32":                     "debug/elf",
+	"elf.R_386_TLS_GD_CALL":                   "debug/elf",
+	"elf.R_386_TLS_GD_POP":                    "debug/elf",
+	"elf.R_386_TLS_GD_PUSH":                   "debug/elf",
+	"elf.R_386_TLS_GOTIE":                     "debug/elf",
+	"elf.R_386_TLS_IE":                        "debug/elf",
+	"elf.R_386_TLS_IE_32":                     "debug/elf",
+	"elf.R_386_TLS_LDM":                       "debug/elf",
+	"elf.R_386_TLS_LDM_32":                    "debug/elf",
+	"elf.R_386_TLS_LDM_CALL":                  "debug/elf",
+	"elf.R_386_TLS_LDM_POP":                   "debug/elf",
+	"elf.R_386_TLS_LDM_PUSH":                  "debug/elf",
+	"elf.R_386_TLS_LDO_32":                    "debug/elf",
+	"elf.R_386_TLS_LE":                        "debug/elf",
+	"elf.R_386_TLS_LE_32":                     "debug/elf",
+	"elf.R_386_TLS_TPOFF":                     "debug/elf",
+	"elf.R_386_TLS_TPOFF32":                   "debug/elf",
+	"elf.R_ALPHA":                             "debug/elf",
+	"elf.R_ALPHA_BRADDR":                      "debug/elf",
+	"elf.R_ALPHA_COPY":                        "debug/elf",
+	"elf.R_ALPHA_GLOB_DAT":                    "debug/elf",
+	"elf.R_ALPHA_GPDISP":                      "debug/elf",
+	"elf.R_ALPHA_GPREL32":                     "debug/elf",
+	"elf.R_ALPHA_GPRELHIGH":                   "debug/elf",
+	"elf.R_ALPHA_GPRELLOW":                    "debug/elf",
+	"elf.R_ALPHA_GPVALUE":                     "debug/elf",
+	"elf.R_ALPHA_HINT":                        "debug/elf",
+	"elf.R_ALPHA_IMMED_BR_HI32":               "debug/elf",
+	"elf.R_ALPHA_IMMED_GP_16":                 "debug/elf",
+	"elf.R_ALPHA_IMMED_GP_HI32":               "debug/elf",
+	"elf.R_ALPHA_IMMED_LO32":                  "debug/elf",
+	"elf.R_ALPHA_IMMED_SCN_HI32":              "debug/elf",
+	"elf.R_ALPHA_JMP_SLOT":                    "debug/elf",
+	"elf.R_ALPHA_LITERAL":                     "debug/elf",
+	"elf.R_ALPHA_LITUSE":                      "debug/elf",
+	"elf.R_ALPHA_NONE":                        "debug/elf",
+	"elf.R_ALPHA_OP_PRSHIFT":                  "debug/elf",
+	"elf.R_ALPHA_OP_PSUB":                     "debug/elf",
+	"elf.R_ALPHA_OP_PUSH":                     "debug/elf",
+	"elf.R_ALPHA_OP_STORE":                    "debug/elf",
+	"elf.R_ALPHA_REFLONG":                     "debug/elf",
+	"elf.R_ALPHA_REFQUAD":                     "debug/elf",
+	"elf.R_ALPHA_RELATIVE":                    "debug/elf",
+	"elf.R_ALPHA_SREL16":                      "debug/elf",
+	"elf.R_ALPHA_SREL32":                      "debug/elf",
+	"elf.R_ALPHA_SREL64":                      "debug/elf",
+	"elf.R_ARM":                               "debug/elf",
+	"elf.R_ARM_ABS12":                         "debug/elf",
+	"elf.R_ARM_ABS16":                         "debug/elf",
+	"elf.R_ARM_ABS32":                         "debug/elf",
+	"elf.R_ARM_ABS8":                          "debug/elf",
+	"elf.R_ARM_AMP_VCALL9":                    "debug/elf",
+	"elf.R_ARM_COPY":                          "debug/elf",
+	"elf.R_ARM_GLOB_DAT":                      "debug/elf",
+	"elf.R_ARM_GNU_VTENTRY":                   "debug/elf",
+	"elf.R_ARM_GNU_VTINHERIT":                 "debug/elf",
+	"elf.R_ARM_GOT32":                         "debug/elf",
+	"elf.R_ARM_GOTOFF":                        "debug/elf",
+	"elf.R_ARM_GOTPC":                         "debug/elf",
+	"elf.R_ARM_JUMP_SLOT":                     "debug/elf",
+	"elf.R_ARM_NONE":                          "debug/elf",
+	"elf.R_ARM_PC13":                          "debug/elf",
+	"elf.R_ARM_PC24":                          "debug/elf",
+	"elf.R_ARM_PLT32":                         "debug/elf",
+	"elf.R_ARM_RABS32":                        "debug/elf",
+	"elf.R_ARM_RBASE":                         "debug/elf",
+	"elf.R_ARM_REL32":                         "debug/elf",
+	"elf.R_ARM_RELATIVE":                      "debug/elf",
+	"elf.R_ARM_RPC24":                         "debug/elf",
+	"elf.R_ARM_RREL32":                        "debug/elf",
+	"elf.R_ARM_RSBREL32":                      "debug/elf",
+	"elf.R_ARM_SBREL32":                       "debug/elf",
+	"elf.R_ARM_SWI24":                         "debug/elf",
+	"elf.R_ARM_THM_ABS5":                      "debug/elf",
+	"elf.R_ARM_THM_PC22":                      "debug/elf",
+	"elf.R_ARM_THM_PC8":                       "debug/elf",
+	"elf.R_ARM_THM_RPC22":                     "debug/elf",
+	"elf.R_ARM_THM_SWI8":                      "debug/elf",
+	"elf.R_ARM_THM_XPC22":                     "debug/elf",
+	"elf.R_ARM_XPC25":                         "debug/elf",
+	"elf.R_INFO":                              "debug/elf",
+	"elf.R_INFO32":                            "debug/elf",
+	"elf.R_PPC":                               "debug/elf",
+	"elf.R_PPC_ADDR14":                        "debug/elf",
+	"elf.R_PPC_ADDR14_BRNTAKEN":               "debug/elf",
+	"elf.R_PPC_ADDR14_BRTAKEN":                "debug/elf",
+	"elf.R_PPC_ADDR16":                        "debug/elf",
+	"elf.R_PPC_ADDR16_HA":                     "debug/elf",
+	"elf.R_PPC_ADDR16_HI":                     "debug/elf",
+	"elf.R_PPC_ADDR16_LO":                     "debug/elf",
+	"elf.R_PPC_ADDR24":                        "debug/elf",
+	"elf.R_PPC_ADDR32":                        "debug/elf",
+	"elf.R_PPC_COPY":                          "debug/elf",
+	"elf.R_PPC_DTPMOD32":                      "debug/elf",
+	"elf.R_PPC_DTPREL16":                      "debug/elf",
+	"elf.R_PPC_DTPREL16_HA":                   "debug/elf",
+	"elf.R_PPC_DTPREL16_HI":                   "debug/elf",
+	"elf.R_PPC_DTPREL16_LO":                   "debug/elf",
+	"elf.R_PPC_DTPREL32":                      "debug/elf",
+	"elf.R_PPC_EMB_BIT_FLD":                   "debug/elf",
+	"elf.R_PPC_EMB_MRKREF":                    "debug/elf",
+	"elf.R_PPC_EMB_NADDR16":                   "debug/elf",
+	"elf.R_PPC_EMB_NADDR16_HA":                "debug/elf",
+	"elf.R_PPC_EMB_NADDR16_HI":                "debug/elf",
+	"elf.R_PPC_EMB_NADDR16_LO":                "debug/elf",
+	"elf.R_PPC_EMB_NADDR32":                   "debug/elf",
+	"elf.R_PPC_EMB_RELSDA":                    "debug/elf",
+	"elf.R_PPC_EMB_RELSEC16":                  "debug/elf",
+	"elf.R_PPC_EMB_RELST_HA":                  "debug/elf",
+	"elf.R_PPC_EMB_RELST_HI":                  "debug/elf",
+	"elf.R_PPC_EMB_RELST_LO":                  "debug/elf",
+	"elf.R_PPC_EMB_SDA21":                     "debug/elf",
+	"elf.R_PPC_EMB_SDA2I16":                   "debug/elf",
+	"elf.R_PPC_EMB_SDA2REL":                   "debug/elf",
+	"elf.R_PPC_EMB_SDAI16":                    "debug/elf",
+	"elf.R_PPC_GLOB_DAT":                      "debug/elf",
+	"elf.R_PPC_GOT16":                         "debug/elf",
+	"elf.R_PPC_GOT16_HA":                      "debug/elf",
+	"elf.R_PPC_GOT16_HI":                      "debug/elf",
+	"elf.R_PPC_GOT16_LO":                      "debug/elf",
+	"elf.R_PPC_GOT_TLSGD16":                   "debug/elf",
+	"elf.R_PPC_GOT_TLSGD16_HA":                "debug/elf",
+	"elf.R_PPC_GOT_TLSGD16_HI":                "debug/elf",
+	"elf.R_PPC_GOT_TLSGD16_LO":                "debug/elf",
+	"elf.R_PPC_GOT_TLSLD16":                   "debug/elf",
+	"elf.R_PPC_GOT_TLSLD16_HA":                "debug/elf",
+	"elf.R_PPC_GOT_TLSLD16_HI":                "debug/elf",
+	"elf.R_PPC_GOT_TLSLD16_LO":                "debug/elf",
+	"elf.R_PPC_GOT_TPREL16":                   "debug/elf",
+	"elf.R_PPC_GOT_TPREL16_HA":                "debug/elf",
+	"elf.R_PPC_GOT_TPREL16_HI":                "debug/elf",
+	"elf.R_PPC_GOT_TPREL16_LO":                "debug/elf",
+	"elf.R_PPC_JMP_SLOT":                      "debug/elf",
+	"elf.R_PPC_LOCAL24PC":                     "debug/elf",
+	"elf.R_PPC_NONE":                          "debug/elf",
+	"elf.R_PPC_PLT16_HA":                      "debug/elf",
+	"elf.R_PPC_PLT16_HI":                      "debug/elf",
+	"elf.R_PPC_PLT16_LO":                      "debug/elf",
+	"elf.R_PPC_PLT32":                         "debug/elf",
+	"elf.R_PPC_PLTREL24":                      "debug/elf",
+	"elf.R_PPC_PLTREL32":                      "debug/elf",
+	"elf.R_PPC_REL14":                         "debug/elf",
+	"elf.R_PPC_REL14_BRNTAKEN":                "debug/elf",
+	"elf.R_PPC_REL14_BRTAKEN":                 "debug/elf",
+	"elf.R_PPC_REL24":                         "debug/elf",
+	"elf.R_PPC_REL32":                         "debug/elf",
+	"elf.R_PPC_RELATIVE":                      "debug/elf",
+	"elf.R_PPC_SDAREL16":                      "debug/elf",
+	"elf.R_PPC_SECTOFF":                       "debug/elf",
+	"elf.R_PPC_SECTOFF_HA":                    "debug/elf",
+	"elf.R_PPC_SECTOFF_HI":                    "debug/elf",
+	"elf.R_PPC_SECTOFF_LO":                    "debug/elf",
+	"elf.R_PPC_TLS":                           "debug/elf",
+	"elf.R_PPC_TPREL16":                       "debug/elf",
+	"elf.R_PPC_TPREL16_HA":                    "debug/elf",
+	"elf.R_PPC_TPREL16_HI":                    "debug/elf",
+	"elf.R_PPC_TPREL16_LO":                    "debug/elf",
+	"elf.R_PPC_TPREL32":                       "debug/elf",
+	"elf.R_PPC_UADDR16":                       "debug/elf",
+	"elf.R_PPC_UADDR32":                       "debug/elf",
+	"elf.R_SPARC":                             "debug/elf",
+	"elf.R_SPARC_10":                          "debug/elf",
+	"elf.R_SPARC_11":                          "debug/elf",
+	"elf.R_SPARC_13":                          "debug/elf",
+	"elf.R_SPARC_16":                          "debug/elf",
+	"elf.R_SPARC_22":                          "debug/elf",
+	"elf.R_SPARC_32":                          "debug/elf",
+	"elf.R_SPARC_5":                           "debug/elf",
+	"elf.R_SPARC_6":                           "debug/elf",
+	"elf.R_SPARC_64":                          "debug/elf",
+	"elf.R_SPARC_7":                           "debug/elf",
+	"elf.R_SPARC_8":                           "debug/elf",
+	"elf.R_SPARC_COPY":                        "debug/elf",
+	"elf.R_SPARC_DISP16":                      "debug/elf",
+	"elf.R_SPARC_DISP32":                      "debug/elf",
+	"elf.R_SPARC_DISP64":                      "debug/elf",
+	"elf.R_SPARC_DISP8":                       "debug/elf",
+	"elf.R_SPARC_GLOB_DAT":                    "debug/elf",
+	"elf.R_SPARC_GLOB_JMP":                    "debug/elf",
+	"elf.R_SPARC_GOT10":                       "debug/elf",
+	"elf.R_SPARC_GOT13":                       "debug/elf",
+	"elf.R_SPARC_GOT22":                       "debug/elf",
+	"elf.R_SPARC_H44":                         "debug/elf",
+	"elf.R_SPARC_HH22":                        "debug/elf",
+	"elf.R_SPARC_HI22":                        "debug/elf",
+	"elf.R_SPARC_HIPLT22":                     "debug/elf",
+	"elf.R_SPARC_HIX22":                       "debug/elf",
+	"elf.R_SPARC_HM10":                        "debug/elf",
+	"elf.R_SPARC_JMP_SLOT":                    "debug/elf",
+	"elf.R_SPARC_L44":                         "debug/elf",
+	"elf.R_SPARC_LM22":                        "debug/elf",
+	"elf.R_SPARC_LO10":                        "debug/elf",
+	"elf.R_SPARC_LOPLT10":                     "debug/elf",
+	"elf.R_SPARC_LOX10":                       "debug/elf",
+	"elf.R_SPARC_M44":                         "debug/elf",
+	"elf.R_SPARC_NONE":                        "debug/elf",
+	"elf.R_SPARC_OLO10":                       "debug/elf",
+	"elf.R_SPARC_PC10":                        "debug/elf",
+	"elf.R_SPARC_PC22":                        "debug/elf",
+	"elf.R_SPARC_PCPLT10":                     "debug/elf",
+	"elf.R_SPARC_PCPLT22":                     "debug/elf",
+	"elf.R_SPARC_PCPLT32":                     "debug/elf",
+	"elf.R_SPARC_PC_HH22":                     "debug/elf",
+	"elf.R_SPARC_PC_HM10":                     "debug/elf",
+	"elf.R_SPARC_PC_LM22":                     "debug/elf",
+	"elf.R_SPARC_PLT32":                       "debug/elf",
+	"elf.R_SPARC_PLT64":                       "debug/elf",
+	"elf.R_SPARC_REGISTER":                    "debug/elf",
+	"elf.R_SPARC_RELATIVE":                    "debug/elf",
+	"elf.R_SPARC_UA16":                        "debug/elf",
+	"elf.R_SPARC_UA32":                        "debug/elf",
+	"elf.R_SPARC_UA64":                        "debug/elf",
+	"elf.R_SPARC_WDISP16":                     "debug/elf",
+	"elf.R_SPARC_WDISP19":                     "debug/elf",
+	"elf.R_SPARC_WDISP22":                     "debug/elf",
+	"elf.R_SPARC_WDISP30":                     "debug/elf",
+	"elf.R_SPARC_WPLT30":                      "debug/elf",
+	"elf.R_SYM32":                             "debug/elf",
+	"elf.R_SYM64":                             "debug/elf",
+	"elf.R_TYPE32":                            "debug/elf",
+	"elf.R_TYPE64":                            "debug/elf",
+	"elf.R_X86_64":                            "debug/elf",
+	"elf.R_X86_64_16":                         "debug/elf",
+	"elf.R_X86_64_32":                         "debug/elf",
+	"elf.R_X86_64_32S":                        "debug/elf",
+	"elf.R_X86_64_64":                         "debug/elf",
+	"elf.R_X86_64_8":                          "debug/elf",
+	"elf.R_X86_64_COPY":                       "debug/elf",
+	"elf.R_X86_64_DTPMOD64":                   "debug/elf",
+	"elf.R_X86_64_DTPOFF32":                   "debug/elf",
+	"elf.R_X86_64_DTPOFF64":                   "debug/elf",
+	"elf.R_X86_64_GLOB_DAT":                   "debug/elf",
+	"elf.R_X86_64_GOT32":                      "debug/elf",
+	"elf.R_X86_64_GOTPCREL":                   "debug/elf",
+	"elf.R_X86_64_GOTTPOFF":                   "debug/elf",
+	"elf.R_X86_64_JMP_SLOT":                   "debug/elf",
+	"elf.R_X86_64_NONE":                       "debug/elf",
+	"elf.R_X86_64_PC16":                       "debug/elf",
+	"elf.R_X86_64_PC32":                       "debug/elf",
+	"elf.R_X86_64_PC8":                        "debug/elf",
+	"elf.R_X86_64_PLT32":                      "debug/elf",
+	"elf.R_X86_64_RELATIVE":                   "debug/elf",
+	"elf.R_X86_64_TLSGD":                      "debug/elf",
+	"elf.R_X86_64_TLSLD":                      "debug/elf",
+	"elf.R_X86_64_TPOFF32":                    "debug/elf",
+	"elf.R_X86_64_TPOFF64":                    "debug/elf",
+	"elf.Rel32":                               "debug/elf",
+	"elf.Rel64":                               "debug/elf",
+	"elf.Rela32":                              "debug/elf",
+	"elf.Rela64":                              "debug/elf",
+	"elf.SHF_ALLOC":                           "debug/elf",
+	"elf.SHF_EXECINSTR":                       "debug/elf",
+	"elf.SHF_GROUP":                           "debug/elf",
+	"elf.SHF_INFO_LINK":                       "debug/elf",
+	"elf.SHF_LINK_ORDER":                      "debug/elf",
+	"elf.SHF_MASKOS":                          "debug/elf",
+	"elf.SHF_MASKPROC":                        "debug/elf",
+	"elf.SHF_MERGE":                           "debug/elf",
+	"elf.SHF_OS_NONCONFORMING":                "debug/elf",
+	"elf.SHF_STRINGS":                         "debug/elf",
+	"elf.SHF_TLS":                             "debug/elf",
+	"elf.SHF_WRITE":                           "debug/elf",
+	"elf.SHN_ABS":                             "debug/elf",
+	"elf.SHN_COMMON":                          "debug/elf",
+	"elf.SHN_HIOS":                            "debug/elf",
+	"elf.SHN_HIPROC":                          "debug/elf",
+	"elf.SHN_HIRESERVE":                       "debug/elf",
+	"elf.SHN_LOOS":                            "debug/elf",
+	"elf.SHN_LOPROC":                          "debug/elf",
+	"elf.SHN_LORESERVE":                       "debug/elf",
+	"elf.SHN_UNDEF":                           "debug/elf",
+	"elf.SHN_XINDEX":                          "debug/elf",
+	"elf.SHT_DYNAMIC":                         "debug/elf",
+	"elf.SHT_DYNSYM":                          "debug/elf",
+	"elf.SHT_FINI_ARRAY":                      "debug/elf",
+	"elf.SHT_GNU_ATTRIBUTES":                  "debug/elf",
+	"elf.SHT_GNU_HASH":                        "debug/elf",
+	"elf.SHT_GNU_LIBLIST":                     "debug/elf",
+	"elf.SHT_GNU_VERDEF":                      "debug/elf",
+	"elf.SHT_GNU_VERNEED":                     "debug/elf",
+	"elf.SHT_GNU_VERSYM":                      "debug/elf",
+	"elf.SHT_GROUP":                           "debug/elf",
+	"elf.SHT_HASH":                            "debug/elf",
+	"elf.SHT_HIOS":                            "debug/elf",
+	"elf.SHT_HIPROC":                          "debug/elf",
+	"elf.SHT_HIUSER":                          "debug/elf",
+	"elf.SHT_INIT_ARRAY":                      "debug/elf",
+	"elf.SHT_LOOS":                            "debug/elf",
+	"elf.SHT_LOPROC":                          "debug/elf",
+	"elf.SHT_LOUSER":                          "debug/elf",
+	"elf.SHT_NOBITS":                          "debug/elf",
+	"elf.SHT_NOTE":                            "debug/elf",
+	"elf.SHT_NULL":                            "debug/elf",
+	"elf.SHT_PREINIT_ARRAY":                   "debug/elf",
+	"elf.SHT_PROGBITS":                        "debug/elf",
+	"elf.SHT_REL":                             "debug/elf",
+	"elf.SHT_RELA":                            "debug/elf",
+	"elf.SHT_SHLIB":                           "debug/elf",
+	"elf.SHT_STRTAB":                          "debug/elf",
+	"elf.SHT_SYMTAB":                          "debug/elf",
+	"elf.SHT_SYMTAB_SHNDX":                    "debug/elf",
+	"elf.STB_GLOBAL":                          "debug/elf",
+	"elf.STB_HIOS":                            "debug/elf",
+	"elf.STB_HIPROC":                          "debug/elf",
+	"elf.STB_LOCAL":                           "debug/elf",
+	"elf.STB_LOOS":                            "debug/elf",
+	"elf.STB_LOPROC":                          "debug/elf",
+	"elf.STB_WEAK":                            "debug/elf",
+	"elf.STT_COMMON":                          "debug/elf",
+	"elf.STT_FILE":                            "debug/elf",
+	"elf.STT_FUNC":                            "debug/elf",
+	"elf.STT_HIOS":                            "debug/elf",
+	"elf.STT_HIPROC":                          "debug/elf",
+	"elf.STT_LOOS":                            "debug/elf",
+	"elf.STT_LOPROC":                          "debug/elf",
+	"elf.STT_NOTYPE":                          "debug/elf",
+	"elf.STT_OBJECT":                          "debug/elf",
+	"elf.STT_SECTION":                         "debug/elf",
+	"elf.STT_TLS":                             "debug/elf",
+	"elf.STV_DEFAULT":                         "debug/elf",
+	"elf.STV_HIDDEN":                          "debug/elf",
+	"elf.STV_INTERNAL":                        "debug/elf",
+	"elf.STV_PROTECTED":                       "debug/elf",
+	"elf.ST_BIND":                             "debug/elf",
+	"elf.ST_INFO":                             "debug/elf",
+	"elf.ST_TYPE":                             "debug/elf",
+	"elf.ST_VISIBILITY":                       "debug/elf",
+	"elf.Section":                             "debug/elf",
+	"elf.Section32":                           "debug/elf",
+	"elf.Section64":                           "debug/elf",
+	"elf.SectionFlag":                         "debug/elf",
+	"elf.SectionHeader":                       "debug/elf",
+	"elf.SectionIndex":                        "debug/elf",
+	"elf.SectionType":                         "debug/elf",
+	"elf.Sym32":                               "debug/elf",
+	"elf.Sym32Size":                           "debug/elf",
+	"elf.Sym64":                               "debug/elf",
+	"elf.Sym64Size":                           "debug/elf",
+	"elf.SymBind":                             "debug/elf",
+	"elf.SymType":                             "debug/elf",
+	"elf.SymVis":                              "debug/elf",
+	"elf.Symbol":                              "debug/elf",
+	"elf.Type":                                "debug/elf",
+	"elf.Version":                             "debug/elf",
+	"elliptic.Curve":                          "crypto/elliptic",
+	"elliptic.CurveParams":                    "crypto/elliptic",
+	"elliptic.GenerateKey":                    "crypto/elliptic",
+	"elliptic.Marshal":                        "crypto/elliptic",
+	"elliptic.P224":                           "crypto/elliptic",
+	"elliptic.P256":                           "crypto/elliptic",
+	"elliptic.P384":                           "crypto/elliptic",
+	"elliptic.P521":                           "crypto/elliptic",
+	"elliptic.Unmarshal":                      "crypto/elliptic",
+	"encoding.BinaryMarshaler":                "encoding",
+	"encoding.BinaryUnmarshaler":              "encoding",
+	"encoding.TextMarshaler":                  "encoding",
+	"encoding.TextUnmarshaler":                "encoding",
+	"errors.New":                              "errors",
+	"exec.Cmd":                                "os/exec",
+	"exec.Command":                            "os/exec",
+	"exec.ErrNotFound":                        "os/exec",
+	"exec.Error":                              "os/exec",
+	"exec.ExitError":                          "os/exec",
+	"exec.LookPath":                           "os/exec",
+	"expvar.Do":                               "expvar",
+	"expvar.Float":                            "expvar",
+	"expvar.Func":                             "expvar",
+	"expvar.Get":                              "expvar",
+	"expvar.Int":                              "expvar",
+	"expvar.KeyValue":                         "expvar",
+	"expvar.Map":                              "expvar",
+	"expvar.NewFloat":                         "expvar",
+	"expvar.NewInt":                           "expvar",
+	"expvar.NewMap":                           "expvar",
+	"expvar.NewString":                        "expvar",
+	"expvar.Publish":                          "expvar",
+	"expvar.String":                           "expvar",
+	"expvar.Var":                              "expvar",
+	"fcgi.Serve":                              "net/http/fcgi",
+	"filepath.Abs":                            "path/filepath",
+	"filepath.Base":                           "path/filepath",
+	"filepath.Clean":                          "path/filepath",
+	"filepath.Dir":                            "path/filepath",
+	"filepath.ErrBadPattern":                  "path/filepath",
+	"filepath.EvalSymlinks":                   "path/filepath",
+	"filepath.Ext":                            "path/filepath",
+	"filepath.FromSlash":                      "path/filepath",
+	"filepath.Glob":                           "path/filepath",
+	"filepath.HasPrefix":                      "path/filepath",
+	"filepath.IsAbs":                          "path/filepath",
+	"filepath.Join":                           "path/filepath",
+	"filepath.ListSeparator":                  "path/filepath",
+	"filepath.Match":                          "path/filepath",
+	"filepath.Rel":                            "path/filepath",
+	"filepath.Separator":                      "path/filepath",
+	"filepath.SkipDir":                        "path/filepath",
+	"filepath.Split":                          "path/filepath",
+	"filepath.SplitList":                      "path/filepath",
+	"filepath.ToSlash":                        "path/filepath",
+	"filepath.VolumeName":                     "path/filepath",
+	"filepath.Walk":                           "path/filepath",
+	"filepath.WalkFunc":                       "path/filepath",
+	"flag.Arg":                                "flag",
+	"flag.Args":                               "flag",
+	"flag.Bool":                               "flag",
+	"flag.BoolVar":                            "flag",
+	"flag.CommandLine":                        "flag",
+	"flag.ContinueOnError":                    "flag",
+	"flag.Duration":                           "flag",
+	"flag.DurationVar":                        "flag",
+	"flag.ErrHelp":                            "flag",
+	"flag.ErrorHandling":                      "flag",
+	"flag.ExitOnError":                        "flag",
+	"flag.Flag":                               "flag",
+	"flag.FlagSet":                            "flag",
+	"flag.Float64":                            "flag",
+	"flag.Float64Var":                         "flag",
+	"flag.Getter":                             "flag",
+	"flag.Int":                                "flag",
+	"flag.Int64":                              "flag",
+	"flag.Int64Var":                           "flag",
+	"flag.IntVar":                             "flag",
+	"flag.Lookup":                             "flag",
+	"flag.NArg":                               "flag",
+	"flag.NFlag":                              "flag",
+	"flag.NewFlagSet":                         "flag",
+	"flag.PanicOnError":                       "flag",
+	"flag.Parse":                              "flag",
+	"flag.Parsed":                             "flag",
+	"flag.PrintDefaults":                      "flag",
+	"flag.Set":                                "flag",
+	"flag.String":                             "flag",
+	"flag.StringVar":                          "flag",
+	"flag.Uint":                               "flag",
+	"flag.Uint64":                             "flag",
+	"flag.Uint64Var":                          "flag",
+	"flag.UintVar":                            "flag",
+	"flag.Usage":                              "flag",
+	"flag.Value":                              "flag",
+	"flag.Var":                                "flag",
+	"flag.Visit":                              "flag",
+	"flag.VisitAll":                           "flag",
+	"flate.BestCompression":                   "compress/flate",
+	"flate.BestSpeed":                         "compress/flate",
+	"flate.CorruptInputError":                 "compress/flate",
+	"flate.DefaultCompression":                "compress/flate",
+	"flate.InternalError":                     "compress/flate",
+	"flate.NewReader":                         "compress/flate",
+	"flate.NewReaderDict":                     "compress/flate",
+	"flate.NewWriter":                         "compress/flate",
+	"flate.NewWriterDict":                     "compress/flate",
+	"flate.NoCompression":                     "compress/flate",
+	"flate.ReadError":                         "compress/flate",
+	"flate.Reader":                            "compress/flate",
+	"flate.WriteError":                        "compress/flate",
+	"flate.Writer":                            "compress/flate",
+	"fmt.Errorf":                              "fmt",
+	"fmt.Formatter":                           "fmt",
+	"fmt.Fprint":                              "fmt",
+	"fmt.Fprintf":                             "fmt",
+	"fmt.Fprintln":                            "fmt",
+	"fmt.Fscan":                               "fmt",
+	"fmt.Fscanf":                              "fmt",
+	"fmt.Fscanln":                             "fmt",
+	"fmt.GoStringer":                          "fmt",
+	"fmt.Print":                               "fmt",
+	"fmt.Printf":                              "fmt",
+	"fmt.Println":                             "fmt",
+	"fmt.Scan":                                "fmt",
+	"fmt.ScanState":                           "fmt",
+	"fmt.Scanf":                               "fmt",
+	"fmt.Scanln":                              "fmt",
+	"fmt.Scanner":                             "fmt",
+	"fmt.Sprint":                              "fmt",
+	"fmt.Sprintf":                             "fmt",
+	"fmt.Sprintln":                            "fmt",
+	"fmt.Sscan":                               "fmt",
+	"fmt.Sscanf":                              "fmt",
+	"fmt.Sscanln":                             "fmt",
+	"fmt.State":                               "fmt",
+	"fmt.Stringer":                            "fmt",
+	"fnv.New32":                               "hash/fnv",
+	"fnv.New32a":                              "hash/fnv",
+	"fnv.New64":                               "hash/fnv",
+	"fnv.New64a":                              "hash/fnv",
+	"format.Node":                             "go/format",
+	"format.Source":                           "go/format",
+	"gif.Decode":                              "image/gif",
+	"gif.DecodeAll":                           "image/gif",
+	"gif.DecodeConfig":                        "image/gif",
+	"gif.Encode":                              "image/gif",
+	"gif.EncodeAll":                           "image/gif",
+	"gif.GIF":                                 "image/gif",
+	"gif.Options":                             "image/gif",
+	"gob.CommonType":                          "encoding/gob",
+	"gob.Decoder":                             "encoding/gob",
+	"gob.Encoder":                             "encoding/gob",
+	"gob.GobDecoder":                          "encoding/gob",
+	"gob.GobEncoder":                          "encoding/gob",
+	"gob.NewDecoder":                          "encoding/gob",
+	"gob.NewEncoder":                          "encoding/gob",
+	"gob.Register":                            "encoding/gob",
+	"gob.RegisterName":                        "encoding/gob",
+	"gosym.DecodingError":                     "debug/gosym",
+	"gosym.Func":                              "debug/gosym",
+	"gosym.LineTable":                         "debug/gosym",
+	"gosym.NewLineTable":                      "debug/gosym",
+	"gosym.NewTable":                          "debug/gosym",
+	"gosym.Obj":                               "debug/gosym",
+	"gosym.Sym":                               "debug/gosym",
+	"gosym.Table":                             "debug/gosym",
+	"gosym.UnknownFileError":                  "debug/gosym",
+	"gosym.UnknownLineError":                  "debug/gosym",
+	"gzip.BestCompression":                    "compress/gzip",
+	"gzip.BestSpeed":                          "compress/gzip",
+	"gzip.DefaultCompression":                 "compress/gzip",
+	"gzip.ErrChecksum":                        "compress/gzip",
+	"gzip.ErrHeader":                          "compress/gzip",
+	"gzip.Header":                             "compress/gzip",
+	"gzip.NewReader":                          "compress/gzip",
+	"gzip.NewWriter":                          "compress/gzip",
+	"gzip.NewWriterLevel":                     "compress/gzip",
+	"gzip.NoCompression":                      "compress/gzip",
+	"gzip.Reader":                             "compress/gzip",
+	"gzip.Writer":                             "compress/gzip",
+	"hash.Hash":                               "hash",
+	"hash.Hash32":                             "hash",
+	"hash.Hash64":                             "hash",
+	"heap.Fix":                                "container/heap",
+	"heap.Init":                               "container/heap",
+	"heap.Interface":                          "container/heap",
+	"heap.Pop":                                "container/heap",
+	"heap.Push":                               "container/heap",
+	"heap.Remove":                             "container/heap",
+	"hex.Decode":                              "encoding/hex",
+	"hex.DecodeString":                        "encoding/hex",
+	"hex.DecodedLen":                          "encoding/hex",
+	"hex.Dump":                                "encoding/hex",
+	"hex.Dumper":                              "encoding/hex",
+	"hex.Encode":                              "encoding/hex",
+	"hex.EncodeToString":                      "encoding/hex",
+	"hex.EncodedLen":                          "encoding/hex",
+	"hex.ErrLength":                           "encoding/hex",
+	"hex.InvalidByteError":                    "encoding/hex",
+	"hmac.Equal":                              "crypto/hmac",
+	"hmac.New":                                "crypto/hmac",
+	"html.EscapeString":                       "html",
+	"html.UnescapeString":                     "html",
+	"http.CanonicalHeaderKey":                 "net/http",
+	"http.Client":                             "net/http",
+	"http.CloseNotifier":                      "net/http",
+	"http.Cookie":                             "net/http",
+	"http.CookieJar":                          "net/http",
+	"http.DefaultClient":                      "net/http",
+	"http.DefaultMaxHeaderBytes":              "net/http",
+	"http.DefaultMaxIdleConnsPerHost":         "net/http",
+	"http.DefaultServeMux":                    "net/http",
+	"http.DefaultTransport":                   "net/http",
+	"http.DetectContentType":                  "net/http",
+	"http.Dir":                                "net/http",
+	"http.ErrBodyNotAllowed":                  "net/http",
+	"http.ErrBodyReadAfterClose":              "net/http",
+	"http.ErrContentLength":                   "net/http",
+	"http.ErrHandlerTimeout":                  "net/http",
+	"http.ErrHeaderTooLong":                   "net/http",
+	"http.ErrHijacked":                        "net/http",
+	"http.ErrLineTooLong":                     "net/http",
+	"http.ErrMissingBoundary":                 "net/http",
+	"http.ErrMissingContentLength":            "net/http",
+	"http.ErrMissingFile":                     "net/http",
+	"http.ErrNoCookie":                        "net/http",
+	"http.ErrNoLocation":                      "net/http",
+	"http.ErrNotMultipart":                    "net/http",
+	"http.ErrNotSupported":                    "net/http",
+	"http.ErrShortBody":                       "net/http",
+	"http.ErrUnexpectedTrailer":               "net/http",
+	"http.ErrWriteAfterFlush":                 "net/http",
+	"http.Error":                              "net/http",
+	"http.File":                               "net/http",
+	"http.FileServer":                         "net/http",
+	"http.FileSystem":                         "net/http",
+	"http.Flusher":                            "net/http",
+	"http.Get":                                "net/http",
+	"http.Handle":                             "net/http",
+	"http.HandleFunc":                         "net/http",
+	"http.Handler":                            "net/http",
+	"http.HandlerFunc":                        "net/http",
+	"http.Head":                               "net/http",
+	"http.Header":                             "net/http",
+	"http.Hijacker":                           "net/http",
+	"http.ListenAndServe":                     "net/http",
+	"http.ListenAndServeTLS":                  "net/http",
+	"http.MaxBytesReader":                     "net/http",
+	"http.NewFileTransport":                   "net/http",
+	"http.NewRequest":                         "net/http",
+	"http.NewServeMux":                        "net/http",
+	"http.NotFound":                           "net/http",
+	"http.NotFoundHandler":                    "net/http",
+	"http.ParseHTTPVersion":                   "net/http",
+	"http.ParseTime":                          "net/http",
+	"http.Post":                               "net/http",
+	"http.PostForm":                           "net/http",
+	"http.ProtocolError":                      "net/http",
+	"http.ProxyFromEnvironment":               "net/http",
+	"http.ProxyURL":                           "net/http",
+	"http.ReadRequest":                        "net/http",
+	"http.ReadResponse":                       "net/http",
+	"http.Redirect":                           "net/http",
+	"http.RedirectHandler":                    "net/http",
+	"http.Request":                            "net/http",
+	"http.Response":                           "net/http",
+	"http.ResponseWriter":                     "net/http",
+	"http.RoundTripper":                       "net/http",
+	"http.Serve":                              "net/http",
+	"http.ServeContent":                       "net/http",
+	"http.ServeFile":                          "net/http",
+	"http.ServeMux":                           "net/http",
+	"http.Server":                             "net/http",
+	"http.SetCookie":                          "net/http",
+	"http.StatusAccepted":                     "net/http",
+	"http.StatusBadGateway":                   "net/http",
+	"http.StatusBadRequest":                   "net/http",
+	"http.StatusConflict":                     "net/http",
+	"http.StatusContinue":                     "net/http",
+	"http.StatusCreated":                      "net/http",
+	"http.StatusExpectationFailed":            "net/http",
+	"http.StatusForbidden":                    "net/http",
+	"http.StatusFound":                        "net/http",
+	"http.StatusGatewayTimeout":               "net/http",
+	"http.StatusGone":                         "net/http",
+	"http.StatusHTTPVersionNotSupported":      "net/http",
+	"http.StatusInternalServerError":          "net/http",
+	"http.StatusLengthRequired":               "net/http",
+	"http.StatusMethodNotAllowed":             "net/http",
+	"http.StatusMovedPermanently":             "net/http",
+	"http.StatusMultipleChoices":              "net/http",
+	"http.StatusNoContent":                    "net/http",
+	"http.StatusNonAuthoritativeInfo":         "net/http",
+	"http.StatusNotAcceptable":                "net/http",
+	"http.StatusNotFound":                     "net/http",
+	"http.StatusNotImplemented":               "net/http",
+	"http.StatusNotModified":                  "net/http",
+	"http.StatusOK":                           "net/http",
+	"http.StatusPartialContent":               "net/http",
+	"http.StatusPaymentRequired":              "net/http",
+	"http.StatusPreconditionFailed":           "net/http",
+	"http.StatusProxyAuthRequired":            "net/http",
+	"http.StatusRequestEntityTooLarge":        "net/http",
+	"http.StatusRequestTimeout":               "net/http",
+	"http.StatusRequestURITooLong":            "net/http",
+	"http.StatusRequestedRangeNotSatisfiable": "net/http",
+	"http.StatusResetContent":                 "net/http",
+	"http.StatusSeeOther":                     "net/http",
+	"http.StatusServiceUnavailable":           "net/http",
+	"http.StatusSwitchingProtocols":           "net/http",
+	"http.StatusTeapot":                       "net/http",
+	"http.StatusTemporaryRedirect":            "net/http",
+	"http.StatusText":                         "net/http",
+	"http.StatusUnauthorized":                 "net/http",
+	"http.StatusUnsupportedMediaType":         "net/http",
+	"http.StatusUseProxy":                     "net/http",
+	"http.StripPrefix":                        "net/http",
+	"http.TimeFormat":                         "net/http",
+	"http.TimeoutHandler":                     "net/http",
+	"http.Transport":                          "net/http",
+	"httptest.DefaultRemoteAddr":              "net/http/httptest",
+	"httptest.NewRecorder":                    "net/http/httptest",
+	"httptest.NewServer":                      "net/http/httptest",
+	"httptest.NewTLSServer":                   "net/http/httptest",
+	"httptest.NewUnstartedServer":             "net/http/httptest",
+	"httptest.ResponseRecorder":               "net/http/httptest",
+	"httptest.Server":                         "net/http/httptest",
+	"httputil.ClientConn":                     "net/http/httputil",
+	"httputil.DumpRequest":                    "net/http/httputil",
+	"httputil.DumpRequestOut":                 "net/http/httputil",
+	"httputil.DumpResponse":                   "net/http/httputil",
+	"httputil.ErrClosed":                      "net/http/httputil",
+	"httputil.ErrLineTooLong":                 "net/http/httputil",
+	"httputil.ErrPersistEOF":                  "net/http/httputil",
+	"httputil.ErrPipeline":                    "net/http/httputil",
+	"httputil.NewChunkedReader":               "net/http/httputil",
+	"httputil.NewChunkedWriter":               "net/http/httputil",
+	"httputil.NewClientConn":                  "net/http/httputil",
+	"httputil.NewProxyClientConn":             "net/http/httputil",
+	"httputil.NewServerConn":                  "net/http/httputil",
+	"httputil.NewSingleHostReverseProxy":      "net/http/httputil",
+	"httputil.ReverseProxy":                   "net/http/httputil",
+	"httputil.ServerConn":                     "net/http/httputil",
+	"image.Alpha":                             "image",
+	"image.Alpha16":                           "image",
+	"image.Black":                             "image",
+	"image.Config":                            "image",
+	"image.Decode":                            "image",
+	"image.DecodeConfig":                      "image",
+	"image.ErrFormat":                         "image",
+	"image.Gray":                              "image",
+	"image.Gray16":                            "image",
+	"image.Image":                             "image",
+	"image.NRGBA":                             "image",
+	"image.NRGBA64":                           "image",
+	"image.NewAlpha":                          "image",
+	"image.NewAlpha16":                        "image",
+	"image.NewGray":                           "image",
+	"image.NewGray16":                         "image",
+	"image.NewNRGBA":                          "image",
+	"image.NewNRGBA64":                        "image",
+	"image.NewPaletted":                       "image",
+	"image.NewRGBA":                           "image",
+	"image.NewRGBA64":                         "image",
+	"image.NewUniform":                        "image",
+	"image.NewYCbCr":                          "image",
+	"image.Opaque":                            "image",
+	"image.Paletted":                          "image",
+	"image.PalettedImage":                     "image",
+	"image.Point":                             "image",
+	"image.Pt":                                "image",
+	"image.RGBA":                              "image",
+	"image.RGBA64":                            "image",
+	"image.Rect":                              "image",
+	"image.Rectangle":                         "image",
+	"image.RegisterFormat":                    "image",
+	"image.Transparent":                       "image",
+	"image.Uniform":                           "image",
+	"image.White":                             "image",
+	"image.YCbCr":                             "image",
+	"image.YCbCrSubsampleRatio":               "image",
+	"image.YCbCrSubsampleRatio420":            "image",
+	"image.YCbCrSubsampleRatio422":            "image",
+	"image.YCbCrSubsampleRatio440":            "image",
+	"image.YCbCrSubsampleRatio444":            "image",
+	"image.ZP":                                "image",
+	"image.ZR":                                "image",
+	"io.ByteReader":                           "io",
+	"io.ByteScanner":                          "io",
+	"io.ByteWriter":                           "io",
+	"io.Closer":                               "io",
+	"io.Copy":                                 "io",
+	"io.CopyN":                                "io",
+	"io.EOF":                                  "io",
+	"io.ErrClosedPipe":                        "io",
+	"io.ErrNoProgress":                        "io",
+	"io.ErrShortBuffer":                       "io",
+	"io.ErrShortWrite":                        "io",
+	"io.ErrUnexpectedEOF":                     "io",
+	"io.LimitReader":                          "io",
+	"io.LimitedReader":                        "io",
+	"io.MultiReader":                          "io",
+	"io.MultiWriter":                          "io",
+	"io.NewSectionReader":                     "io",
+	"io.Pipe":                                 "io",
+	"io.PipeReader":                           "io",
+	"io.PipeWriter":                           "io",
+	"io.ReadAtLeast":                          "io",
+	"io.ReadCloser":                           "io",
+	"io.ReadFull":                             "io",
+	"io.ReadSeeker":                           "io",
+	"io.ReadWriteCloser":                      "io",
+	"io.ReadWriteSeeker":                      "io",
+	"io.ReadWriter":                           "io",
+	"io.Reader":                               "io",
+	"io.ReaderAt":                             "io",
+	"io.ReaderFrom":                           "io",
+	"io.RuneReader":                           "io",
+	"io.RuneScanner":                          "io",
+	"io.SectionReader":                        "io",
+	"io.Seeker":                               "io",
+	"io.TeeReader":                            "io",
+	"io.WriteCloser":                          "io",
+	"io.WriteSeeker":                          "io",
+	"io.WriteString":                          "io",
+	"io.Writer":                               "io",
+	"io.WriterAt":                             "io",
+	"io.WriterTo":                             "io",
+	"iotest.DataErrReader":                    "testing/iotest",
+	"iotest.ErrTimeout":                       "testing/iotest",
+	"iotest.HalfReader":                       "testing/iotest",
+	"iotest.NewReadLogger":                    "testing/iotest",
+	"iotest.NewWriteLogger":                   "testing/iotest",
+	"iotest.OneByteReader":                    "testing/iotest",
+	"iotest.TimeoutReader":                    "testing/iotest",
+	"iotest.TruncateWriter":                   "testing/iotest",
+	"ioutil.Discard":                          "io/ioutil",
+	"ioutil.NopCloser":                        "io/ioutil",
+	"ioutil.ReadAll":                          "io/ioutil",
+	"ioutil.ReadDir":                          "io/ioutil",
+	"ioutil.ReadFile":                         "io/ioutil",
+	"ioutil.TempDir":                          "io/ioutil",
+	"ioutil.TempFile":                         "io/ioutil",
+	"ioutil.WriteFile":                        "io/ioutil",
+	"jpeg.Decode":                             "image/jpeg",
+	"jpeg.DecodeConfig":                       "image/jpeg",
+	"jpeg.DefaultQuality":                     "image/jpeg",
+	"jpeg.Encode":                             "image/jpeg",
+	"jpeg.FormatError":                        "image/jpeg",
+	"jpeg.Options":                            "image/jpeg",
+	"jpeg.Reader":                             "image/jpeg",
+	"jpeg.UnsupportedError":                   "image/jpeg",
+	"json.Compact":                            "encoding/json",
+	"json.Decoder":                            "encoding/json",
+	"json.Encoder":                            "encoding/json",
+	"json.HTMLEscape":                         "encoding/json",
+	"json.Indent":                             "encoding/json",
+	"json.InvalidUTF8Error":                   "encoding/json",
+	"json.InvalidUnmarshalError":              "encoding/json",
+	"json.Marshal":                            "encoding/json",
+	"json.MarshalIndent":                      "encoding/json",
+	"json.Marshaler":                          "encoding/json",
+	"json.MarshalerError":                     "encoding/json",
+	"json.NewDecoder":                         "encoding/json",
+	"json.NewEncoder":                         "encoding/json",
+	"json.Number":                             "encoding/json",
+	"json.RawMessage":                         "encoding/json",
+	"json.SyntaxError":                        "encoding/json",
+	"json.Unmarshal":                          "encoding/json",
+	"json.UnmarshalFieldError":                "encoding/json",
+	"json.UnmarshalTypeError":                 "encoding/json",
+	"json.Unmarshaler":                        "encoding/json",
+	"json.UnsupportedTypeError":               "encoding/json",
+	"json.UnsupportedValueError":              "encoding/json",
+	"jsonrpc.Dial":                            "net/rpc/jsonrpc",
+	"jsonrpc.NewClient":                       "net/rpc/jsonrpc",
+	"jsonrpc.NewClientCodec":                  "net/rpc/jsonrpc",
+	"jsonrpc.NewServerCodec":                  "net/rpc/jsonrpc",
+	"jsonrpc.ServeConn":                       "net/rpc/jsonrpc",
+	"list.Element":                            "container/list",
+	"list.List":                               "container/list",
+	"list.New":                                "container/list",
+	"log.Fatal":                               "log",
+	"log.Fatalf":                              "log",
+	"log.Fatalln":                             "log",
+	"log.Flags":                               "log",
+	"log.Ldate":                               "log",
+	"log.Llongfile":                           "log",
+	"log.Lmicroseconds":                       "log",
+	"log.Logger":                              "log",
+	"log.Lshortfile":                          "log",
+	"log.LstdFlags":                           "log",
+	"log.Ltime":                               "log",
+	"log.New":                                 "log",
+	"log.Panic":                               "log",
+	"log.Panicf":                              "log",
+	"log.Panicln":                             "log",
+	"log.Prefix":                              "log",
+	"log.Print":                               "log",
+	"log.Printf":                              "log",
+	"log.Println":                             "log",
+	"log.SetFlags":                            "log",
+	"log.SetOutput":                           "log",
+	"log.SetPrefix":                           "log",
+	"lzw.LSB":                                 "compress/lzw",
+	"lzw.MSB":                                 "compress/lzw",
+	"lzw.NewReader":                           "compress/lzw",
+	"lzw.NewWriter":                           "compress/lzw",
+	"lzw.Order":                               "compress/lzw",
+	"macho.Cpu":                               "debug/macho",
+	"macho.Cpu386":                            "debug/macho",
+	"macho.CpuAmd64":                          "debug/macho",
+	"macho.Dylib":                             "debug/macho",
+	"macho.DylibCmd":                          "debug/macho",
+	"macho.Dysymtab":                          "debug/macho",
+	"macho.DysymtabCmd":                       "debug/macho",
+	"macho.File":                              "debug/macho",
+	"macho.FileHeader":                        "debug/macho",
+	"macho.FormatError":                       "debug/macho",
+	"macho.Load":                              "debug/macho",
+	"macho.LoadBytes":                         "debug/macho",
+	"macho.LoadCmd":                           "debug/macho",
+	"macho.LoadCmdDylib":                      "debug/macho",
+	"macho.LoadCmdDylinker":                   "debug/macho",
+	"macho.LoadCmdDysymtab":                   "debug/macho",
+	"macho.LoadCmdSegment":                    "debug/macho",
+	"macho.LoadCmdSegment64":                  "debug/macho",
+	"macho.LoadCmdSymtab":                     "debug/macho",
+	"macho.LoadCmdThread":                     "debug/macho",
+	"macho.LoadCmdUnixThread":                 "debug/macho",
+	"macho.Magic32":                           "debug/macho",
+	"macho.Magic64":                           "debug/macho",
+	"macho.NewFile":                           "debug/macho",
+	"macho.Nlist32":                           "debug/macho",
+	"macho.Nlist64":                           "debug/macho",
+	"macho.Open":                              "debug/macho",
+	"macho.Regs386":                           "debug/macho",
+	"macho.RegsAMD64":                         "debug/macho",
+	"macho.Section":                           "debug/macho",
+	"macho.Section32":                         "debug/macho",
+	"macho.Section64":                         "debug/macho",
+	"macho.SectionHeader":                     "debug/macho",
+	"macho.Segment":                           "debug/macho",
+	"macho.Segment32":                         "debug/macho",
+	"macho.Segment64":                         "debug/macho",
+	"macho.SegmentHeader":                     "debug/macho",
+	"macho.Symbol":                            "debug/macho",
+	"macho.Symtab":                            "debug/macho",
+	"macho.SymtabCmd":                         "debug/macho",
+	"macho.Thread":                            "debug/macho",
+	"macho.Type":                              "debug/macho",
+	"macho.TypeExec":                          "debug/macho",
+	"macho.TypeObj":                           "debug/macho",
+	"mail.Address":                            "net/mail",
+	"mail.ErrHeaderNotPresent":                "net/mail",
+	"mail.Header":                             "net/mail",
+	"mail.Message":                            "net/mail",
+	"mail.ParseAddress":                       "net/mail",
+	"mail.ParseAddressList":                   "net/mail",
+	"mail.ReadMessage":                        "net/mail",
+	"math.Abs":                                "math",
+	"math.Acos":                               "math",
+	"math.Acosh":                              "math",
+	"math.Asin":                               "math",
+	"math.Asinh":                              "math",
+	"math.Atan":                               "math",
+	"math.Atan2":                              "math",
+	"math.Atanh":                              "math",
+	"math.Cbrt":                               "math",
+	"math.Ceil":                               "math",
+	"math.Copysign":                           "math",
+	"math.Cos":                                "math",
+	"math.Cosh":                               "math",
+	"math.Dim":                                "math",
+	"math.E":                                  "math",
+	"math.Erf":                                "math",
+	"math.Erfc":                               "math",
+	"math.Exp":                                "math",
+	"math.Exp2":                               "math",
+	"math.Expm1":                              "math",
+	"math.Float32bits":                        "math",
+	"math.Float32frombits":                    "math",
+	"math.Float64bits":                        "math",
+	"math.Float64frombits":                    "math",
+	"math.Floor":                              "math",
+	"math.Frexp":                              "math",
+	"math.Gamma":                              "math",
+	"math.Hypot":                              "math",
+	"math.Ilogb":                              "math",
+	"math.Inf":                                "math",
+	"math.IsInf":                              "math",
+	"math.IsNaN":                              "math",
+	"math.J0":                                 "math",
+	"math.J1":                                 "math",
+	"math.Jn":                                 "math",
+	"math.Ldexp":                              "math",
+	"math.Lgamma":                             "math",
+	"math.Ln10":                               "math",
+	"math.Ln2":                                "math",
+	"math.Log":                                "math",
+	"math.Log10":                              "math",
+	"math.Log10E":                             "math",
+	"math.Log1p":                              "math",
+	"math.Log2":                               "math",
+	"math.Log2E":                              "math",
+	"math.Logb":                               "math",
+	"math.Max":                                "math",
+	"math.MaxFloat32":                         "math",
+	"math.MaxFloat64":                         "math",
+	"math.MaxInt16":                           "math",
+	"math.MaxInt32":                           "math",
+	"math.MaxInt64":                           "math",
+	"math.MaxInt8":                            "math",
+	"math.MaxUint16":                          "math",
+	"math.MaxUint32":                          "math",
+	"math.MaxUint64":                          "math",
+	"math.MaxUint8":                           "math",
+	"math.Min":                                "math",
+	"math.MinInt16":                           "math",
+	"math.MinInt32":                           "math",
+	"math.MinInt64":                           "math",
+	"math.MinInt8":                            "math",
+	"math.Mod":                                "math",
+	"math.Modf":                               "math",
+	"math.NaN":                                "math",
+	"math.Nextafter":                          "math",
+	"math.Phi":                                "math",
+	"math.Pi":                                 "math",
+	"math.Pow":                                "math",
+	"math.Pow10":                              "math",
+	"math.Remainder":                          "math",
+	"math.Signbit":                            "math",
+	"math.Sin":                                "math",
+	"math.Sincos":                             "math",
+	"math.Sinh":                               "math",
+	"math.SmallestNonzeroFloat32":             "math",
+	"math.SmallestNonzeroFloat64":             "math",
+	"math.Sqrt":                               "math",
+	"math.Sqrt2":                              "math",
+	"math.SqrtE":                              "math",
+	"math.SqrtPhi":                            "math",
+	"math.SqrtPi":                             "math",
+	"math.Tan":                                "math",
+	"math.Tanh":                               "math",
+	"math.Trunc":                              "math",
+	"math.Y0":                                 "math",
+	"math.Y1":                                 "math",
+	"math.Yn":                                 "math",
+	"md5.BlockSize":                           "crypto/md5",
+	"md5.New":                                 "crypto/md5",
+	"md5.Size":                                "crypto/md5",
+	"md5.Sum":                                 "crypto/md5",
+	"mime.AddExtensionType":                   "mime",
+	"mime.FormatMediaType":                    "mime",
+	"mime.ParseMediaType":                     "mime",
+	"mime.TypeByExtension":                    "mime",
+	"multipart.File":                          "mime/multipart",
+	"multipart.FileHeader":                    "mime/multipart",
+	"multipart.Form":                          "mime/multipart",
+	"multipart.NewReader":                     "mime/multipart",
+	"multipart.NewWriter":                     "mime/multipart",
+	"multipart.Part":                          "mime/multipart",
+	"multipart.Reader":                        "mime/multipart",
+	"multipart.Writer":                        "mime/multipart",
+	"net.Addr":                                "net",
+	"net.AddrError":                           "net",
+	"net.CIDRMask":                            "net",
+	"net.Conn":                                "net",
+	"net.DNSConfigError":                      "net",
+	"net.DNSError":                            "net",
+	"net.Dial":                                "net",
+	"net.DialIP":                              "net",
+	"net.DialTCP":                             "net",
+	"net.DialTimeout":                         "net",
+	"net.DialUDP":                             "net",
+	"net.DialUnix":                            "net",
+	"net.Dialer":                              "net",
+	"net.ErrWriteToConnected":                 "net",
+	"net.Error":                               "net",
+	"net.FileConn":                            "net",
+	"net.FileListener":                        "net",
+	"net.FilePacketConn":                      "net",
+	"net.FlagBroadcast":                       "net",
+	"net.FlagLoopback":                        "net",
+	"net.FlagMulticast":                       "net",
+	"net.FlagPointToPoint":                    "net",
+	"net.FlagUp":                              "net",
+	"net.Flags":                               "net",
+	"net.HardwareAddr":                        "net",
+	"net.IP":                                  "net",
+	"net.IPAddr":                              "net",
+	"net.IPConn":                              "net",
+	"net.IPMask":                              "net",
+	"net.IPNet":                               "net",
+	"net.IPv4":                                "net",
+	"net.IPv4Mask":                            "net",
+	"net.IPv4allrouter":                       "net",
+	"net.IPv4allsys":                          "net",
+	"net.IPv4bcast":                           "net",
+	"net.IPv4len":                             "net",
+	"net.IPv4zero":                            "net",
+	"net.IPv6interfacelocalallnodes":          "net",
+	"net.IPv6len":                             "net",
+	"net.IPv6linklocalallnodes":               "net",
+	"net.IPv6linklocalallrouters":             "net",
+	"net.IPv6loopback":                        "net",
+	"net.IPv6unspecified":                     "net",
+	"net.IPv6zero":                            "net",
+	"net.Interface":                           "net",
+	"net.InterfaceAddrs":                      "net",
+	"net.InterfaceByIndex":                    "net",
+	"net.InterfaceByName":                     "net",
+	"net.Interfaces":                          "net",
+	"net.InvalidAddrError":                    "net",
+	"net.JoinHostPort":                        "net",
+	"net.Listen":                              "net",
+	"net.ListenIP":                            "net",
+	"net.ListenMulticastUDP":                  "net",
+	"net.ListenPacket":                        "net",
+	"net.ListenTCP":                           "net",
+	"net.ListenUDP":                           "net",
+	"net.ListenUnix":                          "net",
+	"net.ListenUnixgram":                      "net",
+	"net.Listener":                            "net",
+	"net.LookupAddr":                          "net",
+	"net.LookupCNAME":                         "net",
+	"net.LookupHost":                          "net",
+	"net.LookupIP":                            "net",
+	"net.LookupMX":                            "net",
+	"net.LookupNS":                            "net",
+	"net.LookupPort":                          "net",
+	"net.LookupSRV":                           "net",
+	"net.LookupTXT":                           "net",
+	"net.MX":                                  "net",
+	"net.NS":                                  "net",
+	"net.OpError":                             "net",
+	"net.PacketConn":                          "net",
+	"net.ParseCIDR":                           "net",
+	"net.ParseError":                          "net",
+	"net.ParseIP":                             "net",
+	"net.ParseMAC":                            "net",
+	"net.Pipe":                                "net",
+	"net.ResolveIPAddr":                       "net",
+	"net.ResolveTCPAddr":                      "net",
+	"net.ResolveUDPAddr":                      "net",
+	"net.ResolveUnixAddr":                     "net",
+	"net.SRV":                                 "net",
+	"net.SplitHostPort":                       "net",
+	"net.TCPAddr":                             "net",
+	"net.TCPConn":                             "net",
+	"net.TCPListener":                         "net",
+	"net.UDPAddr":                             "net",
+	"net.UDPConn":                             "net",
+	"net.UnixAddr":                            "net",
+	"net.UnixConn":                            "net",
+	"net.UnixListener":                        "net",
+	"net.UnknownNetworkError":                 "net",
+	"os.Args":                                 "os",
+	"os.Chdir":                                "os",
+	"os.Chmod":                                "os",
+	"os.Chown":                                "os",
+	"os.Chtimes":                              "os",
+	"os.Clearenv":                             "os",
+	"os.Create":                               "os",
+	"os.DevNull":                              "os",
+	"os.Environ":                              "os",
+	"os.ErrExist":                             "os",
+	"os.ErrInvalid":                           "os",
+	"os.ErrNotExist":                          "os",
+	"os.ErrPermission":                        "os",
+	"os.Exit":                                 "os",
+	"os.Expand":                               "os",
+	"os.ExpandEnv":                            "os",
+	"os.File":                                 "os",
+	"os.FileInfo":                             "os",
+	"os.FileMode":                             "os",
+	"os.FindProcess":                          "os",
+	"os.Getegid":                              "os",
+	"os.Getenv":                               "os",
+	"os.Geteuid":                              "os",
+	"os.Getgid":                               "os",
+	"os.Getgroups":                            "os",
+	"os.Getpagesize":                          "os",
+	"os.Getpid":                               "os",
+	"os.Getppid":                              "os",
+	"os.Getuid":                               "os",
+	"os.Getwd":                                "os",
+	"os.Hostname":                             "os",
+	"os.Interrupt":                            "os",
+	"os.IsExist":                              "os",
+	"os.IsNotExist":                           "os",
+	"os.IsPathSeparator":                      "os",
+	"os.IsPermission":                         "os",
+	"os.Kill":                                 "os",
+	"os.Lchown":                               "os",
+	"os.Link":                                 "os",
+	"os.LinkError":                            "os",
+	"os.Lstat":                                "os",
+	"os.Mkdir":                                "os",
+	"os.MkdirAll":                             "os",
+	"os.ModeAppend":                           "os",
+	"os.ModeCharDevice":                       "os",
+	"os.ModeDevice":                           "os",
+	"os.ModeDir":                              "os",
+	"os.ModeExclusive":                        "os",
+	"os.ModeNamedPipe":                        "os",
+	"os.ModePerm":                             "os",
+	"os.ModeSetgid":                           "os",
+	"os.ModeSetuid":                           "os",
+	"os.ModeSocket":                           "os",
+	"os.ModeSticky":                           "os",
+	"os.ModeSymlink":                          "os",
+	"os.ModeTemporary":                        "os",
+	"os.ModeType":                             "os",
+	"os.NewFile":                              "os",
+	"os.NewSyscallError":                      "os",
+	"os.O_APPEND":                             "os",
+	"os.O_CREATE":                             "os",
+	"os.O_EXCL":                               "os",
+	"os.O_RDONLY":                             "os",
+	"os.O_RDWR":                               "os",
+	"os.O_SYNC":                               "os",
+	"os.O_TRUNC":                              "os",
+	"os.O_WRONLY":                             "os",
+	"os.Open":                                 "os",
+	"os.OpenFile":                             "os",
+	"os.PathError":                            "os",
+	"os.PathListSeparator":                    "os",
+	"os.PathSeparator":                        "os",
+	"os.Pipe":                                 "os",
+	"os.ProcAttr":                             "os",
+	"os.Process":                              "os",
+	"os.ProcessState":                         "os",
+	"os.Readlink":                             "os",
+	"os.Remove":                               "os",
+	"os.RemoveAll":                            "os",
+	"os.Rename":                               "os",
+	"os.SEEK_CUR":                             "os",
+	"os.SEEK_END":                             "os",
+	"os.SEEK_SET":                             "os",
+	"os.SameFile":                             "os",
+	"os.Setenv":                               "os",
+	"os.Signal":                               "os",
+	"os.StartProcess":                         "os",
+	"os.Stat":                                 "os",
+	"os.Stderr":                               "os",
+	"os.Stdin":                                "os",
+	"os.Stdout":                               "os",
+	"os.Symlink":                              "os",
+	"os.SyscallError":                         "os",
+	"os.TempDir":                              "os",
+	"os.Truncate":                             "os",
+	"palette.Plan9":                           "image/color/palette",
+	"palette.WebSafe":                         "image/color/palette",
+	"parse.ActionNode":                        "text/template/parse",
+	"parse.BoolNode":                          "text/template/parse",
+	"parse.BranchNode":                        "text/template/parse",
+	"parse.ChainNode":                         "text/template/parse",
+	"parse.CommandNode":                       "text/template/parse",
+	"parse.DotNode":                           "text/template/parse",
+	"parse.FieldNode":                         "text/template/parse",
+	"parse.IdentifierNode":                    "text/template/parse",
+	"parse.IfNode":                            "text/template/parse",
+	"parse.IsEmptyTree":                       "text/template/parse",
+	"parse.ListNode":                          "text/template/parse",
+	"parse.New":                               "text/template/parse",
+	"parse.NewIdentifier":                     "text/template/parse",
+	"parse.NilNode":                           "text/template/parse",
+	"parse.Node":                              "text/template/parse",
+	"parse.NodeAction":                        "text/template/parse",
+	"parse.NodeBool":                          "text/template/parse",
+	"parse.NodeChain":                         "text/template/parse",
+	"parse.NodeCommand":                       "text/template/parse",
+	"parse.NodeDot":                           "text/template/parse",
+	"parse.NodeField":                         "text/template/parse",
+	"parse.NodeIdentifier":                    "text/template/parse",
+	"parse.NodeIf":                            "text/template/parse",
+	"parse.NodeList":                          "text/template/parse",
+	"parse.NodeNil":                           "text/template/parse",
+	"parse.NodeNumber":                        "text/template/parse",
+	"parse.NodePipe":                          "text/template/parse",
+	"parse.NodeRange":                         "text/template/parse",
+	"parse.NodeString":                        "text/template/parse",
+	"parse.NodeTemplate":                      "text/template/parse",
+	"parse.NodeText":                          "text/template/parse",
+	"parse.NodeType":                          "text/template/parse",
+	"parse.NodeVariable":                      "text/template/parse",
+	"parse.NodeWith":                          "text/template/parse",
+	"parse.NumberNode":                        "text/template/parse",
+	"parse.Parse":                             "text/template/parse",
+	"parse.PipeNode":                          "text/template/parse",
+	"parse.Pos":                               "text/template/parse",
+	"parse.RangeNode":                         "text/template/parse",
+	"parse.StringNode":                        "text/template/parse",
+	"parse.TemplateNode":                      "text/template/parse",
+	"parse.TextNode":                          "text/template/parse",
+	"parse.Tree":                              "text/template/parse",
+	"parse.VariableNode":                      "text/template/parse",
+	"parse.WithNode":                          "text/template/parse",
+	"parser.AllErrors":                        "go/parser",
+	"parser.DeclarationErrors":                "go/parser",
+	"parser.ImportsOnly":                      "go/parser",
+	"parser.Mode":                             "go/parser",
+	"parser.PackageClauseOnly":                "go/parser",
+	"parser.ParseComments":                    "go/parser",
+	"parser.ParseDir":                         "go/parser",
+	"parser.ParseExpr":                        "go/parser",
+	"parser.ParseFile":                        "go/parser",
+	"parser.SpuriousErrors":                   "go/parser",
+	"parser.Trace":                            "go/parser",
+	"path.Base":                               "path",
+	"path.Clean":                              "path",
+	"path.Dir":                                "path",
+	"path.ErrBadPattern":                      "path",
+	"path.Ext":                                "path",
+	"path.IsAbs":                              "path",
+	"path.Join":                               "path",
+	"path.Match":                              "path",
+	"path.Split":                              "path",
+	"pe.COFFSymbol":                           "debug/pe",
+	"pe.COFFSymbolSize":                       "debug/pe",
+	"pe.File":                                 "debug/pe",
+	"pe.FileHeader":                           "debug/pe",
+	"pe.FormatError":                          "debug/pe",
+	"pe.IMAGE_FILE_MACHINE_AM33":              "debug/pe",
+	"pe.IMAGE_FILE_MACHINE_AMD64":             "debug/pe",
+	"pe.IMAGE_FILE_MACHINE_ARM":               "debug/pe",
+	"pe.IMAGE_FILE_MACHINE_EBC":               "debug/pe",
+	"pe.IMAGE_FILE_MACHINE_I386":              "debug/pe",
+	"pe.IMAGE_FILE_MACHINE_IA64":              "debug/pe",
+	"pe.IMAGE_FILE_MACHINE_M32R":              "debug/pe",
+	"pe.IMAGE_FILE_MACHINE_MIPS16":            "debug/pe",
+	"pe.IMAGE_FILE_MACHINE_MIPSFPU":           "debug/pe",
+	"pe.IMAGE_FILE_MACHINE_MIPSFPU16":         "debug/pe",
+	"pe.IMAGE_FILE_MACHINE_POWERPC":           "debug/pe",
+	"pe.IMAGE_FILE_MACHINE_POWERPCFP":         "debug/pe",
+	"pe.IMAGE_FILE_MACHINE_R4000":             "debug/pe",
+	"pe.IMAGE_FILE_MACHINE_SH3":               "debug/pe",
+	"pe.IMAGE_FILE_MACHINE_SH3DSP":            "debug/pe",
+	"pe.IMAGE_FILE_MACHINE_SH4":               "debug/pe",
+	"pe.IMAGE_FILE_MACHINE_SH5":               "debug/pe",
+	"pe.IMAGE_FILE_MACHINE_THUMB":             "debug/pe",
+	"pe.IMAGE_FILE_MACHINE_UNKNOWN":           "debug/pe",
+	"pe.IMAGE_FILE_MACHINE_WCEMIPSV2":         "debug/pe",
+	"pe.ImportDirectory":                      "debug/pe",
+	"pe.NewFile":                              "debug/pe",
+	"pe.Open":                                 "debug/pe",
+	"pe.Section":                              "debug/pe",
+	"pe.SectionHeader":                        "debug/pe",
+	"pe.SectionHeader32":                      "debug/pe",
+	"pe.Symbol":                               "debug/pe",
+	"pem.Block":                               "encoding/pem",
+	"pem.Decode":                              "encoding/pem",
+	"pem.Encode":                              "encoding/pem",
+	"pem.EncodeToMemory":                      "encoding/pem",
+	"pkix.AlgorithmIdentifier":                "crypto/x509/pkix",
+	"pkix.AttributeTypeAndValue":              "crypto/x509/pkix",
+	"pkix.CertificateList":                    "crypto/x509/pkix",
+	"pkix.Extension":                          "crypto/x509/pkix",
+	"pkix.Name":                               "crypto/x509/pkix",
+	"pkix.RDNSequence":                        "crypto/x509/pkix",
+	"pkix.RelativeDistinguishedNameSET":       "crypto/x509/pkix",
+	"pkix.RevokedCertificate":                 "crypto/x509/pkix",
+	"pkix.TBSCertificateList":                 "crypto/x509/pkix",
+	"png.Decode":                              "image/png",
+	"png.DecodeConfig":                        "image/png",
+	"png.Encode":                              "image/png",
+	"png.FormatError":                         "image/png",
+	"png.UnsupportedError":                    "image/png",
+	"pprof.Cmdline":                           "net/http/pprof",
+	"pprof.Handler":                           "net/http/pprof",
+	"pprof.Index":                             "net/http/pprof",
+	"pprof.Lookup":                            "runtime/pprof",
+	"pprof.NewProfile":                        "runtime/pprof",
+	// "pprof.Profile" is ambiguous
+	"pprof.Profiles":         "runtime/pprof",
+	"pprof.StartCPUProfile":  "runtime/pprof",
+	"pprof.StopCPUProfile":   "runtime/pprof",
+	"pprof.Symbol":           "net/http/pprof",
+	"pprof.WriteHeapProfile": "runtime/pprof",
+	"printer.CommentedNode":  "go/printer",
+	"printer.Config":         "go/printer",
+	"printer.Fprint":         "go/printer",
+	"printer.Mode":           "go/printer",
+	"printer.RawFormat":      "go/printer",
+	"printer.SourcePos":      "go/printer",
+	"printer.TabIndent":      "go/printer",
+	"printer.UseSpaces":      "go/printer",
+	"quick.Check":            "testing/quick",
+	"quick.CheckEqual":       "testing/quick",
+	"quick.CheckEqualError":  "testing/quick",
+	"quick.CheckError":       "testing/quick",
+	"quick.Config":           "testing/quick",
+	"quick.Generator":        "testing/quick",
+	"quick.SetupError":       "testing/quick",
+	"quick.Value":            "testing/quick",
+	"rand.ExpFloat64":        "math/rand",
+	"rand.Float32":           "math/rand",
+	"rand.Float64":           "math/rand",
+	// "rand.Int" is ambiguous
+	"rand.Int31":                    "math/rand",
+	"rand.Int31n":                   "math/rand",
+	"rand.Int63":                    "math/rand",
+	"rand.Int63n":                   "math/rand",
+	"rand.Intn":                     "math/rand",
+	"rand.New":                      "math/rand",
+	"rand.NewSource":                "math/rand",
+	"rand.NewZipf":                  "math/rand",
+	"rand.NormFloat64":              "math/rand",
+	"rand.Perm":                     "math/rand",
+	"rand.Prime":                    "crypto/rand",
+	"rand.Rand":                     "math/rand",
+	"rand.Read":                     "crypto/rand",
+	"rand.Reader":                   "crypto/rand",
+	"rand.Seed":                     "math/rand",
+	"rand.Source":                   "math/rand",
+	"rand.Uint32":                   "math/rand",
+	"rand.Zipf":                     "math/rand",
+	"rc4.Cipher":                    "crypto/rc4",
+	"rc4.KeySizeError":              "crypto/rc4",
+	"rc4.NewCipher":                 "crypto/rc4",
+	"reflect.Append":                "reflect",
+	"reflect.AppendSlice":           "reflect",
+	"reflect.Array":                 "reflect",
+	"reflect.Bool":                  "reflect",
+	"reflect.BothDir":               "reflect",
+	"reflect.Chan":                  "reflect",
+	"reflect.ChanDir":               "reflect",
+	"reflect.ChanOf":                "reflect",
+	"reflect.Complex128":            "reflect",
+	"reflect.Complex64":             "reflect",
+	"reflect.Copy":                  "reflect",
+	"reflect.DeepEqual":             "reflect",
+	"reflect.Float32":               "reflect",
+	"reflect.Float64":               "reflect",
+	"reflect.Func":                  "reflect",
+	"reflect.Indirect":              "reflect",
+	"reflect.Int":                   "reflect",
+	"reflect.Int16":                 "reflect",
+	"reflect.Int32":                 "reflect",
+	"reflect.Int64":                 "reflect",
+	"reflect.Int8":                  "reflect",
+	"reflect.Interface":             "reflect",
+	"reflect.Invalid":               "reflect",
+	"reflect.Kind":                  "reflect",
+	"reflect.MakeChan":              "reflect",
+	"reflect.MakeFunc":              "reflect",
+	"reflect.MakeMap":               "reflect",
+	"reflect.MakeSlice":             "reflect",
+	"reflect.Map":                   "reflect",
+	"reflect.MapOf":                 "reflect",
+	"reflect.Method":                "reflect",
+	"reflect.New":                   "reflect",
+	"reflect.NewAt":                 "reflect",
+	"reflect.Ptr":                   "reflect",
+	"reflect.PtrTo":                 "reflect",
+	"reflect.RecvDir":               "reflect",
+	"reflect.Select":                "reflect",
+	"reflect.SelectCase":            "reflect",
+	"reflect.SelectDefault":         "reflect",
+	"reflect.SelectDir":             "reflect",
+	"reflect.SelectRecv":            "reflect",
+	"reflect.SelectSend":            "reflect",
+	"reflect.SendDir":               "reflect",
+	"reflect.Slice":                 "reflect",
+	"reflect.SliceHeader":           "reflect",
+	"reflect.SliceOf":               "reflect",
+	"reflect.String":                "reflect",
+	"reflect.StringHeader":          "reflect",
+	"reflect.Struct":                "reflect",
+	"reflect.StructField":           "reflect",
+	"reflect.StructTag":             "reflect",
+	"reflect.TypeOf":                "reflect",
+	"reflect.Uint":                  "reflect",
+	"reflect.Uint16":                "reflect",
+	"reflect.Uint32":                "reflect",
+	"reflect.Uint64":                "reflect",
+	"reflect.Uint8":                 "reflect",
+	"reflect.Uintptr":               "reflect",
+	"reflect.UnsafePointer":         "reflect",
+	"reflect.Value":                 "reflect",
+	"reflect.ValueError":            "reflect",
+	"reflect.ValueOf":               "reflect",
+	"reflect.Zero":                  "reflect",
+	"regexp.Compile":                "regexp",
+	"regexp.CompilePOSIX":           "regexp",
+	"regexp.Match":                  "regexp",
+	"regexp.MatchReader":            "regexp",
+	"regexp.MatchString":            "regexp",
+	"regexp.MustCompile":            "regexp",
+	"regexp.MustCompilePOSIX":       "regexp",
+	"regexp.QuoteMeta":              "regexp",
+	"regexp.Regexp":                 "regexp",
+	"ring.New":                      "container/ring",
+	"ring.Ring":                     "container/ring",
+	"rpc.Accept":                    "net/rpc",
+	"rpc.Call":                      "net/rpc",
+	"rpc.Client":                    "net/rpc",
+	"rpc.ClientCodec":               "net/rpc",
+	"rpc.DefaultDebugPath":          "net/rpc",
+	"rpc.DefaultRPCPath":            "net/rpc",
+	"rpc.DefaultServer":             "net/rpc",
+	"rpc.Dial":                      "net/rpc",
+	"rpc.DialHTTP":                  "net/rpc",
+	"rpc.DialHTTPPath":              "net/rpc",
+	"rpc.ErrShutdown":               "net/rpc",
+	"rpc.HandleHTTP":                "net/rpc",
+	"rpc.NewClient":                 "net/rpc",
+	"rpc.NewClientWithCodec":        "net/rpc",
+	"rpc.NewServer":                 "net/rpc",
+	"rpc.Register":                  "net/rpc",
+	"rpc.RegisterName":              "net/rpc",
+	"rpc.Request":                   "net/rpc",
+	"rpc.Response":                  "net/rpc",
+	"rpc.ServeCodec":                "net/rpc",
+	"rpc.ServeConn":                 "net/rpc",
+	"rpc.ServeRequest":              "net/rpc",
+	"rpc.Server":                    "net/rpc",
+	"rpc.ServerCodec":               "net/rpc",
+	"rpc.ServerError":               "net/rpc",
+	"rsa.CRTValue":                  "crypto/rsa",
+	"rsa.DecryptOAEP":               "crypto/rsa",
+	"rsa.DecryptPKCS1v15":           "crypto/rsa",
+	"rsa.DecryptPKCS1v15SessionKey": "crypto/rsa",
+	"rsa.EncryptOAEP":               "crypto/rsa",
+	"rsa.EncryptPKCS1v15":           "crypto/rsa",
+	"rsa.ErrDecryption":             "crypto/rsa",
+	"rsa.ErrMessageTooLong":         "crypto/rsa",
+	"rsa.ErrVerification":           "crypto/rsa",
+	"rsa.GenerateKey":               "crypto/rsa",
+	"rsa.GenerateMultiPrimeKey":     "crypto/rsa",
+	"rsa.PSSOptions":                "crypto/rsa",
+	"rsa.PSSSaltLengthAuto":         "crypto/rsa",
+	"rsa.PSSSaltLengthEqualsHash":   "crypto/rsa",
+	"rsa.PrecomputedValues":         "crypto/rsa",
+	"rsa.PrivateKey":                "crypto/rsa",
+	"rsa.PublicKey":                 "crypto/rsa",
+	"rsa.SignPKCS1v15":              "crypto/rsa",
+	"rsa.SignPSS":                   "crypto/rsa",
+	"rsa.VerifyPKCS1v15":            "crypto/rsa",
+	"rsa.VerifyPSS":                 "crypto/rsa",
+	"runtime.BlockProfile":          "runtime",
+	"runtime.BlockProfileRecord":    "runtime",
+	"runtime.Breakpoint":            "runtime",
+	"runtime.CPUProfile":            "runtime",
+	"runtime.Caller":                "runtime",
+	"runtime.Callers":               "runtime",
+	"runtime.Compiler":              "runtime",
+	"runtime.Error":                 "runtime",
+	"runtime.Func":                  "runtime",
+	"runtime.FuncForPC":             "runtime",
+	"runtime.GC":                    "runtime",
+	"runtime.GOARCH":                "runtime",
+	"runtime.GOMAXPROCS":            "runtime",
+	"runtime.GOOS":                  "runtime",
+	"runtime.GOROOT":                "runtime",
+	"runtime.Goexit":                "runtime",
+	"runtime.GoroutineProfile":      "runtime",
+	"runtime.Gosched":               "runtime",
+	"runtime.LockOSThread":          "runtime",
+	"runtime.MemProfile":            "runtime",
+	"runtime.MemProfileRate":        "runtime",
+	"runtime.MemProfileRecord":      "runtime",
+	"runtime.MemStats":              "runtime",
+	"runtime.NumCPU":                "runtime",
+	"runtime.NumCgoCall":            "runtime",
+	"runtime.NumGoroutine":          "runtime",
+	"runtime.ReadMemStats":          "runtime",
+	"runtime.SetBlockProfileRate":   "runtime",
+	"runtime.SetCPUProfileRate":     "runtime",
+	"runtime.SetFinalizer":          "runtime",
+	"runtime.Stack":                 "runtime",
+	"runtime.StackRecord":           "runtime",
+	"runtime.ThreadCreateProfile":   "runtime",
+	"runtime.TypeAssertionError":    "runtime",
+	"runtime.UnlockOSThread":        "runtime",
+	"runtime.Version":               "runtime",
+	"scanner.Char":                  "text/scanner",
+	"scanner.Comment":               "text/scanner",
+	"scanner.EOF":                   "text/scanner",
+	"scanner.Error":                 "go/scanner",
+	"scanner.ErrorHandler":          "go/scanner",
+	"scanner.ErrorList":             "go/scanner",
+	"scanner.Float":                 "text/scanner",
+	"scanner.GoTokens":              "text/scanner",
+	"scanner.GoWhitespace":          "text/scanner",
+	"scanner.Ident":                 "text/scanner",
+	"scanner.Int":                   "text/scanner",
+	"scanner.Mode":                  "go/scanner",
+	"scanner.Position":              "text/scanner",
+	"scanner.PrintError":            "go/scanner",
+	"scanner.RawString":             "text/scanner",
+	"scanner.ScanChars":             "text/scanner",
+	// "scanner.ScanComments" is ambiguous
+	"scanner.ScanFloats":     "text/scanner",
+	"scanner.ScanIdents":     "text/scanner",
+	"scanner.ScanInts":       "text/scanner",
+	"scanner.ScanRawStrings": "text/scanner",
+	"scanner.ScanStrings":    "text/scanner",
+	// "scanner.Scanner" is ambiguous
+	"scanner.SkipComments":                                 "text/scanner",
+	"scanner.String":                                       "text/scanner",
+	"scanner.TokenString":                                  "text/scanner",
+	"sha1.BlockSize":                                       "crypto/sha1",
+	"sha1.New":                                             "crypto/sha1",
+	"sha1.Size":                                            "crypto/sha1",
+	"sha1.Sum":                                             "crypto/sha1",
+	"sha256.BlockSize":                                     "crypto/sha256",
+	"sha256.New":                                           "crypto/sha256",
+	"sha256.New224":                                        "crypto/sha256",
+	"sha256.Size":                                          "crypto/sha256",
+	"sha256.Size224":                                       "crypto/sha256",
+	"sha256.Sum224":                                        "crypto/sha256",
+	"sha256.Sum256":                                        "crypto/sha256",
+	"sha512.BlockSize":                                     "crypto/sha512",
+	"sha512.New":                                           "crypto/sha512",
+	"sha512.New384":                                        "crypto/sha512",
+	"sha512.Size":                                          "crypto/sha512",
+	"sha512.Size384":                                       "crypto/sha512",
+	"sha512.Sum384":                                        "crypto/sha512",
+	"sha512.Sum512":                                        "crypto/sha512",
+	"signal.Notify":                                        "os/signal",
+	"signal.Stop":                                          "os/signal",
+	"smtp.Auth":                                            "net/smtp",
+	"smtp.CRAMMD5Auth":                                     "net/smtp",
+	"smtp.Client":                                          "net/smtp",
+	"smtp.Dial":                                            "net/smtp",
+	"smtp.NewClient":                                       "net/smtp",
+	"smtp.PlainAuth":                                       "net/smtp",
+	"smtp.SendMail":                                        "net/smtp",
+	"smtp.ServerInfo":                                      "net/smtp",
+	"sort.Float64Slice":                                    "sort",
+	"sort.Float64s":                                        "sort",
+	"sort.Float64sAreSorted":                               "sort",
+	"sort.IntSlice":                                        "sort",
+	"sort.Interface":                                       "sort",
+	"sort.Ints":                                            "sort",
+	"sort.IntsAreSorted":                                   "sort",
+	"sort.IsSorted":                                        "sort",
+	"sort.Reverse":                                         "sort",
+	"sort.Search":                                          "sort",
+	"sort.SearchFloat64s":                                  "sort",
+	"sort.SearchInts":                                      "sort",
+	"sort.SearchStrings":                                   "sort",
+	"sort.Sort":                                            "sort",
+	"sort.Stable":                                          "sort",
+	"sort.StringSlice":                                     "sort",
+	"sort.Strings":                                         "sort",
+	"sort.StringsAreSorted":                                "sort",
+	"sql.DB":                                               "database/sql",
+	"sql.ErrNoRows":                                        "database/sql",
+	"sql.ErrTxDone":                                        "database/sql",
+	"sql.NullBool":                                         "database/sql",
+	"sql.NullFloat64":                                      "database/sql",
+	"sql.NullInt64":                                        "database/sql",
+	"sql.NullString":                                       "database/sql",
+	"sql.Open":                                             "database/sql",
+	"sql.RawBytes":                                         "database/sql",
+	"sql.Register":                                         "database/sql",
+	"sql.Result":                                           "database/sql",
+	"sql.Row":                                              "database/sql",
+	"sql.Rows":                                             "database/sql",
+	"sql.Scanner":                                          "database/sql",
+	"sql.Stmt":                                             "database/sql",
+	"sql.Tx":                                               "database/sql",
+	"strconv.AppendBool":                                   "strconv",
+	"strconv.AppendFloat":                                  "strconv",
+	"strconv.AppendInt":                                    "strconv",
+	"strconv.AppendQuote":                                  "strconv",
+	"strconv.AppendQuoteRune":                              "strconv",
+	"strconv.AppendQuoteRuneToASCII":                       "strconv",
+	"strconv.AppendQuoteToASCII":                           "strconv",
+	"strconv.AppendUint":                                   "strconv",
+	"strconv.Atoi":                                         "strconv",
+	"strconv.CanBackquote":                                 "strconv",
+	"strconv.ErrRange":                                     "strconv",
+	"strconv.ErrSyntax":                                    "strconv",
+	"strconv.FormatBool":                                   "strconv",
+	"strconv.FormatFloat":                                  "strconv",
+	"strconv.FormatInt":                                    "strconv",
+	"strconv.FormatUint":                                   "strconv",
+	"strconv.IntSize":                                      "strconv",
+	"strconv.IsPrint":                                      "strconv",
+	"strconv.Itoa":                                         "strconv",
+	"strconv.NumError":                                     "strconv",
+	"strconv.ParseBool":                                    "strconv",
+	"strconv.ParseFloat":                                   "strconv",
+	"strconv.ParseInt":                                     "strconv",
+	"strconv.ParseUint":                                    "strconv",
+	"strconv.Quote":                                        "strconv",
+	"strconv.QuoteRune":                                    "strconv",
+	"strconv.QuoteRuneToASCII":                             "strconv",
+	"strconv.QuoteToASCII":                                 "strconv",
+	"strconv.Unquote":                                      "strconv",
+	"strconv.UnquoteChar":                                  "strconv",
+	"strings.Contains":                                     "strings",
+	"strings.ContainsAny":                                  "strings",
+	"strings.ContainsRune":                                 "strings",
+	"strings.Count":                                        "strings",
+	"strings.EqualFold":                                    "strings",
+	"strings.Fields":                                       "strings",
+	"strings.FieldsFunc":                                   "strings",
+	"strings.HasPrefix":                                    "strings",
+	"strings.HasSuffix":                                    "strings",
+	"strings.Index":                                        "strings",
+	"strings.IndexAny":                                     "strings",
+	"strings.IndexByte":                                    "strings",
+	"strings.IndexFunc":                                    "strings",
+	"strings.IndexRune":                                    "strings",
+	"strings.Join":                                         "strings",
+	"strings.LastIndex":                                    "strings",
+	"strings.LastIndexAny":                                 "strings",
+	"strings.LastIndexFunc":                                "strings",
+	"strings.Map":                                          "strings",
+	"strings.NewReader":                                    "strings",
+	"strings.NewReplacer":                                  "strings",
+	"strings.Reader":                                       "strings",
+	"strings.Repeat":                                       "strings",
+	"strings.Replace":                                      "strings",
+	"strings.Replacer":                                     "strings",
+	"strings.Split":                                        "strings",
+	"strings.SplitAfter":                                   "strings",
+	"strings.SplitAfterN":                                  "strings",
+	"strings.SplitN":                                       "strings",
+	"strings.Title":                                        "strings",
+	"strings.ToLower":                                      "strings",
+	"strings.ToLowerSpecial":                               "strings",
+	"strings.ToTitle":                                      "strings",
+	"strings.ToTitleSpecial":                               "strings",
+	"strings.ToUpper":                                      "strings",
+	"strings.ToUpperSpecial":                               "strings",
+	"strings.Trim":                                         "strings",
+	"strings.TrimFunc":                                     "strings",
+	"strings.TrimLeft":                                     "strings",
+	"strings.TrimLeftFunc":                                 "strings",
+	"strings.TrimPrefix":                                   "strings",
+	"strings.TrimRight":                                    "strings",
+	"strings.TrimRightFunc":                                "strings",
+	"strings.TrimSpace":                                    "strings",
+	"strings.TrimSuffix":                                   "strings",
+	"subtle.ConstantTimeByteEq":                            "crypto/subtle",
+	"subtle.ConstantTimeCompare":                           "crypto/subtle",
+	"subtle.ConstantTimeCopy":                              "crypto/subtle",
+	"subtle.ConstantTimeEq":                                "crypto/subtle",
+	"subtle.ConstantTimeLessOrEq":                          "crypto/subtle",
+	"subtle.ConstantTimeSelect":                            "crypto/subtle",
+	"suffixarray.Index":                                    "index/suffixarray",
+	"suffixarray.New":                                      "index/suffixarray",
+	"sync.Cond":                                            "sync",
+	"sync.Locker":                                          "sync",
+	"sync.Mutex":                                           "sync",
+	"sync.NewCond":                                         "sync",
+	"sync.Once":                                            "sync",
+	"sync.RWMutex":                                         "sync",
+	"sync.WaitGroup":                                       "sync",
+	"syntax.ClassNL":                                       "regexp/syntax",
+	"syntax.Compile":                                       "regexp/syntax",
+	"syntax.DotNL":                                         "regexp/syntax",
+	"syntax.EmptyBeginLine":                                "regexp/syntax",
+	"syntax.EmptyBeginText":                                "regexp/syntax",
+	"syntax.EmptyEndLine":                                  "regexp/syntax",
+	"syntax.EmptyEndText":                                  "regexp/syntax",
+	"syntax.EmptyNoWordBoundary":                           "regexp/syntax",
+	"syntax.EmptyOp":                                       "regexp/syntax",
+	"syntax.EmptyOpContext":                                "regexp/syntax",
+	"syntax.EmptyWordBoundary":                             "regexp/syntax",
+	"syntax.ErrInternalError":                              "regexp/syntax",
+	"syntax.ErrInvalidCharClass":                           "regexp/syntax",
+	"syntax.ErrInvalidCharRange":                           "regexp/syntax",
+	"syntax.ErrInvalidEscape":                              "regexp/syntax",
+	"syntax.ErrInvalidNamedCapture":                        "regexp/syntax",
+	"syntax.ErrInvalidPerlOp":                              "regexp/syntax",
+	"syntax.ErrInvalidRepeatOp":                            "regexp/syntax",
+	"syntax.ErrInvalidRepeatSize":                          "regexp/syntax",
+	"syntax.ErrInvalidUTF8":                                "regexp/syntax",
+	"syntax.ErrMissingBracket":                             "regexp/syntax",
+	"syntax.ErrMissingParen":                               "regexp/syntax",
+	"syntax.ErrMissingRepeatArgument":                      "regexp/syntax",
+	"syntax.ErrTrailingBackslash":                          "regexp/syntax",
+	"syntax.ErrUnexpectedParen":                            "regexp/syntax",
+	"syntax.Error":                                         "regexp/syntax",
+	"syntax.ErrorCode":                                     "regexp/syntax",
+	"syntax.Flags":                                         "regexp/syntax",
+	"syntax.FoldCase":                                      "regexp/syntax",
+	"syntax.Inst":                                          "regexp/syntax",
+	"syntax.InstAlt":                                       "regexp/syntax",
+	"syntax.InstAltMatch":                                  "regexp/syntax",
+	"syntax.InstCapture":                                   "regexp/syntax",
+	"syntax.InstEmptyWidth":                                "regexp/syntax",
+	"syntax.InstFail":                                      "regexp/syntax",
+	"syntax.InstMatch":                                     "regexp/syntax",
+	"syntax.InstNop":                                       "regexp/syntax",
+	"syntax.InstOp":                                        "regexp/syntax",
+	"syntax.InstRune":                                      "regexp/syntax",
+	"syntax.InstRune1":                                     "regexp/syntax",
+	"syntax.InstRuneAny":                                   "regexp/syntax",
+	"syntax.InstRuneAnyNotNL":                              "regexp/syntax",
+	"syntax.IsWordChar":                                    "regexp/syntax",
+	"syntax.Literal":                                       "regexp/syntax",
+	"syntax.MatchNL":                                       "regexp/syntax",
+	"syntax.NonGreedy":                                     "regexp/syntax",
+	"syntax.OneLine":                                       "regexp/syntax",
+	"syntax.Op":                                            "regexp/syntax",
+	"syntax.OpAlternate":                                   "regexp/syntax",
+	"syntax.OpAnyChar":                                     "regexp/syntax",
+	"syntax.OpAnyCharNotNL":                                "regexp/syntax",
+	"syntax.OpBeginLine":                                   "regexp/syntax",
+	"syntax.OpBeginText":                                   "regexp/syntax",
+	"syntax.OpCapture":                                     "regexp/syntax",
+	"syntax.OpCharClass":                                   "regexp/syntax",
+	"syntax.OpConcat":                                      "regexp/syntax",
+	"syntax.OpEmptyMatch":                                  "regexp/syntax",
+	"syntax.OpEndLine":                                     "regexp/syntax",
+	"syntax.OpEndText":                                     "regexp/syntax",
+	"syntax.OpLiteral":                                     "regexp/syntax",
+	"syntax.OpNoMatch":                                     "regexp/syntax",
+	"syntax.OpNoWordBoundary":                              "regexp/syntax",
+	"syntax.OpPlus":                                        "regexp/syntax",
+	"syntax.OpQuest":                                       "regexp/syntax",
+	"syntax.OpRepeat":                                      "regexp/syntax",
+	"syntax.OpStar":                                        "regexp/syntax",
+	"syntax.OpWordBoundary":                                "regexp/syntax",
+	"syntax.POSIX":                                         "regexp/syntax",
+	"syntax.Parse":                                         "regexp/syntax",
+	"syntax.Perl":                                          "regexp/syntax",
+	"syntax.PerlX":                                         "regexp/syntax",
+	"syntax.Prog":                                          "regexp/syntax",
+	"syntax.Regexp":                                        "regexp/syntax",
+	"syntax.Simple":                                        "regexp/syntax",
+	"syntax.UnicodeGroups":                                 "regexp/syntax",
+	"syntax.WasDollar":                                     "regexp/syntax",
+	"syscall.AF_ALG":                                       "syscall",
+	"syscall.AF_APPLETALK":                                 "syscall",
+	"syscall.AF_ARP":                                       "syscall",
+	"syscall.AF_ASH":                                       "syscall",
+	"syscall.AF_ATM":                                       "syscall",
+	"syscall.AF_ATMPVC":                                    "syscall",
+	"syscall.AF_ATMSVC":                                    "syscall",
+	"syscall.AF_AX25":                                      "syscall",
+	"syscall.AF_BLUETOOTH":                                 "syscall",
+	"syscall.AF_BRIDGE":                                    "syscall",
+	"syscall.AF_CAIF":                                      "syscall",
+	"syscall.AF_CAN":                                       "syscall",
+	"syscall.AF_CCITT":                                     "syscall",
+	"syscall.AF_CHAOS":                                     "syscall",
+	"syscall.AF_CNT":                                       "syscall",
+	"syscall.AF_COIP":                                      "syscall",
+	"syscall.AF_DATAKIT":                                   "syscall",
+	"syscall.AF_DECnet":                                    "syscall",
+	"syscall.AF_DLI":                                       "syscall",
+	"syscall.AF_E164":                                      "syscall",
+	"syscall.AF_ECMA":                                      "syscall",
+	"syscall.AF_ECONET":                                    "syscall",
+	"syscall.AF_ENCAP":                                     "syscall",
+	"syscall.AF_FILE":                                      "syscall",
+	"syscall.AF_HYLINK":                                    "syscall",
+	"syscall.AF_IEEE80211":                                 "syscall",
+	"syscall.AF_IEEE802154":                                "syscall",
+	"syscall.AF_IMPLINK":                                   "syscall",
+	"syscall.AF_INET":                                      "syscall",
+	"syscall.AF_INET6":                                     "syscall",
+	"syscall.AF_IPX":                                       "syscall",
+	"syscall.AF_IRDA":                                      "syscall",
+	"syscall.AF_ISDN":                                      "syscall",
+	"syscall.AF_ISO":                                       "syscall",
+	"syscall.AF_IUCV":                                      "syscall",
+	"syscall.AF_KEY":                                       "syscall",
+	"syscall.AF_LAT":                                       "syscall",
+	"syscall.AF_LINK":                                      "syscall",
+	"syscall.AF_LLC":                                       "syscall",
+	"syscall.AF_LOCAL":                                     "syscall",
+	"syscall.AF_MAX":                                       "syscall",
+	"syscall.AF_MPLS":                                      "syscall",
+	"syscall.AF_NATM":                                      "syscall",
+	"syscall.AF_NDRV":                                      "syscall",
+	"syscall.AF_NETBEUI":                                   "syscall",
+	"syscall.AF_NETBIOS":                                   "syscall",
+	"syscall.AF_NETGRAPH":                                  "syscall",
+	"syscall.AF_NETLINK":                                   "syscall",
+	"syscall.AF_NETROM":                                    "syscall",
+	"syscall.AF_NS":                                        "syscall",
+	"syscall.AF_OROUTE":                                    "syscall",
+	"syscall.AF_OSI":                                       "syscall",
+	"syscall.AF_PACKET":                                    "syscall",
+	"syscall.AF_PHONET":                                    "syscall",
+	"syscall.AF_PPP":                                       "syscall",
+	"syscall.AF_PPPOX":                                     "syscall",
+	"syscall.AF_PUP":                                       "syscall",
+	"syscall.AF_RDS":                                       "syscall",
+	"syscall.AF_RESERVED_36":                               "syscall",
+	"syscall.AF_ROSE":                                      "syscall",
+	"syscall.AF_ROUTE":                                     "syscall",
+	"syscall.AF_RXRPC":                                     "syscall",
+	"syscall.AF_SCLUSTER":                                  "syscall",
+	"syscall.AF_SECURITY":                                  "syscall",
+	"syscall.AF_SIP":                                       "syscall",
+	"syscall.AF_SLOW":                                      "syscall",
+	"syscall.AF_SNA":                                       "syscall",
+	"syscall.AF_SYSTEM":                                    "syscall",
+	"syscall.AF_TIPC":                                      "syscall",
+	"syscall.AF_UNIX":                                      "syscall",
+	"syscall.AF_UNSPEC":                                    "syscall",
+	"syscall.AF_VENDOR00":                                  "syscall",
+	"syscall.AF_VENDOR01":                                  "syscall",
+	"syscall.AF_VENDOR02":                                  "syscall",
+	"syscall.AF_VENDOR03":                                  "syscall",
+	"syscall.AF_VENDOR04":                                  "syscall",
+	"syscall.AF_VENDOR05":                                  "syscall",
+	"syscall.AF_VENDOR06":                                  "syscall",
+	"syscall.AF_VENDOR07":                                  "syscall",
+	"syscall.AF_VENDOR08":                                  "syscall",
+	"syscall.AF_VENDOR09":                                  "syscall",
+	"syscall.AF_VENDOR10":                                  "syscall",
+	"syscall.AF_VENDOR11":                                  "syscall",
+	"syscall.AF_VENDOR12":                                  "syscall",
+	"syscall.AF_VENDOR13":                                  "syscall",
+	"syscall.AF_VENDOR14":                                  "syscall",
+	"syscall.AF_VENDOR15":                                  "syscall",
+	"syscall.AF_VENDOR16":                                  "syscall",
+	"syscall.AF_VENDOR17":                                  "syscall",
+	"syscall.AF_VENDOR18":                                  "syscall",
+	"syscall.AF_VENDOR19":                                  "syscall",
+	"syscall.AF_VENDOR20":                                  "syscall",
+	"syscall.AF_VENDOR21":                                  "syscall",
+	"syscall.AF_VENDOR22":                                  "syscall",
+	"syscall.AF_VENDOR23":                                  "syscall",
+	"syscall.AF_VENDOR24":                                  "syscall",
+	"syscall.AF_VENDOR25":                                  "syscall",
+	"syscall.AF_VENDOR26":                                  "syscall",
+	"syscall.AF_VENDOR27":                                  "syscall",
+	"syscall.AF_VENDOR28":                                  "syscall",
+	"syscall.AF_VENDOR29":                                  "syscall",
+	"syscall.AF_VENDOR30":                                  "syscall",
+	"syscall.AF_VENDOR31":                                  "syscall",
+	"syscall.AF_VENDOR32":                                  "syscall",
+	"syscall.AF_VENDOR33":                                  "syscall",
+	"syscall.AF_VENDOR34":                                  "syscall",
+	"syscall.AF_VENDOR35":                                  "syscall",
+	"syscall.AF_VENDOR36":                                  "syscall",
+	"syscall.AF_VENDOR37":                                  "syscall",
+	"syscall.AF_VENDOR38":                                  "syscall",
+	"syscall.AF_VENDOR39":                                  "syscall",
+	"syscall.AF_VENDOR40":                                  "syscall",
+	"syscall.AF_VENDOR41":                                  "syscall",
+	"syscall.AF_VENDOR42":                                  "syscall",
+	"syscall.AF_VENDOR43":                                  "syscall",
+	"syscall.AF_VENDOR44":                                  "syscall",
+	"syscall.AF_VENDOR45":                                  "syscall",
+	"syscall.AF_VENDOR46":                                  "syscall",
+	"syscall.AF_VENDOR47":                                  "syscall",
+	"syscall.AF_WANPIPE":                                   "syscall",
+	"syscall.AF_X25":                                       "syscall",
+	"syscall.AI_CANONNAME":                                 "syscall",
+	"syscall.AI_NUMERICHOST":                               "syscall",
+	"syscall.AI_PASSIVE":                                   "syscall",
+	"syscall.APPLICATION_ERROR":                            "syscall",
+	"syscall.ARPHRD_ADAPT":                                 "syscall",
+	"syscall.ARPHRD_APPLETLK":                              "syscall",
+	"syscall.ARPHRD_ARCNET":                                "syscall",
+	"syscall.ARPHRD_ASH":                                   "syscall",
+	"syscall.ARPHRD_ATM":                                   "syscall",
+	"syscall.ARPHRD_AX25":                                  "syscall",
+	"syscall.ARPHRD_BIF":                                   "syscall",
+	"syscall.ARPHRD_CHAOS":                                 "syscall",
+	"syscall.ARPHRD_CISCO":                                 "syscall",
+	"syscall.ARPHRD_CSLIP":                                 "syscall",
+	"syscall.ARPHRD_CSLIP6":                                "syscall",
+	"syscall.ARPHRD_DDCMP":                                 "syscall",
+	"syscall.ARPHRD_DLCI":                                  "syscall",
+	"syscall.ARPHRD_ECONET":                                "syscall",
+	"syscall.ARPHRD_EETHER":                                "syscall",
+	"syscall.ARPHRD_ETHER":                                 "syscall",
+	"syscall.ARPHRD_EUI64":                                 "syscall",
+	"syscall.ARPHRD_FCAL":                                  "syscall",
+	"syscall.ARPHRD_FCFABRIC":                              "syscall",
+	"syscall.ARPHRD_FCPL":                                  "syscall",
+	"syscall.ARPHRD_FCPP":                                  "syscall",
+	"syscall.ARPHRD_FDDI":                                  "syscall",
+	"syscall.ARPHRD_FRAD":                                  "syscall",
+	"syscall.ARPHRD_FRELAY":                                "syscall",
+	"syscall.ARPHRD_HDLC":                                  "syscall",
+	"syscall.ARPHRD_HIPPI":                                 "syscall",
+	"syscall.ARPHRD_HWX25":                                 "syscall",
+	"syscall.ARPHRD_IEEE1394":                              "syscall",
+	"syscall.ARPHRD_IEEE802":                               "syscall",
+	"syscall.ARPHRD_IEEE80211":                             "syscall",
+	"syscall.ARPHRD_IEEE80211_PRISM":                       "syscall",
+	"syscall.ARPHRD_IEEE80211_RADIOTAP":                    "syscall",
+	"syscall.ARPHRD_IEEE802154":                            "syscall",
+	"syscall.ARPHRD_IEEE802154_PHY":                        "syscall",
+	"syscall.ARPHRD_IEEE802_TR":                            "syscall",
+	"syscall.ARPHRD_INFINIBAND":                            "syscall",
+	"syscall.ARPHRD_IPDDP":                                 "syscall",
+	"syscall.ARPHRD_IPGRE":                                 "syscall",
+	"syscall.ARPHRD_IRDA":                                  "syscall",
+	"syscall.ARPHRD_LAPB":                                  "syscall",
+	"syscall.ARPHRD_LOCALTLK":                              "syscall",
+	"syscall.ARPHRD_LOOPBACK":                              "syscall",
+	"syscall.ARPHRD_METRICOM":                              "syscall",
+	"syscall.ARPHRD_NETROM":                                "syscall",
+	"syscall.ARPHRD_NONE":                                  "syscall",
+	"syscall.ARPHRD_PIMREG":                                "syscall",
+	"syscall.ARPHRD_PPP":                                   "syscall",
+	"syscall.ARPHRD_PRONET":                                "syscall",
+	"syscall.ARPHRD_RAWHDLC":                               "syscall",
+	"syscall.ARPHRD_ROSE":                                  "syscall",
+	"syscall.ARPHRD_RSRVD":                                 "syscall",
+	"syscall.ARPHRD_SIT":                                   "syscall",
+	"syscall.ARPHRD_SKIP":                                  "syscall",
+	"syscall.ARPHRD_SLIP":                                  "syscall",
+	"syscall.ARPHRD_SLIP6":                                 "syscall",
+	"syscall.ARPHRD_STRIP":                                 "syscall",
+	"syscall.ARPHRD_TUNNEL":                                "syscall",
+	"syscall.ARPHRD_TUNNEL6":                               "syscall",
+	"syscall.ARPHRD_VOID":                                  "syscall",
+	"syscall.ARPHRD_X25":                                   "syscall",
+	"syscall.AUTHTYPE_CLIENT":                              "syscall",
+	"syscall.AUTHTYPE_SERVER":                              "syscall",
+	"syscall.Accept":                                       "syscall",
+	"syscall.Accept4":                                      "syscall",
+	"syscall.AcceptEx":                                     "syscall",
+	"syscall.Access":                                       "syscall",
+	"syscall.Acct":                                         "syscall",
+	"syscall.AddrinfoW":                                    "syscall",
+	"syscall.Adjtime":                                      "syscall",
+	"syscall.Adjtimex":                                     "syscall",
+	"syscall.AttachLsf":                                    "syscall",
+	"syscall.B0":                                           "syscall",
+	"syscall.B1000000":                                     "syscall",
+	"syscall.B110":                                         "syscall",
+	"syscall.B115200":                                      "syscall",
+	"syscall.B1152000":                                     "syscall",
+	"syscall.B1200":                                        "syscall",
+	"syscall.B134":                                         "syscall",
+	"syscall.B14400":                                       "syscall",
+	"syscall.B150":                                         "syscall",
+	"syscall.B1500000":                                     "syscall",
+	"syscall.B1800":                                        "syscall",
+	"syscall.B19200":                                       "syscall",
+	"syscall.B200":                                         "syscall",
+	"syscall.B2000000":                                     "syscall",
+	"syscall.B230400":                                      "syscall",
+	"syscall.B2400":                                        "syscall",
+	"syscall.B2500000":                                     "syscall",
+	"syscall.B28800":                                       "syscall",
+	"syscall.B300":                                         "syscall",
+	"syscall.B3000000":                                     "syscall",
+	"syscall.B3500000":                                     "syscall",
+	"syscall.B38400":                                       "syscall",
+	"syscall.B4000000":                                     "syscall",
+	"syscall.B460800":                                      "syscall",
+	"syscall.B4800":                                        "syscall",
+	"syscall.B50":                                          "syscall",
+	"syscall.B500000":                                      "syscall",
+	"syscall.B57600":                                       "syscall",
+	"syscall.B576000":                                      "syscall",
+	"syscall.B600":                                         "syscall",
+	"syscall.B7200":                                        "syscall",
+	"syscall.B75":                                          "syscall",
+	"syscall.B76800":                                       "syscall",
+	"syscall.B921600":                                      "syscall",
+	"syscall.B9600":                                        "syscall",
+	"syscall.BASE_PROTOCOL":                                "syscall",
+	"syscall.BIOCFEEDBACK":                                 "syscall",
+	"syscall.BIOCFLUSH":                                    "syscall",
+	"syscall.BIOCGBLEN":                                    "syscall",
+	"syscall.BIOCGDIRECTION":                               "syscall",
+	"syscall.BIOCGDIRFILT":                                 "syscall",
+	"syscall.BIOCGDLT":                                     "syscall",
+	"syscall.BIOCGDLTLIST":                                 "syscall",
+	"syscall.BIOCGETBUFMODE":                               "syscall",
+	"syscall.BIOCGETIF":                                    "syscall",
+	"syscall.BIOCGETZMAX":                                  "syscall",
+	"syscall.BIOCGFEEDBACK":                                "syscall",
+	"syscall.BIOCGFILDROP":                                 "syscall",
+	"syscall.BIOCGHDRCMPLT":                                "syscall",
+	"syscall.BIOCGRSIG":                                    "syscall",
+	"syscall.BIOCGRTIMEOUT":                                "syscall",
+	"syscall.BIOCGSEESENT":                                 "syscall",
+	"syscall.BIOCGSTATS":                                   "syscall",
+	"syscall.BIOCGSTATSOLD":                                "syscall",
+	"syscall.BIOCGTSTAMP":                                  "syscall",
+	"syscall.BIOCIMMEDIATE":                                "syscall",
+	"syscall.BIOCLOCK":                                     "syscall",
+	"syscall.BIOCPROMISC":                                  "syscall",
+	"syscall.BIOCROTZBUF":                                  "syscall",
+	"syscall.BIOCSBLEN":                                    "syscall",
+	"syscall.BIOCSDIRECTION":                               "syscall",
+	"syscall.BIOCSDIRFILT":                                 "syscall",
+	"syscall.BIOCSDLT":                                     "syscall",
+	"syscall.BIOCSETBUFMODE":                               "syscall",
+	"syscall.BIOCSETF":                                     "syscall",
+	"syscall.BIOCSETFNR":                                   "syscall",
+	"syscall.BIOCSETIF":                                    "syscall",
+	"syscall.BIOCSETWF":                                    "syscall",
+	"syscall.BIOCSETZBUF":                                  "syscall",
+	"syscall.BIOCSFEEDBACK":                                "syscall",
+	"syscall.BIOCSFILDROP":                                 "syscall",
+	"syscall.BIOCSHDRCMPLT":                                "syscall",
+	"syscall.BIOCSRSIG":                                    "syscall",
+	"syscall.BIOCSRTIMEOUT":                                "syscall",
+	"syscall.BIOCSSEESENT":                                 "syscall",
+	"syscall.BIOCSTCPF":                                    "syscall",
+	"syscall.BIOCSTSTAMP":                                  "syscall",
+	"syscall.BIOCSUDPF":                                    "syscall",
+	"syscall.BIOCVERSION":                                  "syscall",
+	"syscall.BPF_A":                                        "syscall",
+	"syscall.BPF_ABS":                                      "syscall",
+	"syscall.BPF_ADD":                                      "syscall",
+	"syscall.BPF_ALIGNMENT":                                "syscall",
+	"syscall.BPF_ALIGNMENT32":                              "syscall",
+	"syscall.BPF_ALU":                                      "syscall",
+	"syscall.BPF_AND":                                      "syscall",
+	"syscall.BPF_B":                                        "syscall",
+	"syscall.BPF_BUFMODE_BUFFER":                           "syscall",
+	"syscall.BPF_BUFMODE_ZBUF":                             "syscall",
+	"syscall.BPF_DFLTBUFSIZE":                              "syscall",
+	"syscall.BPF_DIRECTION_IN":                             "syscall",
+	"syscall.BPF_DIRECTION_OUT":                            "syscall",
+	"syscall.BPF_DIV":                                      "syscall",
+	"syscall.BPF_H":                                        "syscall",
+	"syscall.BPF_IMM":                                      "syscall",
+	"syscall.BPF_IND":                                      "syscall",
+	"syscall.BPF_JA":                                       "syscall",
+	"syscall.BPF_JEQ":                                      "syscall",
+	"syscall.BPF_JGE":                                      "syscall",
+	"syscall.BPF_JGT":                                      "syscall",
+	"syscall.BPF_JMP":                                      "syscall",
+	"syscall.BPF_JSET":                                     "syscall",
+	"syscall.BPF_K":                                        "syscall",
+	"syscall.BPF_LD":                                       "syscall",
+	"syscall.BPF_LDX":                                      "syscall",
+	"syscall.BPF_LEN":                                      "syscall",
+	"syscall.BPF_LSH":                                      "syscall",
+	"syscall.BPF_MAJOR_VERSION":                            "syscall",
+	"syscall.BPF_MAXBUFSIZE":                               "syscall",
+	"syscall.BPF_MAXINSNS":                                 "syscall",
+	"syscall.BPF_MEM":                                      "syscall",
+	"syscall.BPF_MEMWORDS":                                 "syscall",
+	"syscall.BPF_MINBUFSIZE":                               "syscall",
+	"syscall.BPF_MINOR_VERSION":                            "syscall",
+	"syscall.BPF_MISC":                                     "syscall",
+	"syscall.BPF_MSH":                                      "syscall",
+	"syscall.BPF_MUL":                                      "syscall",
+	"syscall.BPF_NEG":                                      "syscall",
+	"syscall.BPF_OR":                                       "syscall",
+	"syscall.BPF_RELEASE":                                  "syscall",
+	"syscall.BPF_RET":                                      "syscall",
+	"syscall.BPF_RSH":                                      "syscall",
+	"syscall.BPF_ST":                                       "syscall",
+	"syscall.BPF_STX":                                      "syscall",
+	"syscall.BPF_SUB":                                      "syscall",
+	"syscall.BPF_TAX":                                      "syscall",
+	"syscall.BPF_TXA":                                      "syscall",
+	"syscall.BPF_T_BINTIME":                                "syscall",
+	"syscall.BPF_T_BINTIME_FAST":                           "syscall",
+	"syscall.BPF_T_BINTIME_MONOTONIC":                      "syscall",
+	"syscall.BPF_T_BINTIME_MONOTONIC_FAST":                 "syscall",
+	"syscall.BPF_T_FAST":                                   "syscall",
+	"syscall.BPF_T_FLAG_MASK":                              "syscall",
+	"syscall.BPF_T_FORMAT_MASK":                            "syscall",
+	"syscall.BPF_T_MICROTIME":                              "syscall",
+	"syscall.BPF_T_MICROTIME_FAST":                         "syscall",
+	"syscall.BPF_T_MICROTIME_MONOTONIC":                    "syscall",
+	"syscall.BPF_T_MICROTIME_MONOTONIC_FAST":               "syscall",
+	"syscall.BPF_T_MONOTONIC":                              "syscall",
+	"syscall.BPF_T_MONOTONIC_FAST":                         "syscall",
+	"syscall.BPF_T_NANOTIME":                               "syscall",
+	"syscall.BPF_T_NANOTIME_FAST":                          "syscall",
+	"syscall.BPF_T_NANOTIME_MONOTONIC":                     "syscall",
+	"syscall.BPF_T_NANOTIME_MONOTONIC_FAST":                "syscall",
+	"syscall.BPF_T_NONE":                                   "syscall",
+	"syscall.BPF_T_NORMAL":                                 "syscall",
+	"syscall.BPF_W":                                        "syscall",
+	"syscall.BPF_X":                                        "syscall",
+	"syscall.BRKINT":                                       "syscall",
+	"syscall.Bind":                                         "syscall",
+	"syscall.BindToDevice":                                 "syscall",
+	"syscall.BpfBuflen":                                    "syscall",
+	"syscall.BpfDatalink":                                  "syscall",
+	"syscall.BpfHdr":                                       "syscall",
+	"syscall.BpfHeadercmpl":                                "syscall",
+	"syscall.BpfInsn":                                      "syscall",
+	"syscall.BpfInterface":                                 "syscall",
+	"syscall.BpfJump":                                      "syscall",
+	"syscall.BpfProgram":                                   "syscall",
+	"syscall.BpfStat":                                      "syscall",
+	"syscall.BpfStats":                                     "syscall",
+	"syscall.BpfStmt":                                      "syscall",
+	"syscall.BpfTimeout":                                   "syscall",
+	"syscall.BpfTimeval":                                   "syscall",
+	"syscall.BpfVersion":                                   "syscall",
+	"syscall.BpfZbuf":                                      "syscall",
+	"syscall.BpfZbufHeader":                                "syscall",
+	"syscall.ByHandleFileInformation":                      "syscall",
+	"syscall.BytePtrFromString":                            "syscall",
+	"syscall.ByteSliceFromString":                          "syscall",
+	"syscall.CCR0_FLUSH":                                   "syscall",
+	"syscall.CERT_CHAIN_POLICY_AUTHENTICODE":               "syscall",
+	"syscall.CERT_CHAIN_POLICY_AUTHENTICODE_TS":            "syscall",
+	"syscall.CERT_CHAIN_POLICY_BASE":                       "syscall",
+	"syscall.CERT_CHAIN_POLICY_BASIC_CONSTRAINTS":          "syscall",
+	"syscall.CERT_CHAIN_POLICY_EV":                         "syscall",
+	"syscall.CERT_CHAIN_POLICY_MICROSOFT_ROOT":             "syscall",
+	"syscall.CERT_CHAIN_POLICY_NT_AUTH":                    "syscall",
+	"syscall.CERT_CHAIN_POLICY_SSL":                        "syscall",
+	"syscall.CERT_E_CN_NO_MATCH":                           "syscall",
+	"syscall.CERT_E_EXPIRED":                               "syscall",
+	"syscall.CERT_E_PURPOSE":                               "syscall",
+	"syscall.CERT_E_ROLE":                                  "syscall",
+	"syscall.CERT_E_UNTRUSTEDROOT":                         "syscall",
+	"syscall.CERT_STORE_ADD_ALWAYS":                        "syscall",
+	"syscall.CERT_STORE_DEFER_CLOSE_UNTIL_LAST_FREE_FLAG":  "syscall",
+	"syscall.CERT_STORE_PROV_MEMORY":                       "syscall",
+	"syscall.CERT_TRUST_HAS_EXCLUDED_NAME_CONSTRAINT":      "syscall",
+	"syscall.CERT_TRUST_HAS_NOT_DEFINED_NAME_CONSTRAINT":   "syscall",
+	"syscall.CERT_TRUST_HAS_NOT_PERMITTED_NAME_CONSTRAINT": "syscall",
+	"syscall.CERT_TRUST_HAS_NOT_SUPPORTED_CRITICAL_EXT":    "syscall",
+	"syscall.CERT_TRUST_HAS_NOT_SUPPORTED_NAME_CONSTRAINT": "syscall",
+	"syscall.CERT_TRUST_INVALID_BASIC_CONSTRAINTS":         "syscall",
+	"syscall.CERT_TRUST_INVALID_EXTENSION":                 "syscall",
+	"syscall.CERT_TRUST_INVALID_NAME_CONSTRAINTS":          "syscall",
+	"syscall.CERT_TRUST_INVALID_POLICY_CONSTRAINTS":        "syscall",
+	"syscall.CERT_TRUST_IS_CYCLIC":                         "syscall",
+	"syscall.CERT_TRUST_IS_EXPLICIT_DISTRUST":              "syscall",
+	"syscall.CERT_TRUST_IS_NOT_SIGNATURE_VALID":            "syscall",
+	"syscall.CERT_TRUST_IS_NOT_TIME_VALID":                 "syscall",
+	"syscall.CERT_TRUST_IS_NOT_VALID_FOR_USAGE":            "syscall",
+	"syscall.CERT_TRUST_IS_OFFLINE_REVOCATION":             "syscall",
+	"syscall.CERT_TRUST_IS_REVOKED":                        "syscall",
+	"syscall.CERT_TRUST_IS_UNTRUSTED_ROOT":                 "syscall",
+	"syscall.CERT_TRUST_NO_ERROR":                          "syscall",
+	"syscall.CERT_TRUST_NO_ISSUANCE_CHAIN_POLICY":          "syscall",
+	"syscall.CERT_TRUST_REVOCATION_STATUS_UNKNOWN":         "syscall",
+	"syscall.CFLUSH":                                       "syscall",
+	"syscall.CLOCAL":                                       "syscall",
+	"syscall.CLONE_CHILD_CLEARTID":                         "syscall",
+	"syscall.CLONE_CHILD_SETTID":                           "syscall",
+	"syscall.CLONE_DETACHED":                               "syscall",
+	"syscall.CLONE_FILES":                                  "syscall",
+	"syscall.CLONE_FS":                                     "syscall",
+	"syscall.CLONE_IO":                                     "syscall",
+	"syscall.CLONE_NEWIPC":                                 "syscall",
+	"syscall.CLONE_NEWNET":                                 "syscall",
+	"syscall.CLONE_NEWNS":                                  "syscall",
+	"syscall.CLONE_NEWPID":                                 "syscall",
+	"syscall.CLONE_NEWUSER":                                "syscall",
+	"syscall.CLONE_NEWUTS":                                 "syscall",
+	"syscall.CLONE_PARENT":                                 "syscall",
+	"syscall.CLONE_PARENT_SETTID":                          "syscall",
+	"syscall.CLONE_PTRACE":                                 "syscall",
+	"syscall.CLONE_SETTLS":                                 "syscall",
+	"syscall.CLONE_SIGHAND":                                "syscall",
+	"syscall.CLONE_SYSVSEM":                                "syscall",
+	"syscall.CLONE_THREAD":                                 "syscall",
+	"syscall.CLONE_UNTRACED":                               "syscall",
+	"syscall.CLONE_VFORK":                                  "syscall",
+	"syscall.CLONE_VM":                                     "syscall",
+	"syscall.CPUID_CFLUSH":                                 "syscall",
+	"syscall.CREAD":                                        "syscall",
+	"syscall.CREATE_ALWAYS":                                "syscall",
+	"syscall.CREATE_NEW":                                   "syscall",
+	"syscall.CREATE_NEW_PROCESS_GROUP":                     "syscall",
+	"syscall.CREATE_UNICODE_ENVIRONMENT":                   "syscall",
+	"syscall.CRYPT_DEFAULT_CONTAINER_OPTIONAL":             "syscall",
+	"syscall.CRYPT_DELETEKEYSET":                           "syscall",
+	"syscall.CRYPT_MACHINE_KEYSET":                         "syscall",
+	"syscall.CRYPT_NEWKEYSET":                              "syscall",
+	"syscall.CRYPT_SILENT":                                 "syscall",
+	"syscall.CRYPT_VERIFYCONTEXT":                          "syscall",
+	"syscall.CS5":                                          "syscall",
+	"syscall.CS6":                                          "syscall",
+	"syscall.CS7":                                          "syscall",
+	"syscall.CS8":                                          "syscall",
+	"syscall.CSIZE":                                        "syscall",
+	"syscall.CSTART":                                       "syscall",
+	"syscall.CSTATUS":                                      "syscall",
+	"syscall.CSTOP":                                        "syscall",
+	"syscall.CSTOPB":                                       "syscall",
+	"syscall.CSUSP":                                        "syscall",
+	"syscall.CTL_MAXNAME":                                  "syscall",
+	"syscall.CTL_NET":                                      "syscall",
+	"syscall.CTL_QUERY":                                    "syscall",
+	"syscall.CTRL_BREAK_EVENT":                             "syscall",
+	"syscall.CTRL_C_EVENT":                                 "syscall",
+	"syscall.CancelIo":                                     "syscall",
+	"syscall.CancelIoEx":                                   "syscall",
+	"syscall.CertAddCertificateContextToStore":             "syscall",
+	"syscall.CertChainContext":                             "syscall",
+	"syscall.CertChainElement":                             "syscall",
+	"syscall.CertChainPara":                                "syscall",
+	"syscall.CertChainPolicyPara":                          "syscall",
+	"syscall.CertChainPolicyStatus":                        "syscall",
+	"syscall.CertCloseStore":                               "syscall",
+	"syscall.CertContext":                                  "syscall",
+	"syscall.CertCreateCertificateContext":                 "syscall",
+	"syscall.CertEnhKeyUsage":                              "syscall",
+	"syscall.CertEnumCertificatesInStore":                  "syscall",
+	"syscall.CertFreeCertificateChain":                     "syscall",
+	"syscall.CertFreeCertificateContext":                   "syscall",
+	"syscall.CertGetCertificateChain":                      "syscall",
+	"syscall.CertOpenStore":                                "syscall",
+	"syscall.CertOpenSystemStore":                          "syscall",
+	"syscall.CertRevocationInfo":                           "syscall",
+	"syscall.CertSimpleChain":                              "syscall",
+	"syscall.CertTrustStatus":                              "syscall",
+	"syscall.CertUsageMatch":                               "syscall",
+	"syscall.CertVerifyCertificateChainPolicy":             "syscall",
+	"syscall.Chdir":                                        "syscall",
+	"syscall.CheckBpfVersion":                              "syscall",
+	"syscall.Chflags":                                      "syscall",
+	"syscall.Chmod":                                        "syscall",
+	"syscall.Chown":                                        "syscall",
+	"syscall.Chroot":                                       "syscall",
+	"syscall.Clearenv":                                     "syscall",
+	"syscall.Close":                                        "syscall",
+	"syscall.CloseHandle":                                  "syscall",
+	"syscall.CloseOnExec":                                  "syscall",
+	"syscall.Closesocket":                                  "syscall",
+	"syscall.CmsgLen":                                      "syscall",
+	"syscall.CmsgSpace":                                    "syscall",
+	"syscall.Cmsghdr":                                      "syscall",
+	"syscall.CommandLineToArgv":                            "syscall",
+	"syscall.ComputerName":                                 "syscall",
+	"syscall.Connect":                                      "syscall",
+	"syscall.ConnectEx":                                    "syscall",
+	"syscall.ConvertSidToStringSid":                        "syscall",
+	"syscall.ConvertStringSidToSid":                        "syscall",
+	"syscall.CopySid":                                      "syscall",
+	"syscall.Creat":                                        "syscall",
+	"syscall.CreateDirectory":                              "syscall",
+	"syscall.CreateFile":                                   "syscall",
+	"syscall.CreateFileMapping":                            "syscall",
+	"syscall.CreateIoCompletionPort":                       "syscall",
+	"syscall.CreatePipe":                                   "syscall",
+	"syscall.CreateProcess":                                "syscall",
+	"syscall.Credential":                                   "syscall",
+	"syscall.CryptAcquireContext":                          "syscall",
+	"syscall.CryptGenRandom":                               "syscall",
+	"syscall.CryptReleaseContext":                          "syscall",
+	"syscall.DIOCBSFLUSH":                                  "syscall",
+	"syscall.DIOCOSFPFLUSH":                                "syscall",
+	"syscall.DLL":                                          "syscall",
+	"syscall.DLLError":                                     "syscall",
+	"syscall.DLT_A429":                                     "syscall",
+	"syscall.DLT_A653_ICM":                                 "syscall",
+	"syscall.DLT_AIRONET_HEADER":                           "syscall",
+	"syscall.DLT_AOS":                                      "syscall",
+	"syscall.DLT_APPLE_IP_OVER_IEEE1394":                   "syscall",
+	"syscall.DLT_ARCNET":                                   "syscall",
+	"syscall.DLT_ARCNET_LINUX":                             "syscall",
+	"syscall.DLT_ATM_CLIP":                                 "syscall",
+	"syscall.DLT_ATM_RFC1483":                              "syscall",
+	"syscall.DLT_AURORA":                                   "syscall",
+	"syscall.DLT_AX25":                                     "syscall",
+	"syscall.DLT_AX25_KISS":                                "syscall",
+	"syscall.DLT_BACNET_MS_TP":                             "syscall",
+	"syscall.DLT_BLUETOOTH_HCI_H4":                         "syscall",
+	"syscall.DLT_BLUETOOTH_HCI_H4_WITH_PHDR":               "syscall",
+	"syscall.DLT_CAN20B":                                   "syscall",
+	"syscall.DLT_CAN_SOCKETCAN":                            "syscall",
+	"syscall.DLT_CHAOS":                                    "syscall",
+	"syscall.DLT_CHDLC":                                    "syscall",
+	"syscall.DLT_CISCO_IOS":                                "syscall",
+	"syscall.DLT_C_HDLC":                                   "syscall",
+	"syscall.DLT_C_HDLC_WITH_DIR":                          "syscall",
+	"syscall.DLT_DBUS":                                     "syscall",
+	"syscall.DLT_DECT":                                     "syscall",
+	"syscall.DLT_DOCSIS":                                   "syscall",
+	"syscall.DLT_DVB_CI":                                   "syscall",
+	"syscall.DLT_ECONET":                                   "syscall",
+	"syscall.DLT_EN10MB":                                   "syscall",
+	"syscall.DLT_EN3MB":                                    "syscall",
+	"syscall.DLT_ENC":                                      "syscall",
+	"syscall.DLT_ERF":                                      "syscall",
+	"syscall.DLT_ERF_ETH":                                  "syscall",
+	"syscall.DLT_ERF_POS":                                  "syscall",
+	"syscall.DLT_FC_2":                                     "syscall",
+	"syscall.DLT_FC_2_WITH_FRAME_DELIMS":                   "syscall",
+	"syscall.DLT_FDDI":                                     "syscall",
+	"syscall.DLT_FLEXRAY":                                  "syscall",
+	"syscall.DLT_FRELAY":                                   "syscall",
+	"syscall.DLT_FRELAY_WITH_DIR":                          "syscall",
+	"syscall.DLT_GCOM_SERIAL":                              "syscall",
+	"syscall.DLT_GCOM_T1E1":                                "syscall",
+	"syscall.DLT_GPF_F":                                    "syscall",
+	"syscall.DLT_GPF_T":                                    "syscall",
+	"syscall.DLT_GPRS_LLC":                                 "syscall",
+	"syscall.DLT_GSMTAP_ABIS":                              "syscall",
+	"syscall.DLT_GSMTAP_UM":                                "syscall",
+	"syscall.DLT_HDLC":                                     "syscall",
+	"syscall.DLT_HHDLC":                                    "syscall",
+	"syscall.DLT_HIPPI":                                    "syscall",
+	"syscall.DLT_IBM_SN":                                   "syscall",
+	"syscall.DLT_IBM_SP":                                   "syscall",
+	"syscall.DLT_IEEE802":                                  "syscall",
+	"syscall.DLT_IEEE802_11":                               "syscall",
+	"syscall.DLT_IEEE802_11_RADIO":                         "syscall",
+	"syscall.DLT_IEEE802_11_RADIO_AVS":                     "syscall",
+	"syscall.DLT_IEEE802_15_4":                             "syscall",
+	"syscall.DLT_IEEE802_15_4_LINUX":                       "syscall",
+	"syscall.DLT_IEEE802_15_4_NOFCS":                       "syscall",
+	"syscall.DLT_IEEE802_15_4_NONASK_PHY":                  "syscall",
+	"syscall.DLT_IEEE802_16_MAC_CPS":                       "syscall",
+	"syscall.DLT_IEEE802_16_MAC_CPS_RADIO":                 "syscall",
+	"syscall.DLT_IPFILTER":                                 "syscall",
+	"syscall.DLT_IPMB":                                     "syscall",
+	"syscall.DLT_IPMB_LINUX":                               "syscall",
+	"syscall.DLT_IPNET":                                    "syscall",
+	"syscall.DLT_IPOIB":                                    "syscall",
+	"syscall.DLT_IPV4":                                     "syscall",
+	"syscall.DLT_IPV6":                                     "syscall",
+	"syscall.DLT_IP_OVER_FC":                               "syscall",
+	"syscall.DLT_JUNIPER_ATM1":                             "syscall",
+	"syscall.DLT_JUNIPER_ATM2":                             "syscall",
+	"syscall.DLT_JUNIPER_ATM_CEMIC":                        "syscall",
+	"syscall.DLT_JUNIPER_CHDLC":                            "syscall",
+	"syscall.DLT_JUNIPER_ES":                               "syscall",
+	"syscall.DLT_JUNIPER_ETHER":                            "syscall",
+	"syscall.DLT_JUNIPER_FIBRECHANNEL":                     "syscall",
+	"syscall.DLT_JUNIPER_FRELAY":                           "syscall",
+	"syscall.DLT_JUNIPER_GGSN":                             "syscall",
+	"syscall.DLT_JUNIPER_ISM":                              "syscall",
+	"syscall.DLT_JUNIPER_MFR":                              "syscall",
+	"syscall.DLT_JUNIPER_MLFR":                             "syscall",
+	"syscall.DLT_JUNIPER_MLPPP":                            "syscall",
+	"syscall.DLT_JUNIPER_MONITOR":                          "syscall",
+	"syscall.DLT_JUNIPER_PIC_PEER":                         "syscall",
+	"syscall.DLT_JUNIPER_PPP":                              "syscall",
+	"syscall.DLT_JUNIPER_PPPOE":                            "syscall",
+	"syscall.DLT_JUNIPER_PPPOE_ATM":                        "syscall",
+	"syscall.DLT_JUNIPER_SERVICES":                         "syscall",
+	"syscall.DLT_JUNIPER_SRX_E2E":                          "syscall",
+	"syscall.DLT_JUNIPER_ST":                               "syscall",
+	"syscall.DLT_JUNIPER_VP":                               "syscall",
+	"syscall.DLT_JUNIPER_VS":                               "syscall",
+	"syscall.DLT_LAPB_WITH_DIR":                            "syscall",
+	"syscall.DLT_LAPD":                                     "syscall",
+	"syscall.DLT_LIN":                                      "syscall",
+	"syscall.DLT_LINUX_EVDEV":                              "syscall",
+	"syscall.DLT_LINUX_IRDA":                               "syscall",
+	"syscall.DLT_LINUX_LAPD":                               "syscall",
+	"syscall.DLT_LINUX_PPP_WITHDIRECTION":                  "syscall",
+	"syscall.DLT_LINUX_SLL":                                "syscall",
+	"syscall.DLT_LOOP":                                     "syscall",
+	"syscall.DLT_LTALK":                                    "syscall",
+	"syscall.DLT_MATCHING_MAX":                             "syscall",
+	"syscall.DLT_MATCHING_MIN":                             "syscall",
+	"syscall.DLT_MFR":                                      "syscall",
+	"syscall.DLT_MOST":                                     "syscall",
+	"syscall.DLT_MPEG_2_TS":                                "syscall",
+	"syscall.DLT_MPLS":                                     "syscall",
+	"syscall.DLT_MTP2":                                     "syscall",
+	"syscall.DLT_MTP2_WITH_PHDR":                           "syscall",
+	"syscall.DLT_MTP3":                                     "syscall",
+	"syscall.DLT_MUX27010":                                 "syscall",
+	"syscall.DLT_NETANALYZER":                              "syscall",
+	"syscall.DLT_NETANALYZER_TRANSPARENT":                  "syscall",
+	"syscall.DLT_NFC_LLCP":                                 "syscall",
+	"syscall.DLT_NFLOG":                                    "syscall",
+	"syscall.DLT_NG40":                                     "syscall",
+	"syscall.DLT_NULL":                                     "syscall",
+	"syscall.DLT_PCI_EXP":                                  "syscall",
+	"syscall.DLT_PFLOG":                                    "syscall",
+	"syscall.DLT_PFSYNC":                                   "syscall",
+	"syscall.DLT_PPI":                                      "syscall",
+	"syscall.DLT_PPP":                                      "syscall",
+	"syscall.DLT_PPP_BSDOS":                                "syscall",
+	"syscall.DLT_PPP_ETHER":                                "syscall",
+	"syscall.DLT_PPP_PPPD":                                 "syscall",
+	"syscall.DLT_PPP_SERIAL":                               "syscall",
+	"syscall.DLT_PPP_WITH_DIR":                             "syscall",
+	"syscall.DLT_PPP_WITH_DIRECTION":                       "syscall",
+	"syscall.DLT_PRISM_HEADER":                             "syscall",
+	"syscall.DLT_PRONET":                                   "syscall",
+	"syscall.DLT_RAIF1":                                    "syscall",
+	"syscall.DLT_RAW":                                      "syscall",
+	"syscall.DLT_RAWAF_MASK":                               "syscall",
+	"syscall.DLT_RIO":                                      "syscall",
+	"syscall.DLT_SCCP":                                     "syscall",
+	"syscall.DLT_SITA":                                     "syscall",
+	"syscall.DLT_SLIP":                                     "syscall",
+	"syscall.DLT_SLIP_BSDOS":                               "syscall",
+	"syscall.DLT_STANAG_5066_D_PDU":                        "syscall",
+	"syscall.DLT_SUNATM":                                   "syscall",
+	"syscall.DLT_SYMANTEC_FIREWALL":                        "syscall",
+	"syscall.DLT_TZSP":                                     "syscall",
+	"syscall.DLT_USB":                                      "syscall",
+	"syscall.DLT_USB_LINUX":                                "syscall",
+	"syscall.DLT_USB_LINUX_MMAPPED":                        "syscall",
+	"syscall.DLT_USER0":                                    "syscall",
+	"syscall.DLT_USER1":                                    "syscall",
+	"syscall.DLT_USER10":                                   "syscall",
+	"syscall.DLT_USER11":                                   "syscall",
+	"syscall.DLT_USER12":                                   "syscall",
+	"syscall.DLT_USER13":                                   "syscall",
+	"syscall.DLT_USER14":                                   "syscall",
+	"syscall.DLT_USER15":                                   "syscall",
+	"syscall.DLT_USER2":                                    "syscall",
+	"syscall.DLT_USER3":                                    "syscall",
+	"syscall.DLT_USER4":                                    "syscall",
+	"syscall.DLT_USER5":                                    "syscall",
+	"syscall.DLT_USER6":                                    "syscall",
+	"syscall.DLT_USER7":                                    "syscall",
+	"syscall.DLT_USER8":                                    "syscall",
+	"syscall.DLT_USER9":                                    "syscall",
+	"syscall.DLT_WIHART":                                   "syscall",
+	"syscall.DLT_X2E_SERIAL":                               "syscall",
+	"syscall.DLT_X2E_XORAYA":                               "syscall",
+	"syscall.DNSMXData":                                    "syscall",
+	"syscall.DNSPTRData":                                   "syscall",
+	"syscall.DNSRecord":                                    "syscall",
+	"syscall.DNSSRVData":                                   "syscall",
+	"syscall.DNSTXTData":                                   "syscall",
+	"syscall.DNS_TYPE_A":                                   "syscall",
+	"syscall.DNS_TYPE_A6":                                  "syscall",
+	"syscall.DNS_TYPE_AAAA":                                "syscall",
+	"syscall.DNS_TYPE_ADDRS":                               "syscall",
+	"syscall.DNS_TYPE_AFSDB":                               "syscall",
+	"syscall.DNS_TYPE_ALL":                                 "syscall",
+	"syscall.DNS_TYPE_ANY":                                 "syscall",
+	"syscall.DNS_TYPE_ATMA":                                "syscall",
+	"syscall.DNS_TYPE_AXFR":                                "syscall",
+	"syscall.DNS_TYPE_CERT":                                "syscall",
+	"syscall.DNS_TYPE_CNAME":                               "syscall",
+	"syscall.DNS_TYPE_DHCID":                               "syscall",
+	"syscall.DNS_TYPE_DNAME":                               "syscall",
+	"syscall.DNS_TYPE_DNSKEY":                              "syscall",
+	"syscall.DNS_TYPE_DS":                                  "syscall",
+	"syscall.DNS_TYPE_EID":                                 "syscall",
+	"syscall.DNS_TYPE_GID":                                 "syscall",
+	"syscall.DNS_TYPE_GPOS":                                "syscall",
+	"syscall.DNS_TYPE_HINFO":                               "syscall",
+	"syscall.DNS_TYPE_ISDN":                                "syscall",
+	"syscall.DNS_TYPE_IXFR":                                "syscall",
+	"syscall.DNS_TYPE_KEY":                                 "syscall",
+	"syscall.DNS_TYPE_KX":                                  "syscall",
+	"syscall.DNS_TYPE_LOC":                                 "syscall",
+	"syscall.DNS_TYPE_MAILA":                               "syscall",
+	"syscall.DNS_TYPE_MAILB":                               "syscall",
+	"syscall.DNS_TYPE_MB":                                  "syscall",
+	"syscall.DNS_TYPE_MD":                                  "syscall",
+	"syscall.DNS_TYPE_MF":                                  "syscall",
+	"syscall.DNS_TYPE_MG":                                  "syscall",
+	"syscall.DNS_TYPE_MINFO":                               "syscall",
+	"syscall.DNS_TYPE_MR":                                  "syscall",
+	"syscall.DNS_TYPE_MX":                                  "syscall",
+	"syscall.DNS_TYPE_NAPTR":                               "syscall",
+	"syscall.DNS_TYPE_NBSTAT":                              "syscall",
+	"syscall.DNS_TYPE_NIMLOC":                              "syscall",
+	"syscall.DNS_TYPE_NS":                                  "syscall",
+	"syscall.DNS_TYPE_NSAP":                                "syscall",
+	"syscall.DNS_TYPE_NSAPPTR":                             "syscall",
+	"syscall.DNS_TYPE_NSEC":                                "syscall",
+	"syscall.DNS_TYPE_NULL":                                "syscall",
+	"syscall.DNS_TYPE_NXT":                                 "syscall",
+	"syscall.DNS_TYPE_OPT":                                 "syscall",
+	"syscall.DNS_TYPE_PTR":                                 "syscall",
+	"syscall.DNS_TYPE_PX":                                  "syscall",
+	"syscall.DNS_TYPE_RP":                                  "syscall",
+	"syscall.DNS_TYPE_RRSIG":                               "syscall",
+	"syscall.DNS_TYPE_RT":                                  "syscall",
+	"syscall.DNS_TYPE_SIG":                                 "syscall",
+	"syscall.DNS_TYPE_SINK":                                "syscall",
+	"syscall.DNS_TYPE_SOA":                                 "syscall",
+	"syscall.DNS_TYPE_SRV":                                 "syscall",
+	"syscall.DNS_TYPE_TEXT":                                "syscall",
+	"syscall.DNS_TYPE_TKEY":                                "syscall",
+	"syscall.DNS_TYPE_TSIG":                                "syscall",
+	"syscall.DNS_TYPE_UID":                                 "syscall",
+	"syscall.DNS_TYPE_UINFO":                               "syscall",
+	"syscall.DNS_TYPE_UNSPEC":                              "syscall",
+	"syscall.DNS_TYPE_WINS":                                "syscall",
+	"syscall.DNS_TYPE_WINSR":                               "syscall",
+	"syscall.DNS_TYPE_WKS":                                 "syscall",
+	"syscall.DNS_TYPE_X25":                                 "syscall",
+	"syscall.DT_BLK":                                       "syscall",
+	"syscall.DT_CHR":                                       "syscall",
+	"syscall.DT_DIR":                                       "syscall",
+	"syscall.DT_FIFO":                                      "syscall",
+	"syscall.DT_LNK":                                       "syscall",
+	"syscall.DT_REG":                                       "syscall",
+	"syscall.DT_SOCK":                                      "syscall",
+	"syscall.DT_UNKNOWN":                                   "syscall",
+	"syscall.DT_WHT":                                       "syscall",
+	"syscall.DUPLICATE_CLOSE_SOURCE":                       "syscall",
+	"syscall.DUPLICATE_SAME_ACCESS":                        "syscall",
+	"syscall.DeleteFile":                                   "syscall",
+	"syscall.DetachLsf":                                    "syscall",
+	"syscall.Dirent":                                       "syscall",
+	"syscall.DnsQuery":                                     "syscall",
+	"syscall.DnsRecordListFree":                            "syscall",
+	"syscall.Dup":                                          "syscall",
+	"syscall.Dup2":                                         "syscall",
+	"syscall.Dup3":                                         "syscall",
+	"syscall.DuplicateHandle":                              "syscall",
+	"syscall.E2BIG":                                        "syscall",
+	"syscall.EACCES":                                       "syscall",
+	"syscall.EADDRINUSE":                                   "syscall",
+	"syscall.EADDRNOTAVAIL":                                "syscall",
+	"syscall.EADV":                                         "syscall",
+	"syscall.EAFNOSUPPORT":                                 "syscall",
+	"syscall.EAGAIN":                                       "syscall",
+	"syscall.EALREADY":                                     "syscall",
+	"syscall.EAUTH":                                        "syscall",
+	"syscall.EBADARCH":                                     "syscall",
+	"syscall.EBADE":                                        "syscall",
+	"syscall.EBADEXEC":                                     "syscall",
+	"syscall.EBADF":                                        "syscall",
+	"syscall.EBADFD":                                       "syscall",
+	"syscall.EBADMACHO":                                    "syscall",
+	"syscall.EBADMSG":                                      "syscall",
+	"syscall.EBADR":                                        "syscall",
+	"syscall.EBADRPC":                                      "syscall",
+	"syscall.EBADRQC":                                      "syscall",
+	"syscall.EBADSLT":                                      "syscall",
+	"syscall.EBFONT":                                       "syscall",
+	"syscall.EBUSY":                                        "syscall",
+	"syscall.ECANCELED":                                    "syscall",
+	"syscall.ECAPMODE":                                     "syscall",
+	"syscall.ECHILD":                                       "syscall",
+	"syscall.ECHO":                                         "syscall",
+	"syscall.ECHOCTL":                                      "syscall",
+	"syscall.ECHOE":                                        "syscall",
+	"syscall.ECHOK":                                        "syscall",
+	"syscall.ECHOKE":                                       "syscall",
+	"syscall.ECHONL":                                       "syscall",
+	"syscall.ECHOPRT":                                      "syscall",
+	"syscall.ECHRNG":                                       "syscall",
+	"syscall.ECOMM":                                        "syscall",
+	"syscall.ECONNABORTED":                                 "syscall",
+	"syscall.ECONNREFUSED":                                 "syscall",
+	"syscall.ECONNRESET":                                   "syscall",
+	"syscall.EDEADLK":                                      "syscall",
+	"syscall.EDEADLOCK":                                    "syscall",
+	"syscall.EDESTADDRREQ":                                 "syscall",
+	"syscall.EDEVERR":                                      "syscall",
+	"syscall.EDOM":                                         "syscall",
+	"syscall.EDOOFUS":                                      "syscall",
+	"syscall.EDOTDOT":                                      "syscall",
+	"syscall.EDQUOT":                                       "syscall",
+	"syscall.EEXIST":                                       "syscall",
+	"syscall.EFAULT":                                       "syscall",
+	"syscall.EFBIG":                                        "syscall",
+	"syscall.EFER_LMA":                                     "syscall",
+	"syscall.EFER_LME":                                     "syscall",
+	"syscall.EFER_NXE":                                     "syscall",
+	"syscall.EFER_SCE":                                     "syscall",
+	"syscall.EFTYPE":                                       "syscall",
+	"syscall.EHOSTDOWN":                                    "syscall",
+	"syscall.EHOSTUNREACH":                                 "syscall",
+	"syscall.EHWPOISON":                                    "syscall",
+	"syscall.EIDRM":                                        "syscall",
+	"syscall.EILSEQ":                                       "syscall",
+	"syscall.EINPROGRESS":                                  "syscall",
+	"syscall.EINTR":                                        "syscall",
+	"syscall.EINVAL":                                       "syscall",
+	"syscall.EIO":                                          "syscall",
+	"syscall.EIPSEC":                                       "syscall",
+	"syscall.EISCONN":                                      "syscall",
+	"syscall.EISDIR":                                       "syscall",
+	"syscall.EISNAM":                                       "syscall",
+	"syscall.EKEYEXPIRED":                                  "syscall",
+	"syscall.EKEYREJECTED":                                 "syscall",
+	"syscall.EKEYREVOKED":                                  "syscall",
+	"syscall.EL2HLT":                                       "syscall",
+	"syscall.EL2NSYNC":                                     "syscall",
+	"syscall.EL3HLT":                                       "syscall",
+	"syscall.EL3RST":                                       "syscall",
+	"syscall.ELAST":                                        "syscall",
+	"syscall.ELF_NGREG":                                    "syscall",
+	"syscall.ELF_PRARGSZ":                                  "syscall",
+	"syscall.ELIBACC":                                      "syscall",
+	"syscall.ELIBBAD":                                      "syscall",
+	"syscall.ELIBEXEC":                                     "syscall",
+	"syscall.ELIBMAX":                                      "syscall",
+	"syscall.ELIBSCN":                                      "syscall",
+	"syscall.ELNRNG":                                       "syscall",
+	"syscall.ELOOP":                                        "syscall",
+	"syscall.EMEDIUMTYPE":                                  "syscall",
+	"syscall.EMFILE":                                       "syscall",
+	"syscall.EMLINK":                                       "syscall",
+	"syscall.EMSGSIZE":                                     "syscall",
+	"syscall.EMT_TAGOVF":                                   "syscall",
+	"syscall.EMULTIHOP":                                    "syscall",
+	"syscall.EMUL_ENABLED":                                 "syscall",
+	"syscall.EMUL_LINUX":                                   "syscall",
+	"syscall.EMUL_LINUX32":                                 "syscall",
+	"syscall.EMUL_MAXID":                                   "syscall",
+	"syscall.EMUL_NATIVE":                                  "syscall",
+	"syscall.ENAMETOOLONG":                                 "syscall",
+	"syscall.ENAVAIL":                                      "syscall",
+	"syscall.ENDRUNDISC":                                   "syscall",
+	"syscall.ENEEDAUTH":                                    "syscall",
+	"syscall.ENETDOWN":                                     "syscall",
+	"syscall.ENETRESET":                                    "syscall",
+	"syscall.ENETUNREACH":                                  "syscall",
+	"syscall.ENFILE":                                       "syscall",
+	"syscall.ENOANO":                                       "syscall",
+	"syscall.ENOATTR":                                      "syscall",
+	"syscall.ENOBUFS":                                      "syscall",
+	"syscall.ENOCSI":                                       "syscall",
+	"syscall.ENODATA":                                      "syscall",
+	"syscall.ENODEV":                                       "syscall",
+	"syscall.ENOENT":                                       "syscall",
+	"syscall.ENOEXEC":                                      "syscall",
+	"syscall.ENOKEY":                                       "syscall",
+	"syscall.ENOLCK":                                       "syscall",
+	"syscall.ENOLINK":                                      "syscall",
+	"syscall.ENOMEDIUM":                                    "syscall",
+	"syscall.ENOMEM":                                       "syscall",
+	"syscall.ENOMSG":                                       "syscall",
+	"syscall.ENONET":                                       "syscall",
+	"syscall.ENOPKG":                                       "syscall",
+	"syscall.ENOPOLICY":                                    "syscall",
+	"syscall.ENOPROTOOPT":                                  "syscall",
+	"syscall.ENOSPC":                                       "syscall",
+	"syscall.ENOSR":                                        "syscall",
+	"syscall.ENOSTR":                                       "syscall",
+	"syscall.ENOSYS":                                       "syscall",
+	"syscall.ENOTBLK":                                      "syscall",
+	"syscall.ENOTCAPABLE":                                  "syscall",
+	"syscall.ENOTCONN":                                     "syscall",
+	"syscall.ENOTDIR":                                      "syscall",
+	"syscall.ENOTEMPTY":                                    "syscall",
+	"syscall.ENOTNAM":                                      "syscall",
+	"syscall.ENOTRECOVERABLE":                              "syscall",
+	"syscall.ENOTSOCK":                                     "syscall",
+	"syscall.ENOTSUP":                                      "syscall",
+	"syscall.ENOTTY":                                       "syscall",
+	"syscall.ENOTUNIQ":                                     "syscall",
+	"syscall.ENXIO":                                        "syscall",
+	"syscall.EN_SW_CTL_INF":                                "syscall",
+	"syscall.EN_SW_CTL_PREC":                               "syscall",
+	"syscall.EN_SW_CTL_ROUND":                              "syscall",
+	"syscall.EN_SW_DATACHAIN":                              "syscall",
+	"syscall.EN_SW_DENORM":                                 "syscall",
+	"syscall.EN_SW_INVOP":                                  "syscall",
+	"syscall.EN_SW_OVERFLOW":                               "syscall",
+	"syscall.EN_SW_PRECLOSS":                               "syscall",
+	"syscall.EN_SW_UNDERFLOW":                              "syscall",
+	"syscall.EN_SW_ZERODIV":                                "syscall",
+	"syscall.EOPNOTSUPP":                                   "syscall",
+	"syscall.EOVERFLOW":                                    "syscall",
+	"syscall.EOWNERDEAD":                                   "syscall",
+	"syscall.EPERM":                                        "syscall",
+	"syscall.EPFNOSUPPORT":                                 "syscall",
+	"syscall.EPIPE":                                        "syscall",
+	"syscall.EPOLLERR":                                     "syscall",
+	"syscall.EPOLLET":                                      "syscall",
+	"syscall.EPOLLHUP":                                     "syscall",
+	"syscall.EPOLLIN":                                      "syscall",
+	"syscall.EPOLLMSG":                                     "syscall",
+	"syscall.EPOLLONESHOT":                                 "syscall",
+	"syscall.EPOLLOUT":                                     "syscall",
+	"syscall.EPOLLPRI":                                     "syscall",
+	"syscall.EPOLLRDBAND":                                  "syscall",
+	"syscall.EPOLLRDHUP":                                   "syscall",
+	"syscall.EPOLLRDNORM":                                  "syscall",
+	"syscall.EPOLLWRBAND":                                  "syscall",
+	"syscall.EPOLLWRNORM":                                  "syscall",
+	"syscall.EPOLL_CLOEXEC":                                "syscall",
+	"syscall.EPOLL_CTL_ADD":                                "syscall",
+	"syscall.EPOLL_CTL_DEL":                                "syscall",
+	"syscall.EPOLL_CTL_MOD":                                "syscall",
+	"syscall.EPOLL_NONBLOCK":                               "syscall",
+	"syscall.EPROCLIM":                                     "syscall",
+	"syscall.EPROCUNAVAIL":                                 "syscall",
+	"syscall.EPROGMISMATCH":                                "syscall",
+	"syscall.EPROGUNAVAIL":                                 "syscall",
+	"syscall.EPROTO":                                       "syscall",
+	"syscall.EPROTONOSUPPORT":                              "syscall",
+	"syscall.EPROTOTYPE":                                   "syscall",
+	"syscall.EPWROFF":                                      "syscall",
+	"syscall.ERANGE":                                       "syscall",
+	"syscall.EREMCHG":                                      "syscall",
+	"syscall.EREMOTE":                                      "syscall",
+	"syscall.EREMOTEIO":                                    "syscall",
+	"syscall.ERESTART":                                     "syscall",
+	"syscall.ERFKILL":                                      "syscall",
+	"syscall.EROFS":                                        "syscall",
+	"syscall.ERPCMISMATCH":                                 "syscall",
+	"syscall.ERROR_ACCESS_DENIED":                          "syscall",
+	"syscall.ERROR_ALREADY_EXISTS":                         "syscall",
+	"syscall.ERROR_BROKEN_PIPE":                            "syscall",
+	"syscall.ERROR_BUFFER_OVERFLOW":                        "syscall",
+	"syscall.ERROR_ENVVAR_NOT_FOUND":                       "syscall",
+	"syscall.ERROR_FILE_EXISTS":                            "syscall",
+	"syscall.ERROR_FILE_NOT_FOUND":                         "syscall",
+	"syscall.ERROR_HANDLE_EOF":                             "syscall",
+	"syscall.ERROR_INSUFFICIENT_BUFFER":                    "syscall",
+	"syscall.ERROR_IO_PENDING":                             "syscall",
+	"syscall.ERROR_MOD_NOT_FOUND":                          "syscall",
+	"syscall.ERROR_NOT_FOUND":                              "syscall",
+	"syscall.ERROR_NO_MORE_FILES":                          "syscall",
+	"syscall.ERROR_OPERATION_ABORTED":                      "syscall",
+	"syscall.ERROR_PATH_NOT_FOUND":                         "syscall",
+	"syscall.ERROR_PROC_NOT_FOUND":                         "syscall",
+	"syscall.ESHLIBVERS":                                   "syscall",
+	"syscall.ESHUTDOWN":                                    "syscall",
+	"syscall.ESOCKTNOSUPPORT":                              "syscall",
+	"syscall.ESPIPE":                                       "syscall",
+	"syscall.ESRCH":                                        "syscall",
+	"syscall.ESRMNT":                                       "syscall",
+	"syscall.ESTALE":                                       "syscall",
+	"syscall.ESTRPIPE":                                     "syscall",
+	"syscall.ETHERCAP_JUMBO_MTU":                           "syscall",
+	"syscall.ETHERCAP_VLAN_HWTAGGING":                      "syscall",
+	"syscall.ETHERCAP_VLAN_MTU":                            "syscall",
+	"syscall.ETHERMIN":                                     "syscall",
+	"syscall.ETHERMTU":                                     "syscall",
+	"syscall.ETHERMTU_JUMBO":                               "syscall",
+	"syscall.ETHERTYPE_8023":                               "syscall",
+	"syscall.ETHERTYPE_AARP":                               "syscall",
+	"syscall.ETHERTYPE_ACCTON":                             "syscall",
+	"syscall.ETHERTYPE_AEONIC":                             "syscall",
+	"syscall.ETHERTYPE_ALPHA":                              "syscall",
+	"syscall.ETHERTYPE_AMBER":                              "syscall",
+	"syscall.ETHERTYPE_AMOEBA":                             "syscall",
+	"syscall.ETHERTYPE_AOE":                                "syscall",
+	"syscall.ETHERTYPE_APOLLO":                             "syscall",
+	"syscall.ETHERTYPE_APOLLODOMAIN":                       "syscall",
+	"syscall.ETHERTYPE_APPLETALK":                          "syscall",
+	"syscall.ETHERTYPE_APPLITEK":                           "syscall",
+	"syscall.ETHERTYPE_ARGONAUT":                           "syscall",
+	"syscall.ETHERTYPE_ARP":                                "syscall",
+	"syscall.ETHERTYPE_AT":                                 "syscall",
+	"syscall.ETHERTYPE_ATALK":                              "syscall",
+	"syscall.ETHERTYPE_ATOMIC":                             "syscall",
+	"syscall.ETHERTYPE_ATT":                                "syscall",
+	"syscall.ETHERTYPE_ATTSTANFORD":                        "syscall",
+	"syscall.ETHERTYPE_AUTOPHON":                           "syscall",
+	"syscall.ETHERTYPE_AXIS":                               "syscall",
+	"syscall.ETHERTYPE_BCLOOP":                             "syscall",
+	"syscall.ETHERTYPE_BOFL":                               "syscall",
+	"syscall.ETHERTYPE_CABLETRON":                          "syscall",
+	"syscall.ETHERTYPE_CHAOS":                              "syscall",
+	"syscall.ETHERTYPE_COMDESIGN":                          "syscall",
+	"syscall.ETHERTYPE_COMPUGRAPHIC":                       "syscall",
+	"syscall.ETHERTYPE_COUNTERPOINT":                       "syscall",
+	"syscall.ETHERTYPE_CRONUS":                             "syscall",
+	"syscall.ETHERTYPE_CRONUSVLN":                          "syscall",
+	"syscall.ETHERTYPE_DCA":                                "syscall",
+	"syscall.ETHERTYPE_DDE":                                "syscall",
+	"syscall.ETHERTYPE_DEBNI":                              "syscall",
+	"syscall.ETHERTYPE_DECAM":                              "syscall",
+	"syscall.ETHERTYPE_DECCUST":                            "syscall",
+	"syscall.ETHERTYPE_DECDIAG":                            "syscall",
+	"syscall.ETHERTYPE_DECDNS":                             "syscall",
+	"syscall.ETHERTYPE_DECDTS":                             "syscall",
+	"syscall.ETHERTYPE_DECEXPER":                           "syscall",
+	"syscall.ETHERTYPE_DECLAST":                            "syscall",
+	"syscall.ETHERTYPE_DECLTM":                             "syscall",
+	"syscall.ETHERTYPE_DECMUMPS":                           "syscall",
+	"syscall.ETHERTYPE_DECNETBIOS":                         "syscall",
+	"syscall.ETHERTYPE_DELTACON":                           "syscall",
+	"syscall.ETHERTYPE_DIDDLE":                             "syscall",
+	"syscall.ETHERTYPE_DLOG1":                              "syscall",
+	"syscall.ETHERTYPE_DLOG2":                              "syscall",
+	"syscall.ETHERTYPE_DN":                                 "syscall",
+	"syscall.ETHERTYPE_DOGFIGHT":                           "syscall",
+	"syscall.ETHERTYPE_DSMD":                               "syscall",
+	"syscall.ETHERTYPE_ECMA":                               "syscall",
+	"syscall.ETHERTYPE_ENCRYPT":                            "syscall",
+	"syscall.ETHERTYPE_ES":                                 "syscall",
+	"syscall.ETHERTYPE_EXCELAN":                            "syscall",
+	"syscall.ETHERTYPE_EXPERDATA":                          "syscall",
+	"syscall.ETHERTYPE_FLIP":                               "syscall",
+	"syscall.ETHERTYPE_FLOWCONTROL":                        "syscall",
+	"syscall.ETHERTYPE_FRARP":                              "syscall",
+	"syscall.ETHERTYPE_GENDYN":                             "syscall",
+	"syscall.ETHERTYPE_HAYES":                              "syscall",
+	"syscall.ETHERTYPE_HIPPI_FP":                           "syscall",
+	"syscall.ETHERTYPE_HITACHI":                            "syscall",
+	"syscall.ETHERTYPE_HP":                                 "syscall",
+	"syscall.ETHERTYPE_IEEEPUP":                            "syscall",
+	"syscall.ETHERTYPE_IEEEPUPAT":                          "syscall",
+	"syscall.ETHERTYPE_IMLBL":                              "syscall",
+	"syscall.ETHERTYPE_IMLBLDIAG":                          "syscall",
+	"syscall.ETHERTYPE_IP":                                 "syscall",
+	"syscall.ETHERTYPE_IPAS":                               "syscall",
+	"syscall.ETHERTYPE_IPV6":                               "syscall",
+	"syscall.ETHERTYPE_IPX":                                "syscall",
+	"syscall.ETHERTYPE_IPXNEW":                             "syscall",
+	"syscall.ETHERTYPE_KALPANA":                            "syscall",
+	"syscall.ETHERTYPE_LANBRIDGE":                          "syscall",
+	"syscall.ETHERTYPE_LANPROBE":                           "syscall",
+	"syscall.ETHERTYPE_LAT":                                "syscall",
+	"syscall.ETHERTYPE_LBACK":                              "syscall",
+	"syscall.ETHERTYPE_LITTLE":                             "syscall",
+	"syscall.ETHERTYPE_LLDP":                               "syscall",
+	"syscall.ETHERTYPE_LOGICRAFT":                          "syscall",
+	"syscall.ETHERTYPE_LOOPBACK":                           "syscall",
+	"syscall.ETHERTYPE_MATRA":                              "syscall",
+	"syscall.ETHERTYPE_MAX":                                "syscall",
+	"syscall.ETHERTYPE_MERIT":                              "syscall",
+	"syscall.ETHERTYPE_MICP":                               "syscall",
+	"syscall.ETHERTYPE_MOPDL":                              "syscall",
+	"syscall.ETHERTYPE_MOPRC":                              "syscall",
+	"syscall.ETHERTYPE_MOTOROLA":                           "syscall",
+	"syscall.ETHERTYPE_MPLS":                               "syscall",
+	"syscall.ETHERTYPE_MPLS_MCAST":                         "syscall",
+	"syscall.ETHERTYPE_MUMPS":                              "syscall",
+	"syscall.ETHERTYPE_NBPCC":                              "syscall",
+	"syscall.ETHERTYPE_NBPCLAIM":                           "syscall",
+	"syscall.ETHERTYPE_NBPCLREQ":                           "syscall",
+	"syscall.ETHERTYPE_NBPCLRSP":                           "syscall",
+	"syscall.ETHERTYPE_NBPCREQ":                            "syscall",
+	"syscall.ETHERTYPE_NBPCRSP":                            "syscall",
+	"syscall.ETHERTYPE_NBPDG":                              "syscall",
+	"syscall.ETHERTYPE_NBPDGB":                             "syscall",
+	"syscall.ETHERTYPE_NBPDLTE":                            "syscall",
+	"syscall.ETHERTYPE_NBPRAR":                             "syscall",
+	"syscall.ETHERTYPE_NBPRAS":                             "syscall",
+	"syscall.ETHERTYPE_NBPRST":                             "syscall",
+	"syscall.ETHERTYPE_NBPSCD":                             "syscall",
+	"syscall.ETHERTYPE_NBPVCD":                             "syscall",
+	"syscall.ETHERTYPE_NBS":                                "syscall",
+	"syscall.ETHERTYPE_NCD":                                "syscall",
+	"syscall.ETHERTYPE_NESTAR":                             "syscall",
+	"syscall.ETHERTYPE_NETBEUI":                            "syscall",
+	"syscall.ETHERTYPE_NOVELL":                             "syscall",
+	"syscall.ETHERTYPE_NS":                                 "syscall",
+	"syscall.ETHERTYPE_NSAT":                               "syscall",
+	"syscall.ETHERTYPE_NSCOMPAT":                           "syscall",
+	"syscall.ETHERTYPE_NTRAILER":                           "syscall",
+	"syscall.ETHERTYPE_OS9":                                "syscall",
+	"syscall.ETHERTYPE_OS9NET":                             "syscall",
+	"syscall.ETHERTYPE_PACER":                              "syscall",
+	"syscall.ETHERTYPE_PAE":                                "syscall",
+	"syscall.ETHERTYPE_PCS":                                "syscall",
+	"syscall.ETHERTYPE_PLANNING":                           "syscall",
+	"syscall.ETHERTYPE_PPP":                                "syscall",
+	"syscall.ETHERTYPE_PPPOE":                              "syscall",
+	"syscall.ETHERTYPE_PPPOEDISC":                          "syscall",
+	"syscall.ETHERTYPE_PRIMENTS":                           "syscall",
+	"syscall.ETHERTYPE_PUP":                                "syscall",
+	"syscall.ETHERTYPE_PUPAT":                              "syscall",
+	"syscall.ETHERTYPE_QINQ":                               "syscall",
+	"syscall.ETHERTYPE_RACAL":                              "syscall",
+	"syscall.ETHERTYPE_RATIONAL":                           "syscall",
+	"syscall.ETHERTYPE_RAWFR":                              "syscall",
+	"syscall.ETHERTYPE_RCL":                                "syscall",
+	"syscall.ETHERTYPE_RDP":                                "syscall",
+	"syscall.ETHERTYPE_RETIX":                              "syscall",
+	"syscall.ETHERTYPE_REVARP":                             "syscall",
+	"syscall.ETHERTYPE_SCA":                                "syscall",
+	"syscall.ETHERTYPE_SECTRA":                             "syscall",
+	"syscall.ETHERTYPE_SECUREDATA":                         "syscall",
+	"syscall.ETHERTYPE_SGITW":                              "syscall",
+	"syscall.ETHERTYPE_SG_BOUNCE":                          "syscall",
+	"syscall.ETHERTYPE_SG_DIAG":                            "syscall",
+	"syscall.ETHERTYPE_SG_NETGAMES":                        "syscall",
+	"syscall.ETHERTYPE_SG_RESV":                            "syscall",
+	"syscall.ETHERTYPE_SIMNET":                             "syscall",
+	"syscall.ETHERTYPE_SLOW":                               "syscall",
+	"syscall.ETHERTYPE_SLOWPROTOCOLS":                      "syscall",
+	"syscall.ETHERTYPE_SNA":                                "syscall",
+	"syscall.ETHERTYPE_SNMP":                               "syscall",
+	"syscall.ETHERTYPE_SONIX":                              "syscall",
+	"syscall.ETHERTYPE_SPIDER":                             "syscall",
+	"syscall.ETHERTYPE_SPRITE":                             "syscall",
+	"syscall.ETHERTYPE_STP":                                "syscall",
+	"syscall.ETHERTYPE_TALARIS":                            "syscall",
+	"syscall.ETHERTYPE_TALARISMC":                          "syscall",
+	"syscall.ETHERTYPE_TCPCOMP":                            "syscall",
+	"syscall.ETHERTYPE_TCPSM":                              "syscall",
+	"syscall.ETHERTYPE_TEC":                                "syscall",
+	"syscall.ETHERTYPE_TIGAN":                              "syscall",
+	"syscall.ETHERTYPE_TRAIL":                              "syscall",
+	"syscall.ETHERTYPE_TRANSETHER":                         "syscall",
+	"syscall.ETHERTYPE_TYMSHARE":                           "syscall",
+	"syscall.ETHERTYPE_UBBST":                              "syscall",
+	"syscall.ETHERTYPE_UBDEBUG":                            "syscall",
+	"syscall.ETHERTYPE_UBDIAGLOOP":                         "syscall",
+	"syscall.ETHERTYPE_UBDL":                               "syscall",
+	"syscall.ETHERTYPE_UBNIU":                              "syscall",
+	"syscall.ETHERTYPE_UBNMC":                              "syscall",
+	"syscall.ETHERTYPE_VALID":                              "syscall",
+	"syscall.ETHERTYPE_VARIAN":                             "syscall",
+	"syscall.ETHERTYPE_VAXELN":                             "syscall",
+	"syscall.ETHERTYPE_VEECO":                              "syscall",
+	"syscall.ETHERTYPE_VEXP":                               "syscall",
+	"syscall.ETHERTYPE_VGLAB":                              "syscall",
+	"syscall.ETHERTYPE_VINES":                              "syscall",
+	"syscall.ETHERTYPE_VINESECHO":                          "syscall",
+	"syscall.ETHERTYPE_VINESLOOP":                          "syscall",
+	"syscall.ETHERTYPE_VITAL":                              "syscall",
+	"syscall.ETHERTYPE_VLAN":                               "syscall",
+	"syscall.ETHERTYPE_VLTLMAN":                            "syscall",
+	"syscall.ETHERTYPE_VPROD":                              "syscall",
+	"syscall.ETHERTYPE_VURESERVED":                         "syscall",
+	"syscall.ETHERTYPE_WATERLOO":                           "syscall",
+	"syscall.ETHERTYPE_WELLFLEET":                          "syscall",
+	"syscall.ETHERTYPE_X25":                                "syscall",
+	"syscall.ETHERTYPE_X75":                                "syscall",
+	"syscall.ETHERTYPE_XNSSM":                              "syscall",
+	"syscall.ETHERTYPE_XTP":                                "syscall",
+	"syscall.ETHER_ADDR_LEN":                               "syscall",
+	"syscall.ETHER_ALIGN":                                  "syscall",
+	"syscall.ETHER_CRC_LEN":                                "syscall",
+	"syscall.ETHER_CRC_POLY_BE":                            "syscall",
+	"syscall.ETHER_CRC_POLY_LE":                            "syscall",
+	"syscall.ETHER_HDR_LEN":                                "syscall",
+	"syscall.ETHER_MAX_DIX_LEN":                            "syscall",
+	"syscall.ETHER_MAX_LEN":                                "syscall",
+	"syscall.ETHER_MAX_LEN_JUMBO":                          "syscall",
+	"syscall.ETHER_MIN_LEN":                                "syscall",
+	"syscall.ETHER_PPPOE_ENCAP_LEN":                        "syscall",
+	"syscall.ETHER_TYPE_LEN":                               "syscall",
+	"syscall.ETHER_VLAN_ENCAP_LEN":                         "syscall",
+	"syscall.ETH_P_1588":                                   "syscall",
+	"syscall.ETH_P_8021Q":                                  "syscall",
+	"syscall.ETH_P_802_2":                                  "syscall",
+	"syscall.ETH_P_802_3":                                  "syscall",
+	"syscall.ETH_P_AARP":                                   "syscall",
+	"syscall.ETH_P_ALL":                                    "syscall",
+	"syscall.ETH_P_AOE":                                    "syscall",
+	"syscall.ETH_P_ARCNET":                                 "syscall",
+	"syscall.ETH_P_ARP":                                    "syscall",
+	"syscall.ETH_P_ATALK":                                  "syscall",
+	"syscall.ETH_P_ATMFATE":                                "syscall",
+	"syscall.ETH_P_ATMMPOA":                                "syscall",
+	"syscall.ETH_P_AX25":                                   "syscall",
+	"syscall.ETH_P_BPQ":                                    "syscall",
+	"syscall.ETH_P_CAIF":                                   "syscall",
+	"syscall.ETH_P_CAN":                                    "syscall",
+	"syscall.ETH_P_CONTROL":                                "syscall",
+	"syscall.ETH_P_CUST":                                   "syscall",
+	"syscall.ETH_P_DDCMP":                                  "syscall",
+	"syscall.ETH_P_DEC":                                    "syscall",
+	"syscall.ETH_P_DIAG":                                   "syscall",
+	"syscall.ETH_P_DNA_DL":                                 "syscall",
+	"syscall.ETH_P_DNA_RC":                                 "syscall",
+	"syscall.ETH_P_DNA_RT":                                 "syscall",
+	"syscall.ETH_P_DSA":                                    "syscall",
+	"syscall.ETH_P_ECONET":                                 "syscall",
+	"syscall.ETH_P_EDSA":                                   "syscall",
+	"syscall.ETH_P_FCOE":                                   "syscall",
+	"syscall.ETH_P_FIP":                                    "syscall",
+	"syscall.ETH_P_HDLC":                                   "syscall",
+	"syscall.ETH_P_IEEE802154":                             "syscall",
+	"syscall.ETH_P_IEEEPUP":                                "syscall",
+	"syscall.ETH_P_IEEEPUPAT":                              "syscall",
+	"syscall.ETH_P_IP":                                     "syscall",
+	"syscall.ETH_P_IPV6":                                   "syscall",
+	"syscall.ETH_P_IPX":                                    "syscall",
+	"syscall.ETH_P_IRDA":                                   "syscall",
+	"syscall.ETH_P_LAT":                                    "syscall",
+	"syscall.ETH_P_LINK_CTL":                               "syscall",
+	"syscall.ETH_P_LOCALTALK":                              "syscall",
+	"syscall.ETH_P_LOOP":                                   "syscall",
+	"syscall.ETH_P_MOBITEX":                                "syscall",
+	"syscall.ETH_P_MPLS_MC":                                "syscall",
+	"syscall.ETH_P_MPLS_UC":                                "syscall",
+	"syscall.ETH_P_PAE":                                    "syscall",
+	"syscall.ETH_P_PAUSE":                                  "syscall",
+	"syscall.ETH_P_PHONET":                                 "syscall",
+	"syscall.ETH_P_PPPTALK":                                "syscall",
+	"syscall.ETH_P_PPP_DISC":                               "syscall",
+	"syscall.ETH_P_PPP_MP":                                 "syscall",
+	"syscall.ETH_P_PPP_SES":                                "syscall",
+	"syscall.ETH_P_PUP":                                    "syscall",
+	"syscall.ETH_P_PUPAT":                                  "syscall",
+	"syscall.ETH_P_RARP":                                   "syscall",
+	"syscall.ETH_P_SCA":                                    "syscall",
+	"syscall.ETH_P_SLOW":                                   "syscall",
+	"syscall.ETH_P_SNAP":                                   "syscall",
+	"syscall.ETH_P_TEB":                                    "syscall",
+	"syscall.ETH_P_TIPC":                                   "syscall",
+	"syscall.ETH_P_TRAILER":                                "syscall",
+	"syscall.ETH_P_TR_802_2":                               "syscall",
+	"syscall.ETH_P_WAN_PPP":                                "syscall",
+	"syscall.ETH_P_WCCP":                                   "syscall",
+	"syscall.ETH_P_X25":                                    "syscall",
+	"syscall.ETIME":                                        "syscall",
+	"syscall.ETIMEDOUT":                                    "syscall",
+	"syscall.ETOOMANYREFS":                                 "syscall",
+	"syscall.ETXTBSY":                                      "syscall",
+	"syscall.EUCLEAN":                                      "syscall",
+	"syscall.EUNATCH":                                      "syscall",
+	"syscall.EUSERS":                                       "syscall",
+	"syscall.EVFILT_AIO":                                   "syscall",
+	"syscall.EVFILT_FS":                                    "syscall",
+	"syscall.EVFILT_LIO":                                   "syscall",
+	"syscall.EVFILT_MACHPORT":                              "syscall",
+	"syscall.EVFILT_PROC":                                  "syscall",
+	"syscall.EVFILT_READ":                                  "syscall",
+	"syscall.EVFILT_SIGNAL":                                "syscall",
+	"syscall.EVFILT_SYSCOUNT":                              "syscall",
+	"syscall.EVFILT_THREADMARKER":                          "syscall",
+	"syscall.EVFILT_TIMER":                                 "syscall",
+	"syscall.EVFILT_USER":                                  "syscall",
+	"syscall.EVFILT_VM":                                    "syscall",
+	"syscall.EVFILT_VNODE":                                 "syscall",
+	"syscall.EVFILT_WRITE":                                 "syscall",
+	"syscall.EV_ADD":                                       "syscall",
+	"syscall.EV_CLEAR":                                     "syscall",
+	"syscall.EV_DELETE":                                    "syscall",
+	"syscall.EV_DISABLE":                                   "syscall",
+	"syscall.EV_DISPATCH":                                  "syscall",
+	"syscall.EV_ENABLE":                                    "syscall",
+	"syscall.EV_EOF":                                       "syscall",
+	"syscall.EV_ERROR":                                     "syscall",
+	"syscall.EV_FLAG0":                                     "syscall",
+	"syscall.EV_FLAG1":                                     "syscall",
+	"syscall.EV_ONESHOT":                                   "syscall",
+	"syscall.EV_OOBAND":                                    "syscall",
+	"syscall.EV_POLL":                                      "syscall",
+	"syscall.EV_RECEIPT":                                   "syscall",
+	"syscall.EV_SYSFLAGS":                                  "syscall",
+	"syscall.EWINDOWS":                                     "syscall",
+	"syscall.EWOULDBLOCK":                                  "syscall",
+	"syscall.EXDEV":                                        "syscall",
+	"syscall.EXFULL":                                       "syscall",
+	"syscall.EXTA":                                         "syscall",
+	"syscall.EXTB":                                         "syscall",
+	"syscall.EXTPROC":                                      "syscall",
+	"syscall.Environ":                                      "syscall",
+	"syscall.EpollCreate":                                  "syscall",
+	"syscall.EpollCreate1":                                 "syscall",
+	"syscall.EpollCtl":                                     "syscall",
+	"syscall.EpollEvent":                                   "syscall",
+	"syscall.EpollWait":                                    "syscall",
+	"syscall.Errno":                                        "syscall",
+	"syscall.EscapeArg":                                    "syscall",
+	"syscall.Exchangedata":                                 "syscall",
+	"syscall.Exec":                                         "syscall",
+	"syscall.Exit":                                         "syscall",
+	"syscall.ExitProcess":                                  "syscall",
+	"syscall.FD_CLOEXEC":                                   "syscall",
+	"syscall.FD_SETSIZE":                                   "syscall",
+	"syscall.FILE_ACTION_ADDED":                            "syscall",
+	"syscall.FILE_ACTION_MODIFIED":                         "syscall",
+	"syscall.FILE_ACTION_REMOVED":                          "syscall",
+	"syscall.FILE_ACTION_RENAMED_NEW_NAME":                 "syscall",
+	"syscall.FILE_ACTION_RENAMED_OLD_NAME":                 "syscall",
+	"syscall.FILE_APPEND_DATA":                             "syscall",
+	"syscall.FILE_ATTRIBUTE_ARCHIVE":                       "syscall",
+	"syscall.FILE_ATTRIBUTE_DIRECTORY":                     "syscall",
+	"syscall.FILE_ATTRIBUTE_HIDDEN":                        "syscall",
+	"syscall.FILE_ATTRIBUTE_NORMAL":                        "syscall",
+	"syscall.FILE_ATTRIBUTE_READONLY":                      "syscall",
+	"syscall.FILE_ATTRIBUTE_SYSTEM":                        "syscall",
+	"syscall.FILE_BEGIN":                                   "syscall",
+	"syscall.FILE_CURRENT":                                 "syscall",
+	"syscall.FILE_END":                                     "syscall",
+	"syscall.FILE_FLAG_BACKUP_SEMANTICS":                   "syscall",
+	"syscall.FILE_FLAG_OVERLAPPED":                         "syscall",
+	"syscall.FILE_LIST_DIRECTORY":                          "syscall",
+	"syscall.FILE_MAP_COPY":                                "syscall",
+	"syscall.FILE_MAP_EXECUTE":                             "syscall",
+	"syscall.FILE_MAP_READ":                                "syscall",
+	"syscall.FILE_MAP_WRITE":                               "syscall",
+	"syscall.FILE_NOTIFY_CHANGE_ATTRIBUTES":                "syscall",
+	"syscall.FILE_NOTIFY_CHANGE_CREATION":                  "syscall",
+	"syscall.FILE_NOTIFY_CHANGE_DIR_NAME":                  "syscall",
+	"syscall.FILE_NOTIFY_CHANGE_FILE_NAME":                 "syscall",
+	"syscall.FILE_NOTIFY_CHANGE_LAST_ACCESS":               "syscall",
+	"syscall.FILE_NOTIFY_CHANGE_LAST_WRITE":                "syscall",
+	"syscall.FILE_NOTIFY_CHANGE_SIZE":                      "syscall",
+	"syscall.FILE_SHARE_DELETE":                            "syscall",
+	"syscall.FILE_SHARE_READ":                              "syscall",
+	"syscall.FILE_SHARE_WRITE":                             "syscall",
+	"syscall.FILE_SKIP_COMPLETION_PORT_ON_SUCCESS":         "syscall",
+	"syscall.FILE_SKIP_SET_EVENT_ON_HANDLE":                "syscall",
+	"syscall.FILE_TYPE_CHAR":                               "syscall",
+	"syscall.FILE_TYPE_DISK":                               "syscall",
+	"syscall.FILE_TYPE_PIPE":                               "syscall",
+	"syscall.FILE_TYPE_REMOTE":                             "syscall",
+	"syscall.FILE_TYPE_UNKNOWN":                            "syscall",
+	"syscall.FILE_WRITE_ATTRIBUTES":                        "syscall",
+	"syscall.FLUSHO":                                       "syscall",
+	"syscall.FORMAT_MESSAGE_ALLOCATE_BUFFER":               "syscall",
+	"syscall.FORMAT_MESSAGE_ARGUMENT_ARRAY":                "syscall",
+	"syscall.FORMAT_MESSAGE_FROM_HMODULE":                  "syscall",
+	"syscall.FORMAT_MESSAGE_FROM_STRING":                   "syscall",
+	"syscall.FORMAT_MESSAGE_FROM_SYSTEM":                   "syscall",
+	"syscall.FORMAT_MESSAGE_IGNORE_INSERTS":                "syscall",
+	"syscall.FORMAT_MESSAGE_MAX_WIDTH_MASK":                "syscall",
+	"syscall.F_ADDFILESIGS":                                "syscall",
+	"syscall.F_ADDSIGS":                                    "syscall",
+	"syscall.F_ALLOCATEALL":                                "syscall",
+	"syscall.F_ALLOCATECONTIG":                             "syscall",
+	"syscall.F_CANCEL":                                     "syscall",
+	"syscall.F_CHKCLEAN":                                   "syscall",
+	"syscall.F_CLOSEM":                                     "syscall",
+	"syscall.F_DUP2FD":                                     "syscall",
+	"syscall.F_DUP2FD_CLOEXEC":                             "syscall",
+	"syscall.F_DUPFD":                                      "syscall",
+	"syscall.F_DUPFD_CLOEXEC":                              "syscall",
+	"syscall.F_EXLCK":                                      "syscall",
+	"syscall.F_FLUSH_DATA":                                 "syscall",
+	"syscall.F_FREEZE_FS":                                  "syscall",
+	"syscall.F_FSCTL":                                      "syscall",
+	"syscall.F_FSDIRMASK":                                  "syscall",
+	"syscall.F_FSIN":                                       "syscall",
+	"syscall.F_FSINOUT":                                    "syscall",
+	"syscall.F_FSOUT":                                      "syscall",
+	"syscall.F_FSPRIV":                                     "syscall",
+	"syscall.F_FSVOID":                                     "syscall",
+	"syscall.F_FULLFSYNC":                                  "syscall",
+	"syscall.F_GETFD":                                      "syscall",
+	"syscall.F_GETFL":                                      "syscall",
+	"syscall.F_GETLEASE":                                   "syscall",
+	"syscall.F_GETLK":                                      "syscall",
+	"syscall.F_GETLK64":                                    "syscall",
+	"syscall.F_GETLKPID":                                   "syscall",
+	"syscall.F_GETNOSIGPIPE":                               "syscall",
+	"syscall.F_GETOWN":                                     "syscall",
+	"syscall.F_GETOWN_EX":                                  "syscall",
+	"syscall.F_GETPATH":                                    "syscall",
+	"syscall.F_GETPATH_MTMINFO":                            "syscall",
+	"syscall.F_GETPIPE_SZ":                                 "syscall",
+	"syscall.F_GETPROTECTIONCLASS":                         "syscall",
+	"syscall.F_GETSIG":                                     "syscall",
+	"syscall.F_GLOBAL_NOCACHE":                             "syscall",
+	"syscall.F_LOCK":                                       "syscall",
+	"syscall.F_LOG2PHYS":                                   "syscall",
+	"syscall.F_LOG2PHYS_EXT":                               "syscall",
+	"syscall.F_MARKDEPENDENCY":                             "syscall",
+	"syscall.F_MAXFD":                                      "syscall",
+	"syscall.F_NOCACHE":                                    "syscall",
+	"syscall.F_NODIRECT":                                   "syscall",
+	"syscall.F_NOTIFY":                                     "syscall",
+	"syscall.F_OGETLK":                                     "syscall",
+	"syscall.F_OK":                                         "syscall",
+	"syscall.F_OSETLK":                                     "syscall",
+	"syscall.F_OSETLKW":                                    "syscall",
+	"syscall.F_PARAM_MASK":                                 "syscall",
+	"syscall.F_PARAM_MAX":                                  "syscall",
+	"syscall.F_PATHPKG_CHECK":                              "syscall",
+	"syscall.F_PEOFPOSMODE":                                "syscall",
+	"syscall.F_PREALLOCATE":                                "syscall",
+	"syscall.F_RDADVISE":                                   "syscall",
+	"syscall.F_RDAHEAD":                                    "syscall",
+	"syscall.F_RDLCK":                                      "syscall",
+	"syscall.F_READAHEAD":                                  "syscall",
+	"syscall.F_READBOOTSTRAP":                              "syscall",
+	"syscall.F_SETBACKINGSTORE":                            "syscall",
+	"syscall.F_SETFD":                                      "syscall",
+	"syscall.F_SETFL":                                      "syscall",
+	"syscall.F_SETLEASE":                                   "syscall",
+	"syscall.F_SETLK":                                      "syscall",
+	"syscall.F_SETLK64":                                    "syscall",
+	"syscall.F_SETLKW":                                     "syscall",
+	"syscall.F_SETLKW64":                                   "syscall",
+	"syscall.F_SETLK_REMOTE":                               "syscall",
+	"syscall.F_SETNOSIGPIPE":                               "syscall",
+	"syscall.F_SETOWN":                                     "syscall",
+	"syscall.F_SETOWN_EX":                                  "syscall",
+	"syscall.F_SETPIPE_SZ":                                 "syscall",
+	"syscall.F_SETPROTECTIONCLASS":                         "syscall",
+	"syscall.F_SETSIG":                                     "syscall",
+	"syscall.F_SETSIZE":                                    "syscall",
+	"syscall.F_SHLCK":                                      "syscall",
+	"syscall.F_TEST":                                       "syscall",
+	"syscall.F_THAW_FS":                                    "syscall",
+	"syscall.F_TLOCK":                                      "syscall",
+	"syscall.F_ULOCK":                                      "syscall",
+	"syscall.F_UNLCK":                                      "syscall",
+	"syscall.F_UNLCKSYS":                                   "syscall",
+	"syscall.F_VOLPOSMODE":                                 "syscall",
+	"syscall.F_WRITEBOOTSTRAP":                             "syscall",
+	"syscall.F_WRLCK":                                      "syscall",
+	"syscall.Faccessat":                                    "syscall",
+	"syscall.Fallocate":                                    "syscall",
+	"syscall.Fbootstraptransfer_t":                         "syscall",
+	"syscall.Fchdir":                                       "syscall",
+	"syscall.Fchflags":                                     "syscall",
+	"syscall.Fchmod":                                       "syscall",
+	"syscall.Fchmodat":                                     "syscall",
+	"syscall.Fchown":                                       "syscall",
+	"syscall.Fchownat":                                     "syscall",
+	"syscall.FdSet":                                        "syscall",
+	"syscall.Fdatasync":                                    "syscall",
+	"syscall.FileNotifyInformation":                        "syscall",
+	"syscall.Filetime":                                     "syscall",
+	"syscall.FindClose":                                    "syscall",
+	"syscall.FindFirstFile":                                "syscall",
+	"syscall.FindNextFile":                                 "syscall",
+	"syscall.Flock":                                        "syscall",
+	"syscall.Flock_t":                                      "syscall",
+	"syscall.FlushBpf":                                     "syscall",
+	"syscall.FlushFileBuffers":                             "syscall",
+	"syscall.FlushViewOfFile":                              "syscall",
+	"syscall.ForkExec":                                     "syscall",
+	"syscall.ForkLock":                                     "syscall",
+	"syscall.FormatMessage":                                "syscall",
+	"syscall.Fpathconf":                                    "syscall",
+	"syscall.FreeAddrInfoW":                                "syscall",
+	"syscall.FreeEnvironmentStrings":                       "syscall",
+	"syscall.FreeLibrary":                                  "syscall",
+	"syscall.Fsid":                                         "syscall",
+	"syscall.Fstat":                                        "syscall",
+	"syscall.Fstatfs":                                      "syscall",
+	"syscall.Fstore_t":                                     "syscall",
+	"syscall.Fsync":                                        "syscall",
+	"syscall.Ftruncate":                                    "syscall",
+	"syscall.Futimes":                                      "syscall",
+	"syscall.Futimesat":                                    "syscall",
+	"syscall.GENERIC_ALL":                                  "syscall",
+	"syscall.GENERIC_EXECUTE":                              "syscall",
+	"syscall.GENERIC_READ":                                 "syscall",
+	"syscall.GENERIC_WRITE":                                "syscall",
+	"syscall.GUID":                                         "syscall",
+	"syscall.GetAcceptExSockaddrs":                         "syscall",
+	"syscall.GetAdaptersInfo":                              "syscall",
+	"syscall.GetAddrInfoW":                                 "syscall",
+	"syscall.GetCommandLine":                               "syscall",
+	"syscall.GetComputerName":                              "syscall",
+	"syscall.GetConsoleMode":                               "syscall",
+	"syscall.GetCurrentDirectory":                          "syscall",
+	"syscall.GetCurrentProcess":                            "syscall",
+	"syscall.GetEnvironmentStrings":                        "syscall",
+	"syscall.GetEnvironmentVariable":                       "syscall",
+	"syscall.GetExitCodeProcess":                           "syscall",
+	"syscall.GetFileAttributes":                            "syscall",
+	"syscall.GetFileAttributesEx":                          "syscall",
+	"syscall.GetFileExInfoStandard":                        "syscall",
+	"syscall.GetFileExMaxInfoLevel":                        "syscall",
+	"syscall.GetFileInformationByHandle":                   "syscall",
+	"syscall.GetFileType":                                  "syscall",
+	"syscall.GetFullPathName":                              "syscall",
+	"syscall.GetHostByName":                                "syscall",
+	"syscall.GetIfEntry":                                   "syscall",
+	"syscall.GetLastError":                                 "syscall",
+	"syscall.GetLengthSid":                                 "syscall",
+	"syscall.GetLongPathName":                              "syscall",
+	"syscall.GetProcAddress":                               "syscall",
+	"syscall.GetProcessTimes":                              "syscall",
+	"syscall.GetProtoByName":                               "syscall",
+	"syscall.GetQueuedCompletionStatus":                    "syscall",
+	"syscall.GetServByName":                                "syscall",
+	"syscall.GetShortPathName":                             "syscall",
+	"syscall.GetStartupInfo":                               "syscall",
+	"syscall.GetStdHandle":                                 "syscall",
+	"syscall.GetSystemTimeAsFileTime":                      "syscall",
+	"syscall.GetTempPath":                                  "syscall",
+	"syscall.GetTimeZoneInformation":                       "syscall",
+	"syscall.GetTokenInformation":                          "syscall",
+	"syscall.GetUserNameEx":                                "syscall",
+	"syscall.GetUserProfileDirectory":                      "syscall",
+	"syscall.GetVersion":                                   "syscall",
+	"syscall.Getcwd":                                       "syscall",
+	"syscall.Getdents":                                     "syscall",
+	"syscall.Getdirentries":                                "syscall",
+	"syscall.Getdtablesize":                                "syscall",
+	"syscall.Getegid":                                      "syscall",
+	"syscall.Getenv":                                       "syscall",
+	"syscall.Geteuid":                                      "syscall",
+	"syscall.Getfsstat":                                    "syscall",
+	"syscall.Getgid":                                       "syscall",
+	"syscall.Getgroups":                                    "syscall",
+	"syscall.Getpagesize":                                  "syscall",
+	"syscall.Getpeername":                                  "syscall",
+	"syscall.Getpgid":                                      "syscall",
+	"syscall.Getpgrp":                                      "syscall",
+	"syscall.Getpid":                                       "syscall",
+	"syscall.Getppid":                                      "syscall",
+	"syscall.Getpriority":                                  "syscall",
+	"syscall.Getrlimit":                                    "syscall",
+	"syscall.Getrusage":                                    "syscall",
+	"syscall.Getsid":                                       "syscall",
+	"syscall.Getsockname":                                  "syscall",
+	"syscall.Getsockopt":                                   "syscall",
+	"syscall.GetsockoptByte":                               "syscall",
+	"syscall.GetsockoptICMPv6Filter":                       "syscall",
+	"syscall.GetsockoptIPMreq":                             "syscall",
+	"syscall.GetsockoptIPMreqn":                            "syscall",
+	"syscall.GetsockoptIPv6MTUInfo":                        "syscall",
+	"syscall.GetsockoptIPv6Mreq":                           "syscall",
+	"syscall.GetsockoptInet4Addr":                          "syscall",
+	"syscall.GetsockoptInt":                                "syscall",
+	"syscall.GetsockoptUcred":                              "syscall",
+	"syscall.Gettid":                                       "syscall",
+	"syscall.Gettimeofday":                                 "syscall",
+	"syscall.Getuid":                                       "syscall",
+	"syscall.Getwd":                                        "syscall",
+	"syscall.Getxattr":                                     "syscall",
+	"syscall.HANDLE_FLAG_INHERIT":                          "syscall",
+	"syscall.HKEY_CLASSES_ROOT":                            "syscall",
+	"syscall.HKEY_CURRENT_CONFIG":                          "syscall",
+	"syscall.HKEY_CURRENT_USER":                            "syscall",
+	"syscall.HKEY_DYN_DATA":                                "syscall",
+	"syscall.HKEY_LOCAL_MACHINE":                           "syscall",
+	"syscall.HKEY_PERFORMANCE_DATA":                        "syscall",
+	"syscall.HKEY_USERS":                                   "syscall",
+	"syscall.HUPCL":                                        "syscall",
+	"syscall.Handle":                                       "syscall",
+	"syscall.Hostent":                                      "syscall",
+	"syscall.ICANON":                                       "syscall",
+	"syscall.ICMP6_FILTER":                                 "syscall",
+	"syscall.ICMPV6_FILTER":                                "syscall",
+	"syscall.ICMPv6Filter":                                 "syscall",
+	"syscall.ICRNL":                                        "syscall",
+	"syscall.IEXTEN":                                       "syscall",
+	"syscall.IFAN_ARRIVAL":                                 "syscall",
+	"syscall.IFAN_DEPARTURE":                               "syscall",
+	"syscall.IFA_ADDRESS":                                  "syscall",
+	"syscall.IFA_ANYCAST":                                  "syscall",
+	"syscall.IFA_BROADCAST":                                "syscall",
+	"syscall.IFA_CACHEINFO":                                "syscall",
+	"syscall.IFA_F_DADFAILED":                              "syscall",
+	"syscall.IFA_F_DEPRECATED":                             "syscall",
+	"syscall.IFA_F_HOMEADDRESS":                            "syscall",
+	"syscall.IFA_F_NODAD":                                  "syscall",
+	"syscall.IFA_F_OPTIMISTIC":                             "syscall",
+	"syscall.IFA_F_PERMANENT":                              "syscall",
+	"syscall.IFA_F_SECONDARY":                              "syscall",
+	"syscall.IFA_F_TEMPORARY":                              "syscall",
+	"syscall.IFA_F_TENTATIVE":                              "syscall",
+	"syscall.IFA_LABEL":                                    "syscall",
+	"syscall.IFA_LOCAL":                                    "syscall",
+	"syscall.IFA_MAX":                                      "syscall",
+	"syscall.IFA_MULTICAST":                                "syscall",
+	"syscall.IFA_ROUTE":                                    "syscall",
+	"syscall.IFA_UNSPEC":                                   "syscall",
+	"syscall.IFF_ALLMULTI":                                 "syscall",
+	"syscall.IFF_ALTPHYS":                                  "syscall",
+	"syscall.IFF_AUTOMEDIA":                                "syscall",
+	"syscall.IFF_BROADCAST":                                "syscall",
+	"syscall.IFF_CANTCHANGE":                               "syscall",
+	"syscall.IFF_CANTCONFIG":                               "syscall",
+	"syscall.IFF_DEBUG":                                    "syscall",
+	"syscall.IFF_DRV_OACTIVE":                              "syscall",
+	"syscall.IFF_DRV_RUNNING":                              "syscall",
+	"syscall.IFF_DYING":                                    "syscall",
+	"syscall.IFF_DYNAMIC":                                  "syscall",
+	"syscall.IFF_LINK0":                                    "syscall",
+	"syscall.IFF_LINK1":                                    "syscall",
+	"syscall.IFF_LINK2":                                    "syscall",
+	"syscall.IFF_LOOPBACK":                                 "syscall",
+	"syscall.IFF_MASTER":                                   "syscall",
+	"syscall.IFF_MONITOR":                                  "syscall",
+	"syscall.IFF_MULTICAST":                                "syscall",
+	"syscall.IFF_NOARP":                                    "syscall",
+	"syscall.IFF_NOTRAILERS":                               "syscall",
+	"syscall.IFF_NO_PI":                                    "syscall",
+	"syscall.IFF_OACTIVE":                                  "syscall",
+	"syscall.IFF_ONE_QUEUE":                                "syscall",
+	"syscall.IFF_POINTOPOINT":                              "syscall",
+	"syscall.IFF_POINTTOPOINT":                             "syscall",
+	"syscall.IFF_PORTSEL":                                  "syscall",
+	"syscall.IFF_PPROMISC":                                 "syscall",
+	"syscall.IFF_PROMISC":                                  "syscall",
+	"syscall.IFF_RENAMING":                                 "syscall",
+	"syscall.IFF_RUNNING":                                  "syscall",
+	"syscall.IFF_SIMPLEX":                                  "syscall",
+	"syscall.IFF_SLAVE":                                    "syscall",
+	"syscall.IFF_SMART":                                    "syscall",
+	"syscall.IFF_STATICARP":                                "syscall",
+	"syscall.IFF_TAP":                                      "syscall",
+	"syscall.IFF_TUN":                                      "syscall",
+	"syscall.IFF_TUN_EXCL":                                 "syscall",
+	"syscall.IFF_UP":                                       "syscall",
+	"syscall.IFF_VNET_HDR":                                 "syscall",
+	"syscall.IFLA_ADDRESS":                                 "syscall",
+	"syscall.IFLA_BROADCAST":                               "syscall",
+	"syscall.IFLA_COST":                                    "syscall",
+	"syscall.IFLA_IFALIAS":                                 "syscall",
+	"syscall.IFLA_IFNAME":                                  "syscall",
+	"syscall.IFLA_LINK":                                    "syscall",
+	"syscall.IFLA_LINKINFO":                                "syscall",
+	"syscall.IFLA_LINKMODE":                                "syscall",
+	"syscall.IFLA_MAP":                                     "syscall",
+	"syscall.IFLA_MASTER":                                  "syscall",
+	"syscall.IFLA_MAX":                                     "syscall",
+	"syscall.IFLA_MTU":                                     "syscall",
+	"syscall.IFLA_NET_NS_PID":                              "syscall",
+	"syscall.IFLA_OPERSTATE":                               "syscall",
+	"syscall.IFLA_PRIORITY":                                "syscall",
+	"syscall.IFLA_PROTINFO":                                "syscall",
+	"syscall.IFLA_QDISC":                                   "syscall",
+	"syscall.IFLA_STATS":                                   "syscall",
+	"syscall.IFLA_TXQLEN":                                  "syscall",
+	"syscall.IFLA_UNSPEC":                                  "syscall",
+	"syscall.IFLA_WEIGHT":                                  "syscall",
+	"syscall.IFLA_WIRELESS":                                "syscall",
+	"syscall.IFNAMSIZ":                                     "syscall",
+	"syscall.IFT_1822":                                     "syscall",
+	"syscall.IFT_A12MPPSWITCH":                             "syscall",
+	"syscall.IFT_AAL2":                                     "syscall",
+	"syscall.IFT_AAL5":                                     "syscall",
+	"syscall.IFT_ADSL":                                     "syscall",
+	"syscall.IFT_AFLANE8023":                               "syscall",
+	"syscall.IFT_AFLANE8025":                               "syscall",
+	"syscall.IFT_ARAP":                                     "syscall",
+	"syscall.IFT_ARCNET":                                   "syscall",
+	"syscall.IFT_ARCNETPLUS":                               "syscall",
+	"syscall.IFT_ASYNC":                                    "syscall",
+	"syscall.IFT_ATM":                                      "syscall",
+	"syscall.IFT_ATMDXI":                                   "syscall",
+	"syscall.IFT_ATMFUNI":                                  "syscall",
+	"syscall.IFT_ATMIMA":                                   "syscall",
+	"syscall.IFT_ATMLOGICAL":                               "syscall",
+	"syscall.IFT_ATMRADIO":                                 "syscall",
+	"syscall.IFT_ATMSUBINTERFACE":                          "syscall",
+	"syscall.IFT_ATMVCIENDPT":                              "syscall",
+	"syscall.IFT_ATMVIRTUAL":                               "syscall",
+	"syscall.IFT_BGPPOLICYACCOUNTING":                      "syscall",
+	"syscall.IFT_BLUETOOTH":                                "syscall",
+	"syscall.IFT_BRIDGE":                                   "syscall",
+	"syscall.IFT_BSC":                                      "syscall",
+	"syscall.IFT_CARP":                                     "syscall",
+	"syscall.IFT_CCTEMUL":                                  "syscall",
+	"syscall.IFT_CELLULAR":                                 "syscall",
+	"syscall.IFT_CEPT":                                     "syscall",
+	"syscall.IFT_CES":                                      "syscall",
+	"syscall.IFT_CHANNEL":                                  "syscall",
+	"syscall.IFT_CNR":                                      "syscall",
+	"syscall.IFT_COFFEE":                                   "syscall",
+	"syscall.IFT_COMPOSITELINK":                            "syscall",
+	"syscall.IFT_DCN":                                      "syscall",
+	"syscall.IFT_DIGITALPOWERLINE":                         "syscall",
+	"syscall.IFT_DIGITALWRAPPEROVERHEADCHANNEL":            "syscall",
+	"syscall.IFT_DLSW":                                     "syscall",
+	"syscall.IFT_DOCSCABLEDOWNSTREAM":                      "syscall",
+	"syscall.IFT_DOCSCABLEMACLAYER":                        "syscall",
+	"syscall.IFT_DOCSCABLEUPSTREAM":                        "syscall",
+	"syscall.IFT_DOCSCABLEUPSTREAMCHANNEL":                 "syscall",
+	"syscall.IFT_DS0":                                      "syscall",
+	"syscall.IFT_DS0BUNDLE":                                "syscall",
+	"syscall.IFT_DS1FDL":                                   "syscall",
+	"syscall.IFT_DS3":                                      "syscall",
+	"syscall.IFT_DTM":                                      "syscall",
+	"syscall.IFT_DUMMY":                                    "syscall",
+	"syscall.IFT_DVBASILN":                                 "syscall",
+	"syscall.IFT_DVBASIOUT":                                "syscall",
+	"syscall.IFT_DVBRCCDOWNSTREAM":                         "syscall",
+	"syscall.IFT_DVBRCCMACLAYER":                           "syscall",
+	"syscall.IFT_DVBRCCUPSTREAM":                           "syscall",
+	"syscall.IFT_ECONET":                                   "syscall",
+	"syscall.IFT_ENC":                                      "syscall",
+	"syscall.IFT_EON":                                      "syscall",
+	"syscall.IFT_EPLRS":                                    "syscall",
+	"syscall.IFT_ESCON":                                    "syscall",
+	"syscall.IFT_ETHER":                                    "syscall",
+	"syscall.IFT_FAITH":                                    "syscall",
+	"syscall.IFT_FAST":                                     "syscall",
+	"syscall.IFT_FASTETHER":                                "syscall",
+	"syscall.IFT_FASTETHERFX":                              "syscall",
+	"syscall.IFT_FDDI":                                     "syscall",
+	"syscall.IFT_FIBRECHANNEL":                             "syscall",
+	"syscall.IFT_FRAMERELAYINTERCONNECT":                   "syscall",
+	"syscall.IFT_FRAMERELAYMPI":                            "syscall",
+	"syscall.IFT_FRDLCIENDPT":                              "syscall",
+	"syscall.IFT_FRELAY":                                   "syscall",
+	"syscall.IFT_FRELAYDCE":                                "syscall",
+	"syscall.IFT_FRF16MFRBUNDLE":                           "syscall",
+	"syscall.IFT_FRFORWARD":                                "syscall",
+	"syscall.IFT_G703AT2MB":                                "syscall",
+	"syscall.IFT_G703AT64K":                                "syscall",
+	"syscall.IFT_GIF":                                      "syscall",
+	"syscall.IFT_GIGABITETHERNET":                          "syscall",
+	"syscall.IFT_GR303IDT":                                 "syscall",
+	"syscall.IFT_GR303RDT":                                 "syscall",
+	"syscall.IFT_H323GATEKEEPER":                           "syscall",
+	"syscall.IFT_H323PROXY":                                "syscall",
+	"syscall.IFT_HDH1822":                                  "syscall",
+	"syscall.IFT_HDLC":                                     "syscall",
+	"syscall.IFT_HDSL2":                                    "syscall",
+	"syscall.IFT_HIPERLAN2":                                "syscall",
+	"syscall.IFT_HIPPI":                                    "syscall",
+	"syscall.IFT_HIPPIINTERFACE":                           "syscall",
+	"syscall.IFT_HOSTPAD":                                  "syscall",
+	"syscall.IFT_HSSI":                                     "syscall",
+	"syscall.IFT_HY":                                       "syscall",
+	"syscall.IFT_IBM370PARCHAN":                            "syscall",
+	"syscall.IFT_IDSL":                                     "syscall",
+	"syscall.IFT_IEEE1394":                                 "syscall",
+	"syscall.IFT_IEEE80211":                                "syscall",
+	"syscall.IFT_IEEE80212":                                "syscall",
+	"syscall.IFT_IEEE8023ADLAG":                            "syscall",
+	"syscall.IFT_IFGSN":                                    "syscall",
+	"syscall.IFT_IMT":                                      "syscall",
+	"syscall.IFT_INFINIBAND":                               "syscall",
+	"syscall.IFT_INTERLEAVE":                               "syscall",
+	"syscall.IFT_IP":                                       "syscall",
+	"syscall.IFT_IPFORWARD":                                "syscall",
+	"syscall.IFT_IPOVERATM":                                "syscall",
+	"syscall.IFT_IPOVERCDLC":                               "syscall",
+	"syscall.IFT_IPOVERCLAW":                               "syscall",
+	"syscall.IFT_IPSWITCH":                                 "syscall",
+	"syscall.IFT_IPXIP":                                    "syscall",
+	"syscall.IFT_ISDN":                                     "syscall",
+	"syscall.IFT_ISDNBASIC":                                "syscall",
+	"syscall.IFT_ISDNPRIMARY":                              "syscall",
+	"syscall.IFT_ISDNS":                                    "syscall",
+	"syscall.IFT_ISDNU":                                    "syscall",
+	"syscall.IFT_ISO88022LLC":                              "syscall",
+	"syscall.IFT_ISO88023":                                 "syscall",
+	"syscall.IFT_ISO88024":                                 "syscall",
+	"syscall.IFT_ISO88025":                                 "syscall",
+	"syscall.IFT_ISO88025CRFPINT":                          "syscall",
+	"syscall.IFT_ISO88025DTR":                              "syscall",
+	"syscall.IFT_ISO88025FIBER":                            "syscall",
+	"syscall.IFT_ISO88026":                                 "syscall",
+	"syscall.IFT_ISUP":                                     "syscall",
+	"syscall.IFT_L2VLAN":                                   "syscall",
+	"syscall.IFT_L3IPVLAN":                                 "syscall",
+	"syscall.IFT_L3IPXVLAN":                                "syscall",
+	"syscall.IFT_LAPB":                                     "syscall",
+	"syscall.IFT_LAPD":                                     "syscall",
+	"syscall.IFT_LAPF":                                     "syscall",
+	"syscall.IFT_LINEGROUP":                                "syscall",
+	"syscall.IFT_LOCALTALK":                                "syscall",
+	"syscall.IFT_LOOP":                                     "syscall",
+	"syscall.IFT_MEDIAMAILOVERIP":                          "syscall",
+	"syscall.IFT_MFSIGLINK":                                "syscall",
+	"syscall.IFT_MIOX25":                                   "syscall",
+	"syscall.IFT_MODEM":                                    "syscall",
+	"syscall.IFT_MPC":                                      "syscall",
+	"syscall.IFT_MPLS":                                     "syscall",
+	"syscall.IFT_MPLSTUNNEL":                               "syscall",
+	"syscall.IFT_MSDSL":                                    "syscall",
+	"syscall.IFT_MVL":                                      "syscall",
+	"syscall.IFT_MYRINET":                                  "syscall",
+	"syscall.IFT_NFAS":                                     "syscall",
+	"syscall.IFT_NSIP":                                     "syscall",
+	"syscall.IFT_OPTICALCHANNEL":                           "syscall",
+	"syscall.IFT_OPTICALTRANSPORT":                         "syscall",
+	"syscall.IFT_OTHER":                                    "syscall",
+	"syscall.IFT_P10":                                      "syscall",
+	"syscall.IFT_P80":                                      "syscall",
+	"syscall.IFT_PARA":                                     "syscall",
+	"syscall.IFT_PDP":                                      "syscall",
+	"syscall.IFT_PFLOG":                                    "syscall",
+	"syscall.IFT_PFLOW":                                    "syscall",
+	"syscall.IFT_PFSYNC":                                   "syscall",
+	"syscall.IFT_PLC":                                      "syscall",
+	"syscall.IFT_PON155":                                   "syscall",
+	"syscall.IFT_PON622":                                   "syscall",
+	"syscall.IFT_POS":                                      "syscall",
+	"syscall.IFT_PPP":                                      "syscall",
+	"syscall.IFT_PPPMULTILINKBUNDLE":                       "syscall",
+	"syscall.IFT_PROPATM":                                  "syscall",
+	"syscall.IFT_PROPBWAP2MP":                              "syscall",
+	"syscall.IFT_PROPCNLS":                                 "syscall",
+	"syscall.IFT_PROPDOCSWIRELESSDOWNSTREAM":               "syscall",
+	"syscall.IFT_PROPDOCSWIRELESSMACLAYER":                 "syscall",
+	"syscall.IFT_PROPDOCSWIRELESSUPSTREAM":                 "syscall",
+	"syscall.IFT_PROPMUX":                                  "syscall",
+	"syscall.IFT_PROPVIRTUAL":                              "syscall",
+	"syscall.IFT_PROPWIRELESSP2P":                          "syscall",
+	"syscall.IFT_PTPSERIAL":                                "syscall",
+	"syscall.IFT_PVC":                                      "syscall",
+	"syscall.IFT_Q2931":                                    "syscall",
+	"syscall.IFT_QLLC":                                     "syscall",
+	"syscall.IFT_RADIOMAC":                                 "syscall",
+	"syscall.IFT_RADSL":                                    "syscall",
+	"syscall.IFT_REACHDSL":                                 "syscall",
+	"syscall.IFT_RFC1483":                                  "syscall",
+	"syscall.IFT_RS232":                                    "syscall",
+	"syscall.IFT_RSRB":                                     "syscall",
+	"syscall.IFT_SDLC":                                     "syscall",
+	"syscall.IFT_SDSL":                                     "syscall",
+	"syscall.IFT_SHDSL":                                    "syscall",
+	"syscall.IFT_SIP":                                      "syscall",
+	"syscall.IFT_SIPSIG":                                   "syscall",
+	"syscall.IFT_SIPTG":                                    "syscall",
+	"syscall.IFT_SLIP":                                     "syscall",
+	"syscall.IFT_SMDSDXI":                                  "syscall",
+	"syscall.IFT_SMDSICIP":                                 "syscall",
+	"syscall.IFT_SONET":                                    "syscall",
+	"syscall.IFT_SONETOVERHEADCHANNEL":                     "syscall",
+	"syscall.IFT_SONETPATH":                                "syscall",
+	"syscall.IFT_SONETVT":                                  "syscall",
+	"syscall.IFT_SRP":                                      "syscall",
+	"syscall.IFT_SS7SIGLINK":                               "syscall",
+	"syscall.IFT_STACKTOSTACK":                             "syscall",
+	"syscall.IFT_STARLAN":                                  "syscall",
+	"syscall.IFT_STF":                                      "syscall",
+	"syscall.IFT_T1":                                       "syscall",
+	"syscall.IFT_TDLC":                                     "syscall",
+	"syscall.IFT_TELINK":                                   "syscall",
+	"syscall.IFT_TERMPAD":                                  "syscall",
+	"syscall.IFT_TR008":                                    "syscall",
+	"syscall.IFT_TRANSPHDLC":                               "syscall",
+	"syscall.IFT_TUNNEL":                                   "syscall",
+	"syscall.IFT_ULTRA":                                    "syscall",
+	"syscall.IFT_USB":                                      "syscall",
+	"syscall.IFT_V11":                                      "syscall",
+	"syscall.IFT_V35":                                      "syscall",
+	"syscall.IFT_V36":                                      "syscall",
+	"syscall.IFT_V37":                                      "syscall",
+	"syscall.IFT_VDSL":                                     "syscall",
+	"syscall.IFT_VIRTUALIPADDRESS":                         "syscall",
+	"syscall.IFT_VIRTUALTG":                                "syscall",
+	"syscall.IFT_VOICEDID":                                 "syscall",
+	"syscall.IFT_VOICEEM":                                  "syscall",
+	"syscall.IFT_VOICEEMFGD":                               "syscall",
+	"syscall.IFT_VOICEENCAP":                               "syscall",
+	"syscall.IFT_VOICEFGDEANA":                             "syscall",
+	"syscall.IFT_VOICEFXO":                                 "syscall",
+	"syscall.IFT_VOICEFXS":                                 "syscall",
+	"syscall.IFT_VOICEOVERATM":                             "syscall",
+	"syscall.IFT_VOICEOVERCABLE":                           "syscall",
+	"syscall.IFT_VOICEOVERFRAMERELAY":                      "syscall",
+	"syscall.IFT_VOICEOVERIP":                              "syscall",
+	"syscall.IFT_X213":                                     "syscall",
+	"syscall.IFT_X25":                                      "syscall",
+	"syscall.IFT_X25DDN":                                   "syscall",
+	"syscall.IFT_X25HUNTGROUP":                             "syscall",
+	"syscall.IFT_X25MLP":                                   "syscall",
+	"syscall.IFT_X25PLE":                                   "syscall",
+	"syscall.IFT_XETHER":                                   "syscall",
+	"syscall.IGNBRK":                                       "syscall",
+	"syscall.IGNCR":                                        "syscall",
+	"syscall.IGNORE":                                       "syscall",
+	"syscall.IGNPAR":                                       "syscall",
+	"syscall.IMAXBEL":                                      "syscall",
+	"syscall.INFINITE":                                     "syscall",
+	"syscall.INLCR":                                        "syscall",
+	"syscall.INPCK":                                        "syscall",
+	"syscall.INVALID_FILE_ATTRIBUTES":                      "syscall",
+	"syscall.IN_ACCESS":                                    "syscall",
+	"syscall.IN_ALL_EVENTS":                                "syscall",
+	"syscall.IN_ATTRIB":                                    "syscall",
+	"syscall.IN_CLASSA_HOST":                               "syscall",
+	"syscall.IN_CLASSA_MAX":                                "syscall",
+	"syscall.IN_CLASSA_NET":                                "syscall",
+	"syscall.IN_CLASSA_NSHIFT":                             "syscall",
+	"syscall.IN_CLASSB_HOST":                               "syscall",
+	"syscall.IN_CLASSB_MAX":                                "syscall",
+	"syscall.IN_CLASSB_NET":                                "syscall",
+	"syscall.IN_CLASSB_NSHIFT":                             "syscall",
+	"syscall.IN_CLASSC_HOST":                               "syscall",
+	"syscall.IN_CLASSC_NET":                                "syscall",
+	"syscall.IN_CLASSC_NSHIFT":                             "syscall",
+	"syscall.IN_CLASSD_HOST":                               "syscall",
+	"syscall.IN_CLASSD_NET":                                "syscall",
+	"syscall.IN_CLASSD_NSHIFT":                             "syscall",
+	"syscall.IN_CLOEXEC":                                   "syscall",
+	"syscall.IN_CLOSE":                                     "syscall",
+	"syscall.IN_CLOSE_NOWRITE":                             "syscall",
+	"syscall.IN_CLOSE_WRITE":                               "syscall",
+	"syscall.IN_CREATE":                                    "syscall",
+	"syscall.IN_DELETE":                                    "syscall",
+	"syscall.IN_DELETE_SELF":                               "syscall",
+	"syscall.IN_DONT_FOLLOW":                               "syscall",
+	"syscall.IN_EXCL_UNLINK":                               "syscall",
+	"syscall.IN_IGNORED":                                   "syscall",
+	"syscall.IN_ISDIR":                                     "syscall",
+	"syscall.IN_LINKLOCALNETNUM":                           "syscall",
+	"syscall.IN_LOOPBACKNET":                               "syscall",
+	"syscall.IN_MASK_ADD":                                  "syscall",
+	"syscall.IN_MODIFY":                                    "syscall",
+	"syscall.IN_MOVE":                                      "syscall",
+	"syscall.IN_MOVED_FROM":                                "syscall",
+	"syscall.IN_MOVED_TO":                                  "syscall",
+	"syscall.IN_MOVE_SELF":                                 "syscall",
+	"syscall.IN_NONBLOCK":                                  "syscall",
+	"syscall.IN_ONESHOT":                                   "syscall",
+	"syscall.IN_ONLYDIR":                                   "syscall",
+	"syscall.IN_OPEN":                                      "syscall",
+	"syscall.IN_Q_OVERFLOW":                                "syscall",
+	"syscall.IN_RFC3021_HOST":                              "syscall",
+	"syscall.IN_RFC3021_MASK":                              "syscall",
+	"syscall.IN_RFC3021_NET":                               "syscall",
+	"syscall.IN_RFC3021_NSHIFT":                            "syscall",
+	"syscall.IN_UNMOUNT":                                   "syscall",
+	"syscall.IOC_IN":                                       "syscall",
+	"syscall.IOC_INOUT":                                    "syscall",
+	"syscall.IOC_OUT":                                      "syscall",
+	"syscall.IOC_WS2":                                      "syscall",
+	"syscall.IPMreq":                                       "syscall",
+	"syscall.IPMreqn":                                      "syscall",
+	"syscall.IPPROTO_3PC":                                  "syscall",
+	"syscall.IPPROTO_ADFS":                                 "syscall",
+	"syscall.IPPROTO_AH":                                   "syscall",
+	"syscall.IPPROTO_AHIP":                                 "syscall",
+	"syscall.IPPROTO_APES":                                 "syscall",
+	"syscall.IPPROTO_ARGUS":                                "syscall",
+	"syscall.IPPROTO_AX25":                                 "syscall",
+	"syscall.IPPROTO_BHA":                                  "syscall",
+	"syscall.IPPROTO_BLT":                                  "syscall",
+	"syscall.IPPROTO_BRSATMON":                             "syscall",
+	"syscall.IPPROTO_CARP":                                 "syscall",
+	"syscall.IPPROTO_CFTP":                                 "syscall",
+	"syscall.IPPROTO_CHAOS":                                "syscall",
+	"syscall.IPPROTO_CMTP":                                 "syscall",
+	"syscall.IPPROTO_COMP":                                 "syscall",
+	"syscall.IPPROTO_CPHB":                                 "syscall",
+	"syscall.IPPROTO_CPNX":                                 "syscall",
+	"syscall.IPPROTO_DCCP":                                 "syscall",
+	"syscall.IPPROTO_DDP":                                  "syscall",
+	"syscall.IPPROTO_DGP":                                  "syscall",
+	"syscall.IPPROTO_DIVERT":                               "syscall",
+	"syscall.IPPROTO_DONE":                                 "syscall",
+	"syscall.IPPROTO_DSTOPTS":                              "syscall",
+	"syscall.IPPROTO_EGP":                                  "syscall",
+	"syscall.IPPROTO_EMCON":                                "syscall",
+	"syscall.IPPROTO_ENCAP":                                "syscall",
+	"syscall.IPPROTO_EON":                                  "syscall",
+	"syscall.IPPROTO_ESP":                                  "syscall",
+	"syscall.IPPROTO_ETHERIP":                              "syscall",
+	"syscall.IPPROTO_FRAGMENT":                             "syscall",
+	"syscall.IPPROTO_GGP":                                  "syscall",
+	"syscall.IPPROTO_GMTP":                                 "syscall",
+	"syscall.IPPROTO_GRE":                                  "syscall",
+	"syscall.IPPROTO_HELLO":                                "syscall",
+	"syscall.IPPROTO_HMP":                                  "syscall",
+	"syscall.IPPROTO_HOPOPTS":                              "syscall",
+	"syscall.IPPROTO_ICMP":                                 "syscall",
+	"syscall.IPPROTO_ICMPV6":                               "syscall",
+	"syscall.IPPROTO_IDP":                                  "syscall",
+	"syscall.IPPROTO_IDPR":                                 "syscall",
+	"syscall.IPPROTO_IDRP":                                 "syscall",
+	"syscall.IPPROTO_IGMP":                                 "syscall",
+	"syscall.IPPROTO_IGP":                                  "syscall",
+	"syscall.IPPROTO_IGRP":                                 "syscall",
+	"syscall.IPPROTO_IL":                                   "syscall",
+	"syscall.IPPROTO_INLSP":                                "syscall",
+	"syscall.IPPROTO_INP":                                  "syscall",
+	"syscall.IPPROTO_IP":                                   "syscall",
+	"syscall.IPPROTO_IPCOMP":                               "syscall",
+	"syscall.IPPROTO_IPCV":                                 "syscall",
+	"syscall.IPPROTO_IPEIP":                                "syscall",
+	"syscall.IPPROTO_IPIP":                                 "syscall",
+	"syscall.IPPROTO_IPPC":                                 "syscall",
+	"syscall.IPPROTO_IPV4":                                 "syscall",
+	"syscall.IPPROTO_IPV6":                                 "syscall",
+	"syscall.IPPROTO_IPV6_ICMP":                            "syscall",
+	"syscall.IPPROTO_IRTP":                                 "syscall",
+	"syscall.IPPROTO_KRYPTOLAN":                            "syscall",
+	"syscall.IPPROTO_LARP":                                 "syscall",
+	"syscall.IPPROTO_LEAF1":                                "syscall",
+	"syscall.IPPROTO_LEAF2":                                "syscall",
+	"syscall.IPPROTO_MAX":                                  "syscall",
+	"syscall.IPPROTO_MAXID":                                "syscall",
+	"syscall.IPPROTO_MEAS":                                 "syscall",
+	"syscall.IPPROTO_MH":                                   "syscall",
+	"syscall.IPPROTO_MHRP":                                 "syscall",
+	"syscall.IPPROTO_MICP":                                 "syscall",
+	"syscall.IPPROTO_MOBILE":                               "syscall",
+	"syscall.IPPROTO_MPLS":                                 "syscall",
+	"syscall.IPPROTO_MTP":                                  "syscall",
+	"syscall.IPPROTO_MUX":                                  "syscall",
+	"syscall.IPPROTO_ND":                                   "syscall",
+	"syscall.IPPROTO_NHRP":                                 "syscall",
+	"syscall.IPPROTO_NONE":                                 "syscall",
+	"syscall.IPPROTO_NSP":                                  "syscall",
+	"syscall.IPPROTO_NVPII":                                "syscall",
+	"syscall.IPPROTO_OLD_DIVERT":                           "syscall",
+	"syscall.IPPROTO_OSPFIGP":                              "syscall",
+	"syscall.IPPROTO_PFSYNC":                               "syscall",
+	"syscall.IPPROTO_PGM":                                  "syscall",
+	"syscall.IPPROTO_PIGP":                                 "syscall",
+	"syscall.IPPROTO_PIM":                                  "syscall",
+	"syscall.IPPROTO_PRM":                                  "syscall",
+	"syscall.IPPROTO_PUP":                                  "syscall",
+	"syscall.IPPROTO_PVP":                                  "syscall",
+	"syscall.IPPROTO_RAW":                                  "syscall",
+	"syscall.IPPROTO_RCCMON":                               "syscall",
+	"syscall.IPPROTO_RDP":                                  "syscall",
+	"syscall.IPPROTO_ROUTING":                              "syscall",
+	"syscall.IPPROTO_RSVP":                                 "syscall",
+	"syscall.IPPROTO_RVD":                                  "syscall",
+	"syscall.IPPROTO_SATEXPAK":                             "syscall",
+	"syscall.IPPROTO_SATMON":                               "syscall",
+	"syscall.IPPROTO_SCCSP":                                "syscall",
+	"syscall.IPPROTO_SCTP":                                 "syscall",
+	"syscall.IPPROTO_SDRP":                                 "syscall",
+	"syscall.IPPROTO_SEND":                                 "syscall",
+	"syscall.IPPROTO_SEP":                                  "syscall",
+	"syscall.IPPROTO_SKIP":                                 "syscall",
+	"syscall.IPPROTO_SPACER":                               "syscall",
+	"syscall.IPPROTO_SRPC":                                 "syscall",
+	"syscall.IPPROTO_ST":                                   "syscall",
+	"syscall.IPPROTO_SVMTP":                                "syscall",
+	"syscall.IPPROTO_SWIPE":                                "syscall",
+	"syscall.IPPROTO_TCF":                                  "syscall",
+	"syscall.IPPROTO_TCP":                                  "syscall",
+	"syscall.IPPROTO_TLSP":                                 "syscall",
+	"syscall.IPPROTO_TP":                                   "syscall",
+	"syscall.IPPROTO_TPXX":                                 "syscall",
+	"syscall.IPPROTO_TRUNK1":                               "syscall",
+	"syscall.IPPROTO_TRUNK2":                               "syscall",
+	"syscall.IPPROTO_TTP":                                  "syscall",
+	"syscall.IPPROTO_UDP":                                  "syscall",
+	"syscall.IPPROTO_UDPLITE":                              "syscall",
+	"syscall.IPPROTO_VINES":                                "syscall",
+	"syscall.IPPROTO_VISA":                                 "syscall",
+	"syscall.IPPROTO_VMTP":                                 "syscall",
+	"syscall.IPPROTO_VRRP":                                 "syscall",
+	"syscall.IPPROTO_WBEXPAK":                              "syscall",
+	"syscall.IPPROTO_WBMON":                                "syscall",
+	"syscall.IPPROTO_WSN":                                  "syscall",
+	"syscall.IPPROTO_XNET":                                 "syscall",
+	"syscall.IPPROTO_XTP":                                  "syscall",
+	"syscall.IPV6_2292DSTOPTS":                             "syscall",
+	"syscall.IPV6_2292HOPLIMIT":                            "syscall",
+	"syscall.IPV6_2292HOPOPTS":                             "syscall",
+	"syscall.IPV6_2292NEXTHOP":                             "syscall",
+	"syscall.IPV6_2292PKTINFO":                             "syscall",
+	"syscall.IPV6_2292PKTOPTIONS":                          "syscall",
+	"syscall.IPV6_2292RTHDR":                               "syscall",
+	"syscall.IPV6_ADDRFORM":                                "syscall",
+	"syscall.IPV6_ADD_MEMBERSHIP":                          "syscall",
+	"syscall.IPV6_AUTHHDR":                                 "syscall",
+	"syscall.IPV6_AUTH_LEVEL":                              "syscall",
+	"syscall.IPV6_AUTOFLOWLABEL":                           "syscall",
+	"syscall.IPV6_BINDANY":                                 "syscall",
+	"syscall.IPV6_BINDV6ONLY":                              "syscall",
+	"syscall.IPV6_BOUND_IF":                                "syscall",
+	"syscall.IPV6_CHECKSUM":                                "syscall",
+	"syscall.IPV6_DEFAULT_MULTICAST_HOPS":                  "syscall",
+	"syscall.IPV6_DEFAULT_MULTICAST_LOOP":                  "syscall",
+	"syscall.IPV6_DEFHLIM":                                 "syscall",
+	"syscall.IPV6_DONTFRAG":                                "syscall",
+	"syscall.IPV6_DROP_MEMBERSHIP":                         "syscall",
+	"syscall.IPV6_DSTOPTS":                                 "syscall",
+	"syscall.IPV6_ESP_NETWORK_LEVEL":                       "syscall",
+	"syscall.IPV6_ESP_TRANS_LEVEL":                         "syscall",
+	"syscall.IPV6_FAITH":                                   "syscall",
+	"syscall.IPV6_FLOWINFO_MASK":                           "syscall",
+	"syscall.IPV6_FLOWLABEL_MASK":                          "syscall",
+	"syscall.IPV6_FRAGTTL":                                 "syscall",
+	"syscall.IPV6_FW_ADD":                                  "syscall",
+	"syscall.IPV6_FW_DEL":                                  "syscall",
+	"syscall.IPV6_FW_FLUSH":                                "syscall",
+	"syscall.IPV6_FW_GET":                                  "syscall",
+	"syscall.IPV6_FW_ZERO":                                 "syscall",
+	"syscall.IPV6_HLIMDEC":                                 "syscall",
+	"syscall.IPV6_HOPLIMIT":                                "syscall",
+	"syscall.IPV6_HOPOPTS":                                 "syscall",
+	"syscall.IPV6_IPCOMP_LEVEL":                            "syscall",
+	"syscall.IPV6_IPSEC_POLICY":                            "syscall",
+	"syscall.IPV6_JOIN_ANYCAST":                            "syscall",
+	"syscall.IPV6_JOIN_GROUP":                              "syscall",
+	"syscall.IPV6_LEAVE_ANYCAST":                           "syscall",
+	"syscall.IPV6_LEAVE_GROUP":                             "syscall",
+	"syscall.IPV6_MAXHLIM":                                 "syscall",
+	"syscall.IPV6_MAXOPTHDR":                               "syscall",
+	"syscall.IPV6_MAXPACKET":                               "syscall",
+	"syscall.IPV6_MAX_GROUP_SRC_FILTER":                    "syscall",
+	"syscall.IPV6_MAX_MEMBERSHIPS":                         "syscall",
+	"syscall.IPV6_MAX_SOCK_SRC_FILTER":                     "syscall",
+	"syscall.IPV6_MIN_MEMBERSHIPS":                         "syscall",
+	"syscall.IPV6_MMTU":                                    "syscall",
+	"syscall.IPV6_MSFILTER":                                "syscall",
+	"syscall.IPV6_MTU":                                     "syscall",
+	"syscall.IPV6_MTU_DISCOVER":                            "syscall",
+	"syscall.IPV6_MULTICAST_HOPS":                          "syscall",
+	"syscall.IPV6_MULTICAST_IF":                            "syscall",
+	"syscall.IPV6_MULTICAST_LOOP":                          "syscall",
+	"syscall.IPV6_NEXTHOP":                                 "syscall",
+	"syscall.IPV6_OPTIONS":                                 "syscall",
+	"syscall.IPV6_PATHMTU":                                 "syscall",
+	"syscall.IPV6_PIPEX":                                   "syscall",
+	"syscall.IPV6_PKTINFO":                                 "syscall",
+	"syscall.IPV6_PMTUDISC_DO":                             "syscall",
+	"syscall.IPV6_PMTUDISC_DONT":                           "syscall",
+	"syscall.IPV6_PMTUDISC_PROBE":                          "syscall",
+	"syscall.IPV6_PMTUDISC_WANT":                           "syscall",
+	"syscall.IPV6_PORTRANGE":                               "syscall",
+	"syscall.IPV6_PORTRANGE_DEFAULT":                       "syscall",
+	"syscall.IPV6_PORTRANGE_HIGH":                          "syscall",
+	"syscall.IPV6_PORTRANGE_LOW":                           "syscall",
+	"syscall.IPV6_PREFER_TEMPADDR":                         "syscall",
+	"syscall.IPV6_RECVDSTOPTS":                             "syscall",
+	"syscall.IPV6_RECVERR":                                 "syscall",
+	"syscall.IPV6_RECVHOPLIMIT":                            "syscall",
+	"syscall.IPV6_RECVHOPOPTS":                             "syscall",
+	"syscall.IPV6_RECVPATHMTU":                             "syscall",
+	"syscall.IPV6_RECVPKTINFO":                             "syscall",
+	"syscall.IPV6_RECVRTHDR":                               "syscall",
+	"syscall.IPV6_RECVTCLASS":                              "syscall",
+	"syscall.IPV6_ROUTER_ALERT":                            "syscall",
+	"syscall.IPV6_RTABLE":                                  "syscall",
+	"syscall.IPV6_RTHDR":                                   "syscall",
+	"syscall.IPV6_RTHDRDSTOPTS":                            "syscall",
+	"syscall.IPV6_RTHDR_LOOSE":                             "syscall",
+	"syscall.IPV6_RTHDR_STRICT":                            "syscall",
+	"syscall.IPV6_RTHDR_TYPE_0":                            "syscall",
+	"syscall.IPV6_RXDSTOPTS":                               "syscall",
+	"syscall.IPV6_RXHOPOPTS":                               "syscall",
+	"syscall.IPV6_SOCKOPT_RESERVED1":                       "syscall",
+	"syscall.IPV6_TCLASS":                                  "syscall",
+	"syscall.IPV6_UNICAST_HOPS":                            "syscall",
+	"syscall.IPV6_USE_MIN_MTU":                             "syscall",
+	"syscall.IPV6_V6ONLY":                                  "syscall",
+	"syscall.IPV6_VERSION":                                 "syscall",
+	"syscall.IPV6_VERSION_MASK":                            "syscall",
+	"syscall.IPV6_XFRM_POLICY":                             "syscall",
+	"syscall.IP_ADD_MEMBERSHIP":                            "syscall",
+	"syscall.IP_ADD_SOURCE_MEMBERSHIP":                     "syscall",
+	"syscall.IP_AUTH_LEVEL":                                "syscall",
+	"syscall.IP_BINDANY":                                   "syscall",
+	"syscall.IP_BLOCK_SOURCE":                              "syscall",
+	"syscall.IP_BOUND_IF":                                  "syscall",
+	"syscall.IP_DEFAULT_MULTICAST_LOOP":                    "syscall",
+	"syscall.IP_DEFAULT_MULTICAST_TTL":                     "syscall",
+	"syscall.IP_DF":                                        "syscall",
+	"syscall.IP_DONTFRAG":                                  "syscall",
+	"syscall.IP_DROP_MEMBERSHIP":                           "syscall",
+	"syscall.IP_DROP_SOURCE_MEMBERSHIP":                    "syscall",
+	"syscall.IP_DUMMYNET3":                                 "syscall",
+	"syscall.IP_DUMMYNET_CONFIGURE":                        "syscall",
+	"syscall.IP_DUMMYNET_DEL":                              "syscall",
+	"syscall.IP_DUMMYNET_FLUSH":                            "syscall",
+	"syscall.IP_DUMMYNET_GET":                              "syscall",
+	"syscall.IP_EF":                                        "syscall",
+	"syscall.IP_ERRORMTU":                                  "syscall",
+	"syscall.IP_ESP_NETWORK_LEVEL":                         "syscall",
+	"syscall.IP_ESP_TRANS_LEVEL":                           "syscall",
+	"syscall.IP_FAITH":                                     "syscall",
+	"syscall.IP_FREEBIND":                                  "syscall",
+	"syscall.IP_FW3":                                       "syscall",
+	"syscall.IP_FW_ADD":                                    "syscall",
+	"syscall.IP_FW_DEL":                                    "syscall",
+	"syscall.IP_FW_FLUSH":                                  "syscall",
+	"syscall.IP_FW_GET":                                    "syscall",
+	"syscall.IP_FW_NAT_CFG":                                "syscall",
+	"syscall.IP_FW_NAT_DEL":                                "syscall",
+	"syscall.IP_FW_NAT_GET_CONFIG":                         "syscall",
+	"syscall.IP_FW_NAT_GET_LOG":                            "syscall",
+	"syscall.IP_FW_RESETLOG":                               "syscall",
+	"syscall.IP_FW_TABLE_ADD":                              "syscall",
+	"syscall.IP_FW_TABLE_DEL":                              "syscall",
+	"syscall.IP_FW_TABLE_FLUSH":                            "syscall",
+	"syscall.IP_FW_TABLE_GETSIZE":                          "syscall",
+	"syscall.IP_FW_TABLE_LIST":                             "syscall",
+	"syscall.IP_FW_ZERO":                                   "syscall",
+	"syscall.IP_HDRINCL":                                   "syscall",
+	"syscall.IP_IPCOMP_LEVEL":                              "syscall",
+	"syscall.IP_IPSECFLOWINFO":                             "syscall",
+	"syscall.IP_IPSEC_LOCAL_AUTH":                          "syscall",
+	"syscall.IP_IPSEC_LOCAL_CRED":                          "syscall",
+	"syscall.IP_IPSEC_LOCAL_ID":                            "syscall",
+	"syscall.IP_IPSEC_POLICY":                              "syscall",
+	"syscall.IP_IPSEC_REMOTE_AUTH":                         "syscall",
+	"syscall.IP_IPSEC_REMOTE_CRED":                         "syscall",
+	"syscall.IP_IPSEC_REMOTE_ID":                           "syscall",
+	"syscall.IP_MAXPACKET":                                 "syscall",
+	"syscall.IP_MAX_GROUP_SRC_FILTER":                      "syscall",
+	"syscall.IP_MAX_MEMBERSHIPS":                           "syscall",
+	"syscall.IP_MAX_SOCK_MUTE_FILTER":                      "syscall",
+	"syscall.IP_MAX_SOCK_SRC_FILTER":                       "syscall",
+	"syscall.IP_MAX_SOURCE_FILTER":                         "syscall",
+	"syscall.IP_MF":                                        "syscall",
+	"syscall.IP_MINFRAGSIZE":                               "syscall",
+	"syscall.IP_MINTTL":                                    "syscall",
+	"syscall.IP_MIN_MEMBERSHIPS":                           "syscall",
+	"syscall.IP_MSFILTER":                                  "syscall",
+	"syscall.IP_MSS":                                       "syscall",
+	"syscall.IP_MTU":                                       "syscall",
+	"syscall.IP_MTU_DISCOVER":                              "syscall",
+	"syscall.IP_MULTICAST_IF":                              "syscall",
+	"syscall.IP_MULTICAST_IFINDEX":                         "syscall",
+	"syscall.IP_MULTICAST_LOOP":                            "syscall",
+	"syscall.IP_MULTICAST_TTL":                             "syscall",
+	"syscall.IP_MULTICAST_VIF":                             "syscall",
+	"syscall.IP_NAT__XXX":                                  "syscall",
+	"syscall.IP_OFFMASK":                                   "syscall",
+	"syscall.IP_OLD_FW_ADD":                                "syscall",
+	"syscall.IP_OLD_FW_DEL":                                "syscall",
+	"syscall.IP_OLD_FW_FLUSH":                              "syscall",
+	"syscall.IP_OLD_FW_GET":                                "syscall",
+	"syscall.IP_OLD_FW_RESETLOG":                           "syscall",
+	"syscall.IP_OLD_FW_ZERO":                               "syscall",
+	"syscall.IP_ONESBCAST":                                 "syscall",
+	"syscall.IP_OPTIONS":                                   "syscall",
+	"syscall.IP_ORIGDSTADDR":                               "syscall",
+	"syscall.IP_PASSSEC":                                   "syscall",
+	"syscall.IP_PIPEX":                                     "syscall",
+	"syscall.IP_PKTINFO":                                   "syscall",
+	"syscall.IP_PKTOPTIONS":                                "syscall",
+	"syscall.IP_PMTUDISC":                                  "syscall",
+	"syscall.IP_PMTUDISC_DO":                               "syscall",
+	"syscall.IP_PMTUDISC_DONT":                             "syscall",
+	"syscall.IP_PMTUDISC_PROBE":                            "syscall",
+	"syscall.IP_PMTUDISC_WANT":                             "syscall",
+	"syscall.IP_PORTRANGE":                                 "syscall",
+	"syscall.IP_PORTRANGE_DEFAULT":                         "syscall",
+	"syscall.IP_PORTRANGE_HIGH":                            "syscall",
+	"syscall.IP_PORTRANGE_LOW":                             "syscall",
+	"syscall.IP_RECVDSTADDR":                               "syscall",
+	"syscall.IP_RECVDSTPORT":                               "syscall",
+	"syscall.IP_RECVERR":                                   "syscall",
+	"syscall.IP_RECVIF":                                    "syscall",
+	"syscall.IP_RECVOPTS":                                  "syscall",
+	"syscall.IP_RECVORIGDSTADDR":                           "syscall",
+	"syscall.IP_RECVPKTINFO":                               "syscall",
+	"syscall.IP_RECVRETOPTS":                               "syscall",
+	"syscall.IP_RECVRTABLE":                                "syscall",
+	"syscall.IP_RECVTOS":                                   "syscall",
+	"syscall.IP_RECVTTL":                                   "syscall",
+	"syscall.IP_RETOPTS":                                   "syscall",
+	"syscall.IP_RF":                                        "syscall",
+	"syscall.IP_ROUTER_ALERT":                              "syscall",
+	"syscall.IP_RSVP_OFF":                                  "syscall",
+	"syscall.IP_RSVP_ON":                                   "syscall",
+	"syscall.IP_RSVP_VIF_OFF":                              "syscall",
+	"syscall.IP_RSVP_VIF_ON":                               "syscall",
+	"syscall.IP_RTABLE":                                    "syscall",
+	"syscall.IP_SENDSRCADDR":                               "syscall",
+	"syscall.IP_STRIPHDR":                                  "syscall",
+	"syscall.IP_TOS":                                       "syscall",
+	"syscall.IP_TRAFFIC_MGT_BACKGROUND":                    "syscall",
+	"syscall.IP_TRANSPARENT":                               "syscall",
+	"syscall.IP_TTL":                                       "syscall",
+	"syscall.IP_UNBLOCK_SOURCE":                            "syscall",
+	"syscall.IP_XFRM_POLICY":                               "syscall",
+	"syscall.IPv6MTUInfo":                                  "syscall",
+	"syscall.IPv6Mreq":                                     "syscall",
+	"syscall.ISIG":                                         "syscall",
+	"syscall.ISTRIP":                                       "syscall",
+	"syscall.IUCLC":                                        "syscall",
+	"syscall.IUTF8":                                        "syscall",
+	"syscall.IXANY":                                        "syscall",
+	"syscall.IXOFF":                                        "syscall",
+	"syscall.IXON":                                         "syscall",
+	"syscall.IfAddrmsg":                                    "syscall",
+	"syscall.IfAnnounceMsghdr":                             "syscall",
+	"syscall.IfData":                                       "syscall",
+	"syscall.IfInfomsg":                                    "syscall",
+	"syscall.IfMsghdr":                                     "syscall",
+	"syscall.IfaMsghdr":                                    "syscall",
+	"syscall.IfmaMsghdr":                                   "syscall",
+	"syscall.IfmaMsghdr2":                                  "syscall",
+	"syscall.ImplementsGetwd":                              "syscall",
+	"syscall.Inet4Pktinfo":                                 "syscall",
+	"syscall.Inet6Pktinfo":                                 "syscall",
+	"syscall.InotifyAddWatch":                              "syscall",
+	"syscall.InotifyEvent":                                 "syscall",
+	"syscall.InotifyInit":                                  "syscall",
+	"syscall.InotifyInit1":                                 "syscall",
+	"syscall.InotifyRmWatch":                               "syscall",
+	"syscall.InterfaceAddrMessage":                         "syscall",
+	"syscall.InterfaceAnnounceMessage":                     "syscall",
+	"syscall.InterfaceInfo":                                "syscall",
+	"syscall.InterfaceMessage":                             "syscall",
+	"syscall.InterfaceMulticastAddrMessage":                "syscall",
+	"syscall.InvalidHandle":                                "syscall",
+	"syscall.Ioperm":                                       "syscall",
+	"syscall.Iopl":                                         "syscall",
+	"syscall.Iovec":                                        "syscall",
+	"syscall.IpAdapterInfo":                                "syscall",
+	"syscall.IpAddrString":                                 "syscall",
+	"syscall.IpAddressString":                              "syscall",
+	"syscall.IpMaskString":                                 "syscall",
+	"syscall.Issetugid":                                    "syscall",
+	"syscall.KEY_ALL_ACCESS":                               "syscall",
+	"syscall.KEY_CREATE_LINK":                              "syscall",
+	"syscall.KEY_CREATE_SUB_KEY":                           "syscall",
+	"syscall.KEY_ENUMERATE_SUB_KEYS":                       "syscall",
+	"syscall.KEY_EXECUTE":                                  "syscall",
+	"syscall.KEY_NOTIFY":                                   "syscall",
+	"syscall.KEY_QUERY_VALUE":                              "syscall",
+	"syscall.KEY_READ":                                     "syscall",
+	"syscall.KEY_SET_VALUE":                                "syscall",
+	"syscall.KEY_WOW64_32KEY":                              "syscall",
+	"syscall.KEY_WOW64_64KEY":                              "syscall",
+	"syscall.KEY_WRITE":                                    "syscall",
+	"syscall.Kevent":                                       "syscall",
+	"syscall.Kevent_t":                                     "syscall",
+	"syscall.Kill":                                         "syscall",
+	"syscall.Klogctl":                                      "syscall",
+	"syscall.Kqueue":                                       "syscall",
+	"syscall.LANG_ENGLISH":                                 "syscall",
+	"syscall.LAYERED_PROTOCOL":                             "syscall",
+	"syscall.LCNT_OVERLOAD_FLUSH":                          "syscall",
+	"syscall.LINUX_REBOOT_CMD_CAD_OFF":                     "syscall",
+	"syscall.LINUX_REBOOT_CMD_CAD_ON":                      "syscall",
+	"syscall.LINUX_REBOOT_CMD_HALT":                        "syscall",
+	"syscall.LINUX_REBOOT_CMD_KEXEC":                       "syscall",
+	"syscall.LINUX_REBOOT_CMD_POWER_OFF":                   "syscall",
+	"syscall.LINUX_REBOOT_CMD_RESTART":                     "syscall",
+	"syscall.LINUX_REBOOT_CMD_RESTART2":                    "syscall",
+	"syscall.LINUX_REBOOT_CMD_SW_SUSPEND":                  "syscall",
+	"syscall.LINUX_REBOOT_MAGIC1":                          "syscall",
+	"syscall.LINUX_REBOOT_MAGIC2":                          "syscall",
+	"syscall.LOCK_EX":                                      "syscall",
+	"syscall.LOCK_NB":                                      "syscall",
+	"syscall.LOCK_SH":                                      "syscall",
+	"syscall.LOCK_UN":                                      "syscall",
+	"syscall.LazyDLL":                                      "syscall",
+	"syscall.LazyProc":                                     "syscall",
+	"syscall.Lchown":                                       "syscall",
+	"syscall.Linger":                                       "syscall",
+	"syscall.Link":                                         "syscall",
+	"syscall.Listen":                                       "syscall",
+	"syscall.Listxattr":                                    "syscall",
+	"syscall.LoadCancelIoEx":                               "syscall",
+	"syscall.LoadConnectEx":                                "syscall",
+	"syscall.LoadDLL":                                      "syscall",
+	"syscall.LoadGetAddrInfo":                              "syscall",
+	"syscall.LoadLibrary":                                  "syscall",
+	"syscall.LoadSetFileCompletionNotificationModes":       "syscall",
+	"syscall.LocalFree":                                    "syscall",
+	"syscall.Log2phys_t":                                   "syscall",
+	"syscall.LookupAccountName":                            "syscall",
+	"syscall.LookupAccountSid":                             "syscall",
+	"syscall.LookupSID":                                    "syscall",
+	"syscall.LsfJump":                                      "syscall",
+	"syscall.LsfSocket":                                    "syscall",
+	"syscall.LsfStmt":                                      "syscall",
+	"syscall.Lstat":                                        "syscall",
+	"syscall.MADV_AUTOSYNC":                                "syscall",
+	"syscall.MADV_CAN_REUSE":                               "syscall",
+	"syscall.MADV_CORE":                                    "syscall",
+	"syscall.MADV_DOFORK":                                  "syscall",
+	"syscall.MADV_DONTFORK":                                "syscall",
+	"syscall.MADV_DONTNEED":                                "syscall",
+	"syscall.MADV_FREE":                                    "syscall",
+	"syscall.MADV_FREE_REUSABLE":                           "syscall",
+	"syscall.MADV_FREE_REUSE":                              "syscall",
+	"syscall.MADV_HUGEPAGE":                                "syscall",
+	"syscall.MADV_HWPOISON":                                "syscall",
+	"syscall.MADV_MERGEABLE":                               "syscall",
+	"syscall.MADV_NOCORE":                                  "syscall",
+	"syscall.MADV_NOHUGEPAGE":                              "syscall",
+	"syscall.MADV_NORMAL":                                  "syscall",
+	"syscall.MADV_NOSYNC":                                  "syscall",
+	"syscall.MADV_PROTECT":                                 "syscall",
+	"syscall.MADV_RANDOM":                                  "syscall",
+	"syscall.MADV_REMOVE":                                  "syscall",
+	"syscall.MADV_SEQUENTIAL":                              "syscall",
+	"syscall.MADV_UNMERGEABLE":                             "syscall",
+	"syscall.MADV_WILLNEED":                                "syscall",
+	"syscall.MADV_ZERO_WIRED_PAGES":                        "syscall",
+	"syscall.MAP_32BIT":                                    "syscall",
+	"syscall.MAP_ANON":                                     "syscall",
+	"syscall.MAP_ANONYMOUS":                                "syscall",
+	"syscall.MAP_COPY":                                     "syscall",
+	"syscall.MAP_DENYWRITE":                                "syscall",
+	"syscall.MAP_EXECUTABLE":                               "syscall",
+	"syscall.MAP_FILE":                                     "syscall",
+	"syscall.MAP_FIXED":                                    "syscall",
+	"syscall.MAP_GROWSDOWN":                                "syscall",
+	"syscall.MAP_HASSEMAPHORE":                             "syscall",
+	"syscall.MAP_HUGETLB":                                  "syscall",
+	"syscall.MAP_JIT":                                      "syscall",
+	"syscall.MAP_LOCKED":                                   "syscall",
+	"syscall.MAP_NOCACHE":                                  "syscall",
+	"syscall.MAP_NOCORE":                                   "syscall",
+	"syscall.MAP_NOEXTEND":                                 "syscall",
+	"syscall.MAP_NONBLOCK":                                 "syscall",
+	"syscall.MAP_NORESERVE":                                "syscall",
+	"syscall.MAP_NOSYNC":                                   "syscall",
+	"syscall.MAP_POPULATE":                                 "syscall",
+	"syscall.MAP_PREFAULT_READ":                            "syscall",
+	"syscall.MAP_PRIVATE":                                  "syscall",
+	"syscall.MAP_RENAME":                                   "syscall",
+	"syscall.MAP_RESERVED0080":                             "syscall",
+	"syscall.MAP_RESERVED0100":                             "syscall",
+	"syscall.MAP_SHARED":                                   "syscall",
+	"syscall.MAP_STACK":                                    "syscall",
+	"syscall.MAP_TYPE":                                     "syscall",
+	"syscall.MAXLEN_IFDESCR":                               "syscall",
+	"syscall.MAXLEN_PHYSADDR":                              "syscall",
+	"syscall.MAX_ADAPTER_ADDRESS_LENGTH":                   "syscall",
+	"syscall.MAX_ADAPTER_DESCRIPTION_LENGTH":               "syscall",
+	"syscall.MAX_ADAPTER_NAME_LENGTH":                      "syscall",
+	"syscall.MAX_COMPUTERNAME_LENGTH":                      "syscall",
+	"syscall.MAX_INTERFACE_NAME_LEN":                       "syscall",
+	"syscall.MAX_LONG_PATH":                                "syscall",
+	"syscall.MAX_PATH":                                     "syscall",
+	"syscall.MAX_PROTOCOL_CHAIN":                           "syscall",
+	"syscall.MCL_CURRENT":                                  "syscall",
+	"syscall.MCL_FUTURE":                                   "syscall",
+	"syscall.MNT_DETACH":                                   "syscall",
+	"syscall.MNT_EXPIRE":                                   "syscall",
+	"syscall.MNT_FORCE":                                    "syscall",
+	"syscall.MSG_BCAST":                                    "syscall",
+	"syscall.MSG_CMSG_CLOEXEC":                             "syscall",
+	"syscall.MSG_COMPAT":                                   "syscall",
+	"syscall.MSG_CONFIRM":                                  "syscall",
+	"syscall.MSG_CONTROLMBUF":                              "syscall",
+	"syscall.MSG_CTRUNC":                                   "syscall",
+	"syscall.MSG_DONTROUTE":                                "syscall",
+	"syscall.MSG_DONTWAIT":                                 "syscall",
+	"syscall.MSG_EOF":                                      "syscall",
+	"syscall.MSG_EOR":                                      "syscall",
+	"syscall.MSG_ERRQUEUE":                                 "syscall",
+	"syscall.MSG_FASTOPEN":                                 "syscall",
+	"syscall.MSG_FIN":                                      "syscall",
+	"syscall.MSG_FLUSH":                                    "syscall",
+	"syscall.MSG_HAVEMORE":                                 "syscall",
+	"syscall.MSG_HOLD":                                     "syscall",
+	"syscall.MSG_IOVUSRSPACE":                              "syscall",
+	"syscall.MSG_LENUSRSPACE":                              "syscall",
+	"syscall.MSG_MCAST":                                    "syscall",
+	"syscall.MSG_MORE":                                     "syscall",
+	"syscall.MSG_NAMEMBUF":                                 "syscall",
+	"syscall.MSG_NBIO":                                     "syscall",
+	"syscall.MSG_NEEDSA":                                   "syscall",
+	"syscall.MSG_NOSIGNAL":                                 "syscall",
+	"syscall.MSG_NOTIFICATION":                             "syscall",
+	"syscall.MSG_OOB":                                      "syscall",
+	"syscall.MSG_PEEK":                                     "syscall",
+	"syscall.MSG_PROXY":                                    "syscall",
+	"syscall.MSG_RCVMORE":                                  "syscall",
+	"syscall.MSG_RST":                                      "syscall",
+	"syscall.MSG_SEND":                                     "syscall",
+	"syscall.MSG_SYN":                                      "syscall",
+	"syscall.MSG_TRUNC":                                    "syscall",
+	"syscall.MSG_TRYHARD":                                  "syscall",
+	"syscall.MSG_USERFLAGS":                                "syscall",
+	"syscall.MSG_WAITALL":                                  "syscall",
+	"syscall.MSG_WAITFORONE":                               "syscall",
+	"syscall.MSG_WAITSTREAM":                               "syscall",
+	"syscall.MS_ACTIVE":                                    "syscall",
+	"syscall.MS_ASYNC":                                     "syscall",
+	"syscall.MS_BIND":                                      "syscall",
+	"syscall.MS_DEACTIVATE":                                "syscall",
+	"syscall.MS_DIRSYNC":                                   "syscall",
+	"syscall.MS_INVALIDATE":                                "syscall",
+	"syscall.MS_I_VERSION":                                 "syscall",
+	"syscall.MS_KERNMOUNT":                                 "syscall",
+	"syscall.MS_KILLPAGES":                                 "syscall",
+	"syscall.MS_MANDLOCK":                                  "syscall",
+	"syscall.MS_MGC_MSK":                                   "syscall",
+	"syscall.MS_MGC_VAL":                                   "syscall",
+	"syscall.MS_MOVE":                                      "syscall",
+	"syscall.MS_NOATIME":                                   "syscall",
+	"syscall.MS_NODEV":                                     "syscall",
+	"syscall.MS_NODIRATIME":                                "syscall",
+	"syscall.MS_NOEXEC":                                    "syscall",
+	"syscall.MS_NOSUID":                                    "syscall",
+	"syscall.MS_NOUSER":                                    "syscall",
+	"syscall.MS_POSIXACL":                                  "syscall",
+	"syscall.MS_PRIVATE":                                   "syscall",
+	"syscall.MS_RDONLY":                                    "syscall",
+	"syscall.MS_REC":                                       "syscall",
+	"syscall.MS_RELATIME":                                  "syscall",
+	"syscall.MS_REMOUNT":                                   "syscall",
+	"syscall.MS_RMT_MASK":                                  "syscall",
+	"syscall.MS_SHARED":                                    "syscall",
+	"syscall.MS_SILENT":                                    "syscall",
+	"syscall.MS_SLAVE":                                     "syscall",
+	"syscall.MS_STRICTATIME":                               "syscall",
+	"syscall.MS_SYNC":                                      "syscall",
+	"syscall.MS_SYNCHRONOUS":                               "syscall",
+	"syscall.MS_UNBINDABLE":                                "syscall",
+	"syscall.Madvise":                                      "syscall",
+	"syscall.MapViewOfFile":                                "syscall",
+	"syscall.MaxTokenInfoClass":                            "syscall",
+	"syscall.Mclpool":                                      "syscall",
+	"syscall.MibIfRow":                                     "syscall",
+	"syscall.Mkdir":                                        "syscall",
+	"syscall.Mkdirat":                                      "syscall",
+	"syscall.Mkfifo":                                       "syscall",
+	"syscall.Mknod":                                        "syscall",
+	"syscall.Mknodat":                                      "syscall",
+	"syscall.Mlock":                                        "syscall",
+	"syscall.Mlockall":                                     "syscall",
+	"syscall.Mmap":                                         "syscall",
+	"syscall.Mount":                                        "syscall",
+	"syscall.MoveFile":                                     "syscall",
+	"syscall.Mprotect":                                     "syscall",
+	"syscall.Msghdr":                                       "syscall",
+	"syscall.Munlock":                                      "syscall",
+	"syscall.Munlockall":                                   "syscall",
+	"syscall.Munmap":                                       "syscall",
+	"syscall.MustLoadDLL":                                  "syscall",
+	"syscall.NAME_MAX":                                     "syscall",
+	"syscall.NETLINK_ADD_MEMBERSHIP":                       "syscall",
+	"syscall.NETLINK_AUDIT":                                "syscall",
+	"syscall.NETLINK_BROADCAST_ERROR":                      "syscall",
+	"syscall.NETLINK_CONNECTOR":                            "syscall",
+	"syscall.NETLINK_DNRTMSG":                              "syscall",
+	"syscall.NETLINK_DROP_MEMBERSHIP":                      "syscall",
+	"syscall.NETLINK_ECRYPTFS":                             "syscall",
+	"syscall.NETLINK_FIB_LOOKUP":                           "syscall",
+	"syscall.NETLINK_FIREWALL":                             "syscall",
+	"syscall.NETLINK_GENERIC":                              "syscall",
+	"syscall.NETLINK_INET_DIAG":                            "syscall",
+	"syscall.NETLINK_IP6_FW":                               "syscall",
+	"syscall.NETLINK_ISCSI":                                "syscall",
+	"syscall.NETLINK_KOBJECT_UEVENT":                       "syscall",
+	"syscall.NETLINK_NETFILTER":                            "syscall",
+	"syscall.NETLINK_NFLOG":                                "syscall",
+	"syscall.NETLINK_NO_ENOBUFS":                           "syscall",
+	"syscall.NETLINK_PKTINFO":                              "syscall",
+	"syscall.NETLINK_RDMA":                                 "syscall",
+	"syscall.NETLINK_ROUTE":                                "syscall",
+	"syscall.NETLINK_SCSITRANSPORT":                        "syscall",
+	"syscall.NETLINK_SELINUX":                              "syscall",
+	"syscall.NETLINK_UNUSED":                               "syscall",
+	"syscall.NETLINK_USERSOCK":                             "syscall",
+	"syscall.NETLINK_XFRM":                                 "syscall",
+	"syscall.NET_RT_DUMP":                                  "syscall",
+	"syscall.NET_RT_DUMP2":                                 "syscall",
+	"syscall.NET_RT_FLAGS":                                 "syscall",
+	"syscall.NET_RT_IFLIST":                                "syscall",
+	"syscall.NET_RT_IFLIST2":                               "syscall",
+	"syscall.NET_RT_IFLISTL":                               "syscall",
+	"syscall.NET_RT_IFMALIST":                              "syscall",
+	"syscall.NET_RT_MAXID":                                 "syscall",
+	"syscall.NET_RT_OIFLIST":                               "syscall",
+	"syscall.NET_RT_OOIFLIST":                              "syscall",
+	"syscall.NET_RT_STAT":                                  "syscall",
+	"syscall.NET_RT_STATS":                                 "syscall",
+	"syscall.NET_RT_TABLE":                                 "syscall",
+	"syscall.NET_RT_TRASH":                                 "syscall",
+	"syscall.NLA_ALIGNTO":                                  "syscall",
+	"syscall.NLA_F_NESTED":                                 "syscall",
+	"syscall.NLA_F_NET_BYTEORDER":                          "syscall",
+	"syscall.NLA_HDRLEN":                                   "syscall",
+	"syscall.NLMSG_ALIGNTO":                                "syscall",
+	"syscall.NLMSG_DONE":                                   "syscall",
+	"syscall.NLMSG_ERROR":                                  "syscall",
+	"syscall.NLMSG_HDRLEN":                                 "syscall",
+	"syscall.NLMSG_MIN_TYPE":                               "syscall",
+	"syscall.NLMSG_NOOP":                                   "syscall",
+	"syscall.NLMSG_OVERRUN":                                "syscall",
+	"syscall.NLM_F_ACK":                                    "syscall",
+	"syscall.NLM_F_APPEND":                                 "syscall",
+	"syscall.NLM_F_ATOMIC":                                 "syscall",
+	"syscall.NLM_F_CREATE":                                 "syscall",
+	"syscall.NLM_F_DUMP":                                   "syscall",
+	"syscall.NLM_F_ECHO":                                   "syscall",
+	"syscall.NLM_F_EXCL":                                   "syscall",
+	"syscall.NLM_F_MATCH":                                  "syscall",
+	"syscall.NLM_F_MULTI":                                  "syscall",
+	"syscall.NLM_F_REPLACE":                                "syscall",
+	"syscall.NLM_F_REQUEST":                                "syscall",
+	"syscall.NLM_F_ROOT":                                   "syscall",
+	"syscall.NOFLSH":                                       "syscall",
+	"syscall.NOTE_ABSOLUTE":                                "syscall",
+	"syscall.NOTE_ATTRIB":                                  "syscall",
+	"syscall.NOTE_CHILD":                                   "syscall",
+	"syscall.NOTE_DELETE":                                  "syscall",
+	"syscall.NOTE_EOF":                                     "syscall",
+	"syscall.NOTE_EXEC":                                    "syscall",
+	"syscall.NOTE_EXIT":                                    "syscall",
+	"syscall.NOTE_EXITSTATUS":                              "syscall",
+	"syscall.NOTE_EXTEND":                                  "syscall",
+	"syscall.NOTE_FFAND":                                   "syscall",
+	"syscall.NOTE_FFCOPY":                                  "syscall",
+	"syscall.NOTE_FFCTRLMASK":                              "syscall",
+	"syscall.NOTE_FFLAGSMASK":                              "syscall",
+	"syscall.NOTE_FFNOP":                                   "syscall",
+	"syscall.NOTE_FFOR":                                    "syscall",
+	"syscall.NOTE_FORK":                                    "syscall",
+	"syscall.NOTE_LINK":                                    "syscall",
+	"syscall.NOTE_LOWAT":                                   "syscall",
+	"syscall.NOTE_NONE":                                    "syscall",
+	"syscall.NOTE_NSECONDS":                                "syscall",
+	"syscall.NOTE_PCTRLMASK":                               "syscall",
+	"syscall.NOTE_PDATAMASK":                               "syscall",
+	"syscall.NOTE_REAP":                                    "syscall",
+	"syscall.NOTE_RENAME":                                  "syscall",
+	"syscall.NOTE_RESOURCEEND":                             "syscall",
+	"syscall.NOTE_REVOKE":                                  "syscall",
+	"syscall.NOTE_SECONDS":                                 "syscall",
+	"syscall.NOTE_SIGNAL":                                  "syscall",
+	"syscall.NOTE_TRACK":                                   "syscall",
+	"syscall.NOTE_TRACKERR":                                "syscall",
+	"syscall.NOTE_TRIGGER":                                 "syscall",
+	"syscall.NOTE_TRUNCATE":                                "syscall",
+	"syscall.NOTE_USECONDS":                                "syscall",
+	"syscall.NOTE_VM_ERROR":                                "syscall",
+	"syscall.NOTE_VM_PRESSURE":                             "syscall",
+	"syscall.NOTE_VM_PRESSURE_SUDDEN_TERMINATE":            "syscall",
+	"syscall.NOTE_VM_PRESSURE_TERMINATE":                   "syscall",
+	"syscall.NOTE_WRITE":                                   "syscall",
+	"syscall.NameCanonical":                                "syscall",
+	"syscall.NameCanonicalEx":                              "syscall",
+	"syscall.NameDisplay":                                  "syscall",
+	"syscall.NameDnsDomain":                                "syscall",
+	"syscall.NameFullyQualifiedDN":                         "syscall",
+	"syscall.NameSamCompatible":                            "syscall",
+	"syscall.NameServicePrincipal":                         "syscall",
+	"syscall.NameUniqueId":                                 "syscall",
+	"syscall.NameUnknown":                                  "syscall",
+	"syscall.NameUserPrincipal":                            "syscall",
+	"syscall.Nanosleep":                                    "syscall",
+	"syscall.NetApiBufferFree":                             "syscall",
+	"syscall.NetGetJoinInformation":                        "syscall",
+	"syscall.NetSetupDomainName":                           "syscall",
+	"syscall.NetSetupUnjoined":                             "syscall",
+	"syscall.NetSetupUnknownStatus":                        "syscall",
+	"syscall.NetSetupWorkgroupName":                        "syscall",
+	"syscall.NetUserGetInfo":                               "syscall",
+	"syscall.NetlinkMessage":                               "syscall",
+	"syscall.NetlinkRIB":                                   "syscall",
+	"syscall.NetlinkRouteAttr":                             "syscall",
+	"syscall.NetlinkRouteRequest":                          "syscall",
+	"syscall.NewCallback":                                  "syscall",
+	"syscall.NewLazyDLL":                                   "syscall",
+	"syscall.NlAttr":                                       "syscall",
+	"syscall.NlMsgerr":                                     "syscall",
+	"syscall.NlMsghdr":                                     "syscall",
+	"syscall.NsecToFiletime":                               "syscall",
+	"syscall.NsecToTimespec":                               "syscall",
+	"syscall.NsecToTimeval":                                "syscall",
+	"syscall.Ntohs":                                        "syscall",
+	"syscall.OCRNL":                                        "syscall",
+	"syscall.OFDEL":                                        "syscall",
+	"syscall.OFILL":                                        "syscall",
+	"syscall.OFIOGETBMAP":                                  "syscall",
+	"syscall.OID_PKIX_KP_SERVER_AUTH":                      "syscall",
+	"syscall.OID_SERVER_GATED_CRYPTO":                      "syscall",
+	"syscall.OID_SGC_NETSCAPE":                             "syscall",
+	"syscall.OLCUC":                                        "syscall",
+	"syscall.ONLCR":                                        "syscall",
+	"syscall.ONLRET":                                       "syscall",
+	"syscall.ONOCR":                                        "syscall",
+	"syscall.ONOEOT":                                       "syscall",
+	"syscall.OPEN_ALWAYS":                                  "syscall",
+	"syscall.OPEN_EXISTING":                                "syscall",
+	"syscall.OPOST":                                        "syscall",
+	"syscall.O_ACCMODE":                                    "syscall",
+	"syscall.O_ALERT":                                      "syscall",
+	"syscall.O_ALT_IO":                                     "syscall",
+	"syscall.O_APPEND":                                     "syscall",
+	"syscall.O_ASYNC":                                      "syscall",
+	"syscall.O_CLOEXEC":                                    "syscall",
+	"syscall.O_CREAT":                                      "syscall",
+	"syscall.O_DIRECT":                                     "syscall",
+	"syscall.O_DIRECTORY":                                  "syscall",
+	"syscall.O_DSYNC":                                      "syscall",
+	"syscall.O_EVTONLY":                                    "syscall",
+	"syscall.O_EXCL":                                       "syscall",
+	"syscall.O_EXEC":                                       "syscall",
+	"syscall.O_EXLOCK":                                     "syscall",
+	"syscall.O_FSYNC":                                      "syscall",
+	"syscall.O_LARGEFILE":                                  "syscall",
+	"syscall.O_NDELAY":                                     "syscall",
+	"syscall.O_NOATIME":                                    "syscall",
+	"syscall.O_NOCTTY":                                     "syscall",
+	"syscall.O_NOFOLLOW":                                   "syscall",
+	"syscall.O_NONBLOCK":                                   "syscall",
+	"syscall.O_NOSIGPIPE":                                  "syscall",
+	"syscall.O_POPUP":                                      "syscall",
+	"syscall.O_RDONLY":                                     "syscall",
+	"syscall.O_RDWR":                                       "syscall",
+	"syscall.O_RSYNC":                                      "syscall",
+	"syscall.O_SHLOCK":                                     "syscall",
+	"syscall.O_SYMLINK":                                    "syscall",
+	"syscall.O_SYNC":                                       "syscall",
+	"syscall.O_TRUNC":                                      "syscall",
+	"syscall.O_TTY_INIT":                                   "syscall",
+	"syscall.O_WRONLY":                                     "syscall",
+	"syscall.Open":                                         "syscall",
+	"syscall.OpenCurrentProcessToken":                      "syscall",
+	"syscall.OpenProcess":                                  "syscall",
+	"syscall.OpenProcessToken":                             "syscall",
+	"syscall.Openat":                                       "syscall",
+	"syscall.Overlapped":                                   "syscall",
+	"syscall.PACKET_ADD_MEMBERSHIP":                        "syscall",
+	"syscall.PACKET_BROADCAST":                             "syscall",
+	"syscall.PACKET_DROP_MEMBERSHIP":                       "syscall",
+	"syscall.PACKET_FASTROUTE":                             "syscall",
+	"syscall.PACKET_HOST":                                  "syscall",
+	"syscall.PACKET_LOOPBACK":                              "syscall",
+	"syscall.PACKET_MR_ALLMULTI":                           "syscall",
+	"syscall.PACKET_MR_MULTICAST":                          "syscall",
+	"syscall.PACKET_MR_PROMISC":                            "syscall",
+	"syscall.PACKET_MULTICAST":                             "syscall",
+	"syscall.PACKET_OTHERHOST":                             "syscall",
+	"syscall.PACKET_OUTGOING":                              "syscall",
+	"syscall.PACKET_RECV_OUTPUT":                           "syscall",
+	"syscall.PACKET_RX_RING":                               "syscall",
+	"syscall.PACKET_STATISTICS":                            "syscall",
+	"syscall.PAGE_EXECUTE_READ":                            "syscall",
+	"syscall.PAGE_EXECUTE_READWRITE":                       "syscall",
+	"syscall.PAGE_EXECUTE_WRITECOPY":                       "syscall",
+	"syscall.PAGE_READONLY":                                "syscall",
+	"syscall.PAGE_READWRITE":                               "syscall",
+	"syscall.PAGE_WRITECOPY":                               "syscall",
+	"syscall.PARENB":                                       "syscall",
+	"syscall.PARMRK":                                       "syscall",
+	"syscall.PARODD":                                       "syscall",
+	"syscall.PENDIN":                                       "syscall",
+	"syscall.PFL_HIDDEN":                                   "syscall",
+	"syscall.PFL_MATCHES_PROTOCOL_ZERO":                    "syscall",
+	"syscall.PFL_MULTIPLE_PROTO_ENTRIES":                   "syscall",
+	"syscall.PFL_NETWORKDIRECT_PROVIDER":                   "syscall",
+	"syscall.PFL_RECOMMENDED_PROTO_ENTRY":                  "syscall",
+	"syscall.PF_FLUSH":                                     "syscall",
+	"syscall.PKCS_7_ASN_ENCODING":                          "syscall",
+	"syscall.PMC5_PIPELINE_FLUSH":                          "syscall",
+	"syscall.PRIO_PGRP":                                    "syscall",
+	"syscall.PRIO_PROCESS":                                 "syscall",
+	"syscall.PRIO_USER":                                    "syscall",
+	"syscall.PRI_IOFLUSH":                                  "syscall",
+	"syscall.PROCESS_QUERY_INFORMATION":                    "syscall",
+	"syscall.PROCESS_TERMINATE":                            "syscall",
+	"syscall.PROT_EXEC":                                    "syscall",
+	"syscall.PROT_GROWSDOWN":                               "syscall",
+	"syscall.PROT_GROWSUP":                                 "syscall",
+	"syscall.PROT_NONE":                                    "syscall",
+	"syscall.PROT_READ":                                    "syscall",
+	"syscall.PROT_WRITE":                                   "syscall",
+	"syscall.PROV_DH_SCHANNEL":                             "syscall",
+	"syscall.PROV_DSS":                                     "syscall",
+	"syscall.PROV_DSS_DH":                                  "syscall",
+	"syscall.PROV_EC_ECDSA_FULL":                           "syscall",
+	"syscall.PROV_EC_ECDSA_SIG":                            "syscall",
+	"syscall.PROV_EC_ECNRA_FULL":                           "syscall",
+	"syscall.PROV_EC_ECNRA_SIG":                            "syscall",
+	"syscall.PROV_FORTEZZA":                                "syscall",
+	"syscall.PROV_INTEL_SEC":                               "syscall",
+	"syscall.PROV_MS_EXCHANGE":                             "syscall",
+	"syscall.PROV_REPLACE_OWF":                             "syscall",
+	"syscall.PROV_RNG":                                     "syscall",
+	"syscall.PROV_RSA_AES":                                 "syscall",
+	"syscall.PROV_RSA_FULL":                                "syscall",
+	"syscall.PROV_RSA_SCHANNEL":                            "syscall",
+	"syscall.PROV_RSA_SIG":                                 "syscall",
+	"syscall.PROV_SPYRUS_LYNKS":                            "syscall",
+	"syscall.PROV_SSL":                                     "syscall",
+	"syscall.PR_CAPBSET_DROP":                              "syscall",
+	"syscall.PR_CAPBSET_READ":                              "syscall",
+	"syscall.PR_CLEAR_SECCOMP_FILTER":                      "syscall",
+	"syscall.PR_ENDIAN_BIG":                                "syscall",
+	"syscall.PR_ENDIAN_LITTLE":                             "syscall",
+	"syscall.PR_ENDIAN_PPC_LITTLE":                         "syscall",
+	"syscall.PR_FPEMU_NOPRINT":                             "syscall",
+	"syscall.PR_FPEMU_SIGFPE":                              "syscall",
+	"syscall.PR_FP_EXC_ASYNC":                              "syscall",
+	"syscall.PR_FP_EXC_DISABLED":                           "syscall",
+	"syscall.PR_FP_EXC_DIV":                                "syscall",
+	"syscall.PR_FP_EXC_INV":                                "syscall",
+	"syscall.PR_FP_EXC_NONRECOV":                           "syscall",
+	"syscall.PR_FP_EXC_OVF":                                "syscall",
+	"syscall.PR_FP_EXC_PRECISE":                            "syscall",
+	"syscall.PR_FP_EXC_RES":                                "syscall",
+	"syscall.PR_FP_EXC_SW_ENABLE":                          "syscall",
+	"syscall.PR_FP_EXC_UND":                                "syscall",
+	"syscall.PR_GET_DUMPABLE":                              "syscall",
+	"syscall.PR_GET_ENDIAN":                                "syscall",
+	"syscall.PR_GET_FPEMU":                                 "syscall",
+	"syscall.PR_GET_FPEXC":                                 "syscall",
+	"syscall.PR_GET_KEEPCAPS":                              "syscall",
+	"syscall.PR_GET_NAME":                                  "syscall",
+	"syscall.PR_GET_PDEATHSIG":                             "syscall",
+	"syscall.PR_GET_SECCOMP":                               "syscall",
+	"syscall.PR_GET_SECCOMP_FILTER":                        "syscall",
+	"syscall.PR_GET_SECUREBITS":                            "syscall",
+	"syscall.PR_GET_TIMERSLACK":                            "syscall",
+	"syscall.PR_GET_TIMING":                                "syscall",
+	"syscall.PR_GET_TSC":                                   "syscall",
+	"syscall.PR_GET_UNALIGN":                               "syscall",
+	"syscall.PR_MCE_KILL":                                  "syscall",
+	"syscall.PR_MCE_KILL_CLEAR":                            "syscall",
+	"syscall.PR_MCE_KILL_DEFAULT":                          "syscall",
+	"syscall.PR_MCE_KILL_EARLY":                            "syscall",
+	"syscall.PR_MCE_KILL_GET":                              "syscall",
+	"syscall.PR_MCE_KILL_LATE":                             "syscall",
+	"syscall.PR_MCE_KILL_SET":                              "syscall",
+	"syscall.PR_SECCOMP_FILTER_EVENT":                      "syscall",
+	"syscall.PR_SECCOMP_FILTER_SYSCALL":                    "syscall",
+	"syscall.PR_SET_DUMPABLE":                              "syscall",
+	"syscall.PR_SET_ENDIAN":                                "syscall",
+	"syscall.PR_SET_FPEMU":                                 "syscall",
+	"syscall.PR_SET_FPEXC":                                 "syscall",
+	"syscall.PR_SET_KEEPCAPS":                              "syscall",
+	"syscall.PR_SET_NAME":                                  "syscall",
+	"syscall.PR_SET_PDEATHSIG":                             "syscall",
+	"syscall.PR_SET_PTRACER":                               "syscall",
+	"syscall.PR_SET_SECCOMP":                               "syscall",
+	"syscall.PR_SET_SECCOMP_FILTER":                        "syscall",
+	"syscall.PR_SET_SECUREBITS":                            "syscall",
+	"syscall.PR_SET_TIMERSLACK":                            "syscall",
+	"syscall.PR_SET_TIMING":                                "syscall",
+	"syscall.PR_SET_TSC":                                   "syscall",
+	"syscall.PR_SET_UNALIGN":                               "syscall",
+	"syscall.PR_TASK_PERF_EVENTS_DISABLE":                  "syscall",
+	"syscall.PR_TASK_PERF_EVENTS_ENABLE":                   "syscall",
+	"syscall.PR_TIMING_STATISTICAL":                        "syscall",
+	"syscall.PR_TIMING_TIMESTAMP":                          "syscall",
+	"syscall.PR_TSC_ENABLE":                                "syscall",
+	"syscall.PR_TSC_SIGSEGV":                               "syscall",
+	"syscall.PR_UNALIGN_NOPRINT":                           "syscall",
+	"syscall.PR_UNALIGN_SIGBUS":                            "syscall",
+	"syscall.PTRACE_ARCH_PRCTL":                            "syscall",
+	"syscall.PTRACE_ATTACH":                                "syscall",
+	"syscall.PTRACE_CONT":                                  "syscall",
+	"syscall.PTRACE_DETACH":                                "syscall",
+	"syscall.PTRACE_EVENT_CLONE":                           "syscall",
+	"syscall.PTRACE_EVENT_EXEC":                            "syscall",
+	"syscall.PTRACE_EVENT_EXIT":                            "syscall",
+	"syscall.PTRACE_EVENT_FORK":                            "syscall",
+	"syscall.PTRACE_EVENT_VFORK":                           "syscall",
+	"syscall.PTRACE_EVENT_VFORK_DONE":                      "syscall",
+	"syscall.PTRACE_GETCRUNCHREGS":                         "syscall",
+	"syscall.PTRACE_GETEVENTMSG":                           "syscall",
+	"syscall.PTRACE_GETFPREGS":                             "syscall",
+	"syscall.PTRACE_GETFPXREGS":                            "syscall",
+	"syscall.PTRACE_GETHBPREGS":                            "syscall",
+	"syscall.PTRACE_GETREGS":                               "syscall",
+	"syscall.PTRACE_GETREGSET":                             "syscall",
+	"syscall.PTRACE_GETSIGINFO":                            "syscall",
+	"syscall.PTRACE_GETVFPREGS":                            "syscall",
+	"syscall.PTRACE_GETWMMXREGS":                           "syscall",
+	"syscall.PTRACE_GET_THREAD_AREA":                       "syscall",
+	"syscall.PTRACE_KILL":                                  "syscall",
+	"syscall.PTRACE_OLDSETOPTIONS":                         "syscall",
+	"syscall.PTRACE_O_MASK":                                "syscall",
+	"syscall.PTRACE_O_TRACECLONE":                          "syscall",
+	"syscall.PTRACE_O_TRACEEXEC":                           "syscall",
+	"syscall.PTRACE_O_TRACEEXIT":                           "syscall",
+	"syscall.PTRACE_O_TRACEFORK":                           "syscall",
+	"syscall.PTRACE_O_TRACESYSGOOD":                        "syscall",
+	"syscall.PTRACE_O_TRACEVFORK":                          "syscall",
+	"syscall.PTRACE_O_TRACEVFORKDONE":                      "syscall",
+	"syscall.PTRACE_PEEKDATA":                              "syscall",
+	"syscall.PTRACE_PEEKTEXT":                              "syscall",
+	"syscall.PTRACE_PEEKUSR":                               "syscall",
+	"syscall.PTRACE_POKEDATA":                              "syscall",
+	"syscall.PTRACE_POKETEXT":                              "syscall",
+	"syscall.PTRACE_POKEUSR":                               "syscall",
+	"syscall.PTRACE_SETCRUNCHREGS":                         "syscall",
+	"syscall.PTRACE_SETFPREGS":                             "syscall",
+	"syscall.PTRACE_SETFPXREGS":                            "syscall",
+	"syscall.PTRACE_SETHBPREGS":                            "syscall",
+	"syscall.PTRACE_SETOPTIONS":                            "syscall",
+	"syscall.PTRACE_SETREGS":                               "syscall",
+	"syscall.PTRACE_SETREGSET":                             "syscall",
+	"syscall.PTRACE_SETSIGINFO":                            "syscall",
+	"syscall.PTRACE_SETVFPREGS":                            "syscall",
+	"syscall.PTRACE_SETWMMXREGS":                           "syscall",
+	"syscall.PTRACE_SET_SYSCALL":                           "syscall",
+	"syscall.PTRACE_SET_THREAD_AREA":                       "syscall",
+	"syscall.PTRACE_SINGLEBLOCK":                           "syscall",
+	"syscall.PTRACE_SINGLESTEP":                            "syscall",
+	"syscall.PTRACE_SYSCALL":                               "syscall",
+	"syscall.PTRACE_SYSEMU":                                "syscall",
+	"syscall.PTRACE_SYSEMU_SINGLESTEP":                     "syscall",
+	"syscall.PTRACE_TRACEME":                               "syscall",
+	"syscall.PT_ATTACH":                                    "syscall",
+	"syscall.PT_ATTACHEXC":                                 "syscall",
+	"syscall.PT_CONTINUE":                                  "syscall",
+	"syscall.PT_DATA_ADDR":                                 "syscall",
+	"syscall.PT_DENY_ATTACH":                               "syscall",
+	"syscall.PT_DETACH":                                    "syscall",
+	"syscall.PT_FIRSTMACH":                                 "syscall",
+	"syscall.PT_FORCEQUOTA":                                "syscall",
+	"syscall.PT_KILL":                                      "syscall",
+	"syscall.PT_MASK":                                      "syscall",
+	"syscall.PT_READ_D":                                    "syscall",
+	"syscall.PT_READ_I":                                    "syscall",
+	"syscall.PT_READ_U":                                    "syscall",
+	"syscall.PT_SIGEXC":                                    "syscall",
+	"syscall.PT_STEP":                                      "syscall",
+	"syscall.PT_TEXT_ADDR":                                 "syscall",
+	"syscall.PT_TEXT_END_ADDR":                             "syscall",
+	"syscall.PT_THUPDATE":                                  "syscall",
+	"syscall.PT_TRACE_ME":                                  "syscall",
+	"syscall.PT_WRITE_D":                                   "syscall",
+	"syscall.PT_WRITE_I":                                   "syscall",
+	"syscall.PT_WRITE_U":                                   "syscall",
+	"syscall.ParseDirent":                                  "syscall",
+	"syscall.ParseNetlinkMessage":                          "syscall",
+	"syscall.ParseNetlinkRouteAttr":                        "syscall",
+	"syscall.ParseRoutingMessage":                          "syscall",
+	"syscall.ParseRoutingSockaddr":                         "syscall",
+	"syscall.ParseSocketControlMessage":                    "syscall",
+	"syscall.ParseUnixCredentials":                         "syscall",
+	"syscall.ParseUnixRights":                              "syscall",
+	"syscall.PathMax":                                      "syscall",
+	"syscall.Pathconf":                                     "syscall",
+	"syscall.Pause":                                        "syscall",
+	"syscall.Pipe":                                         "syscall",
+	"syscall.Pipe2":                                        "syscall",
+	"syscall.PivotRoot":                                    "syscall",
+	"syscall.PostQueuedCompletionStatus":                   "syscall",
+	"syscall.Pread":                                        "syscall",
+	"syscall.Proc":                                         "syscall",
+	"syscall.ProcAttr":                                     "syscall",
+	"syscall.ProcessInformation":                           "syscall",
+	"syscall.Protoent":                                     "syscall",
+	"syscall.PtraceAttach":                                 "syscall",
+	"syscall.PtraceCont":                                   "syscall",
+	"syscall.PtraceDetach":                                 "syscall",
+	"syscall.PtraceGetEventMsg":                            "syscall",
+	"syscall.PtraceGetRegs":                                "syscall",
+	"syscall.PtracePeekData":                               "syscall",
+	"syscall.PtracePeekText":                               "syscall",
+	"syscall.PtracePokeData":                               "syscall",
+	"syscall.PtracePokeText":                               "syscall",
+	"syscall.PtraceRegs":                                   "syscall",
+	"syscall.PtraceSetOptions":                             "syscall",
+	"syscall.PtraceSetRegs":                                "syscall",
+	"syscall.PtraceSingleStep":                             "syscall",
+	"syscall.PtraceSyscall":                                "syscall",
+	"syscall.Pwrite":                                       "syscall",
+	"syscall.REG_BINARY":                                   "syscall",
+	"syscall.REG_DWORD":                                    "syscall",
+	"syscall.REG_DWORD_BIG_ENDIAN":                         "syscall",
+	"syscall.REG_DWORD_LITTLE_ENDIAN":                      "syscall",
+	"syscall.REG_EXPAND_SZ":                                "syscall",
+	"syscall.REG_FULL_RESOURCE_DESCRIPTOR":                 "syscall",
+	"syscall.REG_LINK":                                     "syscall",
+	"syscall.REG_MULTI_SZ":                                 "syscall",
+	"syscall.REG_NONE":                                     "syscall",
+	"syscall.REG_QWORD":                                    "syscall",
+	"syscall.REG_QWORD_LITTLE_ENDIAN":                      "syscall",
+	"syscall.REG_RESOURCE_LIST":                            "syscall",
+	"syscall.REG_RESOURCE_REQUIREMENTS_LIST":               "syscall",
+	"syscall.REG_SZ":                                       "syscall",
+	"syscall.RLIMIT_AS":                                    "syscall",
+	"syscall.RLIMIT_CORE":                                  "syscall",
+	"syscall.RLIMIT_CPU":                                   "syscall",
+	"syscall.RLIMIT_DATA":                                  "syscall",
+	"syscall.RLIMIT_FSIZE":                                 "syscall",
+	"syscall.RLIMIT_NOFILE":                                "syscall",
+	"syscall.RLIMIT_STACK":                                 "syscall",
+	"syscall.RLIM_INFINITY":                                "syscall",
+	"syscall.RTAX_ADVMSS":                                  "syscall",
+	"syscall.RTAX_AUTHOR":                                  "syscall",
+	"syscall.RTAX_BRD":                                     "syscall",
+	"syscall.RTAX_CWND":                                    "syscall",
+	"syscall.RTAX_DST":                                     "syscall",
+	"syscall.RTAX_FEATURES":                                "syscall",
+	"syscall.RTAX_FEATURE_ALLFRAG":                         "syscall",
+	"syscall.RTAX_FEATURE_ECN":                             "syscall",
+	"syscall.RTAX_FEATURE_SACK":                            "syscall",
+	"syscall.RTAX_FEATURE_TIMESTAMP":                       "syscall",
+	"syscall.RTAX_GATEWAY":                                 "syscall",
+	"syscall.RTAX_GENMASK":                                 "syscall",
+	"syscall.RTAX_HOPLIMIT":                                "syscall",
+	"syscall.RTAX_IFA":                                     "syscall",
+	"syscall.RTAX_IFP":                                     "syscall",
+	"syscall.RTAX_INITCWND":                                "syscall",
+	"syscall.RTAX_INITRWND":                                "syscall",
+	"syscall.RTAX_LABEL":                                   "syscall",
+	"syscall.RTAX_LOCK":                                    "syscall",
+	"syscall.RTAX_MAX":                                     "syscall",
+	"syscall.RTAX_MTU":                                     "syscall",
+	"syscall.RTAX_NETMASK":                                 "syscall",
+	"syscall.RTAX_REORDERING":                              "syscall",
+	"syscall.RTAX_RTO_MIN":                                 "syscall",
+	"syscall.RTAX_RTT":                                     "syscall",
+	"syscall.RTAX_RTTVAR":                                  "syscall",
+	"syscall.RTAX_SRC":                                     "syscall",
+	"syscall.RTAX_SRCMASK":                                 "syscall",
+	"syscall.RTAX_SSTHRESH":                                "syscall",
+	"syscall.RTAX_TAG":                                     "syscall",
+	"syscall.RTAX_UNSPEC":                                  "syscall",
+	"syscall.RTAX_WINDOW":                                  "syscall",
+	"syscall.RTA_ALIGNTO":                                  "syscall",
+	"syscall.RTA_AUTHOR":                                   "syscall",
+	"syscall.RTA_BRD":                                      "syscall",
+	"syscall.RTA_CACHEINFO":                                "syscall",
+	"syscall.RTA_DST":                                      "syscall",
+	"syscall.RTA_FLOW":                                     "syscall",
+	"syscall.RTA_GATEWAY":                                  "syscall",
+	"syscall.RTA_GENMASK":                                  "syscall",
+	"syscall.RTA_IFA":                                      "syscall",
+	"syscall.RTA_IFP":                                      "syscall",
+	"syscall.RTA_IIF":                                      "syscall",
+	"syscall.RTA_LABEL":                                    "syscall",
+	"syscall.RTA_MAX":                                      "syscall",
+	"syscall.RTA_METRICS":                                  "syscall",
+	"syscall.RTA_MULTIPATH":                                "syscall",
+	"syscall.RTA_NETMASK":                                  "syscall",
+	"syscall.RTA_OIF":                                      "syscall",
+	"syscall.RTA_PREFSRC":                                  "syscall",
+	"syscall.RTA_PRIORITY":                                 "syscall",
+	"syscall.RTA_SRC":                                      "syscall",
+	"syscall.RTA_SRCMASK":                                  "syscall",
+	"syscall.RTA_TABLE":                                    "syscall",
+	"syscall.RTA_TAG":                                      "syscall",
+	"syscall.RTA_UNSPEC":                                   "syscall",
+	"syscall.RTCF_DIRECTSRC":                               "syscall",
+	"syscall.RTCF_DOREDIRECT":                              "syscall",
+	"syscall.RTCF_LOG":                                     "syscall",
+	"syscall.RTCF_MASQ":                                    "syscall",
+	"syscall.RTCF_NAT":                                     "syscall",
+	"syscall.RTCF_VALVE":                                   "syscall",
+	"syscall.RTF_ADDRCLASSMASK":                            "syscall",
+	"syscall.RTF_ADDRCONF":                                 "syscall",
+	"syscall.RTF_ALLONLINK":                                "syscall",
+	"syscall.RTF_ANNOUNCE":                                 "syscall",
+	"syscall.RTF_BLACKHOLE":                                "syscall",
+	"syscall.RTF_BROADCAST":                                "syscall",
+	"syscall.RTF_CACHE":                                    "syscall",
+	"syscall.RTF_CLONED":                                   "syscall",
+	"syscall.RTF_CLONING":                                  "syscall",
+	"syscall.RTF_CONDEMNED":                                "syscall",
+	"syscall.RTF_DEFAULT":                                  "syscall",
+	"syscall.RTF_DELCLONE":                                 "syscall",
+	"syscall.RTF_DONE":                                     "syscall",
+	"syscall.RTF_DYNAMIC":                                  "syscall",
+	"syscall.RTF_FLOW":                                     "syscall",
+	"syscall.RTF_FMASK":                                    "syscall",
+	"syscall.RTF_GATEWAY":                                  "syscall",
+	"syscall.RTF_HOST":                                     "syscall",
+	"syscall.RTF_IFREF":                                    "syscall",
+	"syscall.RTF_IFSCOPE":                                  "syscall",
+	"syscall.RTF_INTERFACE":                                "syscall",
+	"syscall.RTF_IRTT":                                     "syscall",
+	"syscall.RTF_LINKRT":                                   "syscall",
+	"syscall.RTF_LLDATA":                                   "syscall",
+	"syscall.RTF_LLINFO":                                   "syscall",
+	"syscall.RTF_LOCAL":                                    "syscall",
+	"syscall.RTF_MASK":                                     "syscall",
+	"syscall.RTF_MODIFIED":                                 "syscall",
+	"syscall.RTF_MPATH":                                    "syscall",
+	"syscall.RTF_MPLS":                                     "syscall",
+	"syscall.RTF_MSS":                                      "syscall",
+	"syscall.RTF_MTU":                                      "syscall",
+	"syscall.RTF_MULTICAST":                                "syscall",
+	"syscall.RTF_NAT":                                      "syscall",
+	"syscall.RTF_NOFORWARD":                                "syscall",
+	"syscall.RTF_NONEXTHOP":                                "syscall",
+	"syscall.RTF_NOPMTUDISC":                               "syscall",
+	"syscall.RTF_PERMANENT_ARP":                            "syscall",
+	"syscall.RTF_PINNED":                                   "syscall",
+	"syscall.RTF_POLICY":                                   "syscall",
+	"syscall.RTF_PRCLONING":                                "syscall",
+	"syscall.RTF_PROTO1":                                   "syscall",
+	"syscall.RTF_PROTO2":                                   "syscall",
+	"syscall.RTF_PROTO3":                                   "syscall",
+	"syscall.RTF_REINSTATE":                                "syscall",
+	"syscall.RTF_REJECT":                                   "syscall",
+	"syscall.RTF_RNH_LOCKED":                               "syscall",
+	"syscall.RTF_SOURCE":                                   "syscall",
+	"syscall.RTF_SRC":                                      "syscall",
+	"syscall.RTF_STATIC":                                   "syscall",
+	"syscall.RTF_STICKY":                                   "syscall",
+	"syscall.RTF_THROW":                                    "syscall",
+	"syscall.RTF_TUNNEL":                                   "syscall",
+	"syscall.RTF_UP":                                       "syscall",
+	"syscall.RTF_USETRAILERS":                              "syscall",
+	"syscall.RTF_WASCLONED":                                "syscall",
+	"syscall.RTF_WINDOW":                                   "syscall",
+	"syscall.RTF_XRESOLVE":                                 "syscall",
+	"syscall.RTM_ADD":                                      "syscall",
+	"syscall.RTM_BASE":                                     "syscall",
+	"syscall.RTM_CHANGE":                                   "syscall",
+	"syscall.RTM_CHGADDR":                                  "syscall",
+	"syscall.RTM_DELACTION":                                "syscall",
+	"syscall.RTM_DELADDR":                                  "syscall",
+	"syscall.RTM_DELADDRLABEL":                             "syscall",
+	"syscall.RTM_DELETE":                                   "syscall",
+	"syscall.RTM_DELLINK":                                  "syscall",
+	"syscall.RTM_DELMADDR":                                 "syscall",
+	"syscall.RTM_DELNEIGH":                                 "syscall",
+	"syscall.RTM_DELQDISC":                                 "syscall",
+	"syscall.RTM_DELROUTE":                                 "syscall",
+	"syscall.RTM_DELRULE":                                  "syscall",
+	"syscall.RTM_DELTCLASS":                                "syscall",
+	"syscall.RTM_DELTFILTER":                               "syscall",
+	"syscall.RTM_DESYNC":                                   "syscall",
+	"syscall.RTM_F_CLONED":                                 "syscall",
+	"syscall.RTM_F_EQUALIZE":                               "syscall",
+	"syscall.RTM_F_NOTIFY":                                 "syscall",
+	"syscall.RTM_F_PREFIX":                                 "syscall",
+	"syscall.RTM_GET":                                      "syscall",
+	"syscall.RTM_GET2":                                     "syscall",
+	"syscall.RTM_GETACTION":                                "syscall",
+	"syscall.RTM_GETADDR":                                  "syscall",
+	"syscall.RTM_GETADDRLABEL":                             "syscall",
+	"syscall.RTM_GETANYCAST":                               "syscall",
+	"syscall.RTM_GETDCB":                                   "syscall",
+	"syscall.RTM_GETLINK":                                  "syscall",
+	"syscall.RTM_GETMULTICAST":                             "syscall",
+	"syscall.RTM_GETNEIGH":                                 "syscall",
+	"syscall.RTM_GETNEIGHTBL":                              "syscall",
+	"syscall.RTM_GETQDISC":                                 "syscall",
+	"syscall.RTM_GETROUTE":                                 "syscall",
+	"syscall.RTM_GETRULE":                                  "syscall",
+	"syscall.RTM_GETTCLASS":                                "syscall",
+	"syscall.RTM_GETTFILTER":                               "syscall",
+	"syscall.RTM_IEEE80211":                                "syscall",
+	"syscall.RTM_IFANNOUNCE":                               "syscall",
+	"syscall.RTM_IFINFO":                                   "syscall",
+	"syscall.RTM_IFINFO2":                                  "syscall",
+	"syscall.RTM_LLINFO_UPD":                               "syscall",
+	"syscall.RTM_LOCK":                                     "syscall",
+	"syscall.RTM_LOSING":                                   "syscall",
+	"syscall.RTM_MAX":                                      "syscall",
+	"syscall.RTM_MAXSIZE":                                  "syscall",
+	"syscall.RTM_MISS":                                     "syscall",
+	"syscall.RTM_NEWACTION":                                "syscall",
+	"syscall.RTM_NEWADDR":                                  "syscall",
+	"syscall.RTM_NEWADDRLABEL":                             "syscall",
+	"syscall.RTM_NEWLINK":                                  "syscall",
+	"syscall.RTM_NEWMADDR":                                 "syscall",
+	"syscall.RTM_NEWMADDR2":                                "syscall",
+	"syscall.RTM_NEWNDUSEROPT":                             "syscall",
+	"syscall.RTM_NEWNEIGH":                                 "syscall",
+	"syscall.RTM_NEWNEIGHTBL":                              "syscall",
+	"syscall.RTM_NEWPREFIX":                                "syscall",
+	"syscall.RTM_NEWQDISC":                                 "syscall",
+	"syscall.RTM_NEWROUTE":                                 "syscall",
+	"syscall.RTM_NEWRULE":                                  "syscall",
+	"syscall.RTM_NEWTCLASS":                                "syscall",
+	"syscall.RTM_NEWTFILTER":                               "syscall",
+	"syscall.RTM_NR_FAMILIES":                              "syscall",
+	"syscall.RTM_NR_MSGTYPES":                              "syscall",
+	"syscall.RTM_OIFINFO":                                  "syscall",
+	"syscall.RTM_OLDADD":                                   "syscall",
+	"syscall.RTM_OLDDEL":                                   "syscall",
+	"syscall.RTM_OOIFINFO":                                 "syscall",
+	"syscall.RTM_REDIRECT":                                 "syscall",
+	"syscall.RTM_RESOLVE":                                  "syscall",
+	"syscall.RTM_RTTUNIT":                                  "syscall",
+	"syscall.RTM_SETDCB":                                   "syscall",
+	"syscall.RTM_SETGATE":                                  "syscall",
+	"syscall.RTM_SETLINK":                                  "syscall",
+	"syscall.RTM_SETNEIGHTBL":                              "syscall",
+	"syscall.RTM_VERSION":                                  "syscall",
+	"syscall.RTNH_ALIGNTO":                                 "syscall",
+	"syscall.RTNH_F_DEAD":                                  "syscall",
+	"syscall.RTNH_F_ONLINK":                                "syscall",
+	"syscall.RTNH_F_PERVASIVE":                             "syscall",
+	"syscall.RTNLGRP_IPV4_IFADDR":                          "syscall",
+	"syscall.RTNLGRP_IPV4_MROUTE":                          "syscall",
+	"syscall.RTNLGRP_IPV4_ROUTE":                           "syscall",
+	"syscall.RTNLGRP_IPV4_RULE":                            "syscall",
+	"syscall.RTNLGRP_IPV6_IFADDR":                          "syscall",
+	"syscall.RTNLGRP_IPV6_IFINFO":                          "syscall",
+	"syscall.RTNLGRP_IPV6_MROUTE":                          "syscall",
+	"syscall.RTNLGRP_IPV6_PREFIX":                          "syscall",
+	"syscall.RTNLGRP_IPV6_ROUTE":                           "syscall",
+	"syscall.RTNLGRP_IPV6_RULE":                            "syscall",
+	"syscall.RTNLGRP_LINK":                                 "syscall",
+	"syscall.RTNLGRP_ND_USEROPT":                           "syscall",
+	"syscall.RTNLGRP_NEIGH":                                "syscall",
+	"syscall.RTNLGRP_NONE":                                 "syscall",
+	"syscall.RTNLGRP_NOTIFY":                               "syscall",
+	"syscall.RTNLGRP_TC":                                   "syscall",
+	"syscall.RTN_ANYCAST":                                  "syscall",
+	"syscall.RTN_BLACKHOLE":                                "syscall",
+	"syscall.RTN_BROADCAST":                                "syscall",
+	"syscall.RTN_LOCAL":                                    "syscall",
+	"syscall.RTN_MAX":                                      "syscall",
+	"syscall.RTN_MULTICAST":                                "syscall",
+	"syscall.RTN_NAT":                                      "syscall",
+	"syscall.RTN_PROHIBIT":                                 "syscall",
+	"syscall.RTN_THROW":                                    "syscall",
+	"syscall.RTN_UNICAST":                                  "syscall",
+	"syscall.RTN_UNREACHABLE":                              "syscall",
+	"syscall.RTN_UNSPEC":                                   "syscall",
+	"syscall.RTN_XRESOLVE":                                 "syscall",
+	"syscall.RTPROT_BIRD":                                  "syscall",
+	"syscall.RTPROT_BOOT":                                  "syscall",
+	"syscall.RTPROT_DHCP":                                  "syscall",
+	"syscall.RTPROT_DNROUTED":                              "syscall",
+	"syscall.RTPROT_GATED":                                 "syscall",
+	"syscall.RTPROT_KERNEL":                                "syscall",
+	"syscall.RTPROT_MRT":                                   "syscall",
+	"syscall.RTPROT_NTK":                                   "syscall",
+	"syscall.RTPROT_RA":                                    "syscall",
+	"syscall.RTPROT_REDIRECT":                              "syscall",
+	"syscall.RTPROT_STATIC":                                "syscall",
+	"syscall.RTPROT_UNSPEC":                                "syscall",
+	"syscall.RTPROT_XORP":                                  "syscall",
+	"syscall.RTPROT_ZEBRA":                                 "syscall",
+	"syscall.RTV_EXPIRE":                                   "syscall",
+	"syscall.RTV_HOPCOUNT":                                 "syscall",
+	"syscall.RTV_MTU":                                      "syscall",
+	"syscall.RTV_RPIPE":                                    "syscall",
+	"syscall.RTV_RTT":                                      "syscall",
+	"syscall.RTV_RTTVAR":                                   "syscall",
+	"syscall.RTV_SPIPE":                                    "syscall",
+	"syscall.RTV_SSTHRESH":                                 "syscall",
+	"syscall.RTV_WEIGHT":                                   "syscall",
+	"syscall.RT_CACHING_CONTEXT":                           "syscall",
+	"syscall.RT_CLASS_DEFAULT":                             "syscall",
+	"syscall.RT_CLASS_LOCAL":                               "syscall",
+	"syscall.RT_CLASS_MAIN":                                "syscall",
+	"syscall.RT_CLASS_MAX":                                 "syscall",
+	"syscall.RT_CLASS_UNSPEC":                              "syscall",
+	"syscall.RT_DEFAULT_FIB":                               "syscall",
+	"syscall.RT_NORTREF":                                   "syscall",
+	"syscall.RT_SCOPE_HOST":                                "syscall",
+	"syscall.RT_SCOPE_LINK":                                "syscall",
+	"syscall.RT_SCOPE_NOWHERE":                             "syscall",
+	"syscall.RT_SCOPE_SITE":                                "syscall",
+	"syscall.RT_SCOPE_UNIVERSE":                            "syscall",
+	"syscall.RT_TABLEID_MAX":                               "syscall",
+	"syscall.RT_TABLE_COMPAT":                              "syscall",
+	"syscall.RT_TABLE_DEFAULT":                             "syscall",
+	"syscall.RT_TABLE_LOCAL":                               "syscall",
+	"syscall.RT_TABLE_MAIN":                                "syscall",
+	"syscall.RT_TABLE_MAX":                                 "syscall",
+	"syscall.RT_TABLE_UNSPEC":                              "syscall",
+	"syscall.RUSAGE_CHILDREN":                              "syscall",
+	"syscall.RUSAGE_SELF":                                  "syscall",
+	"syscall.RUSAGE_THREAD":                                "syscall",
+	"syscall.Radvisory_t":                                  "syscall",
+	"syscall.RawSockaddr":                                  "syscall",
+	"syscall.RawSockaddrAny":                               "syscall",
+	"syscall.RawSockaddrDatalink":                          "syscall",
+	"syscall.RawSockaddrInet4":                             "syscall",
+	"syscall.RawSockaddrInet6":                             "syscall",
+	"syscall.RawSockaddrLinklayer":                         "syscall",
+	"syscall.RawSockaddrNetlink":                           "syscall",
+	"syscall.RawSockaddrUnix":                              "syscall",
+	"syscall.RawSyscall":                                   "syscall",
+	"syscall.RawSyscall6":                                  "syscall",
+	"syscall.Read":                                         "syscall",
+	"syscall.ReadConsole":                                  "syscall",
+	"syscall.ReadDirectoryChanges":                         "syscall",
+	"syscall.ReadDirent":                                   "syscall",
+	"syscall.ReadFile":                                     "syscall",
+	"syscall.Readlink":                                     "syscall",
+	"syscall.Reboot":                                       "syscall",
+	"syscall.Recvfrom":                                     "syscall",
+	"syscall.Recvmsg":                                      "syscall",
+	"syscall.RegCloseKey":                                  "syscall",
+	"syscall.RegEnumKeyEx":                                 "syscall",
+	"syscall.RegOpenKeyEx":                                 "syscall",
+	"syscall.RegQueryInfoKey":                              "syscall",
+	"syscall.RegQueryValueEx":                              "syscall",
+	"syscall.RemoveDirectory":                              "syscall",
+	"syscall.Removexattr":                                  "syscall",
+	"syscall.Rename":                                       "syscall",
+	"syscall.Renameat":                                     "syscall",
+	"syscall.Revoke":                                       "syscall",
+	"syscall.Rlimit":                                       "syscall",
+	"syscall.Rmdir":                                        "syscall",
+	"syscall.RouteMessage":                                 "syscall",
+	"syscall.RouteRIB":                                     "syscall",
+	"syscall.RtAttr":                                       "syscall",
+	"syscall.RtGenmsg":                                     "syscall",
+	"syscall.RtMetrics":                                    "syscall",
+	"syscall.RtMsg":                                        "syscall",
+	"syscall.RtMsghdr":                                     "syscall",
+	"syscall.RtNexthop":                                    "syscall",
+	"syscall.Rusage":                                       "syscall",
+	"syscall.SCM_BINTIME":                                  "syscall",
+	"syscall.SCM_CREDENTIALS":                              "syscall",
+	"syscall.SCM_CREDS":                                    "syscall",
+	"syscall.SCM_RIGHTS":                                   "syscall",
+	"syscall.SCM_TIMESTAMP":                                "syscall",
+	"syscall.SCM_TIMESTAMPING":                             "syscall",
+	"syscall.SCM_TIMESTAMPNS":                              "syscall",
+	"syscall.SCM_TIMESTAMP_MONOTONIC":                      "syscall",
+	"syscall.SHUT_RD":                                      "syscall",
+	"syscall.SHUT_RDWR":                                    "syscall",
+	"syscall.SHUT_WR":                                      "syscall",
+	"syscall.SID":                                          "syscall",
+	"syscall.SIDAndAttributes":                             "syscall",
+	"syscall.SIGABRT":                                      "syscall",
+	"syscall.SIGALRM":                                      "syscall",
+	"syscall.SIGBUS":                                       "syscall",
+	"syscall.SIGCHLD":                                      "syscall",
+	"syscall.SIGCLD":                                       "syscall",
+	"syscall.SIGCONT":                                      "syscall",
+	"syscall.SIGEMT":                                       "syscall",
+	"syscall.SIGFPE":                                       "syscall",
+	"syscall.SIGHUP":                                       "syscall",
+	"syscall.SIGILL":                                       "syscall",
+	"syscall.SIGINFO":                                      "syscall",
+	"syscall.SIGINT":                                       "syscall",
+	"syscall.SIGIO":                                        "syscall",
+	"syscall.SIGIOT":                                       "syscall",
+	"syscall.SIGKILL":                                      "syscall",
+	"syscall.SIGLIBRT":                                     "syscall",
+	"syscall.SIGLWP":                                       "syscall",
+	"syscall.SIGPIPE":                                      "syscall",
+	"syscall.SIGPOLL":                                      "syscall",
+	"syscall.SIGPROF":                                      "syscall",
+	"syscall.SIGPWR":                                       "syscall",
+	"syscall.SIGQUIT":                                      "syscall",
+	"syscall.SIGSEGV":                                      "syscall",
+	"syscall.SIGSTKFLT":                                    "syscall",
+	"syscall.SIGSTOP":                                      "syscall",
+	"syscall.SIGSYS":                                       "syscall",
+	"syscall.SIGTERM":                                      "syscall",
+	"syscall.SIGTHR":                                       "syscall",
+	"syscall.SIGTRAP":                                      "syscall",
+	"syscall.SIGTSTP":                                      "syscall",
+	"syscall.SIGTTIN":                                      "syscall",
+	"syscall.SIGTTOU":                                      "syscall",
+	"syscall.SIGUNUSED":                                    "syscall",
+	"syscall.SIGURG":                                       "syscall",
+	"syscall.SIGUSR1":                                      "syscall",
+	"syscall.SIGUSR2":                                      "syscall",
+	"syscall.SIGVTALRM":                                    "syscall",
+	"syscall.SIGWINCH":                                     "syscall",
+	"syscall.SIGXCPU":                                      "syscall",
+	"syscall.SIGXFSZ":                                      "syscall",
+	"syscall.SIOCADDDLCI":                                  "syscall",
+	"syscall.SIOCADDMULTI":                                 "syscall",
+	"syscall.SIOCADDRT":                                    "syscall",
+	"syscall.SIOCAIFADDR":                                  "syscall",
+	"syscall.SIOCAIFGROUP":                                 "syscall",
+	"syscall.SIOCALIFADDR":                                 "syscall",
+	"syscall.SIOCARPIPLL":                                  "syscall",
+	"syscall.SIOCATMARK":                                   "syscall",
+	"syscall.SIOCAUTOADDR":                                 "syscall",
+	"syscall.SIOCAUTONETMASK":                              "syscall",
+	"syscall.SIOCBRDGADD":                                  "syscall",
+	"syscall.SIOCBRDGADDS":                                 "syscall",
+	"syscall.SIOCBRDGARL":                                  "syscall",
+	"syscall.SIOCBRDGDADDR":                                "syscall",
+	"syscall.SIOCBRDGDEL":                                  "syscall",
+	"syscall.SIOCBRDGDELS":                                 "syscall",
+	"syscall.SIOCBRDGFLUSH":                                "syscall",
+	"syscall.SIOCBRDGFRL":                                  "syscall",
+	"syscall.SIOCBRDGGCACHE":                               "syscall",
+	"syscall.SIOCBRDGGFD":                                  "syscall",
+	"syscall.SIOCBRDGGHT":                                  "syscall",
+	"syscall.SIOCBRDGGIFFLGS":                              "syscall",
+	"syscall.SIOCBRDGGMA":                                  "syscall",
+	"syscall.SIOCBRDGGPARAM":                               "syscall",
+	"syscall.SIOCBRDGGPRI":                                 "syscall",
+	"syscall.SIOCBRDGGRL":                                  "syscall",
+	"syscall.SIOCBRDGGSIFS":                                "syscall",
+	"syscall.SIOCBRDGGTO":                                  "syscall",
+	"syscall.SIOCBRDGIFS":                                  "syscall",
+	"syscall.SIOCBRDGRTS":                                  "syscall",
+	"syscall.SIOCBRDGSADDR":                                "syscall",
+	"syscall.SIOCBRDGSCACHE":                               "syscall",
+	"syscall.SIOCBRDGSFD":                                  "syscall",
+	"syscall.SIOCBRDGSHT":                                  "syscall",
+	"syscall.SIOCBRDGSIFCOST":                              "syscall",
+	"syscall.SIOCBRDGSIFFLGS":                              "syscall",
+	"syscall.SIOCBRDGSIFPRIO":                              "syscall",
+	"syscall.SIOCBRDGSMA":                                  "syscall",
+	"syscall.SIOCBRDGSPRI":                                 "syscall",
+	"syscall.SIOCBRDGSPROTO":                               "syscall",
+	"syscall.SIOCBRDGSTO":                                  "syscall",
+	"syscall.SIOCBRDGSTXHC":                                "syscall",
+	"syscall.SIOCDARP":                                     "syscall",
+	"syscall.SIOCDELDLCI":                                  "syscall",
+	"syscall.SIOCDELMULTI":                                 "syscall",
+	"syscall.SIOCDELRT":                                    "syscall",
+	"syscall.SIOCDEVPRIVATE":                               "syscall",
+	"syscall.SIOCDIFADDR":                                  "syscall",
+	"syscall.SIOCDIFGROUP":                                 "syscall",
+	"syscall.SIOCDIFPHYADDR":                               "syscall",
+	"syscall.SIOCDLIFADDR":                                 "syscall",
+	"syscall.SIOCDRARP":                                    "syscall",
+	"syscall.SIOCGARP":                                     "syscall",
+	"syscall.SIOCGDRVSPEC":                                 "syscall",
+	"syscall.SIOCGETKALIVE":                                "syscall",
+	"syscall.SIOCGETLABEL":                                 "syscall",
+	"syscall.SIOCGETPFLOW":                                 "syscall",
+	"syscall.SIOCGETPFSYNC":                                "syscall",
+	"syscall.SIOCGETSGCNT":                                 "syscall",
+	"syscall.SIOCGETVIFCNT":                                "syscall",
+	"syscall.SIOCGETVLAN":                                  "syscall",
+	"syscall.SIOCGHIWAT":                                   "syscall",
+	"syscall.SIOCGIFADDR":                                  "syscall",
+	"syscall.SIOCGIFADDRPREF":                              "syscall",
+	"syscall.SIOCGIFALIAS":                                 "syscall",
+	"syscall.SIOCGIFALTMTU":                                "syscall",
+	"syscall.SIOCGIFASYNCMAP":                              "syscall",
+	"syscall.SIOCGIFBOND":                                  "syscall",
+	"syscall.SIOCGIFBR":                                    "syscall",
+	"syscall.SIOCGIFBRDADDR":                               "syscall",
+	"syscall.SIOCGIFCAP":                                   "syscall",
+	"syscall.SIOCGIFCONF":                                  "syscall",
+	"syscall.SIOCGIFCOUNT":                                 "syscall",
+	"syscall.SIOCGIFDATA":                                  "syscall",
+	"syscall.SIOCGIFDESCR":                                 "syscall",
+	"syscall.SIOCGIFDEVMTU":                                "syscall",
+	"syscall.SIOCGIFDLT":                                   "syscall",
+	"syscall.SIOCGIFDSTADDR":                               "syscall",
+	"syscall.SIOCGIFENCAP":                                 "syscall",
+	"syscall.SIOCGIFFIB":                                   "syscall",
+	"syscall.SIOCGIFFLAGS":                                 "syscall",
+	"syscall.SIOCGIFGATTR":                                 "syscall",
+	"syscall.SIOCGIFGENERIC":                               "syscall",
+	"syscall.SIOCGIFGMEMB":                                 "syscall",
+	"syscall.SIOCGIFGROUP":                                 "syscall",
+	"syscall.SIOCGIFHWADDR":                                "syscall",
+	"syscall.SIOCGIFINDEX":                                 "syscall",
+	"syscall.SIOCGIFKPI":                                   "syscall",
+	"syscall.SIOCGIFMAC":                                   "syscall",
+	"syscall.SIOCGIFMAP":                                   "syscall",
+	"syscall.SIOCGIFMEDIA":                                 "syscall",
+	"syscall.SIOCGIFMEM":                                   "syscall",
+	"syscall.SIOCGIFMETRIC":                                "syscall",
+	"syscall.SIOCGIFMTU":                                   "syscall",
+	"syscall.SIOCGIFNAME":                                  "syscall",
+	"syscall.SIOCGIFNETMASK":                               "syscall",
+	"syscall.SIOCGIFPDSTADDR":                              "syscall",
+	"syscall.SIOCGIFPFLAGS":                                "syscall",
+	"syscall.SIOCGIFPHYS":                                  "syscall",
+	"syscall.SIOCGIFPRIORITY":                              "syscall",
+	"syscall.SIOCGIFPSRCADDR":                              "syscall",
+	"syscall.SIOCGIFRDOMAIN":                               "syscall",
+	"syscall.SIOCGIFRTLABEL":                               "syscall",
+	"syscall.SIOCGIFSLAVE":                                 "syscall",
+	"syscall.SIOCGIFSTATUS":                                "syscall",
+	"syscall.SIOCGIFTIMESLOT":                              "syscall",
+	"syscall.SIOCGIFTXQLEN":                                "syscall",
+	"syscall.SIOCGIFVLAN":                                  "syscall",
+	"syscall.SIOCGIFWAKEFLAGS":                             "syscall",
+	"syscall.SIOCGIFXFLAGS":                                "syscall",
+	"syscall.SIOCGLIFADDR":                                 "syscall",
+	"syscall.SIOCGLIFPHYADDR":                              "syscall",
+	"syscall.SIOCGLIFPHYRTABLE":                            "syscall",
+	"syscall.SIOCGLINKSTR":                                 "syscall",
+	"syscall.SIOCGLOWAT":                                   "syscall",
+	"syscall.SIOCGPGRP":                                    "syscall",
+	"syscall.SIOCGPRIVATE_0":                               "syscall",
+	"syscall.SIOCGPRIVATE_1":                               "syscall",
+	"syscall.SIOCGRARP":                                    "syscall",
+	"syscall.SIOCGSTAMP":                                   "syscall",
+	"syscall.SIOCGSTAMPNS":                                 "syscall",
+	"syscall.SIOCGVH":                                      "syscall",
+	"syscall.SIOCIFCREATE":                                 "syscall",
+	"syscall.SIOCIFCREATE2":                                "syscall",
+	"syscall.SIOCIFDESTROY":                                "syscall",
+	"syscall.SIOCIFGCLONERS":                               "syscall",
+	"syscall.SIOCINITIFADDR":                               "syscall",
+	"syscall.SIOCPROTOPRIVATE":                             "syscall",
+	"syscall.SIOCRSLVMULTI":                                "syscall",
+	"syscall.SIOCRTMSG":                                    "syscall",
+	"syscall.SIOCSARP":                                     "syscall",
+	"syscall.SIOCSDRVSPEC":                                 "syscall",
+	"syscall.SIOCSETKALIVE":                                "syscall",
+	"syscall.SIOCSETLABEL":                                 "syscall",
+	"syscall.SIOCSETPFLOW":                                 "syscall",
+	"syscall.SIOCSETPFSYNC":                                "syscall",
+	"syscall.SIOCSETVLAN":                                  "syscall",
+	"syscall.SIOCSHIWAT":                                   "syscall",
+	"syscall.SIOCSIFADDR":                                  "syscall",
+	"syscall.SIOCSIFADDRPREF":                              "syscall",
+	"syscall.SIOCSIFALTMTU":                                "syscall",
+	"syscall.SIOCSIFASYNCMAP":                              "syscall",
+	"syscall.SIOCSIFBOND":                                  "syscall",
+	"syscall.SIOCSIFBR":                                    "syscall",
+	"syscall.SIOCSIFBRDADDR":                               "syscall",
+	"syscall.SIOCSIFCAP":                                   "syscall",
+	"syscall.SIOCSIFDESCR":                                 "syscall",
+	"syscall.SIOCSIFDSTADDR":                               "syscall",
+	"syscall.SIOCSIFENCAP":                                 "syscall",
+	"syscall.SIOCSIFFIB":                                   "syscall",
+	"syscall.SIOCSIFFLAGS":                                 "syscall",
+	"syscall.SIOCSIFGATTR":                                 "syscall",
+	"syscall.SIOCSIFGENERIC":                               "syscall",
+	"syscall.SIOCSIFHWADDR":                                "syscall",
+	"syscall.SIOCSIFHWBROADCAST":                           "syscall",
+	"syscall.SIOCSIFKPI":                                   "syscall",
+	"syscall.SIOCSIFLINK":                                  "syscall",
+	"syscall.SIOCSIFLLADDR":                                "syscall",
+	"syscall.SIOCSIFMAC":                                   "syscall",
+	"syscall.SIOCSIFMAP":                                   "syscall",
+	"syscall.SIOCSIFMEDIA":                                 "syscall",
+	"syscall.SIOCSIFMEM":                                   "syscall",
+	"syscall.SIOCSIFMETRIC":                                "syscall",
+	"syscall.SIOCSIFMTU":                                   "syscall",
+	"syscall.SIOCSIFNAME":                                  "syscall",
+	"syscall.SIOCSIFNETMASK":                               "syscall",
+	"syscall.SIOCSIFPFLAGS":                                "syscall",
+	"syscall.SIOCSIFPHYADDR":                               "syscall",
+	"syscall.SIOCSIFPHYS":                                  "syscall",
+	"syscall.SIOCSIFPRIORITY":                              "syscall",
+	"syscall.SIOCSIFRDOMAIN":                               "syscall",
+	"syscall.SIOCSIFRTLABEL":                               "syscall",
+	"syscall.SIOCSIFRVNET":                                 "syscall",
+	"syscall.SIOCSIFSLAVE":                                 "syscall",
+	"syscall.SIOCSIFTIMESLOT":                              "syscall",
+	"syscall.SIOCSIFTXQLEN":                                "syscall",
+	"syscall.SIOCSIFVLAN":                                  "syscall",
+	"syscall.SIOCSIFVNET":                                  "syscall",
+	"syscall.SIOCSIFXFLAGS":                                "syscall",
+	"syscall.SIOCSLIFPHYADDR":                              "syscall",
+	"syscall.SIOCSLIFPHYRTABLE":                            "syscall",
+	"syscall.SIOCSLINKSTR":                                 "syscall",
+	"syscall.SIOCSLOWAT":                                   "syscall",
+	"syscall.SIOCSPGRP":                                    "syscall",
+	"syscall.SIOCSRARP":                                    "syscall",
+	"syscall.SIOCSVH":                                      "syscall",
+	"syscall.SIOCZIFDATA":                                  "syscall",
+	"syscall.SIO_GET_EXTENSION_FUNCTION_POINTER":           "syscall",
+	"syscall.SIO_GET_INTERFACE_LIST":                       "syscall",
+	"syscall.SOCK_CLOEXEC":                                 "syscall",
+	"syscall.SOCK_DCCP":                                    "syscall",
+	"syscall.SOCK_DGRAM":                                   "syscall",
+	"syscall.SOCK_FLAGS_MASK":                              "syscall",
+	"syscall.SOCK_MAXADDRLEN":                              "syscall",
+	"syscall.SOCK_NONBLOCK":                                "syscall",
+	"syscall.SOCK_NOSIGPIPE":                               "syscall",
+	"syscall.SOCK_PACKET":                                  "syscall",
+	"syscall.SOCK_RAW":                                     "syscall",
+	"syscall.SOCK_RDM":                                     "syscall",
+	"syscall.SOCK_SEQPACKET":                               "syscall",
+	"syscall.SOCK_STREAM":                                  "syscall",
+	"syscall.SOL_AAL":                                      "syscall",
+	"syscall.SOL_ATM":                                      "syscall",
+	"syscall.SOL_DECNET":                                   "syscall",
+	"syscall.SOL_ICMPV6":                                   "syscall",
+	"syscall.SOL_IP":                                       "syscall",
+	"syscall.SOL_IPV6":                                     "syscall",
+	"syscall.SOL_IRDA":                                     "syscall",
+	"syscall.SOL_PACKET":                                   "syscall",
+	"syscall.SOL_RAW":                                      "syscall",
+	"syscall.SOL_SOCKET":                                   "syscall",
+	"syscall.SOL_TCP":                                      "syscall",
+	"syscall.SOL_X25":                                      "syscall",
+	"syscall.SOMAXCONN":                                    "syscall",
+	"syscall.SO_ACCEPTCONN":                                "syscall",
+	"syscall.SO_ACCEPTFILTER":                              "syscall",
+	"syscall.SO_ATTACH_FILTER":                             "syscall",
+	"syscall.SO_BINDANY":                                   "syscall",
+	"syscall.SO_BINDTODEVICE":                              "syscall",
+	"syscall.SO_BINTIME":                                   "syscall",
+	"syscall.SO_BROADCAST":                                 "syscall",
+	"syscall.SO_BSDCOMPAT":                                 "syscall",
+	"syscall.SO_DEBUG":                                     "syscall",
+	"syscall.SO_DETACH_FILTER":                             "syscall",
+	"syscall.SO_DOMAIN":                                    "syscall",
+	"syscall.SO_DONTROUTE":                                 "syscall",
+	"syscall.SO_DONTTRUNC":                                 "syscall",
+	"syscall.SO_ERROR":                                     "syscall",
+	"syscall.SO_KEEPALIVE":                                 "syscall",
+	"syscall.SO_LABEL":                                     "syscall",
+	"syscall.SO_LINGER":                                    "syscall",
+	"syscall.SO_LINGER_SEC":                                "syscall",
+	"syscall.SO_LISTENINCQLEN":                             "syscall",
+	"syscall.SO_LISTENQLEN":                                "syscall",
+	"syscall.SO_LISTENQLIMIT":                              "syscall",
+	"syscall.SO_MARK":                                      "syscall",
+	"syscall.SO_NETPROC":                                   "syscall",
+	"syscall.SO_NKE":                                       "syscall",
+	"syscall.SO_NOADDRERR":                                 "syscall",
+	"syscall.SO_NOHEADER":                                  "syscall",
+	"syscall.SO_NOSIGPIPE":                                 "syscall",
+	"syscall.SO_NOTIFYCONFLICT":                            "syscall",
+	"syscall.SO_NO_CHECK":                                  "syscall",
+	"syscall.SO_NO_DDP":                                    "syscall",
+	"syscall.SO_NO_OFFLOAD":                                "syscall",
+	"syscall.SO_NP_EXTENSIONS":                             "syscall",
+	"syscall.SO_NREAD":                                     "syscall",
+	"syscall.SO_NWRITE":                                    "syscall",
+	"syscall.SO_OOBINLINE":                                 "syscall",
+	"syscall.SO_OVERFLOWED":                                "syscall",
+	"syscall.SO_PASSCRED":                                  "syscall",
+	"syscall.SO_PASSSEC":                                   "syscall",
+	"syscall.SO_PEERCRED":                                  "syscall",
+	"syscall.SO_PEERLABEL":                                 "syscall",
+	"syscall.SO_PEERNAME":                                  "syscall",
+	"syscall.SO_PEERSEC":                                   "syscall",
+	"syscall.SO_PRIORITY":                                  "syscall",
+	"syscall.SO_PROTOCOL":                                  "syscall",
+	"syscall.SO_PROTOTYPE":                                 "syscall",
+	"syscall.SO_RANDOMPORT":                                "syscall",
+	"syscall.SO_RCVBUF":                                    "syscall",
+	"syscall.SO_RCVBUFFORCE":                               "syscall",
+	"syscall.SO_RCVLOWAT":                                  "syscall",
+	"syscall.SO_RCVTIMEO":                                  "syscall",
+	"syscall.SO_RESTRICTIONS":                              "syscall",
+	"syscall.SO_RESTRICT_DENYIN":                           "syscall",
+	"syscall.SO_RESTRICT_DENYOUT":                          "syscall",
+	"syscall.SO_RESTRICT_DENYSET":                          "syscall",
+	"syscall.SO_REUSEADDR":                                 "syscall",
+	"syscall.SO_REUSEPORT":                                 "syscall",
+	"syscall.SO_REUSESHAREUID":                             "syscall",
+	"syscall.SO_RTABLE":                                    "syscall",
+	"syscall.SO_RXQ_OVFL":                                  "syscall",
+	"syscall.SO_SECURITY_AUTHENTICATION":                   "syscall",
+	"syscall.SO_SECURITY_ENCRYPTION_NETWORK":               "syscall",
+	"syscall.SO_SECURITY_ENCRYPTION_TRANSPORT":             "syscall",
+	"syscall.SO_SETFIB":                                    "syscall",
+	"syscall.SO_SNDBUF":                                    "syscall",
+	"syscall.SO_SNDBUFFORCE":                               "syscall",
+	"syscall.SO_SNDLOWAT":                                  "syscall",
+	"syscall.SO_SNDTIMEO":                                  "syscall",
+	"syscall.SO_SPLICE":                                    "syscall",
+	"syscall.SO_TIMESTAMP":                                 "syscall",
+	"syscall.SO_TIMESTAMPING":                              "syscall",
+	"syscall.SO_TIMESTAMPNS":                               "syscall",
+	"syscall.SO_TIMESTAMP_MONOTONIC":                       "syscall",
+	"syscall.SO_TYPE":                                      "syscall",
+	"syscall.SO_UPCALLCLOSEWAIT":                           "syscall",
+	"syscall.SO_UPDATE_ACCEPT_CONTEXT":                     "syscall",
+	"syscall.SO_UPDATE_CONNECT_CONTEXT":                    "syscall",
+	"syscall.SO_USELOOPBACK":                               "syscall",
+	"syscall.SO_USER_COOKIE":                               "syscall",
+	"syscall.SO_WANTMORE":                                  "syscall",
+	"syscall.SO_WANTOOBFLAG":                               "syscall",
+	"syscall.SSLExtraCertChainPolicyPara":                  "syscall",
+	"syscall.STANDARD_RIGHTS_ALL":                          "syscall",
+	"syscall.STANDARD_RIGHTS_EXECUTE":                      "syscall",
+	"syscall.STANDARD_RIGHTS_READ":                         "syscall",
+	"syscall.STANDARD_RIGHTS_REQUIRED":                     "syscall",
+	"syscall.STANDARD_RIGHTS_WRITE":                        "syscall",
+	"syscall.STARTF_USESHOWWINDOW":                         "syscall",
+	"syscall.STARTF_USESTDHANDLES":                         "syscall",
+	"syscall.STD_ERROR_HANDLE":                             "syscall",
+	"syscall.STD_INPUT_HANDLE":                             "syscall",
+	"syscall.STD_OUTPUT_HANDLE":                            "syscall",
+	"syscall.SUBLANG_ENGLISH_US":                           "syscall",
+	"syscall.SW_FORCEMINIMIZE":                             "syscall",
+	"syscall.SW_HIDE":                                      "syscall",
+	"syscall.SW_MAXIMIZE":                                  "syscall",
+	"syscall.SW_MINIMIZE":                                  "syscall",
+	"syscall.SW_NORMAL":                                    "syscall",
+	"syscall.SW_RESTORE":                                   "syscall",
+	"syscall.SW_SHOW":                                      "syscall",
+	"syscall.SW_SHOWDEFAULT":                               "syscall",
+	"syscall.SW_SHOWMAXIMIZED":                             "syscall",
+	"syscall.SW_SHOWMINIMIZED":                             "syscall",
+	"syscall.SW_SHOWMINNOACTIVE":                           "syscall",
+	"syscall.SW_SHOWNA":                                    "syscall",
+	"syscall.SW_SHOWNOACTIVATE":                            "syscall",
+	"syscall.SW_SHOWNORMAL":                                "syscall",
+	"syscall.SYNCHRONIZE":                                  "syscall",
+	"syscall.SYSCTL_VERSION":                               "syscall",
+	"syscall.SYSCTL_VERS_0":                                "syscall",
+	"syscall.SYSCTL_VERS_1":                                "syscall",
+	"syscall.SYSCTL_VERS_MASK":                             "syscall",
+	"syscall.SYS_ABORT2":                                   "syscall",
+	"syscall.SYS_ACCEPT":                                   "syscall",
+	"syscall.SYS_ACCEPT4":                                  "syscall",
+	"syscall.SYS_ACCEPT_NOCANCEL":                          "syscall",
+	"syscall.SYS_ACCESS":                                   "syscall",
+	"syscall.SYS_ACCESS_EXTENDED":                          "syscall",
+	"syscall.SYS_ACCT":                                     "syscall",
+	"syscall.SYS_ADD_KEY":                                  "syscall",
+	"syscall.SYS_ADD_PROFIL":                               "syscall",
+	"syscall.SYS_ADJFREQ":                                  "syscall",
+	"syscall.SYS_ADJTIME":                                  "syscall",
+	"syscall.SYS_ADJTIMEX":                                 "syscall",
+	"syscall.SYS_AFS_SYSCALL":                              "syscall",
+	"syscall.SYS_AIO_CANCEL":                               "syscall",
+	"syscall.SYS_AIO_ERROR":                                "syscall",
+	"syscall.SYS_AIO_FSYNC":                                "syscall",
+	"syscall.SYS_AIO_READ":                                 "syscall",
+	"syscall.SYS_AIO_RETURN":                               "syscall",
+	"syscall.SYS_AIO_SUSPEND":                              "syscall",
+	"syscall.SYS_AIO_SUSPEND_NOCANCEL":                     "syscall",
+	"syscall.SYS_AIO_WRITE":                                "syscall",
+	"syscall.SYS_ALARM":                                    "syscall",
+	"syscall.SYS_ARCH_PRCTL":                               "syscall",
+	"syscall.SYS_ARM_FADVISE64_64":                         "syscall",
+	"syscall.SYS_ARM_SYNC_FILE_RANGE":                      "syscall",
+	"syscall.SYS_ATGETMSG":                                 "syscall",
+	"syscall.SYS_ATPGETREQ":                                "syscall",
+	"syscall.SYS_ATPGETRSP":                                "syscall",
+	"syscall.SYS_ATPSNDREQ":                                "syscall",
+	"syscall.SYS_ATPSNDRSP":                                "syscall",
+	"syscall.SYS_ATPUTMSG":                                 "syscall",
+	"syscall.SYS_ATSOCKET":                                 "syscall",
+	"syscall.SYS_AUDIT":                                    "syscall",
+	"syscall.SYS_AUDITCTL":                                 "syscall",
+	"syscall.SYS_AUDITON":                                  "syscall",
+	"syscall.SYS_AUDIT_SESSION_JOIN":                       "syscall",
+	"syscall.SYS_AUDIT_SESSION_PORT":                       "syscall",
+	"syscall.SYS_AUDIT_SESSION_SELF":                       "syscall",
+	"syscall.SYS_BDFLUSH":                                  "syscall",
+	"syscall.SYS_BIND":                                     "syscall",
+	"syscall.SYS_BREAK":                                    "syscall",
+	"syscall.SYS_BRK":                                      "syscall",
+	"syscall.SYS_BSDTHREAD_CREATE":                         "syscall",
+	"syscall.SYS_BSDTHREAD_REGISTER":                       "syscall",
+	"syscall.SYS_BSDTHREAD_TERMINATE":                      "syscall",
+	"syscall.SYS_CAPGET":                                   "syscall",
+	"syscall.SYS_CAPSET":                                   "syscall",
+	"syscall.SYS_CAP_ENTER":                                "syscall",
+	"syscall.SYS_CAP_FCNTLS_GET":                           "syscall",
+	"syscall.SYS_CAP_FCNTLS_LIMIT":                         "syscall",
+	"syscall.SYS_CAP_GETMODE":                              "syscall",
+	"syscall.SYS_CAP_GETRIGHTS":                            "syscall",
+	"syscall.SYS_CAP_IOCTLS_GET":                           "syscall",
+	"syscall.SYS_CAP_IOCTLS_LIMIT":                         "syscall",
+	"syscall.SYS_CAP_NEW":                                  "syscall",
+	"syscall.SYS_CAP_RIGHTS_GET":                           "syscall",
+	"syscall.SYS_CAP_RIGHTS_LIMIT":                         "syscall",
+	"syscall.SYS_CHDIR":                                    "syscall",
+	"syscall.SYS_CHFLAGS":                                  "syscall",
+	"syscall.SYS_CHMOD":                                    "syscall",
+	"syscall.SYS_CHMOD_EXTENDED":                           "syscall",
+	"syscall.SYS_CHOWN":                                    "syscall",
+	"syscall.SYS_CHOWN32":                                  "syscall",
+	"syscall.SYS_CHROOT":                                   "syscall",
+	"syscall.SYS_CHUD":                                     "syscall",
+	"syscall.SYS_CLOCK_ADJTIME":                            "syscall",
+	"syscall.SYS_CLOCK_GETCPUCLOCKID2":                     "syscall",
+	"syscall.SYS_CLOCK_GETRES":                             "syscall",
+	"syscall.SYS_CLOCK_GETTIME":                            "syscall",
+	"syscall.SYS_CLOCK_NANOSLEEP":                          "syscall",
+	"syscall.SYS_CLOCK_SETTIME":                            "syscall",
+	"syscall.SYS_CLONE":                                    "syscall",
+	"syscall.SYS_CLOSE":                                    "syscall",
+	"syscall.SYS_CLOSEFROM":                                "syscall",
+	"syscall.SYS_CLOSE_NOCANCEL":                           "syscall",
+	"syscall.SYS_CONNECT":                                  "syscall",
+	"syscall.SYS_CONNECT_NOCANCEL":                         "syscall",
+	"syscall.SYS_COPYFILE":                                 "syscall",
+	"syscall.SYS_CPUSET":                                   "syscall",
+	"syscall.SYS_CPUSET_GETAFFINITY":                       "syscall",
+	"syscall.SYS_CPUSET_GETID":                             "syscall",
+	"syscall.SYS_CPUSET_SETAFFINITY":                       "syscall",
+	"syscall.SYS_CPUSET_SETID":                             "syscall",
+	"syscall.SYS_CREAT":                                    "syscall",
+	"syscall.SYS_CREATE_MODULE":                            "syscall",
+	"syscall.SYS_CSOPS":                                    "syscall",
+	"syscall.SYS_DELETE":                                   "syscall",
+	"syscall.SYS_DELETE_MODULE":                            "syscall",
+	"syscall.SYS_DUP":                                      "syscall",
+	"syscall.SYS_DUP2":                                     "syscall",
+	"syscall.SYS_DUP3":                                     "syscall",
+	"syscall.SYS_EACCESS":                                  "syscall",
+	"syscall.SYS_EPOLL_CREATE":                             "syscall",
+	"syscall.SYS_EPOLL_CREATE1":                            "syscall",
+	"syscall.SYS_EPOLL_CTL":                                "syscall",
+	"syscall.SYS_EPOLL_CTL_OLD":                            "syscall",
+	"syscall.SYS_EPOLL_PWAIT":                              "syscall",
+	"syscall.SYS_EPOLL_WAIT":                               "syscall",
+	"syscall.SYS_EPOLL_WAIT_OLD":                           "syscall",
+	"syscall.SYS_EVENTFD":                                  "syscall",
+	"syscall.SYS_EVENTFD2":                                 "syscall",
+	"syscall.SYS_EXCHANGEDATA":                             "syscall",
+	"syscall.SYS_EXECVE":                                   "syscall",
+	"syscall.SYS_EXIT":                                     "syscall",
+	"syscall.SYS_EXIT_GROUP":                               "syscall",
+	"syscall.SYS_EXTATTRCTL":                               "syscall",
+	"syscall.SYS_EXTATTR_DELETE_FD":                        "syscall",
+	"syscall.SYS_EXTATTR_DELETE_FILE":                      "syscall",
+	"syscall.SYS_EXTATTR_DELETE_LINK":                      "syscall",
+	"syscall.SYS_EXTATTR_GET_FD":                           "syscall",
+	"syscall.SYS_EXTATTR_GET_FILE":                         "syscall",
+	"syscall.SYS_EXTATTR_GET_LINK":                         "syscall",
+	"syscall.SYS_EXTATTR_LIST_FD":                          "syscall",
+	"syscall.SYS_EXTATTR_LIST_FILE":                        "syscall",
+	"syscall.SYS_EXTATTR_LIST_LINK":                        "syscall",
+	"syscall.SYS_EXTATTR_SET_FD":                           "syscall",
+	"syscall.SYS_EXTATTR_SET_FILE":                         "syscall",
+	"syscall.SYS_EXTATTR_SET_LINK":                         "syscall",
+	"syscall.SYS_FACCESSAT":                                "syscall",
+	"syscall.SYS_FADVISE64":                                "syscall",
+	"syscall.SYS_FADVISE64_64":                             "syscall",
+	"syscall.SYS_FALLOCATE":                                "syscall",
+	"syscall.SYS_FANOTIFY_INIT":                            "syscall",
+	"syscall.SYS_FANOTIFY_MARK":                            "syscall",
+	"syscall.SYS_FCHDIR":                                   "syscall",
+	"syscall.SYS_FCHFLAGS":                                 "syscall",
+	"syscall.SYS_FCHMOD":                                   "syscall",
+	"syscall.SYS_FCHMODAT":                                 "syscall",
+	"syscall.SYS_FCHMOD_EXTENDED":                          "syscall",
+	"syscall.SYS_FCHOWN":                                   "syscall",
+	"syscall.SYS_FCHOWN32":                                 "syscall",
+	"syscall.SYS_FCHOWNAT":                                 "syscall",
+	"syscall.SYS_FCHROOT":                                  "syscall",
+	"syscall.SYS_FCNTL":                                    "syscall",
+	"syscall.SYS_FCNTL64":                                  "syscall",
+	"syscall.SYS_FCNTL_NOCANCEL":                           "syscall",
+	"syscall.SYS_FDATASYNC":                                "syscall",
+	"syscall.SYS_FEXECVE":                                  "syscall",
+	"syscall.SYS_FFCLOCK_GETCOUNTER":                       "syscall",
+	"syscall.SYS_FFCLOCK_GETESTIMATE":                      "syscall",
+	"syscall.SYS_FFCLOCK_SETESTIMATE":                      "syscall",
+	"syscall.SYS_FFSCTL":                                   "syscall",
+	"syscall.SYS_FGETATTRLIST":                             "syscall",
+	"syscall.SYS_FGETXATTR":                                "syscall",
+	"syscall.SYS_FHOPEN":                                   "syscall",
+	"syscall.SYS_FHSTAT":                                   "syscall",
+	"syscall.SYS_FHSTATFS":                                 "syscall",
+	"syscall.SYS_FILEPORT_MAKEFD":                          "syscall",
+	"syscall.SYS_FILEPORT_MAKEPORT":                        "syscall",
+	"syscall.SYS_FKTRACE":                                  "syscall",
+	"syscall.SYS_FLISTXATTR":                               "syscall",
+	"syscall.SYS_FLOCK":                                    "syscall",
+	"syscall.SYS_FORK":                                     "syscall",
+	"syscall.SYS_FPATHCONF":                                "syscall",
+	"syscall.SYS_FREEBSD6_FTRUNCATE":                       "syscall",
+	"syscall.SYS_FREEBSD6_LSEEK":                           "syscall",
+	"syscall.SYS_FREEBSD6_MMAP":                            "syscall",
+	"syscall.SYS_FREEBSD6_PREAD":                           "syscall",
+	"syscall.SYS_FREEBSD6_PWRITE":                          "syscall",
+	"syscall.SYS_FREEBSD6_TRUNCATE":                        "syscall",
+	"syscall.SYS_FREMOVEXATTR":                             "syscall",
+	"syscall.SYS_FSCTL":                                    "syscall",
+	"syscall.SYS_FSETATTRLIST":                             "syscall",
+	"syscall.SYS_FSETXATTR":                                "syscall",
+	"syscall.SYS_FSGETPATH":                                "syscall",
+	"syscall.SYS_FSTAT":                                    "syscall",
+	"syscall.SYS_FSTAT64":                                  "syscall",
+	"syscall.SYS_FSTAT64_EXTENDED":                         "syscall",
+	"syscall.SYS_FSTATAT":                                  "syscall",
+	"syscall.SYS_FSTATAT64":                                "syscall",
+	"syscall.SYS_FSTATFS":                                  "syscall",
+	"syscall.SYS_FSTATFS64":                                "syscall",
+	"syscall.SYS_FSTATV":                                   "syscall",
+	"syscall.SYS_FSTATVFS1":                                "syscall",
+	"syscall.SYS_FSTAT_EXTENDED":                           "syscall",
+	"syscall.SYS_FSYNC":                                    "syscall",
+	"syscall.SYS_FSYNC_NOCANCEL":                           "syscall",
+	"syscall.SYS_FSYNC_RANGE":                              "syscall",
+	"syscall.SYS_FTIME":                                    "syscall",
+	"syscall.SYS_FTRUNCATE":                                "syscall",
+	"syscall.SYS_FTRUNCATE64":                              "syscall",
+	"syscall.SYS_FUTEX":                                    "syscall",
+	"syscall.SYS_FUTIMENS":                                 "syscall",
+	"syscall.SYS_FUTIMES":                                  "syscall",
+	"syscall.SYS_FUTIMESAT":                                "syscall",
+	"syscall.SYS_GETATTRLIST":                              "syscall",
+	"syscall.SYS_GETAUDIT":                                 "syscall",
+	"syscall.SYS_GETAUDIT_ADDR":                            "syscall",
+	"syscall.SYS_GETAUID":                                  "syscall",
+	"syscall.SYS_GETCONTEXT":                               "syscall",
+	"syscall.SYS_GETCPU":                                   "syscall",
+	"syscall.SYS_GETCWD":                                   "syscall",
+	"syscall.SYS_GETDENTS":                                 "syscall",
+	"syscall.SYS_GETDENTS64":                               "syscall",
+	"syscall.SYS_GETDIRENTRIES":                            "syscall",
+	"syscall.SYS_GETDIRENTRIES64":                          "syscall",
+	"syscall.SYS_GETDIRENTRIESATTR":                        "syscall",
+	"syscall.SYS_GETDTABLECOUNT":                           "syscall",
+	"syscall.SYS_GETDTABLESIZE":                            "syscall",
+	"syscall.SYS_GETEGID":                                  "syscall",
+	"syscall.SYS_GETEGID32":                                "syscall",
+	"syscall.SYS_GETEUID":                                  "syscall",
+	"syscall.SYS_GETEUID32":                                "syscall",
+	"syscall.SYS_GETFH":                                    "syscall",
+	"syscall.SYS_GETFSSTAT":                                "syscall",
+	"syscall.SYS_GETFSSTAT64":                              "syscall",
+	"syscall.SYS_GETGID":                                   "syscall",
+	"syscall.SYS_GETGID32":                                 "syscall",
+	"syscall.SYS_GETGROUPS":                                "syscall",
+	"syscall.SYS_GETGROUPS32":                              "syscall",
+	"syscall.SYS_GETHOSTUUID":                              "syscall",
+	"syscall.SYS_GETITIMER":                                "syscall",
+	"syscall.SYS_GETLCID":                                  "syscall",
+	"syscall.SYS_GETLOGIN":                                 "syscall",
+	"syscall.SYS_GETLOGINCLASS":                            "syscall",
+	"syscall.SYS_GETPEERNAME":                              "syscall",
+	"syscall.SYS_GETPGID":                                  "syscall",
+	"syscall.SYS_GETPGRP":                                  "syscall",
+	"syscall.SYS_GETPID":                                   "syscall",
+	"syscall.SYS_GETPMSG":                                  "syscall",
+	"syscall.SYS_GETPPID":                                  "syscall",
+	"syscall.SYS_GETPRIORITY":                              "syscall",
+	"syscall.SYS_GETRESGID":                                "syscall",
+	"syscall.SYS_GETRESGID32":                              "syscall",
+	"syscall.SYS_GETRESUID":                                "syscall",
+	"syscall.SYS_GETRESUID32":                              "syscall",
+	"syscall.SYS_GETRLIMIT":                                "syscall",
+	"syscall.SYS_GETRTABLE":                                "syscall",
+	"syscall.SYS_GETRUSAGE":                                "syscall",
+	"syscall.SYS_GETSGROUPS":                               "syscall",
+	"syscall.SYS_GETSID":                                   "syscall",
+	"syscall.SYS_GETSOCKNAME":                              "syscall",
+	"syscall.SYS_GETSOCKOPT":                               "syscall",
+	"syscall.SYS_GETTHRID":                                 "syscall",
+	"syscall.SYS_GETTID":                                   "syscall",
+	"syscall.SYS_GETTIMEOFDAY":                             "syscall",
+	"syscall.SYS_GETUID":                                   "syscall",
+	"syscall.SYS_GETUID32":                                 "syscall",
+	"syscall.SYS_GETVFSSTAT":                               "syscall",
+	"syscall.SYS_GETWGROUPS":                               "syscall",
+	"syscall.SYS_GETXATTR":                                 "syscall",
+	"syscall.SYS_GET_KERNEL_SYMS":                          "syscall",
+	"syscall.SYS_GET_MEMPOLICY":                            "syscall",
+	"syscall.SYS_GET_ROBUST_LIST":                          "syscall",
+	"syscall.SYS_GET_THREAD_AREA":                          "syscall",
+	"syscall.SYS_GTTY":                                     "syscall",
+	"syscall.SYS_IDENTITYSVC":                              "syscall",
+	"syscall.SYS_IDLE":                                     "syscall",
+	"syscall.SYS_INITGROUPS":                               "syscall",
+	"syscall.SYS_INIT_MODULE":                              "syscall",
+	"syscall.SYS_INOTIFY_ADD_WATCH":                        "syscall",
+	"syscall.SYS_INOTIFY_INIT":                             "syscall",
+	"syscall.SYS_INOTIFY_INIT1":                            "syscall",
+	"syscall.SYS_INOTIFY_RM_WATCH":                         "syscall",
+	"syscall.SYS_IOCTL":                                    "syscall",
+	"syscall.SYS_IOPERM":                                   "syscall",
+	"syscall.SYS_IOPL":                                     "syscall",
+	"syscall.SYS_IOPOLICYSYS":                              "syscall",
+	"syscall.SYS_IOPRIO_GET":                               "syscall",
+	"syscall.SYS_IOPRIO_SET":                               "syscall",
+	"syscall.SYS_IO_CANCEL":                                "syscall",
+	"syscall.SYS_IO_DESTROY":                               "syscall",
+	"syscall.SYS_IO_GETEVENTS":                             "syscall",
+	"syscall.SYS_IO_SETUP":                                 "syscall",
+	"syscall.SYS_IO_SUBMIT":                                "syscall",
+	"syscall.SYS_IPC":                                      "syscall",
+	"syscall.SYS_ISSETUGID":                                "syscall",
+	"syscall.SYS_JAIL":                                     "syscall",
+	"syscall.SYS_JAIL_ATTACH":                              "syscall",
+	"syscall.SYS_JAIL_GET":                                 "syscall",
+	"syscall.SYS_JAIL_REMOVE":                              "syscall",
+	"syscall.SYS_JAIL_SET":                                 "syscall",
+	"syscall.SYS_KDEBUG_TRACE":                             "syscall",
+	"syscall.SYS_KENV":                                     "syscall",
+	"syscall.SYS_KEVENT":                                   "syscall",
+	"syscall.SYS_KEVENT64":                                 "syscall",
+	"syscall.SYS_KEXEC_LOAD":                               "syscall",
+	"syscall.SYS_KEYCTL":                                   "syscall",
+	"syscall.SYS_KILL":                                     "syscall",
+	"syscall.SYS_KLDFIND":                                  "syscall",
+	"syscall.SYS_KLDFIRSTMOD":                              "syscall",
+	"syscall.SYS_KLDLOAD":                                  "syscall",
+	"syscall.SYS_KLDNEXT":                                  "syscall",
+	"syscall.SYS_KLDSTAT":                                  "syscall",
+	"syscall.SYS_KLDSYM":                                   "syscall",
+	"syscall.SYS_KLDUNLOAD":                                "syscall",
+	"syscall.SYS_KLDUNLOADF":                               "syscall",
+	"syscall.SYS_KQUEUE":                                   "syscall",
+	"syscall.SYS_KQUEUE1":                                  "syscall",
+	"syscall.SYS_KTIMER_CREATE":                            "syscall",
+	"syscall.SYS_KTIMER_DELETE":                            "syscall",
+	"syscall.SYS_KTIMER_GETOVERRUN":                        "syscall",
+	"syscall.SYS_KTIMER_GETTIME":                           "syscall",
+	"syscall.SYS_KTIMER_SETTIME":                           "syscall",
+	"syscall.SYS_KTRACE":                                   "syscall",
+	"syscall.SYS_LCHFLAGS":                                 "syscall",
+	"syscall.SYS_LCHMOD":                                   "syscall",
+	"syscall.SYS_LCHOWN":                                   "syscall",
+	"syscall.SYS_LCHOWN32":                                 "syscall",
+	"syscall.SYS_LGETFH":                                   "syscall",
+	"syscall.SYS_LGETXATTR":                                "syscall",
+	"syscall.SYS_LINK":                                     "syscall",
+	"syscall.SYS_LINKAT":                                   "syscall",
+	"syscall.SYS_LIO_LISTIO":                               "syscall",
+	"syscall.SYS_LISTEN":                                   "syscall",
+	"syscall.SYS_LISTXATTR":                                "syscall",
+	"syscall.SYS_LLISTXATTR":                               "syscall",
+	"syscall.SYS_LOCK":                                     "syscall",
+	"syscall.SYS_LOOKUP_DCOOKIE":                           "syscall",
+	"syscall.SYS_LPATHCONF":                                "syscall",
+	"syscall.SYS_LREMOVEXATTR":                             "syscall",
+	"syscall.SYS_LSEEK":                                    "syscall",
+	"syscall.SYS_LSETXATTR":                                "syscall",
+	"syscall.SYS_LSTAT":                                    "syscall",
+	"syscall.SYS_LSTAT64":                                  "syscall",
+	"syscall.SYS_LSTAT64_EXTENDED":                         "syscall",
+	"syscall.SYS_LSTATV":                                   "syscall",
+	"syscall.SYS_LSTAT_EXTENDED":                           "syscall",
+	"syscall.SYS_LUTIMES":                                  "syscall",
+	"syscall.SYS_MAC_SYSCALL":                              "syscall",
+	"syscall.SYS_MADVISE":                                  "syscall",
+	"syscall.SYS_MADVISE1":                                 "syscall",
+	"syscall.SYS_MAXSYSCALL":                               "syscall",
+	"syscall.SYS_MBIND":                                    "syscall",
+	"syscall.SYS_MIGRATE_PAGES":                            "syscall",
+	"syscall.SYS_MINCORE":                                  "syscall",
+	"syscall.SYS_MINHERIT":                                 "syscall",
+	"syscall.SYS_MKCOMPLEX":                                "syscall",
+	"syscall.SYS_MKDIR":                                    "syscall",
+	"syscall.SYS_MKDIRAT":                                  "syscall",
+	"syscall.SYS_MKDIR_EXTENDED":                           "syscall",
+	"syscall.SYS_MKFIFO":                                   "syscall",
+	"syscall.SYS_MKFIFOAT":                                 "syscall",
+	"syscall.SYS_MKFIFO_EXTENDED":                          "syscall",
+	"syscall.SYS_MKNOD":                                    "syscall",
+	"syscall.SYS_MKNODAT":                                  "syscall",
+	"syscall.SYS_MLOCK":                                    "syscall",
+	"syscall.SYS_MLOCKALL":                                 "syscall",
+	"syscall.SYS_MMAP":                                     "syscall",
+	"syscall.SYS_MMAP2":                                    "syscall",
+	"syscall.SYS_MODCTL":                                   "syscall",
+	"syscall.SYS_MODFIND":                                  "syscall",
+	"syscall.SYS_MODFNEXT":                                 "syscall",
+	"syscall.SYS_MODIFY_LDT":                               "syscall",
+	"syscall.SYS_MODNEXT":                                  "syscall",
+	"syscall.SYS_MODSTAT":                                  "syscall",
+	"syscall.SYS_MODWATCH":                                 "syscall",
+	"syscall.SYS_MOUNT":                                    "syscall",
+	"syscall.SYS_MOVE_PAGES":                               "syscall",
+	"syscall.SYS_MPROTECT":                                 "syscall",
+	"syscall.SYS_MPX":                                      "syscall",
+	"syscall.SYS_MQUERY":                                   "syscall",
+	"syscall.SYS_MQ_GETSETATTR":                            "syscall",
+	"syscall.SYS_MQ_NOTIFY":                                "syscall",
+	"syscall.SYS_MQ_OPEN":                                  "syscall",
+	"syscall.SYS_MQ_TIMEDRECEIVE":                          "syscall",
+	"syscall.SYS_MQ_TIMEDSEND":                             "syscall",
+	"syscall.SYS_MQ_UNLINK":                                "syscall",
+	"syscall.SYS_MREMAP":                                   "syscall",
+	"syscall.SYS_MSGCTL":                                   "syscall",
+	"syscall.SYS_MSGGET":                                   "syscall",
+	"syscall.SYS_MSGRCV":                                   "syscall",
+	"syscall.SYS_MSGRCV_NOCANCEL":                          "syscall",
+	"syscall.SYS_MSGSND":                                   "syscall",
+	"syscall.SYS_MSGSND_NOCANCEL":                          "syscall",
+	"syscall.SYS_MSGSYS":                                   "syscall",
+	"syscall.SYS_MSYNC":                                    "syscall",
+	"syscall.SYS_MSYNC_NOCANCEL":                           "syscall",
+	"syscall.SYS_MUNLOCK":                                  "syscall",
+	"syscall.SYS_MUNLOCKALL":                               "syscall",
+	"syscall.SYS_MUNMAP":                                   "syscall",
+	"syscall.SYS_NAME_TO_HANDLE_AT":                        "syscall",
+	"syscall.SYS_NANOSLEEP":                                "syscall",
+	"syscall.SYS_NEWFSTATAT":                               "syscall",
+	"syscall.SYS_NFSCLNT":                                  "syscall",
+	"syscall.SYS_NFSSERVCTL":                               "syscall",
+	"syscall.SYS_NFSSVC":                                   "syscall",
+	"syscall.SYS_NFSTAT":                                   "syscall",
+	"syscall.SYS_NICE":                                     "syscall",
+	"syscall.SYS_NLSTAT":                                   "syscall",
+	"syscall.SYS_NMOUNT":                                   "syscall",
+	"syscall.SYS_NSTAT":                                    "syscall",
+	"syscall.SYS_NTP_ADJTIME":                              "syscall",
+	"syscall.SYS_NTP_GETTIME":                              "syscall",
+	"syscall.SYS_OABI_SYSCALL_BASE":                        "syscall",
+	"syscall.SYS_OBREAK":                                   "syscall",
+	"syscall.SYS_OLDFSTAT":                                 "syscall",
+	"syscall.SYS_OLDLSTAT":                                 "syscall",
+	"syscall.SYS_OLDOLDUNAME":                              "syscall",
+	"syscall.SYS_OLDSTAT":                                  "syscall",
+	"syscall.SYS_OLDUNAME":                                 "syscall",
+	"syscall.SYS_OPEN":                                     "syscall",
+	"syscall.SYS_OPENAT":                                   "syscall",
+	"syscall.SYS_OPENBSD_POLL":                             "syscall",
+	"syscall.SYS_OPEN_BY_HANDLE_AT":                        "syscall",
+	"syscall.SYS_OPEN_EXTENDED":                            "syscall",
+	"syscall.SYS_OPEN_NOCANCEL":                            "syscall",
+	"syscall.SYS_OVADVISE":                                 "syscall",
+	"syscall.SYS_PACCEPT":                                  "syscall",
+	"syscall.SYS_PATHCONF":                                 "syscall",
+	"syscall.SYS_PAUSE":                                    "syscall",
+	"syscall.SYS_PCICONFIG_IOBASE":                         "syscall",
+	"syscall.SYS_PCICONFIG_READ":                           "syscall",
+	"syscall.SYS_PCICONFIG_WRITE":                          "syscall",
+	"syscall.SYS_PDFORK":                                   "syscall",
+	"syscall.SYS_PDGETPID":                                 "syscall",
+	"syscall.SYS_PDKILL":                                   "syscall",
+	"syscall.SYS_PERF_EVENT_OPEN":                          "syscall",
+	"syscall.SYS_PERSONALITY":                              "syscall",
+	"syscall.SYS_PID_HIBERNATE":                            "syscall",
+	"syscall.SYS_PID_RESUME":                               "syscall",
+	"syscall.SYS_PID_SHUTDOWN_SOCKETS":                     "syscall",
+	"syscall.SYS_PID_SUSPEND":                              "syscall",
+	"syscall.SYS_PIPE":                                     "syscall",
+	"syscall.SYS_PIPE2":                                    "syscall",
+	"syscall.SYS_PIVOT_ROOT":                               "syscall",
+	"syscall.SYS_PMC_CONTROL":                              "syscall",
+	"syscall.SYS_PMC_GET_INFO":                             "syscall",
+	"syscall.SYS_POLL":                                     "syscall",
+	"syscall.SYS_POLLTS":                                   "syscall",
+	"syscall.SYS_POLL_NOCANCEL":                            "syscall",
+	"syscall.SYS_POSIX_FADVISE":                            "syscall",
+	"syscall.SYS_POSIX_FALLOCATE":                          "syscall",
+	"syscall.SYS_POSIX_OPENPT":                             "syscall",
+	"syscall.SYS_POSIX_SPAWN":                              "syscall",
+	"syscall.SYS_PPOLL":                                    "syscall",
+	"syscall.SYS_PRCTL":                                    "syscall",
+	"syscall.SYS_PREAD":                                    "syscall",
+	"syscall.SYS_PREAD64":                                  "syscall",
+	"syscall.SYS_PREADV":                                   "syscall",
+	"syscall.SYS_PREAD_NOCANCEL":                           "syscall",
+	"syscall.SYS_PRLIMIT64":                                "syscall",
+	"syscall.SYS_PROCESS_POLICY":                           "syscall",
+	"syscall.SYS_PROCESS_VM_READV":                         "syscall",
+	"syscall.SYS_PROCESS_VM_WRITEV":                        "syscall",
+	"syscall.SYS_PROC_INFO":                                "syscall",
+	"syscall.SYS_PROF":                                     "syscall",
+	"syscall.SYS_PROFIL":                                   "syscall",
+	"syscall.SYS_PSELECT":                                  "syscall",
+	"syscall.SYS_PSELECT6":                                 "syscall",
+	"syscall.SYS_PSET_ASSIGN":                              "syscall",
+	"syscall.SYS_PSET_CREATE":                              "syscall",
+	"syscall.SYS_PSET_DESTROY":                             "syscall",
+	"syscall.SYS_PSYNCH_CVBROAD":                           "syscall",
+	"syscall.SYS_PSYNCH_CVCLRPREPOST":                      "syscall",
+	"syscall.SYS_PSYNCH_CVSIGNAL":                          "syscall",
+	"syscall.SYS_PSYNCH_CVWAIT":                            "syscall",
+	"syscall.SYS_PSYNCH_MUTEXDROP":                         "syscall",
+	"syscall.SYS_PSYNCH_MUTEXWAIT":                         "syscall",
+	"syscall.SYS_PSYNCH_RW_DOWNGRADE":                      "syscall",
+	"syscall.SYS_PSYNCH_RW_LONGRDLOCK":                     "syscall",
+	"syscall.SYS_PSYNCH_RW_RDLOCK":                         "syscall",
+	"syscall.SYS_PSYNCH_RW_UNLOCK":                         "syscall",
+	"syscall.SYS_PSYNCH_RW_UNLOCK2":                        "syscall",
+	"syscall.SYS_PSYNCH_RW_UPGRADE":                        "syscall",
+	"syscall.SYS_PSYNCH_RW_WRLOCK":                         "syscall",
+	"syscall.SYS_PSYNCH_RW_YIELDWRLOCK":                    "syscall",
+	"syscall.SYS_PTRACE":                                   "syscall",
+	"syscall.SYS_PUTPMSG":                                  "syscall",
+	"syscall.SYS_PWRITE":                                   "syscall",
+	"syscall.SYS_PWRITE64":                                 "syscall",
+	"syscall.SYS_PWRITEV":                                  "syscall",
+	"syscall.SYS_PWRITE_NOCANCEL":                          "syscall",
+	"syscall.SYS_QUERY_MODULE":                             "syscall",
+	"syscall.SYS_QUOTACTL":                                 "syscall",
+	"syscall.SYS_RASCTL":                                   "syscall",
+	"syscall.SYS_RCTL_ADD_RULE":                            "syscall",
+	"syscall.SYS_RCTL_GET_LIMITS":                          "syscall",
+	"syscall.SYS_RCTL_GET_RACCT":                           "syscall",
+	"syscall.SYS_RCTL_GET_RULES":                           "syscall",
+	"syscall.SYS_RCTL_REMOVE_RULE":                         "syscall",
+	"syscall.SYS_READ":                                     "syscall",
+	"syscall.SYS_READAHEAD":                                "syscall",
+	"syscall.SYS_READDIR":                                  "syscall",
+	"syscall.SYS_READLINK":                                 "syscall",
+	"syscall.SYS_READLINKAT":                               "syscall",
+	"syscall.SYS_READV":                                    "syscall",
+	"syscall.SYS_READV_NOCANCEL":                           "syscall",
+	"syscall.SYS_READ_NOCANCEL":                            "syscall",
+	"syscall.SYS_REBOOT":                                   "syscall",
+	"syscall.SYS_RECV":                                     "syscall",
+	"syscall.SYS_RECVFROM":                                 "syscall",
+	"syscall.SYS_RECVFROM_NOCANCEL":                        "syscall",
+	"syscall.SYS_RECVMMSG":                                 "syscall",
+	"syscall.SYS_RECVMSG":                                  "syscall",
+	"syscall.SYS_RECVMSG_NOCANCEL":                         "syscall",
+	"syscall.SYS_REMAP_FILE_PAGES":                         "syscall",
+	"syscall.SYS_REMOVEXATTR":                              "syscall",
+	"syscall.SYS_RENAME":                                   "syscall",
+	"syscall.SYS_RENAMEAT":                                 "syscall",
+	"syscall.SYS_REQUEST_KEY":                              "syscall",
+	"syscall.SYS_RESTART_SYSCALL":                          "syscall",
+	"syscall.SYS_REVOKE":                                   "syscall",
+	"syscall.SYS_RFORK":                                    "syscall",
+	"syscall.SYS_RMDIR":                                    "syscall",
+	"syscall.SYS_RTPRIO":                                   "syscall",
+	"syscall.SYS_RTPRIO_THREAD":                            "syscall",
+	"syscall.SYS_RT_SIGACTION":                             "syscall",
+	"syscall.SYS_RT_SIGPENDING":                            "syscall",
+	"syscall.SYS_RT_SIGPROCMASK":                           "syscall",
+	"syscall.SYS_RT_SIGQUEUEINFO":                          "syscall",
+	"syscall.SYS_RT_SIGRETURN":                             "syscall",
+	"syscall.SYS_RT_SIGSUSPEND":                            "syscall",
+	"syscall.SYS_RT_SIGTIMEDWAIT":                          "syscall",
+	"syscall.SYS_RT_TGSIGQUEUEINFO":                        "syscall",
+	"syscall.SYS_SBRK":                                     "syscall",
+	"syscall.SYS_SCHED_GETAFFINITY":                        "syscall",
+	"syscall.SYS_SCHED_GETPARAM":                           "syscall",
+	"syscall.SYS_SCHED_GETSCHEDULER":                       "syscall",
+	"syscall.SYS_SCHED_GET_PRIORITY_MAX":                   "syscall",
+	"syscall.SYS_SCHED_GET_PRIORITY_MIN":                   "syscall",
+	"syscall.SYS_SCHED_RR_GET_INTERVAL":                    "syscall",
+	"syscall.SYS_SCHED_SETAFFINITY":                        "syscall",
+	"syscall.SYS_SCHED_SETPARAM":                           "syscall",
+	"syscall.SYS_SCHED_SETSCHEDULER":                       "syscall",
+	"syscall.SYS_SCHED_YIELD":                              "syscall",
+	"syscall.SYS_SCTP_GENERIC_RECVMSG":                     "syscall",
+	"syscall.SYS_SCTP_GENERIC_SENDMSG":                     "syscall",
+	"syscall.SYS_SCTP_GENERIC_SENDMSG_IOV":                 "syscall",
+	"syscall.SYS_SCTP_PEELOFF":                             "syscall",
+	"syscall.SYS_SEARCHFS":                                 "syscall",
+	"syscall.SYS_SECURITY":                                 "syscall",
+	"syscall.SYS_SELECT":                                   "syscall",
+	"syscall.SYS_SELECT_NOCANCEL":                          "syscall",
+	"syscall.SYS_SEMCONFIG":                                "syscall",
+	"syscall.SYS_SEMCTL":                                   "syscall",
+	"syscall.SYS_SEMGET":                                   "syscall",
+	"syscall.SYS_SEMOP":                                    "syscall",
+	"syscall.SYS_SEMSYS":                                   "syscall",
+	"syscall.SYS_SEMTIMEDOP":                               "syscall",
+	"syscall.SYS_SEM_CLOSE":                                "syscall",
+	"syscall.SYS_SEM_DESTROY":                              "syscall",
+	"syscall.SYS_SEM_GETVALUE":                             "syscall",
+	"syscall.SYS_SEM_INIT":                                 "syscall",
+	"syscall.SYS_SEM_OPEN":                                 "syscall",
+	"syscall.SYS_SEM_POST":                                 "syscall",
+	"syscall.SYS_SEM_TRYWAIT":                              "syscall",
+	"syscall.SYS_SEM_UNLINK":                               "syscall",
+	"syscall.SYS_SEM_WAIT":                                 "syscall",
+	"syscall.SYS_SEM_WAIT_NOCANCEL":                        "syscall",
+	"syscall.SYS_SEND":                                     "syscall",
+	"syscall.SYS_SENDFILE":                                 "syscall",
+	"syscall.SYS_SENDFILE64":                               "syscall",
+	"syscall.SYS_SENDMMSG":                                 "syscall",
+	"syscall.SYS_SENDMSG":                                  "syscall",
+	"syscall.SYS_SENDMSG_NOCANCEL":                         "syscall",
+	"syscall.SYS_SENDTO":                                   "syscall",
+	"syscall.SYS_SENDTO_NOCANCEL":                          "syscall",
+	"syscall.SYS_SETATTRLIST":                              "syscall",
+	"syscall.SYS_SETAUDIT":                                 "syscall",
+	"syscall.SYS_SETAUDIT_ADDR":                            "syscall",
+	"syscall.SYS_SETAUID":                                  "syscall",
+	"syscall.SYS_SETCONTEXT":                               "syscall",
+	"syscall.SYS_SETDOMAINNAME":                            "syscall",
+	"syscall.SYS_SETEGID":                                  "syscall",
+	"syscall.SYS_SETEUID":                                  "syscall",
+	"syscall.SYS_SETFIB":                                   "syscall",
+	"syscall.SYS_SETFSGID":                                 "syscall",
+	"syscall.SYS_SETFSGID32":                               "syscall",
+	"syscall.SYS_SETFSUID":                                 "syscall",
+	"syscall.SYS_SETFSUID32":                               "syscall",
+	"syscall.SYS_SETGID":                                   "syscall",
+	"syscall.SYS_SETGID32":                                 "syscall",
+	"syscall.SYS_SETGROUPS":                                "syscall",
+	"syscall.SYS_SETGROUPS32":                              "syscall",
+	"syscall.SYS_SETHOSTNAME":                              "syscall",
+	"syscall.SYS_SETITIMER":                                "syscall",
+	"syscall.SYS_SETLCID":                                  "syscall",
+	"syscall.SYS_SETLOGIN":                                 "syscall",
+	"syscall.SYS_SETLOGINCLASS":                            "syscall",
+	"syscall.SYS_SETNS":                                    "syscall",
+	"syscall.SYS_SETPGID":                                  "syscall",
+	"syscall.SYS_SETPRIORITY":                              "syscall",
+	"syscall.SYS_SETPRIVEXEC":                              "syscall",
+	"syscall.SYS_SETREGID":                                 "syscall",
+	"syscall.SYS_SETREGID32":                               "syscall",
+	"syscall.SYS_SETRESGID":                                "syscall",
+	"syscall.SYS_SETRESGID32":                              "syscall",
+	"syscall.SYS_SETRESUID":                                "syscall",
+	"syscall.SYS_SETRESUID32":                              "syscall",
+	"syscall.SYS_SETREUID":                                 "syscall",
+	"syscall.SYS_SETREUID32":                               "syscall",
+	"syscall.SYS_SETRLIMIT":                                "syscall",
+	"syscall.SYS_SETRTABLE":                                "syscall",
+	"syscall.SYS_SETSGROUPS":                               "syscall",
+	"syscall.SYS_SETSID":                                   "syscall",
+	"syscall.SYS_SETSOCKOPT":                               "syscall",
+	"syscall.SYS_SETTID":                                   "syscall",
+	"syscall.SYS_SETTID_WITH_PID":                          "syscall",
+	"syscall.SYS_SETTIMEOFDAY":                             "syscall",
+	"syscall.SYS_SETUID":                                   "syscall",
+	"syscall.SYS_SETUID32":                                 "syscall",
+	"syscall.SYS_SETWGROUPS":                               "syscall",
+	"syscall.SYS_SETXATTR":                                 "syscall",
+	"syscall.SYS_SET_MEMPOLICY":                            "syscall",
+	"syscall.SYS_SET_ROBUST_LIST":                          "syscall",
+	"syscall.SYS_SET_THREAD_AREA":                          "syscall",
+	"syscall.SYS_SET_TID_ADDRESS":                          "syscall",
+	"syscall.SYS_SGETMASK":                                 "syscall",
+	"syscall.SYS_SHARED_REGION_CHECK_NP":                   "syscall",
+	"syscall.SYS_SHARED_REGION_MAP_AND_SLIDE_NP":           "syscall",
+	"syscall.SYS_SHMAT":                                    "syscall",
+	"syscall.SYS_SHMCTL":                                   "syscall",
+	"syscall.SYS_SHMDT":                                    "syscall",
+	"syscall.SYS_SHMGET":                                   "syscall",
+	"syscall.SYS_SHMSYS":                                   "syscall",
+	"syscall.SYS_SHM_OPEN":                                 "syscall",
+	"syscall.SYS_SHM_UNLINK":                               "syscall",
+	"syscall.SYS_SHUTDOWN":                                 "syscall",
+	"syscall.SYS_SIGACTION":                                "syscall",
+	"syscall.SYS_SIGALTSTACK":                              "syscall",
+	"syscall.SYS_SIGNAL":                                   "syscall",
+	"syscall.SYS_SIGNALFD":                                 "syscall",
+	"syscall.SYS_SIGNALFD4":                                "syscall",
+	"syscall.SYS_SIGPENDING":                               "syscall",
+	"syscall.SYS_SIGPROCMASK":                              "syscall",
+	"syscall.SYS_SIGQUEUE":                                 "syscall",
+	"syscall.SYS_SIGQUEUEINFO":                             "syscall",
+	"syscall.SYS_SIGRETURN":                                "syscall",
+	"syscall.SYS_SIGSUSPEND":                               "syscall",
+	"syscall.SYS_SIGSUSPEND_NOCANCEL":                      "syscall",
+	"syscall.SYS_SIGTIMEDWAIT":                             "syscall",
+	"syscall.SYS_SIGWAIT":                                  "syscall",
+	"syscall.SYS_SIGWAITINFO":                              "syscall",
+	"syscall.SYS_SOCKET":                                   "syscall",
+	"syscall.SYS_SOCKETCALL":                               "syscall",
+	"syscall.SYS_SOCKETPAIR":                               "syscall",
+	"syscall.SYS_SPLICE":                                   "syscall",
+	"syscall.SYS_SSETMASK":                                 "syscall",
+	"syscall.SYS_SSTK":                                     "syscall",
+	"syscall.SYS_STACK_SNAPSHOT":                           "syscall",
+	"syscall.SYS_STAT":                                     "syscall",
+	"syscall.SYS_STAT64":                                   "syscall",
+	"syscall.SYS_STAT64_EXTENDED":                          "syscall",
+	"syscall.SYS_STATFS":                                   "syscall",
+	"syscall.SYS_STATFS64":                                 "syscall",
+	"syscall.SYS_STATV":                                    "syscall",
+	"syscall.SYS_STATVFS1":                                 "syscall",
+	"syscall.SYS_STAT_EXTENDED":                            "syscall",
+	"syscall.SYS_STIME":                                    "syscall",
+	"syscall.SYS_STTY":                                     "syscall",
+	"syscall.SYS_SWAPCONTEXT":                              "syscall",
+	"syscall.SYS_SWAPCTL":                                  "syscall",
+	"syscall.SYS_SWAPOFF":                                  "syscall",
+	"syscall.SYS_SWAPON":                                   "syscall",
+	"syscall.SYS_SYMLINK":                                  "syscall",
+	"syscall.SYS_SYMLINKAT":                                "syscall",
+	"syscall.SYS_SYNC":                                     "syscall",
+	"syscall.SYS_SYNCFS":                                   "syscall",
+	"syscall.SYS_SYNC_FILE_RANGE":                          "syscall",
+	"syscall.SYS_SYSARCH":                                  "syscall",
+	"syscall.SYS_SYSCALL":                                  "syscall",
+	"syscall.SYS_SYSCALL_BASE":                             "syscall",
+	"syscall.SYS_SYSFS":                                    "syscall",
+	"syscall.SYS_SYSINFO":                                  "syscall",
+	"syscall.SYS_SYSLOG":                                   "syscall",
+	"syscall.SYS_TEE":                                      "syscall",
+	"syscall.SYS_TGKILL":                                   "syscall",
+	"syscall.SYS_THREAD_SELFID":                            "syscall",
+	"syscall.SYS_THR_CREATE":                               "syscall",
+	"syscall.SYS_THR_EXIT":                                 "syscall",
+	"syscall.SYS_THR_KILL":                                 "syscall",
+	"syscall.SYS_THR_KILL2":                                "syscall",
+	"syscall.SYS_THR_NEW":                                  "syscall",
+	"syscall.SYS_THR_SELF":                                 "syscall",
+	"syscall.SYS_THR_SET_NAME":                             "syscall",
+	"syscall.SYS_THR_SUSPEND":                              "syscall",
+	"syscall.SYS_THR_WAKE":                                 "syscall",
+	"syscall.SYS_TIME":                                     "syscall",
+	"syscall.SYS_TIMERFD_CREATE":                           "syscall",
+	"syscall.SYS_TIMERFD_GETTIME":                          "syscall",
+	"syscall.SYS_TIMERFD_SETTIME":                          "syscall",
+	"syscall.SYS_TIMER_CREATE":                             "syscall",
+	"syscall.SYS_TIMER_DELETE":                             "syscall",
+	"syscall.SYS_TIMER_GETOVERRUN":                         "syscall",
+	"syscall.SYS_TIMER_GETTIME":                            "syscall",
+	"syscall.SYS_TIMER_SETTIME":                            "syscall",
+	"syscall.SYS_TIMES":                                    "syscall",
+	"syscall.SYS_TKILL":                                    "syscall",
+	"syscall.SYS_TRUNCATE":                                 "syscall",
+	"syscall.SYS_TRUNCATE64":                               "syscall",
+	"syscall.SYS_TUXCALL":                                  "syscall",
+	"syscall.SYS_UGETRLIMIT":                               "syscall",
+	"syscall.SYS_ULIMIT":                                   "syscall",
+	"syscall.SYS_UMASK":                                    "syscall",
+	"syscall.SYS_UMASK_EXTENDED":                           "syscall",
+	"syscall.SYS_UMOUNT":                                   "syscall",
+	"syscall.SYS_UMOUNT2":                                  "syscall",
+	"syscall.SYS_UNAME":                                    "syscall",
+	"syscall.SYS_UNDELETE":                                 "syscall",
+	"syscall.SYS_UNLINK":                                   "syscall",
+	"syscall.SYS_UNLINKAT":                                 "syscall",
+	"syscall.SYS_UNMOUNT":                                  "syscall",
+	"syscall.SYS_UNSHARE":                                  "syscall",
+	"syscall.SYS_USELIB":                                   "syscall",
+	"syscall.SYS_USTAT":                                    "syscall",
+	"syscall.SYS_UTIME":                                    "syscall",
+	"syscall.SYS_UTIMENSAT":                                "syscall",
+	"syscall.SYS_UTIMES":                                   "syscall",
+	"syscall.SYS_UTRACE":                                   "syscall",
+	"syscall.SYS_UUIDGEN":                                  "syscall",
+	"syscall.SYS_VADVISE":                                  "syscall",
+	"syscall.SYS_VFORK":                                    "syscall",
+	"syscall.SYS_VHANGUP":                                  "syscall",
+	"syscall.SYS_VM86":                                     "syscall",
+	"syscall.SYS_VM86OLD":                                  "syscall",
+	"syscall.SYS_VMSPLICE":                                 "syscall",
+	"syscall.SYS_VM_PRESSURE_MONITOR":                      "syscall",
+	"syscall.SYS_VSERVER":                                  "syscall",
+	"syscall.SYS_WAIT4":                                    "syscall",
+	"syscall.SYS_WAIT4_NOCANCEL":                           "syscall",
+	"syscall.SYS_WAIT6":                                    "syscall",
+	"syscall.SYS_WAITEVENT":                                "syscall",
+	"syscall.SYS_WAITID":                                   "syscall",
+	"syscall.SYS_WAITID_NOCANCEL":                          "syscall",
+	"syscall.SYS_WAITPID":                                  "syscall",
+	"syscall.SYS_WATCHEVENT":                               "syscall",
+	"syscall.SYS_WORKQ_KERNRETURN":                         "syscall",
+	"syscall.SYS_WORKQ_OPEN":                               "syscall",
+	"syscall.SYS_WRITE":                                    "syscall",
+	"syscall.SYS_WRITEV":                                   "syscall",
+	"syscall.SYS_WRITEV_NOCANCEL":                          "syscall",
+	"syscall.SYS_WRITE_NOCANCEL":                           "syscall",
+	"syscall.SYS_YIELD":                                    "syscall",
+	"syscall.SYS__LLSEEK":                                  "syscall",
+	"syscall.SYS__LWP_CONTINUE":                            "syscall",
+	"syscall.SYS__LWP_CREATE":                              "syscall",
+	"syscall.SYS__LWP_CTL":                                 "syscall",
+	"syscall.SYS__LWP_DETACH":                              "syscall",
+	"syscall.SYS__LWP_EXIT":                                "syscall",
+	"syscall.SYS__LWP_GETNAME":                             "syscall",
+	"syscall.SYS__LWP_GETPRIVATE":                          "syscall",
+	"syscall.SYS__LWP_KILL":                                "syscall",
+	"syscall.SYS__LWP_PARK":                                "syscall",
+	"syscall.SYS__LWP_SELF":                                "syscall",
+	"syscall.SYS__LWP_SETNAME":                             "syscall",
+	"syscall.SYS__LWP_SETPRIVATE":                          "syscall",
+	"syscall.SYS__LWP_SUSPEND":                             "syscall",
+	"syscall.SYS__LWP_UNPARK":                              "syscall",
+	"syscall.SYS__LWP_UNPARK_ALL":                          "syscall",
+	"syscall.SYS__LWP_WAIT":                                "syscall",
+	"syscall.SYS__LWP_WAKEUP":                              "syscall",
+	"syscall.SYS__NEWSELECT":                               "syscall",
+	"syscall.SYS__PSET_BIND":                               "syscall",
+	"syscall.SYS__SCHED_GETAFFINITY":                       "syscall",
+	"syscall.SYS__SCHED_GETPARAM":                          "syscall",
+	"syscall.SYS__SCHED_SETAFFINITY":                       "syscall",
+	"syscall.SYS__SCHED_SETPARAM":                          "syscall",
+	"syscall.SYS__SYSCTL":                                  "syscall",
+	"syscall.SYS__UMTX_LOCK":                               "syscall",
+	"syscall.SYS__UMTX_OP":                                 "syscall",
+	"syscall.SYS__UMTX_UNLOCK":                             "syscall",
+	"syscall.SYS___ACL_ACLCHECK_FD":                        "syscall",
+	"syscall.SYS___ACL_ACLCHECK_FILE":                      "syscall",
+	"syscall.SYS___ACL_ACLCHECK_LINK":                      "syscall",
+	"syscall.SYS___ACL_DELETE_FD":                          "syscall",
+	"syscall.SYS___ACL_DELETE_FILE":                        "syscall",
+	"syscall.SYS___ACL_DELETE_LINK":                        "syscall",
+	"syscall.SYS___ACL_GET_FD":                             "syscall",
+	"syscall.SYS___ACL_GET_FILE":                           "syscall",
+	"syscall.SYS___ACL_GET_LINK":                           "syscall",
+	"syscall.SYS___ACL_SET_FD":                             "syscall",
+	"syscall.SYS___ACL_SET_FILE":                           "syscall",
+	"syscall.SYS___ACL_SET_LINK":                           "syscall",
+	"syscall.SYS___CLONE":                                  "syscall",
+	"syscall.SYS___DISABLE_THREADSIGNAL":                   "syscall",
+	"syscall.SYS___GETCWD":                                 "syscall",
+	"syscall.SYS___GETLOGIN":                               "syscall",
+	"syscall.SYS___GET_TCB":                                "syscall",
+	"syscall.SYS___MAC_EXECVE":                             "syscall",
+	"syscall.SYS___MAC_GETFSSTAT":                          "syscall",
+	"syscall.SYS___MAC_GET_FD":                             "syscall",
+	"syscall.SYS___MAC_GET_FILE":                           "syscall",
+	"syscall.SYS___MAC_GET_LCID":                           "syscall",
+	"syscall.SYS___MAC_GET_LCTX":                           "syscall",
+	"syscall.SYS___MAC_GET_LINK":                           "syscall",
+	"syscall.SYS___MAC_GET_MOUNT":                          "syscall",
+	"syscall.SYS___MAC_GET_PID":                            "syscall",
+	"syscall.SYS___MAC_GET_PROC":                           "syscall",
+	"syscall.SYS___MAC_MOUNT":                              "syscall",
+	"syscall.SYS___MAC_SET_FD":                             "syscall",
+	"syscall.SYS___MAC_SET_FILE":                           "syscall",
+	"syscall.SYS___MAC_SET_LCTX":                           "syscall",
+	"syscall.SYS___MAC_SET_LINK":                           "syscall",
+	"syscall.SYS___MAC_SET_PROC":                           "syscall",
+	"syscall.SYS___MAC_SYSCALL":                            "syscall",
+	"syscall.SYS___OLD_SEMWAIT_SIGNAL":                     "syscall",
+	"syscall.SYS___OLD_SEMWAIT_SIGNAL_NOCANCEL":            "syscall",
+	"syscall.SYS___POSIX_CHOWN":                            "syscall",
+	"syscall.SYS___POSIX_FCHOWN":                           "syscall",
+	"syscall.SYS___POSIX_LCHOWN":                           "syscall",
+	"syscall.SYS___POSIX_RENAME":                           "syscall",
+	"syscall.SYS___PTHREAD_CANCELED":                       "syscall",
+	"syscall.SYS___PTHREAD_CHDIR":                          "syscall",
+	"syscall.SYS___PTHREAD_FCHDIR":                         "syscall",
+	"syscall.SYS___PTHREAD_KILL":                           "syscall",
+	"syscall.SYS___PTHREAD_MARKCANCEL":                     "syscall",
+	"syscall.SYS___PTHREAD_SIGMASK":                        "syscall",
+	"syscall.SYS___QUOTACTL":                               "syscall",
+	"syscall.SYS___SEMCTL":                                 "syscall",
+	"syscall.SYS___SEMWAIT_SIGNAL":                         "syscall",
+	"syscall.SYS___SEMWAIT_SIGNAL_NOCANCEL":                "syscall",
+	"syscall.SYS___SETLOGIN":                               "syscall",
+	"syscall.SYS___SETUGID":                                "syscall",
+	"syscall.SYS___SET_TCB":                                "syscall",
+	"syscall.SYS___SIGACTION_SIGTRAMP":                     "syscall",
+	"syscall.SYS___SIGTIMEDWAIT":                           "syscall",
+	"syscall.SYS___SIGWAIT":                                "syscall",
+	"syscall.SYS___SIGWAIT_NOCANCEL":                       "syscall",
+	"syscall.SYS___SYSCTL":                                 "syscall",
+	"syscall.SYS___TFORK":                                  "syscall",
+	"syscall.SYS___THREXIT":                                "syscall",
+	"syscall.SYS___THRSIGDIVERT":                           "syscall",
+	"syscall.SYS___THRSLEEP":                               "syscall",
+	"syscall.SYS___THRWAKEUP":                              "syscall",
+	"syscall.S_ARCH1":                                      "syscall",
+	"syscall.S_ARCH2":                                      "syscall",
+	"syscall.S_BLKSIZE":                                    "syscall",
+	"syscall.S_IEXEC":                                      "syscall",
+	"syscall.S_IFBLK":                                      "syscall",
+	"syscall.S_IFCHR":                                      "syscall",
+	"syscall.S_IFDIR":                                      "syscall",
+	"syscall.S_IFIFO":                                      "syscall",
+	"syscall.S_IFLNK":                                      "syscall",
+	"syscall.S_IFMT":                                       "syscall",
+	"syscall.S_IFREG":                                      "syscall",
+	"syscall.S_IFSOCK":                                     "syscall",
+	"syscall.S_IFWHT":                                      "syscall",
+	"syscall.S_IREAD":                                      "syscall",
+	"syscall.S_IRGRP":                                      "syscall",
+	"syscall.S_IROTH":                                      "syscall",
+	"syscall.S_IRUSR":                                      "syscall",
+	"syscall.S_IRWXG":                                      "syscall",
+	"syscall.S_IRWXO":                                      "syscall",
+	"syscall.S_IRWXU":                                      "syscall",
+	"syscall.S_ISGID":                                      "syscall",
+	"syscall.S_ISTXT":                                      "syscall",
+	"syscall.S_ISUID":                                      "syscall",
+	"syscall.S_ISVTX":                                      "syscall",
+	"syscall.S_IWGRP":                                      "syscall",
+	"syscall.S_IWOTH":                                      "syscall",
+	"syscall.S_IWRITE":                                     "syscall",
+	"syscall.S_IWUSR":                                      "syscall",
+	"syscall.S_IXGRP":                                      "syscall",
+	"syscall.S_IXOTH":                                      "syscall",
+	"syscall.S_IXUSR":                                      "syscall",
+	"syscall.S_LOGIN_SET":                                  "syscall",
+	"syscall.SecurityAttributes":                           "syscall",
+	"syscall.Seek":                                         "syscall",
+	"syscall.Select":                                       "syscall",
+	"syscall.Sendfile":                                     "syscall",
+	"syscall.Sendmsg":                                      "syscall",
+	"syscall.Sendto":                                       "syscall",
+	"syscall.Servent":                                      "syscall",
+	"syscall.SetBpf":                                       "syscall",
+	"syscall.SetBpfBuflen":                                 "syscall",
+	"syscall.SetBpfDatalink":                               "syscall",
+	"syscall.SetBpfHeadercmpl":                             "syscall",
+	"syscall.SetBpfImmediate":                              "syscall",
+	"syscall.SetBpfInterface":                              "syscall",
+	"syscall.SetBpfPromisc":                                "syscall",
+	"syscall.SetBpfTimeout":                                "syscall",
+	"syscall.SetCurrentDirectory":                          "syscall",
+	"syscall.SetEndOfFile":                                 "syscall",
+	"syscall.SetEnvironmentVariable":                       "syscall",
+	"syscall.SetFileAttributes":                            "syscall",
+	"syscall.SetFileCompletionNotificationModes":           "syscall",
+	"syscall.SetFilePointer":                               "syscall",
+	"syscall.SetFileTime":                                  "syscall",
+	"syscall.SetHandleInformation":                         "syscall",
+	"syscall.SetKevent":                                    "syscall",
+	"syscall.SetLsfPromisc":                                "syscall",
+	"syscall.SetNonblock":                                  "syscall",
+	"syscall.Setdomainname":                                "syscall",
+	"syscall.Setegid":                                      "syscall",
+	"syscall.Setenv":                                       "syscall",
+	"syscall.Seteuid":                                      "syscall",
+	"syscall.Setfsgid":                                     "syscall",
+	"syscall.Setfsuid":                                     "syscall",
+	"syscall.Setgid":                                       "syscall",
+	"syscall.Setgroups":                                    "syscall",
+	"syscall.Sethostname":                                  "syscall",
+	"syscall.Setlogin":                                     "syscall",
+	"syscall.Setpgid":                                      "syscall",
+	"syscall.Setpriority":                                  "syscall",
+	"syscall.Setprivexec":                                  "syscall",
+	"syscall.Setregid":                                     "syscall",
+	"syscall.Setresgid":                                    "syscall",
+	"syscall.Setresuid":                                    "syscall",
+	"syscall.Setreuid":                                     "syscall",
+	"syscall.Setrlimit":                                    "syscall",
+	"syscall.Setsid":                                       "syscall",
+	"syscall.Setsockopt":                                   "syscall",
+	"syscall.SetsockoptByte":                               "syscall",
+	"syscall.SetsockoptICMPv6Filter":                       "syscall",
+	"syscall.SetsockoptIPMreq":                             "syscall",
+	"syscall.SetsockoptIPMreqn":                            "syscall",
+	"syscall.SetsockoptIPv6Mreq":                           "syscall",
+	"syscall.SetsockoptInet4Addr":                          "syscall",
+	"syscall.SetsockoptInt":                                "syscall",
+	"syscall.SetsockoptLinger":                             "syscall",
+	"syscall.SetsockoptString":                             "syscall",
+	"syscall.SetsockoptTimeval":                            "syscall",
+	"syscall.Settimeofday":                                 "syscall",
+	"syscall.Setuid":                                       "syscall",
+	"syscall.Setxattr":                                     "syscall",
+	"syscall.Shutdown":                                     "syscall",
+	"syscall.SidTypeAlias":                                 "syscall",
+	"syscall.SidTypeComputer":                              "syscall",
+	"syscall.SidTypeDeletedAccount":                        "syscall",
+	"syscall.SidTypeDomain":                                "syscall",
+	"syscall.SidTypeGroup":                                 "syscall",
+	"syscall.SidTypeInvalid":                               "syscall",
+	"syscall.SidTypeLabel":                                 "syscall",
+	"syscall.SidTypeUnknown":                               "syscall",
+	"syscall.SidTypeUser":                                  "syscall",
+	"syscall.SidTypeWellKnownGroup":                        "syscall",
+	"syscall.Signal":                                       "syscall",
+	"syscall.SizeofBpfHdr":                                 "syscall",
+	"syscall.SizeofBpfInsn":                                "syscall",
+	"syscall.SizeofBpfProgram":                             "syscall",
+	"syscall.SizeofBpfStat":                                "syscall",
+	"syscall.SizeofBpfVersion":                             "syscall",
+	"syscall.SizeofBpfZbuf":                                "syscall",
+	"syscall.SizeofBpfZbufHeader":                          "syscall",
+	"syscall.SizeofCmsghdr":                                "syscall",
+	"syscall.SizeofICMPv6Filter":                           "syscall",
+	"syscall.SizeofIPMreq":                                 "syscall",
+	"syscall.SizeofIPMreqn":                                "syscall",
+	"syscall.SizeofIPv6MTUInfo":                            "syscall",
+	"syscall.SizeofIPv6Mreq":                               "syscall",
+	"syscall.SizeofIfAddrmsg":                              "syscall",
+	"syscall.SizeofIfAnnounceMsghdr":                       "syscall",
+	"syscall.SizeofIfData":                                 "syscall",
+	"syscall.SizeofIfInfomsg":                              "syscall",
+	"syscall.SizeofIfMsghdr":                               "syscall",
+	"syscall.SizeofIfaMsghdr":                              "syscall",
+	"syscall.SizeofIfmaMsghdr":                             "syscall",
+	"syscall.SizeofIfmaMsghdr2":                            "syscall",
+	"syscall.SizeofInet4Pktinfo":                           "syscall",
+	"syscall.SizeofInet6Pktinfo":                           "syscall",
+	"syscall.SizeofInotifyEvent":                           "syscall",
+	"syscall.SizeofLinger":                                 "syscall",
+	"syscall.SizeofMsghdr":                                 "syscall",
+	"syscall.SizeofNlAttr":                                 "syscall",
+	"syscall.SizeofNlMsgerr":                               "syscall",
+	"syscall.SizeofNlMsghdr":                               "syscall",
+	"syscall.SizeofRtAttr":                                 "syscall",
+	"syscall.SizeofRtGenmsg":                               "syscall",
+	"syscall.SizeofRtMetrics":                              "syscall",
+	"syscall.SizeofRtMsg":                                  "syscall",
+	"syscall.SizeofRtMsghdr":                               "syscall",
+	"syscall.SizeofRtNexthop":                              "syscall",
+	"syscall.SizeofSockFilter":                             "syscall",
+	"syscall.SizeofSockFprog":                              "syscall",
+	"syscall.SizeofSockaddrAny":                            "syscall",
+	"syscall.SizeofSockaddrDatalink":                       "syscall",
+	"syscall.SizeofSockaddrInet4":                          "syscall",
+	"syscall.SizeofSockaddrInet6":                          "syscall",
+	"syscall.SizeofSockaddrLinklayer":                      "syscall",
+	"syscall.SizeofSockaddrNetlink":                        "syscall",
+	"syscall.SizeofSockaddrUnix":                           "syscall",
+	"syscall.SizeofTCPInfo":                                "syscall",
+	"syscall.SizeofUcred":                                  "syscall",
+	"syscall.SlicePtrFromStrings":                          "syscall",
+	"syscall.SockFilter":                                   "syscall",
+	"syscall.SockFprog":                                    "syscall",
+	"syscall.SockaddrDatalink":                             "syscall",
+	"syscall.SockaddrGen":                                  "syscall",
+	"syscall.SockaddrInet4":                                "syscall",
+	"syscall.SockaddrInet6":                                "syscall",
+	"syscall.SockaddrLinklayer":                            "syscall",
+	"syscall.SockaddrNetlink":                              "syscall",
+	"syscall.SockaddrUnix":                                 "syscall",
+	"syscall.Socket":                                       "syscall",
+	"syscall.SocketControlMessage":                         "syscall",
+	"syscall.SocketDisableIPv6":                            "syscall",
+	"syscall.Socketpair":                                   "syscall",
+	"syscall.Splice":                                       "syscall",
+	"syscall.StartProcess":                                 "syscall",
+	"syscall.StartupInfo":                                  "syscall",
+	"syscall.Stat":                                         "syscall",
+	"syscall.Stat_t":                                       "syscall",
+	"syscall.Statfs":                                       "syscall",
+	"syscall.Statfs_t":                                     "syscall",
+	"syscall.Stderr":                                       "syscall",
+	"syscall.Stdin":                                        "syscall",
+	"syscall.Stdout":                                       "syscall",
+	"syscall.StringBytePtr":                                "syscall",
+	"syscall.StringByteSlice":                              "syscall",
+	"syscall.StringSlicePtr":                               "syscall",
+	"syscall.StringToSid":                                  "syscall",
+	"syscall.StringToUTF16":                                "syscall",
+	"syscall.StringToUTF16Ptr":                             "syscall",
+	"syscall.Symlink":                                      "syscall",
+	"syscall.Sync":                                         "syscall",
+	"syscall.SyncFileRange":                                "syscall",
+	"syscall.SysProcAttr":                                  "syscall",
+	"syscall.Syscall":                                      "syscall",
+	"syscall.Syscall12":                                    "syscall",
+	"syscall.Syscall15":                                    "syscall",
+	"syscall.Syscall6":                                     "syscall",
+	"syscall.Syscall9":                                     "syscall",
+	"syscall.Sysctl":                                       "syscall",
+	"syscall.SysctlUint32":                                 "syscall",
+	"syscall.Sysctlnode":                                   "syscall",
+	"syscall.Sysinfo":                                      "syscall",
+	"syscall.Sysinfo_t":                                    "syscall",
+	"syscall.Systemtime":                                   "syscall",
+	"syscall.TCGETS":                                       "syscall",
+	"syscall.TCIFLUSH":                                     "syscall",
+	"syscall.TCIOFLUSH":                                    "syscall",
+	"syscall.TCOFLUSH":                                     "syscall",
+	"syscall.TCPInfo":                                      "syscall",
+	"syscall.TCP_CA_NAME_MAX":                              "syscall",
+	"syscall.TCP_CONGCTL":                                  "syscall",
+	"syscall.TCP_CONGESTION":                               "syscall",
+	"syscall.TCP_CONNECTIONTIMEOUT":                        "syscall",
+	"syscall.TCP_CORK":                                     "syscall",
+	"syscall.TCP_DEFER_ACCEPT":                             "syscall",
+	"syscall.TCP_INFO":                                     "syscall",
+	"syscall.TCP_KEEPALIVE":                                "syscall",
+	"syscall.TCP_KEEPCNT":                                  "syscall",
+	"syscall.TCP_KEEPIDLE":                                 "syscall",
+	"syscall.TCP_KEEPINIT":                                 "syscall",
+	"syscall.TCP_KEEPINTVL":                                "syscall",
+	"syscall.TCP_LINGER2":                                  "syscall",
+	"syscall.TCP_MAXBURST":                                 "syscall",
+	"syscall.TCP_MAXHLEN":                                  "syscall",
+	"syscall.TCP_MAXOLEN":                                  "syscall",
+	"syscall.TCP_MAXSEG":                                   "syscall",
+	"syscall.TCP_MAXWIN":                                   "syscall",
+	"syscall.TCP_MAX_SACK":                                 "syscall",
+	"syscall.TCP_MAX_WINSHIFT":                             "syscall",
+	"syscall.TCP_MD5SIG":                                   "syscall",
+	"syscall.TCP_MD5SIG_MAXKEYLEN":                         "syscall",
+	"syscall.TCP_MINMSS":                                   "syscall",
+	"syscall.TCP_MINMSSOVERLOAD":                           "syscall",
+	"syscall.TCP_MSS":                                      "syscall",
+	"syscall.TCP_NODELAY":                                  "syscall",
+	"syscall.TCP_NOOPT":                                    "syscall",
+	"syscall.TCP_NOPUSH":                                   "syscall",
+	"syscall.TCP_NSTATES":                                  "syscall",
+	"syscall.TCP_QUICKACK":                                 "syscall",
+	"syscall.TCP_RXT_CONNDROPTIME":                         "syscall",
+	"syscall.TCP_RXT_FINDROP":                              "syscall",
+	"syscall.TCP_SACK_ENABLE":                              "syscall",
+	"syscall.TCP_SYNCNT":                                   "syscall",
+	"syscall.TCP_WINDOW_CLAMP":                             "syscall",
+	"syscall.TCSAFLUSH":                                    "syscall",
+	"syscall.TCSETS":                                       "syscall",
+	"syscall.TF_DISCONNECT":                                "syscall",
+	"syscall.TF_REUSE_SOCKET":                              "syscall",
+	"syscall.TF_USE_DEFAULT_WORKER":                        "syscall",
+	"syscall.TF_USE_KERNEL_APC":                            "syscall",
+	"syscall.TF_USE_SYSTEM_THREAD":                         "syscall",
+	"syscall.TF_WRITE_BEHIND":                              "syscall",
+	"syscall.TIME_ZONE_ID_DAYLIGHT":                        "syscall",
+	"syscall.TIME_ZONE_ID_STANDARD":                        "syscall",
+	"syscall.TIME_ZONE_ID_UNKNOWN":                         "syscall",
+	"syscall.TIOCCBRK":                                     "syscall",
+	"syscall.TIOCCDTR":                                     "syscall",
+	"syscall.TIOCCONS":                                     "syscall",
+	"syscall.TIOCDCDTIMESTAMP":                             "syscall",
+	"syscall.TIOCDRAIN":                                    "syscall",
+	"syscall.TIOCDSIMICROCODE":                             "syscall",
+	"syscall.TIOCEXCL":                                     "syscall",
+	"syscall.TIOCEXT":                                      "syscall",
+	"syscall.TIOCFLAG_CDTRCTS":                             "syscall",
+	"syscall.TIOCFLAG_CLOCAL":                              "syscall",
+	"syscall.TIOCFLAG_CRTSCTS":                             "syscall",
+	"syscall.TIOCFLAG_MDMBUF":                              "syscall",
+	"syscall.TIOCFLAG_PPS":                                 "syscall",
+	"syscall.TIOCFLAG_SOFTCAR":                             "syscall",
+	"syscall.TIOCFLUSH":                                    "syscall",
+	"syscall.TIOCGDEV":                                     "syscall",
+	"syscall.TIOCGDRAINWAIT":                               "syscall",
+	"syscall.TIOCGETA":                                     "syscall",
+	"syscall.TIOCGETD":                                     "syscall",
+	"syscall.TIOCGFLAGS":                                   "syscall",
+	"syscall.TIOCGICOUNT":                                  "syscall",
+	"syscall.TIOCGLCKTRMIOS":                               "syscall",
+	"syscall.TIOCGLINED":                                   "syscall",
+	"syscall.TIOCGPGRP":                                    "syscall",
+	"syscall.TIOCGPTN":                                     "syscall",
+	"syscall.TIOCGQSIZE":                                   "syscall",
+	"syscall.TIOCGRANTPT":                                  "syscall",
+	"syscall.TIOCGRS485":                                   "syscall",
+	"syscall.TIOCGSERIAL":                                  "syscall",
+	"syscall.TIOCGSID":                                     "syscall",
+	"syscall.TIOCGSIZE":                                    "syscall",
+	"syscall.TIOCGSOFTCAR":                                 "syscall",
+	"syscall.TIOCGTSTAMP":                                  "syscall",
+	"syscall.TIOCGWINSZ":                                   "syscall",
+	"syscall.TIOCINQ":                                      "syscall",
+	"syscall.TIOCIXOFF":                                    "syscall",
+	"syscall.TIOCIXON":                                     "syscall",
+	"syscall.TIOCLINUX":                                    "syscall",
+	"syscall.TIOCMBIC":                                     "syscall",
+	"syscall.TIOCMBIS":                                     "syscall",
+	"syscall.TIOCMGDTRWAIT":                                "syscall",
+	"syscall.TIOCMGET":                                     "syscall",
+	"syscall.TIOCMIWAIT":                                   "syscall",
+	"syscall.TIOCMODG":                                     "syscall",
+	"syscall.TIOCMODS":                                     "syscall",
+	"syscall.TIOCMSDTRWAIT":                                "syscall",
+	"syscall.TIOCMSET":                                     "syscall",
+	"syscall.TIOCM_CAR":                                    "syscall",
+	"syscall.TIOCM_CD":                                     "syscall",
+	"syscall.TIOCM_CTS":                                    "syscall",
+	"syscall.TIOCM_DCD":                                    "syscall",
+	"syscall.TIOCM_DSR":                                    "syscall",
+	"syscall.TIOCM_DTR":                                    "syscall",
+	"syscall.TIOCM_LE":                                     "syscall",
+	"syscall.TIOCM_RI":                                     "syscall",
+	"syscall.TIOCM_RNG":                                    "syscall",
+	"syscall.TIOCM_RTS":                                    "syscall",
+	"syscall.TIOCM_SR":                                     "syscall",
+	"syscall.TIOCM_ST":                                     "syscall",
+	"syscall.TIOCNOTTY":                                    "syscall",
+	"syscall.TIOCNXCL":                                     "syscall",
+	"syscall.TIOCOUTQ":                                     "syscall",
+	"syscall.TIOCPKT":                                      "syscall",
+	"syscall.TIOCPKT_DATA":                                 "syscall",
+	"syscall.TIOCPKT_DOSTOP":                               "syscall",
+	"syscall.TIOCPKT_FLUSHREAD":                            "syscall",
+	"syscall.TIOCPKT_FLUSHWRITE":                           "syscall",
+	"syscall.TIOCPKT_IOCTL":                                "syscall",
+	"syscall.TIOCPKT_NOSTOP":                               "syscall",
+	"syscall.TIOCPKT_START":                                "syscall",
+	"syscall.TIOCPKT_STOP":                                 "syscall",
+	"syscall.TIOCPTMASTER":                                 "syscall",
+	"syscall.TIOCPTMGET":                                   "syscall",
+	"syscall.TIOCPTSNAME":                                  "syscall",
+	"syscall.TIOCPTYGNAME":                                 "syscall",
+	"syscall.TIOCPTYGRANT":                                 "syscall",
+	"syscall.TIOCPTYUNLK":                                  "syscall",
+	"syscall.TIOCRCVFRAME":                                 "syscall",
+	"syscall.TIOCREMOTE":                                   "syscall",
+	"syscall.TIOCSBRK":                                     "syscall",
+	"syscall.TIOCSCONS":                                    "syscall",
+	"syscall.TIOCSCTTY":                                    "syscall",
+	"syscall.TIOCSDRAINWAIT":                               "syscall",
+	"syscall.TIOCSDTR":                                     "syscall",
+	"syscall.TIOCSERCONFIG":                                "syscall",
+	"syscall.TIOCSERGETLSR":                                "syscall",
+	"syscall.TIOCSERGETMULTI":                              "syscall",
+	"syscall.TIOCSERGSTRUCT":                               "syscall",
+	"syscall.TIOCSERGWILD":                                 "syscall",
+	"syscall.TIOCSERSETMULTI":                              "syscall",
+	"syscall.TIOCSERSWILD":                                 "syscall",
+	"syscall.TIOCSER_TEMT":                                 "syscall",
+	"syscall.TIOCSETA":                                     "syscall",
+	"syscall.TIOCSETAF":                                    "syscall",
+	"syscall.TIOCSETAW":                                    "syscall",
+	"syscall.TIOCSETD":                                     "syscall",
+	"syscall.TIOCSFLAGS":                                   "syscall",
+	"syscall.TIOCSIG":                                      "syscall",
+	"syscall.TIOCSLCKTRMIOS":                               "syscall",
+	"syscall.TIOCSLINED":                                   "syscall",
+	"syscall.TIOCSPGRP":                                    "syscall",
+	"syscall.TIOCSPTLCK":                                   "syscall",
+	"syscall.TIOCSQSIZE":                                   "syscall",
+	"syscall.TIOCSRS485":                                   "syscall",
+	"syscall.TIOCSSERIAL":                                  "syscall",
+	"syscall.TIOCSSIZE":                                    "syscall",
+	"syscall.TIOCSSOFTCAR":                                 "syscall",
+	"syscall.TIOCSTART":                                    "syscall",
+	"syscall.TIOCSTAT":                                     "syscall",
+	"syscall.TIOCSTI":                                      "syscall",
+	"syscall.TIOCSTOP":                                     "syscall",
+	"syscall.TIOCSTSTAMP":                                  "syscall",
+	"syscall.TIOCSWINSZ":                                   "syscall",
+	"syscall.TIOCTIMESTAMP":                                "syscall",
+	"syscall.TIOCUCNTL":                                    "syscall",
+	"syscall.TIOCVHANGUP":                                  "syscall",
+	"syscall.TIOCXMTFRAME":                                 "syscall",
+	"syscall.TOKEN_ADJUST_DEFAULT":                         "syscall",
+	"syscall.TOKEN_ADJUST_GROUPS":                          "syscall",
+	"syscall.TOKEN_ADJUST_PRIVILEGES":                      "syscall",
+	"syscall.TOKEN_ALL_ACCESS":                             "syscall",
+	"syscall.TOKEN_ASSIGN_PRIMARY":                         "syscall",
+	"syscall.TOKEN_DUPLICATE":                              "syscall",
+	"syscall.TOKEN_EXECUTE":                                "syscall",
+	"syscall.TOKEN_IMPERSONATE":                            "syscall",
+	"syscall.TOKEN_QUERY":                                  "syscall",
+	"syscall.TOKEN_QUERY_SOURCE":                           "syscall",
+	"syscall.TOKEN_READ":                                   "syscall",
+	"syscall.TOKEN_WRITE":                                  "syscall",
+	"syscall.TOSTOP":                                       "syscall",
+	"syscall.TRUNCATE_EXISTING":                            "syscall",
+	"syscall.TUNATTACHFILTER":                              "syscall",
+	"syscall.TUNDETACHFILTER":                              "syscall",
+	"syscall.TUNGETFEATURES":                               "syscall",
+	"syscall.TUNGETIFF":                                    "syscall",
+	"syscall.TUNGETSNDBUF":                                 "syscall",
+	"syscall.TUNGETVNETHDRSZ":                              "syscall",
+	"syscall.TUNSETDEBUG":                                  "syscall",
+	"syscall.TUNSETGROUP":                                  "syscall",
+	"syscall.TUNSETIFF":                                    "syscall",
+	"syscall.TUNSETLINK":                                   "syscall",
+	"syscall.TUNSETNOCSUM":                                 "syscall",
+	"syscall.TUNSETOFFLOAD":                                "syscall",
+	"syscall.TUNSETOWNER":                                  "syscall",
+	"syscall.TUNSETPERSIST":                                "syscall",
+	"syscall.TUNSETSNDBUF":                                 "syscall",
+	"syscall.TUNSETTXFILTER":                               "syscall",
+	"syscall.TUNSETVNETHDRSZ":                              "syscall",
+	"syscall.Tee":                                          "syscall",
+	"syscall.TerminateProcess":                             "syscall",
+	"syscall.Termios":                                      "syscall",
+	"syscall.Tgkill":                                       "syscall",
+	"syscall.Time":                                         "syscall",
+	"syscall.Time_t":                                       "syscall",
+	"syscall.Times":                                        "syscall",
+	"syscall.Timespec":                                     "syscall",
+	"syscall.TimespecToNsec":                               "syscall",
+	"syscall.Timeval":                                      "syscall",
+	"syscall.Timeval32":                                    "syscall",
+	"syscall.TimevalToNsec":                                "syscall",
+	"syscall.Timex":                                        "syscall",
+	"syscall.Timezoneinformation":                          "syscall",
+	"syscall.Tms":                                          "syscall",
+	"syscall.Token":                                        "syscall",
+	"syscall.TokenAccessInformation":                       "syscall",
+	"syscall.TokenAuditPolicy":                             "syscall",
+	"syscall.TokenDefaultDacl":                             "syscall",
+	"syscall.TokenElevation":                               "syscall",
+	"syscall.TokenElevationType":                           "syscall",
+	"syscall.TokenGroups":                                  "syscall",
+	"syscall.TokenGroupsAndPrivileges":                     "syscall",
+	"syscall.TokenHasRestrictions":                         "syscall",
+	"syscall.TokenImpersonationLevel":                      "syscall",
+	"syscall.TokenIntegrityLevel":                          "syscall",
+	"syscall.TokenLinkedToken":                             "syscall",
+	"syscall.TokenLogonSid":                                "syscall",
+	"syscall.TokenMandatoryPolicy":                         "syscall",
+	"syscall.TokenOrigin":                                  "syscall",
+	"syscall.TokenOwner":                                   "syscall",
+	"syscall.TokenPrimaryGroup":                            "syscall",
+	"syscall.TokenPrivileges":                              "syscall",
+	"syscall.TokenRestrictedSids":                          "syscall",
+	"syscall.TokenSandBoxInert":                            "syscall",
+	"syscall.TokenSessionId":                               "syscall",
+	"syscall.TokenSessionReference":                        "syscall",
+	"syscall.TokenSource":                                  "syscall",
+	"syscall.TokenStatistics":                              "syscall",
+	"syscall.TokenType":                                    "syscall",
+	"syscall.TokenUIAccess":                                "syscall",
+	"syscall.TokenUser":                                    "syscall",
+	"syscall.TokenVirtualizationAllowed":                   "syscall",
+	"syscall.TokenVirtualizationEnabled":                   "syscall",
+	"syscall.Tokenprimarygroup":                            "syscall",
+	"syscall.Tokenuser":                                    "syscall",
+	"syscall.TranslateAccountName":                         "syscall",
+	"syscall.TranslateName":                                "syscall",
+	"syscall.TransmitFile":                                 "syscall",
+	"syscall.TransmitFileBuffers":                          "syscall",
+	"syscall.Truncate":                                     "syscall",
+	"syscall.USAGE_MATCH_TYPE_AND":                         "syscall",
+	"syscall.USAGE_MATCH_TYPE_OR":                          "syscall",
+	"syscall.UTF16FromString":                              "syscall",
+	"syscall.UTF16PtrFromString":                           "syscall",
+	"syscall.UTF16ToString":                                "syscall",
+	"syscall.Ucred":                                        "syscall",
+	"syscall.Umask":                                        "syscall",
+	"syscall.Uname":                                        "syscall",
+	"syscall.Undelete":                                     "syscall",
+	"syscall.UnixCredentials":                              "syscall",
+	"syscall.UnixRights":                                   "syscall",
+	"syscall.Unlink":                                       "syscall",
+	"syscall.Unlinkat":                                     "syscall",
+	"syscall.UnmapViewOfFile":                              "syscall",
+	"syscall.Unmount":                                      "syscall",
+	"syscall.Unshare":                                      "syscall",
+	"syscall.UserInfo10":                                   "syscall",
+	"syscall.Ustat":                                        "syscall",
+	"syscall.Ustat_t":                                      "syscall",
+	"syscall.Utimbuf":                                      "syscall",
+	"syscall.Utime":                                        "syscall",
+	"syscall.Utimes":                                       "syscall",
+	"syscall.UtimesNano":                                   "syscall",
+	"syscall.Utsname":                                      "syscall",
+	"syscall.VDISCARD":                                     "syscall",
+	"syscall.VDSUSP":                                       "syscall",
+	"syscall.VEOF":                                         "syscall",
+	"syscall.VEOL":                                         "syscall",
+	"syscall.VEOL2":                                        "syscall",
+	"syscall.VERASE":                                       "syscall",
+	"syscall.VERASE2":                                      "syscall",
+	"syscall.VINTR":                                        "syscall",
+	"syscall.VKILL":                                        "syscall",
+	"syscall.VLNEXT":                                       "syscall",
+	"syscall.VMIN":                                         "syscall",
+	"syscall.VQUIT":                                        "syscall",
+	"syscall.VREPRINT":                                     "syscall",
+	"syscall.VSTART":                                       "syscall",
+	"syscall.VSTATUS":                                      "syscall",
+	"syscall.VSTOP":                                        "syscall",
+	"syscall.VSUSP":                                        "syscall",
+	"syscall.VSWTC":                                        "syscall",
+	"syscall.VT0":                                          "syscall",
+	"syscall.VT1":                                          "syscall",
+	"syscall.VTDLY":                                        "syscall",
+	"syscall.VTIME":                                        "syscall",
+	"syscall.VWERASE":                                      "syscall",
+	"syscall.VirtualLock":                                  "syscall",
+	"syscall.VirtualUnlock":                                "syscall",
+	"syscall.WAIT_ABANDONED":                               "syscall",
+	"syscall.WAIT_FAILED":                                  "syscall",
+	"syscall.WAIT_OBJECT_0":                                "syscall",
+	"syscall.WAIT_TIMEOUT":                                 "syscall",
+	"syscall.WALL":                                         "syscall",
+	"syscall.WALLSIG":                                      "syscall",
+	"syscall.WALTSIG":                                      "syscall",
+	"syscall.WCLONE":                                       "syscall",
+	"syscall.WCONTINUED":                                   "syscall",
+	"syscall.WCOREFLAG":                                    "syscall",
+	"syscall.WEXITED":                                      "syscall",
+	"syscall.WLINUXCLONE":                                  "syscall",
+	"syscall.WNOHANG":                                      "syscall",
+	"syscall.WNOTHREAD":                                    "syscall",
+	"syscall.WNOWAIT":                                      "syscall",
+	"syscall.WNOZOMBIE":                                    "syscall",
+	"syscall.WOPTSCHECKED":                                 "syscall",
+	"syscall.WORDSIZE":                                     "syscall",
+	"syscall.WSABuf":                                       "syscall",
+	"syscall.WSACleanup":                                   "syscall",
+	"syscall.WSADESCRIPTION_LEN":                           "syscall",
+	"syscall.WSAData":                                      "syscall",
+	"syscall.WSAEACCES":                                    "syscall",
+	"syscall.WSAEnumProtocols":                             "syscall",
+	"syscall.WSAID_CONNECTEX":                              "syscall",
+	"syscall.WSAIoctl":                                     "syscall",
+	"syscall.WSAPROTOCOL_LEN":                              "syscall",
+	"syscall.WSAProtocolChain":                             "syscall",
+	"syscall.WSAProtocolInfo":                              "syscall",
+	"syscall.WSARecv":                                      "syscall",
+	"syscall.WSARecvFrom":                                  "syscall",
+	"syscall.WSASYS_STATUS_LEN":                            "syscall",
+	"syscall.WSASend":                                      "syscall",
+	"syscall.WSASendTo":                                    "syscall",
+	"syscall.WSASendto":                                    "syscall",
+	"syscall.WSAStartup":                                   "syscall",
+	"syscall.WSTOPPED":                                     "syscall",
+	"syscall.WTRAPPED":                                     "syscall",
+	"syscall.WUNTRACED":                                    "syscall",
+	"syscall.Wait4":                                        "syscall",
+	"syscall.WaitForSingleObject":                          "syscall",
+	"syscall.WaitStatus":                                   "syscall",
+	"syscall.Win32FileAttributeData":                       "syscall",
+	"syscall.Win32finddata":                                "syscall",
+	"syscall.Write":                                        "syscall",
+	"syscall.WriteConsole":                                 "syscall",
+	"syscall.WriteFile":                                    "syscall",
+	"syscall.X509_ASN_ENCODING":                            "syscall",
+	"syscall.XCASE":                                        "syscall",
+	"syscall.XP1_CONNECTIONLESS":                           "syscall",
+	"syscall.XP1_CONNECT_DATA":                             "syscall",
+	"syscall.XP1_DISCONNECT_DATA":                          "syscall",
+	"syscall.XP1_EXPEDITED_DATA":                           "syscall",
+	"syscall.XP1_GRACEFUL_CLOSE":                           "syscall",
+	"syscall.XP1_GUARANTEED_DELIVERY":                      "syscall",
+	"syscall.XP1_GUARANTEED_ORDER":                         "syscall",
+	"syscall.XP1_IFS_HANDLES":                              "syscall",
+	"syscall.XP1_MESSAGE_ORIENTED":                         "syscall",
+	"syscall.XP1_MULTIPOINT_CONTROL_PLANE":                 "syscall",
+	"syscall.XP1_MULTIPOINT_DATA_PLANE":                    "syscall",
+	"syscall.XP1_PARTIAL_MESSAGE":                          "syscall",
+	"syscall.XP1_PSEUDO_STREAM":                            "syscall",
+	"syscall.XP1_QOS_SUPPORTED":                            "syscall",
+	"syscall.XP1_SAN_SUPPORT_SDP":                          "syscall",
+	"syscall.XP1_SUPPORT_BROADCAST":                        "syscall",
+	"syscall.XP1_SUPPORT_MULTIPOINT":                       "syscall",
+	"syscall.XP1_UNI_RECV":                                 "syscall",
+	"syscall.XP1_UNI_SEND":                                 "syscall",
+	"syslog.Dial":                                          "log/syslog",
+	"syslog.LOG_ALERT":                                     "log/syslog",
+	"syslog.LOG_AUTH":                                      "log/syslog",
+	"syslog.LOG_AUTHPRIV":                                  "log/syslog",
+	"syslog.LOG_CRIT":                                      "log/syslog",
+	"syslog.LOG_CRON":                                      "log/syslog",
+	"syslog.LOG_DAEMON":                                    "log/syslog",
+	"syslog.LOG_DEBUG":                                     "log/syslog",
+	"syslog.LOG_EMERG":                                     "log/syslog",
+	"syslog.LOG_ERR":                                       "log/syslog",
+	"syslog.LOG_FTP":                                       "log/syslog",
+	"syslog.LOG_INFO":                                      "log/syslog",
+	"syslog.LOG_KERN":                                      "log/syslog",
+	"syslog.LOG_LOCAL0":                                    "log/syslog",
+	"syslog.LOG_LOCAL1":                                    "log/syslog",
+	"syslog.LOG_LOCAL2":                                    "log/syslog",
+	"syslog.LOG_LOCAL3":                                    "log/syslog",
+	"syslog.LOG_LOCAL4":                                    "log/syslog",
+	"syslog.LOG_LOCAL5":                                    "log/syslog",
+	"syslog.LOG_LOCAL6":                                    "log/syslog",
+	"syslog.LOG_LOCAL7":                                    "log/syslog",
+	"syslog.LOG_LPR":                                       "log/syslog",
+	"syslog.LOG_MAIL":                                      "log/syslog",
+	"syslog.LOG_NEWS":                                      "log/syslog",
+	"syslog.LOG_NOTICE":                                    "log/syslog",
+	"syslog.LOG_SYSLOG":                                    "log/syslog",
+	"syslog.LOG_USER":                                      "log/syslog",
+	"syslog.LOG_UUCP":                                      "log/syslog",
+	"syslog.LOG_WARNING":                                   "log/syslog",
+	"syslog.New":                                           "log/syslog",
+	"syslog.NewLogger":                                     "log/syslog",
+	"syslog.Priority":                                      "log/syslog",
+	"syslog.Writer":                                        "log/syslog",
+	"tabwriter.AlignRight":                                 "text/tabwriter",
+	"tabwriter.Debug":                                      "text/tabwriter",
+	"tabwriter.DiscardEmptyColumns":                        "text/tabwriter",
+	"tabwriter.Escape":                                     "text/tabwriter",
+	"tabwriter.FilterHTML":                                 "text/tabwriter",
+	"tabwriter.NewWriter":                                  "text/tabwriter",
+	"tabwriter.StripEscape":                                "text/tabwriter",
+	"tabwriter.TabIndent":                                  "text/tabwriter",
+	"tabwriter.Writer":                                     "text/tabwriter",
+	"tar.ErrFieldTooLong":                                  "archive/tar",
+	"tar.ErrHeader":                                        "archive/tar",
+	"tar.ErrWriteAfterClose":                               "archive/tar",
+	"tar.ErrWriteTooLong":                                  "archive/tar",
+	"tar.FileInfoHeader":                                   "archive/tar",
+	"tar.Header":                                           "archive/tar",
+	"tar.NewReader":                                        "archive/tar",
+	"tar.NewWriter":                                        "archive/tar",
+	"tar.Reader":                                           "archive/tar",
+	"tar.TypeBlock":                                        "archive/tar",
+	"tar.TypeChar":                                         "archive/tar",
+	"tar.TypeCont":                                         "archive/tar",
+	"tar.TypeDir":                                          "archive/tar",
+	"tar.TypeFifo":                                         "archive/tar",
+	"tar.TypeGNULongLink":                                  "archive/tar",
+	"tar.TypeGNULongName":                                  "archive/tar",
+	"tar.TypeLink":                                         "archive/tar",
+	"tar.TypeReg":                                          "archive/tar",
+	"tar.TypeRegA":                                         "archive/tar",
+	"tar.TypeSymlink":                                      "archive/tar",
+	"tar.TypeXGlobalHeader":                                "archive/tar",
+	"tar.TypeXHeader":                                      "archive/tar",
+	"tar.Writer":                                           "archive/tar",
+	"template.CSS":                                         "html/template",
+	"template.ErrAmbigContext":                             "html/template",
+	"template.ErrBadHTML":                                  "html/template",
+	"template.ErrBranchEnd":                                "html/template",
+	"template.ErrEndContext":                               "html/template",
+	"template.ErrNoSuchTemplate":                           "html/template",
+	"template.ErrOutputContext":                            "html/template",
+	"template.ErrPartialCharset":                           "html/template",
+	"template.ErrPartialEscape":                            "html/template",
+	"template.ErrRangeLoopReentry":                         "html/template",
+	"template.ErrSlashAmbig":                               "html/template",
+	"template.Error":                                       "html/template",
+	"template.ErrorCode":                                   "html/template",
+	// "template.FuncMap" is ambiguous
+	"template.HTML":     "html/template",
+	"template.HTMLAttr": "html/template",
+	// "template.HTMLEscape" is ambiguous
+	// "template.HTMLEscapeString" is ambiguous
+	// "template.HTMLEscaper" is ambiguous
+	"template.JS": "html/template",
+	// "template.JSEscape" is ambiguous
+	// "template.JSEscapeString" is ambiguous
+	// "template.JSEscaper" is ambiguous
+	"template.JSStr": "html/template",
+	// "template.Must" is ambiguous
+	// "template.New" is ambiguous
+	"template.OK": "html/template",
+	// "template.ParseFiles" is ambiguous
+	// "template.ParseGlob" is ambiguous
+	// "template.Template" is ambiguous
+	"template.URL": "html/template",
+	// "template.URLQueryEscaper" is ambiguous
+	"testing.AllocsPerRun":                        "testing",
+	"testing.B":                                   "testing",
+	"testing.Benchmark":                           "testing",
+	"testing.BenchmarkResult":                     "testing",
+	"testing.Cover":                               "testing",
+	"testing.CoverBlock":                          "testing",
+	"testing.InternalBenchmark":                   "testing",
+	"testing.InternalExample":                     "testing",
+	"testing.InternalTest":                        "testing",
+	"testing.Main":                                "testing",
+	"testing.RegisterCover":                       "testing",
+	"testing.RunBenchmarks":                       "testing",
+	"testing.RunExamples":                         "testing",
+	"testing.RunTests":                            "testing",
+	"testing.Short":                               "testing",
+	"testing.T":                                   "testing",
+	"testing.Verbose":                             "testing",
+	"textproto.CanonicalMIMEHeaderKey":            "net/textproto",
+	"textproto.Conn":                              "net/textproto",
+	"textproto.Dial":                              "net/textproto",
+	"textproto.Error":                             "net/textproto",
+	"textproto.MIMEHeader":                        "net/textproto",
+	"textproto.NewConn":                           "net/textproto",
+	"textproto.NewReader":                         "net/textproto",
+	"textproto.NewWriter":                         "net/textproto",
+	"textproto.Pipeline":                          "net/textproto",
+	"textproto.ProtocolError":                     "net/textproto",
+	"textproto.Reader":                            "net/textproto",
+	"textproto.TrimBytes":                         "net/textproto",
+	"textproto.TrimString":                        "net/textproto",
+	"textproto.Writer":                            "net/textproto",
+	"time.ANSIC":                                  "time",
+	"time.After":                                  "time",
+	"time.AfterFunc":                              "time",
+	"time.April":                                  "time",
+	"time.August":                                 "time",
+	"time.Date":                                   "time",
+	"time.December":                               "time",
+	"time.Duration":                               "time",
+	"time.February":                               "time",
+	"time.FixedZone":                              "time",
+	"time.Friday":                                 "time",
+	"time.Hour":                                   "time",
+	"time.January":                                "time",
+	"time.July":                                   "time",
+	"time.June":                                   "time",
+	"time.Kitchen":                                "time",
+	"time.LoadLocation":                           "time",
+	"time.Local":                                  "time",
+	"time.Location":                               "time",
+	"time.March":                                  "time",
+	"time.May":                                    "time",
+	"time.Microsecond":                            "time",
+	"time.Millisecond":                            "time",
+	"time.Minute":                                 "time",
+	"time.Monday":                                 "time",
+	"time.Month":                                  "time",
+	"time.Nanosecond":                             "time",
+	"time.NewTicker":                              "time",
+	"time.NewTimer":                               "time",
+	"time.November":                               "time",
+	"time.Now":                                    "time",
+	"time.October":                                "time",
+	"time.Parse":                                  "time",
+	"time.ParseDuration":                          "time",
+	"time.ParseError":                             "time",
+	"time.ParseInLocation":                        "time",
+	"time.RFC1123":                                "time",
+	"time.RFC1123Z":                               "time",
+	"time.RFC3339":                                "time",
+	"time.RFC3339Nano":                            "time",
+	"time.RFC822":                                 "time",
+	"time.RFC822Z":                                "time",
+	"time.RFC850":                                 "time",
+	"time.RubyDate":                               "time",
+	"time.Saturday":                               "time",
+	"time.Second":                                 "time",
+	"time.September":                              "time",
+	"time.Since":                                  "time",
+	"time.Sleep":                                  "time",
+	"time.Stamp":                                  "time",
+	"time.StampMicro":                             "time",
+	"time.StampMilli":                             "time",
+	"time.StampNano":                              "time",
+	"time.Sunday":                                 "time",
+	"time.Thursday":                               "time",
+	"time.Tick":                                   "time",
+	"time.Ticker":                                 "time",
+	"time.Time":                                   "time",
+	"time.Timer":                                  "time",
+	"time.Tuesday":                                "time",
+	"time.UTC":                                    "time",
+	"time.Unix":                                   "time",
+	"time.UnixDate":                               "time",
+	"time.Wednesday":                              "time",
+	"time.Weekday":                                "time",
+	"tls.Certificate":                             "crypto/tls",
+	"tls.Client":                                  "crypto/tls",
+	"tls.ClientAuthType":                          "crypto/tls",
+	"tls.Config":                                  "crypto/tls",
+	"tls.Conn":                                    "crypto/tls",
+	"tls.ConnectionState":                         "crypto/tls",
+	"tls.Dial":                                    "crypto/tls",
+	"tls.Listen":                                  "crypto/tls",
+	"tls.LoadX509KeyPair":                         "crypto/tls",
+	"tls.NewListener":                             "crypto/tls",
+	"tls.NoClientCert":                            "crypto/tls",
+	"tls.RequestClientCert":                       "crypto/tls",
+	"tls.RequireAndVerifyClientCert":              "crypto/tls",
+	"tls.RequireAnyClientCert":                    "crypto/tls",
+	"tls.Server":                                  "crypto/tls",
+	"tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA":    "crypto/tls",
+	"tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256": "crypto/tls",
+	"tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA":    "crypto/tls",
+	"tls.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA":        "crypto/tls",
+	"tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA":     "crypto/tls",
+	"tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA":      "crypto/tls",
+	"tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256":   "crypto/tls",
+	"tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA":      "crypto/tls",
+	"tls.TLS_ECDHE_RSA_WITH_RC4_128_SHA":          "crypto/tls",
+	"tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA":           "crypto/tls",
+	"tls.TLS_RSA_WITH_AES_128_CBC_SHA":            "crypto/tls",
+	"tls.TLS_RSA_WITH_AES_256_CBC_SHA":            "crypto/tls",
+	"tls.TLS_RSA_WITH_RC4_128_SHA":                "crypto/tls",
+	"tls.VerifyClientCertIfGiven":                 "crypto/tls",
+	"tls.VersionSSL30":                            "crypto/tls",
+	"tls.VersionTLS10":                            "crypto/tls",
+	"tls.VersionTLS11":                            "crypto/tls",
+	"tls.VersionTLS12":                            "crypto/tls",
+	"tls.X509KeyPair":                             "crypto/tls",
+	"token.ADD":                                   "go/token",
+	"token.ADD_ASSIGN":                            "go/token",
+	"token.AND":                                   "go/token",
+	"token.AND_ASSIGN":                            "go/token",
+	"token.AND_NOT":                               "go/token",
+	"token.AND_NOT_ASSIGN":                        "go/token",
+	"token.ARROW":                                 "go/token",
+	"token.ASSIGN":                                "go/token",
+	"token.BREAK":                                 "go/token",
+	"token.CASE":                                  "go/token",
+	"token.CHAN":                                  "go/token",
+	"token.CHAR":                                  "go/token",
+	"token.COLON":                                 "go/token",
+	"token.COMMA":                                 "go/token",
+	"token.COMMENT":                               "go/token",
+	"token.CONST":                                 "go/token",
+	"token.CONTINUE":                              "go/token",
+	"token.DEC":                                   "go/token",
+	"token.DEFAULT":                               "go/token",
+	"token.DEFER":                                 "go/token",
+	"token.DEFINE":                                "go/token",
+	"token.ELLIPSIS":                              "go/token",
+	"token.ELSE":                                  "go/token",
+	"token.EOF":                                   "go/token",
+	"token.EQL":                                   "go/token",
+	"token.FALLTHROUGH":                           "go/token",
+	"token.FLOAT":                                 "go/token",
+	"token.FOR":                                   "go/token",
+	"token.FUNC":                                  "go/token",
+	"token.File":                                  "go/token",
+	"token.FileSet":                               "go/token",
+	"token.GEQ":                                   "go/token",
+	"token.GO":                                    "go/token",
+	"token.GOTO":                                  "go/token",
+	"token.GTR":                                   "go/token",
+	"token.HighestPrec":                           "go/token",
+	"token.IDENT":                                 "go/token",
+	"token.IF":                                    "go/token",
+	"token.ILLEGAL":                               "go/token",
+	"token.IMAG":                                  "go/token",
+	"token.IMPORT":                                "go/token",
+	"token.INC":                                   "go/token",
+	"token.INT":                                   "go/token",
+	"token.INTERFACE":                             "go/token",
+	"token.LAND":                                  "go/token",
+	"token.LBRACE":                                "go/token",
+	"token.LBRACK":                                "go/token",
+	"token.LEQ":                                   "go/token",
+	"token.LOR":                                   "go/token",
+	"token.LPAREN":                                "go/token",
+	"token.LSS":                                   "go/token",
+	"token.Lookup":                                "go/token",
+	"token.LowestPrec":                            "go/token",
+	"token.MAP":                                   "go/token",
+	"token.MUL":                                   "go/token",
+	"token.MUL_ASSIGN":                            "go/token",
+	"token.NEQ":                                   "go/token",
+	"token.NOT":                                   "go/token",
+	"token.NewFileSet":                            "go/token",
+	"token.NoPos":                                 "go/token",
+	"token.OR":                                    "go/token",
+	"token.OR_ASSIGN":                             "go/token",
+	"token.PACKAGE":                               "go/token",
+	"token.PERIOD":                                "go/token",
+	"token.Pos":                                   "go/token",
+	"token.Position":                              "go/token",
+	"token.QUO":                                   "go/token",
+	"token.QUO_ASSIGN":                            "go/token",
+	"token.RANGE":                                 "go/token",
+	"token.RBRACE":                                "go/token",
+	"token.RBRACK":                                "go/token",
+	"token.REM":                                   "go/token",
+	"token.REM_ASSIGN":                            "go/token",
+	"token.RETURN":                                "go/token",
+	"token.RPAREN":                                "go/token",
+	"token.SELECT":                                "go/token",
+	"token.SEMICOLON":                             "go/token",
+	"token.SHL":                                   "go/token",
+	"token.SHL_ASSIGN":                            "go/token",
+	"token.SHR":                                   "go/token",
+	"token.SHR_ASSIGN":                            "go/token",
+	"token.STRING":                                "go/token",
+	"token.STRUCT":                                "go/token",
+	"token.SUB":                                   "go/token",
+	"token.SUB_ASSIGN":                            "go/token",
+	"token.SWITCH":                                "go/token",
+	"token.TYPE":                                  "go/token",
+	"token.Token":                                 "go/token",
+	"token.UnaryPrec":                             "go/token",
+	"token.VAR":                                   "go/token",
+	"token.XOR":                                   "go/token",
+	"token.XOR_ASSIGN":                            "go/token",
+	"unicode.ASCII_Hex_Digit":                     "unicode",
+	"unicode.Arabic":                              "unicode",
+	"unicode.Armenian":                            "unicode",
+	"unicode.Avestan":                             "unicode",
+	"unicode.AzeriCase":                           "unicode",
+	"unicode.Balinese":                            "unicode",
+	"unicode.Bamum":                               "unicode",
+	"unicode.Batak":                               "unicode",
+	"unicode.Bengali":                             "unicode",
+	"unicode.Bidi_Control":                        "unicode",
+	"unicode.Bopomofo":                            "unicode",
+	"unicode.Brahmi":                              "unicode",
+	"unicode.Braille":                             "unicode",
+	"unicode.Buginese":                            "unicode",
+	"unicode.Buhid":                               "unicode",
+	"unicode.C":                                   "unicode",
+	"unicode.Canadian_Aboriginal":                 "unicode",
+	"unicode.Carian":                              "unicode",
+	"unicode.CaseRange":                           "unicode",
+	"unicode.CaseRanges":                          "unicode",
+	"unicode.Categories":                          "unicode",
+	"unicode.Cc":                                  "unicode",
+	"unicode.Cf":                                  "unicode",
+	"unicode.Chakma":                              "unicode",
+	"unicode.Cham":                                "unicode",
+	"unicode.Cherokee":                            "unicode",
+	"unicode.Co":                                  "unicode",
+	"unicode.Common":                              "unicode",
+	"unicode.Coptic":                              "unicode",
+	"unicode.Cs":                                  "unicode",
+	"unicode.Cuneiform":                           "unicode",
+	"unicode.Cypriot":                             "unicode",
+	"unicode.Cyrillic":                            "unicode",
+	"unicode.Dash":                                "unicode",
+	"unicode.Deprecated":                          "unicode",
+	"unicode.Deseret":                             "unicode",
+	"unicode.Devanagari":                          "unicode",
+	"unicode.Diacritic":                           "unicode",
+	"unicode.Digit":                               "unicode",
+	"unicode.Egyptian_Hieroglyphs":                "unicode",
+	"unicode.Ethiopic":                            "unicode",
+	"unicode.Extender":                            "unicode",
+	"unicode.FoldCategory":                        "unicode",
+	"unicode.FoldScript":                          "unicode",
+	"unicode.Georgian":                            "unicode",
+	"unicode.Glagolitic":                          "unicode",
+	"unicode.Gothic":                              "unicode",
+	"unicode.GraphicRanges":                       "unicode",
+	"unicode.Greek":                               "unicode",
+	"unicode.Gujarati":                            "unicode",
+	"unicode.Gurmukhi":                            "unicode",
+	"unicode.Han":                                 "unicode",
+	"unicode.Hangul":                              "unicode",
+	"unicode.Hanunoo":                             "unicode",
+	"unicode.Hebrew":                              "unicode",
+	"unicode.Hex_Digit":                           "unicode",
+	"unicode.Hiragana":                            "unicode",
+	"unicode.Hyphen":                              "unicode",
+	"unicode.IDS_Binary_Operator":                 "unicode",
+	"unicode.IDS_Trinary_Operator":                "unicode",
+	"unicode.Ideographic":                         "unicode",
+	"unicode.Imperial_Aramaic":                    "unicode",
+	"unicode.In":                                  "unicode",
+	"unicode.Inherited":                           "unicode",
+	"unicode.Inscriptional_Pahlavi":               "unicode",
+	"unicode.Inscriptional_Parthian":              "unicode",
+	"unicode.Is":                                  "unicode",
+	"unicode.IsControl":                           "unicode",
+	"unicode.IsDigit":                             "unicode",
+	"unicode.IsGraphic":                           "unicode",
+	"unicode.IsLetter":                            "unicode",
+	"unicode.IsLower":                             "unicode",
+	"unicode.IsMark":                              "unicode",
+	"unicode.IsNumber":                            "unicode",
+	"unicode.IsOneOf":                             "unicode",
+	"unicode.IsPrint":                             "unicode",
+	"unicode.IsPunct":                             "unicode",
+	"unicode.IsSpace":                             "unicode",
+	"unicode.IsSymbol":                            "unicode",
+	"unicode.IsTitle":                             "unicode",
+	"unicode.IsUpper":                             "unicode",
+	"unicode.Javanese":                            "unicode",
+	"unicode.Join_Control":                        "unicode",
+	"unicode.Kaithi":                              "unicode",
+	"unicode.Kannada":                             "unicode",
+	"unicode.Katakana":                            "unicode",
+	"unicode.Kayah_Li":                            "unicode",
+	"unicode.Kharoshthi":                          "unicode",
+	"unicode.Khmer":                               "unicode",
+	"unicode.L":                                   "unicode",
+	"unicode.Lao":                                 "unicode",
+	"unicode.Latin":                               "unicode",
+	"unicode.Lepcha":                              "unicode",
+	"unicode.Letter":                              "unicode",
+	"unicode.Limbu":                               "unicode",
+	"unicode.Linear_B":                            "unicode",
+	"unicode.Lisu":                                "unicode",
+	"unicode.Ll":                                  "unicode",
+	"unicode.Lm":                                  "unicode",
+	"unicode.Lo":                                  "unicode",
+	"unicode.Logical_Order_Exception":             "unicode",
+	"unicode.Lower":                               "unicode",
+	"unicode.LowerCase":                           "unicode",
+	"unicode.Lt":                                  "unicode",
+	"unicode.Lu":                                  "unicode",
+	"unicode.Lycian":                              "unicode",
+	"unicode.Lydian":                              "unicode",
+	"unicode.M":                                   "unicode",
+	"unicode.Malayalam":                           "unicode",
+	"unicode.Mandaic":                             "unicode",
+	"unicode.Mark":                                "unicode",
+	"unicode.MaxASCII":                            "unicode",
+	"unicode.MaxCase":                             "unicode",
+	"unicode.MaxLatin1":                           "unicode",
+	"unicode.MaxRune":                             "unicode",
+	"unicode.Mc":                                  "unicode",
+	"unicode.Me":                                  "unicode",
+	"unicode.Meetei_Mayek":                        "unicode",
+	"unicode.Meroitic_Cursive":                    "unicode",
+	"unicode.Meroitic_Hieroglyphs":                "unicode",
+	"unicode.Miao":                                "unicode",
+	"unicode.Mn":                                  "unicode",
+	"unicode.Mongolian":                           "unicode",
+	"unicode.Myanmar":                             "unicode",
+	"unicode.N":                                   "unicode",
+	"unicode.Nd":                                  "unicode",
+	"unicode.New_Tai_Lue":                         "unicode",
+	"unicode.Nko":                                 "unicode",
+	"unicode.Nl":                                  "unicode",
+	"unicode.No":                                  "unicode",
+	"unicode.Noncharacter_Code_Point":             "unicode",
+	"unicode.Number":                              "unicode",
+	"unicode.Ogham":                               "unicode",
+	"unicode.Ol_Chiki":                            "unicode",
+	"unicode.Old_Italic":                          "unicode",
+	"unicode.Old_Persian":                         "unicode",
+	"unicode.Old_South_Arabian":                   "unicode",
+	"unicode.Old_Turkic":                          "unicode",
+	"unicode.Oriya":                               "unicode",
+	"unicode.Osmanya":                             "unicode",
+	"unicode.Other":                               "unicode",
+	"unicode.Other_Alphabetic":                    "unicode",
+	"unicode.Other_Default_Ignorable_Code_Point":  "unicode",
+	"unicode.Other_Grapheme_Extend":               "unicode",
+	"unicode.Other_ID_Continue":                   "unicode",
+	"unicode.Other_ID_Start":                      "unicode",
+	"unicode.Other_Lowercase":                     "unicode",
+	"unicode.Other_Math":                          "unicode",
+	"unicode.Other_Uppercase":                     "unicode",
+	"unicode.P":                                   "unicode",
+	"unicode.Pattern_Syntax":                      "unicode",
+	"unicode.Pattern_White_Space":                 "unicode",
+	"unicode.Pc":                                  "unicode",
+	"unicode.Pd":                                  "unicode",
+	"unicode.Pe":                                  "unicode",
+	"unicode.Pf":                                  "unicode",
+	"unicode.Phags_Pa":                            "unicode",
+	"unicode.Phoenician":                          "unicode",
+	"unicode.Pi":                                  "unicode",
+	"unicode.Po":                                  "unicode",
+	"unicode.PrintRanges":                         "unicode",
+	"unicode.Properties":                          "unicode",
+	"unicode.Ps":                                  "unicode",
+	"unicode.Punct":                               "unicode",
+	"unicode.Quotation_Mark":                      "unicode",
+	"unicode.Radical":                             "unicode",
+	"unicode.Range16":                             "unicode",
+	"unicode.Range32":                             "unicode",
+	"unicode.RangeTable":                          "unicode",
+	"unicode.Rejang":                              "unicode",
+	"unicode.ReplacementChar":                     "unicode",
+	"unicode.Runic":                               "unicode",
+	"unicode.S":                                   "unicode",
+	"unicode.STerm":                               "unicode",
+	"unicode.Samaritan":                           "unicode",
+	"unicode.Saurashtra":                          "unicode",
+	"unicode.Sc":                                  "unicode",
+	"unicode.Scripts":                             "unicode",
+	"unicode.Sharada":                             "unicode",
+	"unicode.Shavian":                             "unicode",
+	"unicode.SimpleFold":                          "unicode",
+	"unicode.Sinhala":                             "unicode",
+	"unicode.Sk":                                  "unicode",
+	"unicode.Sm":                                  "unicode",
+	"unicode.So":                                  "unicode",
+	"unicode.Soft_Dotted":                         "unicode",
+	"unicode.Sora_Sompeng":                        "unicode",
+	"unicode.Space":                               "unicode",
+	"unicode.SpecialCase":                         "unicode",
+	"unicode.Sundanese":                           "unicode",
+	"unicode.Syloti_Nagri":                        "unicode",
+	"unicode.Symbol":                              "unicode",
+	"unicode.Syriac":                              "unicode",
+	"unicode.Tagalog":                             "unicode",
+	"unicode.Tagbanwa":                            "unicode",
+	"unicode.Tai_Le":                              "unicode",
+	"unicode.Tai_Tham":                            "unicode",
+	"unicode.Tai_Viet":                            "unicode",
+	"unicode.Takri":                               "unicode",
+	"unicode.Tamil":                               "unicode",
+	"unicode.Telugu":                              "unicode",
+	"unicode.Terminal_Punctuation":                "unicode",
+	"unicode.Thaana":                              "unicode",
+	"unicode.Thai":                                "unicode",
+	"unicode.Tibetan":                             "unicode",
+	"unicode.Tifinagh":                            "unicode",
+	"unicode.Title":                               "unicode",
+	"unicode.TitleCase":                           "unicode",
+	"unicode.To":                                  "unicode",
+	"unicode.ToLower":                             "unicode",
+	"unicode.ToTitle":                             "unicode",
+	"unicode.ToUpper":                             "unicode",
+	"unicode.TurkishCase":                         "unicode",
+	"unicode.Ugaritic":                            "unicode",
+	"unicode.Unified_Ideograph":                   "unicode",
+	"unicode.Upper":                               "unicode",
+	"unicode.UpperCase":                           "unicode",
+	"unicode.UpperLower":                          "unicode",
+	"unicode.Vai":                                 "unicode",
+	"unicode.Variation_Selector":                  "unicode",
+	"unicode.Version":                             "unicode",
+	"unicode.White_Space":                         "unicode",
+	"unicode.Yi":                                  "unicode",
+	"unicode.Z":                                   "unicode",
+	"unicode.Zl":                                  "unicode",
+	"unicode.Zp":                                  "unicode",
+	"unicode.Zs":                                  "unicode",
+	"url.Error":                                   "net/url",
+	"url.EscapeError":                             "net/url",
+	"url.Parse":                                   "net/url",
+	"url.ParseQuery":                              "net/url",
+	"url.ParseRequestURI":                         "net/url",
+	"url.QueryEscape":                             "net/url",
+	"url.QueryUnescape":                           "net/url",
+	"url.URL":                                     "net/url",
+	"url.User":                                    "net/url",
+	"url.UserPassword":                            "net/url",
+	"url.Userinfo":                                "net/url",
+	"url.Values":                                  "net/url",
+	"user.Current":                                "os/user",
+	"user.Lookup":                                 "os/user",
+	"user.LookupId":                               "os/user",
+	"user.UnknownUserError":                       "os/user",
+	"user.UnknownUserIdError":                     "os/user",
+	"user.User":                                   "os/user",
+	"utf16.Decode":                                "unicode/utf16",
+	"utf16.DecodeRune":                            "unicode/utf16",
+	"utf16.Encode":                                "unicode/utf16",
+	"utf16.EncodeRune":                            "unicode/utf16",
+	"utf16.IsSurrogate":                           "unicode/utf16",
+	"utf8.DecodeLastRune":                         "unicode/utf8",
+	"utf8.DecodeLastRuneInString":                 "unicode/utf8",
+	"utf8.DecodeRune":                             "unicode/utf8",
+	"utf8.DecodeRuneInString":                     "unicode/utf8",
+	"utf8.EncodeRune":                             "unicode/utf8",
+	"utf8.FullRune":                               "unicode/utf8",
+	"utf8.FullRuneInString":                       "unicode/utf8",
+	"utf8.MaxRune":                                "unicode/utf8",
+	"utf8.RuneCount":                              "unicode/utf8",
+	"utf8.RuneCountInString":                      "unicode/utf8",
+	"utf8.RuneError":                              "unicode/utf8",
+	"utf8.RuneLen":                                "unicode/utf8",
+	"utf8.RuneSelf":                               "unicode/utf8",
+	"utf8.RuneStart":                              "unicode/utf8",
+	"utf8.UTFMax":                                 "unicode/utf8",
+	"utf8.Valid":                                  "unicode/utf8",
+	"utf8.ValidRune":                              "unicode/utf8",
+	"utf8.ValidString":                            "unicode/utf8",
+	"x509.CANotAuthorizedForThisName":             "crypto/x509",
+	"x509.CertPool":                               "crypto/x509",
+	"x509.Certificate":                            "crypto/x509",
+	"x509.CertificateInvalidError":                "crypto/x509",
+	"x509.ConstraintViolationError":               "crypto/x509",
+	"x509.CreateCertificate":                      "crypto/x509",
+	"x509.DSA":                                    "crypto/x509",
+	"x509.DSAWithSHA1":                            "crypto/x509",
+	"x509.DSAWithSHA256":                          "crypto/x509",
+	"x509.DecryptPEMBlock":                        "crypto/x509",
+	"x509.ECDSA":                                  "crypto/x509",
+	"x509.ECDSAWithSHA1":                          "crypto/x509",
+	"x509.ECDSAWithSHA256":                        "crypto/x509",
+	"x509.ECDSAWithSHA384":                        "crypto/x509",
+	"x509.ECDSAWithSHA512":                        "crypto/x509",
+	"x509.EncryptPEMBlock":                        "crypto/x509",
+	"x509.ErrUnsupportedAlgorithm":                "crypto/x509",
+	"x509.Expired":                                "crypto/x509",
+	"x509.ExtKeyUsage":                            "crypto/x509",
+	"x509.ExtKeyUsageAny":                         "crypto/x509",
+	"x509.ExtKeyUsageClientAuth":                  "crypto/x509",
+	"x509.ExtKeyUsageCodeSigning":                 "crypto/x509",
+	"x509.ExtKeyUsageEmailProtection":             "crypto/x509",
+	"x509.ExtKeyUsageIPSECEndSystem":              "crypto/x509",
+	"x509.ExtKeyUsageIPSECTunnel":                 "crypto/x509",
+	"x509.ExtKeyUsageIPSECUser":                   "crypto/x509",
+	"x509.ExtKeyUsageMicrosoftServerGatedCrypto":  "crypto/x509",
+	"x509.ExtKeyUsageNetscapeServerGatedCrypto":   "crypto/x509",
+	"x509.ExtKeyUsageOCSPSigning":                 "crypto/x509",
+	"x509.ExtKeyUsageServerAuth":                  "crypto/x509",
+	"x509.ExtKeyUsageTimeStamping":                "crypto/x509",
+	"x509.HostnameError":                          "crypto/x509",
+	"x509.IncompatibleUsage":                      "crypto/x509",
+	"x509.IncorrectPasswordError":                 "crypto/x509",
+	"x509.InvalidReason":                          "crypto/x509",
+	"x509.IsEncryptedPEMBlock":                    "crypto/x509",
+	"x509.KeyUsage":                               "crypto/x509",
+	"x509.KeyUsageCRLSign":                        "crypto/x509",
+	"x509.KeyUsageCertSign":                       "crypto/x509",
+	"x509.KeyUsageContentCommitment":              "crypto/x509",
+	"x509.KeyUsageDataEncipherment":               "crypto/x509",
+	"x509.KeyUsageDecipherOnly":                   "crypto/x509",
+	"x509.KeyUsageDigitalSignature":               "crypto/x509",
+	"x509.KeyUsageEncipherOnly":                   "crypto/x509",
+	"x509.KeyUsageKeyAgreement":                   "crypto/x509",
+	"x509.KeyUsageKeyEncipherment":                "crypto/x509",
+	"x509.MD2WithRSA":                             "crypto/x509",
+	"x509.MD5WithRSA":                             "crypto/x509",
+	"x509.MarshalECPrivateKey":                    "crypto/x509",
+	"x509.MarshalPKCS1PrivateKey":                 "crypto/x509",
+	"x509.MarshalPKIXPublicKey":                   "crypto/x509",
+	"x509.NewCertPool":                            "crypto/x509",
+	"x509.NotAuthorizedToSign":                    "crypto/x509",
+	"x509.PEMCipher":                              "crypto/x509",
+	"x509.PEMCipher3DES":                          "crypto/x509",
+	"x509.PEMCipherAES128":                        "crypto/x509",
+	"x509.PEMCipherAES192":                        "crypto/x509",
+	"x509.PEMCipherAES256":                        "crypto/x509",
+	"x509.PEMCipherDES":                           "crypto/x509",
+	"x509.ParseCRL":                               "crypto/x509",
+	"x509.ParseCertificate":                       "crypto/x509",
+	"x509.ParseCertificates":                      "crypto/x509",
+	"x509.ParseDERCRL":                            "crypto/x509",
+	"x509.ParseECPrivateKey":                      "crypto/x509",
+	"x509.ParsePKCS1PrivateKey":                   "crypto/x509",
+	"x509.ParsePKCS8PrivateKey":                   "crypto/x509",
+	"x509.ParsePKIXPublicKey":                     "crypto/x509",
+	"x509.PublicKeyAlgorithm":                     "crypto/x509",
+	"x509.RSA":                                    "crypto/x509",
+	"x509.SHA1WithRSA":                            "crypto/x509",
+	"x509.SHA256WithRSA":                          "crypto/x509",
+	"x509.SHA384WithRSA":                          "crypto/x509",
+	"x509.SHA512WithRSA":                          "crypto/x509",
+	"x509.SignatureAlgorithm":                     "crypto/x509",
+	"x509.SystemRootsError":                       "crypto/x509",
+	"x509.TooManyIntermediates":                   "crypto/x509",
+	"x509.UnhandledCriticalExtension":             "crypto/x509",
+	"x509.UnknownAuthorityError":                  "crypto/x509",
+	"x509.UnknownPublicKeyAlgorithm":              "crypto/x509",
+	"x509.UnknownSignatureAlgorithm":              "crypto/x509",
+	"x509.VerifyOptions":                          "crypto/x509",
+	"xml.Attr":                                    "encoding/xml",
+	"xml.CharData":                                "encoding/xml",
+	"xml.Comment":                                 "encoding/xml",
+	"xml.CopyToken":                               "encoding/xml",
+	"xml.Decoder":                                 "encoding/xml",
+	"xml.Directive":                               "encoding/xml",
+	"xml.Encoder":                                 "encoding/xml",
+	"xml.EndElement":                              "encoding/xml",
+	"xml.Escape":                                  "encoding/xml",
+	"xml.EscapeText":                              "encoding/xml",
+	"xml.HTMLAutoClose":                           "encoding/xml",
+	"xml.HTMLEntity":                              "encoding/xml",
+	"xml.Header":                                  "encoding/xml",
+	"xml.Marshal":                                 "encoding/xml",
+	"xml.MarshalIndent":                           "encoding/xml",
+	"xml.Marshaler":                               "encoding/xml",
+	"xml.MarshalerAttr":                           "encoding/xml",
+	"xml.Name":                                    "encoding/xml",
+	"xml.NewDecoder":                              "encoding/xml",
+	"xml.NewEncoder":                              "encoding/xml",
+	"xml.ProcInst":                                "encoding/xml",
+	"xml.StartElement":                            "encoding/xml",
+	"xml.SyntaxError":                             "encoding/xml",
+	"xml.TagPathError":                            "encoding/xml",
+	"xml.Token":                                   "encoding/xml",
+	"xml.Unmarshal":                               "encoding/xml",
+	"xml.UnmarshalError":                          "encoding/xml",
+	"xml.Unmarshaler":                             "encoding/xml",
+	"xml.UnmarshalerAttr":                         "encoding/xml",
+	"xml.UnsupportedTypeError":                    "encoding/xml",
+	"zip.Compressor":                              "archive/zip",
+	"zip.Decompressor":                            "archive/zip",
+	"zip.Deflate":                                 "archive/zip",
+	"zip.ErrAlgorithm":                            "archive/zip",
+	"zip.ErrChecksum":                             "archive/zip",
+	"zip.ErrFormat":                               "archive/zip",
+	"zip.File":                                    "archive/zip",
+	"zip.FileHeader":                              "archive/zip",
+	"zip.FileInfoHeader":                          "archive/zip",
+	"zip.NewReader":                               "archive/zip",
+	"zip.NewWriter":                               "archive/zip",
+	"zip.OpenReader":                              "archive/zip",
+	"zip.ReadCloser":                              "archive/zip",
+	"zip.Reader":                                  "archive/zip",
+	"zip.RegisterCompressor":                      "archive/zip",
+	"zip.RegisterDecompressor":                    "archive/zip",
+	"zip.Store":                                   "archive/zip",
+	"zip.Writer":                                  "archive/zip",
+	"zlib.BestCompression":                        "compress/zlib",
+	"zlib.BestSpeed":                              "compress/zlib",
+	"zlib.DefaultCompression":                     "compress/zlib",
+	"zlib.ErrChecksum":                            "compress/zlib",
+	"zlib.ErrDictionary":                          "compress/zlib",
+	"zlib.ErrHeader":                              "compress/zlib",
+	"zlib.NewReader":                              "compress/zlib",
+	"zlib.NewReaderDict":                          "compress/zlib",
+	"zlib.NewWriter":                              "compress/zlib",
+	"zlib.NewWriterLevel":                         "compress/zlib",
+	"zlib.NewWriterLevelDict":                     "compress/zlib",
+	"zlib.NoCompression":                          "compress/zlib",
+	"zlib.Writer":                                 "compress/zlib",
+}
diff --git a/oracle/TODO b/oracle/TODO
new file mode 100644
index 0000000..8fbf5e8
--- /dev/null
+++ b/oracle/TODO
@@ -0,0 +1,83 @@
+
+
+ORACLE TODO
+===========
+
+General
+=======
+
+Save unsaved editor buffers into an archive and provide that to the
+tools, which should act as if they were saved.
+
+Include complete pos/end information Serial output.
+  But beware that sometimes a single token (e.g. +) is more helpful
+  than the pos/end of the containing expression (e.g. x \n + \n y).
+
+Specific queries
+================
+
+callers, callees
+
+  Use a type-based (e.g. RTA) callgraph when a callers/callees query is
+  outside the analysis scope.
+
+implements
+
+   Make it require that the selection is a type, and show only the
+   implements relation as it applies to that type.
+
+definition, referrers
+
+  definition: Make it work with qualified identifiers (SelectorExpr) too.
+
+  references: Make it work on things that are implicit idents, like
+  import specs, perhaps?
+
+what
+
+  Report def/ref info if available.
+  Editors could use it to highlight all idents of the same local var.
+
+  More tests.
+
+pointsto
+
+  When invoked on a function Ident, we get an error.
+
+  When invoked on a named return parameter, we get an error.
+
+describe
+
+  When invoked on a var, we want to see the type and its methods.
+
+  Split "show type" and "describe syntax" into separate commands?
+
+peers
+
+  Permit querying from a makechan, for...range, or reflective op.
+
+  Report aliasing reflect.{Send,Recv,Close} and close() operations.
+
+New queries
+
+"updaters": show all statements that may update the selected lvalue
+  (local, global, field, etc).
+
+"creators": show all places where an object of type T is created
+  (&T{}, var t T, new(T), new(struct{array [3]T}), etc.
+  (Useful for datatypes whose zero value is not safe)
+
+
+Editor-specific
+===============
+
+Add support for "what" to .el; clean up.
+
+Emacs: use JSON to get the raw information from the oracle.  Don't
+ open an editor buffer for simpler queries, just jump to the result
+ and/or display it in the modeline.
+
+Emacs: go-root-and-paths depends on the current buffer, so be sure to
+   call it from within the source file, not the *go-oracle* buffer:
+   the user may have switched workspaces and the oracle should run in
+   the new one.
diff --git a/oracle/callees.go b/oracle/callees.go
new file mode 100644
index 0000000..56e45e1
--- /dev/null
+++ b/oracle/callees.go
@@ -0,0 +1,253 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package oracle
+
+import (
+	"fmt"
+	"go/ast"
+	"go/token"
+	"sort"
+
+	"golang.org/x/tools/go/loader"
+	"golang.org/x/tools/go/pointer"
+	"golang.org/x/tools/go/ssa"
+	"golang.org/x/tools/go/ssa/ssautil"
+	"golang.org/x/tools/go/types"
+	"golang.org/x/tools/oracle/serial"
+)
+
+// Callees reports the possible callees of the function call site
+// identified by the specified source location.
+func callees(q *Query) error {
+	lconf := loader.Config{Build: q.Build}
+
+	if err := setPTAScope(&lconf, q.Scope); err != nil {
+		return err
+	}
+
+	// Load/parse/type-check the program.
+	lprog, err := lconf.Load()
+	if err != nil {
+		return err
+	}
+	q.Fset = lprog.Fset
+
+	qpos, err := parseQueryPos(lprog, q.Pos, true) // needs exact pos
+	if err != nil {
+		return err
+	}
+
+	// Determine the enclosing call for the specified position.
+	var e *ast.CallExpr
+	for _, n := range qpos.path {
+		if e, _ = n.(*ast.CallExpr); e != nil {
+			break
+		}
+	}
+	if e == nil {
+		return fmt.Errorf("there is no function call here")
+	}
+	// TODO(adonovan): issue an error if the call is "too far
+	// away" from the current selection, as this most likely is
+	// not what the user intended.
+
+	// Reject type conversions.
+	if qpos.info.Types[e.Fun].IsType() {
+		return fmt.Errorf("this is a type conversion, not a function call")
+	}
+
+	// Deal with obviously static calls before constructing SSA form.
+	// Some static calls may yet require SSA construction,
+	// e.g.  f := func(){}; f().
+	switch funexpr := unparen(e.Fun).(type) {
+	case *ast.Ident:
+		switch obj := qpos.info.Uses[funexpr].(type) {
+		case *types.Builtin:
+			// Reject calls to built-ins.
+			return fmt.Errorf("this is a call to the built-in '%s' operator", obj.Name())
+		case *types.Func:
+			// This is a static function call
+			q.result = &calleesTypesResult{
+				site:   e,
+				callee: obj,
+			}
+			return nil
+		}
+	case *ast.SelectorExpr:
+		sel := qpos.info.Selections[funexpr]
+		if sel == nil {
+			// qualified identifier.
+			// May refer to top level function variable
+			// or to top level function.
+			callee := qpos.info.Uses[funexpr.Sel]
+			if obj, ok := callee.(*types.Func); ok {
+				q.result = &calleesTypesResult{
+					site:   e,
+					callee: obj,
+				}
+				return nil
+			}
+		} else if sel.Kind() == types.MethodVal {
+			recvtype := sel.Recv()
+			if !types.IsInterface(recvtype) {
+				// static method call
+				q.result = &calleesTypesResult{
+					site:   e,
+					callee: sel.Obj().(*types.Func),
+				}
+				return nil
+			}
+		}
+	}
+
+	prog := ssautil.CreateProgram(lprog, ssa.GlobalDebug)
+
+	ptaConfig, err := setupPTA(prog, lprog, q.PTALog, q.Reflection)
+	if err != nil {
+		return err
+	}
+
+	pkg := prog.Package(qpos.info.Pkg)
+	if pkg == nil {
+		return fmt.Errorf("no SSA package")
+	}
+
+	// Defer SSA construction till after errors are reported.
+	prog.BuildAll()
+
+	// Ascertain calling function and call site.
+	callerFn := ssa.EnclosingFunction(pkg, qpos.path)
+	if callerFn == nil {
+		return fmt.Errorf("no SSA function built for this location (dead code?)")
+	}
+
+	// Find the call site.
+	site, err := findCallSite(callerFn, e)
+	if err != nil {
+		return err
+	}
+
+	funcs, err := findCallees(ptaConfig, site)
+	if err != nil {
+		return err
+	}
+
+	q.result = &calleesSSAResult{
+		site:  site,
+		funcs: funcs,
+	}
+	return nil
+}
+
+func findCallSite(fn *ssa.Function, call *ast.CallExpr) (ssa.CallInstruction, error) {
+	instr, _ := fn.ValueForExpr(call)
+	callInstr, _ := instr.(ssa.CallInstruction)
+	if instr == nil {
+		return nil, fmt.Errorf("this call site is unreachable in this analysis")
+	}
+	return callInstr, nil
+}
+
+func findCallees(conf *pointer.Config, site ssa.CallInstruction) ([]*ssa.Function, error) {
+	// Avoid running the pointer analysis for static calls.
+	if callee := site.Common().StaticCallee(); callee != nil {
+		switch callee.String() {
+		case "runtime.SetFinalizer", "(reflect.Value).Call":
+			// The PTA treats calls to these intrinsics as dynamic.
+			// TODO(adonovan): avoid reliance on PTA internals.
+
+		default:
+			return []*ssa.Function{callee}, nil // singleton
+		}
+	}
+
+	// Dynamic call: use pointer analysis.
+	conf.BuildCallGraph = true
+	cg := ptrAnalysis(conf).CallGraph
+	cg.DeleteSyntheticNodes()
+
+	// Find all call edges from the site.
+	n := cg.Nodes[site.Parent()]
+	if n == nil {
+		return nil, fmt.Errorf("this call site is unreachable in this analysis")
+	}
+	calleesMap := make(map[*ssa.Function]bool)
+	for _, edge := range n.Out {
+		if edge.Site == site {
+			calleesMap[edge.Callee.Func] = true
+		}
+	}
+
+	// De-duplicate and sort.
+	funcs := make([]*ssa.Function, 0, len(calleesMap))
+	for f := range calleesMap {
+		funcs = append(funcs, f)
+	}
+	sort.Sort(byFuncPos(funcs))
+	return funcs, nil
+}
+
+type calleesSSAResult struct {
+	site  ssa.CallInstruction
+	funcs []*ssa.Function
+}
+
+type calleesTypesResult struct {
+	site   *ast.CallExpr
+	callee *types.Func
+}
+
+func (r *calleesSSAResult) display(printf printfFunc) {
+	if len(r.funcs) == 0 {
+		// dynamic call on a provably nil func/interface
+		printf(r.site, "%s on nil value", r.site.Common().Description())
+	} else {
+		printf(r.site, "this %s dispatches to:", r.site.Common().Description())
+		for _, callee := range r.funcs {
+			printf(callee, "\t%s", callee)
+		}
+	}
+}
+
+func (r *calleesSSAResult) toSerial(res *serial.Result, fset *token.FileSet) {
+	j := &serial.Callees{
+		Pos:  fset.Position(r.site.Pos()).String(),
+		Desc: r.site.Common().Description(),
+	}
+	for _, callee := range r.funcs {
+		j.Callees = append(j.Callees, &serial.CalleesItem{
+			Name: callee.String(),
+			Pos:  fset.Position(callee.Pos()).String(),
+		})
+	}
+	res.Callees = j
+}
+
+func (r *calleesTypesResult) display(printf printfFunc) {
+	printf(r.site, "this static function call dispatches to:")
+	printf(r.callee, "\t%s", r.callee.FullName())
+}
+
+func (r *calleesTypesResult) toSerial(res *serial.Result, fset *token.FileSet) {
+	j := &serial.Callees{
+		Pos:  fset.Position(r.site.Pos()).String(),
+		Desc: "static function call",
+	}
+	j.Callees = []*serial.CalleesItem{
+		&serial.CalleesItem{
+			Name: r.callee.FullName(),
+			Pos:  fset.Position(r.callee.Pos()).String(),
+		},
+	}
+	res.Callees = j
+}
+
+// NB: byFuncPos is not deterministic across packages since it depends on load order.
+// Use lessPos if the tests need it.
+type byFuncPos []*ssa.Function
+
+func (a byFuncPos) Len() int           { return len(a) }
+func (a byFuncPos) Less(i, j int) bool { return a[i].Pos() < a[j].Pos() }
+func (a byFuncPos) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
diff --git a/oracle/callers.go b/oracle/callers.go
new file mode 100644
index 0000000..159a403
--- /dev/null
+++ b/oracle/callers.go
@@ -0,0 +1,115 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package oracle
+
+import (
+	"fmt"
+	"go/token"
+
+	"golang.org/x/tools/go/callgraph"
+	"golang.org/x/tools/go/loader"
+	"golang.org/x/tools/go/ssa"
+	"golang.org/x/tools/go/ssa/ssautil"
+	"golang.org/x/tools/oracle/serial"
+)
+
+// Callers reports the possible callers of the function
+// immediately enclosing the specified source location.
+//
+func callers(q *Query) error {
+	lconf := loader.Config{Build: q.Build}
+
+	if err := setPTAScope(&lconf, q.Scope); err != nil {
+		return err
+	}
+
+	// Load/parse/type-check the program.
+	lprog, err := lconf.Load()
+	if err != nil {
+		return err
+	}
+	q.Fset = lprog.Fset
+
+	qpos, err := parseQueryPos(lprog, q.Pos, false)
+	if err != nil {
+		return err
+	}
+
+	prog := ssautil.CreateProgram(lprog, 0)
+
+	ptaConfig, err := setupPTA(prog, lprog, q.PTALog, q.Reflection)
+	if err != nil {
+		return err
+	}
+
+	pkg := prog.Package(qpos.info.Pkg)
+	if pkg == nil {
+		return fmt.Errorf("no SSA package")
+	}
+	if !ssa.HasEnclosingFunction(pkg, qpos.path) {
+		return fmt.Errorf("this position is not inside a function")
+	}
+
+	// Defer SSA construction till after errors are reported.
+	prog.BuildAll()
+
+	target := ssa.EnclosingFunction(pkg, qpos.path)
+	if target == nil {
+		return fmt.Errorf("no SSA function built for this location (dead code?)")
+	}
+
+	// TODO(adonovan): opt: if function is never address-taken, skip
+	// the pointer analysis.  Just look for direct calls.  This can
+	// be done in a single pass over the SSA.
+
+	// Run the pointer analysis, recording each
+	// call found to originate from target.
+	ptaConfig.BuildCallGraph = true
+	cg := ptrAnalysis(ptaConfig).CallGraph
+	cg.DeleteSyntheticNodes()
+	edges := cg.CreateNode(target).In
+	// TODO(adonovan): sort + dedup calls to ensure test determinism.
+
+	q.result = &callersResult{
+		target:    target,
+		callgraph: cg,
+		edges:     edges,
+	}
+	return nil
+}
+
+type callersResult struct {
+	target    *ssa.Function
+	callgraph *callgraph.Graph
+	edges     []*callgraph.Edge
+}
+
+func (r *callersResult) display(printf printfFunc) {
+	root := r.callgraph.Root
+	if r.edges == nil {
+		printf(r.target, "%s is not reachable in this program.", r.target)
+	} else {
+		printf(r.target, "%s is called from these %d sites:", r.target, len(r.edges))
+		for _, edge := range r.edges {
+			if edge.Caller == root {
+				printf(r.target, "the root of the call graph")
+			} else {
+				printf(edge, "\t%s from %s", edge.Description(), edge.Caller.Func)
+			}
+		}
+	}
+}
+
+func (r *callersResult) toSerial(res *serial.Result, fset *token.FileSet) {
+	var callers []serial.Caller
+	for _, edge := range r.edges {
+		callers = append(callers, serial.Caller{
+			Caller: edge.Caller.Func.String(),
+			Pos:    fset.Position(edge.Pos()).String(),
+			Desc:   edge.Description(),
+		})
+	}
+	res.Callers = callers
+}
diff --git a/oracle/callstack.go b/oracle/callstack.go
new file mode 100644
index 0000000..6f04b60
--- /dev/null
+++ b/oracle/callstack.go
@@ -0,0 +1,126 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package oracle
+
+import (
+	"fmt"
+	"go/token"
+
+	"golang.org/x/tools/go/callgraph"
+	"golang.org/x/tools/go/loader"
+	"golang.org/x/tools/go/ssa"
+	"golang.org/x/tools/go/ssa/ssautil"
+	"golang.org/x/tools/oracle/serial"
+)
+
+// Callstack displays an arbitrary path from a root of the callgraph
+// to the function at the current position.
+//
+// The information may be misleading in a context-insensitive
+// analysis. e.g. the call path X->Y->Z might be infeasible if Y never
+// calls Z when it is called from X.  TODO(adonovan): think about UI.
+//
+// TODO(adonovan): permit user to specify a starting point other than
+// the analysis root.
+//
+func callstack(q *Query) error {
+	fset := token.NewFileSet()
+	lconf := loader.Config{Fset: fset, Build: q.Build}
+
+	if err := setPTAScope(&lconf, q.Scope); err != nil {
+		return err
+	}
+
+	// Load/parse/type-check the program.
+	lprog, err := lconf.Load()
+	if err != nil {
+		return err
+	}
+
+	qpos, err := parseQueryPos(lprog, q.Pos, false)
+	if err != nil {
+		return err
+	}
+
+	prog := ssautil.CreateProgram(lprog, 0)
+
+	ptaConfig, err := setupPTA(prog, lprog, q.PTALog, q.Reflection)
+	if err != nil {
+		return err
+	}
+
+	pkg := prog.Package(qpos.info.Pkg)
+	if pkg == nil {
+		return fmt.Errorf("no SSA package")
+	}
+
+	if !ssa.HasEnclosingFunction(pkg, qpos.path) {
+		return fmt.Errorf("this position is not inside a function")
+	}
+
+	// Defer SSA construction till after errors are reported.
+	prog.BuildAll()
+
+	target := ssa.EnclosingFunction(pkg, qpos.path)
+	if target == nil {
+		return fmt.Errorf("no SSA function built for this location (dead code?)")
+	}
+
+	// Run the pointer analysis and build the complete call graph.
+	ptaConfig.BuildCallGraph = true
+	cg := ptrAnalysis(ptaConfig).CallGraph
+	cg.DeleteSyntheticNodes()
+
+	// Search for an arbitrary path from a root to the target function.
+	isEnd := func(n *callgraph.Node) bool { return n.Func == target }
+	callpath := callgraph.PathSearch(cg.Root, isEnd)
+	if callpath != nil {
+		callpath = callpath[1:] // remove synthetic edge from <root>
+	}
+
+	q.Fset = fset
+	q.result = &callstackResult{
+		qpos:     qpos,
+		target:   target,
+		callpath: callpath,
+	}
+	return nil
+}
+
+type callstackResult struct {
+	qpos     *queryPos
+	target   *ssa.Function
+	callpath []*callgraph.Edge
+}
+
+func (r *callstackResult) display(printf printfFunc) {
+	if r.callpath != nil {
+		printf(r.qpos, "Found a call path from root to %s", r.target)
+		printf(r.target, "%s", r.target)
+		for i := len(r.callpath) - 1; i >= 0; i-- {
+			edge := r.callpath[i]
+			printf(edge, "%s from %s", edge.Description(), edge.Caller.Func)
+		}
+	} else {
+		printf(r.target, "%s is unreachable in this analysis scope", r.target)
+	}
+}
+
+func (r *callstackResult) toSerial(res *serial.Result, fset *token.FileSet) {
+	var callers []serial.Caller
+	for i := len(r.callpath) - 1; i >= 0; i-- { // (innermost first)
+		edge := r.callpath[i]
+		callers = append(callers, serial.Caller{
+			Pos:    fset.Position(edge.Pos()).String(),
+			Caller: edge.Caller.Func.String(),
+			Desc:   edge.Description(),
+		})
+	}
+	res.Callstack = &serial.CallStack{
+		Pos:     fset.Position(r.target.Pos()).String(),
+		Target:  r.target.String(),
+		Callers: callers,
+	}
+}
diff --git a/oracle/definition.go b/oracle/definition.go
new file mode 100644
index 0000000..a0340c6
--- /dev/null
+++ b/oracle/definition.go
@@ -0,0 +1,76 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package oracle
+
+import (
+	"fmt"
+	"go/ast"
+	"go/token"
+
+	"golang.org/x/tools/go/loader"
+	"golang.org/x/tools/go/types"
+	"golang.org/x/tools/oracle/serial"
+)
+
+// definition reports the location of the definition of an identifier.
+//
+// TODO(adonovan): opt: for intra-file references, the parser's
+// resolution might be enough; we should start with that.
+//
+func definition(q *Query) error {
+	lconf := loader.Config{Build: q.Build}
+	allowErrors(&lconf)
+
+	if err := importQueryPackage(q.Pos, &lconf); err != nil {
+		return err
+	}
+
+	// Load/parse/type-check the program.
+	lprog, err := lconf.Load()
+	if err != nil {
+		return err
+	}
+	q.Fset = lprog.Fset
+
+	qpos, err := parseQueryPos(lprog, q.Pos, false)
+	if err != nil {
+		return err
+	}
+
+	id, _ := qpos.path[0].(*ast.Ident)
+	if id == nil {
+		return fmt.Errorf("no identifier here")
+	}
+
+	obj := qpos.info.ObjectOf(id)
+	if obj == nil {
+		// Happens for y in "switch y := x.(type)",
+		// and the package declaration,
+		// but I think that's all.
+		return fmt.Errorf("no object for identifier")
+	}
+
+	q.result = &definitionResult{qpos, obj}
+	return nil
+}
+
+type definitionResult struct {
+	qpos *queryPos
+	obj  types.Object // object it denotes
+}
+
+func (r *definitionResult) display(printf printfFunc) {
+	printf(r.obj, "defined here as %s", r.qpos.objectString(r.obj))
+}
+
+func (r *definitionResult) toSerial(res *serial.Result, fset *token.FileSet) {
+	definition := &serial.Definition{
+		Desc: r.obj.String(),
+	}
+	if pos := r.obj.Pos(); pos != token.NoPos { // Package objects have no Pos()
+		definition.ObjPos = fset.Position(pos).String()
+	}
+	res.Definition = definition
+}
diff --git a/oracle/describe.go b/oracle/describe.go
new file mode 100644
index 0000000..ea1c5ec
--- /dev/null
+++ b/oracle/describe.go
@@ -0,0 +1,763 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package oracle
+
+import (
+	"bytes"
+	"fmt"
+	"go/ast"
+	"go/token"
+	"log"
+	"os"
+	"strings"
+
+	"golang.org/x/tools/go/ast/astutil"
+	"golang.org/x/tools/go/exact"
+	"golang.org/x/tools/go/loader"
+	"golang.org/x/tools/go/types"
+	"golang.org/x/tools/go/types/typeutil"
+	"golang.org/x/tools/oracle/serial"
+)
+
+// describe describes the syntax node denoted by the query position,
+// including:
+// - its syntactic category
+// - the definition of its referent (for identifiers) [now redundant]
+// - its type and method set (for an expression or type expression)
+//
+func describe(q *Query) error {
+	lconf := loader.Config{Build: q.Build}
+	allowErrors(&lconf)
+
+	if err := importQueryPackage(q.Pos, &lconf); err != nil {
+		return err
+	}
+
+	// Load/parse/type-check the program.
+	lprog, err := lconf.Load()
+	if err != nil {
+		return err
+	}
+	q.Fset = lprog.Fset
+
+	qpos, err := parseQueryPos(lprog, q.Pos, true) // (need exact pos)
+	if err != nil {
+		return err
+	}
+
+	if false { // debugging
+		fprintf(os.Stderr, lprog.Fset, qpos.path[0], "you selected: %s %s",
+			astutil.NodeDescription(qpos.path[0]), pathToString(qpos.path))
+	}
+
+	path, action := findInterestingNode(qpos.info, qpos.path)
+	switch action {
+	case actionExpr:
+		q.result, err = describeValue(qpos, path)
+
+	case actionType:
+		q.result, err = describeType(qpos, path)
+
+	case actionPackage:
+		q.result, err = describePackage(qpos, path)
+
+	case actionStmt:
+		q.result, err = describeStmt(qpos, path)
+
+	case actionUnknown:
+		q.result = &describeUnknownResult{path[0]}
+
+	default:
+		panic(action) // unreachable
+	}
+	return err
+}
+
+type describeUnknownResult struct {
+	node ast.Node
+}
+
+func (r *describeUnknownResult) display(printf printfFunc) {
+	// Nothing much to say about misc syntax.
+	printf(r.node, "%s", astutil.NodeDescription(r.node))
+}
+
+func (r *describeUnknownResult) toSerial(res *serial.Result, fset *token.FileSet) {
+	res.Describe = &serial.Describe{
+		Desc: astutil.NodeDescription(r.node),
+		Pos:  fset.Position(r.node.Pos()).String(),
+	}
+}
+
+type action int
+
+const (
+	actionUnknown action = iota // None of the below
+	actionExpr                  // FuncDecl, true Expr or Ident(types.{Const,Var})
+	actionType                  // type Expr or Ident(types.TypeName).
+	actionStmt                  // Stmt or Ident(types.Label)
+	actionPackage               // Ident(types.Package) or ImportSpec
+)
+
+// findInterestingNode classifies the syntax node denoted by path as one of:
+//    - an expression, part of an expression or a reference to a constant
+//      or variable;
+//    - a type, part of a type, or a reference to a named type;
+//    - a statement, part of a statement, or a label referring to a statement;
+//    - part of a package declaration or import spec.
+//    - none of the above.
+// and returns the most "interesting" associated node, which may be
+// the same node, an ancestor or a descendent.
+//
+func findInterestingNode(pkginfo *loader.PackageInfo, path []ast.Node) ([]ast.Node, action) {
+	// TODO(adonovan): integrate with go/types/stdlib_test.go and
+	// apply this to every AST node we can find to make sure it
+	// doesn't crash.
+
+	// TODO(adonovan): audit for ParenExpr safety, esp. since we
+	// traverse up and down.
+
+	// TODO(adonovan): if the users selects the "." in
+	// "fmt.Fprintf()", they'll get an ambiguous selection error;
+	// we won't even reach here.  Can we do better?
+
+	// TODO(adonovan): describing a field within 'type T struct {...}'
+	// describes the (anonymous) struct type and concludes "no methods".
+	// We should ascend to the enclosing type decl, if any.
+
+	for len(path) > 0 {
+		switch n := path[0].(type) {
+		case *ast.GenDecl:
+			if len(n.Specs) == 1 {
+				// Descend to sole {Import,Type,Value}Spec child.
+				path = append([]ast.Node{n.Specs[0]}, path...)
+				continue
+			}
+			return path, actionUnknown // uninteresting
+
+		case *ast.FuncDecl:
+			// Descend to function name.
+			path = append([]ast.Node{n.Name}, path...)
+			continue
+
+		case *ast.ImportSpec:
+			return path, actionPackage
+
+		case *ast.ValueSpec:
+			if len(n.Names) == 1 {
+				// Descend to sole Ident child.
+				path = append([]ast.Node{n.Names[0]}, path...)
+				continue
+			}
+			return path, actionUnknown // uninteresting
+
+		case *ast.TypeSpec:
+			// Descend to type name.
+			path = append([]ast.Node{n.Name}, path...)
+			continue
+
+		case ast.Stmt:
+			return path, actionStmt
+
+		case *ast.ArrayType,
+			*ast.StructType,
+			*ast.FuncType,
+			*ast.InterfaceType,
+			*ast.MapType,
+			*ast.ChanType:
+			return path, actionType
+
+		case *ast.Comment, *ast.CommentGroup, *ast.File, *ast.KeyValueExpr, *ast.CommClause:
+			return path, actionUnknown // uninteresting
+
+		case *ast.Ellipsis:
+			// Continue to enclosing node.
+			// e.g. [...]T in ArrayType
+			//      f(x...) in CallExpr
+			//      f(x...T) in FuncType
+
+		case *ast.Field:
+			// TODO(adonovan): this needs more thought,
+			// since fields can be so many things.
+			if len(n.Names) == 1 {
+				// Descend to sole Ident child.
+				path = append([]ast.Node{n.Names[0]}, path...)
+				continue
+			}
+			// Zero names (e.g. anon field in struct)
+			// or multiple field or param names:
+			// continue to enclosing field list.
+
+		case *ast.FieldList:
+			// Continue to enclosing node:
+			// {Struct,Func,Interface}Type or FuncDecl.
+
+		case *ast.BasicLit:
+			if _, ok := path[1].(*ast.ImportSpec); ok {
+				return path[1:], actionPackage
+			}
+			return path, actionExpr
+
+		case *ast.SelectorExpr:
+			// TODO(adonovan): use Selections info directly.
+			if pkginfo.Uses[n.Sel] == nil {
+				// TODO(adonovan): is this reachable?
+				return path, actionUnknown
+			}
+			// Descend to .Sel child.
+			path = append([]ast.Node{n.Sel}, path...)
+			continue
+
+		case *ast.Ident:
+			switch pkginfo.ObjectOf(n).(type) {
+			case *types.PkgName:
+				return path, actionPackage
+
+			case *types.Const:
+				return path, actionExpr
+
+			case *types.Label:
+				return path, actionStmt
+
+			case *types.TypeName:
+				return path, actionType
+
+			case *types.Var:
+				// For x in 'struct {x T}', return struct type, for now.
+				if _, ok := path[1].(*ast.Field); ok {
+					_ = path[2].(*ast.FieldList) // assertion
+					if _, ok := path[3].(*ast.StructType); ok {
+						return path[3:], actionType
+					}
+				}
+				return path, actionExpr
+
+			case *types.Func:
+				return path, actionExpr
+
+			case *types.Builtin:
+				// For reference to built-in function, return enclosing call.
+				path = path[1:] // ascend to enclosing function call
+				continue
+
+			case *types.Nil:
+				return path, actionExpr
+			}
+
+			// No object.
+			switch path[1].(type) {
+			case *ast.SelectorExpr:
+				// Return enclosing selector expression.
+				return path[1:], actionExpr
+
+			case *ast.Field:
+				// TODO(adonovan): test this.
+				// e.g. all f in:
+				//  struct { f, g int }
+				//  interface { f() }
+				//  func (f T) method(f, g int) (f, g bool)
+				//
+				// switch path[3].(type) {
+				// case *ast.FuncDecl:
+				// case *ast.StructType:
+				// case *ast.InterfaceType:
+				// }
+				//
+				// return path[1:], actionExpr
+				//
+				// Unclear what to do with these.
+				// Struct.Fields             -- field
+				// Interface.Methods         -- field
+				// FuncType.{Params.Results} -- actionExpr
+				// FuncDecl.Recv             -- actionExpr
+
+			case *ast.File:
+				// 'package foo'
+				return path, actionPackage
+
+			case *ast.ImportSpec:
+				// TODO(adonovan): fix: why no package object? go/types bug?
+				return path[1:], actionPackage
+
+			default:
+				// e.g. blank identifier
+				// or y in "switch y := x.(type)"
+				// or code in a _test.go file that's not part of the package.
+				log.Printf("unknown reference %s in %T\n", n, path[1])
+				return path, actionUnknown
+			}
+
+		case *ast.StarExpr:
+			if pkginfo.Types[n].IsType() {
+				return path, actionType
+			}
+			return path, actionExpr
+
+		case ast.Expr:
+			// All Expr but {BasicLit,Ident,StarExpr} are
+			// "true" expressions that evaluate to a value.
+			return path, actionExpr
+		}
+
+		// Ascend to parent.
+		path = path[1:]
+	}
+
+	return nil, actionUnknown // unreachable
+}
+
+func describeValue(qpos *queryPos, path []ast.Node) (*describeValueResult, error) {
+	var expr ast.Expr
+	var obj types.Object
+	switch n := path[0].(type) {
+	case *ast.ValueSpec:
+		// ambiguous ValueSpec containing multiple names
+		return nil, fmt.Errorf("multiple value specification")
+	case *ast.Ident:
+		obj = qpos.info.ObjectOf(n)
+		expr = n
+	case ast.Expr:
+		expr = n
+	default:
+		// TODO(adonovan): is this reachable?
+		return nil, fmt.Errorf("unexpected AST for expr: %T", n)
+	}
+
+	typ := qpos.info.TypeOf(expr)
+	constVal := qpos.info.Types[expr].Value
+
+	return &describeValueResult{
+		qpos:     qpos,
+		expr:     expr,
+		typ:      typ,
+		constVal: constVal,
+		obj:      obj,
+	}, nil
+}
+
+type describeValueResult struct {
+	qpos     *queryPos
+	expr     ast.Expr     // query node
+	typ      types.Type   // type of expression
+	constVal exact.Value  // value of expression, if constant
+	obj      types.Object // var/func/const object, if expr was Ident
+}
+
+func (r *describeValueResult) display(printf printfFunc) {
+	var prefix, suffix string
+	if r.constVal != nil {
+		suffix = fmt.Sprintf(" of constant value %s", r.constVal)
+	}
+	switch obj := r.obj.(type) {
+	case *types.Func:
+		if recv := obj.Type().(*types.Signature).Recv(); recv != nil {
+			if _, ok := recv.Type().Underlying().(*types.Interface); ok {
+				prefix = "interface method "
+			} else {
+				prefix = "method "
+			}
+		}
+	}
+
+	// Describe the expression.
+	if r.obj != nil {
+		if r.obj.Pos() == r.expr.Pos() {
+			// defining ident
+			printf(r.expr, "definition of %s%s%s", prefix, r.qpos.objectString(r.obj), suffix)
+		} else {
+			// referring ident
+			printf(r.expr, "reference to %s%s%s", prefix, r.qpos.objectString(r.obj), suffix)
+			if def := r.obj.Pos(); def != token.NoPos {
+				printf(def, "defined here")
+			}
+		}
+	} else {
+		desc := astutil.NodeDescription(r.expr)
+		if suffix != "" {
+			// constant expression
+			printf(r.expr, "%s%s", desc, suffix)
+		} else {
+			// non-constant expression
+			printf(r.expr, "%s of type %s", desc, r.qpos.typeString(r.typ))
+		}
+	}
+}
+
+func (r *describeValueResult) toSerial(res *serial.Result, fset *token.FileSet) {
+	var value, objpos string
+	if r.constVal != nil {
+		value = r.constVal.String()
+	}
+	if r.obj != nil {
+		objpos = fset.Position(r.obj.Pos()).String()
+	}
+
+	res.Describe = &serial.Describe{
+		Desc:   astutil.NodeDescription(r.expr),
+		Pos:    fset.Position(r.expr.Pos()).String(),
+		Detail: "value",
+		Value: &serial.DescribeValue{
+			Type:   r.qpos.typeString(r.typ),
+			Value:  value,
+			ObjPos: objpos,
+		},
+	}
+}
+
+// ---- TYPE ------------------------------------------------------------
+
+func describeType(qpos *queryPos, path []ast.Node) (*describeTypeResult, error) {
+	var description string
+	var t types.Type
+	switch n := path[0].(type) {
+	case *ast.Ident:
+		t = qpos.info.TypeOf(n)
+		switch t := t.(type) {
+		case *types.Basic:
+			description = "reference to built-in "
+
+		case *types.Named:
+			isDef := t.Obj().Pos() == n.Pos() // see caveats at isDef above
+			if isDef {
+				description = "definition of "
+			} else {
+				description = "reference to "
+			}
+		}
+
+	case ast.Expr:
+		t = qpos.info.TypeOf(n)
+
+	default:
+		// Unreachable?
+		return nil, fmt.Errorf("unexpected AST for type: %T", n)
+	}
+
+	description = description + "type " + qpos.typeString(t)
+
+	// Show sizes for structs and named types (it's fairly obvious for others).
+	switch t.(type) {
+	case *types.Named, *types.Struct:
+		szs := types.StdSizes{8, 8} // assume amd64
+		description = fmt.Sprintf("%s (size %d, align %d)", description,
+			szs.Sizeof(t), szs.Alignof(t))
+	}
+
+	return &describeTypeResult{
+		qpos:        qpos,
+		node:        path[0],
+		description: description,
+		typ:         t,
+		methods:     accessibleMethods(t, qpos.info.Pkg),
+	}, nil
+}
+
+type describeTypeResult struct {
+	qpos        *queryPos
+	node        ast.Node
+	description string
+	typ         types.Type
+	methods     []*types.Selection
+}
+
+func (r *describeTypeResult) display(printf printfFunc) {
+	printf(r.node, "%s", r.description)
+
+	// Show the underlying type for a reference to a named type.
+	if nt, ok := r.typ.(*types.Named); ok && r.node.Pos() != nt.Obj().Pos() {
+		printf(nt.Obj(), "defined as %s", r.qpos.typeString(nt.Underlying()))
+	}
+
+	// Print the method set, if the type kind is capable of bearing methods.
+	switch r.typ.(type) {
+	case *types.Interface, *types.Struct, *types.Named:
+		if len(r.methods) > 0 {
+			printf(r.node, "Method set:")
+			for _, meth := range r.methods {
+				// TODO(adonovan): print these relative
+				// to the owning package, not the
+				// query package.
+				printf(meth.Obj(), "\t%s", r.qpos.selectionString(meth))
+			}
+		} else {
+			printf(r.node, "No methods.")
+		}
+	}
+}
+
+func (r *describeTypeResult) toSerial(res *serial.Result, fset *token.FileSet) {
+	var namePos, nameDef string
+	if nt, ok := r.typ.(*types.Named); ok {
+		namePos = fset.Position(nt.Obj().Pos()).String()
+		nameDef = nt.Underlying().String()
+	}
+	res.Describe = &serial.Describe{
+		Desc:   r.description,
+		Pos:    fset.Position(r.node.Pos()).String(),
+		Detail: "type",
+		Type: &serial.DescribeType{
+			Type:    r.qpos.typeString(r.typ),
+			NamePos: namePos,
+			NameDef: nameDef,
+			Methods: methodsToSerial(r.qpos.info.Pkg, r.methods, fset),
+		},
+	}
+}
+
+// ---- PACKAGE ------------------------------------------------------------
+
+func describePackage(qpos *queryPos, path []ast.Node) (*describePackageResult, error) {
+	var description string
+	var pkg *types.Package
+	switch n := path[0].(type) {
+	case *ast.ImportSpec:
+		var pkgname *types.PkgName
+		if n.Name != nil {
+			pkgname = qpos.info.Defs[n.Name].(*types.PkgName)
+		} else if p := qpos.info.Implicits[n]; p != nil {
+			pkgname = p.(*types.PkgName)
+		}
+		pkg = pkgname.Imported()
+		description = fmt.Sprintf("import of package %q", pkg.Path())
+
+	case *ast.Ident:
+		if _, isDef := path[1].(*ast.File); isDef {
+			// e.g. package id
+			pkg = qpos.info.Pkg
+			description = fmt.Sprintf("definition of package %q", pkg.Path())
+		} else {
+			// e.g. import id "..."
+			//  or  id.F()
+			pkg = qpos.info.ObjectOf(n).(*types.PkgName).Imported()
+			description = fmt.Sprintf("reference to package %q", pkg.Path())
+		}
+
+	default:
+		// Unreachable?
+		return nil, fmt.Errorf("unexpected AST for package: %T", n)
+	}
+
+	var members []*describeMember
+	// NB: "unsafe" has no types.Package
+	if pkg != nil {
+		// Enumerate the accessible package members
+		// in lexicographic order.
+		for _, name := range pkg.Scope().Names() {
+			if pkg == qpos.info.Pkg || ast.IsExported(name) {
+				mem := pkg.Scope().Lookup(name)
+				var methods []*types.Selection
+				if mem, ok := mem.(*types.TypeName); ok {
+					methods = accessibleMethods(mem.Type(), qpos.info.Pkg)
+				}
+				members = append(members, &describeMember{
+					mem,
+					methods,
+				})
+
+			}
+		}
+	}
+
+	return &describePackageResult{qpos.fset, path[0], description, pkg, members}, nil
+}
+
+type describePackageResult struct {
+	fset        *token.FileSet
+	node        ast.Node
+	description string
+	pkg         *types.Package
+	members     []*describeMember // in lexicographic name order
+}
+
+type describeMember struct {
+	obj     types.Object
+	methods []*types.Selection // in types.MethodSet order
+}
+
+func (r *describePackageResult) display(printf printfFunc) {
+	printf(r.node, "%s", r.description)
+
+	// Compute max width of name "column".
+	maxname := 0
+	for _, mem := range r.members {
+		if l := len(mem.obj.Name()); l > maxname {
+			maxname = l
+		}
+	}
+
+	for _, mem := range r.members {
+		printf(mem.obj, "\t%s", formatMember(mem.obj, maxname))
+		for _, meth := range mem.methods {
+			printf(meth.Obj(), "\t\t%s", types.SelectionString(meth, types.RelativeTo(r.pkg)))
+		}
+	}
+}
+
+func formatMember(obj types.Object, maxname int) string {
+	qualifier := types.RelativeTo(obj.Pkg())
+	var buf bytes.Buffer
+	fmt.Fprintf(&buf, "%-5s %-*s", tokenOf(obj), maxname, obj.Name())
+	switch obj := obj.(type) {
+	case *types.Const:
+		fmt.Fprintf(&buf, " %s = %s", types.TypeString(obj.Type(), qualifier), obj.Val().String())
+
+	case *types.Func:
+		fmt.Fprintf(&buf, " %s", types.TypeString(obj.Type(), qualifier))
+
+	case *types.TypeName:
+		// Abbreviate long aggregate type names.
+		var abbrev string
+		switch t := obj.Type().Underlying().(type) {
+		case *types.Interface:
+			if t.NumMethods() > 1 {
+				abbrev = "interface{...}"
+			}
+		case *types.Struct:
+			if t.NumFields() > 1 {
+				abbrev = "struct{...}"
+			}
+		}
+		if abbrev == "" {
+			fmt.Fprintf(&buf, " %s", types.TypeString(obj.Type().Underlying(), qualifier))
+		} else {
+			fmt.Fprintf(&buf, " %s", abbrev)
+		}
+
+	case *types.Var:
+		fmt.Fprintf(&buf, " %s", types.TypeString(obj.Type(), qualifier))
+	}
+	return buf.String()
+}
+
+func (r *describePackageResult) toSerial(res *serial.Result, fset *token.FileSet) {
+	var members []*serial.DescribeMember
+	for _, mem := range r.members {
+		typ := mem.obj.Type()
+		var val string
+		switch mem := mem.obj.(type) {
+		case *types.Const:
+			val = mem.Val().String()
+		case *types.TypeName:
+			typ = typ.Underlying()
+		}
+		members = append(members, &serial.DescribeMember{
+			Name:    mem.obj.Name(),
+			Type:    typ.String(),
+			Value:   val,
+			Pos:     fset.Position(mem.obj.Pos()).String(),
+			Kind:    tokenOf(mem.obj),
+			Methods: methodsToSerial(r.pkg, mem.methods, fset),
+		})
+	}
+	res.Describe = &serial.Describe{
+		Desc:   r.description,
+		Pos:    fset.Position(r.node.Pos()).String(),
+		Detail: "package",
+		Package: &serial.DescribePackage{
+			Path:    r.pkg.Path(),
+			Members: members,
+		},
+	}
+}
+
+func tokenOf(o types.Object) string {
+	switch o.(type) {
+	case *types.Func:
+		return "func"
+	case *types.Var:
+		return "var"
+	case *types.TypeName:
+		return "type"
+	case *types.Const:
+		return "const"
+	case *types.PkgName:
+		return "package"
+	}
+	panic(o)
+}
+
+// ---- STATEMENT ------------------------------------------------------------
+
+func describeStmt(qpos *queryPos, path []ast.Node) (*describeStmtResult, error) {
+	var description string
+	switch n := path[0].(type) {
+	case *ast.Ident:
+		if qpos.info.Defs[n] != nil {
+			description = "labelled statement"
+		} else {
+			description = "reference to labelled statement"
+		}
+
+	default:
+		// Nothing much to say about statements.
+		description = astutil.NodeDescription(n)
+	}
+	return &describeStmtResult{qpos.fset, path[0], description}, nil
+}
+
+type describeStmtResult struct {
+	fset        *token.FileSet
+	node        ast.Node
+	description string
+}
+
+func (r *describeStmtResult) display(printf printfFunc) {
+	printf(r.node, "%s", r.description)
+}
+
+func (r *describeStmtResult) toSerial(res *serial.Result, fset *token.FileSet) {
+	res.Describe = &serial.Describe{
+		Desc:   r.description,
+		Pos:    fset.Position(r.node.Pos()).String(),
+		Detail: "unknown",
+	}
+}
+
+// ------------------- Utilities -------------------
+
+// pathToString returns a string containing the concrete types of the
+// nodes in path.
+func pathToString(path []ast.Node) string {
+	var buf bytes.Buffer
+	fmt.Fprint(&buf, "[")
+	for i, n := range path {
+		if i > 0 {
+			fmt.Fprint(&buf, " ")
+		}
+		fmt.Fprint(&buf, strings.TrimPrefix(fmt.Sprintf("%T", n), "*ast."))
+	}
+	fmt.Fprint(&buf, "]")
+	return buf.String()
+}
+
+func accessibleMethods(t types.Type, from *types.Package) []*types.Selection {
+	var methods []*types.Selection
+	for _, meth := range typeutil.IntuitiveMethodSet(t, nil) {
+		if isAccessibleFrom(meth.Obj(), from) {
+			methods = append(methods, meth)
+		}
+	}
+	return methods
+}
+
+func isAccessibleFrom(obj types.Object, pkg *types.Package) bool {
+	return ast.IsExported(obj.Name()) || obj.Pkg() == pkg
+}
+
+func methodsToSerial(this *types.Package, methods []*types.Selection, fset *token.FileSet) []serial.DescribeMethod {
+	qualifier := types.RelativeTo(this)
+	var jmethods []serial.DescribeMethod
+	for _, meth := range methods {
+		var ser serial.DescribeMethod
+		if meth != nil { // may contain nils when called by implements (on a method)
+			ser = serial.DescribeMethod{
+				Name: types.SelectionString(meth, qualifier),
+				Pos:  fset.Position(meth.Obj().Pos()).String(),
+			}
+		}
+		jmethods = append(jmethods, ser)
+	}
+	return jmethods
+}
diff --git a/oracle/freevars.go b/oracle/freevars.go
new file mode 100644
index 0000000..400a118
--- /dev/null
+++ b/oracle/freevars.go
@@ -0,0 +1,222 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package oracle
+
+import (
+	"bytes"
+	"go/ast"
+	"go/printer"
+	"go/token"
+	"sort"
+
+	"golang.org/x/tools/go/loader"
+	"golang.org/x/tools/go/types"
+	"golang.org/x/tools/oracle/serial"
+)
+
+// freevars displays the lexical (not package-level) free variables of
+// the selection.
+//
+// It treats A.B.C as a separate variable from A to reveal the parts
+// of an aggregate type that are actually needed.
+// This aids refactoring.
+//
+// TODO(adonovan): optionally display the free references to
+// file/package scope objects, and to objects from other packages.
+// Depending on where the resulting function abstraction will go,
+// these might be interesting.  Perhaps group the results into three
+// bands.
+//
+func freevars(q *Query) error {
+	lconf := loader.Config{Build: q.Build}
+	allowErrors(&lconf)
+
+	if err := importQueryPackage(q.Pos, &lconf); err != nil {
+		return err
+	}
+
+	// Load/parse/type-check the program.
+	lprog, err := lconf.Load()
+	if err != nil {
+		return err
+	}
+	q.Fset = lprog.Fset
+
+	qpos, err := parseQueryPos(lprog, q.Pos, false)
+	if err != nil {
+		return err
+	}
+
+	file := qpos.path[len(qpos.path)-1] // the enclosing file
+	fileScope := qpos.info.Scopes[file]
+	pkgScope := fileScope.Parent()
+
+	// The id and sel functions return non-nil if they denote an
+	// object o or selection o.x.y that is referenced by the
+	// selection but defined neither within the selection nor at
+	// file scope, i.e. it is in the lexical environment.
+	var id func(n *ast.Ident) types.Object
+	var sel func(n *ast.SelectorExpr) types.Object
+
+	sel = func(n *ast.SelectorExpr) types.Object {
+		switch x := unparen(n.X).(type) {
+		case *ast.SelectorExpr:
+			return sel(x)
+		case *ast.Ident:
+			return id(x)
+		}
+		return nil
+	}
+
+	id = func(n *ast.Ident) types.Object {
+		obj := qpos.info.Uses[n]
+		if obj == nil {
+			return nil // not a reference
+		}
+		if _, ok := obj.(*types.PkgName); ok {
+			return nil // imported package
+		}
+		if !(file.Pos() <= obj.Pos() && obj.Pos() <= file.End()) {
+			return nil // not defined in this file
+		}
+		scope := obj.Parent()
+		if scope == nil {
+			return nil // e.g. interface method, struct field
+		}
+		if scope == fileScope || scope == pkgScope {
+			return nil // defined at file or package scope
+		}
+		if qpos.start <= obj.Pos() && obj.Pos() <= qpos.end {
+			return nil // defined within selection => not free
+		}
+		return obj
+	}
+
+	// Maps each reference that is free in the selection
+	// to the object it refers to.
+	// The map de-duplicates repeated references.
+	refsMap := make(map[string]freevarsRef)
+
+	// Visit all the identifiers in the selected ASTs.
+	ast.Inspect(qpos.path[0], func(n ast.Node) bool {
+		if n == nil {
+			return true // popping DFS stack
+		}
+
+		// Is this node contained within the selection?
+		// (freevars permits inexact selections,
+		// like two stmts in a block.)
+		if qpos.start <= n.Pos() && n.End() <= qpos.end {
+			var obj types.Object
+			var prune bool
+			switch n := n.(type) {
+			case *ast.Ident:
+				obj = id(n)
+
+			case *ast.SelectorExpr:
+				obj = sel(n)
+				prune = true
+			}
+
+			if obj != nil {
+				var kind string
+				switch obj.(type) {
+				case *types.Var:
+					kind = "var"
+				case *types.Func:
+					kind = "func"
+				case *types.TypeName:
+					kind = "type"
+				case *types.Const:
+					kind = "const"
+				case *types.Label:
+					kind = "label"
+				default:
+					panic(obj)
+				}
+
+				typ := qpos.info.TypeOf(n.(ast.Expr))
+				ref := freevarsRef{kind, printNode(lprog.Fset, n), typ, obj}
+				refsMap[ref.ref] = ref
+
+				if prune {
+					return false // don't descend
+				}
+			}
+		}
+
+		return true // descend
+	})
+
+	refs := make([]freevarsRef, 0, len(refsMap))
+	for _, ref := range refsMap {
+		refs = append(refs, ref)
+	}
+	sort.Sort(byRef(refs))
+
+	q.result = &freevarsResult{
+		qpos: qpos,
+		refs: refs,
+	}
+	return nil
+}
+
+type freevarsResult struct {
+	qpos *queryPos
+	refs []freevarsRef
+}
+
+type freevarsRef struct {
+	kind string
+	ref  string
+	typ  types.Type
+	obj  types.Object
+}
+
+func (r *freevarsResult) display(printf printfFunc) {
+	if len(r.refs) == 0 {
+		printf(r.qpos, "No free identifiers.")
+	} else {
+		printf(r.qpos, "Free identifiers:")
+		qualifier := types.RelativeTo(r.qpos.info.Pkg)
+		for _, ref := range r.refs {
+			// Avoid printing "type T T".
+			var typstr string
+			if ref.kind != "type" {
+				typstr = " " + types.TypeString(ref.typ, qualifier)
+			}
+			printf(ref.obj, "%s %s%s", ref.kind, ref.ref, typstr)
+		}
+	}
+}
+
+func (r *freevarsResult) toSerial(res *serial.Result, fset *token.FileSet) {
+	var refs []*serial.FreeVar
+	for _, ref := range r.refs {
+		refs = append(refs,
+			&serial.FreeVar{
+				Pos:  fset.Position(ref.obj.Pos()).String(),
+				Kind: ref.kind,
+				Ref:  ref.ref,
+				Type: ref.typ.String(),
+			})
+	}
+	res.Freevars = refs
+}
+
+// -------- utils --------
+
+type byRef []freevarsRef
+
+func (p byRef) Len() int           { return len(p) }
+func (p byRef) Less(i, j int) bool { return p[i].ref < p[j].ref }
+func (p byRef) Swap(i, j int)      { p[i], p[j] = p[j], p[i] }
+
+// printNode returns the pretty-printed syntax of n.
+func printNode(fset *token.FileSet, n ast.Node) string {
+	var buf bytes.Buffer
+	printer.Fprint(&buf, fset, n)
+	return buf.String()
+}
diff --git a/oracle/implements.go b/oracle/implements.go
new file mode 100644
index 0000000..3155ca2
--- /dev/null
+++ b/oracle/implements.go
@@ -0,0 +1,330 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package oracle
+
+import (
+	"fmt"
+	"go/ast"
+	"go/token"
+	"reflect"
+	"sort"
+	"strings"
+
+	"golang.org/x/tools/go/loader"
+	"golang.org/x/tools/go/types"
+	"golang.org/x/tools/go/types/typeutil"
+	"golang.org/x/tools/oracle/serial"
+)
+
+// Implements displays the "implements" relation as it pertains to the
+// selected type within a single package.
+// If the selection is a method, 'implements' displays
+// the corresponding methods of the types that would have been reported
+// by an implements query on the receiver type.
+//
+func implements(q *Query) error {
+	lconf := loader.Config{Build: q.Build}
+	allowErrors(&lconf)
+
+	if err := importQueryPackage(q.Pos, &lconf); err != nil {
+		return err
+	}
+
+	// Load/parse/type-check the program.
+	lprog, err := lconf.Load()
+	if err != nil {
+		return err
+	}
+	q.Fset = lprog.Fset
+
+	qpos, err := parseQueryPos(lprog, q.Pos, false)
+	if err != nil {
+		return err
+	}
+
+	// Find the selected type.
+	path, action := findInterestingNode(qpos.info, qpos.path)
+
+	var method *types.Func
+	var T types.Type // selected type (receiver if method != nil)
+
+	switch action {
+	case actionExpr:
+		// method?
+		if id, ok := path[0].(*ast.Ident); ok {
+			if obj, ok := qpos.info.ObjectOf(id).(*types.Func); ok {
+				recv := obj.Type().(*types.Signature).Recv()
+				if recv == nil {
+					return fmt.Errorf("this function is not a method")
+				}
+				method = obj
+				T = recv.Type()
+			}
+		}
+	case actionType:
+		T = qpos.info.TypeOf(path[0].(ast.Expr))
+	}
+	if T == nil {
+		return fmt.Errorf("no type or method here")
+	}
+
+	// Find all named types, even local types (which can have
+	// methods via promotion) and the built-in "error".
+	//
+	// TODO(adonovan): include all packages in PTA scope too?
+	// i.e. don't reduceScope?
+	//
+	var allNamed []types.Type
+	for _, info := range lprog.AllPackages {
+		for _, obj := range info.Defs {
+			if obj, ok := obj.(*types.TypeName); ok {
+				allNamed = append(allNamed, obj.Type())
+			}
+		}
+	}
+	allNamed = append(allNamed, types.Universe.Lookup("error").Type())
+
+	var msets typeutil.MethodSetCache
+
+	// Test each named type.
+	var to, from, fromPtr []types.Type
+	for _, U := range allNamed {
+		if isInterface(T) {
+			if msets.MethodSet(T).Len() == 0 {
+				continue // empty interface
+			}
+			if isInterface(U) {
+				if msets.MethodSet(U).Len() == 0 {
+					continue // empty interface
+				}
+
+				// T interface, U interface
+				if !types.Identical(T, U) {
+					if types.AssignableTo(U, T) {
+						to = append(to, U)
+					}
+					if types.AssignableTo(T, U) {
+						from = append(from, U)
+					}
+				}
+			} else {
+				// T interface, U concrete
+				if types.AssignableTo(U, T) {
+					to = append(to, U)
+				} else if pU := types.NewPointer(U); types.AssignableTo(pU, T) {
+					to = append(to, pU)
+				}
+			}
+		} else if isInterface(U) {
+			if msets.MethodSet(U).Len() == 0 {
+				continue // empty interface
+			}
+
+			// T concrete, U interface
+			if types.AssignableTo(T, U) {
+				from = append(from, U)
+			} else if pT := types.NewPointer(T); types.AssignableTo(pT, U) {
+				fromPtr = append(fromPtr, U)
+			}
+		}
+	}
+
+	var pos interface{} = qpos
+	if nt, ok := deref(T).(*types.Named); ok {
+		pos = nt.Obj()
+	}
+
+	// Sort types (arbitrarily) to ensure test determinism.
+	sort.Sort(typesByString(to))
+	sort.Sort(typesByString(from))
+	sort.Sort(typesByString(fromPtr))
+
+	var toMethod, fromMethod, fromPtrMethod []*types.Selection // contain nils
+	if method != nil {
+		for _, t := range to {
+			toMethod = append(toMethod,
+				types.NewMethodSet(t).Lookup(method.Pkg(), method.Name()))
+		}
+		for _, t := range from {
+			fromMethod = append(fromMethod,
+				types.NewMethodSet(t).Lookup(method.Pkg(), method.Name()))
+		}
+		for _, t := range fromPtr {
+			fromPtrMethod = append(fromPtrMethod,
+				types.NewMethodSet(t).Lookup(method.Pkg(), method.Name()))
+		}
+	}
+
+	q.result = &implementsResult{
+		qpos, T, pos, to, from, fromPtr, method, toMethod, fromMethod, fromPtrMethod,
+	}
+	return nil
+}
+
+type implementsResult struct {
+	qpos *queryPos
+
+	t       types.Type   // queried type (not necessarily named)
+	pos     interface{}  // pos of t (*types.Name or *QueryPos)
+	to      []types.Type // named or ptr-to-named types assignable to interface T
+	from    []types.Type // named interfaces assignable from T
+	fromPtr []types.Type // named interfaces assignable only from *T
+
+	// if a method was queried:
+	method        *types.Func        // queried method
+	toMethod      []*types.Selection // method of type to[i], if any
+	fromMethod    []*types.Selection // method of type from[i], if any
+	fromPtrMethod []*types.Selection // method of type fromPtrMethod[i], if any
+}
+
+func (r *implementsResult) display(printf printfFunc) {
+	relation := "is implemented by"
+
+	meth := func(sel *types.Selection) {
+		if sel != nil {
+			printf(sel.Obj(), "\t%s method (%s).%s",
+				relation, r.qpos.typeString(sel.Recv()), sel.Obj().Name())
+		}
+	}
+
+	if isInterface(r.t) {
+		if types.NewMethodSet(r.t).Len() == 0 { // TODO(adonovan): cache mset
+			printf(r.pos, "empty interface type %s", r.qpos.typeString(r.t))
+			return
+		}
+
+		if r.method == nil {
+			printf(r.pos, "interface type %s", r.qpos.typeString(r.t))
+		} else {
+			printf(r.method, "abstract method %s", r.qpos.objectString(r.method))
+		}
+
+		// Show concrete types (or methods) first; use two passes.
+		for i, sub := range r.to {
+			if !isInterface(sub) {
+				if r.method == nil {
+					printf(deref(sub).(*types.Named).Obj(), "\t%s %s type %s",
+						relation, typeKind(sub), r.qpos.typeString(sub))
+				} else {
+					meth(r.toMethod[i])
+				}
+			}
+		}
+		for i, sub := range r.to {
+			if isInterface(sub) {
+				if r.method == nil {
+					printf(sub.(*types.Named).Obj(), "\t%s %s type %s",
+						relation, typeKind(sub), r.qpos.typeString(sub))
+				} else {
+					meth(r.toMethod[i])
+				}
+			}
+		}
+
+		relation = "implements"
+		for i, super := range r.from {
+			if r.method == nil {
+				printf(super.(*types.Named).Obj(), "\t%s %s",
+					relation, r.qpos.typeString(super))
+			} else {
+				meth(r.fromMethod[i])
+			}
+		}
+	} else {
+		relation = "implements"
+
+		if r.from != nil {
+			if r.method == nil {
+				printf(r.pos, "%s type %s",
+					typeKind(r.t), r.qpos.typeString(r.t))
+			} else {
+				printf(r.method, "concrete method %s",
+					r.qpos.objectString(r.method))
+			}
+			for i, super := range r.from {
+				if r.method == nil {
+					printf(super.(*types.Named).Obj(), "\t%s %s",
+						relation, r.qpos.typeString(super))
+				} else {
+					meth(r.fromMethod[i])
+				}
+			}
+		}
+		if r.fromPtr != nil {
+			if r.method == nil {
+				printf(r.pos, "pointer type *%s", r.qpos.typeString(r.t))
+			} else {
+				// TODO(adonovan): de-dup (C).f and (*C).f implementing (I).f.
+				printf(r.method, "concrete method %s",
+					r.qpos.objectString(r.method))
+			}
+
+			for i, psuper := range r.fromPtr {
+				if r.method == nil {
+					printf(psuper.(*types.Named).Obj(), "\t%s %s",
+						relation, r.qpos.typeString(psuper))
+				} else {
+					meth(r.fromPtrMethod[i])
+				}
+			}
+		} else if r.from == nil {
+			printf(r.pos, "%s type %s implements only interface{}",
+				typeKind(r.t), r.qpos.typeString(r.t))
+		}
+	}
+}
+
+func (r *implementsResult) toSerial(res *serial.Result, fset *token.FileSet) {
+	res.Implements = &serial.Implements{
+		T:                       makeImplementsType(r.t, fset),
+		AssignableTo:            makeImplementsTypes(r.to, fset),
+		AssignableFrom:          makeImplementsTypes(r.from, fset),
+		AssignableFromPtr:       makeImplementsTypes(r.fromPtr, fset),
+		AssignableToMethod:      methodsToSerial(r.qpos.info.Pkg, r.toMethod, fset),
+		AssignableFromMethod:    methodsToSerial(r.qpos.info.Pkg, r.fromMethod, fset),
+		AssignableFromPtrMethod: methodsToSerial(r.qpos.info.Pkg, r.fromPtrMethod, fset),
+	}
+	if r.method != nil {
+		res.Implements.Method = &serial.DescribeMethod{
+			Name: r.qpos.objectString(r.method),
+			Pos:  fset.Position(r.method.Pos()).String(),
+		}
+	}
+}
+
+func makeImplementsTypes(tt []types.Type, fset *token.FileSet) []serial.ImplementsType {
+	var r []serial.ImplementsType
+	for _, t := range tt {
+		r = append(r, makeImplementsType(t, fset))
+	}
+	return r
+}
+
+func makeImplementsType(T types.Type, fset *token.FileSet) serial.ImplementsType {
+	var pos token.Pos
+	if nt, ok := deref(T).(*types.Named); ok { // implementsResult.t may be non-named
+		pos = nt.Obj().Pos()
+	}
+	return serial.ImplementsType{
+		Name: T.String(),
+		Pos:  fset.Position(pos).String(),
+		Kind: typeKind(T),
+	}
+}
+
+// typeKind returns a string describing the underlying kind of type,
+// e.g. "slice", "array", "struct".
+func typeKind(T types.Type) string {
+	s := reflect.TypeOf(T.Underlying()).String()
+	return strings.ToLower(strings.TrimPrefix(s, "*types."))
+}
+
+func isInterface(T types.Type) bool { return types.IsInterface(T) }
+
+type typesByString []types.Type
+
+func (p typesByString) Len() int           { return len(p) }
+func (p typesByString) Less(i, j int) bool { return p[i].String() < p[j].String() }
+func (p typesByString) Swap(i, j int)      { p[i], p[j] = p[j], p[i] }
diff --git a/oracle/oracle.go b/oracle/oracle.go
new file mode 100644
index 0000000..544cfa4
--- /dev/null
+++ b/oracle/oracle.go
@@ -0,0 +1,364 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package oracle contains the implementation of the oracle tool whose
+// command-line is provided by golang.org/x/tools/cmd/oracle.
+//
+// http://golang.org/s/oracle-design
+// http://golang.org/s/oracle-user-manual
+//
+package oracle // import "golang.org/x/tools/oracle"
+
+// This file defines oracle.Query, the entry point for the oracle tool.
+// The actual executable is defined in cmd/oracle.
+
+// TODO(adonovan): new queries
+// - show all statements that may update the selected lvalue
+//   (local, global, field, etc).
+// - show all places where an object of type T is created
+//   (&T{}, var t T, new(T), new(struct{array [3]T}), etc.
+
+import (
+	"fmt"
+	"go/ast"
+	"go/build"
+	"go/parser"
+	"go/token"
+	"io"
+	"path/filepath"
+
+	"golang.org/x/tools/go/ast/astutil"
+	"golang.org/x/tools/go/loader"
+	"golang.org/x/tools/go/pointer"
+	"golang.org/x/tools/go/ssa"
+	"golang.org/x/tools/go/types"
+	"golang.org/x/tools/oracle/serial"
+)
+
+type printfFunc func(pos interface{}, format string, args ...interface{})
+
+// queryResult is the interface of each query-specific result type.
+type queryResult interface {
+	toSerial(res *serial.Result, fset *token.FileSet)
+	display(printf printfFunc)
+}
+
+// A QueryPos represents the position provided as input to a query:
+// a textual extent in the program's source code, the AST node it
+// corresponds to, and the package to which it belongs.
+// Instances are created by parseQueryPos.
+type queryPos struct {
+	fset       *token.FileSet
+	start, end token.Pos           // source extent of query
+	path       []ast.Node          // AST path from query node to root of ast.File
+	exact      bool                // 2nd result of PathEnclosingInterval
+	info       *loader.PackageInfo // type info for the queried package (nil for fastQueryPos)
+}
+
+// TypeString prints type T relative to the query position.
+func (qpos *queryPos) typeString(T types.Type) string {
+	return types.TypeString(T, types.RelativeTo(qpos.info.Pkg))
+}
+
+// ObjectString prints object obj relative to the query position.
+func (qpos *queryPos) objectString(obj types.Object) string {
+	return types.ObjectString(obj, types.RelativeTo(qpos.info.Pkg))
+}
+
+// SelectionString prints selection sel relative to the query position.
+func (qpos *queryPos) selectionString(sel *types.Selection) string {
+	return types.SelectionString(sel, types.RelativeTo(qpos.info.Pkg))
+}
+
+// A Query specifies a single oracle query.
+type Query struct {
+	Mode  string         // query mode ("callers", etc)
+	Pos   string         // query position
+	Build *build.Context // package loading configuration
+
+	// pointer analysis options
+	Scope      []string  // main packages in (*loader.Config).FromArgs syntax
+	PTALog     io.Writer // (optional) pointer-analysis log file
+	Reflection bool      // model reflection soundly (currently slow).
+
+	// Populated during Run()
+	Fset   *token.FileSet
+	result queryResult
+}
+
+// Serial returns an instance of serial.Result, which implements the
+// {xml,json}.Marshaler interfaces so that query results can be
+// serialized as JSON or XML.
+//
+func (q *Query) Serial() *serial.Result {
+	resj := &serial.Result{Mode: q.Mode}
+	q.result.toSerial(resj, q.Fset)
+	return resj
+}
+
+// WriteTo writes the oracle query result res to out in a compiler diagnostic format.
+func (q *Query) WriteTo(out io.Writer) {
+	printf := func(pos interface{}, format string, args ...interface{}) {
+		fprintf(out, q.Fset, pos, format, args...)
+	}
+	q.result.display(printf)
+}
+
+// Run runs an oracle query and populates its Fset and Result.
+func Run(q *Query) error {
+	switch q.Mode {
+	case "callees":
+		return callees(q)
+	case "callers":
+		return callers(q)
+	case "callstack":
+		return callstack(q)
+	case "peers":
+		return peers(q)
+	case "pointsto":
+		return pointsto(q)
+	case "whicherrs":
+		return whicherrs(q)
+	case "definition":
+		return definition(q)
+	case "describe":
+		return describe(q)
+	case "freevars":
+		return freevars(q)
+	case "implements":
+		return implements(q)
+	case "referrers":
+		return referrers(q)
+	case "what":
+		return what(q)
+	default:
+		return fmt.Errorf("invalid mode: %q", q.Mode)
+	}
+}
+
+func setPTAScope(lconf *loader.Config, scope []string) error {
+	if len(scope) == 0 {
+		return fmt.Errorf("no packages specified for pointer analysis scope")
+	}
+
+	// Determine initial packages for PTA.
+	args, err := lconf.FromArgs(scope, true)
+	if err != nil {
+		return err
+	}
+	if len(args) > 0 {
+		return fmt.Errorf("surplus arguments: %q", args)
+	}
+	return nil
+}
+
+// Create a pointer.Config whose scope is the initial packages of lprog
+// and their dependencies.
+func setupPTA(prog *ssa.Program, lprog *loader.Program, ptaLog io.Writer, reflection bool) (*pointer.Config, error) {
+	// TODO(adonovan): the body of this function is essentially
+	// duplicated in all go/pointer clients.  Refactor.
+
+	// For each initial package (specified on the command line),
+	// if it has a main function, analyze that,
+	// otherwise analyze its tests, if any.
+	var testPkgs, mains []*ssa.Package
+	for _, info := range lprog.InitialPackages() {
+		initialPkg := prog.Package(info.Pkg)
+
+		// Add package to the pointer analysis scope.
+		if initialPkg.Func("main") != nil {
+			mains = append(mains, initialPkg)
+		} else {
+			testPkgs = append(testPkgs, initialPkg)
+		}
+	}
+	if testPkgs != nil {
+		if p := prog.CreateTestMainPackage(testPkgs...); p != nil {
+			mains = append(mains, p)
+		}
+	}
+	if mains == nil {
+		return nil, fmt.Errorf("analysis scope has no main and no tests")
+	}
+	return &pointer.Config{
+		Log:        ptaLog,
+		Reflection: reflection,
+		Mains:      mains,
+	}, nil
+}
+
+// importQueryPackage finds the package P containing the
+// query position and tells conf to import it.
+func importQueryPackage(pos string, conf *loader.Config) error {
+	fqpos, err := fastQueryPos(pos)
+	if err != nil {
+		return err // bad query
+	}
+	filename := fqpos.fset.File(fqpos.start).Name()
+
+	// This will not work for ad-hoc packages
+	// such as $GOROOT/src/net/http/triv.go.
+	// TODO(adonovan): ensure we report a clear error.
+	_, importPath, err := guessImportPath(filename, conf.Build)
+	if err != nil {
+		return err // can't find GOPATH dir
+	}
+	if importPath == "" {
+		return fmt.Errorf("can't guess import path from %s", filename)
+	}
+
+	// Check that it's possible to load the queried package.
+	// (e.g. oracle tests contain different 'package' decls in same dir.)
+	// Keep consistent with logic in loader/util.go!
+	cfg2 := *conf.Build
+	cfg2.CgoEnabled = false
+	bp, err := cfg2.Import(importPath, "", 0)
+	if err != nil {
+		return err // no files for package
+	}
+
+	switch pkgContainsFile(bp, filename) {
+	case 'T':
+		conf.ImportWithTests(importPath)
+	case 'X':
+		conf.ImportWithTests(importPath)
+		importPath += "_test" // for TypeCheckFuncBodies
+	case 'G':
+		conf.Import(importPath)
+	default:
+		return fmt.Errorf("package %q doesn't contain file %s",
+			importPath, filename)
+	}
+
+	conf.TypeCheckFuncBodies = func(p string) bool { return p == importPath }
+
+	return nil
+}
+
+// pkgContainsFile reports whether file was among the packages Go
+// files, Test files, eXternal test files, or not found.
+func pkgContainsFile(bp *build.Package, filename string) byte {
+	for i, files := range [][]string{bp.GoFiles, bp.TestGoFiles, bp.XTestGoFiles} {
+		for _, file := range files {
+			if sameFile(filepath.Join(bp.Dir, file), filename) {
+				return "GTX"[i]
+			}
+		}
+	}
+	return 0 // not found
+}
+
+// ParseQueryPos parses the source query position pos and returns the
+// AST node of the loaded program lprog that it identifies.
+// If needExact, it must identify a single AST subtree;
+// this is appropriate for queries that allow fairly arbitrary syntax,
+// e.g. "describe".
+//
+func parseQueryPos(lprog *loader.Program, posFlag string, needExact bool) (*queryPos, error) {
+	filename, startOffset, endOffset, err := parsePosFlag(posFlag)
+	if err != nil {
+		return nil, err
+	}
+	start, end, err := findQueryPos(lprog.Fset, filename, startOffset, endOffset)
+	if err != nil {
+		return nil, err
+	}
+	info, path, exact := lprog.PathEnclosingInterval(start, end)
+	if path == nil {
+		return nil, fmt.Errorf("no syntax here")
+	}
+	if needExact && !exact {
+		return nil, fmt.Errorf("ambiguous selection within %s", astutil.NodeDescription(path[0]))
+	}
+	return &queryPos{lprog.Fset, start, end, path, exact, info}, nil
+}
+
+// ---------- Utilities ----------
+
+// allowErrors causes type errors to be silently ignored.
+// (Not suitable if SSA construction follows.)
+func allowErrors(lconf *loader.Config) {
+	ctxt := *lconf.Build // copy
+	ctxt.CgoEnabled = false
+	lconf.Build = &ctxt
+	lconf.AllowErrors = true
+	// AllErrors makes the parser always return an AST instead of
+	// bailing out after 10 errors and returning an empty ast.File.
+	lconf.ParserMode = parser.AllErrors
+	lconf.TypeChecker.Error = func(err error) {}
+}
+
+// ptrAnalysis runs the pointer analysis and returns its result.
+func ptrAnalysis(conf *pointer.Config) *pointer.Result {
+	result, err := pointer.Analyze(conf)
+	if err != nil {
+		panic(err) // pointer analysis internal error
+	}
+	return result
+}
+
+func unparen(e ast.Expr) ast.Expr { return astutil.Unparen(e) }
+
+// deref returns a pointer's element type; otherwise it returns typ.
+func deref(typ types.Type) types.Type {
+	if p, ok := typ.Underlying().(*types.Pointer); ok {
+		return p.Elem()
+	}
+	return typ
+}
+
+// fprintf prints to w a message of the form "location: message\n"
+// where location is derived from pos.
+//
+// pos must be one of:
+//    - a token.Pos, denoting a position
+//    - an ast.Node, denoting an interval
+//    - anything with a Pos() method:
+//         ssa.Member, ssa.Value, ssa.Instruction, types.Object, pointer.Label, etc.
+//    - a QueryPos, denoting the extent of the user's query.
+//    - nil, meaning no position at all.
+//
+// The output format is is compatible with the 'gnu'
+// compilation-error-regexp in Emacs' compilation mode.
+// TODO(adonovan): support other editors.
+//
+func fprintf(w io.Writer, fset *token.FileSet, pos interface{}, format string, args ...interface{}) {
+	var start, end token.Pos
+	switch pos := pos.(type) {
+	case ast.Node:
+		start = pos.Pos()
+		end = pos.End()
+	case token.Pos:
+		start = pos
+		end = start
+	case interface {
+		Pos() token.Pos
+	}:
+		start = pos.Pos()
+		end = start
+	case *queryPos:
+		start = pos.start
+		end = pos.end
+	case nil:
+		// no-op
+	default:
+		panic(fmt.Sprintf("invalid pos: %T", pos))
+	}
+
+	if sp := fset.Position(start); start == end {
+		// (prints "-: " for token.NoPos)
+		fmt.Fprintf(w, "%s: ", sp)
+	} else {
+		ep := fset.Position(end)
+		// The -1 below is a concession to Emacs's broken use of
+		// inclusive (not half-open) intervals.
+		// Other editors may not want it.
+		// TODO(adonovan): add an -editor=vim|emacs|acme|auto
+		// flag; auto uses EMACS=t / VIM=... / etc env vars.
+		fmt.Fprintf(w, "%s:%d.%d-%d.%d: ",
+			sp.Filename, sp.Line, sp.Column, ep.Line, ep.Column-1)
+	}
+	fmt.Fprintf(w, format, args...)
+	io.WriteString(w, "\n")
+}
diff --git a/oracle/oracle_test.go b/oracle/oracle_test.go
new file mode 100644
index 0000000..0dd1cdc
--- /dev/null
+++ b/oracle/oracle_test.go
@@ -0,0 +1,272 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package oracle_test
+
+// This file defines a test framework for oracle queries.
+//
+// The files beneath testdata/src/main contain Go programs containing
+// query annotations of the form:
+//
+//   @verb id "select"
+//
+// where verb is the query mode (e.g. "callers"), id is a unique name
+// for this query, and "select" is a regular expression matching the
+// substring of the current line that is the query's input selection.
+//
+// The expected output for each query is provided in the accompanying
+// .golden file.
+//
+// (Location information is not included because it's too fragile to
+// display as text.  TODO(adonovan): think about how we can test its
+// correctness, since it is critical information.)
+//
+// Run this test with:
+// 	% go test golang.org/x/tools/oracle -update
+// to update the golden files.
+
+import (
+	"bytes"
+	"encoding/json"
+	"flag"
+	"fmt"
+	"go/build"
+	"go/parser"
+	"go/token"
+	"io"
+	"io/ioutil"
+	"os"
+	"os/exec"
+	"regexp"
+	"runtime"
+	"strconv"
+	"strings"
+	"testing"
+
+	"golang.org/x/tools/oracle"
+)
+
+var updateFlag = flag.Bool("update", false, "Update the golden files.")
+
+type query struct {
+	id       string         // unique id
+	verb     string         // query mode, e.g. "callees"
+	posn     token.Position // position of of query
+	filename string
+	queryPos string // value of -pos flag
+}
+
+func parseRegexp(text string) (*regexp.Regexp, error) {
+	pattern, err := strconv.Unquote(text)
+	if err != nil {
+		return nil, fmt.Errorf("can't unquote %s", text)
+	}
+	return regexp.Compile(pattern)
+}
+
+// parseQueries parses and returns the queries in the named file.
+func parseQueries(t *testing.T, filename string) []*query {
+	filedata, err := ioutil.ReadFile(filename)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	// Parse the file once to discover the test queries.
+	fset := token.NewFileSet()
+	f, err := parser.ParseFile(fset, filename, filedata, parser.ParseComments)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	lines := bytes.Split(filedata, []byte("\n"))
+
+	var queries []*query
+	queriesById := make(map[string]*query)
+
+	// Find all annotations of these forms:
+	expectRe := regexp.MustCompile(`@([a-z]+)\s+(\S+)\s+(\".*)$`) // @verb id "regexp"
+	for _, c := range f.Comments {
+		text := strings.TrimSpace(c.Text())
+		if text == "" || text[0] != '@' {
+			continue
+		}
+		posn := fset.Position(c.Pos())
+
+		// @verb id "regexp"
+		match := expectRe.FindStringSubmatch(text)
+		if match == nil {
+			t.Errorf("%s: ill-formed query: %s", posn, text)
+			continue
+		}
+
+		id := match[2]
+		if prev, ok := queriesById[id]; ok {
+			t.Errorf("%s: duplicate id %s", posn, id)
+			t.Errorf("%s: previously used here", prev.posn)
+			continue
+		}
+
+		q := &query{
+			id:       id,
+			verb:     match[1],
+			filename: filename,
+			posn:     posn,
+		}
+
+		if match[3] != `"nopos"` {
+			selectRe, err := parseRegexp(match[3])
+			if err != nil {
+				t.Errorf("%s: %s", posn, err)
+				continue
+			}
+
+			// Find text of the current line, sans query.
+			// (Queries must be // not /**/ comments.)
+			line := lines[posn.Line-1][:posn.Column-1]
+
+			// Apply regexp to current line to find input selection.
+			loc := selectRe.FindIndex(line)
+			if loc == nil {
+				t.Errorf("%s: selection pattern %s doesn't match line %q",
+					posn, match[3], string(line))
+				continue
+			}
+
+			// Assumes ASCII. TODO(adonovan): test on UTF-8.
+			linestart := posn.Offset - (posn.Column - 1)
+
+			// Compute the file offsets.
+			q.queryPos = fmt.Sprintf("%s:#%d,#%d",
+				filename, linestart+loc[0], linestart+loc[1])
+		}
+
+		queries = append(queries, q)
+		queriesById[id] = q
+	}
+
+	// Return the slice, not map, for deterministic iteration.
+	return queries
+}
+
+// WriteResult writes res (-format=plain) to w, stripping file locations.
+func WriteResult(w io.Writer, q *oracle.Query) {
+	capture := new(bytes.Buffer) // capture standard output
+	q.WriteTo(capture)
+	for _, line := range strings.Split(capture.String(), "\n") {
+		// Remove a "file:line: " prefix.
+		if i := strings.Index(line, ": "); i >= 0 {
+			line = line[i+2:]
+		}
+		fmt.Fprintf(w, "%s\n", line)
+	}
+}
+
+// doQuery poses query q to the oracle and writes its response and
+// error (if any) to out.
+func doQuery(out io.Writer, q *query, useJson bool) {
+	fmt.Fprintf(out, "-------- @%s %s --------\n", q.verb, q.id)
+
+	var buildContext = build.Default
+	buildContext.GOPATH = "testdata"
+	query := oracle.Query{
+		Mode:       q.verb,
+		Pos:        q.queryPos,
+		Build:      &buildContext,
+		Scope:      []string{q.filename},
+		Reflection: true,
+	}
+	if err := oracle.Run(&query); err != nil {
+		fmt.Fprintf(out, "\nError: %s\n", err)
+		return
+	}
+
+	if useJson {
+		// JSON output
+		b, err := json.MarshalIndent(query.Serial(), "", "\t")
+		if err != nil {
+			fmt.Fprintf(out, "JSON error: %s\n", err.Error())
+			return
+		}
+		out.Write(b)
+		fmt.Fprintln(out)
+	} else {
+		// "plain" (compiler diagnostic format) output
+		WriteResult(out, &query)
+	}
+}
+
+func TestOracle(t *testing.T) {
+	switch runtime.GOOS {
+	case "android":
+		t.Skipf("skipping test on %q (no testdata dir)", runtime.GOOS)
+	case "windows":
+		t.Skipf("skipping test on %q (no /usr/bin/diff)", runtime.GOOS)
+	}
+
+	for _, filename := range []string{
+		"testdata/src/calls/main.go",
+		"testdata/src/describe/main.go",
+		"testdata/src/freevars/main.go",
+		"testdata/src/implements/main.go",
+		"testdata/src/implements-methods/main.go",
+		"testdata/src/imports/main.go",
+		"testdata/src/peers/main.go",
+		"testdata/src/pointsto/main.go",
+		"testdata/src/referrers/main.go",
+		"testdata/src/reflection/main.go",
+		"testdata/src/what/main.go",
+		"testdata/src/whicherrs/main.go",
+		// JSON:
+		// TODO(adonovan): most of these are very similar; combine them.
+		"testdata/src/calls-json/main.go",
+		"testdata/src/peers-json/main.go",
+		"testdata/src/describe-json/main.go",
+		"testdata/src/implements-json/main.go",
+		"testdata/src/implements-methods-json/main.go",
+		"testdata/src/pointsto-json/main.go",
+		"testdata/src/referrers-json/main.go",
+		"testdata/src/what-json/main.go",
+	} {
+		useJson := strings.Contains(filename, "-json/")
+		queries := parseQueries(t, filename)
+		golden := filename + "lden"
+		got := filename + "t"
+		gotfh, err := os.Create(got)
+		if err != nil {
+			t.Errorf("Create(%s) failed: %s", got, err)
+			continue
+		}
+		defer gotfh.Close()
+		defer os.Remove(got)
+
+		// Run the oracle on each query, redirecting its output
+		// and error (if any) to the foo.got file.
+		for _, q := range queries {
+			doQuery(gotfh, q, useJson)
+		}
+
+		// Compare foo.got with foo.golden.
+		var cmd *exec.Cmd
+		switch runtime.GOOS {
+		case "plan9":
+			cmd = exec.Command("/bin/diff", "-c", golden, got)
+		default:
+			cmd = exec.Command("/usr/bin/diff", "-u", golden, got)
+		}
+		buf := new(bytes.Buffer)
+		cmd.Stdout = buf
+		cmd.Stderr = os.Stderr
+		if err := cmd.Run(); err != nil {
+			t.Errorf("Oracle tests for %s failed: %s.\n%s\n",
+				filename, err, buf)
+
+			if *updateFlag {
+				t.Logf("Updating %s...", golden)
+				if err := exec.Command("/bin/cp", got, golden).Run(); err != nil {
+					t.Errorf("Update failed: %s", err)
+				}
+			}
+		}
+	}
+}
diff --git a/oracle/peers.go b/oracle/peers.go
new file mode 100644
index 0000000..9c2a497
--- /dev/null
+++ b/oracle/peers.go
@@ -0,0 +1,252 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package oracle
+
+import (
+	"fmt"
+	"go/ast"
+	"go/token"
+	"sort"
+
+	"golang.org/x/tools/go/loader"
+	"golang.org/x/tools/go/ssa"
+	"golang.org/x/tools/go/ssa/ssautil"
+	"golang.org/x/tools/go/types"
+	"golang.org/x/tools/oracle/serial"
+)
+
+// peers enumerates, for a given channel send (or receive) operation,
+// the set of possible receives (or sends) that correspond to it.
+//
+// TODO(adonovan): support reflect.{Select,Recv,Send,Close}.
+// TODO(adonovan): permit the user to query based on a MakeChan (not send/recv),
+// or the implicit receive in "for v := range ch".
+func peers(q *Query) error {
+	lconf := loader.Config{Build: q.Build}
+
+	if err := setPTAScope(&lconf, q.Scope); err != nil {
+		return err
+	}
+
+	// Load/parse/type-check the program.
+	lprog, err := lconf.Load()
+	if err != nil {
+		return err
+	}
+	q.Fset = lprog.Fset
+
+	qpos, err := parseQueryPos(lprog, q.Pos, false)
+	if err != nil {
+		return err
+	}
+
+	prog := ssautil.CreateProgram(lprog, ssa.GlobalDebug)
+
+	ptaConfig, err := setupPTA(prog, lprog, q.PTALog, q.Reflection)
+	if err != nil {
+		return err
+	}
+
+	opPos := findOp(qpos)
+	if opPos == token.NoPos {
+		return fmt.Errorf("there is no channel operation here")
+	}
+
+	// Defer SSA construction till after errors are reported.
+	prog.BuildAll()
+
+	var queryOp chanOp // the originating send or receive operation
+	var ops []chanOp   // all sends/receives of opposite direction
+
+	// Look at all channel operations in the whole ssa.Program.
+	// Build a list of those of same type as the query.
+	allFuncs := ssautil.AllFunctions(prog)
+	for fn := range allFuncs {
+		for _, b := range fn.Blocks {
+			for _, instr := range b.Instrs {
+				for _, op := range chanOps(instr) {
+					ops = append(ops, op)
+					if op.pos == opPos {
+						queryOp = op // we found the query op
+					}
+				}
+			}
+		}
+	}
+	if queryOp.ch == nil {
+		return fmt.Errorf("ssa.Instruction for send/receive not found")
+	}
+
+	// Discard operations of wrong channel element type.
+	// Build set of channel ssa.Values as query to pointer analysis.
+	// We compare channels by element types, not channel types, to
+	// ignore both directionality and type names.
+	queryType := queryOp.ch.Type()
+	queryElemType := queryType.Underlying().(*types.Chan).Elem()
+	ptaConfig.AddQuery(queryOp.ch)
+	i := 0
+	for _, op := range ops {
+		if types.Identical(op.ch.Type().Underlying().(*types.Chan).Elem(), queryElemType) {
+			ptaConfig.AddQuery(op.ch)
+			ops[i] = op
+			i++
+		}
+	}
+	ops = ops[:i]
+
+	// Run the pointer analysis.
+	ptares := ptrAnalysis(ptaConfig)
+
+	// Find the points-to set.
+	queryChanPtr := ptares.Queries[queryOp.ch]
+
+	// Ascertain which make(chan) labels the query's channel can alias.
+	var makes []token.Pos
+	for _, label := range queryChanPtr.PointsTo().Labels() {
+		makes = append(makes, label.Pos())
+	}
+	sort.Sort(byPos(makes))
+
+	// Ascertain which channel operations can alias the same make(chan) labels.
+	var sends, receives, closes []token.Pos
+	for _, op := range ops {
+		if ptr, ok := ptares.Queries[op.ch]; ok && ptr.MayAlias(queryChanPtr) {
+			switch op.dir {
+			case types.SendOnly:
+				sends = append(sends, op.pos)
+			case types.RecvOnly:
+				receives = append(receives, op.pos)
+			case types.SendRecv:
+				closes = append(closes, op.pos)
+			}
+		}
+	}
+	sort.Sort(byPos(sends))
+	sort.Sort(byPos(receives))
+	sort.Sort(byPos(closes))
+
+	q.result = &peersResult{
+		queryPos:  opPos,
+		queryType: queryType,
+		makes:     makes,
+		sends:     sends,
+		receives:  receives,
+		closes:    closes,
+	}
+	return nil
+}
+
+// findOp returns the position of the enclosing send/receive/close op.
+// For send and receive operations, this is the position of the <- token;
+// for close operations, it's the Lparen of the function call.
+//
+// TODO(adonovan): handle implicit receive operations from 'for...range chan' statements.
+func findOp(qpos *queryPos) token.Pos {
+	for _, n := range qpos.path {
+		switch n := n.(type) {
+		case *ast.UnaryExpr:
+			if n.Op == token.ARROW {
+				return n.OpPos
+			}
+		case *ast.SendStmt:
+			return n.Arrow
+		case *ast.CallExpr:
+			// close function call can only exist as a direct identifier
+			if close, ok := unparen(n.Fun).(*ast.Ident); ok {
+				if b, ok := qpos.info.Info.Uses[close].(*types.Builtin); ok && b.Name() == "close" {
+					return n.Lparen
+				}
+			}
+		}
+	}
+	return token.NoPos
+}
+
+// chanOp abstracts an ssa.Send, ssa.Unop(ARROW), or a SelectState.
+type chanOp struct {
+	ch  ssa.Value
+	dir types.ChanDir // SendOnly=send, RecvOnly=recv, SendRecv=close
+	pos token.Pos
+}
+
+// chanOps returns a slice of all the channel operations in the instruction.
+func chanOps(instr ssa.Instruction) []chanOp {
+	// TODO(adonovan): handle calls to reflect.{Select,Recv,Send,Close} too.
+	var ops []chanOp
+	switch instr := instr.(type) {
+	case *ssa.UnOp:
+		if instr.Op == token.ARROW {
+			ops = append(ops, chanOp{instr.X, types.RecvOnly, instr.Pos()})
+		}
+	case *ssa.Send:
+		ops = append(ops, chanOp{instr.Chan, types.SendOnly, instr.Pos()})
+	case *ssa.Select:
+		for _, st := range instr.States {
+			ops = append(ops, chanOp{st.Chan, st.Dir, st.Pos})
+		}
+	case ssa.CallInstruction:
+		cc := instr.Common()
+		if b, ok := cc.Value.(*ssa.Builtin); ok && b.Name() == "close" {
+			ops = append(ops, chanOp{cc.Args[0], types.SendRecv, cc.Pos()})
+		}
+	}
+	return ops
+}
+
+type peersResult struct {
+	queryPos                       token.Pos   // of queried channel op
+	queryType                      types.Type  // type of queried channel
+	makes, sends, receives, closes []token.Pos // positions of aliased makechan/send/receive/close instrs
+}
+
+func (r *peersResult) display(printf printfFunc) {
+	if len(r.makes) == 0 {
+		printf(r.queryPos, "This channel can't point to anything.")
+		return
+	}
+	printf(r.queryPos, "This channel of type %s may be:", r.queryType)
+	for _, alloc := range r.makes {
+		printf(alloc, "\tallocated here")
+	}
+	for _, send := range r.sends {
+		printf(send, "\tsent to, here")
+	}
+	for _, receive := range r.receives {
+		printf(receive, "\treceived from, here")
+	}
+	for _, clos := range r.closes {
+		printf(clos, "\tclosed, here")
+	}
+}
+
+func (r *peersResult) toSerial(res *serial.Result, fset *token.FileSet) {
+	peers := &serial.Peers{
+		Pos:  fset.Position(r.queryPos).String(),
+		Type: r.queryType.String(),
+	}
+	for _, alloc := range r.makes {
+		peers.Allocs = append(peers.Allocs, fset.Position(alloc).String())
+	}
+	for _, send := range r.sends {
+		peers.Sends = append(peers.Sends, fset.Position(send).String())
+	}
+	for _, receive := range r.receives {
+		peers.Receives = append(peers.Receives, fset.Position(receive).String())
+	}
+	for _, clos := range r.closes {
+		peers.Closes = append(peers.Closes, fset.Position(clos).String())
+	}
+	res.Peers = peers
+}
+
+// -------- utils --------
+
+// NB: byPos is not deterministic across packages since it depends on load order.
+// Use lessPos if the tests need it.
+type byPos []token.Pos
+
+func (p byPos) Len() int           { return len(p) }
+func (p byPos) Less(i, j int) bool { return p[i] < p[j] }
+func (p byPos) Swap(i, j int)      { p[i], p[j] = p[j], p[i] }
diff --git a/oracle/pointsto.go b/oracle/pointsto.go
new file mode 100644
index 0000000..d366dd3
--- /dev/null
+++ b/oracle/pointsto.go
@@ -0,0 +1,291 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package oracle
+
+import (
+	"fmt"
+	"go/ast"
+	"go/token"
+	"sort"
+
+	"golang.org/x/tools/go/ast/astutil"
+	"golang.org/x/tools/go/loader"
+	"golang.org/x/tools/go/pointer"
+	"golang.org/x/tools/go/ssa"
+	"golang.org/x/tools/go/ssa/ssautil"
+	"golang.org/x/tools/go/types"
+	"golang.org/x/tools/oracle/serial"
+)
+
+// pointsto runs the pointer analysis on the selected expression,
+// and reports its points-to set (for a pointer-like expression)
+// or its dynamic types (for an interface, reflect.Value, or
+// reflect.Type expression) and their points-to sets.
+//
+// All printed sets are sorted to ensure determinism.
+//
+func pointsto(q *Query) error {
+	lconf := loader.Config{Build: q.Build}
+
+	if err := setPTAScope(&lconf, q.Scope); err != nil {
+		return err
+	}
+
+	// Load/parse/type-check the program.
+	lprog, err := lconf.Load()
+	if err != nil {
+		return err
+	}
+	q.Fset = lprog.Fset
+
+	qpos, err := parseQueryPos(lprog, q.Pos, true) // needs exact pos
+	if err != nil {
+		return err
+	}
+
+	prog := ssautil.CreateProgram(lprog, ssa.GlobalDebug)
+
+	ptaConfig, err := setupPTA(prog, lprog, q.PTALog, q.Reflection)
+	if err != nil {
+		return err
+	}
+
+	path, action := findInterestingNode(qpos.info, qpos.path)
+	if action != actionExpr {
+		return fmt.Errorf("pointer analysis wants an expression; got %s",
+			astutil.NodeDescription(qpos.path[0]))
+	}
+
+	var expr ast.Expr
+	var obj types.Object
+	switch n := path[0].(type) {
+	case *ast.ValueSpec:
+		// ambiguous ValueSpec containing multiple names
+		return fmt.Errorf("multiple value specification")
+	case *ast.Ident:
+		obj = qpos.info.ObjectOf(n)
+		expr = n
+	case ast.Expr:
+		expr = n
+	default:
+		// TODO(adonovan): is this reachable?
+		return fmt.Errorf("unexpected AST for expr: %T", n)
+	}
+
+	// Reject non-pointerlike types (includes all constants---except nil).
+	// TODO(adonovan): reject nil too.
+	typ := qpos.info.TypeOf(expr)
+	if !pointer.CanPoint(typ) {
+		return fmt.Errorf("pointer analysis wants an expression of reference type; got %s", typ)
+	}
+
+	// Determine the ssa.Value for the expression.
+	var value ssa.Value
+	var isAddr bool
+	if obj != nil {
+		// def/ref of func/var object
+		value, isAddr, err = ssaValueForIdent(prog, qpos.info, obj, path)
+	} else {
+		value, isAddr, err = ssaValueForExpr(prog, qpos.info, path)
+	}
+	if err != nil {
+		return err // e.g. trivially dead code
+	}
+
+	// Defer SSA construction till after errors are reported.
+	prog.BuildAll()
+
+	// Run the pointer analysis.
+	ptrs, err := runPTA(ptaConfig, value, isAddr)
+	if err != nil {
+		return err // e.g. analytically unreachable
+	}
+
+	q.result = &pointstoResult{
+		qpos: qpos,
+		typ:  typ,
+		ptrs: ptrs,
+	}
+	return nil
+}
+
+// ssaValueForIdent returns the ssa.Value for the ast.Ident whose path
+// to the root of the AST is path.  isAddr reports whether the
+// ssa.Value is the address denoted by the ast.Ident, not its value.
+//
+func ssaValueForIdent(prog *ssa.Program, qinfo *loader.PackageInfo, obj types.Object, path []ast.Node) (value ssa.Value, isAddr bool, err error) {
+	switch obj := obj.(type) {
+	case *types.Var:
+		pkg := prog.Package(qinfo.Pkg)
+		pkg.Build()
+		if v, addr := prog.VarValue(obj, pkg, path); v != nil {
+			return v, addr, nil
+		}
+		return nil, false, fmt.Errorf("can't locate SSA Value for var %s", obj.Name())
+
+	case *types.Func:
+		fn := prog.FuncValue(obj)
+		if fn == nil {
+			return nil, false, fmt.Errorf("%s is an interface method", obj)
+		}
+		// TODO(adonovan): there's no point running PTA on a *Func ident.
+		// Eliminate this feature.
+		return fn, false, nil
+	}
+	panic(obj)
+}
+
+// ssaValueForExpr returns the ssa.Value of the non-ast.Ident
+// expression whose path to the root of the AST is path.
+//
+func ssaValueForExpr(prog *ssa.Program, qinfo *loader.PackageInfo, path []ast.Node) (value ssa.Value, isAddr bool, err error) {
+	pkg := prog.Package(qinfo.Pkg)
+	pkg.SetDebugMode(true)
+	pkg.Build()
+
+	fn := ssa.EnclosingFunction(pkg, path)
+	if fn == nil {
+		return nil, false, fmt.Errorf("no SSA function built for this location (dead code?)")
+	}
+
+	if v, addr := fn.ValueForExpr(path[0].(ast.Expr)); v != nil {
+		return v, addr, nil
+	}
+
+	return nil, false, fmt.Errorf("can't locate SSA Value for expression in %s", fn)
+}
+
+// runPTA runs the pointer analysis of the selected SSA value or address.
+func runPTA(conf *pointer.Config, v ssa.Value, isAddr bool) (ptrs []pointerResult, err error) {
+	T := v.Type()
+	if isAddr {
+		conf.AddIndirectQuery(v)
+		T = deref(T)
+	} else {
+		conf.AddQuery(v)
+	}
+	ptares := ptrAnalysis(conf)
+
+	var ptr pointer.Pointer
+	if isAddr {
+		ptr = ptares.IndirectQueries[v]
+	} else {
+		ptr = ptares.Queries[v]
+	}
+	if ptr == (pointer.Pointer{}) {
+		return nil, fmt.Errorf("pointer analysis did not find expression (dead code?)")
+	}
+	pts := ptr.PointsTo()
+
+	if pointer.CanHaveDynamicTypes(T) {
+		// Show concrete types for interface/reflect.Value expression.
+		if concs := pts.DynamicTypes(); concs.Len() > 0 {
+			concs.Iterate(func(conc types.Type, pta interface{}) {
+				labels := pta.(pointer.PointsToSet).Labels()
+				sort.Sort(byPosAndString(labels)) // to ensure determinism
+				ptrs = append(ptrs, pointerResult{conc, labels})
+			})
+		}
+	} else {
+		// Show labels for other expressions.
+		labels := pts.Labels()
+		sort.Sort(byPosAndString(labels)) // to ensure determinism
+		ptrs = append(ptrs, pointerResult{T, labels})
+	}
+	sort.Sort(byTypeString(ptrs)) // to ensure determinism
+	return ptrs, nil
+}
+
+type pointerResult struct {
+	typ    types.Type       // type of the pointer (always concrete)
+	labels []*pointer.Label // set of labels
+}
+
+type pointstoResult struct {
+	qpos *queryPos
+	typ  types.Type      // type of expression
+	ptrs []pointerResult // pointer info (typ is concrete => len==1)
+}
+
+func (r *pointstoResult) display(printf printfFunc) {
+	if pointer.CanHaveDynamicTypes(r.typ) {
+		// Show concrete types for interface, reflect.Type or
+		// reflect.Value expression.
+
+		if len(r.ptrs) > 0 {
+			printf(r.qpos, "this %s may contain these dynamic types:", r.qpos.typeString(r.typ))
+			for _, ptr := range r.ptrs {
+				var obj types.Object
+				if nt, ok := deref(ptr.typ).(*types.Named); ok {
+					obj = nt.Obj()
+				}
+				if len(ptr.labels) > 0 {
+					printf(obj, "\t%s, may point to:", r.qpos.typeString(ptr.typ))
+					printLabels(printf, ptr.labels, "\t\t")
+				} else {
+					printf(obj, "\t%s", r.qpos.typeString(ptr.typ))
+				}
+			}
+		} else {
+			printf(r.qpos, "this %s cannot contain any dynamic types.", r.typ)
+		}
+	} else {
+		// Show labels for other expressions.
+		if ptr := r.ptrs[0]; len(ptr.labels) > 0 {
+			printf(r.qpos, "this %s may point to these objects:",
+				r.qpos.typeString(r.typ))
+			printLabels(printf, ptr.labels, "\t")
+		} else {
+			printf(r.qpos, "this %s may not point to anything.",
+				r.qpos.typeString(r.typ))
+		}
+	}
+}
+
+func (r *pointstoResult) toSerial(res *serial.Result, fset *token.FileSet) {
+	var pts []serial.PointsTo
+	for _, ptr := range r.ptrs {
+		var namePos string
+		if nt, ok := deref(ptr.typ).(*types.Named); ok {
+			namePos = fset.Position(nt.Obj().Pos()).String()
+		}
+		var labels []serial.PointsToLabel
+		for _, l := range ptr.labels {
+			labels = append(labels, serial.PointsToLabel{
+				Pos:  fset.Position(l.Pos()).String(),
+				Desc: l.String(),
+			})
+		}
+		pts = append(pts, serial.PointsTo{
+			Type:    r.qpos.typeString(ptr.typ),
+			NamePos: namePos,
+			Labels:  labels,
+		})
+	}
+	res.PointsTo = pts
+}
+
+type byTypeString []pointerResult
+
+func (a byTypeString) Len() int           { return len(a) }
+func (a byTypeString) Less(i, j int) bool { return a[i].typ.String() < a[j].typ.String() }
+func (a byTypeString) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
+
+type byPosAndString []*pointer.Label
+
+func (a byPosAndString) Len() int { return len(a) }
+func (a byPosAndString) Less(i, j int) bool {
+	cmp := a[i].Pos() - a[j].Pos()
+	return cmp < 0 || (cmp == 0 && a[i].String() < a[j].String())
+}
+func (a byPosAndString) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
+
+func printLabels(printf printfFunc, labels []*pointer.Label, prefix string) {
+	// TODO(adonovan): due to context-sensitivity, many of these
+	// labels may differ only by context, which isn't apparent.
+	for _, label := range labels {
+		printf(label, "%s%s", prefix, label)
+	}
+}
diff --git a/oracle/pos.go b/oracle/pos.go
new file mode 100644
index 0000000..3c706f3
--- /dev/null
+++ b/oracle/pos.go
@@ -0,0 +1,143 @@
+package oracle
+
+// This file defines utilities for working with file positions.
+
+import (
+	"fmt"
+	"go/parser"
+	"go/token"
+	"os"
+	"path/filepath"
+	"strconv"
+	"strings"
+
+	"golang.org/x/tools/go/ast/astutil"
+)
+
+// parseOctothorpDecimal returns the numeric value if s matches "#%d",
+// otherwise -1.
+func parseOctothorpDecimal(s string) int {
+	if s != "" && s[0] == '#' {
+		if s, err := strconv.ParseInt(s[1:], 10, 32); err == nil {
+			return int(s)
+		}
+	}
+	return -1
+}
+
+// parsePosFlag parses a string of the form "file:pos" or
+// file:start,end" where pos, start, end match #%d and represent byte
+// offsets, and returns its components.
+//
+// (Numbers without a '#' prefix are reserved for future use,
+// e.g. to indicate line/column positions.)
+//
+func parsePosFlag(posFlag string) (filename string, startOffset, endOffset int, err error) {
+	if posFlag == "" {
+		err = fmt.Errorf("no source position specified (-pos flag)")
+		return
+	}
+
+	colon := strings.LastIndex(posFlag, ":")
+	if colon < 0 {
+		err = fmt.Errorf("invalid source position -pos=%q", posFlag)
+		return
+	}
+	filename, offset := posFlag[:colon], posFlag[colon+1:]
+	startOffset = -1
+	endOffset = -1
+	if hyphen := strings.Index(offset, ","); hyphen < 0 {
+		// e.g. "foo.go:#123"
+		startOffset = parseOctothorpDecimal(offset)
+		endOffset = startOffset
+	} else {
+		// e.g. "foo.go:#123,#456"
+		startOffset = parseOctothorpDecimal(offset[:hyphen])
+		endOffset = parseOctothorpDecimal(offset[hyphen+1:])
+	}
+	if startOffset < 0 || endOffset < 0 {
+		err = fmt.Errorf("invalid -pos offset %q", offset)
+		return
+	}
+	return
+}
+
+// findQueryPos searches fset for filename and translates the
+// specified file-relative byte offsets into token.Pos form.  It
+// returns an error if the file was not found or the offsets were out
+// of bounds.
+//
+func findQueryPos(fset *token.FileSet, filename string, startOffset, endOffset int) (start, end token.Pos, err error) {
+	var file *token.File
+	fset.Iterate(func(f *token.File) bool {
+		if sameFile(filename, f.Name()) {
+			// (f.Name() is absolute)
+			file = f
+			return false // done
+		}
+		return true // continue
+	})
+	if file == nil {
+		err = fmt.Errorf("couldn't find file containing position")
+		return
+	}
+
+	// Range check [start..end], inclusive of both end-points.
+
+	if 0 <= startOffset && startOffset <= file.Size() {
+		start = file.Pos(int(startOffset))
+	} else {
+		err = fmt.Errorf("start position is beyond end of file")
+		return
+	}
+
+	if 0 <= endOffset && endOffset <= file.Size() {
+		end = file.Pos(int(endOffset))
+	} else {
+		err = fmt.Errorf("end position is beyond end of file")
+		return
+	}
+
+	return
+}
+
+// sameFile returns true if x and y have the same basename and denote
+// the same file.
+//
+func sameFile(x, y string) bool {
+	if filepath.Base(x) == filepath.Base(y) { // (optimisation)
+		if xi, err := os.Stat(x); err == nil {
+			if yi, err := os.Stat(y); err == nil {
+				return os.SameFile(xi, yi)
+			}
+		}
+	}
+	return false
+}
+
+// fastQueryPos parses the -pos flag and returns a QueryPos.
+// It parses only a single file, and does not run the type checker.
+func fastQueryPos(posFlag string) (*queryPos, error) {
+	filename, startOffset, endOffset, err := parsePosFlag(posFlag)
+	if err != nil {
+		return nil, err
+	}
+
+	fset := token.NewFileSet()
+	f, err := parser.ParseFile(fset, filename, nil, 0)
+	if err != nil {
+		return nil, err
+	}
+
+	start, end, err := findQueryPos(fset, filename, startOffset, endOffset)
+	if err != nil {
+		return nil, err
+	}
+
+	path, exact := astutil.PathEnclosingInterval(f, start, end)
+	if path == nil {
+		return nil, fmt.Errorf("no syntax here")
+	}
+
+	return &queryPos{fset, start, end, path, exact, nil}, nil
+}
diff --git a/oracle/referrers.go b/oracle/referrers.go
new file mode 100644
index 0000000..7383d1f
--- /dev/null
+++ b/oracle/referrers.go
@@ -0,0 +1,225 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package oracle
+
+import (
+	"bytes"
+	"fmt"
+	"go/ast"
+	"go/token"
+	"io/ioutil"
+	"sort"
+
+	"golang.org/x/tools/go/loader"
+	"golang.org/x/tools/go/types"
+	"golang.org/x/tools/oracle/serial"
+	"golang.org/x/tools/refactor/importgraph"
+)
+
+// Referrers reports all identifiers that resolve to the same object
+// as the queried identifier, within any package in the analysis scope.
+func referrers(q *Query) error {
+	lconf := loader.Config{Build: q.Build}
+	allowErrors(&lconf)
+
+	if err := importQueryPackage(q.Pos, &lconf); err != nil {
+		return err
+	}
+
+	var id *ast.Ident
+	var obj types.Object
+	var lprog *loader.Program
+	var pass2 bool
+	var qpos *queryPos
+	for {
+		// Load/parse/type-check the program.
+		var err error
+		lprog, err = lconf.Load()
+		if err != nil {
+			return err
+		}
+		q.Fset = lprog.Fset
+
+		qpos, err = parseQueryPos(lprog, q.Pos, false)
+		if err != nil {
+			return err
+		}
+
+		id, _ = qpos.path[0].(*ast.Ident)
+		if id == nil {
+			return fmt.Errorf("no identifier here")
+		}
+
+		obj = qpos.info.ObjectOf(id)
+		if obj == nil {
+			// Happens for y in "switch y := x.(type)",
+			// the package declaration,
+			// and unresolved identifiers.
+			if _, ok := qpos.path[1].(*ast.File); ok { // package decl?
+				pkg := qpos.info.Pkg
+				obj = types.NewPkgName(id.Pos(), pkg, pkg.Name(), pkg)
+			} else {
+				return fmt.Errorf("no object for identifier: %T", qpos.path[1])
+			}
+		}
+
+		if pass2 {
+			break
+		}
+
+		// If the identifier is exported, we must load all packages that
+		// depend transitively upon the package that defines it.
+		// Treat PkgNames as exported, even though they're lowercase.
+		if _, isPkg := obj.(*types.PkgName); !(isPkg || obj.Exported()) {
+			break // not exported
+		}
+
+		// Scan the workspace and build the import graph.
+		// Ignore broken packages.
+		_, rev, _ := importgraph.Build(q.Build)
+
+		// Re-load the larger program.
+		// Create a new file set so that ...
+		// External test packages are never imported,
+		// so they will never appear in the graph.
+		// (We must reset the Config here, not just reset the Fset field.)
+		lconf = loader.Config{
+			Fset:  token.NewFileSet(),
+			Build: q.Build,
+		}
+		allowErrors(&lconf)
+		for path := range rev.Search(obj.Pkg().Path()) {
+			lconf.ImportWithTests(path)
+		}
+		pass2 = true
+	}
+
+	// Iterate over all go/types' Uses facts for the entire program.
+	var refs []*ast.Ident
+	for _, info := range lprog.AllPackages {
+		for id2, obj2 := range info.Uses {
+			if sameObj(obj, obj2) {
+				refs = append(refs, id2)
+			}
+		}
+	}
+	sort.Sort(byNamePos{q.Fset, refs})
+
+	q.result = &referrersResult{
+		qpos:  qpos,
+		query: id,
+		obj:   obj,
+		refs:  refs,
+	}
+	return nil
+}
+
+// same reports whether x and y are identical, or both are PkgNames
+// that import the same Package.
+//
+func sameObj(x, y types.Object) bool {
+	if x == y {
+		return true
+	}
+	if x, ok := x.(*types.PkgName); ok {
+		if y, ok := y.(*types.PkgName); ok {
+			return x.Imported() == y.Imported()
+		}
+	}
+	return false
+}
+
+// -------- utils --------
+
+// An deterministic ordering for token.Pos that doesn't
+// depend on the order in which packages were loaded.
+func lessPos(fset *token.FileSet, x, y token.Pos) bool {
+	fx := fset.File(x)
+	fy := fset.File(y)
+	if fx != fy {
+		return fx.Name() < fy.Name()
+	}
+	return x < y
+}
+
+type byNamePos struct {
+	fset *token.FileSet
+	ids  []*ast.Ident
+}
+
+func (p byNamePos) Len() int      { return len(p.ids) }
+func (p byNamePos) Swap(i, j int) { p.ids[i], p.ids[j] = p.ids[j], p.ids[i] }
+func (p byNamePos) Less(i, j int) bool {
+	return lessPos(p.fset, p.ids[i].NamePos, p.ids[j].NamePos)
+}
+
+type referrersResult struct {
+	qpos  *queryPos
+	query *ast.Ident   // identifier of query
+	obj   types.Object // object it denotes
+	refs  []*ast.Ident // set of all other references to it
+}
+
+func (r *referrersResult) display(printf printfFunc) {
+	printf(r.obj, "%d references to %s", len(r.refs), r.qpos.objectString(r.obj))
+
+	// Show referring lines, like grep.
+	type fileinfo struct {
+		refs     []*ast.Ident
+		linenums []int       // line number of refs[i]
+		data     chan []byte // file contents
+	}
+	var fileinfos []*fileinfo
+	fileinfosByName := make(map[string]*fileinfo)
+
+	// First pass: start the file reads concurrently.
+	for _, ref := range r.refs {
+		posn := r.qpos.fset.Position(ref.Pos())
+		fi := fileinfosByName[posn.Filename]
+		if fi == nil {
+			fi = &fileinfo{data: make(chan []byte)}
+			fileinfosByName[posn.Filename] = fi
+			fileinfos = append(fileinfos, fi)
+
+			// First request for this file:
+			// start asynchronous read.
+			go func() {
+				content, err := ioutil.ReadFile(posn.Filename)
+				if err != nil {
+					content = []byte(fmt.Sprintf("error: %v", err))
+				}
+				fi.data <- content
+			}()
+		}
+		fi.refs = append(fi.refs, ref)
+		fi.linenums = append(fi.linenums, posn.Line)
+	}
+
+	// Second pass: print refs in original order.
+	// One line may have several refs at different columns.
+	for _, fi := range fileinfos {
+		content := <-fi.data // wait for I/O completion
+		lines := bytes.Split(content, []byte("\n"))
+		for i, ref := range fi.refs {
+			printf(ref, "%s", lines[fi.linenums[i]-1])
+		}
+	}
+}
+
+// TODO(adonovan): encode extent, not just Pos info, in Serial form.
+
+func (r *referrersResult) toSerial(res *serial.Result, fset *token.FileSet) {
+	referrers := &serial.Referrers{
+		Pos:  fset.Position(r.query.Pos()).String(),
+		Desc: r.obj.String(),
+	}
+	if pos := r.obj.Pos(); pos != token.NoPos { // Package objects have no Pos()
+		referrers.ObjPos = fset.Position(pos).String()
+	}
+	for _, ref := range r.refs {
+		referrers.Refs = append(referrers.Refs, fset.Position(ref.NamePos).String())
+	}
+	res.Referrers = referrers
+}
diff --git a/oracle/serial/serial.go b/oracle/serial/serial.go
new file mode 100644
index 0000000..65f0822
--- /dev/null
+++ b/oracle/serial/serial.go
@@ -0,0 +1,258 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package serial defines the oracle's schema for structured data
+// serialization using JSON, XML, etc.
+package serial
+
+// All 'pos' strings are of the form "file:line:col".
+// TODO(adonovan): improve performance by sharing filename strings.
+// TODO(adonovan): improve precision by providing the start/end
+// interval when available.
+//
+// TODO(adonovan): consider richer encodings of types, functions,
+// methods, etc.
+
+// A Peers is the result of a 'peers' query.
+// If Allocs is empty, the selected channel can't point to anything.
+type Peers struct {
+	Pos      string   `json:"pos"`                // location of the selected channel op (<-)
+	Type     string   `json:"type"`               // type of the selected channel
+	Allocs   []string `json:"allocs,omitempty"`   // locations of aliased make(chan) ops
+	Sends    []string `json:"sends,omitempty"`    // locations of aliased ch<-x ops
+	Receives []string `json:"receives,omitempty"` // locations of aliased <-ch ops
+	Closes   []string `json:"closes,omitempty"`   // locations of aliased close(ch) ops
+}
+
+// A Referrers is the result of a 'referrers' query.
+type Referrers struct {
+	Pos    string   `json:"pos"`              // location of the query reference
+	ObjPos string   `json:"objpos,omitempty"` // location of the definition
+	Desc   string   `json:"desc"`             // description of the denoted object
+	Refs   []string `json:"refs,omitempty"`   // locations of all references
+}
+
+// A Definition is the result of a 'definition' query.
+type Definition struct {
+	ObjPos string `json:"objpos,omitempty"` // location of the definition
+	Desc   string `json:"desc"`             // description of the denoted object
+}
+
+type CalleesItem struct {
+	Name string `json:"name"` // full name of called function
+	Pos  string `json:"pos"`  // location of called function
+}
+
+// A Callees is the result of a 'callees' query.
+//
+// Callees is nonempty unless the call was a dynamic call on a
+// provably nil func or interface value.
+type Callees struct {
+	Pos     string         `json:"pos"`               // location of selected call site
+	Desc    string         `json:"desc"`              // description of call site
+	Callees []*CalleesItem `json:"callees,omitempty"` // set of possible call targets
+}
+
+// A Caller is one element of the slice returned by a 'callers' query.
+// (Callstack also contains a similar slice.)
+//
+// The root of the callgraph has an unspecified "Caller" string.
+type Caller struct {
+	Pos    string `json:"pos,omitempty"` // location of the calling function
+	Desc   string `json:"desc"`          // description of call site
+	Caller string `json:"caller"`        // full name of calling function
+}
+
+// A CallStack is the result of a 'callstack' query.
+// It indicates an arbitrary path from the root of the callgraph to
+// the query function.
+//
+// If the Callers slice is empty, the function was unreachable in this
+// analysis scope.
+type CallStack struct {
+	Pos     string   `json:"pos"`     // location of the selected function
+	Target  string   `json:"target"`  // the selected function
+	Callers []Caller `json:"callers"` // enclosing calls, innermost first.
+}
+
+// A FreeVar is one element of the slice returned by a 'freevars'
+// query.  Each one identifies an expression referencing a local
+// identifier defined outside the selected region.
+type FreeVar struct {
+	Pos  string `json:"pos"`  // location of the identifier's definition
+	Kind string `json:"kind"` // one of {var,func,type,const,label}
+	Ref  string `json:"ref"`  // referring expression (e.g. "x" or "x.y.z")
+	Type string `json:"type"` // type of the expression
+}
+
+// An Implements contains the result of an 'implements' query.
+// It describes the queried type, the set of named non-empty interface
+// types to which it is assignable, and the set of named/*named types
+// (concrete or non-empty interface) which may be assigned to it.
+//
+type Implements struct {
+	T                 ImplementsType   `json:"type,omitempty"`    // the queried type
+	AssignableTo      []ImplementsType `json:"to,omitempty"`      // types assignable to T
+	AssignableFrom    []ImplementsType `json:"from,omitempty"`    // interface types assignable from T
+	AssignableFromPtr []ImplementsType `json:"fromptr,omitempty"` // interface types assignable only from *T
+
+	// The following fields are set only if the query was a method.
+	// Assignable{To,From,FromPtr}Method[i] is the corresponding
+	// method of type Assignable{To,From,FromPtr}[i], or blank
+	// {"",""} if that type lacks the method.
+	Method                  *DescribeMethod  `json:"method,omitempty"` //  the queried method
+	AssignableToMethod      []DescribeMethod `json:"to_method,omitempty"`
+	AssignableFromMethod    []DescribeMethod `json:"from_method,omitempty"`
+	AssignableFromPtrMethod []DescribeMethod `json:"fromptr_method,omitempty"`
+}
+
+// An ImplementsType describes a single type as part of an 'implements' query.
+type ImplementsType struct {
+	Name string `json:"name"` // full name of the type
+	Pos  string `json:"pos"`  // location of its definition
+	Kind string `json:"kind"` // "basic", "array", etc
+}
+
+// A SyntaxNode is one element of a stack of enclosing syntax nodes in
+// a "what" query.
+type SyntaxNode struct {
+	Description string `json:"desc"`  // description of syntax tree
+	Start       int    `json:"start"` // start byte offset, 0-based
+	End         int    `json:"end"`   // end byte offset
+}
+
+// A What is the result of the "what" query, which quickly identifies
+// the selection, parsing only a single file.  It is intended for use
+// in low-latency GUIs.
+type What struct {
+	Enclosing  []SyntaxNode `json:"enclosing"`            // enclosing nodes of syntax tree
+	Modes      []string     `json:"modes"`                // query modes enabled for this selection.
+	SrcDir     string       `json:"srcdir,omitempty"`     // $GOROOT src directory containing queried package
+	ImportPath string       `json:"importpath,omitempty"` // import path of queried package
+}
+
+// A PointsToLabel describes a pointer analysis label.
+//
+// A "label" is an object that may be pointed to by a pointer, map,
+// channel, 'func', slice or interface.  Labels include:
+//    - functions
+//    - globals
+//    - arrays created by literals (e.g. []byte("foo")) and conversions ([]byte(s))
+//    - stack- and heap-allocated variables (including composite literals)
+//    - arrays allocated by append()
+//    - channels, maps and arrays created by make()
+//    - and their subelements, e.g. "alloc.y[*].z"
+//
+type PointsToLabel struct {
+	Pos  string `json:"pos"`  // location of syntax that allocated the object
+	Desc string `json:"desc"` // description of the label
+}
+
+// A PointsTo is one element of the result of a 'pointsto' query on an
+// expression.  It describes a single pointer: its type and the set of
+// "labels" it points to.
+//
+// If the pointer is of interface type, it will have one PTS entry
+// describing each concrete type that it may contain.  For each
+// concrete type that is a pointer, the PTS entry describes the labels
+// it may point to.  The same is true for reflect.Values, except the
+// dynamic types needn't be concrete.
+//
+type PointsTo struct {
+	Type    string          `json:"type"`              // (concrete) type of the pointer
+	NamePos string          `json:"namepos,omitempty"` // location of type defn, if Named
+	Labels  []PointsToLabel `json:"labels,omitempty"`  // pointed-to objects
+}
+
+// A DescribeValue is the additional result of a 'describe' query
+// if the selection indicates a value or expression.
+type DescribeValue struct {
+	Type   string `json:"type"`             // type of the expression
+	Value  string `json:"value,omitempty"`  // value of the expression, if constant
+	ObjPos string `json:"objpos,omitempty"` // location of the definition, if an Ident
+}
+
+type DescribeMethod struct {
+	Name string `json:"name"` // method name, as defined by types.Selection.String()
+	Pos  string `json:"pos"`  // location of the method's definition
+}
+
+// A DescribeType is the additional result of a 'describe' query
+// if the selection indicates a type.
+type DescribeType struct {
+	Type    string           `json:"type"`              // the string form of the type
+	NamePos string           `json:"namepos,omitempty"` // location of definition of type, if named
+	NameDef string           `json:"namedef,omitempty"` // underlying definition of type, if named
+	Methods []DescribeMethod `json:"methods,omitempty"` // methods of the type
+}
+
+type DescribeMember struct {
+	Name    string           `json:"name"`              // name of member
+	Type    string           `json:"type,omitempty"`    // type of member (underlying, if 'type')
+	Value   string           `json:"value,omitempty"`   // value of member (if 'const')
+	Pos     string           `json:"pos"`               // location of definition of member
+	Kind    string           `json:"kind"`              // one of {var,const,func,type}
+	Methods []DescribeMethod `json:"methods,omitempty"` // methods (if member is a type)
+}
+
+// A DescribePackage is the additional result of a 'describe' if
+// the selection indicates a package.
+type DescribePackage struct {
+	Path    string            `json:"path"`              // import path of the package
+	Members []*DescribeMember `json:"members,omitempty"` // accessible members of the package
+}
+
+// A Describe is the result of a 'describe' query.
+// It may contain an element describing the selected semantic entity
+// in detail.
+type Describe struct {
+	Desc   string `json:"desc"`             // description of the selected syntax node
+	Pos    string `json:"pos"`              // location of the selected syntax node
+	Detail string `json:"detail,omitempty"` // one of {package, type, value}, or "".
+
+	// At most one of the following fields is populated:
+	// the one specified by 'detail'.
+	Package *DescribePackage `json:"package,omitempty"`
+	Type    *DescribeType    `json:"type,omitempty"`
+	Value   *DescribeValue   `json:"value,omitempty"`
+}
+
+// A WhichErrs is the result of a 'whicherrs' query.
+// It contains the position of the queried error and the possible globals,
+// constants, and types it may point to.
+type WhichErrs struct {
+	ErrPos    string          `json:"errpos,omitempty"`    // location of queried error
+	Globals   []string        `json:"globals,omitempty"`   // locations of globals
+	Constants []string        `json:"constants,omitempty"` // locations of constants
+	Types     []WhichErrsType `json:"types,omitempty"`     // Types
+}
+
+type WhichErrsType struct {
+	Type     string `json:"type,omitempty"`
+	Position string `json:"position,omitempty"`
+}
+
+// A Result is the common result of any oracle query.
+// It contains a query-specific result element.
+//
+// TODO(adonovan): perhaps include other info such as: analysis scope,
+// raw query position, stack of ast nodes, query package, etc.
+type Result struct {
+	Mode string `json:"mode"` // mode of the query
+
+	// Exactly one of the following fields is populated:
+	// the one specified by 'mode'.
+	Callees    *Callees    `json:"callees,omitempty"`
+	Callers    []Caller    `json:"callers,omitempty"`
+	Callstack  *CallStack  `json:"callstack,omitempty"`
+	Definition *Definition `json:"definition,omitempty"`
+	Describe   *Describe   `json:"describe,omitempty"`
+	Freevars   []*FreeVar  `json:"freevars,omitempty"`
+	Implements *Implements `json:"implements,omitempty"`
+	Peers      *Peers      `json:"peers,omitempty"`
+	PointsTo   []PointsTo  `json:"pointsto,omitempty"`
+	Referrers  *Referrers  `json:"referrers,omitempty"`
+	What       *What       `json:"what,omitempty"`
+	WhichErrs  *WhichErrs  `json:"whicherrs,omitempty"`
+}
diff --git a/oracle/testdata/src/calls-json/main.go b/oracle/testdata/src/calls-json/main.go
new file mode 100644
index 0000000..1c7a6c9
--- /dev/null
+++ b/oracle/testdata/src/calls-json/main.go
@@ -0,0 +1,16 @@
+package main
+
+// Tests of call-graph queries, -format=json.
+// See go.tools/oracle/oracle_test.go for explanation.
+// See calls-json.golden for expected query results.
+
+func call(f func()) {
+	f() // @callees @callees-f "f"
+}
+
+func main() {
+	call(func() {
+		// @callers callers-main.anon "^"
+		// @callstack callstack-main.anon "^"
+	})
+}
diff --git a/oracle/testdata/src/calls-json/main.golden b/oracle/testdata/src/calls-json/main.golden
new file mode 100644
index 0000000..f5eced6
--- /dev/null
+++ b/oracle/testdata/src/calls-json/main.golden
@@ -0,0 +1,34 @@
+-------- @callees @callees-f --------
+{
+	"mode": "callees",
+	"callees": {
+		"pos": "testdata/src/calls-json/main.go:8:3",
+		"desc": "dynamic function call",
+		"callees": [
+			{
+				"name": "main.main$1",
+				"pos": "testdata/src/calls-json/main.go:12:7"
+			}
+		]
+	}
+}
+-------- @callstack callstack-main.anon --------
+{
+	"mode": "callstack",
+	"callstack": {
+		"pos": "testdata/src/calls-json/main.go:12:7",
+		"target": "main.main$1",
+		"callers": [
+			{
+				"pos": "testdata/src/calls-json/main.go:8:3",
+				"desc": "dynamic function call",
+				"caller": "main.call"
+			},
+			{
+				"pos": "testdata/src/calls-json/main.go:12:6",
+				"desc": "static function call",
+				"caller": "main.main"
+			}
+		]
+	}
+}
diff --git a/oracle/testdata/src/calls/main.go b/oracle/testdata/src/calls/main.go
new file mode 100644
index 0000000..54bb895
--- /dev/null
+++ b/oracle/testdata/src/calls/main.go
@@ -0,0 +1,118 @@
+package main
+
+import (
+	"fmt"
+)
+
+// Tests of call-graph queries.
+// See go.tools/oracle/oracle_test.go for explanation.
+// See calls.golden for expected query results.
+
+func A(x *int) { // @pointsto pointsto-A-x "x"
+	// @callers callers-A "^"
+	// @callstack callstack-A "^"
+}
+
+func B(x *int) { // @pointsto pointsto-B-x "x"
+	// @callers callers-B "^"
+}
+
+func foo() {
+}
+
+// apply is not (yet) treated context-sensitively.
+func apply(f func(x *int), x *int) {
+	f(x) // @callees callees-apply "f"
+	// @callers callers-apply "^"
+}
+
+// store *is* treated context-sensitively,
+// so the points-to sets for pc, pd are precise.
+func store(ptr **int, value *int) {
+	*ptr = value
+	// @callers callers-store "^"
+}
+
+func call(f func() *int) {
+	// Result points to anon function.
+	f() // @pointsto pointsto-result-f "f"
+
+	// Target of call is anon function.
+	f() // @callees callees-main.call-f "f"
+
+	// @callers callers-main.call "^"
+}
+
+func main() {
+	var a, b int
+	go apply(A, &a) // @callees callees-main-apply1 "app"
+	defer apply(B, &b)
+
+	var c, d int
+	var pc, pd *int // @pointsto pointsto-pc "pc"
+	store(&pc, &c)
+	store(&pd, &d)
+	_ = pd // @pointsto pointsto-pd "pd"
+
+	call(func() *int {
+		// We are called twice from main.call
+		// @callers callers-main.anon "^"
+		return &a
+	})
+
+	// Errors
+	_ = "no function call here"   // @callees callees-err-no-call "no"
+	print("builtin")              // @callees callees-err-builtin "builtin"
+	_ = string("type conversion") // @callees callees-err-conversion "str"
+	call(nil)                     // @callees callees-err-bad-selection "call\\(nil"
+	if false {
+		main() // @callees callees-err-deadcode1 "main"
+	}
+	var nilFunc func()
+	nilFunc() // @callees callees-err-nil-func "nilFunc"
+	var i interface {
+		f()
+	}
+	i.f() // @callees callees-err-nil-interface "i.f"
+
+	i = new(myint)
+	i.f() // @callees callees-not-a-wrapper "f"
+
+	// statically dispatched calls. Handled specially by callees, so test that they work.
+	foo()         // @callees callees-static-call "foo"
+	fmt.Println() // @callees callees-qualified-call "Println"
+	m := new(method)
+	m.f() // @callees callees-static-method-call "f"
+}
+
+type myint int
+
+func (myint) f() {
+	// @callers callers-not-a-wrapper "^"
+}
+
+type method int
+
+func (method) f() {
+}
+
+var dynamic = func() {}
+
+func deadcode() {
+	main() // @callees callees-err-deadcode2 "main"
+	// @callers callers-err-deadcode "^"
+	// @callstack callstack-err-deadcode "^"
+
+	// Within dead code, dynamic calls have no callees.
+	dynamic() // @callees callees-err-deadcode3 "dynamic"
+}
+
+// This code belongs to init.
+var global = 123 // @callers callers-global "global"
+
+// The package initializer may be called by other packages' inits, or
+// in this case, the root of the callgraph.  The source-level init functions
+// are in turn called by it.
+func init() {
+	// @callstack callstack-init "^"
+}
diff --git a/oracle/testdata/src/calls/main.golden b/oracle/testdata/src/calls/main.golden
new file mode 100644
index 0000000..b5e6547
--- /dev/null
+++ b/oracle/testdata/src/calls/main.golden
@@ -0,0 +1,121 @@
+-------- @pointsto pointsto-A-x --------
+this *int may point to these objects:
+	a
+	b
+
+-------- @callstack callstack-A --------
+Found a call path from root to main.A
+main.A
+dynamic function call from main.apply
+concurrent static function call from main.main
+
+-------- @pointsto pointsto-B-x --------
+this *int may point to these objects:
+	a
+	b
+
+-------- @callers callers-B --------
+main.B is called from these 1 sites:
+	dynamic function call from main.apply
+
+-------- @callees callees-apply --------
+this dynamic function call dispatches to:
+	main.A
+	main.B
+
+-------- @callers callers-apply --------
+main.apply is called from these 2 sites:
+	concurrent static function call from main.main
+	deferred static function call from main.main
+
+-------- @callers callers-store --------
+main.store is called from these 2 sites:
+	static function call from main.main
+	static function call from main.main
+
+-------- @pointsto pointsto-result-f --------
+this func() *int may point to these objects:
+	main.main$1
+
+-------- @callees callees-main.call-f --------
+this dynamic function call dispatches to:
+	main.main$1
+
+-------- @callers callers-main.call --------
+main.call is called from these 2 sites:
+	static function call from main.main
+	static function call from main.main
+
+-------- @callees callees-main-apply1 --------
+this static function call dispatches to:
+	main.apply
+
+-------- @pointsto pointsto-pc --------
+this *int may point to these objects:
+	c
+
+-------- @pointsto pointsto-pd --------
+this *int may point to these objects:
+	d
+
+-------- @callees callees-err-no-call --------
+
+Error: there is no function call here
+-------- @callees callees-err-builtin --------
+
+Error: this is a call to the built-in 'print' operator
+-------- @callees callees-err-conversion --------
+
+Error: this is a type conversion, not a function call
+-------- @callees callees-err-bad-selection --------
+
+Error: ambiguous selection within function call (or conversion)
+-------- @callees callees-err-deadcode1 --------
+this static function call dispatches to:
+	main.main
+
+-------- @callees callees-err-nil-func --------
+dynamic function call on nil value
+
+-------- @callees callees-err-nil-interface --------
+dynamic method call on nil value
+
+-------- @callees callees-not-a-wrapper --------
+this dynamic method call dispatches to:
+	(main.myint).f
+
+-------- @callees callees-static-call --------
+this static function call dispatches to:
+	main.foo
+
+-------- @callees callees-qualified-call --------
+this static function call dispatches to:
+	fmt.Println
+
+-------- @callees callees-static-method-call --------
+this static function call dispatches to:
+	(main.method).f
+
+-------- @callers callers-not-a-wrapper --------
+(main.myint).f is called from these 1 sites:
+	dynamic method call from main.main
+
+-------- @callees callees-err-deadcode2 --------
+this static function call dispatches to:
+	main.main
+
+-------- @callstack callstack-err-deadcode --------
+main.deadcode is unreachable in this analysis scope
+
+-------- @callees callees-err-deadcode3 --------
+
+Error: this call site is unreachable in this analysis
+-------- @callers callers-global --------
+main.init is called from these 1 sites:
+the root of the call graph
+
+-------- @callstack callstack-init --------
+Found a call path from root to main.init#1
+main.init#1
+static function call from main.init
+
diff --git a/oracle/testdata/src/describe-json/main.go b/oracle/testdata/src/describe-json/main.go
new file mode 100644
index 0000000..359c731
--- /dev/null
+++ b/oracle/testdata/src/describe-json/main.go
@@ -0,0 +1,29 @@
+package describe // @describe pkgdecl "describe"
+
+// Tests of 'describe' query, -format=json.
+// See go.tools/oracle/oracle_test.go for explanation.
+// See describe-json.golden for expected query results.
+
+func main() {
+	var s struct{ x [3]int }
+	p := &s.x[0] // @describe desc-val-p "p"
+	_ = p
+
+	var i I = C(0)
+	if i == nil {
+		i = new(D)
+	}
+	print(i) // @describe desc-val-i "\\bi\\b"
+
+	go main() // @describe desc-stmt "go"
+}
+
+type I interface {
+	f()
+}
+
+type C int // @describe desc-type-C "C"
+type D struct{}
+
+func (c C) f()  {}
+func (d *D) f() {}
diff --git a/oracle/testdata/src/describe-json/main.golden b/oracle/testdata/src/describe-json/main.golden
new file mode 100644
index 0000000..9d03661
--- /dev/null
+++ b/oracle/testdata/src/describe-json/main.golden
@@ -0,0 +1,111 @@
+-------- @describe pkgdecl --------
+{
+	"mode": "describe",
+	"describe": {
+		"desc": "definition of package \"describe-json\"",
+		"pos": "testdata/src/describe-json/main.go:1:9",
+		"detail": "package",
+		"package": {
+			"path": "describe-json",
+			"members": [
+				{
+					"name": "C",
+					"type": "int",
+					"pos": "testdata/src/describe-json/main.go:25:6",
+					"kind": "type",
+					"methods": [
+						{
+							"name": "method (C) f()",
+							"pos": "testdata/src/describe-json/main.go:28:12"
+						}
+					]
+				},
+				{
+					"name": "D",
+					"type": "struct{}",
+					"pos": "testdata/src/describe-json/main.go:26:6",
+					"kind": "type",
+					"methods": [
+						{
+							"name": "method (*D) f()",
+							"pos": "testdata/src/describe-json/main.go:29:13"
+						}
+					]
+				},
+				{
+					"name": "I",
+					"type": "interface{f()}",
+					"pos": "testdata/src/describe-json/main.go:21:6",
+					"kind": "type",
+					"methods": [
+						{
+							"name": "method (I) f()",
+							"pos": "testdata/src/describe-json/main.go:22:2"
+						}
+					]
+				},
+				{
+					"name": "main",
+					"type": "func()",
+					"pos": "testdata/src/describe-json/main.go:7:6",
+					"kind": "func"
+				}
+			]
+		}
+	}
+}
+-------- @describe desc-val-p --------
+{
+	"mode": "describe",
+	"describe": {
+		"desc": "identifier",
+		"pos": "testdata/src/describe-json/main.go:9:2",
+		"detail": "value",
+		"value": {
+			"type": "*int",
+			"objpos": "testdata/src/describe-json/main.go:9:2"
+		}
+	}
+}
+-------- @describe desc-val-i --------
+{
+	"mode": "describe",
+	"describe": {
+		"desc": "identifier",
+		"pos": "testdata/src/describe-json/main.go:16:8",
+		"detail": "value",
+		"value": {
+			"type": "I",
+			"objpos": "testdata/src/describe-json/main.go:12:6"
+		}
+	}
+}
+-------- @describe desc-stmt --------
+{
+	"mode": "describe",
+	"describe": {
+		"desc": "go statement",
+		"pos": "testdata/src/describe-json/main.go:18:2",
+		"detail": "unknown"
+	}
+}
+-------- @describe desc-type-C --------
+{
+	"mode": "describe",
+	"describe": {
+		"desc": "definition of type C (size 8, align 8)",
+		"pos": "testdata/src/describe-json/main.go:25:6",
+		"detail": "type",
+		"type": {
+			"type": "C",
+			"namepos": "testdata/src/describe-json/main.go:25:6",
+			"namedef": "int",
+			"methods": [
+				{
+					"name": "method (C) f()",
+					"pos": "testdata/src/describe-json/main.go:28:12"
+				}
+			]
+		}
+	}
+}
diff --git a/oracle/testdata/src/describe/main.go b/oracle/testdata/src/describe/main.go
new file mode 100644
index 0000000..69e0a75
--- /dev/null
+++ b/oracle/testdata/src/describe/main.go
@@ -0,0 +1,87 @@
+package describe // @describe pkgdecl "describe"
+
+// Tests of 'describe' query.
+// See go.tools/oracle/oracle_test.go for explanation.
+// See describe.golden for expected query results.
+
+// TODO(adonovan): more coverage of the (extensive) logic.
+
+type cake float64 // @describe type-ref-builtin "float64"
+
+const c = iota // @describe const-ref-iota "iota"
+
+const pi = 3.141     // @describe const-def-pi "pi"
+const pie = cake(pi) // @describe const-def-pie "pie"
+const _ = pi         // @describe const-ref-pi "pi"
+
+var global = new(string) // NB: ssa.Global is indirect, i.e. **string
+
+func main() { // @describe func-def-main "main"
+	// func objects
+	_ = main   // @describe func-ref-main "main"
+	_ = (*C).f // @describe func-ref-*C.f "..C..f"
+	_ = D.f    // @describe func-ref-D.f "D.f"
+	_ = I.f    // @describe func-ref-I.f "I.f"
+	var d D    // @describe type-D "D"
+	var i I    // @describe type-I "I"
+	_ = d.f    // @describe func-ref-d.f "d.f"
+	_ = i.f    // @describe func-ref-i.f "i.f"
+
+	// var objects
+	anon := func() {
+		_ = d // @describe ref-lexical-d "d"
+	}
+	_ = anon   // @describe ref-anon "anon"
+	_ = global // @describe ref-global "global"
+
+	// SSA affords some local flow sensitivity.
+	var a, b int
+	var x = &a // @describe var-def-x-1 "x"
+	_ = x      // @describe var-ref-x-1 "x"
+	x = &b     // @describe var-def-x-2 "x"
+	_ = x      // @describe var-ref-x-2 "x"
+
+	i = new(C) // @describe var-ref-i-C "i"
+	if i != nil {
+		i = D{} // @describe var-ref-i-D "i"
+	}
+	print(i) // @describe var-ref-i "\\bi\\b"
+
+	// const objects
+	const localpi = 3.141     // @describe const-local-pi "localpi"
+	const localpie = cake(pi) // @describe const-local-pie "localpie"
+	const _ = localpi         // @describe const-ref-localpi "localpi"
+
+	// type objects
+	type T int      // @describe type-def-T "T"
+	var three T = 3 // @describe type-ref-T "T"
+	_ = three
+
+	print(1 + 2*3)        // @describe const-expr " 2.3"
+	print(real(1+2i) - 3) // @describe const-expr2 "real.*3"
+
+	m := map[string]*int{"a": &a}
+	mapval, _ := m["a"] // @describe map-lookup,ok "m..a.."
+	_ = mapval          // @describe mapval "mapval"
+	_ = m               // @describe m "m"
+
+	defer main() // @describe defer-stmt "defer"
+	go main()    // @describe go-stmt "go"
+
+	panic(3) // @describe builtin-ref-panic "panic"
+
+	var a2 int // @describe var-decl-stmt "var a2 int"
+	_ = a2
+	var _ int // @describe var-decl-stmt2 "var _ int"
+	var _ int // @describe var-def-blank "_"
+}
+
+type I interface { // @describe def-iface-I "I"
+	f() // @describe def-imethod-I.f "f"
+}
+
+type C int
+type D struct{}
+
+func (c *C) f() {}
+func (d D) f()  {}
diff --git a/oracle/testdata/src/describe/main.golden b/oracle/testdata/src/describe/main.golden
new file mode 100644
index 0000000..33d751a
--- /dev/null
+++ b/oracle/testdata/src/describe/main.golden
@@ -0,0 +1,171 @@
+-------- @describe pkgdecl --------
+definition of package "describe"
+	type  C      int
+		method (*C) f()
+	type  D      struct{}
+		method (D) f()
+	type  I      interface{f()}
+		method (I) f()
+	const c      untyped int = 0
+	type  cake   float64
+	var   global *string
+	func  main   func()
+	const pi     untyped float = 3141/1000
+	const pie    cake = 1768225803696341/562949953421312
+
+-------- @describe type-ref-builtin --------
+reference to built-in type float64
+
+-------- @describe const-ref-iota --------
+reference to const iota untyped int of constant value 0
+
+-------- @describe const-def-pi --------
+definition of const pi untyped float
+
+-------- @describe const-def-pie --------
+definition of const pie cake
+
+-------- @describe const-ref-pi --------
+reference to const pi untyped float of constant value 3141/1000
+defined here
+
+-------- @describe func-def-main --------
+definition of func main()
+
+-------- @describe func-ref-main --------
+reference to func main()
+defined here
+
+-------- @describe func-ref-*C.f --------
+reference to method func (*C).f()
+defined here
+
+-------- @describe func-ref-D.f --------
+reference to method func (D).f()
+defined here
+
+-------- @describe func-ref-I.f --------
+reference to interface method func (I).f()
+defined here
+
+-------- @describe type-D --------
+reference to type D (size 0, align 1)
+defined as struct{}
+Method set:
+	method (D) f()
+
+-------- @describe type-I --------
+reference to type I (size 16, align 8)
+defined as interface{f()}
+Method set:
+	method (I) f()
+
+-------- @describe func-ref-d.f --------
+reference to method func (D).f()
+defined here
+
+-------- @describe func-ref-i.f --------
+reference to interface method func (I).f()
+defined here
+
+-------- @describe ref-lexical-d --------
+reference to var d D
+defined here
+
+-------- @describe ref-anon --------
+reference to var anon func()
+defined here
+
+-------- @describe ref-global --------
+reference to var global *string
+defined here
+
+-------- @describe var-def-x-1 --------
+definition of var x *int
+
+-------- @describe var-ref-x-1 --------
+reference to var x *int
+defined here
+
+-------- @describe var-def-x-2 --------
+reference to var x *int
+defined here
+
+-------- @describe var-ref-x-2 --------
+reference to var x *int
+defined here
+
+-------- @describe var-ref-i-C --------
+reference to var i I
+defined here
+
+-------- @describe var-ref-i-D --------
+reference to var i I
+defined here
+
+-------- @describe var-ref-i --------
+reference to var i I
+defined here
+
+-------- @describe const-local-pi --------
+definition of const localpi untyped float
+
+-------- @describe const-local-pie --------
+definition of const localpie cake
+
+-------- @describe const-ref-localpi --------
+reference to const localpi untyped float of constant value 3141/1000
+defined here
+
+-------- @describe type-def-T --------
+definition of type T (size 8, align 8)
+No methods.
+
+-------- @describe type-ref-T --------
+reference to type T (size 8, align 8)
+defined as int
+No methods.
+
+-------- @describe const-expr --------
+binary * operation of constant value 6
+
+-------- @describe const-expr2 --------
+binary - operation of constant value -2
+
+-------- @describe map-lookup,ok --------
+index expression of type (*int, bool)
+
+-------- @describe mapval --------
+reference to var mapval *int
+defined here
+
+-------- @describe m --------
+reference to var m map[string]*int
+defined here
+
+-------- @describe defer-stmt --------
+defer statement
+
+-------- @describe go-stmt --------
+go statement
+
+-------- @describe builtin-ref-panic --------
+function call (or conversion) of type ()
+
+-------- @describe var-decl-stmt --------
+definition of var a2 int
+
+-------- @describe var-decl-stmt2 --------
+definition of var _ int
+
+-------- @describe var-def-blank --------
+definition of var _ int
+
+-------- @describe def-iface-I --------
+definition of type I (size 16, align 8)
+Method set:
+	method (I) f()
+
+-------- @describe def-imethod-I.f --------
+definition of interface method func (I).f()
+
diff --git a/oracle/testdata/src/freevars/main.go b/oracle/testdata/src/freevars/main.go
new file mode 100644
index 0000000..1ce0ae6
--- /dev/null
+++ b/oracle/testdata/src/freevars/main.go
@@ -0,0 +1,41 @@
+package main
+
+// Tests of 'freevars' query.
+// See go.tools/oracle/oracle_test.go for explanation.
+// See freevars.golden for expected query results.
+
+// TODO(adonovan): it's hard to test this query in a single line of gofmt'd code.
+
+type T struct {
+	a, b int
+}
+
+type S struct {
+	x int
+	t T
+}
+
+func f(int) {}
+
+func main() {
+	type C int
+	x := 1
+	const exp = 6
+	if y := 2; x+y+int(C(3)) != exp { // @freevars fv1 "if.*{"
+		panic("expected 6")
+	}
+
+	var s S
+
+	for x, y := range "foo" {
+		println(s.x + s.t.a + s.t.b + x + int(y)) // @freevars fv2 "print.*y."
+	}
+
+	f(x) // @freevars fv3 "f.x."
+
+	// TODO(adonovan): enable when go/types supports labels.
+loop: // #@freevars fv-def-label "loop:"
+	for {
+		break loop // #@freevars fv-ref-label "break loop"
+	}
+}
diff --git a/oracle/testdata/src/freevars/main.golden b/oracle/testdata/src/freevars/main.golden
new file mode 100644
index 0000000..b9eeab2
--- /dev/null
+++ b/oracle/testdata/src/freevars/main.golden
@@ -0,0 +1,18 @@
+-------- @freevars fv1 --------
+Free identifiers:
+type C
+const exp int
+var x int
+
+-------- @freevars fv2 --------
+Free identifiers:
+var s.t.a int
+var s.t.b int
+var s.x int
+var x int
+var y rune
+
+-------- @freevars fv3 --------
+Free identifiers:
+var x int
+
diff --git a/oracle/testdata/src/implements-json/main.go b/oracle/testdata/src/implements-json/main.go
new file mode 100644
index 0000000..d5f8102
--- /dev/null
+++ b/oracle/testdata/src/implements-json/main.go
@@ -0,0 +1,27 @@
+package main
+
+// Tests of 'implements' query, -output=json.
+// See go.tools/oracle/oracle_test.go for explanation.
+// See implements.golden for expected query results.
+
+func main() {
+}
+
+type E interface{} // @implements E "E"
+
+type F interface { // @implements F "F"
+	f()
+}
+
+type FG interface { // @implements FG "FG"
+	f()
+	g() []int // @implements slice "..int"
+}
+
+type C int // @implements C "C"
+type D struct{}
+
+func (c *C) f() {} // @implements starC ".C"
+func (d D) f()  {} // @implements D "D"
+
+func (d *D) g() []int { return nil } // @implements starD ".D"
diff --git a/oracle/testdata/src/implements-json/main.golden b/oracle/testdata/src/implements-json/main.golden
new file mode 100644
index 0000000..7e37f9e
--- /dev/null
+++ b/oracle/testdata/src/implements-json/main.golden
@@ -0,0 +1,159 @@
+-------- @implements E --------
+{
+	"mode": "implements",
+	"implements": {
+		"type": {
+			"name": "implements-json.E",
+			"pos": "testdata/src/implements-json/main.go:10:6",
+			"kind": "interface"
+		}
+	}
+}
+-------- @implements F --------
+{
+	"mode": "implements",
+	"implements": {
+		"type": {
+			"name": "implements-json.F",
+			"pos": "testdata/src/implements-json/main.go:12:6",
+			"kind": "interface"
+		},
+		"to": [
+			{
+				"name": "*implements-json.C",
+				"pos": "testdata/src/implements-json/main.go:21:6",
+				"kind": "pointer"
+			},
+			{
+				"name": "implements-json.D",
+				"pos": "testdata/src/implements-json/main.go:22:6",
+				"kind": "struct"
+			},
+			{
+				"name": "implements-json.FG",
+				"pos": "testdata/src/implements-json/main.go:16:6",
+				"kind": "interface"
+			}
+		]
+	}
+}
+-------- @implements FG --------
+{
+	"mode": "implements",
+	"implements": {
+		"type": {
+			"name": "implements-json.FG",
+			"pos": "testdata/src/implements-json/main.go:16:6",
+			"kind": "interface"
+		},
+		"to": [
+			{
+				"name": "*implements-json.D",
+				"pos": "testdata/src/implements-json/main.go:22:6",
+				"kind": "pointer"
+			}
+		],
+		"from": [
+			{
+				"name": "implements-json.F",
+				"pos": "testdata/src/implements-json/main.go:12:6",
+				"kind": "interface"
+			}
+		]
+	}
+}
+-------- @implements slice --------
+{
+	"mode": "implements",
+	"implements": {
+		"type": {
+			"name": "[]int",
+			"pos": "-",
+			"kind": "slice"
+		}
+	}
+}
+-------- @implements C --------
+{
+	"mode": "implements",
+	"implements": {
+		"type": {
+			"name": "implements-json.C",
+			"pos": "testdata/src/implements-json/main.go:21:6",
+			"kind": "basic"
+		},
+		"fromptr": [
+			{
+				"name": "implements-json.F",
+				"pos": "testdata/src/implements-json/main.go:12:6",
+				"kind": "interface"
+			}
+		]
+	}
+}
+-------- @implements starC --------
+{
+	"mode": "implements",
+	"implements": {
+		"type": {
+			"name": "*implements-json.C",
+			"pos": "testdata/src/implements-json/main.go:21:6",
+			"kind": "pointer"
+		},
+		"from": [
+			{
+				"name": "implements-json.F",
+				"pos": "testdata/src/implements-json/main.go:12:6",
+				"kind": "interface"
+			}
+		]
+	}
+}
+-------- @implements D --------
+{
+	"mode": "implements",
+	"implements": {
+		"type": {
+			"name": "implements-json.D",
+			"pos": "testdata/src/implements-json/main.go:22:6",
+			"kind": "struct"
+		},
+		"from": [
+			{
+				"name": "implements-json.F",
+				"pos": "testdata/src/implements-json/main.go:12:6",
+				"kind": "interface"
+			}
+		],
+		"fromptr": [
+			{
+				"name": "implements-json.FG",
+				"pos": "testdata/src/implements-json/main.go:16:6",
+				"kind": "interface"
+			}
+		]
+	}
+}
+-------- @implements starD --------
+{
+	"mode": "implements",
+	"implements": {
+		"type": {
+			"name": "*implements-json.D",
+			"pos": "testdata/src/implements-json/main.go:22:6",
+			"kind": "pointer"
+		},
+		"from": [
+			{
+				"name": "implements-json.F",
+				"pos": "testdata/src/implements-json/main.go:12:6",
+				"kind": "interface"
+			},
+			{
+				"name": "implements-json.FG",
+				"pos": "testdata/src/implements-json/main.go:16:6",
+				"kind": "interface"
+			}
+		]
+	}
+}
diff --git a/oracle/testdata/src/implements-methods-json/main.go b/oracle/testdata/src/implements-methods-json/main.go
new file mode 100644
index 0000000..6c5bbf4
--- /dev/null
+++ b/oracle/testdata/src/implements-methods-json/main.go
@@ -0,0 +1,37 @@
+package main
+
+// Tests of 'implements' query applied to methods, -output=json.
+// See go.tools/oracle/oracle_test.go for explanation.
+// See implements-methods.golden for expected query results.
+
+import _ "lib"
+
+func main() {
+}
+
+type F interface {
+	f() // @implements F.f "f"
+}
+
+type FG interface {
+	f()       // @implements FG.f "f"
+	g() []int // @implements FG.g "g"
+}
+
+type C int
+type D struct{}
+
+func (c *C) f() {} // @implements *C.f "f"
+func (d D) f()  {} // @implements D.f "f"
+
+func (d *D) g() []int { return nil } // @implements *D.g "g"
+
+type sorter []int
+
+func (sorter) Len() int           { return 0 } // @implements Len "Len"
+func (sorter) Less(i, j int) bool { return false }
+func (sorter) Swap(i, j int)      {}
+
+type I interface {
+	Method(*int) *int // @implements I.Method "Method"
+}
diff --git a/oracle/testdata/src/implements-methods-json/main.golden b/oracle/testdata/src/implements-methods-json/main.golden
new file mode 100644
index 0000000..fa117df
--- /dev/null
+++ b/oracle/testdata/src/implements-methods-json/main.golden
@@ -0,0 +1,290 @@
+-------- @implements F.f --------
+{
+	"mode": "implements",
+	"implements": {
+		"type": {
+			"name": "implements-methods-json.F",
+			"pos": "testdata/src/implements-methods-json/main.go:12:6",
+			"kind": "interface"
+		},
+		"to": [
+			{
+				"name": "*implements-methods-json.C",
+				"pos": "testdata/src/implements-methods-json/main.go:21:6",
+				"kind": "pointer"
+			},
+			{
+				"name": "implements-methods-json.D",
+				"pos": "testdata/src/implements-methods-json/main.go:22:6",
+				"kind": "struct"
+			},
+			{
+				"name": "implements-methods-json.FG",
+				"pos": "testdata/src/implements-methods-json/main.go:16:6",
+				"kind": "interface"
+			}
+		],
+		"method": {
+			"name": "func (F).f()",
+			"pos": "testdata/src/implements-methods-json/main.go:13:2"
+		},
+		"to_method": [
+			{
+				"name": "method (*C) f()",
+				"pos": "testdata/src/implements-methods-json/main.go:24:13"
+			},
+			{
+				"name": "method (D) f()",
+				"pos": "testdata/src/implements-methods-json/main.go:25:12"
+			},
+			{
+				"name": "method (FG) f()",
+				"pos": "testdata/src/implements-methods-json/main.go:17:2"
+			}
+		]
+	}
+}
+-------- @implements FG.f --------
+{
+	"mode": "implements",
+	"implements": {
+		"type": {
+			"name": "implements-methods-json.FG",
+			"pos": "testdata/src/implements-methods-json/main.go:16:6",
+			"kind": "interface"
+		},
+		"to": [
+			{
+				"name": "*implements-methods-json.D",
+				"pos": "testdata/src/implements-methods-json/main.go:22:6",
+				"kind": "pointer"
+			}
+		],
+		"from": [
+			{
+				"name": "implements-methods-json.F",
+				"pos": "testdata/src/implements-methods-json/main.go:12:6",
+				"kind": "interface"
+			}
+		],
+		"method": {
+			"name": "func (FG).f()",
+			"pos": "testdata/src/implements-methods-json/main.go:17:2"
+		},
+		"to_method": [
+			{
+				"name": "method (*D) f()",
+				"pos": "testdata/src/implements-methods-json/main.go:25:12"
+			}
+		],
+		"from_method": [
+			{
+				"name": "method (F) f()",
+				"pos": "testdata/src/implements-methods-json/main.go:13:2"
+			}
+		]
+	}
+}
+-------- @implements FG.g --------
+{
+	"mode": "implements",
+	"implements": {
+		"type": {
+			"name": "implements-methods-json.FG",
+			"pos": "testdata/src/implements-methods-json/main.go:16:6",
+			"kind": "interface"
+		},
+		"to": [
+			{
+				"name": "*implements-methods-json.D",
+				"pos": "testdata/src/implements-methods-json/main.go:22:6",
+				"kind": "pointer"
+			}
+		],
+		"from": [
+			{
+				"name": "implements-methods-json.F",
+				"pos": "testdata/src/implements-methods-json/main.go:12:6",
+				"kind": "interface"
+			}
+		],
+		"method": {
+			"name": "func (FG).g() []int",
+			"pos": "testdata/src/implements-methods-json/main.go:18:2"
+		},
+		"to_method": [
+			{
+				"name": "method (*D) g() []int",
+				"pos": "testdata/src/implements-methods-json/main.go:27:13"
+			}
+		],
+		"from_method": [
+			{
+				"name": "",
+				"pos": ""
+			}
+		]
+	}
+}
+-------- @implements *C.f --------
+{
+	"mode": "implements",
+	"implements": {
+		"type": {
+			"name": "*implements-methods-json.C",
+			"pos": "testdata/src/implements-methods-json/main.go:21:6",
+			"kind": "pointer"
+		},
+		"from": [
+			{
+				"name": "implements-methods-json.F",
+				"pos": "testdata/src/implements-methods-json/main.go:12:6",
+				"kind": "interface"
+			}
+		],
+		"method": {
+			"name": "func (*C).f()",
+			"pos": "testdata/src/implements-methods-json/main.go:24:13"
+		},
+		"from_method": [
+			{
+				"name": "method (F) f()",
+				"pos": "testdata/src/implements-methods-json/main.go:13:2"
+			}
+		]
+	}
+}
+-------- @implements D.f --------
+{
+	"mode": "implements",
+	"implements": {
+		"type": {
+			"name": "implements-methods-json.D",
+			"pos": "testdata/src/implements-methods-json/main.go:22:6",
+			"kind": "struct"
+		},
+		"from": [
+			{
+				"name": "implements-methods-json.F",
+				"pos": "testdata/src/implements-methods-json/main.go:12:6",
+				"kind": "interface"
+			}
+		],
+		"fromptr": [
+			{
+				"name": "implements-methods-json.FG",
+				"pos": "testdata/src/implements-methods-json/main.go:16:6",
+				"kind": "interface"
+			}
+		],
+		"method": {
+			"name": "func (D).f()",
+			"pos": "testdata/src/implements-methods-json/main.go:25:12"
+		},
+		"from_method": [
+			{
+				"name": "method (F) f()",
+				"pos": "testdata/src/implements-methods-json/main.go:13:2"
+			}
+		],
+		"fromptr_method": [
+			{
+				"name": "method (FG) f()",
+				"pos": "testdata/src/implements-methods-json/main.go:17:2"
+			}
+		]
+	}
+}
+-------- @implements *D.g --------
+{
+	"mode": "implements",
+	"implements": {
+		"type": {
+			"name": "*implements-methods-json.D",
+			"pos": "testdata/src/implements-methods-json/main.go:22:6",
+			"kind": "pointer"
+		},
+		"from": [
+			{
+				"name": "implements-methods-json.F",
+				"pos": "testdata/src/implements-methods-json/main.go:12:6",
+				"kind": "interface"
+			},
+			{
+				"name": "implements-methods-json.FG",
+				"pos": "testdata/src/implements-methods-json/main.go:16:6",
+				"kind": "interface"
+			}
+		],
+		"method": {
+			"name": "func (*D).g() []int",
+			"pos": "testdata/src/implements-methods-json/main.go:27:13"
+		},
+		"from_method": [
+			{
+				"name": "",
+				"pos": ""
+			},
+			{
+				"name": "method (FG) g() []int",
+				"pos": "testdata/src/implements-methods-json/main.go:18:2"
+			}
+		]
+	}
+}
+-------- @implements Len --------
+{
+	"mode": "implements",
+	"implements": {
+		"type": {
+			"name": "implements-methods-json.sorter",
+			"pos": "testdata/src/implements-methods-json/main.go:29:6",
+			"kind": "slice"
+		},
+		"from": [
+			{
+				"name": "lib.Sorter",
+				"pos": "testdata/src/lib/lib.go:16:6",
+				"kind": "interface"
+			}
+		],
+		"method": {
+			"name": "func (sorter).Len() int",
+			"pos": "testdata/src/implements-methods-json/main.go:31:15"
+		},
+		"from_method": [
+			{
+				"name": "method (lib.Sorter) Len() int",
+				"pos": "testdata/src/lib/lib.go:17:2"
+			}
+		]
+	}
+}
+-------- @implements I.Method --------
+{
+	"mode": "implements",
+	"implements": {
+		"type": {
+			"name": "implements-methods-json.I",
+			"pos": "testdata/src/implements-methods-json/main.go:35:6",
+			"kind": "interface"
+		},
+		"to": [
+			{
+				"name": "lib.Type",
+				"pos": "testdata/src/lib/lib.go:3:6",
+				"kind": "basic"
+			}
+		],
+		"method": {
+			"name": "func (I).Method(*int) *int",
+			"pos": "testdata/src/implements-methods-json/main.go:36:2"
+		},
+		"to_method": [
+			{
+				"name": "method (lib.Type) Method(x *int) *int",
+				"pos": "testdata/src/lib/lib.go:5:13"
+			}
+		]
+	}
+}
diff --git a/oracle/testdata/src/implements-methods/main.go b/oracle/testdata/src/implements-methods/main.go
new file mode 100644
index 0000000..a24854a
--- /dev/null
+++ b/oracle/testdata/src/implements-methods/main.go
@@ -0,0 +1,37 @@
+package main
+
+// Tests of 'implements' query applied to methods.
+// See go.tools/oracle/oracle_test.go for explanation.
+// See implements-methods.golden for expected query results.
+
+import _ "lib"
+
+func main() {
+}
+
+type F interface {
+	f() // @implements F.f "f"
+}
+
+type FG interface {
+	f()       // @implements FG.f "f"
+	g() []int // @implements FG.g "g"
+}
+
+type C int
+type D struct{}
+
+func (c *C) f() {} // @implements *C.f "f"
+func (d D) f()  {} // @implements D.f "f"
+
+func (d *D) g() []int { return nil } // @implements *D.g "g"
+
+type sorter []int
+
+func (sorter) Len() int           { return 0 } // @implements Len "Len"
+func (sorter) Less(i, j int) bool { return false }
+func (sorter) Swap(i, j int)      {}
+
+type I interface {
+	Method(*int) *int // @implements I.Method "Method"
+}
diff --git a/oracle/testdata/src/implements-methods/main.golden b/oracle/testdata/src/implements-methods/main.golden
new file mode 100644
index 0000000..bd591e8
--- /dev/null
+++ b/oracle/testdata/src/implements-methods/main.golden
@@ -0,0 +1,37 @@
+-------- @implements F.f --------
+abstract method func (F).f()
+	is implemented by method (*C).f
+	is implemented by method (D).f
+	is implemented by method (FG).f
+
+-------- @implements FG.f --------
+abstract method func (FG).f()
+	is implemented by method (*D).f
+	implements method (F).f
+
+-------- @implements FG.g --------
+abstract method func (FG).g() []int
+	is implemented by method (*D).g
+
+-------- @implements *C.f --------
+concrete method func (*C).f()
+	implements method (F).f
+
+-------- @implements D.f --------
+concrete method func (D).f()
+	implements method (F).f
+concrete method func (D).f()
+	implements method (FG).f
+
+-------- @implements *D.g --------
+concrete method func (*D).g() []int
+	implements method (FG).g
+
+-------- @implements Len --------
+concrete method func (sorter).Len() int
+	implements method (lib.Sorter).Len
+
+-------- @implements I.Method --------
+abstract method func (I).Method(*int) *int
+	is implemented by method (lib.Type).Method
+
diff --git a/oracle/testdata/src/implements/main.go b/oracle/testdata/src/implements/main.go
new file mode 100644
index 0000000..14a2f16
--- /dev/null
+++ b/oracle/testdata/src/implements/main.go
@@ -0,0 +1,39 @@
+package main
+
+// Tests of 'implements' query.
+// See go.tools/oracle/oracle_test.go for explanation.
+// See implements.golden for expected query results.
+
+import _ "lib"
+
+func main() {
+}
+
+type E interface{} // @implements E "E"
+
+type F interface { // @implements F "F"
+	f()
+}
+
+type FG interface { // @implements FG "FG"
+	f()
+	g() []int // @implements slice "..int"
+}
+
+type C int // @implements C "C"
+type D struct{}
+
+func (c *C) f() {} // @implements starC ".C"
+func (d D) f()  {} // @implements D "D"
+
+func (d *D) g() []int { return nil } // @implements starD ".D"
+
+type sorter []int // @implements sorter "sorter"
+
+func (sorter) Len() int           { return 0 }
+func (sorter) Less(i, j int) bool { return false }
+func (sorter) Swap(i, j int)      {}
+
+type I interface { // @implements I "I"
+	Method(*int) *int
+}
diff --git a/oracle/testdata/src/implements/main.golden b/oracle/testdata/src/implements/main.golden
new file mode 100644
index 0000000..ee00f3d
--- /dev/null
+++ b/oracle/testdata/src/implements/main.golden
@@ -0,0 +1,44 @@
+-------- @implements E --------
+empty interface type E
+
+-------- @implements F --------
+interface type F
+	is implemented by pointer type *C
+	is implemented by struct type D
+	is implemented by interface type FG
+
+-------- @implements FG --------
+interface type FG
+	is implemented by pointer type *D
+	implements F
+
+-------- @implements slice --------
+slice type []int implements only interface{}
+
+-------- @implements C --------
+pointer type *C
+	implements F
+
+-------- @implements starC --------
+pointer type *C
+	implements F
+
+-------- @implements D --------
+struct type D
+	implements F
+pointer type *D
+	implements FG
+
+-------- @implements starD --------
+pointer type *D
+	implements F
+	implements FG
+
+-------- @implements sorter --------
+slice type sorter
+	implements lib.Sorter
+
+-------- @implements I --------
+interface type I
+	is implemented by basic type lib.Type
+
diff --git a/oracle/testdata/src/imports/main.go b/oracle/testdata/src/imports/main.go
new file mode 100644
index 0000000..0f616ab
--- /dev/null
+++ b/oracle/testdata/src/imports/main.go
@@ -0,0 +1,29 @@
+package main
+
+import (
+	"hash/fnv" // @describe ref-pkg-import2 "fnv"
+	"lib"      // @describe ref-pkg-import "lib"
+)
+
+// Tests that import another package.  (To make the tests run quickly,
+// we avoid using imports in all the other tests.  Remember, each
+// query causes parsing and typechecking of the whole program.)
+//
+// See go.tools/oracle/oracle_test.go for explanation.
+// See imports.golden for expected query results.
+
+var a int
+
+func main() {
+	const c = lib.Const // @describe ref-const "Const"
+	lib.Func()          // @describe ref-func "Func"
+	lib.Var++           // @describe ref-var "Var"
+	var t lib.Type      // @describe ref-type "Type"
+	p := t.Method(&a)   // @describe ref-method "Method"
+
+	print(*p + 1) // @pointsto p "p "
+
+	var _ lib.Type // @describe ref-pkg "lib"
+
+	fnv.New32()
+}
diff --git a/oracle/testdata/src/imports/main.golden b/oracle/testdata/src/imports/main.golden
new file mode 100644
index 0000000..9144210
--- /dev/null
+++ b/oracle/testdata/src/imports/main.golden
@@ -0,0 +1,57 @@
+-------- @describe ref-pkg-import2 --------
+import of package "hash/fnv"
+	func  New32  func() hash.Hash32
+	func  New32a func() hash.Hash32
+	func  New64  func() hash.Hash64
+	func  New64a func() hash.Hash64
+
+-------- @describe ref-pkg-import --------
+import of package "lib"
+	const Const  untyped int = 3
+	func  Func   func()
+	type  Sorter interface{...}
+		method (Sorter) Len() int
+		method (Sorter) Less(i int, j int) bool
+		method (Sorter) Swap(i int, j int)
+	type  Type   int
+		method (Type) Method(x *int) *int
+	var   Var    int
+
+-------- @describe ref-const --------
+reference to const lib.Const untyped int
+defined here
+
+-------- @describe ref-func --------
+reference to func lib.Func()
+defined here
+
+-------- @describe ref-var --------
+reference to var lib.Var int
+defined here
+
+-------- @describe ref-type --------
+reference to type lib.Type (size 8, align 8)
+defined as int
+Method set:
+	method (lib.Type) Method(x *int) *int
+
+-------- @describe ref-method --------
+reference to method func (lib.Type).Method(x *int) *int
+defined here
+
+-------- @pointsto p --------
+this *int may point to these objects:
+	main.a
+
+-------- @describe ref-pkg --------
+reference to package "lib"
+	const Const  untyped int = 3
+	func  Func   func()
+	type  Sorter interface{...}
+		method (Sorter) Len() int
+		method (Sorter) Less(i int, j int) bool
+		method (Sorter) Swap(i int, j int)
+	type  Type   int
+		method (Type) Method(x *int) *int
+	var   Var    int
+
diff --git a/oracle/testdata/src/lib/lib.go b/oracle/testdata/src/lib/lib.go
new file mode 100644
index 0000000..9131c27
--- /dev/null
+++ b/oracle/testdata/src/lib/lib.go
@@ -0,0 +1,20 @@
+package lib
+
+type Type int
+
+func (Type) Method(x *int) *int {
+	return x
+}
+
+func Func() {
+}
+
+const Const = 3
+
+var Var = 0
+
+type Sorter interface {
+	Len() int
+	Less(i, j int) bool
+	Swap(i, j int)
+}
diff --git a/oracle/testdata/src/main/multi.go b/oracle/testdata/src/main/multi.go
new file mode 100644
index 0000000..8c650cd
--- /dev/null
+++ b/oracle/testdata/src/main/multi.go
@@ -0,0 +1,13 @@
+package main
+
+func g(x int) {
+}
+
+func f() {
+	x := 1
+	g(x) // "g(x)" is the selection for multiple queries
+}
+
+func main() {
+	f()
+}
diff --git a/oracle/testdata/src/peers-json/main.go b/oracle/testdata/src/peers-json/main.go
new file mode 100644
index 0000000..1df550b
--- /dev/null
+++ b/oracle/testdata/src/peers-json/main.go
@@ -0,0 +1,13 @@
+package main
+
+// Tests of channel 'peers' query, -format=json.
+// See go.tools/oracle/oracle_test.go for explanation.
+// See peers-json.golden for expected query results.
+
+func main() {
+	chA := make(chan *int)
+	<-chA
+	select {
+	case <-chA: // @peers peer-recv-chA "<-"
+	}
+}
diff --git a/oracle/testdata/src/peers-json/main.golden b/oracle/testdata/src/peers-json/main.golden
new file mode 100644
index 0000000..8c2d06c
--- /dev/null
+++ b/oracle/testdata/src/peers-json/main.golden
@@ -0,0 +1,15 @@
+-------- @peers peer-recv-chA --------
+{
+	"mode": "peers",
+	"peers": {
+		"pos": "testdata/src/peers-json/main.go:11:7",
+		"type": "chan *int",
+		"allocs": [
+			"testdata/src/peers-json/main.go:8:13"
+		],
+		"receives": [
+			"testdata/src/peers-json/main.go:9:2",
+			"testdata/src/peers-json/main.go:11:7"
+		]
+	}
+}
diff --git a/oracle/testdata/src/peers/main.go b/oracle/testdata/src/peers/main.go
new file mode 100644
index 0000000..a4cf91b
--- /dev/null
+++ b/oracle/testdata/src/peers/main.go
@@ -0,0 +1,52 @@
+package main
+
+// Tests of channel 'peers' query.
+// See go.tools/oracle/oracle_test.go for explanation.
+// See peers.golden for expected query results.
+
+var a2 int
+
+func main() {
+	chA := make(chan *int)
+	a1 := 1
+	chA <- &a1
+
+	chA2 := make(chan *int, 2)
+	if a2 == 0 {
+		chA = chA2
+	}
+
+	chB := make(chan *int)
+	b := 3
+	chB <- &b
+
+	<-chA  // @pointsto pointsto-chA "chA"
+	<-chA2 // @pointsto pointsto-chA2 "chA2"
+	<-chB  // @pointsto pointsto-chB "chB"
+
+	select {
+	case rA := <-chA: // @peers peer-recv-chA "<-"
+		_ = rA // @pointsto pointsto-rA "rA"
+	case rB := <-chB: // @peers peer-recv-chB "<-"
+		_ = rB // @pointsto pointsto-rB "rB"
+
+	case <-chA: // @peers peer-recv-chA' "<-"
+
+	case chA2 <- &a2: // @peers peer-send-chA' "<-"
+	}
+
+	for _ = range chA {
+	}
+
+	close(chA) // @peers peer-close-chA "chA"
+
+	chC := make(chan *int)
+	(close)(chC) // @peers peer-close-chC "chC"
+
+	close := func(ch chan *int) chan *int {
+		return ch
+	}
+
+	close(chC) <- &b // @peers peer-send-chC "chC"
+	<-close(chC)     // @peers peer-recv-chC "chC"
+}
diff --git a/oracle/testdata/src/peers/main.golden b/oracle/testdata/src/peers/main.golden
new file mode 100644
index 0000000..597a3c6
--- /dev/null
+++ b/oracle/testdata/src/peers/main.golden
@@ -0,0 +1,100 @@
+-------- @pointsto pointsto-chA --------
+this chan *int may point to these objects:
+	makechan
+	makechan
+
+-------- @pointsto pointsto-chA2 --------
+this chan *int may point to these objects:
+	makechan
+
+-------- @pointsto pointsto-chB --------
+this chan *int may point to these objects:
+	makechan
+
+-------- @peers peer-recv-chA --------
+This channel of type chan *int may be:
+	allocated here
+	allocated here
+	sent to, here
+	sent to, here
+	received from, here
+	received from, here
+	received from, here
+	received from, here
+	received from, here
+	closed, here
+
+-------- @pointsto pointsto-rA --------
+this *int may point to these objects:
+	main.a2
+	a1
+
+-------- @peers peer-recv-chB --------
+This channel of type chan *int may be:
+	allocated here
+	sent to, here
+	received from, here
+	received from, here
+
+-------- @pointsto pointsto-rB --------
+this *int may point to these objects:
+	b
+
+-------- @peers peer-recv-chA' --------
+This channel of type chan *int may be:
+	allocated here
+	allocated here
+	sent to, here
+	sent to, here
+	received from, here
+	received from, here
+	received from, here
+	received from, here
+	received from, here
+	closed, here
+
+-------- @peers peer-send-chA' --------
+This channel of type chan *int may be:
+	allocated here
+	sent to, here
+	received from, here
+	received from, here
+	received from, here
+	received from, here
+	received from, here
+	closed, here
+
+-------- @peers peer-close-chA --------
+This channel of type chan *int may be:
+	allocated here
+	allocated here
+	sent to, here
+	sent to, here
+	received from, here
+	received from, here
+	received from, here
+	received from, here
+	received from, here
+	closed, here
+
+-------- @peers peer-close-chC --------
+This channel of type chan *int may be:
+	allocated here
+	sent to, here
+	received from, here
+	closed, here
+
+-------- @peers peer-send-chC --------
+This channel of type chan *int may be:
+	allocated here
+	sent to, here
+	received from, here
+	closed, here
+
+-------- @peers peer-recv-chC --------
+This channel of type chan *int may be:
+	allocated here
+	sent to, here
+	received from, here
+	closed, here
+
diff --git a/oracle/testdata/src/pointsto-json/main.go b/oracle/testdata/src/pointsto-json/main.go
new file mode 100644
index 0000000..38f1148
--- /dev/null
+++ b/oracle/testdata/src/pointsto-json/main.go
@@ -0,0 +1,27 @@
+package main
+
+// Tests of 'pointsto' queries, -format=json.
+// See go.tools/oracle/oracle_test.go for explanation.
+// See pointsto-json.golden for expected query results.
+
+func main() { //
+	var s struct{ x [3]int }
+	p := &s.x[0] // @pointsto val-p "p"
+	_ = p
+
+	var i I = C(0)
+	if i == nil {
+		i = new(D)
+	}
+	print(i) // @pointsto val-i "\\bi\\b"
+}
+
+type I interface {
+	f()
+}
+
+type C int
+type D struct{}
+
+func (c C) f()  {}
+func (d *D) f() {}
diff --git a/oracle/testdata/src/pointsto-json/main.golden b/oracle/testdata/src/pointsto-json/main.golden
new file mode 100644
index 0000000..13ac1df
--- /dev/null
+++ b/oracle/testdata/src/pointsto-json/main.golden
@@ -0,0 +1,35 @@
+-------- @pointsto val-p --------
+{
+	"mode": "pointsto",
+	"pointsto": [
+		{
+			"type": "*int",
+			"labels": [
+				{
+					"pos": "testdata/src/pointsto-json/main.go:8:6",
+					"desc": "s.x[*]"
+				}
+			]
+		}
+	]
+}
+-------- @pointsto val-i --------
+{
+	"mode": "pointsto",
+	"pointsto": [
+		{
+			"type": "*D",
+			"namepos": "testdata/src/pointsto-json/main.go:24:6",
+			"labels": [
+				{
+					"pos": "testdata/src/pointsto-json/main.go:14:10",
+					"desc": "new"
+				}
+			]
+		},
+		{
+			"type": "C",
+			"namepos": "testdata/src/pointsto-json/main.go:23:6"
+		}
+	]
+}
diff --git a/oracle/testdata/src/pointsto/main.go b/oracle/testdata/src/pointsto/main.go
new file mode 100644
index 0000000..9064e46
--- /dev/null
+++ b/oracle/testdata/src/pointsto/main.go
@@ -0,0 +1,75 @@
+package main
+
+// Tests of 'pointsto' query.
+// See go.tools/oracle/oracle_test.go for explanation.
+// See pointsto.golden for expected query results.
+
+const pi = 3.141 // @pointsto const "pi"
+
+var global = new(string) // NB: ssa.Global is indirect, i.e. **string
+
+func main() {
+	livecode()
+
+	// func objects
+	_ = main   // @pointsto func-ref-main "main"
+	_ = (*C).f // @pointsto func-ref-*C.f "..C..f"
+	_ = D.f    // @pointsto func-ref-D.f "D.f"
+	_ = I.f    // @pointsto func-ref-I.f "I.f"
+	var d D
+	var i I
+	_ = d.f // @pointsto func-ref-d.f "d.f"
+	_ = i.f // @pointsto func-ref-i.f "i.f"
+
+	// var objects
+	anon := func() {
+		_ = d.f // @pointsto ref-lexical-d.f "d.f"
+	}
+	_ = anon   // @pointsto ref-anon "anon"
+	_ = global // @pointsto ref-global "global"
+
+	// SSA affords some local flow sensitivity.
+	var a, b int
+	var x = &a // @pointsto var-def-x-1 "x"
+	_ = x      // @pointsto var-ref-x-1 "x"
+	x = &b     // @pointsto var-def-x-2 "x"
+	_ = x      // @pointsto var-ref-x-2 "x"
+
+	i = new(C) // @pointsto var-ref-i-C "i"
+	if i != nil {
+		i = D{} // @pointsto var-ref-i-D "i"
+	}
+	print(i) // @pointsto var-ref-i "\\bi\\b"
+
+	m := map[string]*int{"a": &a}
+	mapval, _ := m["a"] // @pointsto map-lookup,ok "m..a.."
+	_ = mapval          // @pointsto mapval "mapval"
+	_ = m               // @pointsto m "m"
+
+	if false {
+		panic(3) // @pointsto builtin-panic "panic"
+	}
+
+	// NB: s.f is addressable per (*ssa.Program).VarValue,
+	// but our query concerns the object, not its address.
+	s := struct{ f interface{} }{f: make(chan bool)}
+	print(s.f) // @pointsto var-ref-s-f "s.f"
+}
+
+func livecode() {} // @pointsto func-live "livecode"
+
+func deadcode() { // @pointsto func-dead "deadcode"
+	// Pointer analysis can't run on dead code.
+	var b = new(int) // @pointsto b "b"
+	_ = b
+}
+
+type I interface {
+	f()
+}
+
+type C int
+type D struct{}
+
+func (c *C) f() {}
+func (d D) f()  {}
diff --git a/oracle/testdata/src/pointsto/main.golden b/oracle/testdata/src/pointsto/main.golden
new file mode 100644
index 0000000..fd68bda
--- /dev/null
+++ b/oracle/testdata/src/pointsto/main.golden
@@ -0,0 +1,96 @@
+-------- @pointsto const --------
+
+Error: pointer analysis wants an expression of reference type; got untyped float
+-------- @pointsto func-ref-main --------
+this func() may point to these objects:
+	main.main
+
+-------- @pointsto func-ref-*C.f --------
+this func() may point to these objects:
+	(*main.C).f
+
+-------- @pointsto func-ref-D.f --------
+this func() may point to these objects:
+	(main.D).f
+
+-------- @pointsto func-ref-I.f --------
+
+Error: func (main.I).f() is an interface method
+-------- @pointsto func-ref-d.f --------
+this func() may point to these objects:
+	(main.D).f
+
+-------- @pointsto func-ref-i.f --------
+
+Error: func (main.I).f() is an interface method
+-------- @pointsto ref-lexical-d.f --------
+this func() may point to these objects:
+	(main.D).f
+
+-------- @pointsto ref-anon --------
+this func() may point to these objects:
+	main.main$1
+
+-------- @pointsto ref-global --------
+this *string may point to these objects:
+	new
+
+-------- @pointsto var-def-x-1 --------
+this *int may point to these objects:
+	a
+
+-------- @pointsto var-ref-x-1 --------
+this *int may point to these objects:
+	a
+
+-------- @pointsto var-def-x-2 --------
+this *int may point to these objects:
+	b
+
+-------- @pointsto var-ref-x-2 --------
+this *int may point to these objects:
+	b
+
+-------- @pointsto var-ref-i-C --------
+this I may contain these dynamic types:
+	*C, may point to:
+		new
+
+-------- @pointsto var-ref-i-D --------
+this I may contain these dynamic types:
+	D
+
+-------- @pointsto var-ref-i --------
+this I may contain these dynamic types:
+	*C, may point to:
+		new
+	D
+
+-------- @pointsto map-lookup,ok --------
+
+Error: pointer analysis wants an expression of reference type; got (*int, bool)
+-------- @pointsto mapval --------
+this *int may point to these objects:
+	a
+
+-------- @pointsto m --------
+this map[string]*int may point to these objects:
+	makemap
+
+-------- @pointsto builtin-panic --------
+
+Error: pointer analysis wants an expression of reference type; got ()
+-------- @pointsto var-ref-s-f --------
+this interface{} may contain these dynamic types:
+	chan bool, may point to:
+		makechan
+
+-------- @pointsto func-live --------
+
+Error: pointer analysis did not find expression (dead code?)
+-------- @pointsto func-dead --------
+
+Error: pointer analysis did not find expression (dead code?)
+-------- @pointsto b --------
+
+Error: pointer analysis did not find expression (dead code?)
diff --git a/oracle/testdata/src/referrers-json/main.go b/oracle/testdata/src/referrers-json/main.go
new file mode 100644
index 0000000..f551ee0
--- /dev/null
+++ b/oracle/testdata/src/referrers-json/main.go
@@ -0,0 +1,24 @@
+package main
+
+// Tests of 'referrers' query.
+// See go.tools/oracle/oracle_test.go for explanation.
+// See referrers.golden for expected query results.
+
+import "lib"
+
+type s struct {
+	f int
+}
+
+func main() {
+	var v lib.Type = lib.Const // @referrers ref-package "lib"
+	_ = v.Method               // @referrers ref-method "Method"
+	_ = v.Method
+	v++ //@referrers ref-local "v"
+	v++
+
+	_ = s{}.f // @referrers ref-field "f"
+
+	var s2 s
+	s2.f = 1
+}
diff --git a/oracle/testdata/src/referrers-json/main.golden b/oracle/testdata/src/referrers-json/main.golden
new file mode 100644
index 0000000..47a2d01
--- /dev/null
+++ b/oracle/testdata/src/referrers-json/main.golden
@@ -0,0 +1,59 @@
+-------- @referrers ref-package --------
+{
+	"mode": "referrers",
+	"referrers": {
+		"pos": "testdata/src/referrers-json/main.go:14:8",
+		"objpos": "testdata/src/referrers-json/main.go:7:8",
+		"desc": "package lib",
+		"refs": [
+			"testdata/src/referrers-json/main.go:14:8",
+			"testdata/src/referrers-json/main.go:14:19"
+		]
+	}
+}
+-------- @referrers ref-method --------
+{
+	"mode": "referrers",
+	"referrers": {
+		"pos": "testdata/src/referrers-json/main.go:15:8",
+		"objpos": "testdata/src/lib/lib.go:5:13",
+		"desc": "func (lib.Type).Method(x *int) *int",
+		"refs": [
+			"testdata/src/imports/main.go:22:9",
+			"testdata/src/referrers-json/main.go:15:8",
+			"testdata/src/referrers-json/main.go:16:8",
+			"testdata/src/referrers/ext_test.go:10:17",
+			"testdata/src/referrers/int_test.go:7:17",
+			"testdata/src/referrers/main.go:17:8",
+			"testdata/src/referrers/main.go:18:8"
+		]
+	}
+}
+-------- @referrers ref-local --------
+{
+	"mode": "referrers",
+	"referrers": {
+		"pos": "testdata/src/referrers-json/main.go:17:2",
+		"objpos": "testdata/src/referrers-json/main.go:14:6",
+		"desc": "var v lib.Type",
+		"refs": [
+			"testdata/src/referrers-json/main.go:15:6",
+			"testdata/src/referrers-json/main.go:16:6",
+			"testdata/src/referrers-json/main.go:17:2",
+			"testdata/src/referrers-json/main.go:18:2"
+		]
+	}
+}
+-------- @referrers ref-field --------
+{
+	"mode": "referrers",
+	"referrers": {
+		"pos": "testdata/src/referrers-json/main.go:20:10",
+		"objpos": "testdata/src/referrers-json/main.go:10:2",
+		"desc": "field f int",
+		"refs": [
+			"testdata/src/referrers-json/main.go:20:10",
+			"testdata/src/referrers-json/main.go:23:5"
+		]
+	}
+}
diff --git a/oracle/testdata/src/referrers/ext_test.go b/oracle/testdata/src/referrers/ext_test.go
new file mode 100644
index 0000000..35e3199
--- /dev/null
+++ b/oracle/testdata/src/referrers/ext_test.go
@@ -0,0 +1,12 @@
+package main_test
+
+import (
+	"lib"
+	renamed "referrers" // package has name "main", path "referrers", local name "renamed"
+)
+
+func _() {
+	// This reference should be found by the ref-method query.
+	_ = (lib.Type).Method // ref from external test package
+	var _ renamed.T
+}
diff --git a/oracle/testdata/src/referrers/int_test.go b/oracle/testdata/src/referrers/int_test.go
new file mode 100644
index 0000000..9102cd6
--- /dev/null
+++ b/oracle/testdata/src/referrers/int_test.go
@@ -0,0 +1,8 @@
+package main
+
+import "lib"
+
+func _() {
+	// This reference should be found by the ref-method query.
+	_ = (lib.Type).Method // ref from internal test package
+}
diff --git a/oracle/testdata/src/referrers/main.go b/oracle/testdata/src/referrers/main.go
new file mode 100644
index 0000000..36cdb7a
--- /dev/null
+++ b/oracle/testdata/src/referrers/main.go
@@ -0,0 +1,26 @@
+package main // @referrers package-decl "main"
+
+// Tests of 'referrers' query.
+// See go.tools/oracle/oracle_test.go for explanation.
+// See referrers.golden for expected query results.
+
+import "lib"
+
+type s struct { // @referrers type " s "
+	f int
+}
+
+type T int
+
+func main() {
+	var v lib.Type = lib.Const // @referrers ref-package "lib"
+	_ = v.Method               // @referrers ref-method "Method"
+	_ = v.Method
+	v++ //@referrers ref-local "v"
+	v++
+
+	_ = s{}.f // @referrers ref-field "f"
+
+	var s2 s
+	s2.f = 1
+}
diff --git a/oracle/testdata/src/referrers/main.golden b/oracle/testdata/src/referrers/main.golden
new file mode 100644
index 0000000..1f04be5
--- /dev/null
+++ b/oracle/testdata/src/referrers/main.golden
@@ -0,0 +1,38 @@
+-------- @referrers package-decl --------
+1 references to package main ("referrers")
+	var _ renamed.T
+
+-------- @referrers type --------
+2 references to type s struct{f int}
+	_ = s{}.f // @referrers ref-field "f"
+	var s2 s
+
+-------- @referrers ref-package --------
+4 references to package lib
+	_ = (lib.Type).Method // ref from external test package
+	_ = (lib.Type).Method // ref from internal test package
+	var v lib.Type = lib.Const // @referrers ref-package "lib"
+	var v lib.Type = lib.Const // @referrers ref-package "lib"
+
+-------- @referrers ref-method --------
+7 references to func (lib.Type).Method(x *int) *int
+	p := t.Method(&a)   // @describe ref-method "Method"
+	_ = v.Method               // @referrers ref-method "Method"
+	_ = v.Method
+	_ = (lib.Type).Method // ref from external test package
+	_ = (lib.Type).Method // ref from internal test package
+	_ = v.Method               // @referrers ref-method "Method"
+	_ = v.Method
+
+-------- @referrers ref-local --------
+4 references to var v lib.Type
+	_ = v.Method               // @referrers ref-method "Method"
+	_ = v.Method
+	v++ //@referrers ref-local "v"
+	v++
+
+-------- @referrers ref-field --------
+2 references to field f int
+	_ = s{}.f // @referrers ref-field "f"
+	s2.f = 1
+
diff --git a/oracle/testdata/src/reflection/main.go b/oracle/testdata/src/reflection/main.go
new file mode 100644
index 0000000..392643b
--- /dev/null
+++ b/oracle/testdata/src/reflection/main.go
@@ -0,0 +1,30 @@
+package main
+
+// This is a test of 'pointsto', but we split it into a separate file
+// so that pointsto.go doesn't have to import "reflect" each time.
+
+import "reflect"
+
+var a int
+var b bool
+
+func main() {
+	m := make(map[*int]*bool)
+	m[&a] = &b
+
+	mrv := reflect.ValueOf(m)
+	if a > 0 {
+		mrv = reflect.ValueOf(&b)
+	}
+	if a > 0 {
+		mrv = reflect.ValueOf(&a)
+	}
+
+	_ = mrv                  // @pointsto mrv "mrv"
+	p1 := mrv.Interface()    // @pointsto p1 "p1"
+	p2 := mrv.MapKeys()      // @pointsto p2 "p2"
+	p3 := p2[0]              // @pointsto p3 "p3"
+	p4 := reflect.TypeOf(p1) // @pointsto p4 "p4"
+
+	_, _, _, _ = p1, p2, p3, p4
+}
diff --git a/oracle/testdata/src/reflection/main.golden b/oracle/testdata/src/reflection/main.golden
new file mode 100644
index 0000000..6190c06
--- /dev/null
+++ b/oracle/testdata/src/reflection/main.golden
@@ -0,0 +1,34 @@
+-------- @pointsto mrv --------
+this reflect.Value may contain these dynamic types:
+	*bool, may point to:
+		main.b
+	*int, may point to:
+		main.a
+	map[*int]*bool, may point to:
+		makemap
+
+-------- @pointsto p1 --------
+this interface{} may contain these dynamic types:
+	*bool, may point to:
+		main.b
+	*int, may point to:
+		main.a
+	map[*int]*bool, may point to:
+		makemap
+
+-------- @pointsto p2 --------
+this []reflect.Value may point to these objects:
+	<alloc in (reflect.Value).MapKeys>
+
+-------- @pointsto p3 --------
+this reflect.Value may contain these dynamic types:
+	*int, may point to:
+		main.a
+
+-------- @pointsto p4 --------
+this reflect.Type may contain these dynamic types:
+	*reflect.rtype, may point to:
+		*bool
+		*int
+		map[*int]*bool
+
diff --git a/oracle/testdata/src/what-json/main.go b/oracle/testdata/src/what-json/main.go
new file mode 100644
index 0000000..8d578c7
--- /dev/null
+++ b/oracle/testdata/src/what-json/main.go
@@ -0,0 +1,9 @@
+package main
+
+// Tests of 'what' queries, -format=json.
+// See go.tools/oracle/oracle_test.go for explanation.
+// See what-json.golden for expected query results.
+
+func main() {
+	f() // @what call "f"
+}
diff --git a/oracle/testdata/src/what-json/main.golden b/oracle/testdata/src/what-json/main.golden
new file mode 100644
index 0000000..9a31190
--- /dev/null
+++ b/oracle/testdata/src/what-json/main.golden
@@ -0,0 +1,51 @@
+-------- @what call --------
+{
+	"mode": "what",
+	"what": {
+		"enclosing": [
+			{
+				"desc": "identifier",
+				"start": 179,
+				"end": 180
+			},
+			{
+				"desc": "function call (or conversion)",
+				"start": 179,
+				"end": 182
+			},
+			{
+				"desc": "expression statement",
+				"start": 179,
+				"end": 182
+			},
+			{
+				"desc": "block",
+				"start": 176,
+				"end": 202
+			},
+			{
+				"desc": "function declaration",
+				"start": 164,
+				"end": 202
+			},
+			{
+				"desc": "source file",
+				"start": 0,
+				"end": 202
+			}
+		],
+		"modes": [
+			"callees",
+			"callers",
+			"callstack",
+			"definition",
+			"describe",
+			"freevars",
+			"implements",
+			"pointsto",
+			"referrers"
+		],
+		"srcdir": "testdata/src",
+		"importpath": "what-json"
+	}
+}
diff --git a/oracle/testdata/src/what/main.go b/oracle/testdata/src/what/main.go
new file mode 100644
index 0000000..38e9dc7
--- /dev/null
+++ b/oracle/testdata/src/what/main.go
@@ -0,0 +1,11 @@
+package main // @what pkgdecl "main"
+
+// Tests of 'what' queries.
+// See go.tools/oracle/oracle_test.go for explanation.
+// See what.golden for expected query results.
+
+func main() {
+	f()             // @what call "f"
+	var ch chan int // @what var "var"
+	<-ch            // @what recv "ch"
+}
diff --git a/oracle/testdata/src/what/main.golden b/oracle/testdata/src/what/main.golden
new file mode 100644
index 0000000..56b97dd
--- /dev/null
+++ b/oracle/testdata/src/what/main.golden
@@ -0,0 +1,39 @@
+-------- @what pkgdecl --------
+identifier
+source file
+modes: [definition describe freevars implements pointsto referrers]
+srcdir: testdata/src
+import path: what
+
+-------- @what call --------
+identifier
+function call (or conversion)
+expression statement
+block
+function declaration
+source file
+modes: [callees callers callstack definition describe freevars implements pointsto referrers]
+srcdir: testdata/src
+import path: what
+
+-------- @what var --------
+variable declaration
+variable declaration statement
+block
+function declaration
+source file
+modes: [callers callstack describe freevars pointsto]
+srcdir: testdata/src
+import path: what
+
+-------- @what recv --------
+identifier
+unary <- operation
+expression statement
+block
+function declaration
+source file
+modes: [callers callstack definition describe freevars implements peers pointsto referrers]
+srcdir: testdata/src
+import path: what
+
diff --git a/oracle/testdata/src/whicherrs/main.go b/oracle/testdata/src/whicherrs/main.go
new file mode 100644
index 0000000..27fe6b5
--- /dev/null
+++ b/oracle/testdata/src/whicherrs/main.go
@@ -0,0 +1,27 @@
+package main
+
+type errType string
+
+const constErr errType = "blah"
+
+func (et errType) Error() string {
+	return string(et)
+}
+
+var errVar error = errType("foo")
+
+func genErr(i int) error {
+	switch i {
+	case 0:
+		return constErr
+	case 1:
+		return errVar
+	default:
+		return nil
+	}
+}
+
+func main() {
+	err := genErr(0) // @whicherrs localerrs "err"
+	_ = err
+}
diff --git a/oracle/testdata/src/whicherrs/main.golden b/oracle/testdata/src/whicherrs/main.golden
new file mode 100644
index 0000000..1118e0a
--- /dev/null
+++ b/oracle/testdata/src/whicherrs/main.golden
@@ -0,0 +1,8 @@
+-------- @whicherrs localerrs --------
+this error may point to these globals:
+	errVar
+this error may contain these constants:
+	constErr
+this error may contain these dynamic types:
+	errType
+
diff --git a/oracle/what.go b/oracle/what.go
new file mode 100644
index 0000000..5a5c0cf
--- /dev/null
+++ b/oracle/what.go
@@ -0,0 +1,210 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package oracle
+
+import (
+	"fmt"
+	"go/ast"
+	"go/build"
+	"go/token"
+	"os"
+	"path/filepath"
+	"sort"
+	"strings"
+
+	"golang.org/x/tools/go/ast/astutil"
+	"golang.org/x/tools/oracle/serial"
+)
+
+// what reports all the information about the query selection that can be
+// obtained from parsing only its containing source file.
+// It is intended to be a very low-latency query callable from GUI
+// tools, e.g. to populate a menu of options of slower queries about
+// the selected location.
+//
+func what(q *Query) error {
+	qpos, err := fastQueryPos(q.Pos)
+	if err != nil {
+		return err
+	}
+	q.Fset = qpos.fset
+
+	// (ignore errors)
+	srcdir, importPath, _ := guessImportPath(q.Fset.File(qpos.start).Name(), q.Build)
+
+	// Determine which query modes are applicable to the selection.
+	enable := map[string]bool{
+		"describe": true, // any syntax; always enabled
+	}
+
+	if qpos.end > qpos.start {
+		enable["freevars"] = true // nonempty selection?
+	}
+
+	for _, n := range qpos.path {
+		switch n := n.(type) {
+		case *ast.Ident:
+			enable["definition"] = true
+			enable["referrers"] = true
+			enable["implements"] = true
+		case *ast.CallExpr:
+			enable["callees"] = true
+		case *ast.FuncDecl:
+			enable["callers"] = true
+			enable["callstack"] = true
+		case *ast.SendStmt:
+			enable["peers"] = true
+		case *ast.UnaryExpr:
+			if n.Op == token.ARROW {
+				enable["peers"] = true
+			}
+		}
+
+		// For implements, we approximate findInterestingNode.
+		if _, ok := enable["implements"]; !ok {
+			switch n.(type) {
+			case *ast.ArrayType,
+				*ast.StructType,
+				*ast.FuncType,
+				*ast.InterfaceType,
+				*ast.MapType,
+				*ast.ChanType:
+				enable["implements"] = true
+			}
+		}
+
+		// For pointsto, we approximate findInterestingNode.
+		if _, ok := enable["pointsto"]; !ok {
+			switch n.(type) {
+			case ast.Stmt,
+				*ast.ArrayType,
+				*ast.StructType,
+				*ast.FuncType,
+				*ast.InterfaceType,
+				*ast.MapType,
+				*ast.ChanType:
+				enable["pointsto"] = false // not an expr
+
+			case ast.Expr, ast.Decl, *ast.ValueSpec:
+				enable["pointsto"] = true // an expr, maybe
+
+			default:
+				// Comment, Field, KeyValueExpr, etc: ascend.
+			}
+		}
+	}
+
+	// If we don't have an exact selection, disable modes that need one.
+	if !qpos.exact {
+		enable["callees"] = false
+		enable["pointsto"] = false
+		enable["whicherrs"] = false
+		enable["describe"] = false
+	}
+
+	var modes []string
+	for mode := range enable {
+		modes = append(modes, mode)
+	}
+	sort.Strings(modes)
+
+	q.result = &whatResult{
+		path:       qpos.path,
+		srcdir:     srcdir,
+		importPath: importPath,
+		modes:      modes,
+	}
+	return nil
+}
+
+// guessImportPath finds the package containing filename, and returns
+// its source directory (an element of $GOPATH) and its import path
+// relative to it.
+//
+// TODO(adonovan): what about _test.go files that are not part of the
+// package?
+//
+func guessImportPath(filename string, buildContext *build.Context) (srcdir, importPath string, err error) {
+	absFile, err := filepath.Abs(filename)
+	if err != nil {
+		err = fmt.Errorf("can't form absolute path of %s", filename)
+		return
+	}
+	absFileDir := segments(filepath.Dir(absFile))
+
+	// Find the innermost directory in $GOPATH that encloses filename.
+	minD := 1024
+	for _, gopathDir := range buildContext.SrcDirs() {
+		absDir, err := filepath.Abs(gopathDir)
+		if err != nil {
+			continue // e.g. non-existent dir on $GOPATH
+		}
+		d := prefixLen(segments(absDir), absFileDir)
+		// If there are multiple matches,
+		// prefer the innermost enclosing directory
+		// (smallest d).
+		if d >= 0 && d < minD {
+			minD = d
+			srcdir = gopathDir
+			importPath = strings.Join(absFileDir[len(absFileDir)-minD:], string(os.PathSeparator))
+		}
+	}
+	if srcdir == "" {
+		err = fmt.Errorf("directory %s is not beneath any of these GOROOT/GOPATH directories: %s",
+			filepath.Dir(absFile), strings.Join(buildContext.SrcDirs(), ", "))
+	}
+	return
+}
+
+func segments(path string) []string {
+	return strings.Split(path, string(os.PathSeparator))
+}
+
+// prefixLen returns the length of the remainder of y if x is a prefix
+// of y, a negative number otherwise.
+func prefixLen(x, y []string) int {
+	d := len(y) - len(x)
+	if d >= 0 {
+		for i := range x {
+			if y[i] != x[i] {
+				return -1 // not a prefix
+			}
+		}
+	}
+	return d
+}
+
+type whatResult struct {
+	path       []ast.Node
+	modes      []string
+	srcdir     string
+	importPath string
+}
+
+func (r *whatResult) display(printf printfFunc) {
+	for _, n := range r.path {
+		printf(n, "%s", astutil.NodeDescription(n))
+	}
+	printf(nil, "modes: %s", r.modes)
+	printf(nil, "srcdir: %s", r.srcdir)
+	printf(nil, "import path: %s", r.importPath)
+}
+
+func (r *whatResult) toSerial(res *serial.Result, fset *token.FileSet) {
+	var enclosing []serial.SyntaxNode
+	for _, n := range r.path {
+		enclosing = append(enclosing, serial.SyntaxNode{
+			Description: astutil.NodeDescription(n),
+			Start:       fset.Position(n.Pos()).Offset,
+			End:         fset.Position(n.End()).Offset,
+		})
+	}
+	res.What = &serial.What{
+		Modes:      r.modes,
+		SrcDir:     r.srcdir,
+		ImportPath: r.importPath,
+		Enclosing:  enclosing,
+	}
+}
diff --git a/oracle/whicherrs.go b/oracle/whicherrs.go
new file mode 100644
index 0000000..aaa6068
--- /dev/null
+++ b/oracle/whicherrs.go
@@ -0,0 +1,326 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package oracle
+
+import (
+	"fmt"
+	"go/ast"
+	"go/token"
+	"sort"
+
+	"golang.org/x/tools/go/ast/astutil"
+	"golang.org/x/tools/go/loader"
+	"golang.org/x/tools/go/ssa"
+	"golang.org/x/tools/go/ssa/ssautil"
+	"golang.org/x/tools/go/types"
+	"golang.org/x/tools/oracle/serial"
+)
+
+var builtinErrorType = types.Universe.Lookup("error").Type()
+
+// whicherrs takes an position to an error and tries to find all types, constants
+// and global value which a given error can point to and which can be checked from the
+// scope where the error lives.
+// In short, it returns a list of things that can be checked against in order to handle
+// an error properly.
+//
+// TODO(dmorsing): figure out if fields in errors like *os.PathError.Err
+// can be queried recursively somehow.
+func whicherrs(q *Query) error {
+	lconf := loader.Config{Build: q.Build}
+
+	if err := setPTAScope(&lconf, q.Scope); err != nil {
+		return err
+	}
+
+	// Load/parse/type-check the program.
+	lprog, err := lconf.Load()
+	if err != nil {
+		return err
+	}
+	q.Fset = lprog.Fset
+
+	qpos, err := parseQueryPos(lprog, q.Pos, true) // needs exact pos
+	if err != nil {
+		return err
+	}
+
+	prog := ssautil.CreateProgram(lprog, ssa.GlobalDebug)
+
+	ptaConfig, err := setupPTA(prog, lprog, q.PTALog, q.Reflection)
+	if err != nil {
+		return err
+	}
+
+	path, action := findInterestingNode(qpos.info, qpos.path)
+	if action != actionExpr {
+		return fmt.Errorf("whicherrs wants an expression; got %s",
+			astutil.NodeDescription(qpos.path[0]))
+	}
+	var expr ast.Expr
+	var obj types.Object
+	switch n := path[0].(type) {
+	case *ast.ValueSpec:
+		// ambiguous ValueSpec containing multiple names
+		return fmt.Errorf("multiple value specification")
+	case *ast.Ident:
+		obj = qpos.info.ObjectOf(n)
+		expr = n
+	case ast.Expr:
+		expr = n
+	default:
+		return fmt.Errorf("unexpected AST for expr: %T", n)
+	}
+
+	typ := qpos.info.TypeOf(expr)
+	if !types.Identical(typ, builtinErrorType) {
+		return fmt.Errorf("selection is not an expression of type 'error'")
+	}
+	// Determine the ssa.Value for the expression.
+	var value ssa.Value
+	if obj != nil {
+		// def/ref of func/var object
+		value, _, err = ssaValueForIdent(prog, qpos.info, obj, path)
+	} else {
+		value, _, err = ssaValueForExpr(prog, qpos.info, path)
+	}
+	if err != nil {
+		return err // e.g. trivially dead code
+	}
+
+	// Defer SSA construction till after errors are reported.
+	prog.BuildAll()
+
+	globals := findVisibleErrs(prog, qpos)
+	constants := findVisibleConsts(prog, qpos)
+
+	res := &whicherrsResult{
+		qpos:   qpos,
+		errpos: expr.Pos(),
+	}
+
+	// TODO(adonovan): the following code is heavily duplicated
+	// w.r.t.  "pointsto".  Refactor?
+
+	// Find the instruction which initialized the
+	// global error. If more than one instruction has stored to the global
+	// remove the global from the set of values that we want to query.
+	allFuncs := ssautil.AllFunctions(prog)
+	for fn := range allFuncs {
+		for _, b := range fn.Blocks {
+			for _, instr := range b.Instrs {
+				store, ok := instr.(*ssa.Store)
+				if !ok {
+					continue
+				}
+				gval, ok := store.Addr.(*ssa.Global)
+				if !ok {
+					continue
+				}
+				gbl, ok := globals[gval]
+				if !ok {
+					continue
+				}
+				// we already found a store to this global
+				// The normal error define is just one store in the init
+				// so we just remove this global from the set we want to query
+				if gbl != nil {
+					delete(globals, gval)
+				}
+				globals[gval] = store.Val
+			}
+		}
+	}
+
+	ptaConfig.AddQuery(value)
+	for _, v := range globals {
+		ptaConfig.AddQuery(v)
+	}
+
+	ptares := ptrAnalysis(ptaConfig)
+	valueptr := ptares.Queries[value]
+	for g, v := range globals {
+		ptr, ok := ptares.Queries[v]
+		if !ok {
+			continue
+		}
+		if !ptr.MayAlias(valueptr) {
+			continue
+		}
+		res.globals = append(res.globals, g)
+	}
+	pts := valueptr.PointsTo()
+	dedup := make(map[*ssa.NamedConst]bool)
+	for _, label := range pts.Labels() {
+		// These values are either MakeInterfaces or reflect
+		// generated interfaces. For the purposes of this
+		// analysis, we don't care about reflect generated ones
+		makeiface, ok := label.Value().(*ssa.MakeInterface)
+		if !ok {
+			continue
+		}
+		constval, ok := makeiface.X.(*ssa.Const)
+		if !ok {
+			continue
+		}
+		c := constants[*constval]
+		if c != nil && !dedup[c] {
+			dedup[c] = true
+			res.consts = append(res.consts, c)
+		}
+	}
+	concs := pts.DynamicTypes()
+	concs.Iterate(func(conc types.Type, _ interface{}) {
+		// go/types is a bit annoying here.
+		// We want to find all the types that we can
+		// typeswitch or assert to. This means finding out
+		// if the type pointed to can be seen by us.
+		//
+		// For the purposes of this analysis, the type is always
+		// either a Named type or a pointer to one.
+		// There are cases where error can be implemented
+		// by unnamed types, but in that case, we can't assert to
+		// it, so we don't care about it for this analysis.
+		var name *types.TypeName
+		switch t := conc.(type) {
+		case *types.Pointer:
+			named, ok := t.Elem().(*types.Named)
+			if !ok {
+				return
+			}
+			name = named.Obj()
+		case *types.Named:
+			name = t.Obj()
+		default:
+			return
+		}
+		if !isAccessibleFrom(name, qpos.info.Pkg) {
+			return
+		}
+		res.types = append(res.types, &errorType{conc, name})
+	})
+	sort.Sort(membersByPosAndString(res.globals))
+	sort.Sort(membersByPosAndString(res.consts))
+	sort.Sort(sorterrorType(res.types))
+
+	q.result = res
+	return nil
+}
+
+// findVisibleErrs returns a mapping from each package-level variable of type "error" to nil.
+func findVisibleErrs(prog *ssa.Program, qpos *queryPos) map[*ssa.Global]ssa.Value {
+	globals := make(map[*ssa.Global]ssa.Value)
+	for _, pkg := range prog.AllPackages() {
+		for _, mem := range pkg.Members {
+			gbl, ok := mem.(*ssa.Global)
+			if !ok {
+				continue
+			}
+			gbltype := gbl.Type()
+			// globals are always pointers
+			if !types.Identical(deref(gbltype), builtinErrorType) {
+				continue
+			}
+			if !isAccessibleFrom(gbl.Object(), qpos.info.Pkg) {
+				continue
+			}
+			globals[gbl] = nil
+		}
+	}
+	return globals
+}
+
+// findVisibleConsts returns a mapping from each package-level constant assignable to type "error", to nil.
+func findVisibleConsts(prog *ssa.Program, qpos *queryPos) map[ssa.Const]*ssa.NamedConst {
+	constants := make(map[ssa.Const]*ssa.NamedConst)
+	for _, pkg := range prog.AllPackages() {
+		for _, mem := range pkg.Members {
+			obj, ok := mem.(*ssa.NamedConst)
+			if !ok {
+				continue
+			}
+			consttype := obj.Type()
+			if !types.AssignableTo(consttype, builtinErrorType) {
+				continue
+			}
+			if !isAccessibleFrom(obj.Object(), qpos.info.Pkg) {
+				continue
+			}
+			constants[*obj.Value] = obj
+		}
+	}
+
+	return constants
+}
+
+type membersByPosAndString []ssa.Member
+
+func (a membersByPosAndString) Len() int { return len(a) }
+func (a membersByPosAndString) Less(i, j int) bool {
+	cmp := a[i].Pos() - a[j].Pos()
+	return cmp < 0 || cmp == 0 && a[i].String() < a[j].String()
+}
+func (a membersByPosAndString) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
+
+type sorterrorType []*errorType
+
+func (a sorterrorType) Len() int { return len(a) }
+func (a sorterrorType) Less(i, j int) bool {
+	cmp := a[i].obj.Pos() - a[j].obj.Pos()
+	return cmp < 0 || cmp == 0 && a[i].typ.String() < a[j].typ.String()
+}
+func (a sorterrorType) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
+
+type errorType struct {
+	typ types.Type      // concrete type N or *N that implements error
+	obj *types.TypeName // the named type N
+}
+
+type whicherrsResult struct {
+	qpos    *queryPos
+	errpos  token.Pos
+	globals []ssa.Member
+	consts  []ssa.Member
+	types   []*errorType
+}
+
+func (r *whicherrsResult) display(printf printfFunc) {
+	if len(r.globals) > 0 {
+		printf(r.qpos, "this error may point to these globals:")
+		for _, g := range r.globals {
+			printf(g.Pos(), "\t%s", g.RelString(r.qpos.info.Pkg))
+		}
+	}
+	if len(r.consts) > 0 {
+		printf(r.qpos, "this error may contain these constants:")
+		for _, c := range r.consts {
+			printf(c.Pos(), "\t%s", c.RelString(r.qpos.info.Pkg))
+		}
+	}
+	if len(r.types) > 0 {
+		printf(r.qpos, "this error may contain these dynamic types:")
+		for _, t := range r.types {
+			printf(t.obj.Pos(), "\t%s", r.qpos.typeString(t.typ))
+		}
+	}
+}
+
+func (r *whicherrsResult) toSerial(res *serial.Result, fset *token.FileSet) {
+	we := &serial.WhichErrs{}
+	we.ErrPos = fset.Position(r.errpos).String()
+	for _, g := range r.globals {
+		we.Globals = append(we.Globals, fset.Position(g.Pos()).String())
+	}
+	for _, c := range r.consts {
+		we.Constants = append(we.Constants, fset.Position(c.Pos()).String())
+	}
+	for _, t := range r.types {
+		var et serial.WhichErrsType
+		et.Type = r.qpos.typeString(t.typ)
+		et.Position = fset.Position(t.obj.Pos()).String()
+		we.Types = append(we.Types, et)
+	}
+	res.WhichErrs = we
+}
diff --git a/playground/appengine.go b/playground/appengine.go
new file mode 100644
index 0000000..073b419
--- /dev/null
+++ b/playground/appengine.go
@@ -0,0 +1,22 @@
+// Copyright 2012 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build appengine
+
+package playground
+
+import (
+	"net/http"
+
+	"appengine"
+	"appengine/urlfetch"
+)
+
+func client(r *http.Request) *http.Client {
+	return urlfetch.Client(appengine.NewContext(r))
+}
+
+func report(r *http.Request, err error) {
+	appengine.NewContext(r).Errorf("%v", err)
+}
diff --git a/playground/common.go b/playground/common.go
new file mode 100644
index 0000000..3ffce88
--- /dev/null
+++ b/playground/common.go
@@ -0,0 +1,46 @@
+// Copyright 2013 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package playground registers HTTP handlers at "/compile" and "/share" that
+// proxy requests to the golang.org playground service.
+// This package may be used unaltered on App Engine.
+package playground // import "golang.org/x/tools/playground"
+
+import (
+	"bytes"
+	"fmt"
+	"io"
+	"net/http"
+)
+
+const baseURL = "http://play.golang.org"
+
+func init() {
+	http.HandleFunc("/compile", bounce)
+	http.HandleFunc("/share", bounce)
+}
+
+func bounce(w http.ResponseWriter, r *http.Request) {
+	b := new(bytes.Buffer)
+	if err := passThru(b, r); err != nil {
+		http.Error(w, "Server error.", http.StatusInternalServerError)
+		report(r, err)
+		return
+	}
+	io.Copy(w, b)
+}
+
+func passThru(w io.Writer, req *http.Request) error {
+	defer req.Body.Close()
+	url := baseURL + req.URL.Path
+	r, err := client(req).Post(url, req.Header.Get("Content-type"), req.Body)
+	if err != nil {
+		return fmt.Errorf("making POST request: %v", err)
+	}
+	defer r.Body.Close()
+	if _, err := io.Copy(w, r.Body); err != nil {
+		return fmt.Errorf("copying response Body: %v", err)
+	}
+	return nil
+}
diff --git a/playground/local.go b/playground/local.go
new file mode 100644
index 0000000..b114b87
--- /dev/null
+++ b/playground/local.go
@@ -0,0 +1,20 @@
+// Copyright 2012 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !appengine
+
+package playground
+
+import (
+	"log"
+	"net/http"
+)
+
+func client(r *http.Request) *http.Client {
+	return http.DefaultClient
+}
+
+func report(r *http.Request, err error) {
+	log.Println(err)
+}
diff --git a/playground/socket/socket.go b/playground/socket/socket.go
new file mode 100644
index 0000000..76527ae
--- /dev/null
+++ b/playground/socket/socket.go
@@ -0,0 +1,474 @@
+// Copyright 2012 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !appengine
+
+// Package socket implements an WebSocket-based playground backend.
+// Clients connect to a websocket handler and send run/kill commands, and
+// the server sends the output and exit status of the running processes.
+// Multiple clients running multiple processes may be served concurrently.
+// The wire format is JSON and is described by the Message type.
+//
+// This will not run on App Engine as WebSockets are not supported there.
+package socket // import "golang.org/x/tools/playground/socket"
+
+import (
+	"bytes"
+	"encoding/json"
+	"errors"
+	"go/parser"
+	"go/token"
+	"io"
+	"io/ioutil"
+	"log"
+	"net"
+	"net/http"
+	"net/url"
+	"os"
+	"os/exec"
+	"path/filepath"
+	"runtime"
+	"strconv"
+	"strings"
+	"sync"
+	"time"
+	"unicode/utf8"
+
+	"golang.org/x/net/websocket"
+)
+
+// RunScripts specifies whether the socket handler should execute shell scripts
+// (snippets that start with a shebang).
+var RunScripts = true
+
+// Environ provides an environment when a binary, such as the go tool, is
+// invoked.
+var Environ func() []string = os.Environ
+
+const (
+	// The maximum number of messages to send per session (avoid flooding).
+	msgLimit = 1000
+
+	// Batch messages sent in this interval and send as a single message.
+	msgDelay = 10 * time.Millisecond
+)
+
+// Message is the wire format for the websocket connection to the browser.
+// It is used for both sending output messages and receiving commands, as
+// distinguished by the Kind field.
+type Message struct {
+	Id      string // client-provided unique id for the process
+	Kind    string // in: "run", "kill" out: "stdout", "stderr", "end"
+	Body    string
+	Options *Options `json:",omitempty"`
+}
+
+// Options specify additional message options.
+type Options struct {
+	Race bool // use -race flag when building code (for "run" only)
+}
+
+// NewHandler returns a websocket server which checks the origin of requests.
+func NewHandler(origin *url.URL) websocket.Server {
+	return websocket.Server{
+		Config:    websocket.Config{Origin: origin},
+		Handshake: handshake,
+		Handler:   websocket.Handler(socketHandler),
+	}
+}
+
+// handshake checks the origin of a request during the websocket handshake.
+func handshake(c *websocket.Config, req *http.Request) error {
+	o, err := websocket.Origin(c, req)
+	if err != nil {
+		log.Println("bad websocket origin:", err)
+		return websocket.ErrBadWebSocketOrigin
+	}
+	_, port, err := net.SplitHostPort(c.Origin.Host)
+	if err != nil {
+		log.Println("bad websocket origin:", err)
+		return websocket.ErrBadWebSocketOrigin
+	}
+	ok := c.Origin.Scheme == o.Scheme && (c.Origin.Host == o.Host || c.Origin.Host == net.JoinHostPort(o.Host, port))
+	if !ok {
+		log.Println("bad websocket origin:", o)
+		return websocket.ErrBadWebSocketOrigin
+	}
+	log.Println("accepting connection from:", req.RemoteAddr)
+	return nil
+}
+
+// socketHandler handles the websocket connection for a given present session.
+// It handles transcoding Messages to and from JSON format, and starting
+// and killing processes.
+func socketHandler(c *websocket.Conn) {
+	in, out := make(chan *Message), make(chan *Message)
+	errc := make(chan error, 1)
+
+	// Decode messages from client and send to the in channel.
+	go func() {
+		dec := json.NewDecoder(c)
+		for {
+			var m Message
+			if err := dec.Decode(&m); err != nil {
+				errc <- err
+				return
+			}
+			in <- &m
+		}
+	}()
+
+	// Receive messages from the out channel and encode to the client.
+	go func() {
+		enc := json.NewEncoder(c)
+		for m := range out {
+			if err := enc.Encode(m); err != nil {
+				errc <- err
+				return
+			}
+		}
+	}()
+
+	// Start and kill processes and handle errors.
+	proc := make(map[string]*process)
+	for {
+		select {
+		case m := <-in:
+			switch m.Kind {
+			case "run":
+				log.Println("running snippet from:", c.Request().RemoteAddr)
+				proc[m.Id].Kill()
+				lOut := limiter(in, out)
+				proc[m.Id] = startProcess(m.Id, m.Body, lOut, m.Options)
+			case "kill":
+				proc[m.Id].Kill()
+			}
+		case err := <-errc:
+			if err != io.EOF {
+				// A encode or decode has failed; bail.
+				log.Println(err)
+			}
+			// Shut down any running processes.
+			for _, p := range proc {
+				p.Kill()
+			}
+			return
+		}
+	}
+}
+
+// process represents a running process.
+type process struct {
+	id   string
+	out  chan<- *Message
+	done chan struct{} // closed when wait completes
+	run  *exec.Cmd
+	bin  string
+}
+
+// startProcess builds and runs the given program, sending its output
+// and end event as Messages on the provided channel.
+func startProcess(id, body string, out chan<- *Message, opt *Options) *process {
+	p := &process{
+		id:   id,
+		out:  out,
+		done: make(chan struct{}),
+	}
+	var err error
+	if path, args := shebang(body); path != "" {
+		if RunScripts {
+			err = p.startProcess(path, args, body)
+		} else {
+			err = errors.New("script execution is not allowed")
+		}
+	} else {
+		err = p.start(body, opt)
+	}
+	if err != nil {
+		p.end(err)
+		return nil
+	}
+	go p.wait()
+	return p
+}
+
+// Kill stops the process if it is running and waits for it to exit.
+func (p *process) Kill() {
+	if p == nil {
+		return
+	}
+	p.run.Process.Kill()
+	<-p.done // block until process exits
+}
+
+// shebang looks for a shebang ('#!') at the beginning of the passed string.
+// If found, it returns the path and args after the shebang.
+// args includes the command as args[0].
+func shebang(body string) (path string, args []string) {
+	body = strings.TrimSpace(body)
+	if !strings.HasPrefix(body, "#!") {
+		return "", nil
+	}
+	if i := strings.Index(body, "\n"); i >= 0 {
+		body = body[:i]
+	}
+	fs := strings.Fields(body[2:])
+	return fs[0], fs
+}
+
+// startProcess starts a given program given its path and passing the given body
+// to the command standard input.
+func (p *process) startProcess(path string, args []string, body string) error {
+	cmd := &exec.Cmd{
+		Path:   path,
+		Args:   args,
+		Stdin:  strings.NewReader(body),
+		Stdout: &messageWriter{id: p.id, kind: "stdout", out: p.out},
+		Stderr: &messageWriter{id: p.id, kind: "stderr", out: p.out},
+	}
+	if err := cmd.Start(); err != nil {
+		return err
+	}
+	p.run = cmd
+	return nil
+}
+
+// start builds and starts the given program, sending its output to p.out,
+// and stores the running *exec.Cmd in the run field.
+func (p *process) start(body string, opt *Options) error {
+	// We "go build" and then exec the binary so that the
+	// resultant *exec.Cmd is a handle to the user's program
+	// (rather than the go tool process).
+	// This makes Kill work.
+
+	bin := filepath.Join(tmpdir, "compile"+strconv.Itoa(<-uniq))
+	src := bin + ".go"
+	if runtime.GOOS == "windows" {
+		bin += ".exe"
+	}
+
+	// write body to x.go
+	defer os.Remove(src)
+	err := ioutil.WriteFile(src, []byte(body), 0666)
+	if err != nil {
+		return err
+	}
+
+	// build x.go, creating x
+	p.bin = bin // to be removed by p.end
+	dir, file := filepath.Split(src)
+	args := []string{"go", "build", "-tags", "OMIT"}
+	if opt != nil && opt.Race {
+		p.out <- &Message{
+			Id: p.id, Kind: "stderr",
+			Body: "Running with race detector.\n",
+		}
+		args = append(args, "-race")
+	}
+	args = append(args, "-o", bin, file)
+	cmd := p.cmd(dir, args...)
+	cmd.Stdout = cmd.Stderr // send compiler output to stderr
+	if err := cmd.Run(); err != nil {
+		return err
+	}
+
+	// run x
+	if isNacl() {
+		cmd, err = p.naclCmd(bin)
+		if err != nil {
+			return err
+		}
+	} else {
+		cmd = p.cmd("", bin)
+	}
+	if opt != nil && opt.Race {
+		cmd.Env = append(cmd.Env, "GOMAXPROCS=2")
+	}
+	if err := cmd.Start(); err != nil {
+		// If we failed to exec, that might be because they built
+		// a non-main package instead of an executable.
+		// Check and report that.
+		if name, err := packageName(body); err == nil && name != "main" {
+			return errors.New(`executable programs must use "package main"`)
+		}
+		return err
+	}
+	p.run = cmd
+	return nil
+}
+
+// wait waits for the running process to complete
+// and sends its error state to the client.
+func (p *process) wait() {
+	p.end(p.run.Wait())
+	close(p.done) // unblock waiting Kill calls
+}
+
+// end sends an "end" message to the client, containing the process id and the
+// given error value. It also removes the binary.
+func (p *process) end(err error) {
+	if p.bin != "" {
+		defer os.Remove(p.bin)
+	}
+	m := &Message{Id: p.id, Kind: "end"}
+	if err != nil {
+		m.Body = err.Error()
+	}
+	// Wait for any outstanding reads to finish (potential race here).
+	time.AfterFunc(4*msgDelay, func() { p.out <- m })
+}
+
+// cmd builds an *exec.Cmd that writes its standard output and error to the
+// process' output channel.
+func (p *process) cmd(dir string, args ...string) *exec.Cmd {
+	cmd := exec.Command(args[0], args[1:]...)
+	cmd.Dir = dir
+	cmd.Env = Environ()
+	cmd.Stdout = &messageWriter{id: p.id, kind: "stdout", out: p.out}
+	cmd.Stderr = &messageWriter{id: p.id, kind: "stderr", out: p.out}
+	return cmd
+}
+
+func isNacl() bool {
+	for _, v := range append(Environ(), os.Environ()...) {
+		if v == "GOOS=nacl" {
+			return true
+		}
+	}
+	return false
+}
+
+// naclCmd returns an *exec.Cmd that executes bin under native client.
+func (p *process) naclCmd(bin string) (*exec.Cmd, error) {
+	pwd, err := os.Getwd()
+	if err != nil {
+		return nil, err
+	}
+	var args []string
+	env := []string{
+		"NACLENV_GOOS=" + runtime.GOOS,
+		"NACLENV_GOROOT=/go",
+		"NACLENV_NACLPWD=" + strings.Replace(pwd, runtime.GOROOT(), "/go", 1),
+	}
+	switch runtime.GOARCH {
+	case "amd64":
+		env = append(env, "NACLENV_GOARCH=amd64p32")
+		args = []string{"sel_ldr_x86_64"}
+	case "386":
+		env = append(env, "NACLENV_GOARCH=386")
+		args = []string{"sel_ldr_x86_32"}
+	case "arm":
+		env = append(env, "NACLENV_GOARCH=arm")
+		selLdr, err := exec.LookPath("sel_ldr_arm")
+		if err != nil {
+			return nil, err
+		}
+		args = []string{"nacl_helper_bootstrap_arm", selLdr, "--reserved_at_zero=0xXXXXXXXXXXXXXXXX"}
+	default:
+		return nil, errors.New("native client does not support GOARCH=" + runtime.GOARCH)
+	}
+
+	cmd := p.cmd("", append(args, "-l", "/dev/null", "-S", "-e", bin)...)
+	cmd.Env = append(cmd.Env, env...)
+
+	return cmd, nil
+}
+
+func packageName(body string) (string, error) {
+	f, err := parser.ParseFile(token.NewFileSet(), "prog.go",
+		strings.NewReader(body), parser.PackageClauseOnly)
+	if err != nil {
+		return "", err
+	}
+	return f.Name.String(), nil
+}
+
+// messageWriter is an io.Writer that converts all writes to Message sends on
+// the out channel with the specified id and kind.
+type messageWriter struct {
+	id, kind string
+	out      chan<- *Message
+
+	mu   sync.Mutex
+	buf  []byte
+	send *time.Timer
+}
+
+func (w *messageWriter) Write(b []byte) (n int, err error) {
+	// Buffer writes that occur in a short period to send as one Message.
+	w.mu.Lock()
+	w.buf = append(w.buf, b...)
+	if w.send == nil {
+		w.send = time.AfterFunc(msgDelay, w.sendNow)
+	}
+	w.mu.Unlock()
+	return len(b), nil
+}
+
+func (w *messageWriter) sendNow() {
+	w.mu.Lock()
+	body := safeString(w.buf)
+	w.buf, w.send = nil, nil
+	w.mu.Unlock()
+	w.out <- &Message{Id: w.id, Kind: w.kind, Body: body}
+}
+
+// safeString returns b as a valid UTF-8 string.
+func safeString(b []byte) string {
+	if utf8.Valid(b) {
+		return string(b)
+	}
+	var buf bytes.Buffer
+	for len(b) > 0 {
+		r, size := utf8.DecodeRune(b)
+		b = b[size:]
+		buf.WriteRune(r)
+	}
+	return buf.String()
+}
+
+// limiter returns a channel that wraps dest. Messages sent to the channel are
+// sent to dest. After msgLimit Messages have been passed on, a "kill" Message
+// is sent to the kill channel, and only "end" messages are passed.
+func limiter(kill chan<- *Message, dest chan<- *Message) chan<- *Message {
+	ch := make(chan *Message)
+	go func() {
+		n := 0
+		for m := range ch {
+			switch {
+			case n < msgLimit || m.Kind == "end":
+				dest <- m
+				if m.Kind == "end" {
+					return
+				}
+			case n == msgLimit:
+				// process produced too much output. Kill it.
+				kill <- &Message{Id: m.Id, Kind: "kill"}
+			}
+			n++
+		}
+	}()
+	return ch
+}
+
+var tmpdir string
+
+func init() {
+	// find real path to temporary directory
+	var err error
+	tmpdir, err = filepath.EvalSymlinks(os.TempDir())
+	if err != nil {
+		log.Fatal(err)
+	}
+}
+
+var uniq = make(chan int) // a source of numbers for naming temporary files
+
+func init() {
+	go func() {
+		for i := 0; ; i++ {
+			uniq <- i
+		}
+	}()
+}
diff --git a/present/args.go b/present/args.go
new file mode 100644
index 0000000..49ee1a9
--- /dev/null
+++ b/present/args.go
@@ -0,0 +1,229 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package present
+
+import (
+	"errors"
+	"regexp"
+	"strconv"
+	"unicode/utf8"
+)
+
+// This file is stolen from go/src/cmd/godoc/codewalk.go.
+// It's an evaluator for the file address syntax implemented by acme and sam,
+// but using Go-native regular expressions.
+// To keep things reasonably close, this version uses (?m:re) for all user-provided
+// regular expressions. That is the only change to the code from codewalk.go.
+// See http://plan9.bell-labs.com/sys/doc/sam/sam.html Table II
+// for details on the syntax.
+
+// addrToByte evaluates the given address starting at offset start in data.
+// It returns the lo and hi byte offset of the matched region within data.
+func addrToByteRange(addr string, start int, data []byte) (lo, hi int, err error) {
+	if addr == "" {
+		lo, hi = start, len(data)
+		return
+	}
+	var (
+		dir        byte
+		prevc      byte
+		charOffset bool
+	)
+	lo = start
+	hi = start
+	for addr != "" && err == nil {
+		c := addr[0]
+		switch c {
+		default:
+			err = errors.New("invalid address syntax near " + string(c))
+		case ',':
+			if len(addr) == 1 {
+				hi = len(data)
+			} else {
+				_, hi, err = addrToByteRange(addr[1:], hi, data)
+			}
+			return
+
+		case '+', '-':
+			if prevc == '+' || prevc == '-' {
+				lo, hi, err = addrNumber(data, lo, hi, prevc, 1, charOffset)
+			}
+			dir = c
+
+		case '$':
+			lo = len(data)
+			hi = len(data)
+			if len(addr) > 1 {
+				dir = '+'
+			}
+
+		case '#':
+			charOffset = true
+
+		case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
+			var i int
+			for i = 1; i < len(addr); i++ {
+				if addr[i] < '0' || addr[i] > '9' {
+					break
+				}
+			}
+			var n int
+			n, err = strconv.Atoi(addr[0:i])
+			if err != nil {
+				break
+			}
+			lo, hi, err = addrNumber(data, lo, hi, dir, n, charOffset)
+			dir = 0
+			charOffset = false
+			prevc = c
+			addr = addr[i:]
+			continue
+
+		case '/':
+			var i, j int
+		Regexp:
+			for i = 1; i < len(addr); i++ {
+				switch addr[i] {
+				case '\\':
+					i++
+				case '/':
+					j = i + 1
+					break Regexp
+				}
+			}
+			if j == 0 {
+				j = i
+			}
+			pattern := addr[1:i]
+			lo, hi, err = addrRegexp(data, lo, hi, dir, pattern)
+			prevc = c
+			addr = addr[j:]
+			continue
+		}
+		prevc = c
+		addr = addr[1:]
+	}
+
+	if err == nil && dir != 0 {
+		lo, hi, err = addrNumber(data, lo, hi, dir, 1, charOffset)
+	}
+	if err != nil {
+		return 0, 0, err
+	}
+	return lo, hi, nil
+}
+
+// addrNumber applies the given dir, n, and charOffset to the address lo, hi.
+// dir is '+' or '-', n is the count, and charOffset is true if the syntax
+// used was #n.  Applying +n (or +#n) means to advance n lines
+// (or characters) after hi.  Applying -n (or -#n) means to back up n lines
+// (or characters) before lo.
+// The return value is the new lo, hi.
+func addrNumber(data []byte, lo, hi int, dir byte, n int, charOffset bool) (int, int, error) {
+	switch dir {
+	case 0:
+		lo = 0
+		hi = 0
+		fallthrough
+
+	case '+':
+		if charOffset {
+			pos := hi
+			for ; n > 0 && pos < len(data); n-- {
+				_, size := utf8.DecodeRune(data[pos:])
+				pos += size
+			}
+			if n == 0 {
+				return pos, pos, nil
+			}
+			break
+		}
+		// find next beginning of line
+		if hi > 0 {
+			for hi < len(data) && data[hi-1] != '\n' {
+				hi++
+			}
+		}
+		lo = hi
+		if n == 0 {
+			return lo, hi, nil
+		}
+		for ; hi < len(data); hi++ {
+			if data[hi] != '\n' {
+				continue
+			}
+			switch n--; n {
+			case 1:
+				lo = hi + 1
+			case 0:
+				return lo, hi + 1, nil
+			}
+		}
+
+	case '-':
+		if charOffset {
+			// Scan backward for bytes that are not UTF-8 continuation bytes.
+			pos := lo
+			for ; pos > 0 && n > 0; pos-- {
+				if data[pos]&0xc0 != 0x80 {
+					n--
+				}
+			}
+			if n == 0 {
+				return pos, pos, nil
+			}
+			break
+		}
+		// find earlier beginning of line
+		for lo > 0 && data[lo-1] != '\n' {
+			lo--
+		}
+		hi = lo
+		if n == 0 {
+			return lo, hi, nil
+		}
+		for ; lo >= 0; lo-- {
+			if lo > 0 && data[lo-1] != '\n' {
+				continue
+			}
+			switch n--; n {
+			case 1:
+				hi = lo
+			case 0:
+				return lo, hi, nil
+			}
+		}
+	}
+
+	return 0, 0, errors.New("address out of range")
+}
+
+// addrRegexp searches for pattern in the given direction starting at lo, hi.
+// The direction dir is '+' (search forward from hi) or '-' (search backward from lo).
+// Backward searches are unimplemented.
+func addrRegexp(data []byte, lo, hi int, dir byte, pattern string) (int, int, error) {
+	// We want ^ and $ to work as in sam/acme, so use ?m.
+	re, err := regexp.Compile("(?m:" + pattern + ")")
+	if err != nil {
+		return 0, 0, err
+	}
+	if dir == '-' {
+		// Could implement reverse search using binary search
+		// through file, but that seems like overkill.
+		return 0, 0, errors.New("reverse search not implemented")
+	}
+	m := re.FindIndex(data[hi:])
+	if len(m) > 0 {
+		m[0] += hi
+		m[1] += hi
+	} else if hi > 0 {
+		// No match.  Wrap to beginning of data.
+		m = re.FindIndex(data)
+	}
+	if len(m) == 0 {
+		return 0, 0, errors.New("no match for " + pattern)
+	}
+	return m[0], m[1], nil
+}
diff --git a/present/caption.go b/present/caption.go
new file mode 100644
index 0000000..00e0b5d
--- /dev/null
+++ b/present/caption.go
@@ -0,0 +1,22 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package present
+
+import "strings"
+
+func init() {
+	Register("caption", parseCaption)
+}
+
+type Caption struct {
+	Text string
+}
+
+func (c Caption) TemplateName() string { return "caption" }
+
+func parseCaption(_ *Context, _ string, _ int, text string) (Elem, error) {
+	text = strings.TrimSpace(strings.TrimPrefix(text, ".caption"))
+	return Caption{text}, nil
+}
diff --git a/present/code.go b/present/code.go
new file mode 100644
index 0000000..5a29951
--- /dev/null
+++ b/present/code.go
@@ -0,0 +1,293 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package present
+
+import (
+	"bufio"
+	"bytes"
+	"fmt"
+	"html/template"
+	"path/filepath"
+	"regexp"
+	"strconv"
+	"strings"
+)
+
+// Is the playground available?
+var PlayEnabled = false
+
+// TOOD(adg): replace the PlayEnabled flag with something less spaghetti-like.
+// Instead this will probably be determined by a template execution Context
+// value that contains various global metadata required when rendering
+// templates.
+
+func init() {
+	Register("code", parseCode)
+	Register("play", parseCode)
+}
+
+type Code struct {
+	Text     template.HTML
+	Play     bool   // runnable code
+	FileName string // file name
+	Ext      string // file extension
+	Raw      []byte // content of the file
+}
+
+func (c Code) TemplateName() string { return "code" }
+
+// The input line is a .code or .play entry with a file name and an optional HLfoo marker on the end.
+// Anything between the file and HL (if any) is an address expression, which we treat as a string here.
+// We pick off the HL first, for easy parsing.
+var (
+	highlightRE = regexp.MustCompile(`\s+HL([a-zA-Z0-9_]+)?$`)
+	hlCommentRE = regexp.MustCompile(`(.+) // HL(.*)$`)
+	codeRE      = regexp.MustCompile(`\.(code|play)\s+((?:(?:-edit|-numbers)\s+)*)([^\s]+)(?:\s+(.*))?$`)
+)
+
+// parseCode parses a code present directive. Its syntax:
+//   .code [-numbers] [-edit] <filename> [address] [highlight]
+// The directive may also be ".play" if the snippet is executable.
+func parseCode(ctx *Context, sourceFile string, sourceLine int, cmd string) (Elem, error) {
+	cmd = strings.TrimSpace(cmd)
+
+	// Pull off the HL, if any, from the end of the input line.
+	highlight := ""
+	if hl := highlightRE.FindStringSubmatchIndex(cmd); len(hl) == 4 {
+		highlight = cmd[hl[2]:hl[3]]
+		cmd = cmd[:hl[2]-2]
+	}
+
+	// Parse the remaining command line.
+	// Arguments:
+	// args[0]: whole match
+	// args[1]:  .code/.play
+	// args[2]: flags ("-edit -numbers")
+	// args[3]: file name
+	// args[4]: optional address
+	args := codeRE.FindStringSubmatch(cmd)
+	if len(args) != 5 {
+		return nil, fmt.Errorf("%s:%d: syntax error for .code/.play invocation", sourceFile, sourceLine)
+	}
+	command, flags, file, addr := args[1], args[2], args[3], strings.TrimSpace(args[4])
+	play := command == "play" && PlayEnabled
+
+	// Read in code file and (optionally) match address.
+	filename := filepath.Join(filepath.Dir(sourceFile), file)
+	textBytes, err := ctx.ReadFile(filename)
+	if err != nil {
+		return nil, fmt.Errorf("%s:%d: %v", sourceFile, sourceLine, err)
+	}
+	lo, hi, err := addrToByteRange(addr, 0, textBytes)
+	if err != nil {
+		return nil, fmt.Errorf("%s:%d: %v", sourceFile, sourceLine, err)
+	}
+
+	// Acme pattern matches can stop mid-line,
+	// so run to end of line in both directions if not at line start/end.
+	for lo > 0 && textBytes[lo-1] != '\n' {
+		lo--
+	}
+	if hi > 0 {
+		for hi < len(textBytes) && textBytes[hi-1] != '\n' {
+			hi++
+		}
+	}
+
+	lines := codeLines(textBytes, lo, hi)
+
+	data := &codeTemplateData{
+		Lines:   formatLines(lines, highlight),
+		Edit:    strings.Contains(flags, "-edit"),
+		Numbers: strings.Contains(flags, "-numbers"),
+	}
+
+	// Include before and after in a hidden span for playground code.
+	if play {
+		data.Prefix = textBytes[:lo]
+		data.Suffix = textBytes[hi:]
+	}
+
+	var buf bytes.Buffer
+	if err := codeTemplate.Execute(&buf, data); err != nil {
+		return nil, err
+	}
+	return Code{
+		Text:     template.HTML(buf.String()),
+		Play:     play,
+		FileName: filepath.Base(filename),
+		Ext:      filepath.Ext(filename),
+		Raw:      rawCode(lines),
+	}, nil
+}
+
+// formatLines returns a new slice of codeLine with the given lines
+// replacing tabs with spaces and adding highlighting where needed.
+func formatLines(lines []codeLine, highlight string) []codeLine {
+	formatted := make([]codeLine, len(lines))
+	for i, line := range lines {
+		// Replace tabs with spaces, which work better in HTML.
+		line.L = strings.Replace(line.L, "\t", "    ", -1)
+
+		// Highlight lines that end with "// HL[highlight]"
+		// and strip the magic comment.
+		if m := hlCommentRE.FindStringSubmatch(line.L); m != nil {
+			line.L = m[1]
+			line.HL = m[2] == highlight
+		}
+
+		formatted[i] = line
+	}
+	return formatted
+}
+
+// rawCode returns the code represented by the given codeLines without any kind
+// of formatting.
+func rawCode(lines []codeLine) []byte {
+	b := new(bytes.Buffer)
+	for _, line := range lines {
+		b.WriteString(line.L)
+		b.WriteByte('\n')
+	}
+	return b.Bytes()
+}
+
+type codeTemplateData struct {
+	Lines          []codeLine
+	Prefix, Suffix []byte
+	Edit, Numbers  bool
+}
+
+var leadingSpaceRE = regexp.MustCompile(`^[ \t]*`)
+
+var codeTemplate = template.Must(template.New("code").Funcs(template.FuncMap{
+	"trimSpace":    strings.TrimSpace,
+	"leadingSpace": leadingSpaceRE.FindString,
+}).Parse(codeTemplateHTML))
+
+const codeTemplateHTML = `
+{{with .Prefix}}<pre style="display: none"><span>{{printf "%s" .}}</span></pre>{{end}}
+
+<pre{{if .Edit}} contenteditable="true" spellcheck="false"{{end}}{{if .Numbers}} class="numbers"{{end}}>{{/*
+	*/}}{{range .Lines}}<span num="{{.N}}">{{/*
+	*/}}{{if .HL}}{{leadingSpace .L}}<b>{{trimSpace .L}}</b>{{/*
+	*/}}{{else}}{{.L}}{{end}}{{/*
+*/}}</span>
+{{end}}</pre>
+
+{{with .Suffix}}<pre style="display: none"><span>{{printf "%s" .}}</span></pre>{{end}}
+`
+
+// codeLine represents a line of code extracted from a source file.
+type codeLine struct {
+	L  string // The line of code.
+	N  int    // The line number from the source file.
+	HL bool   // Whether the line should be highlighted.
+}
+
+// codeLines takes a source file and returns the lines that
+// span the byte range specified by start and end.
+// It discards lines that end in "OMIT".
+func codeLines(src []byte, start, end int) (lines []codeLine) {
+	startLine := 1
+	for i, b := range src {
+		if i == start {
+			break
+		}
+		if b == '\n' {
+			startLine++
+		}
+	}
+	s := bufio.NewScanner(bytes.NewReader(src[start:end]))
+	for n := startLine; s.Scan(); n++ {
+		l := s.Text()
+		if strings.HasSuffix(l, "OMIT") {
+			continue
+		}
+		lines = append(lines, codeLine{L: l, N: n})
+	}
+	// Trim leading and trailing blank lines.
+	for len(lines) > 0 && len(lines[0].L) == 0 {
+		lines = lines[1:]
+	}
+	for len(lines) > 0 && len(lines[len(lines)-1].L) == 0 {
+		lines = lines[:len(lines)-1]
+	}
+	return
+}
+
+func parseArgs(name string, line int, args []string) (res []interface{}, err error) {
+	res = make([]interface{}, len(args))
+	for i, v := range args {
+		if len(v) == 0 {
+			return nil, fmt.Errorf("%s:%d bad code argument %q", name, line, v)
+		}
+		switch v[0] {
+		case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
+			n, err := strconv.Atoi(v)
+			if err != nil {
+				return nil, fmt.Errorf("%s:%d bad code argument %q", name, line, v)
+			}
+			res[i] = n
+		case '/':
+			if len(v) < 2 || v[len(v)-1] != '/' {
+				return nil, fmt.Errorf("%s:%d bad code argument %q", name, line, v)
+			}
+			res[i] = v
+		case '$':
+			res[i] = "$"
+		case '_':
+			if len(v) == 1 {
+				// Do nothing; "_" indicates an intentionally empty parameter.
+				break
+			}
+			fallthrough
+		default:
+			return nil, fmt.Errorf("%s:%d bad code argument %q", name, line, v)
+		}
+	}
+	return
+}
+
+// parseArg returns the integer or string value of the argument and tells which it is.
+func parseArg(arg interface{}, max int) (ival int, sval string, isInt bool, err error) {
+	switch n := arg.(type) {
+	case int:
+		if n <= 0 || n > max {
+			return 0, "", false, fmt.Errorf("%d is out of range", n)
+		}
+		return n, "", true, nil
+	case string:
+		return 0, n, false, nil
+	}
+	return 0, "", false, fmt.Errorf("unrecognized argument %v type %T", arg, arg)
+}
+
+// match identifies the input line that matches the pattern in a code invocation.
+// If start>0, match lines starting there rather than at the beginning.
+// The return value is 1-indexed.
+func match(file string, start int, lines []string, pattern string) (int, error) {
+	// $ matches the end of the file.
+	if pattern == "$" {
+		if len(lines) == 0 {
+			return 0, fmt.Errorf("%q: empty file", file)
+		}
+		return len(lines), nil
+	}
+	// /regexp/ matches the line that matches the regexp.
+	if len(pattern) > 2 && pattern[0] == '/' && pattern[len(pattern)-1] == '/' {
+		re, err := regexp.Compile(pattern[1 : len(pattern)-1])
+		if err != nil {
+			return 0, err
+		}
+		for i := start; i < len(lines); i++ {
+			if re.MatchString(lines[i]) {
+				return i + 1, nil
+			}
+		}
+		return 0, fmt.Errorf("%s: no match for %#q", file, pattern)
+	}
+	return 0, fmt.Errorf("unrecognized pattern: %q", pattern)
+}
diff --git a/present/doc.go b/present/doc.go
new file mode 100644
index 0000000..584e0c1
--- /dev/null
+++ b/present/doc.go
@@ -0,0 +1,205 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+/*
+The present file format
+
+Present files have the following format.  The first non-blank non-comment
+line is the title, so the header looks like
+
+	Title of document
+	Subtitle of document
+	15:04 2 Jan 2006
+	Tags: foo, bar, baz
+	<blank line>
+	Author Name
+	Job title, Company
+	joe@example.com
+	http://url/
+	@twitter_name
+
+The subtitle, date, and tags lines are optional.
+
+The date line may be written without a time:
+	2 Jan 2006
+In this case, the time will be interpreted as 10am UTC on that date.
+
+The tags line is a comma-separated list of tags that may be used to categorize
+the document.
+
+The author section may contain a mixture of text, twitter names, and links.
+For slide presentations, only the plain text lines will be displayed on the
+first slide.
+
+Multiple presenters may be specified, separated by a blank line.
+
+After that come slides/sections, each after a blank line:
+
+	* Title of slide or section (must have asterisk)
+
+	Some Text
+
+	** Subsection
+
+	- bullets
+	- more bullets
+	- a bullet with
+
+	*** Sub-subsection
+
+	Some More text
+
+	  Preformatted text
+	  is indented (however you like)
+
+	Further Text, including invocations like:
+
+	.code x.go /^func main/,/^}/
+	.play y.go
+	.image image.jpg
+	.iframe http://foo
+	.link http://foo label
+	.html file.html
+	.caption _Gopher_ by [[http://www.reneefrench.com][Renée French]]
+
+	Again, more text
+
+Blank lines are OK (not mandatory) after the title and after the
+text.  Text, bullets, and .code etc. are all optional; title is
+not.
+
+Lines starting with # in column 1 are commentary.
+
+Fonts:
+
+Within the input for plain text or lists, text bracketed by font
+markers will be presented in italic, bold, or program font.
+Marker characters are _ (italic), * (bold) and ` (program font).
+Unmatched markers appear as plain text.
+Within marked text, a single marker character becomes a space
+and a doubled single marker quotes the marker character.
+
+	_italic_
+	*bold*
+	`program`
+	_this_is_all_italic_
+	_Why_use_scoped__ptr_? Use plain ***ptr* instead.
+
+Inline links:
+
+Links can be included in any text with the form [[url][label]], or
+[[url]] to use the URL itself as the label.
+
+Functions:
+
+A number of template functions are available through invocations
+in the input text. Each such invocation contains a period as the
+first character on the line, followed immediately by the name of
+the function, followed by any arguments. A typical invocation might
+be
+	.play demo.go /^func show/,/^}/
+(except that the ".play" must be at the beginning of the line and
+not be indented like this.)
+
+Here follows a description of the functions:
+
+code:
+
+Injects program source into the output by extracting code from files
+and injecting them as HTML-escaped <pre> blocks.  The argument is
+a file name followed by an optional address that specifies what
+section of the file to display. The address syntax is similar in
+its simplest form to that of ed, but comes from sam and is more
+general. See
+	http://plan9.bell-labs.com/sys/doc/sam/sam.html Table II
+for full details. The displayed block is always rounded out to a
+full line at both ends.
+
+If no pattern is present, the entire file is displayed.
+
+Any line in the program that ends with the four characters
+	OMIT
+is deleted from the source before inclusion, making it easy
+to write things like
+	.code test.go /START OMIT/,/END OMIT/
+to find snippets like this
+	tedious_code = boring_function()
+	// START OMIT
+	interesting_code = fascinating_function()
+	// END OMIT
+and see only this:
+	interesting_code = fascinating_function()
+
+Also, inside the displayed text a line that ends
+	// HL
+will be highlighted in the display; the 'h' key in the browser will
+toggle extra emphasis of any highlighted lines. A highlighting mark
+may have a suffix word, such as
+	// HLxxx
+Such highlights are enabled only if the code invocation ends with
+"HL" followed by the word:
+	.code test.go /^type Foo/,/^}/ HLxxx
+
+The .code function may take one or more flags immediately preceding
+the filename. This command shows test.go in an editable text area:
+	.code -edit test.go
+This command shows test.go with line numbers:
+	.code -numbers test.go
+
+play:
+
+The function "play" is the same as "code" but puts a button
+on the displayed source so the program can be run from the browser.
+Although only the selected text is shown, all the source is included
+in the HTML output so it can be presented to the compiler.
+
+link:
+
+Create a hyperlink. The syntax is 1 or 2 space-separated arguments.
+The first argument is always the HTTP URL.  If there is a second
+argument, it is the text label to display for this link.
+
+	.link http://golang.org golang.org
+
+image:
+
+The template uses the function "image" to inject picture files.
+
+The syntax is simple: 1 or 3 space-separated arguments.
+The first argument is always the file name.
+If there are more arguments, they are the height and width;
+both must be present, or substituted with an underscore.
+Replacing a dimension argument with the underscore parameter
+preserves the aspect ratio of the image when scaling.
+
+	.image images/betsy.jpg 100 200
+
+	.image images/janet.jpg _ 300
+
+
+caption:
+
+The template uses the function "caption" to inject figure captions.
+
+The text after ".caption" is embedded in a figcaption element after
+processing styling and links as in standard text lines.
+
+	.caption _Gopher_ by [[http://www.reneefrench.com][Renée French]]
+
+iframe:
+
+The function "iframe" injects iframes (pages inside pages).
+Its syntax is the same as that of image.
+
+html:
+
+The function html includes the contents of the specified file as
+unescaped HTML. This is useful for including custom HTML elements
+that cannot be created using only the slide format.
+It is your responsibilty to make sure the included HTML is valid and safe.
+
+	.html file.html
+
+*/
+package present // import "golang.org/x/tools/present"
diff --git a/present/html.go b/present/html.go
new file mode 100644
index 0000000..cca90ef
--- /dev/null
+++ b/present/html.go
@@ -0,0 +1,31 @@
+package present
+
+import (
+	"errors"
+	"html/template"
+	"path/filepath"
+	"strings"
+)
+
+func init() {
+	Register("html", parseHTML)
+}
+
+func parseHTML(ctx *Context, fileName string, lineno int, text string) (Elem, error) {
+	p := strings.Fields(text)
+	if len(p) != 2 {
+		return nil, errors.New("invalid .html args")
+	}
+	name := filepath.Join(filepath.Dir(fileName), p[1])
+	b, err := ctx.ReadFile(name)
+	if err != nil {
+		return nil, err
+	}
+	return HTML{template.HTML(b)}, nil
+}
+
+type HTML struct {
+	template.HTML
+}
+
+func (s HTML) TemplateName() string { return "html" }
diff --git a/present/iframe.go b/present/iframe.go
new file mode 100644
index 0000000..2f3c5e5
--- /dev/null
+++ b/present/iframe.go
@@ -0,0 +1,45 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package present
+
+import (
+	"fmt"
+	"strings"
+)
+
+func init() {
+	Register("iframe", parseIframe)
+}
+
+type Iframe struct {
+	URL    string
+	Width  int
+	Height int
+}
+
+func (i Iframe) TemplateName() string { return "iframe" }
+
+func parseIframe(ctx *Context, fileName string, lineno int, text string) (Elem, error) {
+	args := strings.Fields(text)
+	i := Iframe{URL: args[1]}
+	a, err := parseArgs(fileName, lineno, args[2:])
+	if err != nil {
+		return nil, err
+	}
+	switch len(a) {
+	case 0:
+		// no size parameters
+	case 2:
+		if v, ok := a[0].(int); ok {
+			i.Height = v
+		}
+		if v, ok := a[1].(int); ok {
+			i.Width = v
+		}
+	default:
+		return nil, fmt.Errorf("incorrect image invocation: %q", text)
+	}
+	return i, nil
+}
diff --git a/present/image.go b/present/image.go
new file mode 100644
index 0000000..cfa2af9
--- /dev/null
+++ b/present/image.go
@@ -0,0 +1,50 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package present
+
+import (
+	"fmt"
+	"strings"
+)
+
+func init() {
+	Register("image", parseImage)
+}
+
+type Image struct {
+	URL    string
+	Width  int
+	Height int
+}
+
+func (i Image) TemplateName() string { return "image" }
+
+func parseImage(ctx *Context, fileName string, lineno int, text string) (Elem, error) {
+	args := strings.Fields(text)
+	img := Image{URL: args[1]}
+	a, err := parseArgs(fileName, lineno, args[2:])
+	if err != nil {
+		return nil, err
+	}
+	switch len(a) {
+	case 0:
+		// no size parameters
+	case 2:
+		// If a parameter is empty (underscore) or invalid
+		// leave the field set to zero. The "image" action
+		// template will then omit that img tag attribute and
+		// the browser will calculate the value to preserve
+		// the aspect ratio.
+		if v, ok := a[0].(int); ok {
+			img.Height = v
+		}
+		if v, ok := a[1].(int); ok {
+			img.Width = v
+		}
+	default:
+		return nil, fmt.Errorf("incorrect image invocation: %q", text)
+	}
+	return img, nil
+}
diff --git a/present/link.go b/present/link.go
new file mode 100644
index 0000000..6b0968f
--- /dev/null
+++ b/present/link.go
@@ -0,0 +1,97 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package present
+
+import (
+	"fmt"
+	"log"
+	"net/url"
+	"strings"
+)
+
+func init() {
+	Register("link", parseLink)
+}
+
+type Link struct {
+	URL   *url.URL
+	Label string
+}
+
+func (l Link) TemplateName() string { return "link" }
+
+func parseLink(ctx *Context, fileName string, lineno int, text string) (Elem, error) {
+	args := strings.Fields(text)
+	url, err := url.Parse(args[1])
+	if err != nil {
+		return nil, err
+	}
+	label := ""
+	if len(args) > 2 {
+		label = strings.Join(args[2:], " ")
+	} else {
+		scheme := url.Scheme + "://"
+		if url.Scheme == "mailto" {
+			scheme = "mailto:"
+		}
+		label = strings.Replace(url.String(), scheme, "", 1)
+	}
+	return Link{url, label}, nil
+}
+
+func renderLink(href, text string) string {
+	text = font(text)
+	if text == "" {
+		text = href
+	}
+	// Open links in new window only when their url is absolute.
+	target := "_blank"
+	if u, err := url.Parse(href); err != nil {
+		log.Println("rendernLink parsing url:", err)
+	} else if !u.IsAbs() || u.Scheme == "javascript" {
+		target = "_self"
+	}
+
+	return fmt.Sprintf(`<a href="%s" target="%s">%s</a>`, href, target, text)
+}
+
+// parseInlineLink parses an inline link at the start of s, and returns
+// a rendered HTML link and the total length of the raw inline link.
+// If no inline link is present, it returns all zeroes.
+func parseInlineLink(s string) (link string, length int) {
+	if !strings.HasPrefix(s, "[[") {
+		return
+	}
+	end := strings.Index(s, "]]")
+	if end == -1 {
+		return
+	}
+	urlEnd := strings.Index(s, "]")
+	rawURL := s[2:urlEnd]
+	const badURLChars = `<>"{}|\^[] ` + "`" // per RFC2396 section 2.4.3
+	if strings.ContainsAny(rawURL, badURLChars) {
+		return
+	}
+	if urlEnd == end {
+		simpleUrl := ""
+		url, err := url.Parse(rawURL)
+		if err == nil {
+			// If the URL is http://foo.com, drop the http://
+			// In other words, render [[http://golang.org]] as:
+			//   <a href="http://golang.org">golang.org</a>
+			if strings.HasPrefix(rawURL, url.Scheme+"://") {
+				simpleUrl = strings.TrimPrefix(rawURL, url.Scheme+"://")
+			} else if strings.HasPrefix(rawURL, url.Scheme+":") {
+				simpleUrl = strings.TrimPrefix(rawURL, url.Scheme+":")
+			}
+		}
+		return renderLink(rawURL, simpleUrl), end + 2
+	}
+	if s[urlEnd:urlEnd+2] != "][" {
+		return
+	}
+	text := s[urlEnd+2 : end]
+	return renderLink(rawURL, text), end + 2
+}
diff --git a/present/link_test.go b/present/link_test.go
new file mode 100644
index 0000000..334e72b
--- /dev/null
+++ b/present/link_test.go
@@ -0,0 +1,40 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package present
+
+import "testing"
+
+func TestInlineParsing(t *testing.T) {
+	var tests = []struct {
+		in     string
+		link   string
+		text   string
+		length int
+	}{
+		{"[[http://golang.org]]", "http://golang.org", "golang.org", 21},
+		{"[[http://golang.org][]]", "http://golang.org", "http://golang.org", 23},
+		{"[[http://golang.org]] this is ignored", "http://golang.org", "golang.org", 21},
+		{"[[http://golang.org][link]]", "http://golang.org", "link", 27},
+		{"[[http://golang.org][two words]]", "http://golang.org", "two words", 32},
+		{"[[http://golang.org][*link*]]", "http://golang.org", "<b>link</b>", 29},
+		{"[[http://bad[url]]", "", "", 0},
+		{"[[http://golang.org][a [[link]] ]]", "http://golang.org", "a [[link", 31},
+		{"[[http:// *spaces* .com]]", "", "", 0},
+		{"[[http://bad`char.com]]", "", "", 0},
+		{" [[http://google.com]]", "", "", 0},
+		{"[[mailto:gopher@golang.org][Gopher]]", "mailto:gopher@golang.org", "Gopher", 36},
+		{"[[mailto:gopher@golang.org]]", "mailto:gopher@golang.org", "gopher@golang.org", 28},
+	}
+
+	for i, test := range tests {
+		link, length := parseInlineLink(test.in)
+		if length == 0 && test.length == 0 {
+			continue
+		}
+		if a := renderLink(test.link, test.text); length != test.length || link != a {
+			t.Errorf("#%d: parseInlineLink(%q):\ngot\t%q, %d\nwant\t%q, %d", i, test.in, link, length, a, test.length)
+		}
+	}
+}
diff --git a/present/parse.go b/present/parse.go
new file mode 100644
index 0000000..449d5ed
--- /dev/null
+++ b/present/parse.go
@@ -0,0 +1,505 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package present
+
+import (
+	"bufio"
+	"bytes"
+	"errors"
+	"fmt"
+	"html/template"
+	"io"
+	"io/ioutil"
+	"log"
+	"net/url"
+	"regexp"
+	"strings"
+	"time"
+	"unicode"
+	"unicode/utf8"
+)
+
+var (
+	parsers = make(map[string]ParseFunc)
+	funcs   = template.FuncMap{}
+)
+
+// Template returns an empty template with the action functions in its FuncMap.
+func Template() *template.Template {
+	return template.New("").Funcs(funcs)
+}
+
+// Render renders the doc to the given writer using the provided template.
+func (d *Doc) Render(w io.Writer, t *template.Template) error {
+	data := struct {
+		*Doc
+		Template    *template.Template
+		PlayEnabled bool
+	}{d, t, PlayEnabled}
+	return t.ExecuteTemplate(w, "root", data)
+}
+
+// Render renders the section to the given writer using the provided template.
+func (s *Section) Render(w io.Writer, t *template.Template) error {
+	data := struct {
+		*Section
+		Template    *template.Template
+		PlayEnabled bool
+	}{s, t, PlayEnabled}
+	return t.ExecuteTemplate(w, "section", data)
+}
+
+type ParseFunc func(ctx *Context, fileName string, lineNumber int, inputLine string) (Elem, error)
+
+// Register binds the named action, which does not begin with a period, to the
+// specified parser to be invoked when the name, with a period, appears in the
+// present input text.
+func Register(name string, parser ParseFunc) {
+	if len(name) == 0 || name[0] == ';' {
+		panic("bad name in Register: " + name)
+	}
+	parsers["."+name] = parser
+}
+
+// Doc represents an entire document.
+type Doc struct {
+	Title    string
+	Subtitle string
+	Time     time.Time
+	Authors  []Author
+	Sections []Section
+	Tags     []string
+}
+
+// Author represents the person who wrote and/or is presenting the document.
+type Author struct {
+	Elem []Elem
+}
+
+// TextElem returns the first text elements of the author details.
+// This is used to display the author' name, job title, and company
+// without the contact details.
+func (p *Author) TextElem() (elems []Elem) {
+	for _, el := range p.Elem {
+		if _, ok := el.(Text); !ok {
+			break
+		}
+		elems = append(elems, el)
+	}
+	return
+}
+
+// Section represents a section of a document (such as a presentation slide)
+// comprising a title and a list of elements.
+type Section struct {
+	Number []int
+	Title  string
+	Elem   []Elem
+}
+
+func (s Section) Sections() (sections []Section) {
+	for _, e := range s.Elem {
+		if section, ok := e.(Section); ok {
+			sections = append(sections, section)
+		}
+	}
+	return
+}
+
+// Level returns the level of the given section.
+// The document title is level 1, main section 2, etc.
+func (s Section) Level() int {
+	return len(s.Number) + 1
+}
+
+// FormattedNumber returns a string containing the concatenation of the
+// numbers identifying a Section.
+func (s Section) FormattedNumber() string {
+	b := &bytes.Buffer{}
+	for _, n := range s.Number {
+		fmt.Fprintf(b, "%v.", n)
+	}
+	return b.String()
+}
+
+func (s Section) TemplateName() string { return "section" }
+
+// Elem defines the interface for a present element. That is, something that
+// can provide the name of the template used to render the element.
+type Elem interface {
+	TemplateName() string
+}
+
+// renderElem implements the elem template function, used to render
+// sub-templates.
+func renderElem(t *template.Template, e Elem) (template.HTML, error) {
+	var data interface{} = e
+	if s, ok := e.(Section); ok {
+		data = struct {
+			Section
+			Template *template.Template
+		}{s, t}
+	}
+	return execTemplate(t, e.TemplateName(), data)
+}
+
+func init() {
+	funcs["elem"] = renderElem
+}
+
+// execTemplate is a helper to execute a template and return the output as a
+// template.HTML value.
+func execTemplate(t *template.Template, name string, data interface{}) (template.HTML, error) {
+	b := new(bytes.Buffer)
+	err := t.ExecuteTemplate(b, name, data)
+	if err != nil {
+		return "", err
+	}
+	return template.HTML(b.String()), nil
+}
+
+// Text represents an optionally preformatted paragraph.
+type Text struct {
+	Lines []string
+	Pre   bool
+}
+
+func (t Text) TemplateName() string { return "text" }
+
+// List represents a bulleted list.
+type List struct {
+	Bullet []string
+}
+
+func (l List) TemplateName() string { return "list" }
+
+// Lines is a helper for parsing line-based input.
+type Lines struct {
+	line int // 0 indexed, so has 1-indexed number of last line returned
+	text []string
+}
+
+func readLines(r io.Reader) (*Lines, error) {
+	var lines []string
+	s := bufio.NewScanner(r)
+	for s.Scan() {
+		lines = append(lines, s.Text())
+	}
+	if err := s.Err(); err != nil {
+		return nil, err
+	}
+	return &Lines{0, lines}, nil
+}
+
+func (l *Lines) next() (text string, ok bool) {
+	for {
+		current := l.line
+		l.line++
+		if current >= len(l.text) {
+			return "", false
+		}
+		text = l.text[current]
+		// Lines starting with # are comments.
+		if len(text) == 0 || text[0] != '#' {
+			ok = true
+			break
+		}
+	}
+	return
+}
+
+func (l *Lines) back() {
+	l.line--
+}
+
+func (l *Lines) nextNonEmpty() (text string, ok bool) {
+	for {
+		text, ok = l.next()
+		if !ok {
+			return
+		}
+		if len(text) > 0 {
+			break
+		}
+	}
+	return
+}
+
+// A Context specifies the supporting context for parsing a presentation.
+type Context struct {
+	// ReadFile reads the file named by filename and returns the contents.
+	ReadFile func(filename string) ([]byte, error)
+}
+
+// ParseMode represents flags for the Parse function.
+type ParseMode int
+
+const (
+	// If set, parse only the title and subtitle.
+	TitlesOnly ParseMode = 1
+)
+
+// Parse parses a document from r.
+func (ctx *Context) Parse(r io.Reader, name string, mode ParseMode) (*Doc, error) {
+	doc := new(Doc)
+	lines, err := readLines(r)
+	if err != nil {
+		return nil, err
+	}
+	err = parseHeader(doc, lines)
+	if err != nil {
+		return nil, err
+	}
+	if mode&TitlesOnly != 0 {
+		return doc, nil
+	}
+	// Authors
+	if doc.Authors, err = parseAuthors(lines); err != nil {
+		return nil, err
+	}
+	// Sections
+	if doc.Sections, err = parseSections(ctx, name, lines, []int{}, doc); err != nil {
+		return nil, err
+	}
+	return doc, nil
+}
+
+// Parse parses a document from r. Parse reads assets used by the presentation
+// from the file system using ioutil.ReadFile.
+func Parse(r io.Reader, name string, mode ParseMode) (*Doc, error) {
+	ctx := Context{ReadFile: ioutil.ReadFile}
+	return ctx.Parse(r, name, mode)
+}
+
+// isHeading matches any section heading.
+var isHeading = regexp.MustCompile(`^\*+ `)
+
+// lesserHeading returns true if text is a heading of a lesser or equal level
+// than that denoted by prefix.
+func lesserHeading(text, prefix string) bool {
+	return isHeading.MatchString(text) && !strings.HasPrefix(text, prefix+"*")
+}
+
+// parseSections parses Sections from lines for the section level indicated by
+// number (a nil number indicates the top level).
+func parseSections(ctx *Context, name string, lines *Lines, number []int, doc *Doc) ([]Section, error) {
+	var sections []Section
+	for i := 1; ; i++ {
+		// Next non-empty line is title.
+		text, ok := lines.nextNonEmpty()
+		for ok && text == "" {
+			text, ok = lines.next()
+		}
+		if !ok {
+			break
+		}
+		prefix := strings.Repeat("*", len(number)+1)
+		if !strings.HasPrefix(text, prefix+" ") {
+			lines.back()
+			break
+		}
+		section := Section{
+			Number: append(append([]int{}, number...), i),
+			Title:  text[len(prefix)+1:],
+		}
+		text, ok = lines.nextNonEmpty()
+		for ok && !lesserHeading(text, prefix) {
+			var e Elem
+			r, _ := utf8.DecodeRuneInString(text)
+			switch {
+			case unicode.IsSpace(r):
+				i := strings.IndexFunc(text, func(r rune) bool {
+					return !unicode.IsSpace(r)
+				})
+				if i < 0 {
+					break
+				}
+				indent := text[:i]
+				var s []string
+				for ok && (strings.HasPrefix(text, indent) || text == "") {
+					if text != "" {
+						text = text[i:]
+					}
+					s = append(s, text)
+					text, ok = lines.next()
+				}
+				lines.back()
+				pre := strings.Join(s, "\n")
+				pre = strings.Replace(pre, "\t", "    ", -1) // browsers treat tabs badly
+				pre = strings.TrimRightFunc(pre, unicode.IsSpace)
+				e = Text{Lines: []string{pre}, Pre: true}
+			case strings.HasPrefix(text, "- "):
+				var b []string
+				for ok && strings.HasPrefix(text, "- ") {
+					b = append(b, text[2:])
+					text, ok = lines.next()
+				}
+				lines.back()
+				e = List{Bullet: b}
+			case strings.HasPrefix(text, prefix+"* "):
+				lines.back()
+				subsecs, err := parseSections(ctx, name, lines, section.Number, doc)
+				if err != nil {
+					return nil, err
+				}
+				for _, ss := range subsecs {
+					section.Elem = append(section.Elem, ss)
+				}
+			case strings.HasPrefix(text, "."):
+				args := strings.Fields(text)
+				parser := parsers[args[0]]
+				if parser == nil {
+					return nil, fmt.Errorf("%s:%d: unknown command %q\n", name, lines.line, text)
+				}
+				t, err := parser(ctx, name, lines.line, text)
+				if err != nil {
+					return nil, err
+				}
+				e = t
+			default:
+				var l []string
+				for ok && strings.TrimSpace(text) != "" {
+					if text[0] == '.' { // Command breaks text block.
+						break
+					}
+					if strings.HasPrefix(text, `\.`) { // Backslash escapes initial period.
+						text = text[1:]
+					}
+					l = append(l, text)
+					text, ok = lines.next()
+				}
+				if len(l) > 0 {
+					e = Text{Lines: l}
+				}
+			}
+			if e != nil {
+				section.Elem = append(section.Elem, e)
+			}
+			text, ok = lines.nextNonEmpty()
+		}
+		if isHeading.MatchString(text) {
+			lines.back()
+		}
+		sections = append(sections, section)
+	}
+	return sections, nil
+}
+
+func parseHeader(doc *Doc, lines *Lines) error {
+	var ok bool
+	// First non-empty line starts header.
+	doc.Title, ok = lines.nextNonEmpty()
+	if !ok {
+		return errors.New("unexpected EOF; expected title")
+	}
+	for {
+		text, ok := lines.next()
+		if !ok {
+			return errors.New("unexpected EOF")
+		}
+		if text == "" {
+			break
+		}
+		const tagPrefix = "Tags:"
+		if strings.HasPrefix(text, tagPrefix) {
+			tags := strings.Split(text[len(tagPrefix):], ",")
+			for i := range tags {
+				tags[i] = strings.TrimSpace(tags[i])
+			}
+			doc.Tags = append(doc.Tags, tags...)
+		} else if t, ok := parseTime(text); ok {
+			doc.Time = t
+		} else if doc.Subtitle == "" {
+			doc.Subtitle = text
+		} else {
+			return fmt.Errorf("unexpected header line: %q", text)
+		}
+	}
+	return nil
+}
+
+func parseAuthors(lines *Lines) (authors []Author, err error) {
+	// This grammar demarcates authors with blanks.
+
+	// Skip blank lines.
+	if _, ok := lines.nextNonEmpty(); !ok {
+		return nil, errors.New("unexpected EOF")
+	}
+	lines.back()
+
+	var a *Author
+	for {
+		text, ok := lines.next()
+		if !ok {
+			return nil, errors.New("unexpected EOF")
+		}
+
+		// If we find a section heading, we're done.
+		if strings.HasPrefix(text, "* ") {
+			lines.back()
+			break
+		}
+
+		// If we encounter a blank we're done with this author.
+		if a != nil && len(text) == 0 {
+			authors = append(authors, *a)
+			a = nil
+			continue
+		}
+		if a == nil {
+			a = new(Author)
+		}
+
+		// Parse the line. Those that
+		// - begin with @ are twitter names,
+		// - contain slashes are links, or
+		// - contain an @ symbol are an email address.
+		// The rest is just text.
+		var el Elem
+		switch {
+		case strings.HasPrefix(text, "@"):
+			el = parseURL("http://twitter.com/" + text[1:])
+		case strings.Contains(text, ":"):
+			el = parseURL(text)
+		case strings.Contains(text, "@"):
+			el = parseURL("mailto:" + text)
+		}
+		if l, ok := el.(Link); ok {
+			l.Label = text
+			el = l
+		}
+		if el == nil {
+			el = Text{Lines: []string{text}}
+		}
+		a.Elem = append(a.Elem, el)
+	}
+	if a != nil {
+		authors = append(authors, *a)
+	}
+	return authors, nil
+}
+
+func parseURL(text string) Elem {
+	u, err := url.Parse(text)
+	if err != nil {
+		log.Printf("Parse(%q): %v", text, err)
+		return nil
+	}
+	return Link{URL: u}
+}
+
+func parseTime(text string) (t time.Time, ok bool) {
+	t, err := time.Parse("15:04 2 Jan 2006", text)
+	if err == nil {
+		return t, true
+	}
+	t, err = time.Parse("2 Jan 2006", text)
+	if err == nil {
+		// at 11am UTC it is the same date everywhere
+		t = t.Add(time.Hour * 11)
+		return t, true
+	}
+	return time.Time{}, false
+}
diff --git a/present/style.go b/present/style.go
new file mode 100644
index 0000000..1cd240d
--- /dev/null
+++ b/present/style.go
@@ -0,0 +1,166 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package present
+
+import (
+	"bytes"
+	"html"
+	"html/template"
+	"strings"
+	"unicode"
+	"unicode/utf8"
+)
+
+/*
+	Fonts are demarcated by an initial and final char bracketing a
+	space-delimited word, plus possibly some terminal punctuation.
+	The chars are
+		_ for italic
+		* for bold
+		` (back quote) for fixed width.
+	Inner appearances of the char become spaces. For instance,
+		_this_is_italic_!
+	becomes
+		<i>this is italic</i>!
+*/
+
+func init() {
+	funcs["style"] = Style
+}
+
+// Style returns s with HTML entities escaped and font indicators turned into
+// HTML font tags.
+func Style(s string) template.HTML {
+	return template.HTML(font(html.EscapeString(s)))
+}
+
+// font returns s with font indicators turned into HTML font tags.
+func font(s string) string {
+	if strings.IndexAny(s, "[`_*") == -1 {
+		return s
+	}
+	words := split(s)
+	var b bytes.Buffer
+Word:
+	for w, word := range words {
+		if len(word) < 2 {
+			continue Word
+		}
+		if link, _ := parseInlineLink(word); link != "" {
+			words[w] = link
+			continue Word
+		}
+		const punctuation = `.,;:()!?—–'"`
+		const marker = "_*`"
+		// Initial punctuation is OK but must be peeled off.
+		first := strings.IndexAny(word, marker)
+		if first == -1 {
+			continue Word
+		}
+		// Is the marker prefixed only by punctuation?
+		for _, r := range word[:first] {
+			if !strings.ContainsRune(punctuation, r) {
+				continue Word
+			}
+		}
+		open, word := word[:first], word[first:]
+		char := word[0] // ASCII is OK.
+		close := ""
+		switch char {
+		default:
+			continue Word
+		case '_':
+			open += "<i>"
+			close = "</i>"
+		case '*':
+			open += "<b>"
+			close = "</b>"
+		case '`':
+			open += "<code>"
+			close = "</code>"
+		}
+		// Terminal punctuation is OK but must be peeled off.
+		last := strings.LastIndex(word, word[:1])
+		if last == 0 {
+			continue Word
+		}
+		head, tail := word[:last+1], word[last+1:]
+		for _, r := range tail {
+			if !strings.ContainsRune(punctuation, r) {
+				continue Word
+			}
+		}
+		b.Reset()
+		b.WriteString(open)
+		var wid int
+		for i := 1; i < len(head)-1; i += wid {
+			var r rune
+			r, wid = utf8.DecodeRuneInString(head[i:])
+			if r != rune(char) {
+				// Ordinary character.
+				b.WriteRune(r)
+				continue
+			}
+			if head[i+1] != char {
+				// Inner char becomes space.
+				b.WriteRune(' ')
+				continue
+			}
+			// Doubled char becomes real char.
+			// Not worth worrying about "_x__".
+			b.WriteByte(char)
+			wid++ // Consumed two chars, both ASCII.
+		}
+		b.WriteString(close) // Write closing tag.
+		b.WriteString(tail)  // Restore trailing punctuation.
+		words[w] = b.String()
+	}
+	return strings.Join(words, "")
+}
+
+// split is like strings.Fields but also returns the runs of spaces
+// and treats inline links as distinct words.
+func split(s string) []string {
+	var (
+		words = make([]string, 0, 10)
+		start = 0
+	)
+
+	// appendWord appends the string s[start:end] to the words slice.
+	// If the word contains the beginning of a link, the non-link portion
+	// of the word and the entire link are appended as separate words,
+	// and the start index is advanced to the end of the link.
+	appendWord := func(end int) {
+		if j := strings.Index(s[start:end], "[["); j > -1 {
+			if _, l := parseInlineLink(s[start+j:]); l > 0 {
+				// Append portion before link, if any.
+				if j > 0 {
+					words = append(words, s[start:start+j])
+				}
+				// Append link itself.
+				words = append(words, s[start+j:start+j+l])
+				// Advance start index to end of link.
+				start = start + j + l
+				return
+			}
+		}
+		// No link; just add the word.
+		words = append(words, s[start:end])
+		start = end
+	}
+
+	wasSpace := false
+	for i, r := range s {
+		isSpace := unicode.IsSpace(r)
+		if i > start && isSpace != wasSpace {
+			appendWord(i)
+		}
+		wasSpace = isSpace
+	}
+	for start < len(s) {
+		appendWord(len(s))
+	}
+	return words
+}
diff --git a/present/style_test.go b/present/style_test.go
new file mode 100644
index 0000000..d04db72
--- /dev/null
+++ b/present/style_test.go
@@ -0,0 +1,116 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package present
+
+import (
+	"fmt"
+	"reflect"
+	"testing"
+)
+
+func TestSplit(t *testing.T) {
+	var tests = []struct {
+		in  string
+		out []string
+	}{
+		{"", []string{}},
+		{" ", []string{" "}},
+		{"abc", []string{"abc"}},
+		{"abc def", []string{"abc", " ", "def"}},
+		{"abc def ", []string{"abc", " ", "def", " "}},
+		{"hey [[http://golang.org][Gophers]] around",
+			[]string{"hey", " ", "[[http://golang.org][Gophers]]", " ", "around"}},
+		{"A [[http://golang.org/doc][two words]] link",
+			[]string{"A", " ", "[[http://golang.org/doc][two words]]", " ", "link"}},
+		{"Visit [[http://golang.org/doc]] now",
+			[]string{"Visit", " ", "[[http://golang.org/doc]]", " ", "now"}},
+		{"not [[http://golang.org/doc][a [[link]] ]] around",
+			[]string{"not", " ", "[[http://golang.org/doc][a [[link]]", " ", "]]", " ", "around"}},
+		{"[[http://golang.org][foo bar]]",
+			[]string{"[[http://golang.org][foo bar]]"}},
+		{"ends with [[http://golang.org][link]]",
+			[]string{"ends", " ", "with", " ", "[[http://golang.org][link]]"}},
+		{"my talk ([[http://talks.golang.org/][slides here]])",
+			[]string{"my", " ", "talk", " ", "(", "[[http://talks.golang.org/][slides here]]", ")"}},
+	}
+	for _, test := range tests {
+		out := split(test.in)
+		if !reflect.DeepEqual(out, test.out) {
+			t.Errorf("split(%q):\ngot\t%q\nwant\t%q", test.in, out, test.out)
+		}
+	}
+}
+
+func TestFont(t *testing.T) {
+	var tests = []struct {
+		in  string
+		out string
+	}{
+		{"", ""},
+		{" ", " "},
+		{"\tx", "\tx"},
+		{"_a_", "<i>a</i>"},
+		{"*a*", "<b>a</b>"},
+		{"`a`", "<code>a</code>"},
+		{"_a_b_", "<i>a b</i>"},
+		{"_a__b_", "<i>a_b</i>"},
+		{"_a___b_", "<i>a_ b</i>"},
+		{"*a**b*?", "<b>a*b</b>?"},
+		{"_a_<>_b_.", "<i>a <> b</i>."},
+		{"(_a_)", "(<i>a</i>)"},
+		{"((_a_), _b_, _c_).", "((<i>a</i>), <i>b</i>, <i>c</i>)."},
+		{"(_a)", "(_a)"},
+		{"(_a)", "(_a)"},
+		{"_Why_use_scoped__ptr_? Use plain ***ptr* instead.", "<i>Why use scoped_ptr</i>? Use plain <b>*ptr</b> instead."},
+		{"_hey_ [[http://golang.org][*Gophers*]] *around*",
+			`<i>hey</i> <a href="http://golang.org" target="_blank"><b>Gophers</b></a> <b>around</b>`},
+		{"_hey_ [[http://golang.org][so _many_ *Gophers*]] *around*",
+			`<i>hey</i> <a href="http://golang.org" target="_blank">so <i>many</i> <b>Gophers</b></a> <b>around</b>`},
+		{"Visit [[http://golang.org]] now",
+			`Visit <a href="http://golang.org" target="_blank">golang.org</a> now`},
+		{"my talk ([[http://talks.golang.org/][slides here]])",
+			`my talk (<a href="http://talks.golang.org/" target="_blank">slides here</a>)`},
+	}
+	for _, test := range tests {
+		out := font(test.in)
+		if out != test.out {
+			t.Errorf("font(%q):\ngot\t%q\nwant\t%q", test.in, out, test.out)
+		}
+	}
+}
+
+func TestStyle(t *testing.T) {
+	var tests = []struct {
+		in  string
+		out string
+	}{
+		{"", ""},
+		{" ", " "},
+		{"\tx", "\tx"},
+		{"_a_", "<i>a</i>"},
+		{"*a*", "<b>a</b>"},
+		{"`a`", "<code>a</code>"},
+		{"_a_b_", "<i>a b</i>"},
+		{"_a__b_", "<i>a_b</i>"},
+		{"_a___b_", "<i>a_ b</i>"},
+		{"*a**b*?", "<b>a*b</b>?"},
+		{"_a_<>_b_.", "<i>a &lt;&gt; b</i>."},
+		{"(_a_<>_b_)", "(<i>a &lt;&gt; b</i>)"},
+		{"((_a_), _b_, _c_).", "((<i>a</i>), <i>b</i>, <i>c</i>)."},
+		{"(_a)", "(_a)"},
+	}
+	for _, test := range tests {
+		out := string(Style(test.in))
+		if out != test.out {
+			t.Errorf("style(%q):\ngot\t%q\nwant\t%q", test.in, out, test.out)
+		}
+	}
+}
+
+func ExampleStyle() {
+	const s = "*Gophers* are _clearly_ > *cats*!"
+	fmt.Println(Style(s))
+	// Output: <b>Gophers</b> are <i>clearly</i> &gt; <b>cats</b>!
+}
diff --git a/refactor/README b/refactor/README
new file mode 100644
index 0000000..a315784
--- /dev/null
+++ b/refactor/README
@@ -0,0 +1 @@
+golang.org/x/tools/refactor: libraries for refactoring tools.
diff --git a/refactor/eg/eg.go b/refactor/eg/eg.go
new file mode 100644
index 0000000..a609255
--- /dev/null
+++ b/refactor/eg/eg.go
@@ -0,0 +1,351 @@
+// Package eg implements the example-based refactoring tool whose
+// command-line is defined in golang.org/x/tools/cmd/eg.
+package eg // import "golang.org/x/tools/refactor/eg"
+
+import (
+	"bytes"
+	"fmt"
+	"go/ast"
+	"go/format"
+	"go/printer"
+	"go/token"
+	"os"
+
+	"golang.org/x/tools/go/loader"
+	"golang.org/x/tools/go/types"
+)
+
+const Help = `
+This tool implements example-based refactoring of expressions.
+
+The transformation is specified as a Go file defining two functions,
+'before' and 'after', of identical types.  Each function body consists
+of a single statement: either a return statement with a single
+(possibly multi-valued) expression, or an expression statement.  The
+'before' expression specifies a pattern and the 'after' expression its
+replacement.
+
+	package P
+ 	import ( "errors"; "fmt" )
+ 	func before(s string) error { return fmt.Errorf("%s", s) }
+ 	func after(s string)  error { return errors.New(s) }
+
+The expression statement form is useful when the expression has no
+result, for example:
+
+ 	func before(msg string) { log.Fatalf("%s", msg) }
+ 	func after(msg string)  { log.Fatal(msg) }
+
+The parameters of both functions are wildcards that may match any
+expression assignable to that type.  If the pattern contains multiple
+occurrences of the same parameter, each must match the same expression
+in the input for the pattern to match.  If the replacement contains
+multiple occurrences of the same parameter, the expression will be
+duplicated, possibly changing the side-effects.
+
+The tool analyses all Go code in the packages specified by the
+arguments, replacing all occurrences of the pattern with the
+substitution.
+
+So, the transform above would change this input:
+	err := fmt.Errorf("%s", "error: " + msg)
+to this output:
+	err := errors.New("error: " + msg)
+
+Identifiers, including qualified identifiers (p.X) are considered to
+match only if they denote the same object.  This allows correct
+matching even in the presence of dot imports, named imports and
+locally shadowed package names in the input program.
+
+Matching of type syntax is semantic, not syntactic: type syntax in the
+pattern matches type syntax in the input if the types are identical.
+Thus, func(x int) matches func(y int).
+
+This tool was inspired by other example-based refactoring tools,
+'gofmt -r' for Go and Refaster for Java.
+
+
+LIMITATIONS
+===========
+
+EXPRESSIVENESS
+
+Only refactorings that replace one expression with another, regardless
+of the expression's context, may be expressed.  Refactoring arbitrary
+statements (or sequences of statements) is a less well-defined problem
+and is less amenable to this approach.
+
+A pattern that contains a function literal (and hence statements)
+never matches.
+
+There is no way to generalize over related types, e.g. to express that
+a wildcard may have any integer type, for example.
+
+It is not possible to replace an expression by one of a different
+type, even in contexts where this is legal, such as x in fmt.Print(x).
+
+The struct literals T{x} and T{K: x} cannot both be matched by a single
+template.
+
+
+SAFETY
+
+Verifying that a transformation does not introduce type errors is very
+complex in the general case.  An innocuous-looking replacement of one
+constant by another (e.g. 1 to 2) may cause type errors relating to
+array types and indices, for example.  The tool performs only very
+superficial checks of type preservation.
+
+
+IMPORTS
+
+Although the matching algorithm is fully aware of scoping rules, the
+replacement algorithm is not, so the replacement code may contain
+incorrect identifier syntax for imported objects if there are dot
+imports, named imports or locally shadowed package names in the input
+program.
+
+Imports are added as needed, but they are not removed as needed.
+Run 'goimports' on the modified file for now.
+
+Dot imports are forbidden in the template.
+
+
+TIPS
+====
+
+Sometimes a little creativity is required to implement the desired
+migration.  This section lists a few tips and tricks.
+
+To remove the final parameter from a function, temporarily change the
+function signature so that the final parameter is variadic, as this
+allows legal calls both with and without the argument.  Then use eg to
+remove the final argument from all callers, and remove the variadic
+parameter by hand.  The reverse process can be used to add a final
+parameter.
+
+To add or remove parameters other than the final one, you must do it in
+stages: (1) declare a variant function f' with a different name and the
+desired parameters; (2) use eg to transform calls to f into calls to f',
+changing the arguments as needed; (3) change the declaration of f to
+match f'; (4) use eg to rename f' to f in all calls; (5) delete f'.
+`
+
+// TODO(adonovan): allow the tool to be invoked using relative package
+// directory names (./foo).  Requires changes to go/loader.
+
+// TODO(adonovan): expand upon the above documentation as an HTML page.
+
+// TODO(adonovan): eliminate dependency on loader.PackageInfo.
+// Move its TypeOf method into go/types.
+
+// A Transformer represents a single example-based transformation.
+type Transformer struct {
+	fset           *token.FileSet
+	verbose        bool
+	info           loader.PackageInfo // combined type info for template/input/output ASTs
+	seenInfos      map[*types.Info]bool
+	wildcards      map[*types.Var]bool                // set of parameters in func before()
+	env            map[string]ast.Expr                // maps parameter name to wildcard binding
+	importedObjs   map[types.Object]*ast.SelectorExpr // objects imported by after().
+	before, after  ast.Expr
+	allowWildcards bool
+
+	// Working state of Transform():
+	nsubsts    int            // number of substitutions made
+	currentPkg *types.Package // package of current call
+}
+
+// NewTransformer returns a transformer based on the specified template,
+// a package containing "before" and "after" functions as described
+// in the package documentation.
+//
+func NewTransformer(fset *token.FileSet, template *loader.PackageInfo, verbose bool) (*Transformer, error) {
+	// Check the template.
+	beforeSig := funcSig(template.Pkg, "before")
+	if beforeSig == nil {
+		return nil, fmt.Errorf("no 'before' func found in template")
+	}
+	afterSig := funcSig(template.Pkg, "after")
+	if afterSig == nil {
+		return nil, fmt.Errorf("no 'after' func found in template")
+	}
+
+	// TODO(adonovan): should we also check the names of the params match?
+	if !types.Identical(afterSig, beforeSig) {
+		return nil, fmt.Errorf("before %s and after %s functions have different signatures",
+			beforeSig, afterSig)
+	}
+
+	templateFile := template.Files[0]
+	for _, imp := range templateFile.Imports {
+		if imp.Name != nil && imp.Name.Name == "." {
+			// Dot imports are currently forbidden.  We
+			// make the simplifying assumption that all
+			// imports are regular, without local renames.
+			//TODO document
+			return nil, fmt.Errorf("dot-import (of %s) in template", imp.Path.Value)
+		}
+	}
+	var beforeDecl, afterDecl *ast.FuncDecl
+	for _, decl := range templateFile.Decls {
+		if decl, ok := decl.(*ast.FuncDecl); ok {
+			switch decl.Name.Name {
+			case "before":
+				beforeDecl = decl
+			case "after":
+				afterDecl = decl
+			}
+		}
+	}
+
+	before, err := soleExpr(beforeDecl)
+	if err != nil {
+		return nil, fmt.Errorf("before: %s", err)
+	}
+	after, err := soleExpr(afterDecl)
+	if err != nil {
+		return nil, fmt.Errorf("after: %s", err)
+	}
+
+	wildcards := make(map[*types.Var]bool)
+	for i := 0; i < beforeSig.Params().Len(); i++ {
+		wildcards[beforeSig.Params().At(i)] = true
+	}
+
+	// checkExprTypes returns an error if Tb (type of before()) is not
+	// safe to replace with Ta (type of after()).
+	//
+	// Only superficial checks are performed, and they may result in both
+	// false positives and negatives.
+	//
+	// Ideally, we would only require that the replacement be assignable
+	// to the context of a specific pattern occurrence, but the type
+	// checker doesn't record that information and it's complex to deduce.
+	// A Go type cannot capture all the constraints of a given expression
+	// context, which may include the size, constness, signedness,
+	// namedness or constructor of its type, and even the specific value
+	// of the replacement.  (Consider the rule that array literal keys
+	// must be unique.)  So we cannot hope to prove the safety of a
+	// transformation in general.
+	Tb := template.TypeOf(before)
+	Ta := template.TypeOf(after)
+	if types.AssignableTo(Tb, Ta) {
+		// safe: replacement is assignable to pattern.
+	} else if tuple, ok := Tb.(*types.Tuple); ok && tuple.Len() == 0 {
+		// safe: pattern has void type (must appear in an ExprStmt).
+	} else {
+		return nil, fmt.Errorf("%s is not a safe replacement for %s", Ta, Tb)
+	}
+
+	tr := &Transformer{
+		fset:           fset,
+		verbose:        verbose,
+		wildcards:      wildcards,
+		allowWildcards: true,
+		seenInfos:      make(map[*types.Info]bool),
+		importedObjs:   make(map[types.Object]*ast.SelectorExpr),
+		before:         before,
+		after:          after,
+	}
+
+	// Combine type info from the template and input packages, and
+	// type info for the synthesized ASTs too.  This saves us
+	// having to book-keep where each ast.Node originated as we
+	// construct the resulting hybrid AST.
+	//
+	// TODO(adonovan): move type utility methods of PackageInfo to
+	// types.Info, or at least into go/types.typeutil.
+	tr.info.Info = types.Info{
+		Types:      make(map[ast.Expr]types.TypeAndValue),
+		Defs:       make(map[*ast.Ident]types.Object),
+		Uses:       make(map[*ast.Ident]types.Object),
+		Selections: make(map[*ast.SelectorExpr]*types.Selection),
+	}
+	mergeTypeInfo(&tr.info.Info, &template.Info)
+
+	// Compute set of imported objects required by after().
+	// TODO reject dot-imports in pattern
+	ast.Inspect(after, func(n ast.Node) bool {
+		if n, ok := n.(*ast.SelectorExpr); ok {
+			if _, ok := tr.info.Selections[n]; !ok {
+				// qualified ident
+				obj := tr.info.Uses[n.Sel]
+				tr.importedObjs[obj] = n
+				return false // prune
+			}
+		}
+		return true // recur
+	})
+
+	return tr, nil
+}
+
+// WriteAST is a convenience function that writes AST f to the specified file.
+func WriteAST(fset *token.FileSet, filename string, f *ast.File) (err error) {
+	fh, err := os.Create(filename)
+	if err != nil {
+		return err
+	}
+	defer func() {
+		if err2 := fh.Close(); err != nil {
+			err = err2 // prefer earlier error
+		}
+	}()
+	return format.Node(fh, fset, f)
+}
+
+// -- utilities --------------------------------------------------------
+
+// funcSig returns the signature of the specified package-level function.
+func funcSig(pkg *types.Package, name string) *types.Signature {
+	if f, ok := pkg.Scope().Lookup(name).(*types.Func); ok {
+		return f.Type().(*types.Signature)
+	}
+	return nil
+}
+
+// soleExpr returns the sole expression in the before/after template function.
+func soleExpr(fn *ast.FuncDecl) (ast.Expr, error) {
+	if fn.Body == nil {
+		return nil, fmt.Errorf("no body")
+	}
+	if len(fn.Body.List) != 1 {
+		return nil, fmt.Errorf("must contain a single statement")
+	}
+	switch stmt := fn.Body.List[0].(type) {
+	case *ast.ReturnStmt:
+		if len(stmt.Results) != 1 {
+			return nil, fmt.Errorf("return statement must have a single operand")
+		}
+		return stmt.Results[0], nil
+
+	case *ast.ExprStmt:
+		return stmt.X, nil
+	}
+
+	return nil, fmt.Errorf("must contain a single return or expression statement")
+}
+
+// mergeTypeInfo adds type info from src to dst.
+func mergeTypeInfo(dst, src *types.Info) {
+	for k, v := range src.Types {
+		dst.Types[k] = v
+	}
+	for k, v := range src.Defs {
+		dst.Defs[k] = v
+	}
+	for k, v := range src.Uses {
+		dst.Uses[k] = v
+	}
+	for k, v := range src.Selections {
+		dst.Selections[k] = v
+	}
+}
+
+// (debugging only)
+func astString(fset *token.FileSet, n ast.Node) string {
+	var buf bytes.Buffer
+	printer.Fprint(&buf, fset, n)
+	return buf.String()
+}
diff --git a/refactor/eg/eg_test.go b/refactor/eg/eg_test.go
new file mode 100644
index 0000000..295e842
--- /dev/null
+++ b/refactor/eg/eg_test.go
@@ -0,0 +1,160 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// No testdata on Android.
+
+// +build !android
+
+package eg_test
+
+import (
+	"bytes"
+	"flag"
+	"go/parser"
+	"go/token"
+	"os"
+	"os/exec"
+	"path/filepath"
+	"runtime"
+	"strings"
+	"testing"
+
+	"golang.org/x/tools/go/exact"
+	"golang.org/x/tools/go/loader"
+	"golang.org/x/tools/go/types"
+	"golang.org/x/tools/refactor/eg"
+)
+
+// TODO(adonovan): more tests:
+// - of command-line tool
+// - of all parts of syntax
+// - of applying a template to a package it imports:
+//   the replacement syntax should use unqualified names for its objects.
+
+var (
+	updateFlag  = flag.Bool("update", false, "update the golden files")
+	verboseFlag = flag.Bool("verbose", false, "show matcher information")
+)
+
+func Test(t *testing.T) {
+	switch runtime.GOOS {
+	case "windows":
+		t.Skipf("skipping test on %q (no /usr/bin/diff)", runtime.GOOS)
+	}
+
+	conf := loader.Config{
+		Fset:       token.NewFileSet(),
+		ParserMode: parser.ParseComments,
+	}
+
+	// Each entry is a single-file package.
+	// (Multi-file packages aren't interesting for this test.)
+	// Order matters: each non-template package is processed using
+	// the preceding template package.
+	for _, filename := range []string{
+		"testdata/A.template",
+		"testdata/A1.go",
+		"testdata/A2.go",
+
+		"testdata/B.template",
+		"testdata/B1.go",
+
+		"testdata/C.template",
+		"testdata/C1.go",
+
+		"testdata/D.template",
+		"testdata/D1.go",
+
+		"testdata/E.template",
+		"testdata/E1.go",
+
+		"testdata/F.template",
+		"testdata/F1.go",
+
+		"testdata/G.template",
+		"testdata/G1.go",
+
+		"testdata/H.template",
+		"testdata/H1.go",
+
+		"testdata/bad_type.template",
+		"testdata/no_before.template",
+		"testdata/no_after_return.template",
+		"testdata/type_mismatch.template",
+		"testdata/expr_type_mismatch.template",
+	} {
+		pkgname := strings.TrimSuffix(filepath.Base(filename), ".go")
+		conf.CreateFromFilenames(pkgname, filename)
+	}
+	iprog, err := conf.Load()
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	var xform *eg.Transformer
+	for _, info := range iprog.Created {
+		file := info.Files[0]
+		filename := iprog.Fset.File(file.Pos()).Name() // foo.go
+
+		if strings.HasSuffix(filename, "template") {
+			// a new template
+			shouldFail, _ := info.Pkg.Scope().Lookup("shouldFail").(*types.Const)
+			xform, err = eg.NewTransformer(iprog.Fset, info, *verboseFlag)
+			if err != nil {
+				if shouldFail == nil {
+					t.Errorf("NewTransformer(%s): %s", filename, err)
+				} else if want := exact.StringVal(shouldFail.Val()); !strings.Contains(err.Error(), want) {
+					t.Errorf("NewTransformer(%s): got error %q, want error %q", filename, err, want)
+				}
+			} else if shouldFail != nil {
+				t.Errorf("NewTransformer(%s) succeeded unexpectedly; want error %q",
+					filename, shouldFail.Val())
+			}
+			continue
+		}
+
+		if xform == nil {
+			t.Errorf("%s: no previous template", filename)
+			continue
+		}
+
+		// apply previous template to this package
+		n := xform.Transform(&info.Info, info.Pkg, file)
+		if n == 0 {
+			t.Errorf("%s: no matches", filename)
+			continue
+		}
+
+		got := filename + "t"       // foo.got
+		golden := filename + "lden" // foo.golden
+
+		// Write actual output to foo.got.
+		if err := eg.WriteAST(iprog.Fset, got, file); err != nil {
+			t.Error(err)
+		}
+		defer os.Remove(got)
+
+		// Compare foo.got with foo.golden.
+		var cmd *exec.Cmd
+		switch runtime.GOOS {
+		case "plan9":
+			cmd = exec.Command("/bin/diff", "-c", golden, got)
+		default:
+			cmd = exec.Command("/usr/bin/diff", "-u", golden, got)
+		}
+		buf := new(bytes.Buffer)
+		cmd.Stdout = buf
+		cmd.Stderr = os.Stderr
+		if err := cmd.Run(); err != nil {
+			t.Errorf("eg tests for %s failed: %s.\n%s\n", filename, err, buf)
+
+			if *updateFlag {
+				t.Logf("Updating %s...", golden)
+				if err := exec.Command("/bin/cp", got, golden).Run(); err != nil {
+					t.Errorf("Update failed: %s", err)
+				}
+			}
+		}
+	}
+}
diff --git a/refactor/eg/match.go b/refactor/eg/match.go
new file mode 100644
index 0000000..d8590d4
--- /dev/null
+++ b/refactor/eg/match.go
@@ -0,0 +1,246 @@
+package eg
+
+import (
+	"fmt"
+	"go/ast"
+	"go/token"
+	"log"
+	"os"
+	"reflect"
+
+	"golang.org/x/tools/go/ast/astutil"
+	"golang.org/x/tools/go/exact"
+	"golang.org/x/tools/go/loader"
+	"golang.org/x/tools/go/types"
+)
+
+// matchExpr reports whether pattern x matches y.
+//
+// If tr.allowWildcards, Idents in x that refer to parameters are
+// treated as wildcards, and match any y that is assignable to the
+// parameter type; matchExpr records this correspondence in tr.env.
+// Otherwise, matchExpr simply reports whether the two trees are
+// equivalent.
+//
+// A wildcard appearing more than once in the pattern must
+// consistently match the same tree.
+//
+func (tr *Transformer) matchExpr(x, y ast.Expr) bool {
+	if x == nil && y == nil {
+		return true
+	}
+	if x == nil || y == nil {
+		return false
+	}
+	x = unparen(x)
+	y = unparen(y)
+
+	// Is x a wildcard?  (a reference to a 'before' parameter)
+	if xobj, ok := tr.wildcardObj(x); ok {
+		return tr.matchWildcard(xobj, y)
+	}
+
+	// Object identifiers (including pkg-qualified ones)
+	// are handled semantically, not syntactically.
+	xobj := isRef(x, &tr.info)
+	yobj := isRef(y, &tr.info)
+	if xobj != nil {
+		return xobj == yobj
+	}
+	if yobj != nil {
+		return false
+	}
+
+	// TODO(adonovan): audit: we cannot assume these ast.Exprs
+	// contain non-nil pointers.  e.g. ImportSpec.Name may be a
+	// nil *ast.Ident.
+
+	if reflect.TypeOf(x) != reflect.TypeOf(y) {
+		return false
+	}
+	switch x := x.(type) {
+	case *ast.Ident:
+		log.Fatalf("unexpected Ident: %s", astString(tr.fset, x))
+
+	case *ast.BasicLit:
+		y := y.(*ast.BasicLit)
+		xval := exact.MakeFromLiteral(x.Value, x.Kind)
+		yval := exact.MakeFromLiteral(y.Value, y.Kind)
+		return exact.Compare(xval, token.EQL, yval)
+
+	case *ast.FuncLit:
+		// func literals (and thus statement syntax) never match.
+		return false
+
+	case *ast.CompositeLit:
+		y := y.(*ast.CompositeLit)
+		return (x.Type == nil) == (y.Type == nil) &&
+			(x.Type == nil || tr.matchType(x.Type, y.Type)) &&
+			tr.matchExprs(x.Elts, y.Elts)
+
+	case *ast.SelectorExpr:
+		y := y.(*ast.SelectorExpr)
+		return tr.matchSelectorExpr(x, y) &&
+			tr.info.Selections[x].Obj() == tr.info.Selections[y].Obj()
+
+	case *ast.IndexExpr:
+		y := y.(*ast.IndexExpr)
+		return tr.matchExpr(x.X, y.X) &&
+			tr.matchExpr(x.Index, y.Index)
+
+	case *ast.SliceExpr:
+		y := y.(*ast.SliceExpr)
+		return tr.matchExpr(x.X, y.X) &&
+			tr.matchExpr(x.Low, y.Low) &&
+			tr.matchExpr(x.High, y.High) &&
+			tr.matchExpr(x.Max, y.Max) &&
+			x.Slice3 == y.Slice3
+
+	case *ast.TypeAssertExpr:
+		y := y.(*ast.TypeAssertExpr)
+		return tr.matchExpr(x.X, y.X) &&
+			tr.matchType(x.Type, y.Type)
+
+	case *ast.CallExpr:
+		y := y.(*ast.CallExpr)
+		match := tr.matchExpr // function call
+		if tr.info.Types[x.Fun].IsType() {
+			match = tr.matchType // type conversion
+		}
+		return x.Ellipsis.IsValid() == y.Ellipsis.IsValid() &&
+			match(x.Fun, y.Fun) &&
+			tr.matchExprs(x.Args, y.Args)
+
+	case *ast.StarExpr:
+		y := y.(*ast.StarExpr)
+		return tr.matchExpr(x.X, y.X)
+
+	case *ast.UnaryExpr:
+		y := y.(*ast.UnaryExpr)
+		return x.Op == y.Op &&
+			tr.matchExpr(x.X, y.X)
+
+	case *ast.BinaryExpr:
+		y := y.(*ast.BinaryExpr)
+		return x.Op == y.Op &&
+			tr.matchExpr(x.X, y.X) &&
+			tr.matchExpr(x.Y, y.Y)
+
+	case *ast.KeyValueExpr:
+		y := y.(*ast.KeyValueExpr)
+		return tr.matchExpr(x.Key, y.Key) &&
+			tr.matchExpr(x.Value, y.Value)
+	}
+
+	panic(fmt.Sprintf("unhandled AST node type: %T", x))
+}
+
+func (tr *Transformer) matchExprs(xx, yy []ast.Expr) bool {
+	if len(xx) != len(yy) {
+		return false
+	}
+	for i := range xx {
+		if !tr.matchExpr(xx[i], yy[i]) {
+			return false
+		}
+	}
+	return true
+}
+
+// matchType reports whether the two type ASTs denote identical types.
+func (tr *Transformer) matchType(x, y ast.Expr) bool {
+	tx := tr.info.Types[x].Type
+	ty := tr.info.Types[y].Type
+	return types.Identical(tx, ty)
+}
+
+func (tr *Transformer) wildcardObj(x ast.Expr) (*types.Var, bool) {
+	if x, ok := x.(*ast.Ident); ok && x != nil && tr.allowWildcards {
+		if xobj, ok := tr.info.Uses[x].(*types.Var); ok && tr.wildcards[xobj] {
+			return xobj, true
+		}
+	}
+	return nil, false
+}
+
+func (tr *Transformer) matchSelectorExpr(x, y *ast.SelectorExpr) bool {
+	if xobj, ok := tr.wildcardObj(x.X); ok {
+		field := x.Sel.Name
+		yt := tr.info.TypeOf(y.X)
+		o, _, _ := types.LookupFieldOrMethod(yt, true, tr.currentPkg, field)
+		if o != nil {
+			tr.env[xobj.Name()] = y.X // record binding
+			return true
+		}
+	}
+	return tr.matchExpr(x.X, y.X)
+}
+
+func (tr *Transformer) matchWildcard(xobj *types.Var, y ast.Expr) bool {
+	name := xobj.Name()
+
+	if tr.verbose {
+		fmt.Fprintf(os.Stderr, "%s: wildcard %s -> %s?: ",
+			tr.fset.Position(y.Pos()), name, astString(tr.fset, y))
+	}
+
+	// Check that y is assignable to the declared type of the param.
+	yt := tr.info.TypeOf(y)
+	if yt == nil {
+		// y has no type.
+		// Perhaps it is an *ast.Ellipsis in [...]T{}, or
+		// an *ast.KeyValueExpr in T{k: v}.
+		// Clearly these pseudo-expressions cannot match a
+		// wildcard, but it would nice if we had a way to ignore
+		// the difference between T{v} and T{k:v} for structs.
+		return false
+	}
+	if !types.AssignableTo(yt, xobj.Type()) {
+		if tr.verbose {
+			fmt.Fprintf(os.Stderr, "%s not assignable to %s\n", yt, xobj.Type())
+		}
+		return false
+	}
+
+	// A wildcard matches any expression.
+	// If it appears multiple times in the pattern, it must match
+	// the same expression each time.
+	if old, ok := tr.env[name]; ok {
+		// found existing binding
+		tr.allowWildcards = false
+		r := tr.matchExpr(old, y)
+		if tr.verbose {
+			fmt.Fprintf(os.Stderr, "%t secondary match, primary was %s\n",
+				r, astString(tr.fset, old))
+		}
+		tr.allowWildcards = true
+		return r
+	}
+
+	if tr.verbose {
+		fmt.Fprintf(os.Stderr, "primary match\n")
+	}
+
+	tr.env[name] = y // record binding
+	return true
+}
+
+// -- utilities --------------------------------------------------------
+
+func unparen(e ast.Expr) ast.Expr { return astutil.Unparen(e) }
+
+// isRef returns the object referred to by this (possibly qualified)
+// identifier, or nil if the node is not a referring identifier.
+func isRef(n ast.Node, info *loader.PackageInfo) types.Object {
+	switch n := n.(type) {
+	case *ast.Ident:
+		return info.Uses[n]
+
+	case *ast.SelectorExpr:
+		if _, ok := info.Selections[n]; !ok {
+			// qualified ident
+			return info.Uses[n.Sel]
+		}
+	}
+	return nil
+}
diff --git a/refactor/eg/rewrite.go b/refactor/eg/rewrite.go
new file mode 100644
index 0000000..db9c693
--- /dev/null
+++ b/refactor/eg/rewrite.go
@@ -0,0 +1,340 @@
+package eg
+
+// This file defines the AST rewriting pass.
+// Most of it was plundered directly from
+// $GOROOT/src/cmd/gofmt/rewrite.go (after convergent evolution).
+
+import (
+	"fmt"
+	"go/ast"
+	"go/token"
+	"os"
+	"reflect"
+	"sort"
+	"strconv"
+	"strings"
+
+	"golang.org/x/tools/go/ast/astutil"
+	"golang.org/x/tools/go/types"
+)
+
+// Transform applies the transformation to the specified parsed file,
+// whose type information is supplied in info, and returns the number
+// of replacements that were made.
+//
+// It mutates the AST in place (the identity of the root node is
+// unchanged), and may add nodes for which no type information is
+// available in info.
+//
+// Derived from rewriteFile in $GOROOT/src/cmd/gofmt/rewrite.go.
+//
+func (tr *Transformer) Transform(info *types.Info, pkg *types.Package, file *ast.File) int {
+	if !tr.seenInfos[info] {
+		tr.seenInfos[info] = true
+		mergeTypeInfo(&tr.info.Info, info)
+	}
+	tr.currentPkg = pkg
+	tr.nsubsts = 0
+
+	if tr.verbose {
+		fmt.Fprintf(os.Stderr, "before: %s\n", astString(tr.fset, tr.before))
+		fmt.Fprintf(os.Stderr, "after: %s\n", astString(tr.fset, tr.after))
+	}
+
+	var f func(rv reflect.Value) reflect.Value
+	f = func(rv reflect.Value) reflect.Value {
+		// don't bother if val is invalid to start with
+		if !rv.IsValid() {
+			return reflect.Value{}
+		}
+
+		rv = apply(f, rv)
+
+		e := rvToExpr(rv)
+		if e != nil {
+			savedEnv := tr.env
+			tr.env = make(map[string]ast.Expr) // inefficient!  Use a slice of k/v pairs
+
+			if tr.matchExpr(tr.before, e) {
+				if tr.verbose {
+					fmt.Fprintf(os.Stderr, "%s matches %s",
+						astString(tr.fset, tr.before), astString(tr.fset, e))
+					if len(tr.env) > 0 {
+						fmt.Fprintf(os.Stderr, " with:")
+						for name, ast := range tr.env {
+							fmt.Fprintf(os.Stderr, " %s->%s",
+								name, astString(tr.fset, ast))
+						}
+					}
+					fmt.Fprintf(os.Stderr, "\n")
+				}
+				tr.nsubsts++
+
+				// Clone the replacement tree, performing parameter substitution.
+				// We update all positions to n.Pos() to aid comment placement.
+				rv = tr.subst(tr.env, reflect.ValueOf(tr.after),
+					reflect.ValueOf(e.Pos()))
+			}
+			tr.env = savedEnv
+		}
+
+		return rv
+	}
+	file2 := apply(f, reflect.ValueOf(file)).Interface().(*ast.File)
+
+	// By construction, the root node is unchanged.
+	if file != file2 {
+		panic("BUG")
+	}
+
+	// Add any necessary imports.
+	// TODO(adonovan): remove no-longer needed imports too.
+	if tr.nsubsts > 0 {
+		pkgs := make(map[string]*types.Package)
+		for obj := range tr.importedObjs {
+			pkgs[obj.Pkg().Path()] = obj.Pkg()
+		}
+
+		for _, imp := range file.Imports {
+			path, _ := strconv.Unquote(imp.Path.Value)
+			delete(pkgs, path)
+		}
+		delete(pkgs, pkg.Path()) // don't import self
+
+		// NB: AddImport may completely replace the AST!
+		// It thus renders info and tr.info no longer relevant to file.
+		var paths []string
+		for path := range pkgs {
+			paths = append(paths, path)
+		}
+		sort.Strings(paths)
+		for _, path := range paths {
+			astutil.AddImport(tr.fset, file, path)
+		}
+	}
+
+	tr.currentPkg = nil
+
+	return tr.nsubsts
+}
+
+// setValue is a wrapper for x.SetValue(y); it protects
+// the caller from panics if x cannot be changed to y.
+func setValue(x, y reflect.Value) {
+	// don't bother if y is invalid to start with
+	if !y.IsValid() {
+		return
+	}
+	defer func() {
+		if x := recover(); x != nil {
+			if s, ok := x.(string); ok &&
+				(strings.Contains(s, "type mismatch") || strings.Contains(s, "not assignable")) {
+				// x cannot be set to y - ignore this rewrite
+				return
+			}
+			panic(x)
+		}
+	}()
+	x.Set(y)
+}
+
+// Values/types for special cases.
+var (
+	objectPtrNil = reflect.ValueOf((*ast.Object)(nil))
+	scopePtrNil  = reflect.ValueOf((*ast.Scope)(nil))
+
+	identType        = reflect.TypeOf((*ast.Ident)(nil))
+	selectorExprType = reflect.TypeOf((*ast.SelectorExpr)(nil))
+	objectPtrType    = reflect.TypeOf((*ast.Object)(nil))
+	positionType     = reflect.TypeOf(token.NoPos)
+	callExprType     = reflect.TypeOf((*ast.CallExpr)(nil))
+	scopePtrType     = reflect.TypeOf((*ast.Scope)(nil))
+)
+
+// apply replaces each AST field x in val with f(x), returning val.
+// To avoid extra conversions, f operates on the reflect.Value form.
+func apply(f func(reflect.Value) reflect.Value, val reflect.Value) reflect.Value {
+	if !val.IsValid() {
+		return reflect.Value{}
+	}
+
+	// *ast.Objects introduce cycles and are likely incorrect after
+	// rewrite; don't follow them but replace with nil instead
+	if val.Type() == objectPtrType {
+		return objectPtrNil
+	}
+
+	// similarly for scopes: they are likely incorrect after a rewrite;
+	// replace them with nil
+	if val.Type() == scopePtrType {
+		return scopePtrNil
+	}
+
+	switch v := reflect.Indirect(val); v.Kind() {
+	case reflect.Slice:
+		for i := 0; i < v.Len(); i++ {
+			e := v.Index(i)
+			setValue(e, f(e))
+		}
+	case reflect.Struct:
+		for i := 0; i < v.NumField(); i++ {
+			e := v.Field(i)
+			setValue(e, f(e))
+		}
+	case reflect.Interface:
+		e := v.Elem()
+		setValue(v, f(e))
+	}
+	return val
+}
+
+// subst returns a copy of (replacement) pattern with values from env
+// substituted in place of wildcards and pos used as the position of
+// tokens from the pattern.  if env == nil, subst returns a copy of
+// pattern and doesn't change the line number information.
+func (tr *Transformer) subst(env map[string]ast.Expr, pattern, pos reflect.Value) reflect.Value {
+	if !pattern.IsValid() {
+		return reflect.Value{}
+	}
+
+	// *ast.Objects introduce cycles and are likely incorrect after
+	// rewrite; don't follow them but replace with nil instead
+	if pattern.Type() == objectPtrType {
+		return objectPtrNil
+	}
+
+	// similarly for scopes: they are likely incorrect after a rewrite;
+	// replace them with nil
+	if pattern.Type() == scopePtrType {
+		return scopePtrNil
+	}
+
+	// Wildcard gets replaced with map value.
+	if env != nil && pattern.Type() == identType {
+		id := pattern.Interface().(*ast.Ident)
+		if old, ok := env[id.Name]; ok {
+			return tr.subst(nil, reflect.ValueOf(old), reflect.Value{})
+		}
+	}
+
+	// Emit qualified identifiers in the pattern by appropriate
+	// (possibly qualified) identifier in the input.
+	//
+	// The template cannot contain dot imports, so all identifiers
+	// for imported objects are explicitly qualified.
+	//
+	// We assume (unsoundly) that there are no dot or named
+	// imports in the input code, nor are any imported package
+	// names shadowed, so the usual normal qualified identifier
+	// syntax may be used.
+	// TODO(adonovan): fix: avoid this assumption.
+	//
+	// A refactoring may be applied to a package referenced by the
+	// template.  Objects belonging to the current package are
+	// denoted by unqualified identifiers.
+	//
+	if tr.importedObjs != nil && pattern.Type() == selectorExprType {
+		obj := isRef(pattern.Interface().(*ast.SelectorExpr), &tr.info)
+		if obj != nil {
+			if sel, ok := tr.importedObjs[obj]; ok {
+				var id ast.Expr
+				if obj.Pkg() == tr.currentPkg {
+					id = sel.Sel // unqualified
+				} else {
+					id = sel // pkg-qualified
+				}
+
+				// Return a clone of id.
+				saved := tr.importedObjs
+				tr.importedObjs = nil // break cycle
+				r := tr.subst(nil, reflect.ValueOf(id), pos)
+				tr.importedObjs = saved
+				return r
+			}
+		}
+	}
+
+	if pos.IsValid() && pattern.Type() == positionType {
+		// use new position only if old position was valid in the first place
+		if old := pattern.Interface().(token.Pos); !old.IsValid() {
+			return pattern
+		}
+		return pos
+	}
+
+	// Otherwise copy.
+	switch p := pattern; p.Kind() {
+	case reflect.Slice:
+		v := reflect.MakeSlice(p.Type(), p.Len(), p.Len())
+		for i := 0; i < p.Len(); i++ {
+			v.Index(i).Set(tr.subst(env, p.Index(i), pos))
+		}
+		return v
+
+	case reflect.Struct:
+		v := reflect.New(p.Type()).Elem()
+		for i := 0; i < p.NumField(); i++ {
+			v.Field(i).Set(tr.subst(env, p.Field(i), pos))
+		}
+		return v
+
+	case reflect.Ptr:
+		v := reflect.New(p.Type()).Elem()
+		if elem := p.Elem(); elem.IsValid() {
+			v.Set(tr.subst(env, elem, pos).Addr())
+		}
+
+		// Duplicate type information for duplicated ast.Expr.
+		// All ast.Node implementations are *structs,
+		// so this case catches them all.
+		if e := rvToExpr(v); e != nil {
+			updateTypeInfo(&tr.info.Info, e, p.Interface().(ast.Expr))
+		}
+		return v
+
+	case reflect.Interface:
+		v := reflect.New(p.Type()).Elem()
+		if elem := p.Elem(); elem.IsValid() {
+			v.Set(tr.subst(env, elem, pos))
+		}
+		return v
+	}
+
+	return pattern
+}
+
+// -- utilities -------------------------------------------------------
+
+func rvToExpr(rv reflect.Value) ast.Expr {
+	if rv.CanInterface() {
+		if e, ok := rv.Interface().(ast.Expr); ok {
+			return e
+		}
+	}
+	return nil
+}
+
+// updateTypeInfo duplicates type information for the existing AST old
+// so that it also applies to duplicated AST new.
+func updateTypeInfo(info *types.Info, new, old ast.Expr) {
+	switch new := new.(type) {
+	case *ast.Ident:
+		orig := old.(*ast.Ident)
+		if obj, ok := info.Defs[orig]; ok {
+			info.Defs[new] = obj
+		}
+		if obj, ok := info.Uses[orig]; ok {
+			info.Uses[new] = obj
+		}
+
+	case *ast.SelectorExpr:
+		orig := old.(*ast.SelectorExpr)
+		if sel, ok := info.Selections[orig]; ok {
+			info.Selections[new] = sel
+		}
+	}
+
+	if tv, ok := info.Types[old]; ok {
+		info.Types[new] = tv
+	}
+}
diff --git a/refactor/eg/testdata/A.template b/refactor/eg/testdata/A.template
new file mode 100644
index 0000000..f611961
--- /dev/null
+++ b/refactor/eg/testdata/A.template
@@ -0,0 +1,13 @@
+// +build ignore
+
+package template
+
+// Basic test of type-aware expression refactoring.
+
+import (
+	"errors"
+	"fmt"
+)
+
+func before(s string) error { return fmt.Errorf("%s", s) }
+func after(s string) error  { return errors.New(s) }
diff --git a/refactor/eg/testdata/A1.go b/refactor/eg/testdata/A1.go
new file mode 100644
index 0000000..9e65eb3
--- /dev/null
+++ b/refactor/eg/testdata/A1.go
@@ -0,0 +1,51 @@
+// +build ignore
+
+package A1
+
+import (
+	. "fmt"
+	myfmt "fmt"
+	"os"
+	"strings"
+)
+
+func example(n int) {
+	x := "foo" + strings.Repeat("\t", n)
+	// Match, despite named import.
+	myfmt.Errorf("%s", x)
+
+	// Match, despite dot import.
+	Errorf("%s", x)
+
+	// Match: multiple matches in same function are possible.
+	myfmt.Errorf("%s", x)
+
+	// No match: wildcarded operand has the wrong type.
+	myfmt.Errorf("%s", 3)
+
+	// No match: function operand doesn't match.
+	myfmt.Printf("%s", x)
+
+	// No match again, dot import.
+	Printf("%s", x)
+
+	// Match.
+	myfmt.Fprint(os.Stderr, myfmt.Errorf("%s", x+"foo"))
+
+	// No match: though this literally matches the template,
+	// fmt doesn't resolve to a package here.
+	var fmt struct{ Errorf func(string, string) }
+	fmt.Errorf("%s", x)
+
+	// Recursive matching:
+
+	// Match: both matches are well-typed, so both succeed.
+	myfmt.Errorf("%s", myfmt.Errorf("%s", x+"foo").Error())
+
+	// Outer match succeeds, inner doesn't: 3 has wrong type.
+	myfmt.Errorf("%s", myfmt.Errorf("%s", 3).Error())
+
+	// Inner match succeeds, outer doesn't: the inner replacement
+	// has the wrong type (error not string).
+	myfmt.Errorf("%s", myfmt.Errorf("%s", x+"foo"))
+}
diff --git a/refactor/eg/testdata/A1.golden b/refactor/eg/testdata/A1.golden
new file mode 100644
index 0000000..7eb2934
--- /dev/null
+++ b/refactor/eg/testdata/A1.golden
@@ -0,0 +1,52 @@
+// +build ignore
+
+package A1
+
+import (
+	"errors"
+	. "fmt"
+	myfmt "fmt"
+	"os"
+	"strings"
+)
+
+func example(n int) {
+	x := "foo" + strings.Repeat("\t", n)
+	// Match, despite named import.
+	errors.New(x)
+
+	// Match, despite dot import.
+	errors.New(x)
+
+	// Match: multiple matches in same function are possible.
+	errors.New(x)
+
+	// No match: wildcarded operand has the wrong type.
+	myfmt.Errorf("%s", 3)
+
+	// No match: function operand doesn't match.
+	myfmt.Printf("%s", x)
+
+	// No match again, dot import.
+	Printf("%s", x)
+
+	// Match.
+	myfmt.Fprint(os.Stderr, errors.New(x+"foo"))
+
+	// No match: though this literally matches the template,
+	// fmt doesn't resolve to a package here.
+	var fmt struct{ Errorf func(string, string) }
+	fmt.Errorf("%s", x)
+
+	// Recursive matching:
+
+	// Match: both matches are well-typed, so both succeed.
+	errors.New(errors.New(x + "foo").Error())
+
+	// Outer match succeeds, inner doesn't: 3 has wrong type.
+	errors.New(myfmt.Errorf("%s", 3).Error())
+
+	// Inner match succeeds, outer doesn't: the inner replacement
+	// has the wrong type (error not string).
+	myfmt.Errorf("%s", errors.New(x+"foo"))
+}
diff --git a/refactor/eg/testdata/A2.go b/refactor/eg/testdata/A2.go
new file mode 100644
index 0000000..3ae29ad
--- /dev/null
+++ b/refactor/eg/testdata/A2.go
@@ -0,0 +1,12 @@
+// +build ignore
+
+package A2
+
+// This refactoring causes addition of "errors" import.
+// TODO(adonovan): fix: it should also remove "fmt".
+
+import myfmt "fmt"
+
+func example(n int) {
+	myfmt.Errorf("%s", "")
+}
diff --git a/refactor/eg/testdata/A2.golden b/refactor/eg/testdata/A2.golden
new file mode 100644
index 0000000..b6e3a6d
--- /dev/null
+++ b/refactor/eg/testdata/A2.golden
@@ -0,0 +1,15 @@
+// +build ignore
+
+package A2
+
+// This refactoring causes addition of "errors" import.
+// TODO(adonovan): fix: it should also remove "fmt".
+
+import (
+	"errors"
+	myfmt "fmt"
+)
+
+func example(n int) {
+	errors.New("")
+}
diff --git a/refactor/eg/testdata/B.template b/refactor/eg/testdata/B.template
new file mode 100644
index 0000000..c16627b
--- /dev/null
+++ b/refactor/eg/testdata/B.template
@@ -0,0 +1,9 @@
+package template
+
+// Basic test of expression refactoring.
+// (Types are not important in this case; it could be done with gofmt -r.)
+
+import "time"
+
+func before(t time.Time) time.Duration { return time.Now().Sub(t) }
+func after(t time.Time) time.Duration  { return time.Since(t) }
diff --git a/refactor/eg/testdata/B1.go b/refactor/eg/testdata/B1.go
new file mode 100644
index 0000000..8b52546
--- /dev/null
+++ b/refactor/eg/testdata/B1.go
@@ -0,0 +1,17 @@
+// +build ignore
+
+package B1
+
+import "time"
+
+var startup = time.Now()
+
+func example() time.Duration {
+	before := time.Now()
+	time.Sleep(1)
+	return time.Now().Sub(before)
+}
+
+func msSinceStartup() int64 {
+	return int64(time.Now().Sub(startup) / time.Millisecond)
+}
diff --git a/refactor/eg/testdata/B1.golden b/refactor/eg/testdata/B1.golden
new file mode 100644
index 0000000..4d4da21
--- /dev/null
+++ b/refactor/eg/testdata/B1.golden
@@ -0,0 +1,17 @@
+// +build ignore
+
+package B1
+
+import "time"
+
+var startup = time.Now()
+
+func example() time.Duration {
+	before := time.Now()
+	time.Sleep(1)
+	return time.Since(before)
+}
+
+func msSinceStartup() int64 {
+	return int64(time.Since(startup) / time.Millisecond)
+}
diff --git a/refactor/eg/testdata/C.template b/refactor/eg/testdata/C.template
new file mode 100644
index 0000000..f6f94d4
--- /dev/null
+++ b/refactor/eg/testdata/C.template
@@ -0,0 +1,10 @@
+package template
+
+// Test of repeated use of wildcard in pattern.
+
+// NB: multiple patterns would be required to handle variants such as
+// s[:len(s)], s[x:len(s)], etc, since a wildcard can't match nothing at all.
+// TODO(adonovan): support multiple templates in a single pass.
+
+func before(s string) string { return s[:len(s)] }
+func after(s string) string  { return s }
diff --git a/refactor/eg/testdata/C1.go b/refactor/eg/testdata/C1.go
new file mode 100644
index 0000000..523b388
--- /dev/null
+++ b/refactor/eg/testdata/C1.go
@@ -0,0 +1,22 @@
+// +build ignore
+
+package C1
+
+import "strings"
+
+func example() {
+	x := "foo"
+	println(x[:len(x)])
+
+	// Match, but the transformation is not sound w.r.t. possible side effects.
+	println(strings.Repeat("*", 3)[:len(strings.Repeat("*", 3))])
+
+	// No match, since second use of wildcard doesn't match first.
+	println(strings.Repeat("*", 3)[:len(strings.Repeat("*", 2))])
+
+	// Recursive match demonstrating bottom-up rewrite:
+	// only after the inner replacement occurs does the outer syntax match.
+	println((x[:len(x)])[:len(x[:len(x)])])
+	// -> (x[:len(x)])
+	// -> x
+}
diff --git a/refactor/eg/testdata/C1.golden b/refactor/eg/testdata/C1.golden
new file mode 100644
index 0000000..ae7759d
--- /dev/null
+++ b/refactor/eg/testdata/C1.golden
@@ -0,0 +1,22 @@
+// +build ignore
+
+package C1
+
+import "strings"
+
+func example() {
+	x := "foo"
+	println(x)
+
+	// Match, but the transformation is not sound w.r.t. possible side effects.
+	println(strings.Repeat("*", 3))
+
+	// No match, since second use of wildcard doesn't match first.
+	println(strings.Repeat("*", 3)[:len(strings.Repeat("*", 2))])
+
+	// Recursive match demonstrating bottom-up rewrite:
+	// only after the inner replacement occurs does the outer syntax match.
+	println(x)
+	// -> (x[:len(x)])
+	// -> x
+}
diff --git a/refactor/eg/testdata/D.template b/refactor/eg/testdata/D.template
new file mode 100644
index 0000000..6d3b6fe
--- /dev/null
+++ b/refactor/eg/testdata/D.template
@@ -0,0 +1,8 @@
+package template
+
+import "fmt"
+
+// Test of semantic (not syntactic) matching of basic literals.
+
+func before() (int, error) { return fmt.Println(123, "a") }
+func after() (int, error)  { return fmt.Println(456, "!") }
diff --git a/refactor/eg/testdata/D1.go b/refactor/eg/testdata/D1.go
new file mode 100644
index 0000000..ae0a806
--- /dev/null
+++ b/refactor/eg/testdata/D1.go
@@ -0,0 +1,12 @@
+// +build ignore
+
+package D1
+
+import "fmt"
+
+func example() {
+	fmt.Println(123, "a")         // match
+	fmt.Println(0x7b, `a`)        // match
+	fmt.Println(0173, "\x61")     // match
+	fmt.Println(100+20+3, "a"+"") // no match: constant expressions, but not basic literals
+}
diff --git a/refactor/eg/testdata/D1.golden b/refactor/eg/testdata/D1.golden
new file mode 100644
index 0000000..2932652
--- /dev/null
+++ b/refactor/eg/testdata/D1.golden
@@ -0,0 +1,12 @@
+// +build ignore
+
+package D1
+
+import "fmt"
+
+func example() {
+	fmt.Println(456, "!")         // match
+	fmt.Println(456, "!")         // match
+	fmt.Println(456, "!")         // match
+	fmt.Println(100+20+3, "a"+"") // no match: constant expressions, but not basic literals
+}
diff --git a/refactor/eg/testdata/E.template b/refactor/eg/testdata/E.template
new file mode 100644
index 0000000..4bbbd11
--- /dev/null
+++ b/refactor/eg/testdata/E.template
@@ -0,0 +1,12 @@
+package template
+
+import (
+	"fmt"
+	"log"
+	"os"
+)
+
+// Replace call to void function by call to non-void function.
+
+func before(x interface{}) { log.Fatal(x) }
+func after(x interface{})  { fmt.Fprintf(os.Stderr, "warning: %v", x) }
diff --git a/refactor/eg/testdata/E1.go b/refactor/eg/testdata/E1.go
new file mode 100644
index 0000000..3ea1793
--- /dev/null
+++ b/refactor/eg/testdata/E1.go
@@ -0,0 +1,9 @@
+// +build ignore
+
+package E1
+
+import "log"
+
+func example() {
+	log.Fatal("oops") // match
+}
diff --git a/refactor/eg/testdata/E1.golden b/refactor/eg/testdata/E1.golden
new file mode 100644
index 0000000..796364f
--- /dev/null
+++ b/refactor/eg/testdata/E1.golden
@@ -0,0 +1,13 @@
+// +build ignore
+
+package E1
+
+import (
+	"fmt"
+	"log"
+	"os"
+)
+
+func example() {
+	fmt.Fprintf(os.Stderr, "warning: %v", "oops") // match
+}
diff --git a/refactor/eg/testdata/F.template b/refactor/eg/testdata/F.template
new file mode 100644
index 0000000..21e1bd2
--- /dev/null
+++ b/refactor/eg/testdata/F.template
@@ -0,0 +1,8 @@
+package templates
+
+// Test 
+
+import "sync"
+
+func before(s sync.RWMutex) { s.Lock() }
+func after(s sync.RWMutex) { s.RLock() }
\ No newline at end of file
diff --git a/refactor/eg/testdata/F1.go b/refactor/eg/testdata/F1.go
new file mode 100644
index 0000000..2258abd
--- /dev/null
+++ b/refactor/eg/testdata/F1.go
@@ -0,0 +1,48 @@
+// +build ignore
+
+package F1
+
+import "sync"
+
+func example(n int) {
+	var x struct {
+		mutex sync.RWMutex
+	}
+
+	var y struct {
+		sync.RWMutex
+	}
+
+	type l struct {
+		sync.RWMutex
+	}
+
+	var z struct {
+		l
+	}
+
+	var a struct {
+		*l
+	}
+
+	var b struct{ Lock func() }
+
+	// Match
+	x.mutex.Lock()
+
+	// Match
+	y.Lock()
+
+	// Match indirect
+	z.Lock()
+
+	// Should be no match however currently matches due to:
+	// https://golang.org/issue/8584
+	// Will start failing when this is fixed then just change golden to
+	// No match pointer indirect
+	// a.Lock()
+	a.Lock()
+
+	// No match
+	b.Lock()
+}
diff --git a/refactor/eg/testdata/F1.golden b/refactor/eg/testdata/F1.golden
new file mode 100644
index 0000000..5ffda69
--- /dev/null
+++ b/refactor/eg/testdata/F1.golden
@@ -0,0 +1,48 @@
+// +build ignore
+
+package F1
+
+import "sync"
+
+func example(n int) {
+	var x struct {
+		mutex sync.RWMutex
+	}
+
+	var y struct {
+		sync.RWMutex
+	}
+
+	type l struct {
+		sync.RWMutex
+	}
+
+	var z struct {
+		l
+	}
+
+	var a struct {
+		*l
+	}
+
+	var b struct{ Lock func() }
+
+	// Match
+	x.mutex.RLock()
+
+	// Match
+	y.RLock()
+
+	// Match indirect
+	z.RLock()
+
+	// Should be no match however currently matches due to:
+	// https://golang.org/issue/8584
+	// Will start failing when this is fixed then just change golden to
+	// No match pointer indirect
+	// a.Lock()
+	a.RLock()
+
+	// No match
+	b.Lock()
+}
diff --git a/refactor/eg/testdata/G.template b/refactor/eg/testdata/G.template
new file mode 100644
index 0000000..69d84fe
--- /dev/null
+++ b/refactor/eg/testdata/G.template
@@ -0,0 +1,10 @@
+package templates
+
+import (
+	"go/ast" // defines many unencapsulated structs
+	"go/token"
+)
+
+func before(from, to token.Pos) ast.BadExpr { return ast.BadExpr{From: from, To: to} }
+func after(from, to token.Pos) ast.BadExpr  { return ast.BadExpr{from, to} }
+     
\ No newline at end of file
diff --git a/refactor/eg/testdata/G1.go b/refactor/eg/testdata/G1.go
new file mode 100644
index 0000000..07aaff9
--- /dev/null
+++ b/refactor/eg/testdata/G1.go
@@ -0,0 +1,12 @@
+// +build ignore
+
+package G1
+
+import "go/ast"
+
+func example() {
+	_ = ast.BadExpr{From: 123, To: 456} // match
+	_ = ast.BadExpr{123, 456}           // no match
+	_ = ast.BadExpr{From: 123}          // no match
+	_ = ast.BadExpr{To: 456}            // no match
+}
diff --git a/refactor/eg/testdata/G1.golden b/refactor/eg/testdata/G1.golden
new file mode 100644
index 0000000..c93c53f
--- /dev/null
+++ b/refactor/eg/testdata/G1.golden
@@ -0,0 +1,12 @@
+// +build ignore
+
+package G1
+
+import "go/ast"
+
+func example() {
+	_ = ast.BadExpr{123, 456}  // match
+	_ = ast.BadExpr{123, 456}  // no match
+	_ = ast.BadExpr{From: 123} // no match
+	_ = ast.BadExpr{To: 456}   // no match
+}
diff --git a/refactor/eg/testdata/H.template b/refactor/eg/testdata/H.template
new file mode 100644
index 0000000..fa6f802
--- /dev/null
+++ b/refactor/eg/testdata/H.template
@@ -0,0 +1,9 @@
+package templates
+
+import (
+	"go/ast" // defines many unencapsulated structs
+	"go/token"
+)
+
+func before(from, to token.Pos) ast.BadExpr { return ast.BadExpr{from, to} }
+func after(from, to token.Pos) ast.BadExpr  { return ast.BadExpr{From: from, To: to} }
diff --git a/refactor/eg/testdata/H1.go b/refactor/eg/testdata/H1.go
new file mode 100644
index 0000000..ef4291c
--- /dev/null
+++ b/refactor/eg/testdata/H1.go
@@ -0,0 +1,12 @@
+// +build ignore
+
+package H1
+
+import "go/ast"
+
+func example() {
+	_ = ast.BadExpr{From: 123, To: 456} // no match
+	_ = ast.BadExpr{123, 456}           // match
+	_ = ast.BadExpr{From: 123}          // no match
+	_ = ast.BadExpr{To: 456}            // no match
+}
diff --git a/refactor/eg/testdata/H1.golden b/refactor/eg/testdata/H1.golden
new file mode 100644
index 0000000..a1e5961
--- /dev/null
+++ b/refactor/eg/testdata/H1.golden
@@ -0,0 +1,12 @@
+// +build ignore
+
+package H1
+
+import "go/ast"
+
+func example() {
+	_ = ast.BadExpr{From: 123, To: 456} // no match
+	_ = ast.BadExpr{From: 123, To: 456} // match
+	_ = ast.BadExpr{From: 123}          // no match
+	_ = ast.BadExpr{To: 456}            // no match
+}
diff --git a/refactor/eg/testdata/bad_type.template b/refactor/eg/testdata/bad_type.template
new file mode 100644
index 0000000..6d53d7e
--- /dev/null
+++ b/refactor/eg/testdata/bad_type.template
@@ -0,0 +1,8 @@
+package template
+
+// Test in which replacement has a different type.
+
+const shouldFail = "int is not a safe replacement for string"
+
+func before() interface{} { return "three" }
+func after() interface{}  { return 3 }
diff --git a/refactor/eg/testdata/expr_type_mismatch.template b/refactor/eg/testdata/expr_type_mismatch.template
new file mode 100644
index 0000000..2c5c3f0
--- /dev/null
+++ b/refactor/eg/testdata/expr_type_mismatch.template
@@ -0,0 +1,15 @@
+package template
+
+import (
+	"crypto/x509"
+	"fmt"
+)
+
+// This test demonstrates a false negative: according to the language
+// rules this replacement should be ok, but types.Assignable doesn't work
+// in the expected way (elementwise assignability) for tuples.
+// Perhaps that's even a type-checker bug?
+const shouldFail = "(n int, err error) is not a safe replacement for (key interface{}, err error)"
+
+func before() (interface{}, error) { return x509.ParsePKCS8PrivateKey(nil) }
+func after() (interface{}, error)  { return fmt.Print() }
diff --git a/refactor/eg/testdata/no_after_return.template b/refactor/eg/testdata/no_after_return.template
new file mode 100644
index 0000000..536b01e
--- /dev/null
+++ b/refactor/eg/testdata/no_after_return.template
@@ -0,0 +1,6 @@
+package template
+
+const shouldFail = "after: must contain a single statement"
+
+func before() int { return 0 }
+func after() int  { println(); return 0 }
diff --git a/refactor/eg/testdata/no_before.template b/refactor/eg/testdata/no_before.template
new file mode 100644
index 0000000..9205e66
--- /dev/null
+++ b/refactor/eg/testdata/no_before.template
@@ -0,0 +1,5 @@
+package template
+
+const shouldFail = "no 'before' func found in template"
+
+func Before() {}
diff --git a/refactor/eg/testdata/type_mismatch.template b/refactor/eg/testdata/type_mismatch.template
new file mode 100644
index 0000000..787c9a7
--- /dev/null
+++ b/refactor/eg/testdata/type_mismatch.template
@@ -0,0 +1,6 @@
+package template
+
+const shouldFail = "different signatures"
+
+func before() int   { return 0 }
+func after() string { return "" }
diff --git a/refactor/importgraph/graph.go b/refactor/importgraph/graph.go
new file mode 100644
index 0000000..8ad8014
--- /dev/null
+++ b/refactor/importgraph/graph.go
@@ -0,0 +1,128 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package importgraph computes the forward and reverse import
+// dependency graphs for all packages in a Go workspace.
+package importgraph // import "golang.org/x/tools/refactor/importgraph"
+
+import (
+	"go/build"
+	"sync"
+
+	"golang.org/x/tools/go/buildutil"
+)
+
+// A Graph is an import dependency graph, either forward or reverse.
+//
+// The graph maps each node (a package import path) to the set of its
+// successors in the graph.  For a forward graph, this is the set of
+// imported packages (prerequisites); for a reverse graph, it is the set
+// of importing packages (clients).
+//
+type Graph map[string]map[string]bool
+
+func (g Graph) addEdge(from, to string) {
+	edges := g[from]
+	if edges == nil {
+		edges = make(map[string]bool)
+		g[from] = edges
+	}
+	edges[to] = true
+}
+
+// Search returns all the nodes of the graph reachable from
+// any of the specified roots, by following edges forwards.
+// Relationally, this is the reflexive transitive closure.
+func (g Graph) Search(roots ...string) map[string]bool {
+	seen := make(map[string]bool)
+	var visit func(x string)
+	visit = func(x string) {
+		if !seen[x] {
+			seen[x] = true
+			for y := range g[x] {
+				visit(y)
+			}
+		}
+	}
+	for _, root := range roots {
+		visit(root)
+	}
+	return seen
+}
+
+// Build scans the specified Go workspace and builds the forward and
+// reverse import dependency graphs for all its packages.
+// It also returns a mapping from import paths to errors for packages
+// whose loading was not entirely successful.
+// A package may appear in the graph and in the errors mapping.
+func Build(ctxt *build.Context) (forward, reverse Graph, errors map[string]error) {
+	type importEdge struct {
+		from, to string
+	}
+	type pathError struct {
+		path string
+		err  error
+	}
+
+	ch := make(chan interface{})
+
+	var wg sync.WaitGroup
+	buildutil.ForEachPackage(ctxt, func(path string, err error) {
+		wg.Add(1)
+		go func() {
+			defer wg.Done()
+			if err != nil {
+				ch <- pathError{path, err}
+				return
+			}
+
+			bp, err := ctxt.Import(path, "", 0)
+			if err != nil {
+				if _, ok := err.(*build.NoGoError); ok {
+					// empty directory is not an error
+				} else {
+					ch <- pathError{path, err}
+				}
+				// Even in error cases, Import usually returns a package.
+			}
+			if bp != nil {
+				for _, imp := range bp.Imports {
+					ch <- importEdge{path, imp}
+				}
+				for _, imp := range bp.TestImports {
+					ch <- importEdge{path, imp}
+				}
+				for _, imp := range bp.XTestImports {
+					ch <- importEdge{path, imp}
+				}
+			}
+		}()
+	})
+	go func() {
+		wg.Wait()
+		close(ch)
+	}()
+
+	forward = make(Graph)
+	reverse = make(Graph)
+
+	for e := range ch {
+		switch e := e.(type) {
+		case pathError:
+			if errors == nil {
+				errors = make(map[string]error)
+			}
+			errors[e.path] = e.err
+
+		case importEdge:
+			if e.to == "C" {
+				continue // "C" is fake
+			}
+			forward.addEdge(e.from, e.to)
+			reverse.addEdge(e.to, e.from)
+		}
+	}
+
+	return forward, reverse, errors
+}
diff --git a/refactor/importgraph/graph_test.go b/refactor/importgraph/graph_test.go
new file mode 100644
index 0000000..a486c26
--- /dev/null
+++ b/refactor/importgraph/graph_test.go
@@ -0,0 +1,103 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Incomplete std lib sources on Android.
+
+// +build !android
+
+package importgraph_test
+
+import (
+	"go/build"
+	"runtime"
+	"sort"
+	"testing"
+
+	"golang.org/x/tools/refactor/importgraph"
+
+	_ "crypto/hmac" // just for test, below
+)
+
+const this = "golang.org/x/tools/refactor/importgraph"
+
+func TestBuild(t *testing.T) {
+	saved := runtime.GOMAXPROCS(8) // Build is highly parallel
+	defer runtime.GOMAXPROCS(saved)
+
+	forward, reverse, errors := importgraph.Build(&build.Default)
+
+	// Test direct edges.
+	// We throw in crypto/hmac to prove that external test files
+	// (such as this one) are inspected.
+	for _, p := range []string{"go/build", "runtime", "testing", "crypto/hmac"} {
+		if !forward[this][p] {
+			t.Errorf("forward[importgraph][%s] not found", p)
+		}
+		if !reverse[p][this] {
+			t.Errorf("reverse[%s][importgraph] not found", p)
+		}
+	}
+
+	// Test non-existent direct edges
+	for _, p := range []string{"fmt", "errors", "reflect"} {
+		if forward[this][p] {
+			t.Errorf("unexpected: forward[importgraph][%s] found", p)
+		}
+		if reverse[p][this] {
+			t.Errorf("unexpected: reverse[%s][importgraph] found", p)
+		}
+	}
+
+	// Test Search is reflexive.
+	if !forward.Search(this)[this] {
+		t.Errorf("irreflexive: forward.Search(importgraph)[importgraph] not found")
+	}
+	if !reverse.Search(this)[this] {
+		t.Errorf("irrefexive: reverse.Search(importgraph)[importgraph] not found")
+	}
+
+	// Test Search is transitive.  (There is no direct edge to these packages.)
+	for _, p := range []string{"errors", "reflect", "unsafe"} {
+		if !forward.Search(this)[p] {
+			t.Errorf("intransitive: forward.Search(importgraph)[%s] not found", p)
+		}
+		if !reverse.Search(p)[this] {
+			t.Errorf("intransitive: reverse.Search(%s)[importgraph] not found", p)
+		}
+	}
+
+	// Test strongly-connected components.  Because A's external
+	// test package can depend on B, and vice versa, most of the
+	// standard libraries are mutually dependent when their external
+	// tests are considered.
+	//
+	// For any nodes x, y in the same SCC, y appears in the results
+	// of both forward and reverse searches starting from x
+	if !forward.Search("fmt")["io"] ||
+		!forward.Search("io")["fmt"] ||
+		!reverse.Search("fmt")["io"] ||
+		!reverse.Search("io")["fmt"] {
+		t.Errorf("fmt and io are not mutually reachable despite being in the same SCC")
+	}
+
+	// debugging
+	if false {
+		for path, err := range errors {
+			t.Logf("%s: %s", path, err)
+		}
+		printSorted := func(direction string, g importgraph.Graph, start string) {
+			t.Log(direction)
+			var pkgs []string
+			for pkg := range g.Search(start) {
+				pkgs = append(pkgs, pkg)
+			}
+			sort.Strings(pkgs)
+			for _, pkg := range pkgs {
+				t.Logf("\t%s", pkg)
+			}
+		}
+		printSorted("forward", forward, this)
+		printSorted("reverse", reverse, this)
+	}
+}
diff --git a/refactor/lexical/lexical.go b/refactor/lexical/lexical.go
new file mode 100644
index 0000000..c6567e4
--- /dev/null
+++ b/refactor/lexical/lexical.go
@@ -0,0 +1,763 @@
+// Package lexical computes the structure of the lexical environment,
+// including the definition of and references to all universal,
+// package-level, file-level and function-local entities.  It does not
+// record qualified identifiers, labels, struct fields, or methods.
+//
+// It is intended for renaming and refactoring tools, which need a more
+// precise understanding of identifier resolution than is available from
+// the output of the type-checker alone.
+//
+// THIS INTERFACE IS EXPERIMENTAL AND MAY CHANGE OR BE REMOVED IN FUTURE.
+//
+package lexical // import "golang.org/x/tools/refactor/lexical"
+
+// OVERVIEW
+//
+// As we traverse the AST, we build a "spaghetti stack" of Blocks,
+// i.e. a tree with parent edges pointing to the root.  Each time we
+// visit an identifier that's a reference into the lexical environment,
+// we create and save an Environment, which captures the current mapping
+// state of the Block; these are saved for the client.
+//
+// We don't bother recording non-lexical references.
+
+// TODO(adonovan):
+// - make it robust against syntax errors.  Audit all type assertions, etc.
+// - better still, after the Go 1.4 thaw, move this into go/types.
+//   I don't think it need be a big change since the visitor is already there;
+//   we just need to records Environments.  lexical.Block is analogous
+//   to types.Scope.
+
+import (
+	"fmt"
+	"go/ast"
+	"go/token"
+	"os"
+	"strconv"
+
+	"golang.org/x/tools/go/types"
+)
+
+const trace = false
+
+var logf = func(format string, args ...interface{}) {
+	fmt.Fprintf(os.Stderr, format, args...)
+}
+
+// A Block is a level of the lexical environment, a tree of blocks.
+// It maps names to objects.
+//
+type Block struct {
+	kind   string   // one of universe package file func block if switch typeswitch case for range
+	syntax ast.Node // syntax declaring the block (nil for universe and package) [needed?]
+
+	parent   Environment
+	bindings []types.Object // bindings in lexical order
+	index    map[string]int // maps a name to the index of its binding, for fast lookup
+}
+
+// An Environment is a snapshot of a Block taken at a certain lexical
+// position. It may contain bindings for fewer names than the
+// (completed) block, or different bindings for names that are
+// re-defined later in the block.
+//
+// For example, the lexical Block for the function f below contains a
+// binding for the local var x, but the Environments captured by at the
+// two print(x) calls differ: the first contains this binding, the
+// second does not.  The first Environment contains a different binding
+// for x: the string var defined in the package block, an ancestor.
+//
+//	var x string
+// 	func f() {
+//		print(x)
+//		x := 1
+//		print(x)
+//	}
+//
+type Environment struct {
+	block     *Block
+	nbindings int // length of prefix of block.bindings that's visible
+}
+
+// Depth returns the depth of this block in the block tree.
+// The universal block has depth 1, a package block 2, a file block 3, etc.
+func (b *Block) Depth() int {
+	if b == nil {
+		return 0
+	}
+	return 1 + b.parent.block.Depth()
+}
+
+// env returns an Environment that is a snapshot of b's current state.
+func (b *Block) env() Environment {
+	return Environment{b, len(b.bindings)}
+}
+
+// Lookup returns the definition of name in the environment specified by
+// env, and the Block that defines it, which may be an ancestor.
+func (env Environment) Lookup(name string) (types.Object, *Block) {
+	if env.block == nil {
+		return nil, nil
+	}
+	return lookup(env.block, name, env.nbindings)
+}
+
+// nbindings specifies what prefix of b.bindings should be considered visible.
+func lookup(b *Block, name string, nbindings int) (types.Object, *Block) {
+	if b == nil {
+		return nil, nil
+	}
+	if i, ok := b.index[name]; ok && i < nbindings {
+		return b.bindings[i], b
+	}
+
+	parent := b.parent
+	if parent.block == nil {
+		return nil, nil
+	}
+	return lookup(parent.block, name, parent.nbindings)
+}
+
+// Lookup returns the definition of name in the environment specified by
+// b, and the Block that defines it, which may be an ancestor.
+func (b *Block) Lookup(name string) (types.Object, *Block) {
+	return b.env().Lookup(name)
+}
+
+// Block returns the block of which this environment is a partial view.
+func (env Environment) Block() *Block {
+	return env.block
+}
+
+func (env Environment) String() string {
+	return fmt.Sprintf("%s:%d", env.block, env.nbindings)
+}
+
+func (b *Block) String() string {
+	var s string
+	if b.parent.block != nil {
+		s = b.parent.block.String()
+		s += "."
+	}
+	return s + b.kind
+}
+
+var universe = &Block{kind: "universe", index: make(map[string]int)}
+
+func init() {
+	for i, name := range types.Universe.Names() {
+		obj := types.Universe.Lookup(name)
+		universe.bindings = append(universe.bindings, obj)
+		universe.index[name] = i
+	}
+}
+
+// -- resolver ---------------------------------------------------------
+
+// A Reference provides the lexical environment for a given reference to
+// an object in lexical scope.
+type Reference struct {
+	Id  *ast.Ident
+	Env Environment
+}
+
+// resolver holds the state of the identifier resolution visitation:
+// the package information, the result, and the current block.
+type resolver struct {
+	fset    *token.FileSet
+	imports map[string]*types.Package
+	pkg     *types.Package
+	info    *types.Info
+
+	// visitor state
+	block *Block
+
+	result *Info
+}
+
+func (r *resolver) setBlock(kind string, syntax ast.Node) *Block {
+	b := &Block{
+		kind:   kind,
+		syntax: syntax,
+		parent: r.block.env(),
+		index:  make(map[string]int),
+	}
+	if syntax != nil {
+		r.result.Blocks[syntax] = b
+	}
+	r.block = b
+	return b
+}
+
+func (r *resolver) qualifier(pkg *types.Package) string {
+	if pkg == r.pkg {
+		return "" // unqualified intra-package reference
+	}
+	return pkg.Path()
+}
+
+func (r *resolver) use(id *ast.Ident, env Environment) {
+	if id.Name == "_" {
+		return // an error
+	}
+	obj, _ := env.Lookup(id.Name)
+	if obj == nil {
+		logf("%s: lookup of %s failed\n", r.fset.Position(id.Pos()), id.Name)
+	} else if want := r.info.Uses[id]; obj != want {
+		// sanity check against go/types resolver
+		logf("%s: internal error: lookup of %s yielded wrong object: got %v (%s), want %v\n",
+			r.fset.Position(id.Pos()), id.Name, types.ObjectString(obj, r.qualifier),
+			r.fset.Position(obj.Pos()),
+			want)
+	}
+	if trace {
+		logf("use %s = %v in %s\n", id.Name, types.ObjectString(obj, r.qualifier), env)
+	}
+
+	r.result.Refs[obj] = append(r.result.Refs[obj], Reference{id, env})
+}
+
+func (r *resolver) define(b *Block, id *ast.Ident) {
+	obj := r.info.Defs[id]
+	if obj == nil {
+		logf("%s: internal error: not a defining ident: %s\n",
+			r.fset.Position(id.Pos()), id.Name)
+		panic(id)
+	}
+	r.defineObject(b, id.Name, obj)
+
+	// Objects (other than PkgName) defined at file scope
+	// are also defined in the enclosing package scope.
+	if _, ok := b.syntax.(*ast.File); ok {
+		switch obj.(type) {
+		default:
+			r.defineObject(b.parent.block, id.Name, obj)
+		case nil, *types.PkgName:
+		}
+	}
+}
+
+// Used for implicit objects created by some ImportSpecs and CaseClauses.
+func (r *resolver) defineImplicit(b *Block, n ast.Node, name string) {
+	obj := r.info.Implicits[n]
+	if obj == nil {
+		logf("%s: internal error: not an implicit definition: %T\n",
+			r.fset.Position(n.Pos()), n)
+	}
+	r.defineObject(b, name, obj)
+}
+
+func (r *resolver) defineObject(b *Block, name string, obj types.Object) {
+	if obj.Name() == "_" {
+		return
+	}
+	i := len(b.bindings)
+	b.bindings = append(b.bindings, obj)
+	b.index[name] = i
+	if trace {
+		logf("def %s = %s in %s\n", name, types.ObjectString(obj, r.qualifier), b)
+	}
+	r.result.Defs[obj] = b
+}
+
+func (r *resolver) function(recv *ast.FieldList, typ *ast.FuncType, body *ast.BlockStmt, syntax ast.Node) {
+	// Use all signature types in enclosing block.
+	r.expr(typ)
+	r.fieldList(recv, false)
+
+	savedBlock := r.block // save
+	r.setBlock("func", syntax)
+
+	// Define all parameters/results, and visit the body, within the func block.
+	r.fieldList(typ.Params, true)
+	r.fieldList(typ.Results, true)
+	r.fieldList(recv, true)
+	if body != nil {
+		r.stmtList(body.List)
+	}
+
+	r.block = savedBlock // restore
+}
+
+func (r *resolver) fieldList(list *ast.FieldList, def bool) {
+	if list != nil {
+		for _, f := range list.List {
+			if def {
+				for _, id := range f.Names {
+					r.define(r.block, id)
+				}
+			} else {
+				r.expr(f.Type)
+			}
+		}
+	}
+}
+
+func (r *resolver) exprList(list []ast.Expr) {
+	for _, x := range list {
+		r.expr(x)
+	}
+}
+
+func (r *resolver) expr(n ast.Expr) {
+	switch n := n.(type) {
+	case *ast.BadExpr:
+	case *ast.BasicLit:
+		// no-op
+
+	case *ast.Ident:
+		r.use(n, r.block.env())
+
+	case *ast.Ellipsis:
+		if n.Elt != nil {
+			r.expr(n.Elt)
+		}
+
+	case *ast.FuncLit:
+		r.function(nil, n.Type, n.Body, n)
+
+	case *ast.CompositeLit:
+		if n.Type != nil {
+			r.expr(n.Type)
+		}
+		tv := r.info.Types[n]
+		if _, ok := deref(tv.Type).Underlying().(*types.Struct); ok {
+			for _, elt := range n.Elts {
+				if kv, ok := elt.(*ast.KeyValueExpr); ok {
+					r.expr(kv.Value)
+
+					// Also uses field kv.Key (non-lexical)
+					//  id := kv.Key.(*ast.Ident)
+					//  obj := r.info.Uses[id]
+					//  logf("use %s = %v (field)\n",
+					// 	id.Name, types.ObjectString(obj, r.qualifier))
+					// TODO make a fake FieldVal selection?
+				} else {
+					r.expr(elt)
+				}
+			}
+		} else {
+			r.exprList(n.Elts)
+		}
+
+	case *ast.ParenExpr:
+		r.expr(n.X)
+
+	case *ast.SelectorExpr:
+		r.expr(n.X)
+
+		// Non-lexical reference to field/method, or qualified identifier.
+		// if sel, ok := r.info.Selections[n]; ok { // selection
+		// 	switch sel.Kind() {
+		// 	case types.FieldVal:
+		// 		logf("use %s = %v (field)\n",
+		// 			n.Sel.Name, types.ObjectString(sel.Obj(), r.qualifier))
+		// 	case types.MethodExpr, types.MethodVal:
+		// 		logf("use %s = %v (method)\n",
+		// 			n.Sel.Name, types.ObjectString(sel.Obj(), r.qualifier))
+		// 	}
+		// } else { // qualified identifier
+		// 	obj := r.info.Uses[n.Sel]
+		// 	logf("use %s = %v (qualified)\n", n.Sel.Name, obj)
+		// }
+
+	case *ast.IndexExpr:
+		r.expr(n.X)
+		r.expr(n.Index)
+
+	case *ast.SliceExpr:
+		r.expr(n.X)
+		if n.Low != nil {
+			r.expr(n.Low)
+		}
+		if n.High != nil {
+			r.expr(n.High)
+		}
+		if n.Max != nil {
+			r.expr(n.Max)
+		}
+
+	case *ast.TypeAssertExpr:
+		r.expr(n.X)
+		if n.Type != nil {
+			r.expr(n.Type)
+		}
+
+	case *ast.CallExpr:
+		r.expr(n.Fun)
+		r.exprList(n.Args)
+
+	case *ast.StarExpr:
+		r.expr(n.X)
+
+	case *ast.UnaryExpr:
+		r.expr(n.X)
+
+	case *ast.BinaryExpr:
+		r.expr(n.X)
+		r.expr(n.Y)
+
+	case *ast.KeyValueExpr:
+		r.expr(n.Key)
+		r.expr(n.Value)
+
+	case *ast.ArrayType:
+		if n.Len != nil {
+			r.expr(n.Len)
+		}
+		r.expr(n.Elt)
+
+	case *ast.StructType:
+		// Use all the type names, but don't define any fields.
+		r.fieldList(n.Fields, false)
+
+	case *ast.FuncType:
+		// Use all the type names, but don't define any vars.
+		r.fieldList(n.Params, false)
+		r.fieldList(n.Results, false)
+
+	case *ast.InterfaceType:
+		// Use all the type names, but don't define any methods.
+		r.fieldList(n.Methods, false)
+
+	case *ast.MapType:
+		r.expr(n.Key)
+		r.expr(n.Value)
+
+	case *ast.ChanType:
+		r.expr(n.Value)
+
+	default:
+		panic(n)
+	}
+}
+
+func (r *resolver) stmtList(list []ast.Stmt) {
+	for _, s := range list {
+		r.stmt(s)
+	}
+}
+
+func (r *resolver) stmt(n ast.Stmt) {
+	switch n := n.(type) {
+	case *ast.BadStmt:
+	case *ast.EmptyStmt:
+		// nothing to do
+
+	case *ast.DeclStmt:
+		decl := n.Decl.(*ast.GenDecl)
+		for _, spec := range decl.Specs {
+			switch spec := spec.(type) {
+			case *ast.ValueSpec: // const or var
+				if spec.Type != nil {
+					r.expr(spec.Type)
+				}
+				r.exprList(spec.Values)
+				for _, name := range spec.Names {
+					r.define(r.block, name)
+				}
+
+			case *ast.TypeSpec:
+				r.define(r.block, spec.Name)
+				r.expr(spec.Type)
+			}
+		}
+
+	case *ast.LabeledStmt:
+		// Also defines label n.Label (non-lexical)
+		r.stmt(n.Stmt)
+
+	case *ast.ExprStmt:
+		r.expr(n.X)
+
+	case *ast.SendStmt:
+		r.expr(n.Chan)
+		r.expr(n.Value)
+
+	case *ast.IncDecStmt:
+		r.expr(n.X)
+
+	case *ast.AssignStmt:
+		if n.Tok == token.DEFINE {
+			r.exprList(n.Rhs)
+			for _, lhs := range n.Lhs {
+				id := lhs.(*ast.Ident)
+				if _, ok := r.info.Defs[id]; ok {
+					r.define(r.block, id)
+				} else {
+					r.use(id, r.block.env())
+				}
+			}
+		} else { // ASSIGN
+			r.exprList(n.Lhs)
+			r.exprList(n.Rhs)
+		}
+
+	case *ast.GoStmt:
+		r.expr(n.Call)
+
+	case *ast.DeferStmt:
+		r.expr(n.Call)
+
+	case *ast.ReturnStmt:
+		r.exprList(n.Results)
+
+	case *ast.BranchStmt:
+		if n.Label != nil {
+			// Also uses label n.Label (non-lexical)
+		}
+
+	case *ast.SelectStmt:
+		r.stmtList(n.Body.List)
+
+	case *ast.BlockStmt: // (explicit blocks only)
+		savedBlock := r.block // save
+		r.setBlock("block", n)
+		r.stmtList(n.List)
+		r.block = savedBlock // restore
+
+	case *ast.IfStmt:
+		savedBlock := r.block // save
+		r.setBlock("if", n)
+		if n.Init != nil {
+			r.stmt(n.Init)
+		}
+		r.expr(n.Cond)
+		r.stmt(n.Body) // new block
+		if n.Else != nil {
+			r.stmt(n.Else)
+		}
+		r.block = savedBlock // restore
+
+	case *ast.CaseClause:
+		savedBlock := r.block // save
+		r.setBlock("case", n)
+		if obj, ok := r.info.Implicits[n]; ok {
+			// e.g.
+			//   switch y := x.(type) {
+			//   case T: // we declare an implicit 'var y T' in this block
+			//   }
+			r.defineImplicit(r.block, n, obj.Name())
+		}
+		r.exprList(n.List)
+		r.stmtList(n.Body)
+		r.block = savedBlock // restore
+
+	case *ast.SwitchStmt:
+		savedBlock := r.block // save
+		r.setBlock("switch", n)
+		if n.Init != nil {
+			r.stmt(n.Init)
+		}
+		if n.Tag != nil {
+			r.expr(n.Tag)
+		}
+		r.stmtList(n.Body.List)
+		r.block = savedBlock // restore
+
+	case *ast.TypeSwitchStmt:
+		savedBlock := r.block // save
+		r.setBlock("typeswitch", n)
+		if n.Init != nil {
+			r.stmt(n.Init)
+		}
+		if assign, ok := n.Assign.(*ast.AssignStmt); ok { // y := x.(type)
+			r.expr(assign.Rhs[0]) // skip y: not a defining ident
+		} else {
+			r.stmt(n.Assign)
+		}
+		r.stmtList(n.Body.List)
+		r.block = savedBlock // restore
+
+	case *ast.CommClause:
+		savedBlock := r.block // save
+		r.setBlock("case", n)
+		if n.Comm != nil {
+			r.stmt(n.Comm)
+		}
+		r.stmtList(n.Body)
+		r.block = savedBlock // restore
+
+	case *ast.ForStmt:
+		savedBlock := r.block // save
+		r.setBlock("for", n)
+		if n.Init != nil {
+			r.stmt(n.Init)
+		}
+		if n.Cond != nil {
+			r.expr(n.Cond)
+		}
+		if n.Post != nil {
+			r.stmt(n.Post)
+		}
+		r.stmt(n.Body)
+		r.block = savedBlock // restore
+
+	case *ast.RangeStmt:
+		r.expr(n.X)
+		savedBlock := r.block // save
+		r.setBlock("range", n)
+		if n.Tok == token.DEFINE {
+			if n.Key != nil {
+				r.define(r.block, n.Key.(*ast.Ident))
+			}
+			if n.Value != nil {
+				r.define(r.block, n.Value.(*ast.Ident))
+			}
+		} else {
+			if n.Key != nil {
+				r.expr(n.Key)
+			}
+			if n.Value != nil {
+				r.expr(n.Value)
+			}
+		}
+		r.stmt(n.Body)
+		r.block = savedBlock // restore
+
+	default:
+		panic(n)
+	}
+}
+
+func (r *resolver) doImport(s *ast.ImportSpec, fileBlock *Block) {
+	path, _ := strconv.Unquote(s.Path.Value)
+	pkg := r.imports[path]
+	if s.Name == nil { // normal
+		r.defineImplicit(fileBlock, s, pkg.Name())
+	} else if s.Name.Name == "." { // dot import
+		for _, name := range pkg.Scope().Names() {
+			if ast.IsExported(name) {
+				obj := pkg.Scope().Lookup(name)
+				r.defineObject(fileBlock, name, obj)
+			}
+		}
+	} else { // renaming import
+		r.define(fileBlock, s.Name)
+	}
+}
+
+func (r *resolver) doPackage(pkg *types.Package, files []*ast.File) {
+	r.block = universe
+	r.result.Blocks[nil] = universe
+
+	r.result.PackageBlock = r.setBlock("package", nil)
+
+	var fileBlocks []*Block
+
+	// 1. Insert all package-level objects into file and package blocks.
+	//    (PkgName objects are only inserted into file blocks.)
+	for _, f := range files {
+		r.block = r.result.PackageBlock
+		fileBlock := r.setBlock("file", f) // package is not yet visible to file
+		fileBlocks = append(fileBlocks, fileBlock)
+
+		for _, d := range f.Decls {
+			switch d := d.(type) {
+			case *ast.GenDecl:
+				for _, s := range d.Specs {
+					switch s := s.(type) {
+					case *ast.ImportSpec:
+						r.doImport(s, fileBlock)
+
+					case *ast.ValueSpec: // const or var
+						for _, name := range s.Names {
+							r.define(r.result.PackageBlock, name)
+						}
+
+					case *ast.TypeSpec:
+						r.define(r.result.PackageBlock, s.Name)
+					}
+				}
+
+			case *ast.FuncDecl:
+				if d.Recv == nil { // function
+					if d.Name.Name != "init" {
+						r.define(r.result.PackageBlock, d.Name)
+					}
+				}
+			}
+		}
+	}
+
+	// 2. Now resolve bodies of GenDecls and FuncDecls.
+	for i, f := range files {
+		fileBlock := fileBlocks[i]
+		fileBlock.parent = r.result.PackageBlock.env() // make entire package visible to this file
+
+		for _, d := range f.Decls {
+			r.block = fileBlock
+
+			switch d := d.(type) {
+			case *ast.GenDecl:
+				for _, s := range d.Specs {
+					switch s := s.(type) {
+					case *ast.ValueSpec: // const or var
+						if s.Type != nil {
+							r.expr(s.Type)
+						}
+						r.exprList(s.Values)
+
+					case *ast.TypeSpec:
+						r.expr(s.Type)
+					}
+				}
+
+			case *ast.FuncDecl:
+				r.function(d.Recv, d.Type, d.Body, d)
+			}
+		}
+	}
+
+	r.block = nil
+}
+
+// An Info contains the lexical reference structure of a package.
+type Info struct {
+	Defs         map[types.Object]*Block      // maps each object to its defining lexical block
+	Refs         map[types.Object][]Reference // maps each object to the set of references to it
+	Blocks       map[ast.Node]*Block          // maps declaring syntax to block; nil => universe
+	PackageBlock *Block                       // the package-level lexical block
+}
+
+// Structure computes the structure of the lexical environment of the
+// package specified by (pkg, info, files).
+//
+// The info.{Types,Defs,Uses,Implicits} maps must have been populated
+// by the type-checker
+//
+// fset is used for logging.
+//
+func Structure(fset *token.FileSet, pkg *types.Package, info *types.Info, files []*ast.File) *Info {
+	r := resolver{
+		fset:    fset,
+		imports: make(map[string]*types.Package),
+		result: &Info{
+			Defs:   make(map[types.Object]*Block),
+			Refs:   make(map[types.Object][]Reference),
+			Blocks: make(map[ast.Node]*Block),
+		},
+		pkg:  pkg,
+		info: info,
+	}
+
+	// Build import map for just this package.
+	r.imports["unsafe"] = types.Unsafe
+	for _, imp := range pkg.Imports() {
+		r.imports[imp.Path()] = imp
+	}
+
+	r.doPackage(pkg, files)
+
+	return r.result
+}
+
+// -- Plundered from golang.org/x/tools/go/ssa -----------------
+
+// deref returns a pointer's element type; otherwise it returns typ.
+func deref(typ types.Type) types.Type {
+	if p, ok := typ.Underlying().(*types.Pointer); ok {
+		return p.Elem()
+	}
+	return typ
+}
diff --git a/refactor/lexical/lexical_test.go b/refactor/lexical/lexical_test.go
new file mode 100644
index 0000000..77287a4
--- /dev/null
+++ b/refactor/lexical/lexical_test.go
@@ -0,0 +1,53 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Incomplete std lib sources on Android.
+
+// +build !android
+
+package lexical
+
+import (
+	"go/build"
+	"testing"
+
+	"golang.org/x/tools/go/buildutil"
+	"golang.org/x/tools/go/loader"
+)
+
+func TestStdlib(t *testing.T) {
+	defer func(saved func(format string, args ...interface{})) {
+		logf = saved
+	}(logf)
+	logf = t.Errorf
+
+	ctxt := build.Default // copy
+
+	// Enumerate $GOROOT packages.
+	saved := ctxt.GOPATH
+	ctxt.GOPATH = "" // disable GOPATH during AllPackages
+	pkgs := buildutil.AllPackages(&ctxt)
+	ctxt.GOPATH = saved
+
+	// Throw in a number of go.tools packages too.
+	pkgs = append(pkgs,
+		"golang.org/x/tools/cmd/godoc",
+		"golang.org/x/tools/refactor/lexical")
+
+	// Load, parse and type-check the program.
+	conf := loader.Config{Build: &ctxt}
+	for _, path := range pkgs {
+		conf.ImportWithTests(path)
+	}
+	iprog, err := conf.Load()
+	if err != nil {
+		t.Fatalf("Load failed: %v", err)
+	}
+
+	// This test ensures that Structure doesn't panic and that
+	// its internal sanity-checks against go/types don't fail.
+	for pkg, info := range iprog.AllPackages {
+		_ = Structure(iprog.Fset, pkg, &info.Info, info.Files)
+	}
+}
diff --git a/refactor/rename/check.go b/refactor/rename/check.go
new file mode 100644
index 0000000..017a604
--- /dev/null
+++ b/refactor/rename/check.go
@@ -0,0 +1,737 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package rename
+
+// This file defines the safety checks for each kind of renaming.
+
+import (
+	"fmt"
+	"go/ast"
+	"go/token"
+
+	"golang.org/x/tools/go/loader"
+	"golang.org/x/tools/go/types"
+	"golang.org/x/tools/refactor/lexical"
+	"golang.org/x/tools/refactor/satisfy"
+)
+
+// errorf reports an error (e.g. conflict) and prevents file modification.
+func (r *renamer) errorf(pos token.Pos, format string, args ...interface{}) {
+	r.hadConflicts = true
+	reportError(r.iprog.Fset.Position(pos), fmt.Sprintf(format, args...))
+}
+
+// check performs safety checks of the renaming of the 'from' object to r.to.
+func (r *renamer) check(from types.Object) {
+	if r.objsToUpdate[from] {
+		return
+	}
+	r.objsToUpdate[from] = true
+
+	// NB: order of conditions is important.
+	if from_, ok := from.(*types.PkgName); ok {
+		r.checkInFileBlock(from_)
+	} else if from_, ok := from.(*types.Label); ok {
+		r.checkLabel(from_)
+	} else if isPackageLevel(from) {
+		r.checkInPackageBlock(from)
+	} else if v, ok := from.(*types.Var); ok && v.IsField() {
+		r.checkStructField(v)
+	} else if f, ok := from.(*types.Func); ok && recv(f) != nil {
+		r.checkMethod(f)
+	} else if isLocal(from) {
+		r.checkInLocalScope(from)
+	} else {
+		r.errorf(from.Pos(), "unexpected %s object %q (please report a bug)\n",
+			objectKind(from), from)
+	}
+}
+
+// checkInFileBlock performs safety checks for renames of objects in the file block,
+// i.e. imported package names.
+func (r *renamer) checkInFileBlock(from *types.PkgName) {
+	// Check import name is not "init".
+	if r.to == "init" {
+		r.errorf(from.Pos(), "%q is not a valid imported package name", r.to)
+	}
+
+	// Check for conflicts between file and package block.
+	if prev := from.Pkg().Scope().Lookup(r.to); prev != nil {
+		r.errorf(from.Pos(), "renaming this %s %q to %q would conflict",
+			objectKind(from), from.Name(), r.to)
+		r.errorf(prev.Pos(), "\twith this package member %s",
+			objectKind(prev))
+		return // since checkInPackageBlock would report redundant errors
+	}
+
+	// Check for conflicts in lexical scope.
+	r.checkInLexicalScope(from, r.packages[from.Pkg()])
+
+	// Finally, modify ImportSpec syntax to add or remove the Name as needed.
+	info, path, _ := r.iprog.PathEnclosingInterval(from.Pos(), from.Pos())
+	if from.Imported().Name() == r.to {
+		// ImportSpec.Name not needed
+		path[1].(*ast.ImportSpec).Name = nil
+	} else {
+		// ImportSpec.Name needed
+		if spec := path[1].(*ast.ImportSpec); spec.Name == nil {
+			spec.Name = &ast.Ident{NamePos: spec.Path.Pos(), Name: r.to}
+			info.Defs[spec.Name] = from
+		}
+	}
+}
+
+// checkInPackageBlock performs safety checks for renames of
+// func/var/const/type objects in the package block.
+func (r *renamer) checkInPackageBlock(from types.Object) {
+	// Check that there are no references to the name from another
+	// package if the renaming would make it unexported.
+	if ast.IsExported(from.Name()) && !ast.IsExported(r.to) {
+		for pkg, info := range r.packages {
+			if pkg == from.Pkg() {
+				continue
+			}
+			if id := someUse(info, from); id != nil &&
+				!r.checkExport(id, pkg, from) {
+				break
+			}
+		}
+	}
+
+	info := r.packages[from.Pkg()]
+	lexinfo := lexical.Structure(r.iprog.Fset, from.Pkg(), &info.Info, info.Files)
+
+	// Check that in the package block, "init" is a function, and never referenced.
+	if r.to == "init" {
+		kind := objectKind(from)
+		if kind == "func" {
+			// Reject if intra-package references to it exist.
+			if refs := lexinfo.Refs[from]; len(refs) > 0 {
+				r.errorf(from.Pos(),
+					"renaming this func %q to %q would make it a package initializer",
+					from.Name(), r.to)
+				r.errorf(refs[0].Id.Pos(), "\tbut references to it exist")
+			}
+		} else {
+			r.errorf(from.Pos(), "you cannot have a %s at package level named %q",
+				kind, r.to)
+		}
+	}
+
+	// Check for conflicts between package block and all file blocks.
+	for _, f := range info.Files {
+		if prev, b := lexinfo.Blocks[f].Lookup(r.to); b == lexinfo.Blocks[f] {
+			r.errorf(from.Pos(), "renaming this %s %q to %q would conflict",
+				objectKind(from), from.Name(), r.to)
+			r.errorf(prev.Pos(), "\twith this %s",
+				objectKind(prev))
+			return // since checkInPackageBlock would report redundant errors
+		}
+	}
+
+	// Check for conflicts in lexical scope.
+	if from.Exported() {
+		for _, info := range r.packages {
+			r.checkInLexicalScope(from, info)
+		}
+	} else {
+		r.checkInLexicalScope(from, info)
+	}
+}
+
+func (r *renamer) checkInLocalScope(from types.Object) {
+	info := r.packages[from.Pkg()]
+
+	// Is this object an implicit local var for a type switch?
+	// Each case has its own var, whose position is the decl of y,
+	// but Ident in that decl does not appear in the Uses map.
+	//
+	//   switch y := x.(type) {	 // Defs[Ident(y)] is undefined
+	//   case int:    print(y)       // Implicits[CaseClause(int)]    = Var(y_int)
+	//   case string: print(y)       // Implicits[CaseClause(string)] = Var(y_string)
+	//   }
+	//
+	var isCaseVar bool
+	for syntax, obj := range info.Implicits {
+		if _, ok := syntax.(*ast.CaseClause); ok && obj.Pos() == from.Pos() {
+			isCaseVar = true
+			r.check(obj)
+		}
+	}
+
+	r.checkInLexicalScope(from, info)
+
+	// Finally, if this was a type switch, change the variable y.
+	if isCaseVar {
+		_, path, _ := r.iprog.PathEnclosingInterval(from.Pos(), from.Pos())
+		path[0].(*ast.Ident).Name = r.to // path is [Ident AssignStmt TypeSwitchStmt...]
+	}
+}
+
+// checkInLexicalScope performs safety checks that a renaming does not
+// change the lexical reference structure of the specified package.
+//
+// For objects in lexical scope, there are three kinds of conflicts:
+// same-, sub-, and super-block conflicts.  We will illustrate all three
+// using this example:
+//
+//	var x int
+//	var z int
+//
+//	func f(y int) {
+//		print(x)
+//		print(y)
+//	}
+//
+// Renaming x to z encounters a SAME-BLOCK CONFLICT, because an object
+// with the new name already exists, defined in the same lexical block
+// as the old object.
+//
+// Renaming x to y encounters a SUB-BLOCK CONFLICT, because there exists
+// a reference to x from within (what would become) a hole in its scope.
+// The definition of y in an (inner) sub-block would cast a shadow in
+// the scope of the renamed variable.
+//
+// Renaming y to x encounters a SUPER-BLOCK CONFLICT.  This is the
+// converse situation: there is an existing definition of the new name
+// (x) in an (enclosing) super-block, and the renaming would create a
+// hole in its scope, within which there exist references to it.  The
+// new name casts a shadow in scope of the existing definition of x in
+// the super-block.
+//
+// Removing the old name (and all references to it) is always safe, and
+// requires no checks.
+//
+func (r *renamer) checkInLexicalScope(from types.Object, info *loader.PackageInfo) {
+	lexinfo := lexical.Structure(r.iprog.Fset, info.Pkg, &info.Info, info.Files)
+
+	b := lexinfo.Defs[from] // the block defining the 'from' object
+	if b != nil {
+		to, toBlock := b.Lookup(r.to)
+		if toBlock == b {
+			// same-block conflict
+			r.errorf(from.Pos(), "renaming this %s %q to %q",
+				objectKind(from), from.Name(), r.to)
+			r.errorf(to.Pos(), "\tconflicts with %s in same block",
+				objectKind(to))
+			return
+		} else if toBlock != nil {
+			// Check for super-block conflict.
+			// The name r.to is defined in a superblock.
+			// Is that name referenced from within this block?
+			for _, ref := range lexinfo.Refs[to] {
+				if obj, _ := ref.Env.Lookup(from.Name()); obj == from {
+					// super-block conflict
+					r.errorf(from.Pos(), "renaming this %s %q to %q",
+						objectKind(from), from.Name(), r.to)
+					r.errorf(ref.Id.Pos(), "\twould shadow this reference")
+					r.errorf(to.Pos(), "\tto the %s declared here",
+						objectKind(to))
+					return
+				}
+			}
+		}
+	}
+
+	// Check for sub-block conflict.
+	// Is there an intervening definition of r.to between
+	// the block defining 'from' and some reference to it?
+	for _, ref := range lexinfo.Refs[from] {
+		// TODO(adonovan): think about dot imports.
+		// (Is b == fromBlock an invariant?)
+		_, fromBlock := ref.Env.Lookup(from.Name())
+		fromDepth := fromBlock.Depth()
+
+		to, toBlock := ref.Env.Lookup(r.to)
+		if to != nil {
+			// sub-block conflict
+			if toBlock.Depth() > fromDepth {
+				r.errorf(from.Pos(), "renaming this %s %q to %q",
+					objectKind(from), from.Name(), r.to)
+				r.errorf(ref.Id.Pos(), "\twould cause this reference to become shadowed")
+				r.errorf(to.Pos(), "\tby this intervening %s definition",
+					objectKind(to))
+				return
+			}
+		}
+	}
+
+	// Renaming a type that is used as an embedded field
+	// requires renaming the field too. e.g.
+	// 	type T int // if we rename this to U..
+	// 	var s struct {T}
+	// 	print(s.T) // ...this must change too
+	if _, ok := from.(*types.TypeName); ok {
+		for id, obj := range info.Uses {
+			if obj == from {
+				if field := info.Defs[id]; field != nil {
+					r.check(field)
+				}
+			}
+		}
+	}
+}
+
+func (r *renamer) checkLabel(label *types.Label) {
+	// Check there are no identical labels in the function's label block.
+	// (Label blocks don't nest, so this is easy.)
+	if prev := label.Parent().Lookup(r.to); prev != nil {
+		r.errorf(label.Pos(), "renaming this label %q to %q", label.Name(), prev.Name())
+		r.errorf(prev.Pos(), "\twould conflict with this one")
+	}
+}
+
+// checkStructField checks that the field renaming will not cause
+// conflicts at its declaration, or ambiguity or changes to any selection.
+func (r *renamer) checkStructField(from *types.Var) {
+	// Check that the struct declaration is free of field conflicts,
+	// and field/method conflicts.
+
+	// go/types offers no easy way to get from a field (or interface
+	// method) to its declaring struct (or interface), so we must
+	// ascend the AST.
+	info, path, _ := r.iprog.PathEnclosingInterval(from.Pos(), from.Pos())
+	// path matches this pattern:
+	// [Ident SelectorExpr? StarExpr? Field FieldList StructType ParenExpr* ... File]
+
+	// Ascend to FieldList.
+	var i int
+	for {
+		if _, ok := path[i].(*ast.FieldList); ok {
+			break
+		}
+		i++
+	}
+	i++
+	tStruct := path[i].(*ast.StructType)
+	i++
+	// Ascend past parens (unlikely).
+	for {
+		_, ok := path[i].(*ast.ParenExpr)
+		if !ok {
+			break
+		}
+		i++
+	}
+	if spec, ok := path[i].(*ast.TypeSpec); ok {
+		// This struct is also a named type.
+		// We must check for direct (non-promoted) field/field
+		// and method/field conflicts.
+		named := info.Defs[spec.Name].Type()
+		prev, indices, _ := types.LookupFieldOrMethod(named, true, info.Pkg, r.to)
+		if len(indices) == 1 {
+			r.errorf(from.Pos(), "renaming this field %q to %q",
+				from.Name(), r.to)
+			r.errorf(prev.Pos(), "\twould conflict with this %s",
+				objectKind(prev))
+			return // skip checkSelections to avoid redundant errors
+		}
+	} else {
+		// This struct is not a named type.
+		// We need only check for direct (non-promoted) field/field conflicts.
+		T := info.Types[tStruct].Type.Underlying().(*types.Struct)
+		for i := 0; i < T.NumFields(); i++ {
+			if prev := T.Field(i); prev.Name() == r.to {
+				r.errorf(from.Pos(), "renaming this field %q to %q",
+					from.Name(), r.to)
+				r.errorf(prev.Pos(), "\twould conflict with this field")
+				return // skip checkSelections to avoid redundant errors
+			}
+		}
+	}
+
+	// Renaming an anonymous field requires renaming the type too. e.g.
+	// 	print(s.T)       // if we rename T to U,
+	// 	type T int       // this and
+	// 	var s struct {T} // this must change too.
+	if from.Anonymous() {
+		if named, ok := from.Type().(*types.Named); ok {
+			r.check(named.Obj())
+		} else if named, ok := deref(from.Type()).(*types.Named); ok {
+			r.check(named.Obj())
+		}
+	}
+
+	// Check integrity of existing (field and method) selections.
+	r.checkSelections(from)
+}
+
+// checkSelection checks that all uses and selections that resolve to
+// the specified object would continue to do so after the renaming.
+func (r *renamer) checkSelections(from types.Object) {
+	for pkg, info := range r.packages {
+		if id := someUse(info, from); id != nil {
+			if !r.checkExport(id, pkg, from) {
+				return
+			}
+		}
+
+		for syntax, sel := range info.Selections {
+			// There may be extant selections of only the old
+			// name or only the new name, so we must check both.
+			// (If neither, the renaming is sound.)
+			//
+			// In both cases, we wish to compare the lengths
+			// of the implicit field path (Selection.Index)
+			// to see if the renaming would change it.
+			//
+			// If a selection that resolves to 'from', when renamed,
+			// would yield a path of the same or shorter length,
+			// this indicates ambiguity or a changed referent,
+			// analogous to same- or sub-block lexical conflict.
+			//
+			// If a selection using the name 'to' would
+			// yield a path of the same or shorter length,
+			// this indicates ambiguity or shadowing,
+			// analogous to same- or super-block lexical conflict.
+
+			// TODO(adonovan): fix: derive from Types[syntax.X].Mode
+			// TODO(adonovan): test with pointer, value, addressable value.
+			isAddressable := true
+
+			if sel.Obj() == from {
+				if obj, indices, _ := types.LookupFieldOrMethod(sel.Recv(), isAddressable, from.Pkg(), r.to); obj != nil {
+					// Renaming this existing selection of
+					// 'from' may block access to an existing
+					// type member named 'to'.
+					delta := len(indices) - len(sel.Index())
+					if delta > 0 {
+						continue // no ambiguity
+					}
+					r.selectionConflict(from, delta, syntax, obj)
+					return
+				}
+
+			} else if sel.Obj().Name() == r.to {
+				if obj, indices, _ := types.LookupFieldOrMethod(sel.Recv(), isAddressable, from.Pkg(), from.Name()); obj == from {
+					// Renaming 'from' may cause this existing
+					// selection of the name 'to' to change
+					// its meaning.
+					delta := len(indices) - len(sel.Index())
+					if delta > 0 {
+						continue //  no ambiguity
+					}
+					r.selectionConflict(from, -delta, syntax, sel.Obj())
+					return
+				}
+			}
+		}
+	}
+}
+
+func (r *renamer) selectionConflict(from types.Object, delta int, syntax *ast.SelectorExpr, obj types.Object) {
+	r.errorf(from.Pos(), "renaming this %s %q to %q",
+		objectKind(from), from.Name(), r.to)
+
+	switch {
+	case delta < 0:
+		// analogous to sub-block conflict
+		r.errorf(syntax.Sel.Pos(),
+			"\twould change the referent of this selection")
+		r.errorf(obj.Pos(), "\tof this %s", objectKind(obj))
+	case delta == 0:
+		// analogous to same-block conflict
+		r.errorf(syntax.Sel.Pos(),
+			"\twould make this reference ambiguous")
+		r.errorf(obj.Pos(), "\twith this %s", objectKind(obj))
+	case delta > 0:
+		// analogous to super-block conflict
+		r.errorf(syntax.Sel.Pos(),
+			"\twould shadow this selection")
+		r.errorf(obj.Pos(), "\tof the %s declared here",
+			objectKind(obj))
+	}
+}
+
+// checkMethod performs safety checks for renaming a method.
+// There are three hazards:
+// - declaration conflicts
+// - selection ambiguity/changes
+// - entailed renamings of assignable concrete/interface types.
+//   We reject renamings initiated at concrete methods if it would
+//   change the assignability relation.  For renamings of abstract
+//   methods, we rename all methods transitively coupled to it via
+//   assignability.
+func (r *renamer) checkMethod(from *types.Func) {
+	// e.g. error.Error
+	if from.Pkg() == nil {
+		r.errorf(from.Pos(), "you cannot rename built-in method %s", from)
+		return
+	}
+
+	// ASSIGNABILITY: We reject renamings of concrete methods that
+	// would break a 'satisfy' constraint; but renamings of abstract
+	// methods are allowed to proceed, and we rename affected
+	// concrete and abstract methods as necessary.  It is the
+	// initial method that determines the policy.
+
+	// Check for conflict at point of declaration.
+	// Check to ensure preservation of assignability requirements.
+	R := recv(from).Type()
+	if isInterface(R) {
+		// Abstract method
+
+		// declaration
+		prev, _, _ := types.LookupFieldOrMethod(R, false, from.Pkg(), r.to)
+		if prev != nil {
+			r.errorf(from.Pos(), "renaming this interface method %q to %q",
+				from.Name(), r.to)
+			r.errorf(prev.Pos(), "\twould conflict with this method")
+			return
+		}
+
+		// Check all interfaces that embed this one for
+		// declaration conflicts too.
+		for _, info := range r.packages {
+			// Start with named interface types (better errors)
+			for _, obj := range info.Defs {
+				if obj, ok := obj.(*types.TypeName); ok && isInterface(obj.Type()) {
+					f, _, _ := types.LookupFieldOrMethod(
+						obj.Type(), false, from.Pkg(), from.Name())
+					if f == nil {
+						continue
+					}
+					t, _, _ := types.LookupFieldOrMethod(
+						obj.Type(), false, from.Pkg(), r.to)
+					if t == nil {
+						continue
+					}
+					r.errorf(from.Pos(), "renaming this interface method %q to %q",
+						from.Name(), r.to)
+					r.errorf(t.Pos(), "\twould conflict with this method")
+					r.errorf(obj.Pos(), "\tin named interface type %q", obj.Name())
+				}
+			}
+
+			// Now look at all literal interface types (includes named ones again).
+			for e, tv := range info.Types {
+				if e, ok := e.(*ast.InterfaceType); ok {
+					_ = e
+					_ = tv.Type.(*types.Interface)
+					// TODO(adonovan): implement same check as above.
+				}
+			}
+		}
+
+		// assignability
+		//
+		// Find the set of concrete or abstract methods directly
+		// coupled to abstract method 'from' by some
+		// satisfy.Constraint, and rename them too.
+		for key := range r.satisfy() {
+			// key = (lhs, rhs) where lhs is always an interface.
+
+			lsel := r.msets.MethodSet(key.LHS).Lookup(from.Pkg(), from.Name())
+			if lsel == nil {
+				continue
+			}
+			rmethods := r.msets.MethodSet(key.RHS)
+			rsel := rmethods.Lookup(from.Pkg(), from.Name())
+			if rsel == nil {
+				continue
+			}
+
+			// If both sides have a method of this name,
+			// and one of them is m, the other must be coupled.
+			var coupled *types.Func
+			switch from {
+			case lsel.Obj():
+				coupled = rsel.Obj().(*types.Func)
+			case rsel.Obj():
+				coupled = lsel.Obj().(*types.Func)
+			default:
+				continue
+			}
+
+			// We must treat concrete-to-interface
+			// constraints like an implicit selection C.f of
+			// each interface method I.f, and check that the
+			// renaming leaves the selection unchanged and
+			// unambiguous.
+			//
+			// Fun fact: the implicit selection of C.f
+			// 	type I interface{f()}
+			// 	type C struct{I}
+			// 	func (C) g()
+			//      var _ I = C{} // here
+			// yields abstract method I.f.  This can make error
+			// messages less than obvious.
+			//
+			if !isInterface(key.RHS) {
+				// The logic below was derived from checkSelections.
+
+				rtosel := rmethods.Lookup(from.Pkg(), r.to)
+				if rtosel != nil {
+					rto := rtosel.Obj().(*types.Func)
+					delta := len(rsel.Index()) - len(rtosel.Index())
+					if delta < 0 {
+						continue // no ambiguity
+					}
+
+					// TODO(adonovan): record the constraint's position.
+					keyPos := token.NoPos
+
+					r.errorf(from.Pos(), "renaming this method %q to %q",
+						from.Name(), r.to)
+					if delta == 0 {
+						// analogous to same-block conflict
+						r.errorf(keyPos, "\twould make the %s method of %s invoked via interface %s ambiguous",
+							r.to, key.RHS, key.LHS)
+						r.errorf(rto.Pos(), "\twith (%s).%s",
+							recv(rto).Type(), r.to)
+					} else {
+						// analogous to super-block conflict
+						r.errorf(keyPos, "\twould change the %s method of %s invoked via interface %s",
+							r.to, key.RHS, key.LHS)
+						r.errorf(coupled.Pos(), "\tfrom (%s).%s",
+							recv(coupled).Type(), r.to)
+						r.errorf(rto.Pos(), "\tto (%s).%s",
+							recv(rto).Type(), r.to)
+					}
+					return // one error is enough
+				}
+			}
+
+			if !r.changeMethods {
+				// This should be unreachable.
+				r.errorf(from.Pos(), "internal error: during renaming of abstract method %s", from)
+				r.errorf(coupled.Pos(), "\tchangedMethods=false, coupled method=%s", coupled)
+				r.errorf(from.Pos(), "\tPlease file a bug report")
+				return
+			}
+
+			// Rename the coupled method to preserve assignability.
+			r.check(coupled)
+		}
+	} else {
+		// Concrete method
+
+		// declaration
+		prev, indices, _ := types.LookupFieldOrMethod(R, true, from.Pkg(), r.to)
+		if prev != nil && len(indices) == 1 {
+			r.errorf(from.Pos(), "renaming this method %q to %q",
+				from.Name(), r.to)
+			r.errorf(prev.Pos(), "\twould conflict with this %s",
+				objectKind(prev))
+			return
+		}
+
+		// assignability
+		//
+		// Find the set of abstract methods coupled to concrete
+		// method 'from' by some satisfy.Constraint, and rename
+		// them too.
+		//
+		// Coupling may be indirect, e.g. I.f <-> C.f via type D.
+		//
+		// 	type I interface {f()}
+		//	type C int
+		//	type (C) f()
+		//	type D struct{C}
+		//	var _ I = D{}
+		//
+		for key := range r.satisfy() {
+			// key = (lhs, rhs) where lhs is always an interface.
+			if isInterface(key.RHS) {
+				continue
+			}
+			rsel := r.msets.MethodSet(key.RHS).Lookup(from.Pkg(), from.Name())
+			if rsel == nil || rsel.Obj() != from {
+				continue // rhs does not have the method
+			}
+			lsel := r.msets.MethodSet(key.LHS).Lookup(from.Pkg(), from.Name())
+			if lsel == nil {
+				continue
+			}
+			imeth := lsel.Obj().(*types.Func)
+
+			// imeth is the abstract method (e.g. I.f)
+			// and key.RHS is the concrete coupling type (e.g. D).
+			if !r.changeMethods {
+				r.errorf(from.Pos(), "renaming this method %q to %q",
+					from.Name(), r.to)
+				var pos token.Pos
+				var iface string
+
+				I := recv(imeth).Type()
+				if named, ok := I.(*types.Named); ok {
+					pos = named.Obj().Pos()
+					iface = "interface " + named.Obj().Name()
+				} else {
+					pos = from.Pos()
+					iface = I.String()
+				}
+				r.errorf(pos, "\twould make %s no longer assignable to %s",
+					key.RHS, iface)
+				r.errorf(imeth.Pos(), "\t(rename %s.%s if you intend to change both types)",
+					I, from.Name())
+				return // one error is enough
+			}
+
+			// Rename the coupled interface method to preserve assignability.
+			r.check(imeth)
+		}
+	}
+
+	// Check integrity of existing (field and method) selections.
+	// We skip this if there were errors above, to avoid redundant errors.
+	r.checkSelections(from)
+}
+
+func (r *renamer) checkExport(id *ast.Ident, pkg *types.Package, from types.Object) bool {
+	// Reject cross-package references if r.to is unexported.
+	// (Such references may be qualified identifiers or field/method
+	// selections.)
+	if !ast.IsExported(r.to) && pkg != from.Pkg() {
+		r.errorf(from.Pos(),
+			"renaming this %s %q to %q would make it unexported",
+			objectKind(from), from.Name(), r.to)
+		r.errorf(id.Pos(), "\tbreaking references from packages such as %q",
+			pkg.Path())
+		return false
+	}
+	return true
+}
+
+// satisfy returns the set of interface satisfaction constraints.
+func (r *renamer) satisfy() map[satisfy.Constraint]bool {
+	if r.satisfyConstraints == nil {
+		// Compute on demand: it's expensive.
+		var f satisfy.Finder
+		for _, info := range r.packages {
+			f.Find(&info.Info, info.Files)
+		}
+		r.satisfyConstraints = f.Result
+	}
+	return r.satisfyConstraints
+}
+
+// -- helpers ----------------------------------------------------------
+
+// recv returns the method's receiver.
+func recv(meth *types.Func) *types.Var {
+	return meth.Type().(*types.Signature).Recv()
+}
+
+// someUse returns an arbitrary use of obj within info.
+func someUse(info *loader.PackageInfo, obj types.Object) *ast.Ident {
+	for id, o := range info.Uses {
+		if o == obj {
+			return id
+		}
+	}
+	return nil
+}
+
+// -- Plundered from golang.org/x/tools/go/ssa -----------------
+
+func isInterface(T types.Type) bool { return types.IsInterface(T) }
+
+func deref(typ types.Type) types.Type {
+	if p, _ := typ.(*types.Pointer); p != nil {
+		return p.Elem()
+	}
+	return typ
+}
diff --git a/refactor/rename/mvpkg.go b/refactor/rename/mvpkg.go
new file mode 100644
index 0000000..bb0d9b0
--- /dev/null
+++ b/refactor/rename/mvpkg.go
@@ -0,0 +1,343 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// licence that can be found in the LICENSE file.
+
+// This file contains the implementation of the 'gomvpkg' command
+// whose main function is in golang.org/x/tools/cmd/gomvpkg.
+
+package rename
+
+// TODO(matloob):
+// - think about what happens if the package is moving across version control systems.
+// - think about windows, which uses "\" as its directory separator.
+// - dot imports are not supported. Make sure it's clearly documented.
+
+import (
+	"bytes"
+	"fmt"
+	"go/ast"
+	"go/build"
+	"log"
+	"os"
+	"os/exec"
+	"path"
+	"path/filepath"
+	"regexp"
+	"runtime"
+	"strconv"
+	"strings"
+	"text/template"
+
+	"golang.org/x/tools/go/buildutil"
+	"golang.org/x/tools/go/loader"
+	"golang.org/x/tools/refactor/importgraph"
+)
+
+// Move, given a package path and a destination package path, will try
+// to move the given package to the new path. The Move function will
+// first check for any conflicts preventing the move, such as a
+// package already existing at the destination package path. If the
+// move can proceed, it builds an import graph to find all imports of
+// the packages whose paths need to be renamed. This includes uses of
+// the subpackages of the package to be moved as those packages will
+// also need to be moved. It then renames all imports to point to the
+// new paths, and then moves the packages to their new paths.
+func Move(ctxt *build.Context, from, to, moveTmpl string) error {
+	srcDir, err := srcDir(ctxt, from)
+	if err != nil {
+		return err
+	}
+
+	// This should be the only place in the program that constructs
+	// file paths.
+	// TODO(matloob): test on Microsoft Windows.
+	fromDir := buildutil.JoinPath(ctxt, srcDir, filepath.FromSlash(from))
+	toDir := buildutil.JoinPath(ctxt, srcDir, filepath.FromSlash(to))
+	toParent := filepath.Dir(toDir)
+	if !buildutil.IsDir(ctxt, toParent) {
+		return fmt.Errorf("parent directory does not exist for path %s", toDir)
+	}
+
+	// Build the import graph and figure out which packages to update.
+	fwd, rev, errors := importgraph.Build(ctxt)
+	if len(errors) > 0 {
+		// With a large GOPATH tree, errors are inevitable.
+		// Report them but proceed.
+		fmt.Fprintf(os.Stderr, "While scanning Go workspace:\n")
+		for path, err := range errors {
+			fmt.Fprintf(os.Stderr, "Package %q: %s.\n", path, err)
+		}
+	}
+
+	// Determine the affected packages---the set of packages whose import
+	// statements need updating.
+	affectedPackages := map[string]bool{from: true}
+	destinations := map[string]string{} // maps old dir to new dir
+	for pkg := range subpackages(ctxt, srcDir, from) {
+		for r := range rev[pkg] {
+			affectedPackages[r] = true
+		}
+		destinations[pkg] = strings.Replace(pkg,
+			// Ensure directories have a trailing "/".
+			filepath.Join(from, ""), filepath.Join(to, ""), 1)
+	}
+
+	// Load all the affected packages.
+	iprog, err := loadProgram(ctxt, affectedPackages)
+	if err != nil {
+		return err
+	}
+
+	// Prepare the move command, if one was supplied.
+	var cmd string
+	if moveTmpl != "" {
+		if cmd, err = moveCmd(moveTmpl, fromDir, toDir); err != nil {
+			return err
+		}
+	}
+
+	m := mover{
+		ctxt:             ctxt,
+		fwd:              fwd,
+		rev:              rev,
+		iprog:            iprog,
+		from:             from,
+		to:               to,
+		fromDir:          fromDir,
+		toDir:            toDir,
+		affectedPackages: affectedPackages,
+		destinations:     destinations,
+		cmd:              cmd,
+	}
+
+	if err := m.checkValid(); err != nil {
+		return err
+	}
+
+	m.move()
+
+	return nil
+}
+
+// srcDir returns the absolute path of the srcdir containing pkg.
+func srcDir(ctxt *build.Context, pkg string) (string, error) {
+	for _, srcDir := range ctxt.SrcDirs() {
+		path := buildutil.JoinPath(ctxt, srcDir, pkg)
+		if buildutil.IsDir(ctxt, path) {
+			return srcDir, nil
+		}
+	}
+	return "", fmt.Errorf("src dir not found for package: %s", pkg)
+}
+
+// subpackages returns the set of packages in the given srcDir whose
+// import paths start with dir.
+func subpackages(ctxt *build.Context, srcDir string, dir string) map[string]bool {
+	subs := map[string]bool{dir: true}
+
+	// Find all packages under srcDir whose import paths start with dir.
+	buildutil.ForEachPackage(ctxt, func(pkg string, err error) {
+		if err != nil {
+			log.Fatalf("unexpected error in ForEachPackage: %v", err)
+		}
+
+		if !strings.HasPrefix(pkg, path.Join(dir, "")) {
+			return
+		}
+
+		p, err := ctxt.Import(pkg, "", build.FindOnly)
+		if err != nil {
+			log.Fatalf("unexpected: package %s can not be located by build context: %s", pkg, err)
+		}
+		if p.SrcRoot == "" {
+			log.Fatalf("unexpected: could not determine srcDir for package %s: %s", pkg, err)
+		}
+		if p.SrcRoot != srcDir {
+			return
+		}
+
+		subs[pkg] = true
+	})
+
+	return subs
+}
+
+type mover struct {
+	// iprog contains all packages whose contents need to be updated
+	// with new package names or import paths.
+	iprog *loader.Program
+	ctxt  *build.Context
+	// fwd and rev are the forward and reverse import graphs
+	fwd, rev importgraph.Graph
+	// from and to are the source and destination import
+	// paths. fromDir and toDir are the source and destination
+	// absolute paths that package source files will be moved between.
+	from, to, fromDir, toDir string
+	// affectedPackages is the set of all packages whose contents need
+	// to be updated to reflect new package names or import paths.
+	affectedPackages map[string]bool
+	// destinations maps each subpackage to be moved to its
+	// destination path.
+	destinations map[string]string
+	// cmd, if not empty, will be executed to move fromDir to toDir.
+	cmd string
+}
+
+func (m *mover) checkValid() error {
+	const prefix = "invalid move destination"
+
+	match, err := regexp.MatchString("^[_\\pL][_\\pL\\p{Nd}]*$", path.Base(m.to))
+	if err != nil {
+		panic("regexp.MatchString failed")
+	}
+	if !match {
+		return fmt.Errorf("%s: %s; gomvpkg does not support move destinations "+
+			"whose base names are not valid go identifiers", prefix, m.to)
+	}
+
+	if buildutil.FileExists(m.ctxt, m.toDir) {
+		return fmt.Errorf("%s: %s conflicts with file %s", prefix, m.to, m.toDir)
+	}
+	if buildutil.IsDir(m.ctxt, m.toDir) {
+		return fmt.Errorf("%s: %s conflicts with directory %s", prefix, m.to, m.toDir)
+	}
+
+	for _, toSubPkg := range m.destinations {
+		if _, err := m.ctxt.Import(toSubPkg, "", build.FindOnly); err == nil {
+			return fmt.Errorf("%s: %s; package or subpackage %s already exists",
+				prefix, m.to, toSubPkg)
+		}
+	}
+
+	return nil
+}
+
+// moveCmd produces the version control move command used to move fromDir to toDir by
+// executing the given template.
+func moveCmd(moveTmpl, fromDir, toDir string) (string, error) {
+	tmpl, err := template.New("movecmd").Parse(moveTmpl)
+	if err != nil {
+		return "", err
+	}
+
+	var buf bytes.Buffer
+	err = tmpl.Execute(&buf, struct {
+		Src string
+		Dst string
+	}{fromDir, toDir})
+	return buf.String(), err
+}
+
+func (m *mover) move() error {
+	filesToUpdate := make(map[*ast.File]bool)
+
+	// Change the moved package's "package" declaration to its new base name.
+	pkg, ok := m.iprog.Imported[m.from]
+	if !ok {
+		log.Fatalf("unexpected: package %s is not in import map", m.from)
+	}
+	newName := filepath.Base(m.to)
+	for _, f := range pkg.Files {
+		f.Name.Name = newName // change package decl
+		filesToUpdate[f] = true
+	}
+
+	// Look through the external test packages (m.iprog.Created contains the external test packages).
+	for _, info := range m.iprog.Created {
+		// Change the "package" declaration of the external test package.
+		if info.Pkg.Path() == m.from+"_test" {
+			for _, f := range info.Files {
+				f.Name.Name = newName + "_test" // change package decl
+				filesToUpdate[f] = true
+			}
+		}
+
+		// Mark all the loaded external test packages, which import the "from" package,
+		// as affected packages and update the imports.
+		for _, imp := range info.Pkg.Imports() {
+			if imp.Path() == m.from {
+				m.affectedPackages[info.Pkg.Path()] = true
+				m.iprog.Imported[info.Pkg.Path()] = info
+				if err := importName(m.iprog, info, m.from, path.Base(m.from), newName); err != nil {
+					return err
+				}
+			}
+		}
+	}
+
+	// Update imports of that package to use the new import name.
+	// None of the subpackages will change their name---only the from package
+	// itself will.
+	for p := range m.rev[m.from] {
+		if err := importName(m.iprog, m.iprog.Imported[p], m.from, path.Base(m.from), newName); err != nil {
+			return err
+		}
+	}
+
+	// Update import paths for all imports by affected packages.
+	for ap := range m.affectedPackages {
+		info, ok := m.iprog.Imported[ap]
+		if !ok {
+			log.Fatalf("unexpected: package %s is not in import map", ap)
+		}
+		for _, f := range info.Files {
+			for _, imp := range f.Imports {
+				importPath, _ := strconv.Unquote(imp.Path.Value)
+				if newPath, ok := m.destinations[importPath]; ok {
+					imp.Path.Value = strconv.Quote(newPath)
+
+					oldName := path.Base(importPath)
+					if imp.Name != nil {
+						oldName = imp.Name.Name
+					}
+
+					newName := path.Base(newPath)
+					if imp.Name == nil && oldName != newName {
+						imp.Name = ast.NewIdent(oldName)
+					} else if imp.Name == nil || imp.Name.Name == newName {
+						imp.Name = nil
+					}
+					filesToUpdate[f] = true
+				}
+			}
+		}
+	}
+
+	for f := range filesToUpdate {
+		tokenFile := m.iprog.Fset.File(f.Pos())
+		rewriteFile(m.iprog.Fset, f, tokenFile.Name())
+	}
+
+	// Move the directories.
+	// If either the fromDir or toDir are contained under version control it is
+	// the user's responsibility to provide a custom move command that updates
+	// version control to reflect the move.
+	// TODO(matloob): If the parent directory of toDir does not exist, create it.
+	//      For now, it's required that it does exist.
+
+	if m.cmd != "" {
+		// TODO(matloob): Verify that the windows and plan9 cases are correct.
+		var cmd *exec.Cmd
+		switch runtime.GOOS {
+		case "windows":
+			cmd = exec.Command("cmd", "/c", m.cmd)
+		case "plan9":
+			cmd = exec.Command("rc", "-c", m.cmd)
+		default:
+			cmd = exec.Command("sh", "-c", m.cmd)
+		}
+		cmd.Stderr = os.Stderr
+		cmd.Stdout = os.Stdout
+		if err := cmd.Run(); err != nil {
+			return fmt.Errorf("version control system's move command failed: %v", err)
+		}
+
+		return nil
+	}
+
+	return moveDirectory(m.fromDir, m.toDir)
+}
+
+var moveDirectory = func(from, to string) error {
+	return os.Rename(from, to)
+}
diff --git a/refactor/rename/mvpkg_test.go b/refactor/rename/mvpkg_test.go
new file mode 100644
index 0000000..61fa354
--- /dev/null
+++ b/refactor/rename/mvpkg_test.go
@@ -0,0 +1,316 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// licence that can be found in the LICENSE file.
+
+package rename
+
+import (
+	"bytes"
+	"fmt"
+	"go/ast"
+	"go/build"
+	"go/format"
+	"go/token"
+	"io/ioutil"
+	"path/filepath"
+	"regexp"
+	"strings"
+	"testing"
+
+	"golang.org/x/tools/go/buildutil"
+)
+
+func TestErrors(t *testing.T) {
+	tests := []struct {
+		ctxt     *build.Context
+		from, to string
+		want     string // regexp to match error, or "OK"
+	}{
+		// Simple example.
+		{
+			ctxt: fakeContext(map[string][]string{
+				"foo": {`package foo; type T int`},
+				"bar": {`package bar`},
+				"main": {`package main
+
+import "foo"
+
+var _ foo.T
+`},
+			}),
+			from: "foo", to: "bar",
+			want: `invalid move destination: bar conflicts with directory .go.src.bar`,
+		},
+		// Subpackage already exists.
+		{
+			ctxt: fakeContext(map[string][]string{
+				"foo":     {`package foo; type T int`},
+				"foo/sub": {`package sub`},
+				"bar/sub": {`package sub`},
+				"main": {`package main
+
+import "foo"
+
+var _ foo.T
+`},
+			}),
+			from: "foo", to: "bar",
+			want: "invalid move destination: bar; package or subpackage bar/sub already exists",
+		},
+		// Invalid base name.
+		{
+			ctxt: fakeContext(map[string][]string{
+				"foo": {`package foo; type T int`},
+				"main": {`package main
+
+import "foo"
+
+var _ foo.T
+`},
+			}),
+			from: "foo", to: "bar-v2.0",
+			want: "invalid move destination: bar-v2.0; gomvpkg does not " +
+				"support move destinations whose base names are not valid " +
+				"go identifiers",
+		},
+	}
+
+	for _, test := range tests {
+		ctxt := test.ctxt
+
+		got := make(map[string]string)
+		rewriteFile = func(fset *token.FileSet, f *ast.File, orig string) error {
+			var out bytes.Buffer
+			if err := format.Node(&out, fset, f); err != nil {
+				return err
+			}
+			got[orig] = out.String()
+			return nil
+		}
+		moveDirectory = func(from, to string) error {
+			for path, contents := range got {
+				if strings.HasPrefix(path, from) {
+					newPath := strings.Replace(path, from, to, 1)
+					delete(got, path)
+					got[newPath] = contents
+				}
+			}
+			return nil
+		}
+
+		err := Move(ctxt, test.from, test.to, "")
+		prefix := fmt.Sprintf("-from %q -to %q", test.from, test.to)
+		if err == nil {
+			t.Errorf("%s: nil error. Expected error: %s", prefix, test.want)
+			continue
+		}
+		matched, err2 := regexp.MatchString(test.want, err.Error())
+		if err2 != nil {
+			t.Errorf("regexp.MatchString failed %s", err2)
+			continue
+		}
+		if !matched {
+			t.Errorf("%s: conflict does not match expectation:\n"+
+				"Error: %q\n"+
+				"Pattern: %q",
+				prefix, err.Error(), test.want)
+		}
+	}
+}
+
+func TestMoves(t *testing.T) {
+	tests := []struct {
+		ctxt     *build.Context
+		from, to string
+		want     map[string]string
+	}{
+		// Simple example.
+		{
+			ctxt: fakeContext(map[string][]string{
+				"foo": {`package foo; type T int`},
+				"main": {`package main
+
+import "foo"
+
+var _ foo.T
+`},
+			}),
+			from: "foo", to: "bar",
+			want: map[string]string{
+				"/go/src/main/0.go": `package main
+
+import "bar"
+
+var _ bar.T
+`,
+				"/go/src/bar/0.go": `package bar
+
+type T int
+`,
+			},
+		},
+
+		// Example with subpackage.
+		{
+			ctxt: fakeContext(map[string][]string{
+				"foo":     {`package foo; type T int`},
+				"foo/sub": {`package sub; type T int`},
+				"main": {`package main
+
+import "foo"
+import "foo/sub"
+
+var _ foo.T
+var _ sub.T
+`},
+			}),
+			from: "foo", to: "bar",
+			want: map[string]string{
+				"/go/src/main/0.go": `package main
+
+import "bar"
+import "bar/sub"
+
+var _ bar.T
+var _ sub.T
+`,
+				"/go/src/bar/0.go": `package bar
+
+type T int
+`,
+				"/go/src/bar/sub/0.go": `package sub; type T int`,
+			},
+		},
+
+		// References into subpackages
+		{
+			ctxt: fakeContext(map[string][]string{
+				"foo":   {`package foo; import "foo/a"; var _ a.T`},
+				"foo/a": {`package a; type T int`},
+				"foo/b": {`package b; import "foo/a"; var _ a.T`},
+			}),
+			from: "foo", to: "bar",
+			want: map[string]string{
+				"/go/src/bar/0.go": `package bar
+
+import "bar/a"
+
+var _ a.T
+`,
+				"/go/src/bar/a/0.go": `package a; type T int`,
+				"/go/src/bar/b/0.go": `package b
+
+import "bar/a"
+
+var _ a.T
+`,
+			},
+		},
+
+		// External test packages
+		{
+			ctxt: buildutil.FakeContext(map[string]map[string]string{
+				"foo": {
+					"0.go":      `package foo; type T int`,
+					"0_test.go": `package foo_test; import "foo"; var _ foo.T`,
+				},
+				"baz": {
+					"0_test.go": `package baz_test; import "foo"; var _ foo.T`,
+				},
+			}),
+			from: "foo", to: "bar",
+			want: map[string]string{
+				"/go/src/bar/0.go": `package bar
+
+type T int
+`,
+				"/go/src/bar/0_test.go": `package bar_test
+
+import "bar"
+
+var _ bar.T
+`,
+				"/go/src/baz/0_test.go": `package baz_test
+
+import "bar"
+
+var _ bar.T
+`,
+			},
+		},
+	}
+
+	for _, test := range tests {
+		ctxt := test.ctxt
+
+		got := make(map[string]string)
+		// Populate got with starting file set. rewriteFile and moveDirectory
+		// will mutate got to produce resulting file set.
+		buildutil.ForEachPackage(ctxt, func(importPath string, err error) {
+			if err != nil {
+				return
+			}
+			path := filepath.Join("/go/src", importPath, "0.go")
+			if !buildutil.FileExists(ctxt, path) {
+				return
+			}
+			f, err := ctxt.OpenFile(path)
+			if err != nil {
+				t.Errorf("unexpected error opening file: %s", err)
+				return
+			}
+			bytes, err := ioutil.ReadAll(f)
+			f.Close()
+			if err != nil {
+				t.Errorf("unexpected error reading file: %s", err)
+				return
+			}
+			got[path] = string(bytes)
+		})
+		rewriteFile = func(fset *token.FileSet, f *ast.File, orig string) error {
+			var out bytes.Buffer
+			if err := format.Node(&out, fset, f); err != nil {
+				return err
+			}
+			got[orig] = out.String()
+			return nil
+		}
+		moveDirectory = func(from, to string) error {
+			for path, contents := range got {
+				if strings.HasPrefix(path, from) {
+					newPath := strings.Replace(path, from, to, 1)
+					delete(got, path)
+					got[newPath] = contents
+				}
+			}
+			return nil
+		}
+
+		err := Move(ctxt, test.from, test.to, "")
+		prefix := fmt.Sprintf("-from %q -to %q", test.from, test.to)
+		if err != nil {
+			t.Errorf("%s: unexpected error: %s", prefix, err)
+			continue
+		}
+
+		for file, wantContent := range test.want {
+			k := filepath.FromSlash(file)
+			gotContent, ok := got[k]
+			delete(got, k)
+			if !ok {
+				// TODO(matloob): some testcases might have files that won't be
+				// rewritten
+				t.Errorf("%s: file %s not rewritten", prefix, file)
+				continue
+			}
+			if gotContent != wantContent {
+				t.Errorf("%s: rewritten file %s does not match expectation; got <<<%s>>>\n"+
+					"want <<<%s>>>", prefix, file, gotContent, wantContent)
+			}
+		}
+		// got should now be empty
+		for file := range got {
+			t.Errorf("%s: unexpected rewrite of file %s", prefix, file)
+		}
+	}
+}
diff --git a/refactor/rename/rename.el b/refactor/rename/rename.el
new file mode 100644
index 0000000..139bb47
--- /dev/null
+++ b/refactor/rename/rename.el
@@ -0,0 +1,96 @@
+;;; Copyright 2014 The Go Authors. All rights reserved.
+;;; Use of this source code is governed by a BSD-style
+;;; license that can be found in the LICENSE file.
+;;;
+;;; Integration of the 'gorename' tool into Emacs.
+;;;
+;;; To install:
+;;; % go get golang.org/x/tools/cmd/gorename
+;;; % go build golang.org/x/tools/cmd/gorename
+;;; % mv gorename $HOME/bin/         # or elsewhere on $PATH
+;;;
+;;; The go-rename-command variable can be customized to specify an
+;;; alternative location for the installed command.
+
+(require 'compile)
+(require 'go-mode)
+(require 'thingatpt)
+
+(defgroup go-rename nil
+  "Options specific to the Go rename."
+  :group 'go)
+
+(defcustom go-rename-command "gorename"
+  "The `gorename' command; by the default, $PATH is searched."
+  :type 'string
+  :group 'go-rename)
+
+(defun go-rename (new-name &optional force)
+  "Rename the entity denoted by the identifier at point, using
+the `gorename' tool. With FORCE, call `gorename' with the
+`-force' flag."
+  (interactive (list (read-string "New name: " (thing-at-point 'symbol))
+                     current-prefix-arg))
+  (if (not buffer-file-name)
+      (error "Cannot use go-rename on a buffer without a file name"))
+  ;; It's not sufficient to save the current buffer if modified,
+  ;; since if gofmt-before-save is on the before-save-hook,
+  ;; saving will disturb the selected region.
+  (if (buffer-modified-p)
+      (error "Please save the current buffer before invoking go-rename"))
+  ;; Prompt-save all other modified Go buffers, since they might get written.
+  (save-some-buffers nil #'(lambda ()
+              (and (buffer-file-name)
+                   (string= (file-name-extension (buffer-file-name)) ".go"))))
+  (let* ((posflag (format "-offset=%s:#%d"
+                          buffer-file-name
+                          (1- (go--position-bytes (point)))))
+         (env-vars (go-root-and-paths))
+         (goroot-env (concat "GOROOT=" (car env-vars)))
+         (gopath-env (concat "GOPATH=" (mapconcat #'identity (cdr env-vars) ":")))
+         success)
+    (with-current-buffer (get-buffer-create "*go-rename*")
+      (setq buffer-read-only nil)
+      (erase-buffer)
+      (let ((args (append (list go-rename-command nil t nil posflag "-to" new-name) (if force '("-force")))))
+        ;; Log the command to *Messages*, for debugging.
+        (message "Command: %s:" args)
+        (message "Running gorename...")
+        ;; Use dynamic binding to modify/restore the environment
+        (setq success (zerop (let ((process-environment (list* goroot-env gopath-env process-environment)))
+          (apply #'call-process args))))
+      (insert "\n")
+      (compilation-mode)
+      (setq compilation-error-screen-columns nil)
+
+      ;; On success, print the one-line result in the message bar,
+      ;; and hide the *go-rename* buffer.
+      (if success
+          (progn
+            (message "%s" (go--buffer-string-no-trailing-space))
+            (gofmt--kill-error-buffer (current-buffer)))
+        ;; failure
+        (let ((w (display-buffer (current-buffer))))
+          (message "gorename exited")
+          (shrink-window-if-larger-than-buffer w)
+          (set-window-point w (point-min)))))))
+
+  ;; Reload the modified files, saving line/col.
+  ;; (Don't restore the point since the text has changed.)
+  ;;
+  ;; TODO(adonovan): should we also do this for all other files
+  ;; that were updated (the tool can print them)?
+  (let ((line (line-number-at-pos))
+        (col (current-column)))
+    (revert-buffer t t t) ; safe, because we just saved it
+    (goto-char (point-min))
+    (forward-line (1- line))
+    (forward-char col)))
+
+
+(defun go--buffer-string-no-trailing-space ()
+  (replace-regexp-in-string "[\t\n ]*\\'"
+                            ""
+                            (buffer-substring (point-min) (point-max))))
+
+(provide 'go-rename)
diff --git a/refactor/rename/rename.go b/refactor/rename/rename.go
new file mode 100644
index 0000000..a028c21
--- /dev/null
+++ b/refactor/rename/rename.go
@@ -0,0 +1,475 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package rename contains the implementation of the 'gorename' command
+// whose main function is in golang.org/x/tools/cmd/gorename.
+// See the Usage constant for the command documentation.
+package rename // import "golang.org/x/tools/refactor/rename"
+
+import (
+	"bytes"
+	"errors"
+	"fmt"
+	"go/ast"
+	"go/build"
+	"go/format"
+	"go/parser"
+	"go/token"
+	"io/ioutil"
+	"os"
+	"path"
+	"sort"
+	"strconv"
+	"strings"
+
+	"golang.org/x/tools/go/loader"
+	"golang.org/x/tools/go/types"
+	"golang.org/x/tools/go/types/typeutil"
+	"golang.org/x/tools/refactor/importgraph"
+	"golang.org/x/tools/refactor/satisfy"
+)
+
+const Usage = `gorename: precise type-safe renaming of identifiers in Go source code.
+
+Usage:
+
+ gorename (-from <spec> | -offset <file>:#<byte-offset>) -to <name> [-force]
+
+You must specify the object (named entity) to rename using the -offset
+or -from flag.  Exactly one must be specified.
+
+Flags:
+
+-offset    specifies the filename and byte offset of an identifier to rename.
+           This form is intended for use by text editors.
+
+-from      specifies the object to rename using a query notation;
+           This form is intended for interactive use at the command line.
+           A legal -from query has one of the following forms:
+
+  "encoding/json".Decoder.Decode        method of package-level named type
+  (*"encoding/json".Decoder).Decode     ditto, alternative syntax
+  "encoding/json".Decoder.buf           field of package-level named struct type
+  "encoding/json".HTMLEscape            package member (const, func, var, type)
+  "encoding/json".Decoder.Decode::x     local object x within a method
+  "encoding/json".HTMLEscape::x         local object x within a function
+  "encoding/json"::x                    object x anywhere within a package
+  json.go::x                            object x within file json.go
+
+           Double-quotes must be escaped when writing a shell command.
+           Quotes may be omitted for single-segment import paths such as "fmt".
+
+           For methods, the parens and '*' on the receiver type are both
+           optional.
+
+           It is an error if one of the ::x queries matches multiple
+           objects.
+
+-to        the new name.
+
+-force     causes the renaming to proceed even if conflicts were reported.
+           The resulting program may be ill-formed, or experience a change
+           in behaviour.
+
+           WARNING: this flag may even cause the renaming tool to crash.
+           (In due course this bug will be fixed by moving certain
+           analyses into the type-checker.)
+
+-dryrun    causes the tool to report conflicts but not update any files.
+
+-v         enables verbose logging.
+
+gorename automatically computes the set of packages that might be
+affected.  For a local renaming, this is just the package specified by
+-from or -offset, but for a potentially exported name, gorename scans
+the workspace ($GOROOT and $GOPATH).
+
+gorename rejects renamings of concrete methods that would change the
+assignability relation between types and interfaces.  If the interface
+change was intentional, initiate the renaming at the interface method.
+
+gorename rejects any renaming that would create a conflict at the point
+of declaration, or a reference conflict (ambiguity or shadowing), or
+anything else that could cause the resulting program not to compile.
+
+
+Examples:
+
+% gorename -offset file.go:#123 -to foo
+
+  Rename the object whose identifier is at byte offset 123 within file file.go.
+
+% gorename -from \"bytes\".Buffer.Len' -to Size
+
+  Rename the "Len" method of the *bytes.Buffer type to "Size".
+
+---- TODO ----
+
+Correctness:
+- handle dot imports correctly
+- document limitations (reflection, 'implements' algorithm).
+- sketch a proof of exhaustiveness.
+
+Features:
+- support running on packages specified as *.go files on the command line
+- support running on programs containing errors (loader.Config.AllowErrors)
+- allow users to specify a scope other than "global" (to avoid being
+  stuck by neglected packages in $GOPATH that don't build).
+- support renaming the package clause (no object)
+- support renaming an import path (no ident or object)
+  (requires filesystem + SCM updates).
+- detect and reject edits to autogenerated files (cgo, protobufs)
+  and optionally $GOROOT packages.
+- report all conflicts, or at least all qualitatively distinct ones.
+  Sometimes we stop to avoid redundancy, but
+  it may give a disproportionate sense of safety in -force mode.
+- support renaming all instances of a pattern, e.g.
+  all receiver vars of a given type,
+  all local variables of a given type,
+  all PkgNames for a given package.
+- emit JSON output for other editors and tools.
+`
+
+var (
+	// Force enables patching of the source files even if conflicts were reported.
+	// The resulting program may be ill-formed.
+	// It may even cause gorename to crash.  TODO(adonovan): fix that.
+	Force bool
+
+	// DryRun causes the tool to report conflicts but not update any files.
+	DryRun bool
+
+	// ConflictError is returned by Main when it aborts the renaming due to conflicts.
+	// (It is distinguished because the interesting errors are the conflicts themselves.)
+	ConflictError = errors.New("renaming aborted due to conflicts")
+
+	// Verbose enables extra logging.
+	Verbose bool
+)
+
+type renamer struct {
+	iprog              *loader.Program
+	objsToUpdate       map[types.Object]bool
+	hadConflicts       bool
+	to                 string
+	satisfyConstraints map[satisfy.Constraint]bool
+	packages           map[*types.Package]*loader.PackageInfo // subset of iprog.AllPackages to inspect
+	msets              typeutil.MethodSetCache
+	changeMethods      bool
+}
+
+var reportError = func(posn token.Position, message string) {
+	fmt.Fprintf(os.Stderr, "%s: %s\n", posn, message)
+}
+
+// importName renames imports of the package with the given path in
+// the given package.  If fromName is not empty, only imports as
+// fromName will be renamed.  If the renaming would lead to a conflict,
+// the file is left unchanged.
+func importName(iprog *loader.Program, info *loader.PackageInfo, fromPath, fromName, to string) error {
+	for _, f := range info.Files {
+		var from types.Object
+		for _, imp := range f.Imports {
+			importPath, _ := strconv.Unquote(imp.Path.Value)
+			importName := path.Base(importPath)
+			if imp.Name != nil {
+				importName = imp.Name.Name
+			}
+			if importPath == fromPath && (fromName == "" || importName == fromName) {
+				from = info.Implicits[imp]
+				break
+			}
+		}
+		if from == nil {
+			continue
+		}
+		r := renamer{
+			iprog:        iprog,
+			objsToUpdate: make(map[types.Object]bool),
+			to:           to,
+			packages:     map[*types.Package]*loader.PackageInfo{info.Pkg: info},
+		}
+		r.check(from)
+		if r.hadConflicts {
+			continue // ignore errors; leave the existing name
+		}
+		if err := r.update(); err != nil {
+			return err
+		}
+	}
+	return nil
+}
+
+func Main(ctxt *build.Context, offsetFlag, fromFlag, to string) error {
+	// -- Parse the -from or -offset specifier ----------------------------
+
+	if (offsetFlag == "") == (fromFlag == "") {
+		return fmt.Errorf("exactly one of the -from and -offset flags must be specified")
+	}
+
+	if !isValidIdentifier(to) {
+		return fmt.Errorf("-to %q: not a valid identifier", to)
+	}
+
+	var spec *spec
+	var err error
+	if fromFlag != "" {
+		spec, err = parseFromFlag(ctxt, fromFlag)
+	} else {
+		spec, err = parseOffsetFlag(ctxt, offsetFlag)
+	}
+	if err != nil {
+		return err
+	}
+
+	if spec.fromName == to {
+		return fmt.Errorf("the old and new names are the same: %s", to)
+	}
+
+	// -- Load the program consisting of the initial package  -------------
+
+	iprog, err := loadProgram(ctxt, map[string]bool{spec.pkg: true})
+	if err != nil {
+		return err
+	}
+
+	fromObjects, err := findFromObjects(iprog, spec)
+	if err != nil {
+		return err
+	}
+
+	// -- Load a larger program, for global renamings ---------------------
+
+	if requiresGlobalRename(fromObjects, to) {
+		// For a local refactoring, we needn't load more
+		// packages, but if the renaming affects the package's
+		// API, we we must load all packages that depend on the
+		// package defining the object, plus their tests.
+
+		if Verbose {
+			fmt.Fprintln(os.Stderr, "Potentially global renaming; scanning workspace...")
+		}
+
+		// Scan the workspace and build the import graph.
+		_, rev, errors := importgraph.Build(ctxt)
+		if len(errors) > 0 {
+			// With a large GOPATH tree, errors are inevitable.
+			// Report them but proceed.
+			fmt.Fprintf(os.Stderr, "While scanning Go workspace:\n")
+			for path, err := range errors {
+				fmt.Fprintf(os.Stderr, "Package %q: %s.\n", path, err)
+			}
+		}
+
+		// Enumerate the set of potentially affected packages.
+		affectedPackages := make(map[string]bool)
+		for _, obj := range fromObjects {
+			// External test packages are never imported,
+			// so they will never appear in the graph.
+			for path := range rev.Search(obj.Pkg().Path()) {
+				affectedPackages[path] = true
+			}
+		}
+
+		// TODO(adonovan): allow the user to specify the scope,
+		// or -ignore patterns?  Computing the scope when we
+		// don't (yet) support inputs containing errors can make
+		// the tool rather brittle.
+
+		// Re-load the larger program.
+		iprog, err = loadProgram(ctxt, affectedPackages)
+		if err != nil {
+			return err
+		}
+
+		fromObjects, err = findFromObjects(iprog, spec)
+		if err != nil {
+			return err
+		}
+	}
+
+	// -- Do the renaming -------------------------------------------------
+
+	r := renamer{
+		iprog:        iprog,
+		objsToUpdate: make(map[types.Object]bool),
+		to:           to,
+		packages:     make(map[*types.Package]*loader.PackageInfo),
+	}
+
+	// A renaming initiated at an interface method indicates the
+	// intention to rename abstract and concrete methods as needed
+	// to preserve assignability.
+	for _, obj := range fromObjects {
+		if obj, ok := obj.(*types.Func); ok {
+			recv := obj.Type().(*types.Signature).Recv()
+			if recv != nil && isInterface(recv.Type().Underlying()) {
+				r.changeMethods = true
+				break
+			}
+		}
+	}
+
+	// Only the initially imported packages (iprog.Imported) and
+	// their external tests (iprog.Created) should be inspected or
+	// modified, as only they have type-checked functions bodies.
+	// The rest are just dependencies, needed only for package-level
+	// type information.
+	for _, info := range iprog.Imported {
+		r.packages[info.Pkg] = info
+	}
+	for _, info := range iprog.Created { // (tests)
+		r.packages[info.Pkg] = info
+	}
+
+	for _, from := range fromObjects {
+		r.check(from)
+	}
+	if r.hadConflicts && !Force {
+		return ConflictError
+	}
+	if DryRun {
+		// TODO(adonovan): print the delta?
+		return nil
+	}
+	return r.update()
+}
+
+// loadProgram loads the specified set of packages (plus their tests)
+// and all their dependencies, from source, through the specified build
+// context.  Only packages in pkgs will have their functions bodies typechecked.
+func loadProgram(ctxt *build.Context, pkgs map[string]bool) (*loader.Program, error) {
+	conf := loader.Config{
+		Build:      ctxt,
+		ParserMode: parser.ParseComments,
+
+		// TODO(adonovan): enable this.  Requires making a lot of code more robust!
+		AllowErrors: false,
+	}
+
+	// Optimization: don't type-check the bodies of functions in our
+	// dependencies, since we only need exported package members.
+	conf.TypeCheckFuncBodies = func(p string) bool {
+		return pkgs[p] || pkgs[strings.TrimSuffix(p, "_test")]
+	}
+
+	if Verbose {
+		var list []string
+		for pkg := range pkgs {
+			list = append(list, pkg)
+		}
+		sort.Strings(list)
+		for _, pkg := range list {
+			fmt.Fprintf(os.Stderr, "Loading package: %s\n", pkg)
+		}
+	}
+
+	for pkg := range pkgs {
+		conf.ImportWithTests(pkg)
+	}
+	return conf.Load()
+}
+
+// requiresGlobalRename reports whether this renaming could potentially
+// affect other packages in the Go workspace.
+func requiresGlobalRename(fromObjects []types.Object, to string) bool {
+	var tfm bool
+	for _, from := range fromObjects {
+		if from.Exported() {
+			return true
+		}
+		switch objectKind(from) {
+		case "type", "field", "method":
+			tfm = true
+		}
+	}
+	if ast.IsExported(to) && tfm {
+		// A global renaming may be necessary even if we're
+		// exporting a previous unexported name, since if it's
+		// the name of a type, field or method, this could
+		// change selections in other packages.
+		// (We include "type" in this list because a type
+		// used as an embedded struct field entails a field
+		// renaming.)
+		return true
+	}
+	return false
+}
+
+// update updates the input files.
+func (r *renamer) update() error {
+	// We use token.File, not filename, since a file may appear to
+	// belong to multiple packages and be parsed more than once.
+	// token.File captures this distinction; filename does not.
+	var nidents int
+	var filesToUpdate = make(map[*token.File]bool)
+	for _, info := range r.packages {
+		// Mutate the ASTs and note the filenames.
+		for id, obj := range info.Defs {
+			if r.objsToUpdate[obj] {
+				nidents++
+				id.Name = r.to
+				filesToUpdate[r.iprog.Fset.File(id.Pos())] = true
+			}
+		}
+		for id, obj := range info.Uses {
+			if r.objsToUpdate[obj] {
+				nidents++
+				id.Name = r.to
+				filesToUpdate[r.iprog.Fset.File(id.Pos())] = true
+			}
+		}
+	}
+
+	// TODO(adonovan): don't rewrite cgo + generated files.
+	var nerrs, npkgs int
+	for _, info := range r.packages {
+		first := true
+		for _, f := range info.Files {
+			tokenFile := r.iprog.Fset.File(f.Pos())
+			if filesToUpdate[tokenFile] {
+				if first {
+					npkgs++
+					first = false
+					if Verbose {
+						fmt.Fprintf(os.Stderr, "Updating package %s\n",
+							info.Pkg.Path())
+					}
+				}
+				if err := rewriteFile(r.iprog.Fset, f, tokenFile.Name()); err != nil {
+					fmt.Fprintf(os.Stderr, "gorename: %s\n", err)
+					nerrs++
+				}
+			}
+		}
+	}
+	fmt.Fprintf(os.Stderr, "Renamed %d occurrence%s in %d file%s in %d package%s.\n",
+		nidents, plural(nidents),
+		len(filesToUpdate), plural(len(filesToUpdate)),
+		npkgs, plural(npkgs))
+	if nerrs > 0 {
+		return fmt.Errorf("failed to rewrite %d file%s", nerrs, plural(nerrs))
+	}
+	return nil
+}
+
+func plural(n int) string {
+	if n != 1 {
+		return "s"
+	}
+	return ""
+}
+
+var rewriteFile = func(fset *token.FileSet, f *ast.File, filename string) (err error) {
+	// TODO(adonovan): print packages and filenames in a form useful
+	// to editors (so they can reload files).
+	if Verbose {
+		fmt.Fprintf(os.Stderr, "\t%s\n", filename)
+	}
+	var buf bytes.Buffer
+	if err := format.Node(&buf, fset, f); err != nil {
+		return fmt.Errorf("failed to pretty-print syntax tree: %v", err)
+	}
+	return ioutil.WriteFile(filename, buf.Bytes(), 0644)
+}
diff --git a/refactor/rename/rename_test.go b/refactor/rename/rename_test.go
new file mode 100644
index 0000000..1d282a1
--- /dev/null
+++ b/refactor/rename/rename_test.go
@@ -0,0 +1,1040 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package rename
+
+import (
+	"bytes"
+	"fmt"
+	"go/ast"
+	"go/build"
+	"go/format"
+	"go/token"
+	"path/filepath"
+	"regexp"
+	"strings"
+	"testing"
+
+	"golang.org/x/tools/go/buildutil"
+)
+
+// TODO(adonovan): test reported source positions, somehow.
+
+func TestConflicts(t *testing.T) {
+	defer func(savedDryRun bool, savedReportError func(token.Position, string)) {
+		DryRun = savedDryRun
+		reportError = savedReportError
+	}(DryRun, reportError)
+	DryRun = true
+
+	var ctxt *build.Context
+	for _, test := range []struct {
+		ctxt             *build.Context // nil => use previous
+		offset, from, to string         // values of the -offset/-from and -to flags
+		want             string         // regexp to match conflict errors, or "OK"
+	}{
+		// init() checks
+		{
+			ctxt: fakeContext(map[string][]string{
+				"fmt": {`package fmt; type Stringer interface { String() }`},
+				"main": {`
+package main
+
+import foo "fmt"
+
+var v foo.Stringer
+
+func f() { v.String(); f() }
+`,
+					`package main; var w int`},
+			}),
+			from: "main.v", to: "init",
+			want: `you cannot have a var at package level named "init"`,
+		},
+		{
+			from: "main.f", to: "init",
+			want: `renaming this func "f" to "init" would make it a package initializer.*` +
+				`but references to it exist`,
+		},
+		{
+			from: "/go/src/main/0.go::foo", to: "init",
+			want: `"init" is not a valid imported package name`,
+		},
+
+		// Export checks
+		{
+			from: "fmt.Stringer", to: "stringer",
+			want: `renaming this type "Stringer" to "stringer" would make it unexported.*` +
+				`breaking references from packages such as "main"`,
+		},
+		{
+			from: "(fmt.Stringer).String", to: "string",
+			want: `renaming this method "String" to "string" would make it unexported.*` +
+				`breaking references from packages such as "main"`,
+		},
+
+		// Lexical scope checks
+		{
+			// file/package conflict, same file
+			from: "main.v", to: "foo",
+			want: `renaming this var "v" to "foo" would conflict.*` +
+				`with this imported package name`,
+		},
+		{
+			// file/package conflict, same file
+			from: "main::foo", to: "v",
+			want: `renaming this imported package name "foo" to "v" would conflict.*` +
+				`with this package member var`,
+		},
+		{
+			// file/package conflict, different files
+			from: "main.w", to: "foo",
+			want: `renaming this var "w" to "foo" would conflict.*` +
+				`with this imported package name`,
+		},
+		{
+			// file/package conflict, different files
+			from: "main::foo", to: "w",
+			want: `renaming this imported package name "foo" to "w" would conflict.*` +
+				`with this package member var`,
+		},
+		{
+			ctxt: main(`
+package main
+
+var x, z int
+
+func f(y int) {
+	print(x)
+	print(y)
+}
+
+func g(w int) {
+	print(x)
+	x := 1
+	print(x)
+}`),
+			from: "main.x", to: "y",
+			want: `renaming this var "x" to "y".*` +
+				`would cause this reference to become shadowed.*` +
+				`by this intervening var definition`,
+		},
+		{
+			from: "main.g::x", to: "w",
+			want: `renaming this var "x" to "w".*` +
+				`conflicts with var in same block`,
+		},
+		{
+			from: "main.f::y", to: "x",
+			want: `renaming this var "y" to "x".*` +
+				`would shadow this reference.*` +
+				`to the var declared here`,
+		},
+		{
+			from: "main.g::w", to: "x",
+			want: `renaming this var "w" to "x".*` +
+				`conflicts with var in same block`,
+		},
+		{
+			from: "main.z", to: "y", want: "OK",
+		},
+
+		// Label checks
+		{
+			ctxt: main(`
+package main
+
+func f() {
+foo:
+	goto foo
+bar:
+	goto bar
+	func(x int) {
+	wiz:
+		goto wiz
+	}(0)
+}
+`),
+			from: "main.f::foo", to: "bar",
+			want: `renaming this label "foo" to "bar".*` +
+				`would conflict with this one`,
+		},
+		{
+			from: "main.f::foo", to: "wiz", want: "OK",
+		},
+		{
+			from: "main.f::wiz", to: "x", want: "OK",
+		},
+		{
+			from: "main.f::x", to: "wiz", want: "OK",
+		},
+		{
+			from: "main.f::wiz", to: "foo", want: "OK",
+		},
+
+		// Struct fields
+		{
+			ctxt: main(`
+package main
+
+type U struct { u int }
+type V struct { v int }
+
+func (V) x() {}
+
+type W (struct {
+	U
+	V
+	w int
+})
+
+func f() {
+	var w W
+	print(w.u) // NB: there is no selection of w.v
+	var _ struct { yy, zz int }
+}
+`),
+			// field/field conflict in named struct declaration
+			from: "(main.W).U", to: "w",
+			want: `renaming this field "U" to "w".*` +
+				`would conflict with this field`,
+		},
+		{
+			// rename type used as embedded field
+			// => rename field
+			// => field/field conflict
+			// This is an entailed renaming;
+			// it would be nice if we checked source positions.
+			from: "main.U", to: "w",
+			want: `renaming this field "U" to "w".*` +
+				`would conflict with this field`,
+		},
+		{
+			// field/field conflict in unnamed struct declaration
+			from: "main.f::zz", to: "yy",
+			want: `renaming this field "zz" to "yy".*` +
+				`would conflict with this field`,
+		},
+
+		// Now we test both directions of (u,v) (u,w) (v,w) (u,x) (v,x).
+		// Too bad we don't test position info...
+		{
+			// field/field ambiguity at same promotion level ('from' selection)
+			from: "(main.U).u", to: "v",
+			want: `renaming this field "u" to "v".*` +
+				`would make this reference ambiguous.*` +
+				`with this field`,
+		},
+		{
+			// field/field ambiguity at same promotion level ('to' selection)
+			from: "(main.V).v", to: "u",
+			want: `renaming this field "v" to "u".*` +
+				`would make this reference ambiguous.*` +
+				`with this field`,
+		},
+		{
+			// field/method conflict at different promotion level ('from' selection)
+			from: "(main.U).u", to: "w",
+			want: `renaming this field "u" to "w".*` +
+				`would change the referent of this selection.*` +
+				`of this field`,
+		},
+		{
+			// field/field shadowing at different promotion levels ('to' selection)
+			from: "(main.W).w", to: "u",
+			want: `renaming this field "w" to "u".*` +
+				`would shadow this selection.*` +
+				`of the field declared here`,
+		},
+		{
+			from: "(main.V).v", to: "w",
+			want: "OK", // since no selections are made ambiguous
+		},
+		{
+			from: "(main.W).w", to: "v",
+			want: "OK", // since no selections are made ambiguous
+		},
+		{
+			// field/method ambiguity at same promotion level ('from' selection)
+			from: "(main.U).u", to: "x",
+			want: `renaming this field "u" to "x".*` +
+				`would make this reference ambiguous.*` +
+				`with this method`,
+		},
+		{
+			// field/field ambiguity at same promotion level ('to' selection)
+			from: "(main.V).x", to: "u",
+			want: `renaming this method "x" to "u".*` +
+				`would make this reference ambiguous.*` +
+				`with this field`,
+		},
+		{
+			// field/method conflict at named struct declaration
+			from: "(main.V).v", to: "x",
+			want: `renaming this field "v" to "x".*` +
+				`would conflict with this method`,
+		},
+		{
+			// field/method conflict at named struct declaration
+			from: "(main.V).x", to: "v",
+			want: `renaming this method "x" to "v".*` +
+				`would conflict with this field`,
+		},
+
+		// Methods
+		{
+			ctxt: main(`
+package main
+type C int
+func (C) f()
+func (C) g()
+type D int
+func (*D) f()
+func (*D) g()
+type I interface { f(); g() }
+type J interface { I; h() }
+var _ I = new(D)
+var _ interface {f()} = C(0)
+`),
+			from: "(main.I).f", to: "g",
+			want: `renaming this interface method "f" to "g".*` +
+				`would conflict with this method`,
+		},
+		{
+			from: `("main".I).f`, to: "h", // NB: exercises quoted import paths too
+			want: `renaming this interface method "f" to "h".*` +
+				`would conflict with this method.*` +
+				`in named interface type "J"`,
+		},
+		{
+			// type J interface { h; h() } is not a conflict, amusingly.
+			from: "main.I", to: "h",
+			want: `OK`,
+		},
+		{
+			from: "(main.J).h", to: "f",
+			want: `renaming this interface method "h" to "f".*` +
+				`would conflict with this method`,
+		},
+		{
+			from: "(main.C).f", to: "e",
+			want: `renaming this method "f" to "e".*` +
+				`would make main.C no longer assignable to interface{f..}.*` +
+				`(rename interface{f..}.f if you intend to change both types)`,
+		},
+		{
+			from: "(main.D).g", to: "e",
+			want: `renaming this method "g" to "e".*` +
+				`would make \*main.D no longer assignable to interface I.*` +
+				`(rename main.I.g if you intend to change both types)`,
+		},
+		{
+			from: "(main.I).f", to: "e",
+			want: `OK`,
+		},
+		// Indirect C/I method coupling via another concrete type D.
+		{
+			ctxt: main(`
+package main
+type I interface { f() }
+type C int
+func (C) f()
+type D struct{C}
+var _ I = D{}
+`),
+			from: "(main.C).f", to: "F",
+			want: `renaming this method "f" to "F".*` +
+				`would make main.D no longer assignable to interface I.*` +
+				`(rename main.I.f if you intend to change both types)`,
+		},
+		// Renaming causes promoted method to become shadowed; C no longer satisfies I.
+		{
+			ctxt: main(`
+package main
+type I interface { f() }
+type C struct { I }
+func (C) g() int
+var _ I = C{}
+`),
+			from: "main.I.f", to: "g",
+			want: `renaming this method "f" to "g".*` +
+				`would change the g method of main.C invoked via interface main.I.*` +
+				`from \(main.I\).g.*` +
+				`to \(main.C\).g`,
+		},
+		// Renaming causes promoted method to become ambiguous; C no longer satisfies I.
+		{
+			ctxt: main(`
+package main
+type I interface{f()}
+type C int
+func (C) f()
+type D int
+func (D) g()
+type E struct{C;D}
+var _ I = E{}
+`),
+			from: "main.I.f", to: "g",
+			want: `renaming this method "f" to "g".*` +
+				`would make the g method of main.E invoked via interface main.I ambiguous.*` +
+				`with \(main.D\).g`,
+		},
+	} {
+		var conflicts []string
+		reportError = func(posn token.Position, message string) {
+			conflicts = append(conflicts, message)
+		}
+		if test.ctxt != nil {
+			ctxt = test.ctxt
+		}
+		err := Main(ctxt, test.offset, test.from, test.to)
+		var prefix string
+		if test.offset == "" {
+			prefix = fmt.Sprintf("-from %q -to %q", test.from, test.to)
+		} else {
+			prefix = fmt.Sprintf("-offset %q -to %q", test.offset, test.to)
+		}
+		if err == ConflictError {
+			got := strings.Join(conflicts, "\n")
+			if false {
+				t.Logf("%s: %s", prefix, got)
+			}
+			pattern := "(?s:" + test.want + ")" // enable multi-line matching
+			if !regexp.MustCompile(pattern).MatchString(got) {
+				t.Errorf("%s: conflict does not match pattern:\n"+
+					"Conflict:\t%s\n"+
+					"Pattern: %s",
+					prefix, got, test.want)
+			}
+		} else if err != nil {
+			t.Errorf("%s: unexpected error: %s", prefix, err)
+		} else if test.want != "OK" {
+			t.Errorf("%s: unexpected success, want conflicts matching:\n%s",
+				prefix, test.want)
+		}
+	}
+}
+
+func TestRewrites(t *testing.T) {
+	defer func(savedRewriteFile func(*token.FileSet, *ast.File, string) error) {
+		rewriteFile = savedRewriteFile
+	}(rewriteFile)
+
+	var ctxt *build.Context
+	for _, test := range []struct {
+		ctxt             *build.Context    // nil => use previous
+		offset, from, to string            // values of the -from/-offset and -to flags
+		want             map[string]string // contents of updated files
+	}{
+		// Elimination of renaming import.
+		{
+			ctxt: fakeContext(map[string][]string{
+				"foo": {`package foo; type T int`},
+				"main": {`package main
+
+import foo2 "foo"
+
+var _ foo2.T
+`},
+			}),
+			from: "main::foo2", to: "foo",
+			want: map[string]string{
+				"/go/src/main/0.go": `package main
+
+import "foo"
+
+var _ foo.T
+`,
+			},
+		},
+		// Introduction of renaming import.
+		{
+			ctxt: fakeContext(map[string][]string{
+				"foo": {`package foo; type T int`},
+				"main": {`package main
+
+import "foo"
+
+var _ foo.T
+`},
+			}),
+			offset: "/go/src/main/0.go:#36", to: "foo2", // the "foo" in foo.T
+			want: map[string]string{
+				"/go/src/main/0.go": `package main
+
+import foo2 "foo"
+
+var _ foo2.T
+`,
+			},
+		},
+		// Renaming of package-level member.
+		{
+			from: "foo.T", to: "U",
+			want: map[string]string{
+				"/go/src/main/0.go": `package main
+
+import "foo"
+
+var _ foo.U
+`,
+				"/go/src/foo/0.go": `package foo
+
+type U int
+`,
+			},
+		},
+		// Label renamings.
+		{
+			ctxt: main(`package main
+func f() {
+loop:
+	loop := 0
+	go func() {
+	loop:
+		goto loop
+	}()
+	loop++
+	goto loop
+}
+`),
+			offset: "/go/src/main/0.go:#25", to: "loop2", // def of outer label "loop"
+			want: map[string]string{
+				"/go/src/main/0.go": `package main
+
+func f() {
+loop2:
+	loop := 0
+	go func() {
+	loop:
+		goto loop
+	}()
+	loop++
+	goto loop2
+}
+`,
+			},
+		},
+		{
+			offset: "/go/src/main/0.go:#70", to: "loop2", // ref to inner label "loop"
+			want: map[string]string{
+				"/go/src/main/0.go": `package main
+
+func f() {
+loop:
+	loop := 0
+	go func() {
+	loop2:
+		goto loop2
+	}()
+	loop++
+	goto loop
+}
+`,
+			},
+		},
+		// Renaming of type used as embedded field.
+		{
+			ctxt: main(`package main
+
+type T int
+type U struct { T }
+
+var _ = U{}.T
+`),
+			from: "main.T", to: "T2",
+			want: map[string]string{
+				"/go/src/main/0.go": `package main
+
+type T2 int
+type U struct{ T2 }
+
+var _ = U{}.T2
+`,
+			},
+		},
+		// Renaming of embedded field.
+		{
+			ctxt: main(`package main
+
+type T int
+type U struct { T }
+
+var _ = U{}.T
+`),
+			offset: "/go/src/main/0.go:#58", to: "T2", // T in "U{}.T"
+			want: map[string]string{
+				"/go/src/main/0.go": `package main
+
+type T2 int
+type U struct{ T2 }
+
+var _ = U{}.T2
+`,
+			},
+		},
+		// Renaming of pointer embedded field.
+		{
+			ctxt: main(`package main
+
+type T int
+type U struct { *T }
+
+var _ = U{}.T
+`),
+			offset: "/go/src/main/0.go:#59", to: "T2", // T in "U{}.T"
+			want: map[string]string{
+				"/go/src/main/0.go": `package main
+
+type T2 int
+type U struct{ *T2 }
+
+var _ = U{}.T2
+`,
+			},
+		},
+
+		// Lexical scope tests.
+		{
+			ctxt: main(`package main
+
+var y int
+
+func f() {
+	print(y)
+	y := ""
+	print(y)
+}
+`),
+			from: "main.y", to: "x",
+			want: map[string]string{
+				"/go/src/main/0.go": `package main
+
+var x int
+
+func f() {
+	print(x)
+	y := ""
+	print(y)
+}
+`,
+			},
+		},
+		{
+			from: "main.f::y", to: "x",
+			want: map[string]string{
+				"/go/src/main/0.go": `package main
+
+var y int
+
+func f() {
+	print(y)
+	x := ""
+	print(x)
+}
+`,
+			},
+		},
+		// Renaming of typeswitch vars (a corner case).
+		{
+			ctxt: main(`package main
+
+func f(z interface{}) {
+	switch y := z.(type) {
+	case int:
+		print(y)
+	default:
+		print(y)
+	}
+}
+`),
+			offset: "/go/src/main/0.go:#46", to: "x", // def of y
+			want: map[string]string{
+				"/go/src/main/0.go": `package main
+
+func f(z interface{}) {
+	switch x := z.(type) {
+	case int:
+		print(x)
+	default:
+		print(x)
+	}
+}
+`},
+		},
+		{
+			offset: "/go/src/main/0.go:#81", to: "x", // ref of y in case int
+			want: map[string]string{
+				"/go/src/main/0.go": `package main
+
+func f(z interface{}) {
+	switch x := z.(type) {
+	case int:
+		print(x)
+	default:
+		print(x)
+	}
+}
+`},
+		},
+		{
+			offset: "/go/src/main/0.go:#102", to: "x", // ref of y in default case
+			want: map[string]string{
+				"/go/src/main/0.go": `package main
+
+func f(z interface{}) {
+	switch x := z.(type) {
+	case int:
+		print(x)
+	default:
+		print(x)
+	}
+}
+`},
+		},
+
+		// Renaming of embedded field that is a qualified reference.
+		// (Regression test for bug 8924.)
+		{
+			ctxt: fakeContext(map[string][]string{
+				"foo": {`package foo; type T int`},
+				"main": {`package main
+
+import "foo"
+
+type _ struct{ *foo.T }
+`},
+			}),
+			offset: "/go/src/main/0.go:#48", to: "U", // the "T" in *foo.T
+			want: map[string]string{
+				"/go/src/foo/0.go": `package foo
+
+type U int
+`,
+				"/go/src/main/0.go": `package main
+
+import "foo"
+
+type _ struct{ *foo.U }
+`,
+			},
+		},
+
+		// Interface method renaming.
+		{
+			ctxt: fakeContext(map[string][]string{
+				"main": {`
+package main
+type I interface { f() }
+type J interface { f(); g() }
+type A int
+func (A) f()
+type B int
+func (B) f()
+func (B) g()
+type C int
+func (C) f()
+func (C) g()
+var _, _ I = A(0), B(0)
+var _, _ J = B(0), C(0)
+`,
+				},
+			}),
+			offset: "/go/src/main/0.go:#33", to: "F", // abstract method I.f
+			want: map[string]string{
+				"/go/src/main/0.go": `package main
+
+type I interface {
+	F()
+}
+type J interface {
+	F()
+	g()
+}
+type A int
+
+func (A) F()
+
+type B int
+
+func (B) F()
+func (B) g()
+
+type C int
+
+func (C) F()
+func (C) g()
+
+var _, _ I = A(0), B(0)
+var _, _ J = B(0), C(0)
+`,
+			},
+		},
+		{
+			offset: "/go/src/main/0.go:#58", to: "F", // abstract method J.f
+			want: map[string]string{
+				"/go/src/main/0.go": `package main
+
+type I interface {
+	F()
+}
+type J interface {
+	F()
+	g()
+}
+type A int
+
+func (A) F()
+
+type B int
+
+func (B) F()
+func (B) g()
+
+type C int
+
+func (C) F()
+func (C) g()
+
+var _, _ I = A(0), B(0)
+var _, _ J = B(0), C(0)
+`,
+			},
+		},
+		{
+			offset: "/go/src/main/0.go:#63", to: "G", // abstract method J.g
+			want: map[string]string{
+				"/go/src/main/0.go": `package main
+
+type I interface {
+	f()
+}
+type J interface {
+	f()
+	G()
+}
+type A int
+
+func (A) f()
+
+type B int
+
+func (B) f()
+func (B) G()
+
+type C int
+
+func (C) f()
+func (C) G()
+
+var _, _ I = A(0), B(0)
+var _, _ J = B(0), C(0)
+`,
+			},
+		},
+		// Indirect coupling of I.f to C.f from D->I assignment and anonymous field of D.
+		{
+			ctxt: fakeContext(map[string][]string{
+				"main": {`
+package main
+type I interface { f() }
+type C int
+func (C) f()
+type D struct{C}
+var _ I = D{}
+`,
+				},
+			}),
+			offset: "/go/src/main/0.go:#33", to: "F", // abstract method I.f
+			want: map[string]string{
+				"/go/src/main/0.go": `package main
+
+type I interface {
+	F()
+}
+type C int
+
+func (C) F()
+
+type D struct{ C }
+
+var _ I = D{}
+`,
+			},
+		},
+		// Interface embedded in struct.  No conflict if C need not satisfy I.
+		{
+			ctxt: fakeContext(map[string][]string{
+				"main": {`
+package main
+type I interface {f()}
+type C struct{I}
+func (C) g() int
+var _ int = C{}.g()
+`,
+				},
+			}),
+			offset: "/go/src/main/0.go:#32", to: "g", // abstract method I.f
+			want: map[string]string{
+				"/go/src/main/0.go": `package main
+
+type I interface {
+	g()
+}
+type C struct{ I }
+
+func (C) g() int
+
+var _ int = C{}.g()
+`,
+			},
+		},
+		// A type assertion causes method coupling iff signatures match.
+		{
+			ctxt: fakeContext(map[string][]string{
+				"main": {`package main
+type I interface{f()}
+type J interface{f()}
+var _ = I(nil).(J)
+`,
+				},
+			}),
+			offset: "/go/src/main/0.go:#30", to: "g", // abstract method I.f
+			want: map[string]string{
+				"/go/src/main/0.go": `package main
+
+type I interface {
+	g()
+}
+type J interface {
+	g()
+}
+
+var _ = I(nil).(J)
+`,
+			},
+		},
+		// Impossible type assertion: no method coupling.
+		{
+			ctxt: fakeContext(map[string][]string{
+				"main": {`package main
+type I interface{f()}
+type J interface{f()int}
+var _ = I(nil).(J)
+`,
+				},
+			}),
+			offset: "/go/src/main/0.go:#30", to: "g", // abstract method I.f
+			want: map[string]string{
+				"/go/src/main/0.go": `package main
+
+type I interface {
+	g()
+}
+type J interface {
+	f() int
+}
+
+var _ = I(nil).(J)
+`,
+			},
+		},
+		// Impossible type assertion: no method coupling C.f<->J.f.
+		{
+			ctxt: fakeContext(map[string][]string{
+				"main": {`package main
+type I interface{f()}
+type C int
+func (C) f()
+type J interface{f()int}
+var _ = I(C(0)).(J)
+`,
+				},
+			}),
+			offset: "/go/src/main/0.go:#30", to: "g", // abstract method I.f
+			want: map[string]string{
+				"/go/src/main/0.go": `package main
+
+type I interface {
+	g()
+}
+type C int
+
+func (C) g()
+
+type J interface {
+	f() int
+}
+
+var _ = I(C(0)).(J)
+`,
+			},
+		},
+	} {
+		if test.ctxt != nil {
+			ctxt = test.ctxt
+		}
+
+		got := make(map[string]string)
+		rewriteFile = func(fset *token.FileSet, f *ast.File, orig string) error {
+			var out bytes.Buffer
+			if err := format.Node(&out, fset, f); err != nil {
+				return err
+			}
+			got[filepath.ToSlash(orig)] = out.String()
+			return nil
+		}
+
+		err := Main(ctxt, test.offset, test.from, test.to)
+		var prefix string
+		if test.offset == "" {
+			prefix = fmt.Sprintf("-from %q -to %q", test.from, test.to)
+		} else {
+			prefix = fmt.Sprintf("-offset %q -to %q", test.offset, test.to)
+		}
+		if err != nil {
+			t.Errorf("%s: unexpected error: %s", prefix, err)
+			continue
+		}
+
+		for file, wantContent := range test.want {
+			gotContent, ok := got[file]
+			delete(got, file)
+			if !ok {
+				t.Errorf("%s: file %s not rewritten", prefix, file)
+				continue
+			}
+			if gotContent != wantContent {
+				t.Errorf("%s: rewritten file %s does not match expectation; got <<<%s>>>\n"+
+					"want <<<%s>>>", prefix, file, gotContent, wantContent)
+			}
+		}
+		// got should now be empty
+		for file := range got {
+			t.Errorf("%s: unexpected rewrite of file %s", prefix, file)
+		}
+	}
+}
+
+// ---------------------------------------------------------------------
+
+// Simplifying wrapper around buildutil.FakeContext for packages whose
+// filenames are sequentially numbered (%d.go).  pkgs maps a package
+// import path to its list of file contents.
+func fakeContext(pkgs map[string][]string) *build.Context {
+	pkgs2 := make(map[string]map[string]string)
+	for path, files := range pkgs {
+		filemap := make(map[string]string)
+		for i, contents := range files {
+			filemap[fmt.Sprintf("%d.go", i)] = contents
+		}
+		pkgs2[path] = filemap
+	}
+	return buildutil.FakeContext(pkgs2)
+}
+
+// helper for single-file main packages with no imports.
+func main(content string) *build.Context {
+	return fakeContext(map[string][]string{"main": {content}})
+}
diff --git a/refactor/rename/spec.go b/refactor/rename/spec.go
new file mode 100644
index 0000000..3c73653
--- /dev/null
+++ b/refactor/rename/spec.go
@@ -0,0 +1,549 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package rename
+
+// This file contains logic related to specifying a renaming: parsing of
+// the flags as a form of query, and finding the object(s) it denotes.
+// See Usage for flag details.
+
+import (
+	"bytes"
+	"fmt"
+	"go/ast"
+	"go/build"
+	"go/parser"
+	"go/token"
+	"os"
+	"path/filepath"
+	"strconv"
+	"strings"
+
+	"golang.org/x/tools/go/buildutil"
+	"golang.org/x/tools/go/loader"
+	"golang.org/x/tools/go/types"
+)
+
+// A spec specifies an entity to rename.
+//
+// It is populated from an -offset flag or -from query;
+// see Usage for the allowed -from query forms.
+//
+type spec struct {
+	// pkg is the package containing the position
+	// specified by the -from or -offset flag.
+	// If filename == "", our search for the 'from' entity
+	// is restricted to this package.
+	pkg string
+
+	// The original name of the entity being renamed.
+	// If the query had a ::from component, this is that;
+	// otherwise it's the last segment, e.g.
+	//   (encoding/json.Decoder).from
+	//   encoding/json.from
+	fromName string
+
+	// -- The remaining fields are private to this file.  All are optional. --
+
+	// The query's ::x suffix, if any.
+	searchFor string
+
+	// e.g. "Decoder" in "(encoding/json.Decoder).fieldOrMethod"
+	//                or "encoding/json.Decoder
+	pkgMember string
+
+	// e.g. fieldOrMethod in "(encoding/json.Decoder).fieldOrMethod"
+	typeMember string
+
+	// Restricts the query to this file.
+	// Implied by -from="file.go::x" and -offset flags.
+	filename string
+
+	// Byte offset of the 'from' identifier within the file named 'filename'.
+	// -offset mode only.
+	offset int
+}
+
+// parseFromFlag interprets the "-from" flag value as a renaming specification.
+// See Usage in rename.go for valid formats.
+func parseFromFlag(ctxt *build.Context, fromFlag string) (*spec, error) {
+	var spec spec
+	var main string // sans "::x" suffix
+	switch parts := strings.Split(fromFlag, "::"); len(parts) {
+	case 1:
+		main = parts[0]
+	case 2:
+		main = parts[0]
+		spec.searchFor = parts[1]
+		if parts[1] == "" {
+			// error
+		}
+	default:
+		return nil, fmt.Errorf("-from %q: invalid identifier specification (see -help for formats)", fromFlag)
+	}
+
+	if strings.HasSuffix(main, ".go") {
+		// main is "filename.go"
+		if spec.searchFor == "" {
+			return nil, fmt.Errorf("-from: filename %q must have a ::name suffix", main)
+		}
+		spec.filename = main
+		if !buildutil.FileExists(ctxt, spec.filename) {
+			return nil, fmt.Errorf("no such file: %s", spec.filename)
+		}
+
+		bp, err := buildutil.ContainingPackage(ctxt, wd, spec.filename)
+		if err != nil {
+			return nil, err
+		}
+		spec.pkg = bp.ImportPath
+
+	} else {
+		// main is one of:
+		//  "importpath"
+		//  "importpath".member
+		//  (*"importpath".type).fieldormethod           (parens and star optional)
+		if err := parseObjectSpec(&spec, main); err != nil {
+			return nil, err
+		}
+	}
+
+	if spec.searchFor != "" {
+		spec.fromName = spec.searchFor
+	}
+
+	// Sanitize the package.
+	// TODO(adonovan): test with relative packages.  May need loader changes.
+	bp, err := ctxt.Import(spec.pkg, ".", build.FindOnly)
+	if err != nil {
+		return nil, fmt.Errorf("can't find package %q", spec.pkg)
+	}
+	spec.pkg = bp.ImportPath
+
+	if !isValidIdentifier(spec.fromName) {
+		return nil, fmt.Errorf("-from: invalid identifier %q", spec.fromName)
+	}
+
+	if Verbose {
+		fmt.Fprintf(os.Stderr, "-from spec: %+v\n", spec)
+	}
+
+	return &spec, nil
+}
+
+// parseObjectSpec parses main as one of the non-filename forms of
+// object specification.
+func parseObjectSpec(spec *spec, main string) error {
+	// Parse main as a Go expression, albeit a strange one.
+	e, _ := parser.ParseExpr(main)
+
+	if pkg := parseImportPath(e); pkg != "" {
+		// e.g. bytes or "encoding/json": a package
+		spec.pkg = pkg
+		if spec.searchFor == "" {
+			return fmt.Errorf("-from %q: package import path %q must have a ::name suffix",
+				main, main)
+		}
+		return nil
+	}
+
+	if e, ok := e.(*ast.SelectorExpr); ok {
+		x := unparen(e.X)
+
+		// Strip off star constructor, if any.
+		if star, ok := x.(*ast.StarExpr); ok {
+			x = star.X
+		}
+
+		if pkg := parseImportPath(x); pkg != "" {
+			// package member e.g. "encoding/json".HTMLEscape
+			spec.pkg = pkg              // e.g. "encoding/json"
+			spec.pkgMember = e.Sel.Name // e.g. "HTMLEscape"
+			spec.fromName = e.Sel.Name
+			return nil
+		}
+
+		if x, ok := x.(*ast.SelectorExpr); ok {
+			// field/method of type e.g. ("encoding/json".Decoder).Decode
+			y := unparen(x.X)
+			if pkg := parseImportPath(y); pkg != "" {
+				spec.pkg = pkg               // e.g. "encoding/json"
+				spec.pkgMember = x.Sel.Name  // e.g. "Decoder"
+				spec.typeMember = e.Sel.Name // e.g. "Decode"
+				spec.fromName = e.Sel.Name
+				return nil
+			}
+		}
+	}
+
+	return fmt.Errorf("-from %q: invalid expression", main)
+}
+
+// parseImportPath returns the import path of the package denoted by e.
+// Any import path may be represented as a string literal;
+// single-segment import paths (e.g. "bytes") may also be represented as
+// ast.Ident.  parseImportPath returns "" for all other expressions.
+func parseImportPath(e ast.Expr) string {
+	switch e := e.(type) {
+	case *ast.Ident:
+		return e.Name // e.g. bytes
+
+	case *ast.BasicLit:
+		if e.Kind == token.STRING {
+			pkgname, _ := strconv.Unquote(e.Value)
+			return pkgname // e.g. "encoding/json"
+		}
+	}
+	return ""
+}
+
+// parseOffsetFlag interprets the "-offset" flag value as a renaming specification.
+func parseOffsetFlag(ctxt *build.Context, offsetFlag string) (*spec, error) {
+	var spec spec
+	// Validate -offset, e.g. file.go:#123
+	parts := strings.Split(offsetFlag, ":#")
+	if len(parts) != 2 {
+		return nil, fmt.Errorf("-offset %q: invalid offset specification", offsetFlag)
+	}
+
+	spec.filename = parts[0]
+	if !buildutil.FileExists(ctxt, spec.filename) {
+		return nil, fmt.Errorf("no such file: %s", spec.filename)
+	}
+
+	bp, err := buildutil.ContainingPackage(ctxt, wd, spec.filename)
+	if err != nil {
+		return nil, err
+	}
+	spec.pkg = bp.ImportPath
+
+	for _, r := range parts[1] {
+		if !isDigit(r) {
+			return nil, fmt.Errorf("-offset %q: non-numeric offset", offsetFlag)
+		}
+	}
+	spec.offset, err = strconv.Atoi(parts[1])
+	if err != nil {
+		return nil, fmt.Errorf("-offset %q: non-numeric offset", offsetFlag)
+	}
+
+	// Parse the file and check there's an identifier at that offset.
+	fset := token.NewFileSet()
+	f, err := buildutil.ParseFile(fset, ctxt, nil, wd, spec.filename, parser.ParseComments)
+	if err != nil {
+		return nil, fmt.Errorf("-offset %q: cannot parse file: %s", offsetFlag, err)
+	}
+
+	id := identAtOffset(fset, f, spec.offset)
+	if id == nil {
+		return nil, fmt.Errorf("-offset %q: no identifier at this position", offsetFlag)
+	}
+
+	spec.fromName = id.Name
+
+	return &spec, nil
+}
+
+var wd = func() string {
+	wd, err := os.Getwd()
+	if err != nil {
+		panic("cannot get working directory: " + err.Error())
+	}
+	return wd
+}()
+
+// For source trees built with 'go build', the -from or -offset
+// spec identifies exactly one initial 'from' object to rename ,
+// but certain proprietary build systems allow a single file to
+// appear in multiple packages (e.g. the test package contains a
+// copy of its library), so there may be multiple objects for
+// the same source entity.
+
+func findFromObjects(iprog *loader.Program, spec *spec) ([]types.Object, error) {
+	if spec.filename != "" {
+		return findFromObjectsInFile(iprog, spec)
+	}
+
+	// Search for objects defined in specified package.
+
+	// TODO(adonovan): the iprog.ImportMap has an entry {"main": ...}
+	// for main packages, even though that's not an import path.
+	// Seems like a bug.
+	//
+	// pkgObj := iprog.ImportMap[spec.pkg]
+	// if pkgObj == nil {
+	// 	return fmt.Errorf("cannot find package %s", spec.pkg) // can't happen?
+	// }
+
+	// Workaround: lookup by value.
+	var pkgObj *types.Package
+	for pkg := range iprog.AllPackages {
+		if pkg.Path() == spec.pkg {
+			pkgObj = pkg
+			break
+		}
+	}
+	info := iprog.AllPackages[pkgObj]
+
+	objects, err := findObjects(info, spec)
+	if err != nil {
+		return nil, err
+	}
+	if len(objects) > 1 {
+		// ambiguous "*" scope query
+		return nil, ambiguityError(iprog.Fset, objects)
+	}
+	return objects, nil
+}
+
+func findFromObjectsInFile(iprog *loader.Program, spec *spec) ([]types.Object, error) {
+	var fromObjects []types.Object
+	for _, info := range iprog.AllPackages {
+		// restrict to specified filename
+		// NB: under certain proprietary build systems, a given
+		// filename may appear in multiple packages.
+		for _, f := range info.Files {
+			thisFile := iprog.Fset.File(f.Pos())
+			if !sameFile(thisFile.Name(), spec.filename) {
+				continue
+			}
+			// This package contains the query file.
+
+			if spec.offset != 0 {
+				// Search for a specific ident by file/offset.
+				id := identAtOffset(iprog.Fset, f, spec.offset)
+				if id == nil {
+					// can't happen?
+					return nil, fmt.Errorf("identifier not found")
+				}
+				obj := info.Uses[id]
+				if obj == nil {
+					obj = info.Defs[id]
+					if obj == nil {
+						// Ident without Object.
+
+						// Package clause?
+						pos := thisFile.Pos(spec.offset)
+						_, path, _ := iprog.PathEnclosingInterval(pos, pos)
+						if len(path) == 2 { // [Ident File]
+							// TODO(adonovan): support this case.
+							return nil, fmt.Errorf("cannot rename %q: renaming package clauses is not yet supported",
+								path[1].(*ast.File).Name.Name)
+						}
+
+						// Implicit y in "switch y := x.(type) {"?
+						if obj := typeSwitchVar(&info.Info, path); obj != nil {
+							return []types.Object{obj}, nil
+						}
+
+						// Probably a type error.
+						return nil, fmt.Errorf("cannot find object for %q", id.Name)
+					}
+				}
+				if obj.Pkg() == nil {
+					return nil, fmt.Errorf("cannot rename predeclared identifiers (%s)", obj)
+
+				}
+
+				fromObjects = append(fromObjects, obj)
+			} else {
+				// do a package-wide query
+				objects, err := findObjects(info, spec)
+				if err != nil {
+					return nil, err
+				}
+
+				// filter results: only objects defined in thisFile
+				var filtered []types.Object
+				for _, obj := range objects {
+					if iprog.Fset.File(obj.Pos()) == thisFile {
+						filtered = append(filtered, obj)
+					}
+				}
+				if len(filtered) == 0 {
+					return nil, fmt.Errorf("no object %q declared in file %s",
+						spec.fromName, spec.filename)
+				} else if len(filtered) > 1 {
+					return nil, ambiguityError(iprog.Fset, filtered)
+				}
+				fromObjects = append(fromObjects, filtered[0])
+			}
+			break
+		}
+	}
+	if len(fromObjects) == 0 {
+		// can't happen?
+		return nil, fmt.Errorf("file %s was not part of the loaded program", spec.filename)
+	}
+	return fromObjects, nil
+}
+
+func typeSwitchVar(info *types.Info, path []ast.Node) types.Object {
+	if len(path) > 3 {
+		// [Ident AssignStmt TypeSwitchStmt...]
+		if sw, ok := path[2].(*ast.TypeSwitchStmt); ok {
+			// choose the first case.
+			if len(sw.Body.List) > 0 {
+				obj := info.Implicits[sw.Body.List[0].(*ast.CaseClause)]
+				if obj != nil {
+					return obj
+				}
+			}
+		}
+	}
+	return nil
+}
+
+// On success, findObjects returns the list of objects named
+// spec.fromName matching the spec.  On success, the result has exactly
+// one element unless spec.searchFor!="", in which case it has at least one
+// element.
+//
+func findObjects(info *loader.PackageInfo, spec *spec) ([]types.Object, error) {
+	if spec.pkgMember == "" {
+		if spec.searchFor == "" {
+			panic(spec)
+		}
+		objects := searchDefs(&info.Info, spec.searchFor)
+		if objects == nil {
+			return nil, fmt.Errorf("no object %q declared in package %q",
+				spec.searchFor, info.Pkg.Path())
+		}
+		return objects, nil
+	}
+
+	pkgMember := info.Pkg.Scope().Lookup(spec.pkgMember)
+	if pkgMember == nil {
+		return nil, fmt.Errorf("package %q has no member %q",
+			info.Pkg.Path(), spec.pkgMember)
+	}
+
+	var searchFunc *types.Func
+	if spec.typeMember == "" {
+		// package member
+		if spec.searchFor == "" {
+			return []types.Object{pkgMember}, nil
+		}
+
+		// Search within pkgMember, which must be a function.
+		searchFunc, _ = pkgMember.(*types.Func)
+		if searchFunc == nil {
+			return nil, fmt.Errorf("cannot search for %q within %s %q",
+				spec.searchFor, objectKind(pkgMember), pkgMember)
+		}
+	} else {
+		// field/method of type
+		// e.g. (encoding/json.Decoder).Decode
+		// or ::x within it.
+
+		tName, _ := pkgMember.(*types.TypeName)
+		if tName == nil {
+			return nil, fmt.Errorf("%s.%s is a %s, not a type",
+				info.Pkg.Path(), pkgMember.Name(), objectKind(pkgMember))
+		}
+
+		// search within named type.
+		obj, _, _ := types.LookupFieldOrMethod(tName.Type(), true, info.Pkg, spec.typeMember)
+		if obj == nil {
+			return nil, fmt.Errorf("cannot find field or method %q of %s %s.%s",
+				spec.typeMember, typeKind(tName.Type()), info.Pkg.Path(), tName.Name())
+		}
+
+		if spec.searchFor == "" {
+			return []types.Object{obj}, nil
+		}
+
+		searchFunc, _ = obj.(*types.Func)
+		if searchFunc == nil {
+			return nil, fmt.Errorf("cannot search for local name %q within %s (%s.%s).%s; need a function",
+				spec.searchFor, objectKind(obj), info.Pkg.Path(), tName.Name(),
+				obj.Name())
+		}
+		if isInterface(tName.Type()) {
+			return nil, fmt.Errorf("cannot search for local name %q within abstract method (%s.%s).%s",
+				spec.searchFor, info.Pkg.Path(), tName.Name(), searchFunc.Name())
+		}
+	}
+
+	// -- search within function or method --
+
+	decl := funcDecl(info, searchFunc)
+	if decl == nil {
+		return nil, fmt.Errorf("cannot find syntax for %s", searchFunc) // can't happen?
+	}
+
+	var objects []types.Object
+	for _, obj := range searchDefs(&info.Info, spec.searchFor) {
+		// We use positions, not scopes, to determine whether
+		// the obj is within searchFunc.  This is clumsy, but the
+		// alternative, using the types.Scope tree, doesn't
+		// account for non-lexical objects like fields and
+		// interface methods.
+		if decl.Pos() <= obj.Pos() && obj.Pos() < decl.End() && obj != searchFunc {
+			objects = append(objects, obj)
+		}
+	}
+	if objects == nil {
+		return nil, fmt.Errorf("no local definition of %q within %s",
+			spec.searchFor, searchFunc)
+	}
+	return objects, nil
+}
+
+func funcDecl(info *loader.PackageInfo, fn *types.Func) *ast.FuncDecl {
+	for _, f := range info.Files {
+		for _, d := range f.Decls {
+			if d, ok := d.(*ast.FuncDecl); ok && info.Defs[d.Name] == fn {
+				return d
+			}
+		}
+	}
+	return nil
+}
+
+func searchDefs(info *types.Info, name string) []types.Object {
+	var objects []types.Object
+	for id, obj := range info.Defs {
+		if obj == nil {
+			// e.g. blank ident.
+			// TODO(adonovan): but also implicit y in
+			//    switch y := x.(type)
+			// Needs some thought.
+			continue
+		}
+		if id.Name == name {
+			objects = append(objects, obj)
+		}
+	}
+	return objects
+}
+
+func identAtOffset(fset *token.FileSet, f *ast.File, offset int) *ast.Ident {
+	var found *ast.Ident
+	ast.Inspect(f, func(n ast.Node) bool {
+		if id, ok := n.(*ast.Ident); ok {
+			idpos := fset.Position(id.Pos()).Offset
+			if idpos <= offset && offset < idpos+len(id.Name) {
+				found = id
+			}
+		}
+		return found == nil // keep traversing only until found
+	})
+	return found
+}
+
+// ambiguityError returns an error describing an ambiguous "*" scope query.
+func ambiguityError(fset *token.FileSet, objects []types.Object) error {
+	var buf bytes.Buffer
+	for i, obj := range objects {
+		if i > 0 {
+			buf.WriteString(", ")
+		}
+		posn := fset.Position(obj.Pos())
+		fmt.Fprintf(&buf, "%s at %s:%d",
+			objectKind(obj), filepath.Base(posn.Filename), posn.Column)
+	}
+	return fmt.Errorf("ambiguous specifier %s matches %s",
+		objects[0].Name(), buf.String())
+}
diff --git a/refactor/rename/util.go b/refactor/rename/util.go
new file mode 100644
index 0000000..def9399
--- /dev/null
+++ b/refactor/rename/util.go
@@ -0,0 +1,104 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package rename
+
+import (
+	"go/ast"
+	"os"
+	"path/filepath"
+	"reflect"
+	"runtime"
+	"strings"
+	"unicode"
+
+	"golang.org/x/tools/go/ast/astutil"
+	"golang.org/x/tools/go/types"
+)
+
+func objectKind(obj types.Object) string {
+	switch obj := obj.(type) {
+	case *types.PkgName:
+		return "imported package name"
+	case *types.TypeName:
+		return "type"
+	case *types.Var:
+		if obj.IsField() {
+			return "field"
+		}
+	case *types.Func:
+		if obj.Type().(*types.Signature).Recv() != nil {
+			return "method"
+		}
+	}
+	// label, func, var, const
+	return strings.ToLower(strings.TrimPrefix(reflect.TypeOf(obj).String(), "*types."))
+}
+
+func typeKind(T types.Type) string {
+	return strings.ToLower(strings.TrimPrefix(reflect.TypeOf(T.Underlying()).String(), "*types."))
+}
+
+// NB: for renamings, blank is not considered valid.
+func isValidIdentifier(id string) bool {
+	if id == "" || id == "_" {
+		return false
+	}
+	for i, r := range id {
+		if !isLetter(r) && (i == 0 || !isDigit(r)) {
+			return false
+		}
+	}
+	return true
+}
+
+// isLocal reports whether obj is local to some function.
+// Precondition: not a struct field or interface method.
+func isLocal(obj types.Object) bool {
+	// [... 5=stmt 4=func 3=file 2=pkg 1=universe]
+	var depth int
+	for scope := obj.Parent(); scope != nil; scope = scope.Parent() {
+		depth++
+	}
+	return depth >= 4
+}
+
+func isPackageLevel(obj types.Object) bool {
+	return obj.Pkg().Scope().Lookup(obj.Name()) == obj
+}
+
+// -- Plundered from go/scanner: ---------------------------------------
+
+func isLetter(ch rune) bool {
+	return 'a' <= ch && ch <= 'z' || 'A' <= ch && ch <= 'Z' || ch == '_' || ch >= 0x80 && unicode.IsLetter(ch)
+}
+
+func isDigit(ch rune) bool {
+	return '0' <= ch && ch <= '9' || ch >= 0x80 && unicode.IsDigit(ch)
+}
+
+// -- Plundered from golang.org/x/tools/oracle -----------------
+
+// sameFile returns true if x and y have the same basename and denote
+// the same file.
+//
+func sameFile(x, y string) bool {
+	if runtime.GOOS == "windows" {
+		x = filepath.ToSlash(x)
+		y = filepath.ToSlash(y)
+	}
+	if x == y {
+		return true
+	}
+	if filepath.Base(x) == filepath.Base(y) { // (optimisation)
+		if xi, err := os.Stat(x); err == nil {
+			if yi, err := os.Stat(y); err == nil {
+				return os.SameFile(xi, yi)
+			}
+		}
+	}
+	return false
+}
+
+func unparen(e ast.Expr) ast.Expr { return astutil.Unparen(e) }
diff --git a/refactor/satisfy/find.go b/refactor/satisfy/find.go
new file mode 100644
index 0000000..acbcf62
--- /dev/null
+++ b/refactor/satisfy/find.go
@@ -0,0 +1,705 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package satisfy inspects the type-checked ASTs of Go packages and
+// reports the set of discovered type constraints of the form (lhs, rhs
+// Type) where lhs is a non-trivial interface, rhs satisfies this
+// interface, and this fact is necessary for the package to be
+// well-typed.
+//
+// THIS PACKAGE IS EXPERIMENTAL AND MAY CHANGE AT ANY TIME.
+//
+// It is provided only for the gorename tool.  Ideally this
+// functionality will become part of the type-checker in due course,
+// since it is computing it anyway, and it is robust for ill-typed
+// inputs, which this package is not.
+//
+package satisfy // import "golang.org/x/tools/refactor/satisfy"
+
+// NOTES:
+//
+// We don't care about numeric conversions, so we don't descend into
+// types or constant expressions.  This is unsound because
+// constant expressions can contain arbitrary statements, e.g.
+//   const x = len([1]func(){func() {
+//     ...
+//   }})
+//
+// TODO(adonovan): make this robust against ill-typed input.
+// Or move it into the type-checker.
+//
+// Assignability conversions are possible in the following places:
+// - in assignments y = x, y := x, var y = x.
+// - from call argument types to formal parameter types
+// - in append and delete calls
+// - from return operands to result parameter types
+// - in composite literal T{k:v}, from k and v to T's field/element/key type
+// - in map[key] from key to the map's key type
+// - in comparisons x==y and switch x { case y: }.
+// - in explicit conversions T(x)
+// - in sends ch <- x, from x to the channel element type
+// - in type assertions x.(T) and switch x.(type) { case T: }
+//
+// The results of this pass provide information equivalent to the
+// ssa.MakeInterface and ssa.ChangeInterface instructions.
+
+import (
+	"fmt"
+	"go/ast"
+	"go/token"
+
+	"golang.org/x/tools/go/ast/astutil"
+	"golang.org/x/tools/go/types"
+	"golang.org/x/tools/go/types/typeutil"
+)
+
+// A Constraint records the fact that the RHS type does and must
+// satisify the LHS type, which is an interface.
+// The names are suggestive of an assignment statement LHS = RHS.
+type Constraint struct {
+	LHS, RHS types.Type
+}
+
+// A Finder inspects the type-checked ASTs of Go packages and
+// accumulates the set of type constraints (x, y) such that x is
+// assignable to y, y is an interface, and both x and y have methods.
+//
+// In other words, it returns the subset of the "implements" relation
+// that is checked during compilation of a package.  Refactoring tools
+// will need to preserve at least this part of the relation to ensure
+// continued compilation.
+//
+type Finder struct {
+	Result    map[Constraint]bool
+	msetcache typeutil.MethodSetCache
+
+	// per-Find state
+	info *types.Info
+	sig  *types.Signature
+}
+
+// Find inspects a single package, populating Result with its pairs of
+// constrained types.
+//
+// The result is non-canonical and thus may contain duplicates (but this
+// tends to preserves names of interface types better).
+//
+// The package must be free of type errors, and
+// info.{Defs,Uses,Selections,Types} must have been populated by the
+// type-checker.
+//
+func (f *Finder) Find(info *types.Info, files []*ast.File) {
+	if f.Result == nil {
+		f.Result = make(map[Constraint]bool)
+	}
+
+	f.info = info
+	for _, file := range files {
+		for _, d := range file.Decls {
+			switch d := d.(type) {
+			case *ast.GenDecl:
+				if d.Tok == token.VAR { // ignore consts
+					for _, spec := range d.Specs {
+						f.valueSpec(spec.(*ast.ValueSpec))
+					}
+				}
+
+			case *ast.FuncDecl:
+				if d.Body != nil {
+					f.sig = f.info.Defs[d.Name].Type().(*types.Signature)
+					f.stmt(d.Body)
+					f.sig = nil
+				}
+			}
+		}
+	}
+	f.info = nil
+}
+
+var (
+	tInvalid     = types.Typ[types.Invalid]
+	tUntypedBool = types.Typ[types.UntypedBool]
+	tUntypedNil  = types.Typ[types.UntypedNil]
+)
+
+// exprN visits an expression in a multi-value context.
+func (f *Finder) exprN(e ast.Expr) types.Type {
+	typ := f.info.Types[e].Type.(*types.Tuple)
+	switch e := e.(type) {
+	case *ast.ParenExpr:
+		return f.exprN(e.X)
+
+	case *ast.CallExpr:
+		// x, err := f(args)
+		sig := f.expr(e.Fun).Underlying().(*types.Signature)
+		f.call(sig, e.Args)
+
+	case *ast.IndexExpr:
+		// y, ok := x[i]
+		x := f.expr(e.X)
+		f.assign(f.expr(e.Index), x.Underlying().(*types.Map).Key())
+
+	case *ast.TypeAssertExpr:
+		// y, ok := x.(T)
+		f.typeAssert(f.expr(e.X), typ.At(0).Type())
+
+	case *ast.UnaryExpr: // must be receive <-
+		// y, ok := <-x
+		f.expr(e.X)
+
+	default:
+		panic(e)
+	}
+	return typ
+}
+
+func (f *Finder) call(sig *types.Signature, args []ast.Expr) {
+	if len(args) == 0 {
+		return
+	}
+
+	// Ellipsis call?  e.g. f(x, y, z...)
+	if _, ok := args[len(args)-1].(*ast.Ellipsis); ok {
+		for i, arg := range args {
+			// The final arg is a slice, and so is the final param.
+			f.assign(sig.Params().At(i).Type(), f.expr(arg))
+		}
+		return
+	}
+
+	var argtypes []types.Type
+
+	// Gather the effective actual parameter types.
+	if tuple, ok := f.info.Types[args[0]].Type.(*types.Tuple); ok {
+		// f(g()) call where g has multiple results?
+		f.expr(args[0])
+		// unpack the tuple
+		for i := 0; i < tuple.Len(); i++ {
+			argtypes = append(argtypes, tuple.At(i).Type())
+		}
+	} else {
+		for _, arg := range args {
+			argtypes = append(argtypes, f.expr(arg))
+		}
+	}
+
+	// Assign the actuals to the formals.
+	if !sig.Variadic() {
+		for i, argtype := range argtypes {
+			f.assign(sig.Params().At(i).Type(), argtype)
+		}
+	} else {
+		// The first n-1 parameters are assigned normally.
+		nnormals := sig.Params().Len() - 1
+		for i, argtype := range argtypes[:nnormals] {
+			f.assign(sig.Params().At(i).Type(), argtype)
+		}
+		// Remaining args are assigned to elements of varargs slice.
+		tElem := sig.Params().At(nnormals).Type().(*types.Slice).Elem()
+		for i := nnormals; i < len(argtypes); i++ {
+			f.assign(tElem, argtypes[i])
+		}
+	}
+}
+
+func (f *Finder) builtin(obj *types.Builtin, sig *types.Signature, args []ast.Expr, T types.Type) types.Type {
+	switch obj.Name() {
+	case "make", "new":
+		// skip the type operand
+		for _, arg := range args[1:] {
+			f.expr(arg)
+		}
+
+	case "append":
+		s := f.expr(args[0])
+		if _, ok := args[len(args)-1].(*ast.Ellipsis); ok && len(args) == 2 {
+			// append(x, y...)   including append([]byte, "foo"...)
+			f.expr(args[1])
+		} else {
+			// append(x, y, z)
+			tElem := s.Underlying().(*types.Slice).Elem()
+			for _, arg := range args[1:] {
+				f.assign(tElem, f.expr(arg))
+			}
+		}
+
+	case "delete":
+		m := f.expr(args[0])
+		k := f.expr(args[1])
+		f.assign(m.Underlying().(*types.Map).Key(), k)
+
+	default:
+		// ordinary call
+		f.call(sig, args)
+	}
+
+	return T
+}
+
+func (f *Finder) extract(tuple types.Type, i int) types.Type {
+	if tuple, ok := tuple.(*types.Tuple); ok && i < tuple.Len() {
+		return tuple.At(i).Type()
+	}
+	return tInvalid
+}
+
+func (f *Finder) valueSpec(spec *ast.ValueSpec) {
+	var T types.Type
+	if spec.Type != nil {
+		T = f.info.Types[spec.Type].Type
+	}
+	switch len(spec.Values) {
+	case len(spec.Names): // e.g. var x, y = f(), g()
+		for _, value := range spec.Values {
+			v := f.expr(value)
+			if T != nil {
+				f.assign(T, v)
+			}
+		}
+
+	case 1: // e.g. var x, y = f()
+		tuple := f.exprN(spec.Values[0])
+		for i := range spec.Names {
+			if T != nil {
+				f.assign(T, f.extract(tuple, i))
+			}
+		}
+	}
+}
+
+// assign records pairs of distinct types that are related by
+// assignability, where the left-hand side is an interface and both
+// sides have methods.
+//
+// It should be called for all assignability checks, type assertions,
+// explicit conversions and comparisons between two types, unless the
+// types are uninteresting (e.g. lhs is a concrete type, or the empty
+// interface; rhs has no methods).
+//
+func (f *Finder) assign(lhs, rhs types.Type) {
+	if types.Identical(lhs, rhs) {
+		return
+	}
+	if !isInterface(lhs) {
+		return
+	}
+
+	if f.msetcache.MethodSet(lhs).Len() == 0 {
+		return
+	}
+	if f.msetcache.MethodSet(rhs).Len() == 0 {
+		return
+	}
+	// record the pair
+	f.Result[Constraint{lhs, rhs}] = true
+}
+
+// typeAssert must be called for each type assertion x.(T) where x has
+// interface type I.
+func (f *Finder) typeAssert(I, T types.Type) {
+	// Type assertions are slightly subtle, because they are allowed
+	// to be "impossible", e.g.
+	//
+	// 	var x interface{f()}
+	//	_ = x.(interface{f()int}) // legal
+	//
+	// (In hindsight, the language spec should probably not have
+	// allowed this, but it's too late to fix now.)
+	//
+	// This means that a type assert from I to T isn't exactly a
+	// constraint that T is assignable to I, but for a refactoring
+	// tool it is a conditional constraint that, if T is assignable
+	// to I before a refactoring, it should remain so after.
+
+	if types.AssignableTo(T, I) {
+		f.assign(I, T)
+	}
+}
+
+// compare must be called for each comparison x==y.
+func (f *Finder) compare(x, y types.Type) {
+	if types.AssignableTo(x, y) {
+		f.assign(y, x)
+	} else if types.AssignableTo(y, x) {
+		f.assign(x, y)
+	}
+}
+
+// expr visits a true expression (not a type or defining ident)
+// and returns its type.
+func (f *Finder) expr(e ast.Expr) types.Type {
+	tv := f.info.Types[e]
+	if tv.Value != nil {
+		return tv.Type // prune the descent for constants
+	}
+
+	// tv.Type may be nil for an ast.Ident.
+
+	switch e := e.(type) {
+	case *ast.BadExpr, *ast.BasicLit:
+		// no-op
+
+	case *ast.Ident:
+		// (referring idents only)
+		if obj, ok := f.info.Uses[e]; ok {
+			return obj.Type()
+		}
+		if e.Name == "_" { // e.g. "for _ = range x"
+			return tInvalid
+		}
+		panic("undefined ident: " + e.Name)
+
+	case *ast.Ellipsis:
+		if e.Elt != nil {
+			f.expr(e.Elt)
+		}
+
+	case *ast.FuncLit:
+		saved := f.sig
+		f.sig = tv.Type.(*types.Signature)
+		f.stmt(e.Body)
+		f.sig = saved
+
+	case *ast.CompositeLit:
+		switch T := deref(tv.Type).Underlying().(type) {
+		case *types.Struct:
+			for i, elem := range e.Elts {
+				if kv, ok := elem.(*ast.KeyValueExpr); ok {
+					f.assign(f.info.Uses[kv.Key.(*ast.Ident)].Type(), f.expr(kv.Value))
+				} else {
+					f.assign(T.Field(i).Type(), f.expr(elem))
+				}
+			}
+
+		case *types.Map:
+			for _, elem := range e.Elts {
+				elem := elem.(*ast.KeyValueExpr)
+				f.assign(T.Key(), f.expr(elem.Key))
+				f.assign(T.Elem(), f.expr(elem.Value))
+			}
+
+		case *types.Array, *types.Slice:
+			tElem := T.(interface {
+				Elem() types.Type
+			}).Elem()
+			for _, elem := range e.Elts {
+				if kv, ok := elem.(*ast.KeyValueExpr); ok {
+					// ignore the key
+					f.assign(tElem, f.expr(kv.Value))
+				} else {
+					f.assign(tElem, f.expr(elem))
+				}
+			}
+
+		default:
+			panic("unexpected composite literal type: " + tv.Type.String())
+		}
+
+	case *ast.ParenExpr:
+		f.expr(e.X)
+
+	case *ast.SelectorExpr:
+		if _, ok := f.info.Selections[e]; ok {
+			f.expr(e.X) // selection
+		} else {
+			return f.info.Uses[e.Sel].Type() // qualified identifier
+		}
+
+	case *ast.IndexExpr:
+		x := f.expr(e.X)
+		i := f.expr(e.Index)
+		if ux, ok := x.Underlying().(*types.Map); ok {
+			f.assign(ux.Key(), i)
+		}
+
+	case *ast.SliceExpr:
+		f.expr(e.X)
+		if e.Low != nil {
+			f.expr(e.Low)
+		}
+		if e.High != nil {
+			f.expr(e.High)
+		}
+		if e.Max != nil {
+			f.expr(e.Max)
+		}
+
+	case *ast.TypeAssertExpr:
+		x := f.expr(e.X)
+		f.typeAssert(x, f.info.Types[e.Type].Type)
+
+	case *ast.CallExpr:
+		if tvFun := f.info.Types[e.Fun]; tvFun.IsType() {
+			// conversion
+			arg0 := f.expr(e.Args[0])
+			f.assign(tvFun.Type, arg0)
+		} else {
+			// function call
+			if id, ok := unparen(e.Fun).(*ast.Ident); ok {
+				if obj, ok := f.info.Uses[id].(*types.Builtin); ok {
+					sig := f.info.Types[id].Type.(*types.Signature)
+					return f.builtin(obj, sig, e.Args, tv.Type)
+				}
+			}
+			// ordinary call
+			f.call(f.expr(e.Fun).Underlying().(*types.Signature), e.Args)
+		}
+
+	case *ast.StarExpr:
+		f.expr(e.X)
+
+	case *ast.UnaryExpr:
+		f.expr(e.X)
+
+	case *ast.BinaryExpr:
+		x := f.expr(e.X)
+		y := f.expr(e.Y)
+		if e.Op == token.EQL || e.Op == token.NEQ {
+			f.compare(x, y)
+		}
+
+	case *ast.KeyValueExpr:
+		f.expr(e.Key)
+		f.expr(e.Value)
+
+	case *ast.ArrayType,
+		*ast.StructType,
+		*ast.FuncType,
+		*ast.InterfaceType,
+		*ast.MapType,
+		*ast.ChanType:
+		panic(e)
+	}
+
+	if tv.Type == nil {
+		panic(fmt.Sprintf("no type for %T", e))
+	}
+
+	return tv.Type
+}
+
+func (f *Finder) stmt(s ast.Stmt) {
+	switch s := s.(type) {
+	case *ast.BadStmt,
+		*ast.EmptyStmt,
+		*ast.BranchStmt:
+		// no-op
+
+	case *ast.DeclStmt:
+		d := s.Decl.(*ast.GenDecl)
+		if d.Tok == token.VAR { // ignore consts
+			for _, spec := range d.Specs {
+				f.valueSpec(spec.(*ast.ValueSpec))
+			}
+		}
+
+	case *ast.LabeledStmt:
+		f.stmt(s.Stmt)
+
+	case *ast.ExprStmt:
+		f.expr(s.X)
+
+	case *ast.SendStmt:
+		ch := f.expr(s.Chan)
+		val := f.expr(s.Value)
+		f.assign(ch.Underlying().(*types.Chan).Elem(), val)
+
+	case *ast.IncDecStmt:
+		f.expr(s.X)
+
+	case *ast.AssignStmt:
+		switch s.Tok {
+		case token.ASSIGN, token.DEFINE:
+			// y := x   or   y = x
+			var rhsTuple types.Type
+			if len(s.Lhs) != len(s.Rhs) {
+				rhsTuple = f.exprN(s.Rhs[0])
+			}
+			for i := range s.Lhs {
+				var lhs, rhs types.Type
+				if rhsTuple == nil {
+					rhs = f.expr(s.Rhs[i]) // 1:1 assignment
+				} else {
+					rhs = f.extract(rhsTuple, i) // n:1 assignment
+				}
+
+				if id, ok := s.Lhs[i].(*ast.Ident); ok {
+					if id.Name != "_" {
+						if obj, ok := f.info.Defs[id]; ok {
+							lhs = obj.Type() // definition
+						}
+					}
+				}
+				if lhs == nil {
+					lhs = f.expr(s.Lhs[i]) // assignment
+				}
+				f.assign(lhs, rhs)
+			}
+
+		default:
+			// y op= x
+			f.expr(s.Lhs[0])
+			f.expr(s.Rhs[0])
+		}
+
+	case *ast.GoStmt:
+		f.expr(s.Call)
+
+	case *ast.DeferStmt:
+		f.expr(s.Call)
+
+	case *ast.ReturnStmt:
+		formals := f.sig.Results()
+		switch len(s.Results) {
+		case formals.Len(): // 1:1
+			for i, result := range s.Results {
+				f.assign(formals.At(i).Type(), f.expr(result))
+			}
+
+		case 1: // n:1
+			tuple := f.exprN(s.Results[0])
+			for i := 0; i < formals.Len(); i++ {
+				f.assign(formals.At(i).Type(), f.extract(tuple, i))
+			}
+		}
+
+	case *ast.SelectStmt:
+		f.stmt(s.Body)
+
+	case *ast.BlockStmt:
+		for _, s := range s.List {
+			f.stmt(s)
+		}
+
+	case *ast.IfStmt:
+		if s.Init != nil {
+			f.stmt(s.Init)
+		}
+		f.expr(s.Cond)
+		f.stmt(s.Body)
+		if s.Else != nil {
+			f.stmt(s.Else)
+		}
+
+	case *ast.SwitchStmt:
+		if s.Init != nil {
+			f.stmt(s.Init)
+		}
+		var tag types.Type = tUntypedBool
+		if s.Tag != nil {
+			tag = f.expr(s.Tag)
+		}
+		for _, cc := range s.Body.List {
+			cc := cc.(*ast.CaseClause)
+			for _, cond := range cc.List {
+				f.compare(tag, f.info.Types[cond].Type)
+			}
+			for _, s := range cc.Body {
+				f.stmt(s)
+			}
+		}
+
+	case *ast.TypeSwitchStmt:
+		if s.Init != nil {
+			f.stmt(s.Init)
+		}
+		var I types.Type
+		switch ass := s.Assign.(type) {
+		case *ast.ExprStmt: // x.(type)
+			I = f.expr(unparen(ass.X).(*ast.TypeAssertExpr).X)
+		case *ast.AssignStmt: // y := x.(type)
+			I = f.expr(unparen(ass.Rhs[0]).(*ast.TypeAssertExpr).X)
+		}
+		for _, cc := range s.Body.List {
+			cc := cc.(*ast.CaseClause)
+			for _, cond := range cc.List {
+				tCase := f.info.Types[cond].Type
+				if tCase != tUntypedNil {
+					f.typeAssert(I, tCase)
+				}
+			}
+			for _, s := range cc.Body {
+				f.stmt(s)
+			}
+		}
+
+	case *ast.CommClause:
+		if s.Comm != nil {
+			f.stmt(s.Comm)
+		}
+		for _, s := range s.Body {
+			f.stmt(s)
+		}
+
+	case *ast.ForStmt:
+		if s.Init != nil {
+			f.stmt(s.Init)
+		}
+		if s.Cond != nil {
+			f.expr(s.Cond)
+		}
+		if s.Post != nil {
+			f.stmt(s.Post)
+		}
+		f.stmt(s.Body)
+
+	case *ast.RangeStmt:
+		x := f.expr(s.X)
+		// No conversions are involved when Tok==DEFINE.
+		if s.Tok == token.ASSIGN {
+			if s.Key != nil {
+				k := f.expr(s.Key)
+				var xelem types.Type
+				// keys of array, *array, slice, string aren't interesting
+				switch ux := x.Underlying().(type) {
+				case *types.Chan:
+					xelem = ux.Elem()
+				case *types.Map:
+					xelem = ux.Key()
+				}
+				if xelem != nil {
+					f.assign(xelem, k)
+				}
+			}
+			if s.Value != nil {
+				val := f.expr(s.Value)
+				var xelem types.Type
+				// values of strings aren't interesting
+				switch ux := x.Underlying().(type) {
+				case *types.Array:
+					xelem = ux.Elem()
+				case *types.Chan:
+					xelem = ux.Elem()
+				case *types.Map:
+					xelem = ux.Elem()
+				case *types.Pointer: // *array
+					xelem = deref(ux).(*types.Array).Elem()
+				case *types.Slice:
+					xelem = ux.Elem()
+				}
+				if xelem != nil {
+					f.assign(xelem, val)
+				}
+			}
+		}
+		f.stmt(s.Body)
+
+	default:
+		panic(s)
+	}
+}
+
+// -- Plundered from golang.org/x/tools/go/ssa -----------------
+
+// deref returns a pointer's element type; otherwise it returns typ.
+func deref(typ types.Type) types.Type {
+	if p, ok := typ.Underlying().(*types.Pointer); ok {
+		return p.Elem()
+	}
+	return typ
+}
+
+func unparen(e ast.Expr) ast.Expr { return astutil.Unparen(e) }
+
+func isInterface(T types.Type) bool { return types.IsInterface(T) }