diff options
author | Ian Lance Taylor <ian@gcc.gnu.org> | 2012-03-02 16:38:43 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2012-03-02 16:38:43 +0000 |
commit | cbb6491d76c7aa81cdf5d3b3a81386129c5e2fce (patch) | |
tree | efa0c55763b34cbc633bc494c2743d1b5d9aaff3 /libgo/go/text | |
parent | ff2f581b00ac6759f6366c16ef902c935163aa13 (diff) | |
download | gcc-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.go | 7 | ||||
-rw-r--r-- | libgo/go/text/template/doc.go | 6 | ||||
-rw-r--r-- | libgo/go/text/template/exec_test.go | 19 | ||||
-rw-r--r-- | libgo/go/text/template/parse/lex.go | 2 | ||||
-rw-r--r-- | libgo/go/text/template/parse/node.go | 112 | ||||
-rw-r--r-- | libgo/go/text/template/parse/parse_test.go | 18 |
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 |