Commit 2cf66c1d authored by Rob Pike's avatar Rob Pike

template: fix deadlock.

No need for lexInsideAction to loop.
Fixes #2217.

R=golang-dev, bradfitz
CC=golang-dev
https://golang.org/cl/4963054
parent 5edeef21
...@@ -278,53 +278,51 @@ func lexInsideAction(l *lexer) stateFn { ...@@ -278,53 +278,51 @@ func lexInsideAction(l *lexer) stateFn {
// Either number, quoted string, or identifier. // Either number, quoted string, or identifier.
// Spaces separate and are ignored. // Spaces separate and are ignored.
// Pipe symbols separate and are emitted. // Pipe symbols separate and are emitted.
for { if strings.HasPrefix(l.input[l.pos:], rightDelim) {
if strings.HasPrefix(l.input[l.pos:], rightDelim) { return lexRightDelim
return lexRightDelim }
switch r := l.next(); {
case r == eof || r == '\n':
return l.errorf("unclosed action")
case isSpace(r):
l.ignore()
case r == ':':
if l.next() != '=' {
return l.errorf("expected :=")
} }
switch r := l.next(); { l.emit(itemColonEquals)
case r == eof || r == '\n': case r == '|':
return l.errorf("unclosed action") l.emit(itemPipe)
case isSpace(r): case r == '"':
l.ignore() return lexQuote
case r == ':': case r == '`':
if l.next() != '=' { return lexRawQuote
return l.errorf("expected :=") case r == '$':
return lexIdentifier
case r == '\'':
return lexChar
case r == '.':
// special look-ahead for ".field" so we don't break l.backup().
if l.pos < len(l.input) {
r := l.input[l.pos]
if r < '0' || '9' < r {
return lexIdentifier // itemDot comes from the keyword table.
} }
l.emit(itemColonEquals)
case r == '|':
l.emit(itemPipe)
case r == '"':
return lexQuote
case r == '`':
return lexRawQuote
case r == '$':
return lexIdentifier
case r == '\'':
return lexChar
case r == '.':
// special look-ahead for ".field" so we don't break l.backup().
if l.pos < len(l.input) {
r := l.input[l.pos]
if r < '0' || '9' < r {
return lexIdentifier // itemDot comes from the keyword table.
}
}
fallthrough // '.' can start a number.
case r == '+' || r == '-' || ('0' <= r && r <= '9'):
l.backup()
return lexNumber
case isAlphaNumeric(r):
l.backup()
return lexIdentifier
case r <= unicode.MaxASCII && unicode.IsPrint(r):
l.emit(itemChar)
return lexInsideAction
default:
return l.errorf("unrecognized character in action: %#U", r)
} }
fallthrough // '.' can start a number.
case r == '+' || r == '-' || ('0' <= r && r <= '9'):
l.backup()
return lexNumber
case isAlphaNumeric(r):
l.backup()
return lexIdentifier
case r <= unicode.MaxASCII && unicode.IsPrint(r):
l.emit(itemChar)
return lexInsideAction
default:
return l.errorf("unrecognized character in action: %#U", r)
} }
return nil return lexInsideAction
} }
// lexIdentifier scans an alphanumeric or field. // lexIdentifier scans an alphanumeric or field.
......
...@@ -184,6 +184,20 @@ var lexTests = []lexTest{ ...@@ -184,6 +184,20 @@ var lexTests = []lexTest{
tLeft, tLeft,
{itemError, `bad number syntax: "3k"`}, {itemError, `bad number syntax: "3k"`},
}}, }},
// Fixed bugs
// Many elements in an action blew the lookahead until
// we made lexInsideAction not loop.
{"long pipeline deadlock", "{{|||||}}", []item{
tLeft,
tPipe,
tPipe,
tPipe,
tPipe,
tPipe,
tRight,
tEOF,
}},
} }
// collect gathers the emitted items into a slice. // collect gathers the emitted items into a slice.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment