summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOndřej Surý <ondrej@sury.org>2011-09-19 10:12:52 +0200
committerOndřej Surý <ondrej@sury.org>2011-09-19 10:12:52 +0200
commit9ad2a96babca1e646856b4335875b975f9bb7fa1 (patch)
tree4ac4867f2cfffd577fe5d9aa5fe4543bd2d96f45
parent5ff4c17907d5b19510a62e08fd8d3b11e62b431d (diff)
downloadgolang-9ad2a96babca1e646856b4335875b975f9bb7fa1.tar.gz
Imported Upstream version 60.1upstream/60.1
-rw-r--r--doc/devel/release.html15
-rw-r--r--doc/docs.html45
-rw-r--r--misc/goplay/goplay.go4
-rw-r--r--src/cmd/cgo/doc.go3
-rw-r--r--src/cmd/gc/obj.c10
-rw-r--r--src/cmd/godoc/doc.go3
-rw-r--r--src/cmd/ld/dwarf.c26
-rw-r--r--src/pkg/gob/doc.go3
-rw-r--r--src/pkg/json/Makefile1
-rw-r--r--src/pkg/json/decode.go22
-rw-r--r--src/pkg/json/decode_test.go11
-rw-r--r--src/pkg/json/encode.go62
-rw-r--r--src/pkg/json/encode_test.go38
-rw-r--r--src/pkg/json/tags.go44
-rw-r--r--src/pkg/json/tags_test.go28
-rw-r--r--src/pkg/reflect/type.go3
-rwxr-xr-xtest/dwarf/linedirectives.go83
-rw-r--r--test/dwarf/main.go29
-rw-r--r--test/dwarf/z1.go5
-rw-r--r--test/dwarf/z10.go6
-rw-r--r--test/dwarf/z11.go4
-rw-r--r--test/dwarf/z12.go4
-rw-r--r--test/dwarf/z13.go4
-rw-r--r--test/dwarf/z14.go4
-rw-r--r--test/dwarf/z15.go4
-rw-r--r--test/dwarf/z16.go4
-rw-r--r--test/dwarf/z17.go4
-rw-r--r--test/dwarf/z18.go5
-rw-r--r--test/dwarf/z19.go4
-rw-r--r--test/dwarf/z2.go4
-rw-r--r--test/dwarf/z20.go4
-rw-r--r--test/dwarf/z3.go4
-rw-r--r--test/dwarf/z4.go4
-rw-r--r--test/dwarf/z5.go4
-rw-r--r--test/dwarf/z6.go4
-rw-r--r--test/dwarf/z7.go4
-rw-r--r--test/dwarf/z8.go4
-rw-r--r--test/dwarf/z9.go4
-rw-r--r--test/golden.out2
-rwxr-xr-xtest/run2
40 files changed, 469 insertions, 49 deletions
diff --git a/doc/devel/release.html b/doc/devel/release.html
index 458a116de..4ce3d37c1 100644
--- a/doc/devel/release.html
+++ b/doc/devel/release.html
@@ -89,6 +89,21 @@ appropriate tag or branch names in their repositories to make their libraries
more accessible.
</p>
+<h3 id="r60.minor">Minor revisions</h3>
+
+<p>
+r60.1 includes a
+<a href="http://code.google.com/p/go/source/detail?r=1824581bf62d">linker
+fix</a>, a pair of
+<a href="http://code.google.com/p/go/source/detail?r=9ef4429c2c64">goplay</a>
+<a href="http://code.google.com/p/go/source/detail?r=d42ed8c3098e">fixes</a>,
+and a <code>json</code> package
+<a href="http://code.google.com/p/go/source/detail?r=d5e97874fe84">fix</a> and
+a new
+<a href="http://code.google.com/p/go/source/detail?r=4f0e6269213f">struct tag
+option</a>.
+</p>
+
<h2 id="r59">r59 (released 2011/08/01)</h2>
<p>
diff --git a/doc/docs.html b/doc/docs.html
index 9fd3dcebe..ce833fdd1 100644
--- a/doc/docs.html
+++ b/doc/docs.html
@@ -29,9 +29,9 @@ Slides from a 3-day course about the Go programming language.
A more thorough introduction than the tutorial.
</p>
<ul>
-<li><a href="GoCourseDay1.pdf">Day 1: Basics</a> <small>[270KB PDF]</small>
-<li><a href="GoCourseDay2.pdf">Day 2: Types, Methods, Interfaces</a> <small>[270KB PDF]</small>
-<li><a href="GoCourseDay3.pdf">Day 3: Concurrency and Communication</a> <small>[180KB PDF]</small>
+<li><a href="GoCourseDay1.pdf">Day 1: Basics</a> <small>[270KB PDF]</small></li>
+<li><a href="GoCourseDay2.pdf">Day 2: Types, Methods, Interfaces</a> <small>[270KB PDF]</small></li>
+<li><a href="GoCourseDay3.pdf">Day 3: Concurrency and Communication</a> <small>[180KB PDF]</small></li>
</ul>
<h3 id="effective_go"><a href="effective_go.html">Effective Go</a></h3>
@@ -62,12 +62,51 @@ and closures.
<p>
Guided tours of Go programs.
</p>
+<ul>
+<li><a href="/doc/codewalk/functions">First-Class Functions in Go</a></li>
+<li><a href="/doc/codewalk/markov">Generating arbitrary text: a Markov chain algorithm</a></li>
+<li><a href="/doc/codewalk/sharemem">Share Memory by Communicating</a></li>
+</ul>
<h3 id="go_for_cpp_programmers"><a href="go_for_cpp_programmers.html">Go for C++ Programmers</a></h3>
<p>
An introduction to Go for C++ programmers.
</p>
+<h2 id="articles">Go Articles</h2>
+
+<p>
+Notable articles from the <a href="http://blog.golang.org/">Go Blog</a>.
+</p>
+
+<h3>Language</h3>
+
+<ul>
+<li><a href="http://blog.golang.org/2010/04/json-rpc-tale-of-interfaces.html">JSON-RPC: a tale of interfaces</a></li>
+<li><a href="http://blog.golang.org/2010/07/gos-declaration-syntax.html">Go's Declaration Syntax</a></li>
+<li><a href="http://blog.golang.org/2010/08/defer-panic-and-recover.html">Defer, Panic, and Recover</a></li>
+<li><a href="http://blog.golang.org/2010/09/go-concurrency-patterns-timing-out-and.html">Go Concurrency Patterns: Timing out, moving on</a></li>
+<li><a href="http://blog.golang.org/2011/01/go-slices-usage-and-internals.html">Go Slices: usage and internals</a></li>
+<li><a href="http://blog.golang.org/2011/05/gif-decoder-exercise-in-go-interfaces.html">A GIF decoder: an exercise in Go interfaces</a></li>
+<li><a href="http://blog.golang.org/2011/07/error-handling-and-go.html">Error Handling and Go</a></li>
+</ul>
+
+<h3>Packages</h3>
+
+<ul>
+<li><a href="http://blog.golang.org/2011/01/json-and-go.html">JSON and Go</a> - using the <a href="/pkg/json/">json</a> package.</li>
+<li><a href="http://blog.golang.org/2011/03/gobs-of-data.html">Gobs of data</a> - the design and use of the <a href="/pkg/gob/">gob</a> package.</li>
+<li><a href="http://blog.golang.org/2011/09/laws-of-reflection.html">The Laws of Reflection</a> - the fundamentals of the <a href="/pkg/reflect/">reflect</a> package.</li>
+</ul>
+
+<h3>Tools</h3>
+
+<ul>
+<li><a href="http://blog.golang.org/2011/03/c-go-cgo.html">C? Go? Cgo!</a> - linking against C code with <a href="/cmd/cgo/">cgo</a>.</li>
+<li><a href="http://blog.golang.org/2011/03/godoc-documenting-go-code.html">Godoc: documenting Go code</a> - writing good documentation for <a href="/cmd/godoc/">godoc</a>.</li>
+<li><a href="http://blog.golang.org/2011/06/profiling-go-programs.html">Profiling Go Programs</a></li>
+</ul>
+
<h2 id="tutorials_nonenglish">Non-English Documentation</h2>
<h3 id="docs_be">Belarusian &mdash; Беларуская</h3>
diff --git a/misc/goplay/goplay.go b/misc/goplay/goplay.go
index bbc388ba4..a1eb61795 100644
--- a/misc/goplay/goplay.go
+++ b/misc/goplay/goplay.go
@@ -145,7 +145,7 @@ func run(cmd ...string) ([]byte, os.Error) {
var frontPage = template.Must(template.New("frontPage").Parse(frontPageText)) // HTML template
var output = template.Must(template.New("output").Parse(outputText)) // HTML template
-var outputText = `<pre>{{html .}}</pre>`
+var outputText = `<pre>{{printf "%s" . |html}}</pre>`
var frontPageText = `<!doctype html>
<html>
@@ -256,7 +256,7 @@ function compileUpdate() {
</head>
<body>
<table width="100%"><tr><td width="60%" valign="top">
-<textarea autofocus="true" id="edit" spellcheck="false" onkeydown="keyHandler(event);" onkeyup="autocompile();">{{html .}}</textarea>
+<textarea autofocus="true" id="edit" spellcheck="false" onkeydown="keyHandler(event);" onkeyup="autocompile();">{{printf "%s" . |html}}</textarea>
<div class="hints">
(Shift-Enter to compile and run.)&nbsp;&nbsp;&nbsp;&nbsp;
<input type="checkbox" id="autocompile" value="checked" /> Compile and run after each keystroke
diff --git a/src/cmd/cgo/doc.go b/src/cmd/cgo/doc.go
index 63413825a..a4219867c 100644
--- a/src/cmd/cgo/doc.go
+++ b/src/cmd/cgo/doc.go
@@ -92,5 +92,8 @@ process of using cgo. See $GOROOT/misc/cgo/stdio and
$GOROOT/misc/cgo/gmp for examples.
Cgo does not yet work with gccgo.
+
+See "C? Go? Cgo!" for an introduction to using cgo:
+http://blog.golang.org/2011/03/c-go-cgo.html
*/
package documentation
diff --git a/src/cmd/gc/obj.c b/src/cmd/gc/obj.c
index 456aabb88..f99f93bda 100644
--- a/src/cmd/gc/obj.c
+++ b/src/cmd/gc/obj.c
@@ -127,7 +127,6 @@ static void
outhist(Biobuf *b)
{
Hist *h;
- int i, depth = 0;
char *p, ds[] = {'c', ':', '/', 0};
for(h = hist; h != H; h = h->link) {
@@ -164,14 +163,7 @@ outhist(Biobuf *b)
outzfile(b, p);
}
}
- if(h->offset > 0) {
- //line directive
- depth++;
- }
- } else if(depth > 0) {
- for(i = 0; i < depth; i++)
- zhist(b, h->line, h->offset);
- depth = 0;
+
}
zhist(b, h->line, h->offset);
}
diff --git a/src/cmd/godoc/doc.go b/src/cmd/godoc/doc.go
index dc98b0eca..088889d2a 100644
--- a/src/cmd/godoc/doc.go
+++ b/src/cmd/godoc/doc.go
@@ -126,5 +126,8 @@ one may run godoc as follows:
godoc -http=:6060 -zip=go.zip -goroot=$HOME/go
+
+See "Godoc: documenting Go code" for how to write good comments for godoc:
+http://blog.golang.org/2011/03/godoc-documenting-go-code.html
*/
package documentation
diff --git a/src/cmd/ld/dwarf.c b/src/cmd/ld/dwarf.c
index d8ca27ace..77536018a 100644
--- a/src/cmd/ld/dwarf.c
+++ b/src/cmd/ld/dwarf.c
@@ -1578,13 +1578,16 @@ addhistfile(char *zentry)
histfile[histfilesize++] = "<eof>";
fname = decodez(zentry);
+// print("addhistfile %d: %s\n", histfilesize, fname);
if (fname == 0)
return -1;
+
// Don't fill with duplicates (check only top one).
if (strcmp(fname, histfile[histfilesize-1]) == 0) {
free(fname);
return histfilesize - 1;
}
+
histfile[histfilesize++] = fname;
return histfilesize - 1;
}
@@ -1608,11 +1611,13 @@ finddebugruntimepath(void)
}
// Go's runtime C sources are sane, and Go sources nest only 1 level,
-// so 16 should be plenty.
+// so a handful would be plenty, if it weren't for the fact that line
+// directives can push an unlimited number of them.
static struct {
int file;
vlong line;
-} includestack[16];
+} *includestack;
+static int includestacksize;
static int includetop;
static vlong absline;
@@ -1629,17 +1634,15 @@ static Linehist *linehist;
static void
checknesting(void)
{
- int i;
-
if (includetop < 0) {
diag("dwarf: corrupt z stack");
errorexit();
}
- if (includetop >= nelem(includestack)) {
- diag("dwarf: nesting too deep");
- for (i = 0; i < nelem(includestack); i++)
- diag("\t%s", histfile[includestack[i].file]);
- errorexit();
+ if (includetop >= includestacksize) {
+ includestacksize += 1;
+ includestacksize <<= 2;
+// print("checknesting: growing to %d\n", includestacksize);
+ includestack = realloc(includestack, includestacksize * sizeof *includestack);
}
}
@@ -1669,6 +1672,7 @@ inithist(Auto *a)
// Clear the history.
clearhistfile();
includetop = 0;
+ checknesting();
includestack[includetop].file = 0;
includestack[includetop].line = -1;
absline = 0;
@@ -1682,10 +1686,10 @@ inithist(Auto *a)
for (; a; a = a->link) {
if (a->type == D_FILE) { // 'z'
int f = addhistfile(a->asym->name);
- if (f < 0) { // pop file
+ if (f < 0) { // pop file
includetop--;
checknesting();
- } else if(f != includestack[includetop].file) { // pushed a new file
+ } else { // pushed a file (potentially same)
includestack[includetop].line += a->aoffset - absline;
includetop++;
checknesting();
diff --git a/src/pkg/gob/doc.go b/src/pkg/gob/doc.go
index 35d882afb..a9284ced7 100644
--- a/src/pkg/gob/doc.go
+++ b/src/pkg/gob/doc.go
@@ -221,6 +221,9 @@ In summary, a gob stream looks like
where * signifies zero or more repetitions and the type id of a value must
be predefined or be defined before the value in the stream.
+
+See "Gobs of data" for a design discussion of the gob wire format:
+http://blog.golang.org/2011/03/gobs-of-data.html
*/
package gob
diff --git a/src/pkg/json/Makefile b/src/pkg/json/Makefile
index 4e5a8a139..28ed62bc4 100644
--- a/src/pkg/json/Makefile
+++ b/src/pkg/json/Makefile
@@ -11,5 +11,6 @@ GOFILES=\
indent.go\
scanner.go\
stream.go\
+ tags.go\
include ../../Make.pkg
diff --git a/src/pkg/json/decode.go b/src/pkg/json/decode.go
index 4f6562bd5..b7129f984 100644
--- a/src/pkg/json/decode.go
+++ b/src/pkg/json/decode.go
@@ -140,6 +140,7 @@ type decodeState struct {
scan scanner
nextscan scanner // for calls to nextValue
savedError os.Error
+ tempstr string // scratch space to avoid some allocations
}
// errPhase is used for errors that should not happen unless
@@ -470,6 +471,8 @@ func (d *decodeState) object(v reflect.Value) {
// Figure out field corresponding to key.
var subv reflect.Value
+ destring := false // whether the value is wrapped in a string to be decoded first
+
if mv.IsValid() {
elemType := mv.Type().Elem()
if !mapElem.IsValid() {
@@ -486,7 +489,8 @@ func (d *decodeState) object(v reflect.Value) {
if isValidTag(key) {
for i := 0; i < sv.NumField(); i++ {
f = st.Field(i)
- if f.Tag.Get("json") == key {
+ tagName, _ := parseTag(f.Tag.Get("json"))
+ if tagName == key {
ok = true
break
}
@@ -508,6 +512,8 @@ func (d *decodeState) object(v reflect.Value) {
} else {
subv = sv.FieldByIndex(f.Index)
}
+ _, opts := parseTag(f.Tag.Get("json"))
+ destring = opts.Contains("string")
}
}
@@ -520,8 +526,12 @@ func (d *decodeState) object(v reflect.Value) {
}
// Read value.
- d.value(subv)
-
+ if destring {
+ d.value(reflect.ValueOf(&d.tempstr))
+ d.literalStore([]byte(d.tempstr), subv)
+ } else {
+ d.value(subv)
+ }
// Write value back to map;
// if using struct, subv points into struct already.
if mv.IsValid() {
@@ -550,8 +560,12 @@ func (d *decodeState) literal(v reflect.Value) {
// Scan read one byte too far; back up.
d.off--
d.scan.undo(op)
- item := d.data[start:d.off]
+ d.literalStore(d.data[start:d.off], v)
+}
+
+// literalStore decodes a literal stored in item into v.
+func (d *decodeState) literalStore(item []byte, v reflect.Value) {
// Check for unmarshaler.
wantptr := item[0] == 'n' // null
unmarshaler, pv := d.indirect(v, wantptr)
diff --git a/src/pkg/json/decode_test.go b/src/pkg/json/decode_test.go
index a855d6048..5f6c3f5b8 100644
--- a/src/pkg/json/decode_test.go
+++ b/src/pkg/json/decode_test.go
@@ -262,7 +262,10 @@ type All struct {
Float32 float32
Float64 float64
- Foo string `json:"bar"`
+ Foo string `json:"bar"`
+ Foo2 string `json:"bar2,dummyopt"`
+
+ IntStr int64 `json:",string"`
PBool *bool
PInt *int
@@ -331,6 +334,8 @@ var allValue = All{
Float32: 14.1,
Float64: 15.1,
Foo: "foo",
+ Foo2: "foo2",
+ IntStr: 42,
String: "16",
Map: map[string]Small{
"17": {Tag: "tag17"},
@@ -391,6 +396,8 @@ var allValueIndent = `{
"Float32": 14.1,
"Float64": 15.1,
"bar": "foo",
+ "bar2": "foo2",
+ "IntStr": "42",
"PBool": null,
"PInt": null,
"PInt8": null,
@@ -481,6 +488,8 @@ var pallValueIndent = `{
"Float32": 0,
"Float64": 0,
"bar": "",
+ "bar2": "",
+ "IntStr": "0",
"PBool": true,
"PInt": 2,
"PInt8": 3,
diff --git a/src/pkg/json/encode.go b/src/pkg/json/encode.go
index 3e593fec1..16be5e2af 100644
--- a/src/pkg/json/encode.go
+++ b/src/pkg/json/encode.go
@@ -4,6 +4,9 @@
// Package json implements encoding and decoding of JSON objects as defined in
// RFC 4627.
+//
+// See "JSON and Go" for an introduction to this package:
+// http://blog.golang.org/2011/01/json-and-go.html
package json
import (
@@ -14,7 +17,6 @@ import (
"runtime"
"sort"
"strconv"
- "strings"
"unicode"
"utf8"
)
@@ -59,6 +61,12 @@ import (
// // Note the leading comma.
// Field int `json:",omitempty"`
//
+// The "string" option signals that a field is stored as JSON inside a
+// JSON-encoded string. This extra level of encoding is sometimes
+// used when communicating with JavaScript programs:
+//
+// Int64String int64 `json:",string"`
+//
// The key name will be used if it's a non-empty string consisting of
// only Unicode letters, digits, dollar signs, hyphens, and underscores.
//
@@ -221,6 +229,12 @@ func isEmptyValue(v reflect.Value) bool {
}
func (e *encodeState) reflectValue(v reflect.Value) {
+ e.reflectValueQuoted(v, false)
+}
+
+// reflectValueQuoted writes the value in v to the output.
+// If quoted is true, the serialization is wrapped in a JSON string.
+func (e *encodeState) reflectValueQuoted(v reflect.Value, quoted bool) {
if !v.IsValid() {
e.WriteString("null")
return
@@ -238,26 +252,39 @@ func (e *encodeState) reflectValue(v reflect.Value) {
return
}
+ writeString := (*encodeState).WriteString
+ if quoted {
+ writeString = (*encodeState).string
+ }
+
switch v.Kind() {
case reflect.Bool:
x := v.Bool()
if x {
- e.WriteString("true")
+ writeString(e, "true")
} else {
- e.WriteString("false")
+ writeString(e, "false")
}
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
- e.WriteString(strconv.Itoa64(v.Int()))
+ writeString(e, strconv.Itoa64(v.Int()))
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
- e.WriteString(strconv.Uitoa64(v.Uint()))
+ writeString(e, strconv.Uitoa64(v.Uint()))
case reflect.Float32, reflect.Float64:
- e.WriteString(strconv.FtoaN(v.Float(), 'g', -1, v.Type().Bits()))
+ writeString(e, strconv.FtoaN(v.Float(), 'g', -1, v.Type().Bits()))
case reflect.String:
- e.string(v.String())
+ if quoted {
+ sb, err := Marshal(v.String())
+ if err != nil {
+ e.error(err)
+ }
+ e.string(string(sb))
+ } else {
+ e.string(v.String())
+ }
case reflect.Struct:
e.WriteByte('{')
@@ -269,17 +296,14 @@ func (e *encodeState) reflectValue(v reflect.Value) {
if f.PkgPath != "" {
continue
}
- tag, omitEmpty := f.Name, false
+ tag, omitEmpty, quoted := f.Name, false, false
if tv := f.Tag.Get("json"); tv != "" {
- ss := strings.SplitN(tv, ",", 2)
- if isValidTag(ss[0]) {
- tag = ss[0]
- }
- if len(ss) > 1 {
- // Currently the only option is omitempty,
- // so parsing is trivial.
- omitEmpty = ss[1] == "omitempty"
+ name, opts := parseTag(tv)
+ if isValidTag(name) {
+ tag = name
}
+ omitEmpty = opts.Contains("omitempty")
+ quoted = opts.Contains("string")
}
fieldValue := v.Field(i)
if omitEmpty && isEmptyValue(fieldValue) {
@@ -292,7 +316,7 @@ func (e *encodeState) reflectValue(v reflect.Value) {
}
e.string(tag)
e.WriteByte(':')
- e.reflectValue(fieldValue)
+ e.reflectValueQuoted(fieldValue, quoted)
}
e.WriteByte('}')
@@ -380,7 +404,8 @@ func (sv stringValues) Swap(i, j int) { sv[i], sv[j] = sv[j], sv[i] }
func (sv stringValues) Less(i, j int) bool { return sv.get(i) < sv.get(j) }
func (sv stringValues) get(i int) string { return sv[i].String() }
-func (e *encodeState) string(s string) {
+func (e *encodeState) string(s string) (int, os.Error) {
+ len0 := e.Len()
e.WriteByte('"')
start := 0
for i := 0; i < len(s); {
@@ -425,4 +450,5 @@ func (e *encodeState) string(s string) {
e.WriteString(s[start:])
}
e.WriteByte('"')
+ return e.Len() - len0, nil
}
diff --git a/src/pkg/json/encode_test.go b/src/pkg/json/encode_test.go
index 0e4b63770..012e9f143 100644
--- a/src/pkg/json/encode_test.go
+++ b/src/pkg/json/encode_test.go
@@ -5,6 +5,8 @@
package json
import (
+ "bytes"
+ "reflect"
"testing"
)
@@ -42,3 +44,39 @@ func TestOmitEmpty(t *testing.T) {
t.Errorf(" got: %s\nwant: %s\n", got, optionalsExpected)
}
}
+
+type StringTag struct {
+ BoolStr bool `json:",string"`
+ IntStr int64 `json:",string"`
+ StrStr string `json:",string"`
+}
+
+var stringTagExpected = `{
+ "BoolStr": "true",
+ "IntStr": "42",
+ "StrStr": "\"xzbit\""
+}`
+
+func TestStringTag(t *testing.T) {
+ var s StringTag
+ s.BoolStr = true
+ s.IntStr = 42
+ s.StrStr = "xzbit"
+ got, err := MarshalIndent(&s, "", " ")
+ if err != nil {
+ t.Fatal(err)
+ }
+ if got := string(got); got != stringTagExpected {
+ t.Fatalf(" got: %s\nwant: %s\n", got, stringTagExpected)
+ }
+
+ // Verify that it round-trips.
+ var s2 StringTag
+ err = NewDecoder(bytes.NewBuffer(got)).Decode(&s2)
+ if err != nil {
+ t.Fatalf("Decode: %v", err)
+ }
+ if !reflect.DeepEqual(s, s2) {
+ t.Fatalf("decode didn't match.\nsource: %#v\nEncoded as:\n%s\ndecode: %#v", s, string(got), s2)
+ }
+}
diff --git a/src/pkg/json/tags.go b/src/pkg/json/tags.go
new file mode 100644
index 000000000..58cda2027
--- /dev/null
+++ b/src/pkg/json/tags.go
@@ -0,0 +1,44 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package json
+
+import (
+ "strings"
+)
+
+// tagOptions is the string following a comma in a struct field's "json"
+// tag, or the empty string. It does not include the leading comma.
+type tagOptions string
+
+// parseTag splits a struct field's json tag into its name and
+// comma-separated options.
+func parseTag(tag string) (string, tagOptions) {
+ if idx := strings.Index(tag, ","); idx != -1 {
+ return tag[:idx], tagOptions(tag[idx+1:])
+ }
+ return tag, tagOptions("")
+}
+
+// Contains returns whether checks that a comma-separated list of options
+// contains a particular substr flag. substr must be surrounded by a
+// string boundary or commas.
+func (o tagOptions) Contains(optionName string) bool {
+ if len(o) == 0 {
+ return false
+ }
+ s := string(o)
+ for s != "" {
+ var next string
+ i := strings.Index(s, ",")
+ if i >= 0 {
+ s, next = s[:i], s[i+1:]
+ }
+ if s == optionName {
+ return true
+ }
+ s = next
+ }
+ return false
+}
diff --git a/src/pkg/json/tags_test.go b/src/pkg/json/tags_test.go
new file mode 100644
index 000000000..91fb18831
--- /dev/null
+++ b/src/pkg/json/tags_test.go
@@ -0,0 +1,28 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package json
+
+import (
+ "testing"
+)
+
+func TestTagParsing(t *testing.T) {
+ name, opts := parseTag("field,foobar,foo")
+ if name != "field" {
+ t.Fatalf("name = %q, want field", name)
+ }
+ for _, tt := range []struct {
+ opt string
+ want bool
+ }{
+ {"foobar", true},
+ {"foo", true},
+ {"bar", false},
+ } {
+ if opts.Contains(tt.opt) != tt.want {
+ t.Errorf("Contains(%q) = %v", tt.opt, !tt.want)
+ }
+ }
+}
diff --git a/src/pkg/reflect/type.go b/src/pkg/reflect/type.go
index 4c377e1fe..ef0fb87ea 100644
--- a/src/pkg/reflect/type.go
+++ b/src/pkg/reflect/type.go
@@ -10,6 +10,9 @@
// A call to ValueOf returns a Value representing the run-time data.
// Zero takes a Type and returns a Value representing a zero value
// for that type.
+//
+// See "The Laws of Reflection" for an introduction to reflection in Go:
+// http://blog.golang.org/2011/09/laws-of-reflection.html
package reflect
import (
diff --git a/test/dwarf/linedirectives.go b/test/dwarf/linedirectives.go
new file mode 100755
index 000000000..68434f0ab
--- /dev/null
+++ b/test/dwarf/linedirectives.go
@@ -0,0 +1,83 @@
+// $G $D/$F.go && $L $F.$A && ./$A.out
+
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//line foo/bar.y:4
+package main
+//line foo/bar.y:60
+func main() {
+//line foo/bar.y:297
+ f, l := 0, 0
+//line yacctab:1
+ f, l = 1, 1
+//line yaccpar:1
+ f, l = 2, 1
+//line foo/bar.y:82
+ f, l = 3, 82
+//line foo/bar.y:90
+ f, l = 3, 90
+//line foo/bar.y:92
+ f, l = 3, 92
+//line foo/bar.y:100
+ f, l = 3, 100
+//line foo/bar.y:104
+ l = 104
+//line foo/bar.y:112
+ l = 112
+//line foo/bar.y:117
+ l = 117
+//line foo/bar.y:121
+ l = 121
+//line foo/bar.y:125
+ l = 125
+//line foo/bar.y:133
+ l = 133
+//line foo/bar.y:146
+ l = 146
+//line foo/bar.y:148
+//line foo/bar.y:153
+//line foo/bar.y:155
+ l = 155
+//line foo/bar.y:160
+
+//line foo/bar.y:164
+//line foo/bar.y:173
+
+//line foo/bar.y:178
+//line foo/bar.y:180
+//line foo/bar.y:185
+//line foo/bar.y:195
+//line foo/bar.y:197
+//line foo/bar.y:202
+//line foo/bar.y:204
+//line foo/bar.y:208
+//line foo/bar.y:211
+//line foo/bar.y:213
+//line foo/bar.y:215
+//line foo/bar.y:217
+//line foo/bar.y:221
+//line foo/bar.y:229
+//line foo/bar.y:236
+//line foo/bar.y:238
+//line foo/bar.y:240
+//line foo/bar.y:244
+//line foo/bar.y:249
+//line foo/bar.y:253
+//line foo/bar.y:257
+//line foo/bar.y:262
+//line foo/bar.y:267
+//line foo/bar.y:272
+ if l == f {
+//line foo/bar.y:277
+ panic("aie!")
+//line foo/bar.y:281
+ }
+//line foo/bar.y:285
+ return
+//line foo/bar.y:288
+//line foo/bar.y:290
+}
+//line foo/bar.y:293
+//line foo/bar.y:295
diff --git a/test/dwarf/main.go b/test/dwarf/main.go
new file mode 100644
index 000000000..7f2ec4c00
--- /dev/null
+++ b/test/dwarf/main.go
@@ -0,0 +1,29 @@
+// $G $D/$F.go $D/z*.go && $L $F.$A && ./$A.out
+
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+func main() {
+F1()
+F2()
+F3()
+F4()
+F5()
+F6()
+F7()
+F8()
+F9()
+F10()
+F11()
+F12()
+F13()
+F14()
+F15()
+F16()
+F17()
+F18()
+F19()
+F20()
+}
diff --git a/test/dwarf/z1.go b/test/dwarf/z1.go
new file mode 100644
index 000000000..7f163e9a1
--- /dev/null
+++ b/test/dwarf/z1.go
@@ -0,0 +1,5 @@
+
+
+//line x1.go:4
+package main
+func F1() {}
diff --git a/test/dwarf/z10.go b/test/dwarf/z10.go
new file mode 100644
index 000000000..19c70020e
--- /dev/null
+++ b/test/dwarf/z10.go
@@ -0,0 +1,6 @@
+
+
+
+//line x10.go:4
+package main
+func F10() {}
diff --git a/test/dwarf/z11.go b/test/dwarf/z11.go
new file mode 100644
index 000000000..c1d2f9180
--- /dev/null
+++ b/test/dwarf/z11.go
@@ -0,0 +1,4 @@
+
+//line x11.go:4
+package main
+func F11() {}
diff --git a/test/dwarf/z12.go b/test/dwarf/z12.go
new file mode 100644
index 000000000..7455f1894
--- /dev/null
+++ b/test/dwarf/z12.go
@@ -0,0 +1,4 @@
+
+//line x12.go:4
+package main
+func F12() {}
diff --git a/test/dwarf/z13.go b/test/dwarf/z13.go
new file mode 100644
index 000000000..ecb3c4c8c
--- /dev/null
+++ b/test/dwarf/z13.go
@@ -0,0 +1,4 @@
+
+//line x13.go:4
+package main
+func F13() {}
diff --git a/test/dwarf/z14.go b/test/dwarf/z14.go
new file mode 100644
index 000000000..134b39b64
--- /dev/null
+++ b/test/dwarf/z14.go
@@ -0,0 +1,4 @@
+
+//line x14.go:4
+package main
+func F14() {}
diff --git a/test/dwarf/z15.go b/test/dwarf/z15.go
new file mode 100644
index 000000000..d73819b44
--- /dev/null
+++ b/test/dwarf/z15.go
@@ -0,0 +1,4 @@
+
+//line x15.go:4
+package main
+func F15() {}
diff --git a/test/dwarf/z16.go b/test/dwarf/z16.go
new file mode 100644
index 000000000..6c31651ba
--- /dev/null
+++ b/test/dwarf/z16.go
@@ -0,0 +1,4 @@
+
+//line x16.go:4
+package main
+func F16() {}
diff --git a/test/dwarf/z17.go b/test/dwarf/z17.go
new file mode 100644
index 000000000..b742d1672
--- /dev/null
+++ b/test/dwarf/z17.go
@@ -0,0 +1,4 @@
+
+//line x17.go:4
+package main
+func F17() {}
diff --git a/test/dwarf/z18.go b/test/dwarf/z18.go
new file mode 100644
index 000000000..84150ff0a
--- /dev/null
+++ b/test/dwarf/z18.go
@@ -0,0 +1,5 @@
+
+
+//line x18.go:4
+package main
+func F18() {}
diff --git a/test/dwarf/z19.go b/test/dwarf/z19.go
new file mode 100644
index 000000000..bb2e29684
--- /dev/null
+++ b/test/dwarf/z19.go
@@ -0,0 +1,4 @@
+
+//line x19.go:4
+package main
+func F19() {}
diff --git a/test/dwarf/z2.go b/test/dwarf/z2.go
new file mode 100644
index 000000000..68bd58257
--- /dev/null
+++ b/test/dwarf/z2.go
@@ -0,0 +1,4 @@
+
+//line x2.go:4
+package main
+func F2() {}
diff --git a/test/dwarf/z20.go b/test/dwarf/z20.go
new file mode 100644
index 000000000..03111e184
--- /dev/null
+++ b/test/dwarf/z20.go
@@ -0,0 +1,4 @@
+
+//line x20.go:4
+package main
+func F20() {}
diff --git a/test/dwarf/z3.go b/test/dwarf/z3.go
new file mode 100644
index 000000000..5e4ad3ae2
--- /dev/null
+++ b/test/dwarf/z3.go
@@ -0,0 +1,4 @@
+
+//line x3.go:4
+package main
+func F3() {}
diff --git a/test/dwarf/z4.go b/test/dwarf/z4.go
new file mode 100644
index 000000000..1f28465c5
--- /dev/null
+++ b/test/dwarf/z4.go
@@ -0,0 +1,4 @@
+
+//line x4.go:4
+package main
+func F4() {}
diff --git a/test/dwarf/z5.go b/test/dwarf/z5.go
new file mode 100644
index 000000000..7f4eeb419
--- /dev/null
+++ b/test/dwarf/z5.go
@@ -0,0 +1,4 @@
+
+//line x5.go:4
+package main
+func F5() {}
diff --git a/test/dwarf/z6.go b/test/dwarf/z6.go
new file mode 100644
index 000000000..241791dff
--- /dev/null
+++ b/test/dwarf/z6.go
@@ -0,0 +1,4 @@
+
+//line x6.go:4
+package main
+func F6() {}
diff --git a/test/dwarf/z7.go b/test/dwarf/z7.go
new file mode 100644
index 000000000..68c1ad0c2
--- /dev/null
+++ b/test/dwarf/z7.go
@@ -0,0 +1,4 @@
+
+//line x7.go:4
+package main
+func F7() {}
diff --git a/test/dwarf/z8.go b/test/dwarf/z8.go
new file mode 100644
index 000000000..16eed32a2
--- /dev/null
+++ b/test/dwarf/z8.go
@@ -0,0 +1,4 @@
+
+//line x8.go:4
+package main
+func F8() {}
diff --git a/test/dwarf/z9.go b/test/dwarf/z9.go
new file mode 100644
index 000000000..cbb94b4d2
--- /dev/null
+++ b/test/dwarf/z9.go
@@ -0,0 +1,4 @@
+
+//line x9.go:4
+package main
+func F9() {}
diff --git a/test/golden.out b/test/golden.out
index 655ceda56..1618ef68e 100644
--- a/test/golden.out
+++ b/test/golden.out
@@ -124,6 +124,8 @@ panic: interface conversion: *main.S is not main.I2: missing method Name
== syntax/
+== dwarf/
+
== fixedbugs/
=========== fixedbugs/bug027.go
diff --git a/test/run b/test/run
index bc31d2f71..fce4d012f 100755
--- a/test/run
+++ b/test/run
@@ -53,7 +53,7 @@ filterout() {
grep '^'"$2"'$' $1 >/dev/null
}
-for dir in . ken chan interface nilptr syntax fixedbugs bugs
+for dir in . ken chan interface nilptr syntax dwarf fixedbugs bugs
do
echo
echo '==' $dir'/'