aboutsummaryrefslogtreecommitdiff
path: root/libgo/go/text
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@gcc.gnu.org>2012-03-02 16:38:43 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2012-03-02 16:38:43 +0000
commitcbb6491d76c7aa81cdf5d3b3a81386129c5e2fce (patch)
treeefa0c55763b34cbc633bc494c2743d1b5d9aaff3 /libgo/go/text
parentff2f581b00ac6759f6366c16ef902c935163aa13 (diff)
downloadgcc-cbb6491d76c7aa81cdf5d3b3a81386129c5e2fce.zip
gcc-cbb6491d76c7aa81cdf5d3b3a81386129c5e2fce.tar.gz
gcc-cbb6491d76c7aa81cdf5d3b3a81386129c5e2fce.tar.bz2
libgo: Update to weekly.2012-02-14 release.
From-SVN: r184798
Diffstat (limited to 'libgo/go/text')
-rw-r--r--libgo/go/text/scanner/scanner.go7
-rw-r--r--libgo/go/text/template/doc.go6
-rw-r--r--libgo/go/text/template/exec_test.go19
-rw-r--r--libgo/go/text/template/parse/lex.go2
-rw-r--r--libgo/go/text/template/parse/node.go112
-rw-r--r--libgo/go/text/template/parse/parse_test.go18
6 files changed, 146 insertions, 18 deletions
diff --git a/libgo/go/text/scanner/scanner.go b/libgo/go/text/scanner/scanner.go
index f46f63d..565650e 100644
--- a/libgo/go/text/scanner/scanner.go
+++ b/libgo/go/text/scanner/scanner.go
@@ -5,8 +5,7 @@
// Package scanner provides a scanner and tokenizer for UTF-8-encoded text.
// It takes an io.Reader providing the source, which then can be tokenized
// through repeated calls to the Scan function. For compatibility with
-// existing tools, the NUL character is not allowed (implementation
-// restriction).
+// existing tools, the NUL character is not allowed.
//
// By default, a Scanner skips white space and Go comments and recognizes all
// literals as defined by the Go language specification. It may be
@@ -104,7 +103,7 @@ var tokenString = map[rune]string{
Comment: "Comment",
}
-// TokenString returns a (visible) string for a token or Unicode character.
+// TokenString returns a printable string for a token or Unicode character.
func TokenString(tok rune) string {
if s, found := tokenString[tok]; found {
return s
@@ -287,7 +286,7 @@ func (s *Scanner) next() rune {
// special situations
switch ch {
case 0:
- // implementation restriction for compatibility with other tools
+ // for compatibility with other tools
s.error("illegal character NUL")
case '\n':
s.line++
diff --git a/libgo/go/text/template/doc.go b/libgo/go/text/template/doc.go
index 3be1ec4..35c4c68 100644
--- a/libgo/go/text/template/doc.go
+++ b/libgo/go/text/template/doc.go
@@ -3,8 +3,10 @@
// license that can be found in the LICENSE file.
/*
-Package template implements data-driven templates for generating textual output
-such as HTML.
+Package template implements data-driven templates for generating textual output.
+
+To generate HTML output, see package html/template, which has the same interface
+as this package but automatically secures HTML output against certain attacks.
Templates are executed by applying them to a data structure. Annotations in the
template refer to elements of the data structure (typically a field of a struct
diff --git a/libgo/go/text/template/exec_test.go b/libgo/go/text/template/exec_test.go
index 2070cef..9bb55e4 100644
--- a/libgo/go/text/template/exec_test.go
+++ b/libgo/go/text/template/exec_test.go
@@ -9,7 +9,6 @@ import (
"errors"
"flag"
"fmt"
- "os"
"reflect"
"strings"
"testing"
@@ -168,10 +167,12 @@ func (t *T) MAdd(a int, b []int) []int {
return v
}
-// EPERM returns a value and an error according to its argument.
-func (t *T) EPERM(error bool) (bool, error) {
+var myError = errors.New("my error")
+
+// MyError returns a value and an error according to its argument.
+func (t *T) MyError(error bool) (bool, error) {
if error {
- return true, os.EPERM
+ return true, myError
}
return false, nil
}
@@ -417,8 +418,8 @@ var execTests = []execTest{
{"or as if false", `{{or .SIEmpty "slice is empty"}}`, "slice is empty", tVal, true},
// Error handling.
- {"error method, error", "{{.EPERM true}}", "", tVal, false},
- {"error method, no error", "{{.EPERM false}}", "false", tVal, true},
+ {"error method, error", "{{.MyError true}}", "", tVal, false},
+ {"error method, no error", "{{.MyError false}}", "false", tVal, true},
// Fixed bugs.
// Must separate dot and receiver; otherwise args are evaluated with dot set to variable.
@@ -565,18 +566,18 @@ func TestDelims(t *testing.T) {
func TestExecuteError(t *testing.T) {
b := new(bytes.Buffer)
tmpl := New("error")
- _, err := tmpl.Parse("{{.EPERM true}}")
+ _, err := tmpl.Parse("{{.MyError true}}")
if err != nil {
t.Fatalf("parse error: %s", err)
}
err = tmpl.Execute(b, tVal)
if err == nil {
t.Errorf("expected error; got none")
- } else if !strings.Contains(err.Error(), os.EPERM.Error()) {
+ } else if !strings.Contains(err.Error(), myError.Error()) {
if *debug {
fmt.Printf("test execute error: %s\n", err)
}
- t.Errorf("expected os.EPERM; got %s", err)
+ t.Errorf("expected myError; got %s", err)
}
}
diff --git a/libgo/go/text/template/parse/lex.go b/libgo/go/text/template/parse/lex.go
index 97c19a1..54e75ee 100644
--- a/libgo/go/text/template/parse/lex.go
+++ b/libgo/go/text/template/parse/lex.go
@@ -187,7 +187,7 @@ func (l *lexer) lineNumber() int {
}
// error returns an error token and terminates the scan by passing
-// back a nil pointer that will be the next state, terminating l.run.
+// back a nil pointer that will be the next state, terminating l.nextItem.
func (l *lexer) errorf(format string, args ...interface{}) stateFn {
l.items <- item{itemError, fmt.Sprintf(format, args...)}
return nil
diff --git a/libgo/go/text/template/parse/node.go b/libgo/go/text/template/parse/node.go
index 0d030b8..db64562 100644
--- a/libgo/go/text/template/parse/node.go
+++ b/libgo/go/text/template/parse/node.go
@@ -17,6 +17,10 @@ import (
type Node interface {
Type() NodeType
String() string
+ // Copy does a deep copy of the Node and all its components.
+ // To avoid type assertions, some XxxNodes also have specialized
+ // CopyXxx methods that return *XxxNode.
+ Copy() Node
}
// NodeType identifies the type of a parse tree node.
@@ -73,6 +77,21 @@ func (l *ListNode) String() string {
return b.String()
}
+func (l *ListNode) CopyList() *ListNode {
+ if l == nil {
+ return l
+ }
+ n := newList()
+ for _, elem := range l.Nodes {
+ n.append(elem.Copy())
+ }
+ return n
+}
+
+func (l *ListNode) Copy() Node {
+ return l.CopyList()
+}
+
// TextNode holds plain text.
type TextNode struct {
NodeType
@@ -87,6 +106,10 @@ func (t *TextNode) String() string {
return fmt.Sprintf("%q", t.Text)
}
+func (t *TextNode) Copy() Node {
+ return &TextNode{NodeType: NodeText, Text: append([]byte{}, t.Text...)}
+}
+
// PipeNode holds a pipeline with optional declaration
type PipeNode struct {
NodeType
@@ -123,6 +146,25 @@ func (p *PipeNode) String() string {
return s
}
+func (p *PipeNode) CopyPipe() *PipeNode {
+ if p == nil {
+ return p
+ }
+ var decl []*VariableNode
+ for _, d := range p.Decl {
+ decl = append(decl, d.Copy().(*VariableNode))
+ }
+ n := newPipeline(p.Line, decl)
+ for _, c := range p.Cmds {
+ n.append(c.Copy().(*CommandNode))
+ }
+ return n
+}
+
+func (p *PipeNode) Copy() Node {
+ return p.CopyPipe()
+}
+
// ActionNode holds an action (something bounded by delimiters).
// Control actions have their own nodes; ActionNode represents simple
// ones such as field evaluations.
@@ -141,6 +183,11 @@ func (a *ActionNode) String() string {
}
+func (a *ActionNode) Copy() Node {
+ return newAction(a.Line, a.Pipe.CopyPipe())
+
+}
+
// CommandNode holds a command (a pipeline inside an evaluating action).
type CommandNode struct {
NodeType
@@ -166,6 +213,17 @@ func (c *CommandNode) String() string {
return s
}
+func (c *CommandNode) Copy() Node {
+ if c == nil {
+ return c
+ }
+ n := newCommand()
+ for _, c := range c.Args {
+ n.append(c.Copy())
+ }
+ return n
+}
+
// IdentifierNode holds an identifier.
type IdentifierNode struct {
NodeType
@@ -181,6 +239,10 @@ func (i *IdentifierNode) String() string {
return i.Ident
}
+func (i *IdentifierNode) Copy() Node {
+ return NewIdentifier(i.Ident)
+}
+
// VariableNode holds a list of variable names. The dollar sign is
// part of the name.
type VariableNode struct {
@@ -203,6 +265,10 @@ func (v *VariableNode) String() string {
return s
}
+func (v *VariableNode) Copy() Node {
+ return &VariableNode{NodeType: NodeVariable, Ident: append([]string{}, v.Ident...)}
+}
+
// DotNode holds the special identifier '.'. It is represented by a nil pointer.
type DotNode bool
@@ -218,6 +284,10 @@ func (d *DotNode) String() string {
return "."
}
+func (d *DotNode) Copy() Node {
+ return newDot()
+}
+
// FieldNode holds a field (identifier starting with '.').
// The names may be chained ('.x.y').
// The period is dropped from each ident.
@@ -238,6 +308,10 @@ func (f *FieldNode) String() string {
return s
}
+func (f *FieldNode) Copy() Node {
+ return &FieldNode{NodeType: NodeField, Ident: append([]string{}, f.Ident...)}
+}
+
// BoolNode holds a boolean constant.
type BoolNode struct {
NodeType
@@ -255,6 +329,10 @@ func (b *BoolNode) String() string {
return "false"
}
+func (b *BoolNode) Copy() Node {
+ return newBool(b.True)
+}
+
// NumberNode holds a number: signed or unsigned integer, float, or complex.
// The value is parsed and stored under all the types that can represent the value.
// This simulates in a small amount of code the behavior of Go's ideal constants.
@@ -373,6 +451,12 @@ func (n *NumberNode) String() string {
return n.Text
}
+func (n *NumberNode) Copy() Node {
+ nn := new(NumberNode)
+ *nn = *n // Easy, fast, correct.
+ return nn
+}
+
// StringNode holds a string constant. The value has been "unquoted".
type StringNode struct {
NodeType
@@ -388,6 +472,10 @@ func (s *StringNode) String() string {
return s.Quoted
}
+func (s *StringNode) Copy() Node {
+ return newString(s.Quoted, s.Text)
+}
+
// endNode represents an {{end}} action. It is represented by a nil pointer.
// It does not appear in the final parse tree.
type endNode bool
@@ -404,6 +492,10 @@ func (e *endNode) String() string {
return "{{end}}"
}
+func (e *endNode) Copy() Node {
+ return newEnd()
+}
+
// elseNode represents an {{else}} action. Does not appear in the final tree.
type elseNode struct {
NodeType
@@ -422,6 +514,10 @@ func (e *elseNode) String() string {
return "{{else}}"
}
+func (e *elseNode) Copy() Node {
+ return newElse(e.Line)
+}
+
// BranchNode is the common representation of if, range, and with.
type BranchNode struct {
NodeType
@@ -458,6 +554,10 @@ func newIf(line int, pipe *PipeNode, list, elseList *ListNode) *IfNode {
return &IfNode{BranchNode{NodeType: NodeIf, Line: line, Pipe: pipe, List: list, ElseList: elseList}}
}
+func (i *IfNode) Copy() Node {
+ return newIf(i.Line, i.Pipe.CopyPipe(), i.List.CopyList(), i.ElseList.CopyList())
+}
+
// RangeNode represents a {{range}} action and its commands.
type RangeNode struct {
BranchNode
@@ -467,6 +567,10 @@ func newRange(line int, pipe *PipeNode, list, elseList *ListNode) *RangeNode {
return &RangeNode{BranchNode{NodeType: NodeRange, Line: line, Pipe: pipe, List: list, ElseList: elseList}}
}
+func (r *RangeNode) Copy() Node {
+ return newRange(r.Line, r.Pipe.CopyPipe(), r.List.CopyList(), r.ElseList.CopyList())
+}
+
// WithNode represents a {{with}} action and its commands.
type WithNode struct {
BranchNode
@@ -476,6 +580,10 @@ func newWith(line int, pipe *PipeNode, list, elseList *ListNode) *WithNode {
return &WithNode{BranchNode{NodeType: NodeWith, Line: line, Pipe: pipe, List: list, ElseList: elseList}}
}
+func (w *WithNode) Copy() Node {
+ return newWith(w.Line, w.Pipe.CopyPipe(), w.List.CopyList(), w.ElseList.CopyList())
+}
+
// TemplateNode represents a {{template}} action.
type TemplateNode struct {
NodeType
@@ -494,3 +602,7 @@ func (t *TemplateNode) String() string {
}
return fmt.Sprintf("{{template %q %s}}", t.Name, t.Pipe)
}
+
+func (t *TemplateNode) Copy() Node {
+ return newTemplate(t.Line, t.Name, t.Pipe.CopyPipe())
+}
diff --git a/libgo/go/text/template/parse/parse_test.go b/libgo/go/text/template/parse/parse_test.go
index 13c5548..efa7d8b 100644
--- a/libgo/go/text/template/parse/parse_test.go
+++ b/libgo/go/text/template/parse/parse_test.go
@@ -232,7 +232,7 @@ var builtins = map[string]interface{}{
"printf": fmt.Sprintf,
}
-func TestParse(t *testing.T) {
+func testParse(doCopy bool, t *testing.T) {
for _, test := range parseTests {
tmpl, err := New(test.name).Parse(test.input, "", "", make(map[string]*Tree), builtins)
switch {
@@ -249,13 +249,27 @@ func TestParse(t *testing.T) {
}
continue
}
- result := tmpl.Root.String()
+ var result string
+ if doCopy {
+ result = tmpl.Root.Copy().String()
+ } else {
+ result = tmpl.Root.String()
+ }
if result != test.result {
t.Errorf("%s=(%q): got\n\t%v\nexpected\n\t%v", test.name, test.input, result, test.result)
}
}
}
+func TestParse(t *testing.T) {
+ testParse(false, t)
+}
+
+// Same as TestParse, but we copy the node first
+func TestParseCopy(t *testing.T) {
+ testParse(true, t)
+}
+
type isEmptyTest struct {
name string
input string