diff --git a/circle.yml b/circle.yml index 3b3c9171c6..84d02dc1ab 100644 --- a/circle.yml +++ b/circle.yml @@ -19,7 +19,7 @@ dependencies: github.com/fzipp/gocyclo \ github.com/golang/lint/golint \ github.com/kisielk/errcheck \ - ./vendor/github.com/mvdan/sh/cmd/shfmt + gopkg.in/mvdan/sh.v1/cmd/shfmt test: override: diff --git a/vendor/github.com/mvdan/sh/LICENSE b/vendor/github.com/mvdan/sh/LICENSE deleted file mode 100644 index 7d71d51a5e..0000000000 --- a/vendor/github.com/mvdan/sh/LICENSE +++ /dev/null @@ -1,27 +0,0 @@ -Copyright (c) 2015, Daniel Martí. 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 the copyright holder 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/vendor/github.com/mvdan/sh/cmd/shfmt/main.go b/vendor/github.com/mvdan/sh/cmd/shfmt/main.go deleted file mode 100644 index 08f99e0139..0000000000 --- a/vendor/github.com/mvdan/sh/cmd/shfmt/main.go +++ /dev/null @@ -1,202 +0,0 @@ -// Copyright (c) 2016, Daniel Martí -// See LICENSE for licensing information - -package main - -import ( - "bytes" - "flag" - "fmt" - "io" - "log" - "os" - "path/filepath" - "regexp" - "runtime/pprof" - "strings" - - "github.com/mvdan/sh/syntax" -) - -var ( - write = flag.Bool("w", false, "write result to file instead of stdout") - list = flag.Bool("l", false, "list files whose formatting differs from shfmt's") - indent = flag.Int("i", 0, "indent: 0 for tabs (default), >0 for number of spaces") - posix = flag.Bool("p", false, "parse POSIX shell code instead of bash") - cpuprofile = flag.String("cpuprofile", "", "write cpu profile to file") - - parseMode syntax.ParseMode - printConfig syntax.PrintConfig - readBuf, writeBuf bytes.Buffer - - out io.Writer -) - -func main() { - flag.Parse() - if *cpuprofile != "" { - f, err := os.Create(*cpuprofile) - if err != nil { - log.Fatal(err) - } - pprof.StartCPUProfile(f) - defer pprof.StopCPUProfile() - } - - out = os.Stdout - printConfig.Spaces = *indent - parseMode |= syntax.ParseComments - if *posix { - parseMode |= syntax.PosixConformant - } - if flag.NArg() == 0 { - if err := formatStdin(); err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(1) - } - return - } - anyErr := false - onError := func(err error) { - anyErr = true - fmt.Fprintln(os.Stderr, err) - } - for _, path := range flag.Args() { - walk(path, onError) - } - if anyErr { - os.Exit(1) - } -} - -func formatStdin() error { - if *write || *list { - return fmt.Errorf("-w and -l can only be used on files") - } - readBuf.Reset() - if _, err := io.Copy(&readBuf, os.Stdin); err != nil { - return err - } - src := readBuf.Bytes() - prog, err := syntax.Parse(src, "", parseMode) - if err != nil { - return err - } - return printConfig.Fprint(out, prog) -} - -var ( - shellFile = regexp.MustCompile(`\.(sh|bash)$`) - validShebang = regexp.MustCompile(`^#!\s?/(usr/)?bin/(env *)?(sh|bash)`) - vcsDir = regexp.MustCompile(`^\.(git|svn|hg)$`) -) - -type shellConfidence int - -const ( - notShellFile shellConfidence = iota - ifValidShebang - isShellFile -) - -func getConfidence(info os.FileInfo) shellConfidence { - name := info.Name() - switch { - case info.IsDir(), name[0] == '.', !info.Mode().IsRegular(): - return notShellFile - case shellFile.MatchString(name): - return isShellFile - case strings.Contains(name, "."): - return notShellFile // different extension - case info.Size() < 8: - return notShellFile // cannot possibly hold valid shebang - default: - return ifValidShebang - } -} - -func walk(path string, onError func(error)) { - info, err := os.Stat(path) - if err != nil { - onError(err) - return - } - if !info.IsDir() { - if err := formatPath(path, false); err != nil { - onError(err) - } - return - } - filepath.Walk(path, func(path string, info os.FileInfo, err error) error { - if info.IsDir() && vcsDir.MatchString(info.Name()) { - return filepath.SkipDir - } - if err != nil { - onError(err) - return nil - } - conf := getConfidence(info) - if conf == notShellFile { - return nil - } - err = formatPath(path, conf == ifValidShebang) - if err != nil && !os.IsNotExist(err) { - onError(err) - } - return nil - }) -} - -func empty(f *os.File) error { - if err := f.Truncate(0); err != nil { - return err - } - _, err := f.Seek(0, 0) - return err -} - -func formatPath(path string, checkShebang bool) error { - openMode := os.O_RDONLY - if *write { - openMode = os.O_RDWR - } - f, err := os.OpenFile(path, openMode, 0) - if err != nil { - return err - } - defer f.Close() - readBuf.Reset() - if _, err := io.Copy(&readBuf, f); err != nil { - return err - } - src := readBuf.Bytes() - if checkShebang && !validShebang.Match(src[:32]) { - return nil - } - prog, err := syntax.Parse(src, path, parseMode) - if err != nil { - return err - } - writeBuf.Reset() - printConfig.Fprint(&writeBuf, prog) - res := writeBuf.Bytes() - if !bytes.Equal(src, res) { - if *list { - fmt.Fprintln(out, path) - } - if *write { - if err := empty(f); err != nil { - return err - } - if _, err := f.Write(res); err != nil { - return err - } - } - } - if !*list && !*write { - if _, err := out.Write(res); err != nil { - return err - } - } - return nil -} diff --git a/vendor/github.com/mvdan/sh/syntax/doc.go b/vendor/github.com/mvdan/sh/syntax/doc.go deleted file mode 100644 index eff8c2fecc..0000000000 --- a/vendor/github.com/mvdan/sh/syntax/doc.go +++ /dev/null @@ -1,6 +0,0 @@ -// Copyright (c) 2016, Daniel Martí -// See LICENSE for licensing information - -// Package syntax implements parsing and formatting of shell programs. -// It supports both POSIX Shell and Bash. -package syntax diff --git a/vendor/github.com/mvdan/sh/syntax/lexer.go b/vendor/github.com/mvdan/sh/syntax/lexer.go deleted file mode 100644 index 8b5cbd3a14..0000000000 --- a/vendor/github.com/mvdan/sh/syntax/lexer.go +++ /dev/null @@ -1,962 +0,0 @@ -// Copyright (c) 2016, Daniel Martí -// See LICENSE for licensing information - -package syntax - -import ( - "bytes" -) - -// bytes that form or start a token -func regOps(b byte) bool { - return b == ';' || b == '"' || b == '\'' || b == '(' || - b == ')' || b == '$' || b == '|' || b == '&' || - b == '>' || b == '<' || b == '`' -} - -// tokenize these inside parameter expansions -func paramOps(b byte) bool { - return b == '}' || b == '#' || b == ':' || b == '-' || b == '+' || - b == '=' || b == '?' || b == '%' || b == '[' || b == '/' || - b == '^' || b == ',' -} - -// tokenize these inside arithmetic expansions -func arithmOps(b byte) bool { - return b == '+' || b == '-' || b == '!' || b == '*' || - b == '/' || b == '%' || b == '(' || b == ')' || - b == '^' || b == '<' || b == '>' || b == ':' || - b == '=' || b == ',' || b == '?' || b == '|' || - b == '&' -} - -func wordBreak(b byte) bool { - return b == ' ' || b == '\t' || b == '\r' || b == '\n' || - b == '&' || b == '>' || b == '<' || b == '|' || - b == ';' || b == '(' || b == ')' -} - -func (p *parser) next() { - if p.tok == _EOF || p.npos >= len(p.src) { - p.tok = _EOF - return - } - p.spaced, p.newLine = false, false - b, q := p.src[p.npos], p.quote - p.pos = Pos(p.npos + 1) - switch q { - case hdocWord: - if wordBreak(b) { - p.tok = illegalTok - p.spaced = true - return - } - case paramExpRepl: - switch b { - case '}': - p.npos++ - p.tok = rightBrace - case '/': - p.npos++ - p.tok = Quo - case '`', '"', '$': - p.tok = p.dqToken(b) - default: - p.advanceLitOther(q) - } - return - case dblQuotes: - if b == '`' || b == '"' || b == '$' { - p.tok = p.dqToken(b) - } else { - p.advanceLitDquote() - } - return - case hdocBody, hdocBodyTabs: - if b == '`' || b == '$' { - p.tok = p.dqToken(b) - } else if p.hdocStop == nil { - p.tok = illegalTok - } else { - p.advanceLitHdoc() - } - return - case paramExpExp: - switch b { - case '}': - p.npos++ - p.tok = rightBrace - case '`', '"', '$': - p.tok = p.dqToken(b) - default: - p.advanceLitOther(q) - } - return - case sglQuotes: - if b == '\'' { - p.npos++ - p.tok = sglQuote - } else { - p.advanceLitOther(q) - } - return - } -skipSpace: - for { - switch b { - case ' ', '\t', '\r': - p.spaced = true - p.npos++ - case '\n': - if p.quote == arithmExprLet { - p.tok = illegalTok - p.newLine, p.spaced = true, true - return - } - p.spaced = true - if p.npos < len(p.src) { - p.npos++ - } - p.f.Lines = append(p.f.Lines, p.npos) - p.newLine = true - if len(p.heredocs) > p.buriedHdocs { - p.doHeredocs() - if p.tok == _EOF { - return - } - } - case '\\': - if p.npos < len(p.src)-1 && p.src[p.npos+1] == '\n' { - p.npos += 2 - p.f.Lines = append(p.f.Lines, p.npos) - } else { - break skipSpace - } - default: - break skipSpace - } - if p.npos >= len(p.src) { - p.tok = _EOF - return - } - b = p.src[p.npos] - } - p.pos = Pos(p.npos + 1) - switch { - case q&allRegTokens != 0: - switch b { - case ';', '"', '\'', '(', ')', '$', '|', '&', '>', '<', '`': - p.tok = p.regToken(b) - case '#': - p.npos++ - bs, _ := p.readUntil('\n') - p.npos += len(bs) - if p.mode&ParseComments > 0 { - p.f.Comments = append(p.f.Comments, &Comment{ - Hash: p.pos, - Text: string(bs), - }) - } - p.next() - case '?', '*', '+', '@', '!': - if p.bash() && p.npos+1 < len(p.src) && p.src[p.npos+1] == '(' { - switch b { - case '?': - p.tok = globQuest - case '*': - p.tok = globMul - case '+': - p.tok = globAdd - case '@': - p.tok = globAt - default: // '!' - p.tok = globNot - } - p.npos += 2 - } else { - p.advanceLitNone() - } - default: - p.advanceLitNone() - } - case q == paramExpName && paramOps(b): - p.tok = p.paramToken(b) - case q&allArithmExpr != 0 && arithmOps(b): - p.tok = p.arithmToken(b) - case q&allRbrack != 0 && b == ']': - p.npos++ - p.tok = rightBrack - case q == testRegexp: - p.advanceLitRe() - case regOps(b): - p.tok = p.regToken(b) - default: - p.advanceLitOther(q) - } -} - -func byteAt(src []byte, i int) byte { - if i >= len(src) { - return 0 - } - return src[i] -} - -func (p *parser) regToken(b byte) Token { - switch b { - case '\'': - p.npos++ - return sglQuote - case '"': - p.npos++ - return dblQuote - case '`': - p.npos++ - return bckQuote - case '&': - switch byteAt(p.src, p.npos+1) { - case '&': - p.npos += 2 - return AndExpr - case '>': - if !p.bash() { - break - } - if byteAt(p.src, p.npos+2) == '>' { - p.npos += 3 - return appAll - } - p.npos += 2 - return rdrAll - } - p.npos++ - return And - case '|': - switch byteAt(p.src, p.npos+1) { - case '|': - p.npos += 2 - return OrExpr - case '&': - if !p.bash() { - break - } - p.npos += 2 - return pipeAll - } - p.npos++ - return Or - case '$': - switch byteAt(p.src, p.npos+1) { - case '\'': - if !p.bash() { - break - } - p.npos += 2 - return dollSglQuote - case '"': - if !p.bash() { - break - } - p.npos += 2 - return dollDblQuote - case '{': - p.npos += 2 - return dollBrace - case '[': - if !p.bash() { - break - } - p.npos += 2 - return dollBrack - case '(': - if byteAt(p.src, p.npos+2) == '(' { - p.npos += 3 - return dollDblParen - } - p.npos += 2 - return dollParen - } - p.npos++ - return dollar - case '(': - if p.bash() && byteAt(p.src, p.npos+1) == '(' { - p.npos += 2 - return dblLeftParen - } - p.npos++ - return leftParen - case ')': - p.npos++ - return rightParen - case ';': - switch byteAt(p.src, p.npos+1) { - case ';': - if p.bash() && byteAt(p.src, p.npos+2) == '&' { - p.npos += 3 - return dblSemiFall - } - p.npos += 2 - return dblSemicolon - case '&': - if !p.bash() { - break - } - p.npos += 2 - return semiFall - } - p.npos++ - return semicolon - case '<': - switch byteAt(p.src, p.npos+1) { - case '<': - if b := byteAt(p.src, p.npos+2); b == '-' { - p.npos += 3 - return dashHdoc - } else if p.bash() && b == '<' { - p.npos += 3 - return wordHdoc - } - p.npos += 2 - return Shl - case '>': - p.npos += 2 - return rdrInOut - case '&': - p.npos += 2 - return dplIn - case '(': - if !p.bash() { - break - } - p.npos += 2 - return cmdIn - } - p.npos++ - return Lss - default: // '>' - switch byteAt(p.src, p.npos+1) { - case '>': - p.npos += 2 - return Shr - case '&': - p.npos += 2 - return dplOut - case '|': - p.npos += 2 - return clbOut - case '(': - if !p.bash() { - break - } - p.npos += 2 - return cmdOut - } - p.npos++ - return Gtr - } -} - -func (p *parser) dqToken(b byte) Token { - switch b { - case '"': - p.npos++ - return dblQuote - case '`': - p.npos++ - return bckQuote - default: // '$' - switch byteAt(p.src, p.npos+1) { - case '{': - p.npos += 2 - return dollBrace - case '[': - if !p.bash() { - break - } - p.npos += 2 - return dollBrack - case '(': - if byteAt(p.src, p.npos+2) == '(' { - p.npos += 3 - return dollDblParen - } - p.npos += 2 - return dollParen - } - p.npos++ - return dollar - } -} - -func (p *parser) paramToken(b byte) Token { - switch b { - case '}': - p.npos++ - return rightBrace - case ':': - switch byteAt(p.src, p.npos+1) { - case '+': - p.npos += 2 - return ColAdd - case '-': - p.npos += 2 - return ColSub - case '?': - p.npos += 2 - return ColQuest - case '=': - p.npos += 2 - return ColAssgn - } - p.npos++ - return Colon - case '+': - p.npos++ - return Add - case '-': - p.npos++ - return Sub - case '?': - p.npos++ - return Quest - case '=': - p.npos++ - return Assgn - case '%': - if byteAt(p.src, p.npos+1) == '%' { - p.npos += 2 - return dblRem - } - p.npos++ - return Rem - case '#': - if byteAt(p.src, p.npos+1) == '#' { - p.npos += 2 - return dblHash - } - p.npos++ - return Hash - case '[': - p.npos++ - return leftBrack - case '^': - if byteAt(p.src, p.npos+1) == '^' { - p.npos += 2 - return dblXor - } - p.npos++ - return Xor - case ',': - if byteAt(p.src, p.npos+1) == ',' { - p.npos += 2 - return dblComma - } - p.npos++ - return Comma - default: // '/' - if byteAt(p.src, p.npos+1) == '/' { - p.npos += 2 - return dblQuo - } - p.npos++ - return Quo - } -} - -func (p *parser) arithmToken(b byte) Token { - switch b { - case '!': - if byteAt(p.src, p.npos+1) == '=' { - p.npos += 2 - return Neq - } - p.npos++ - return Not - case '=': - if byteAt(p.src, p.npos+1) == '=' { - p.npos += 2 - return Eql - } - p.npos++ - return Assgn - case '(': - p.npos++ - return leftParen - case ')': - p.npos++ - return rightParen - case '&': - switch byteAt(p.src, p.npos+1) { - case '&': - p.npos += 2 - return AndExpr - case '=': - p.npos += 2 - return AndAssgn - } - p.npos++ - return And - case '|': - switch byteAt(p.src, p.npos+1) { - case '|': - p.npos += 2 - return OrExpr - case '=': - p.npos += 2 - return OrAssgn - } - p.npos++ - return Or - case '<': - switch byteAt(p.src, p.npos+1) { - case '<': - if byteAt(p.src, p.npos+2) == '=' { - p.npos += 3 - return ShlAssgn - } - p.npos += 2 - return Shl - case '=': - p.npos += 2 - return Leq - } - p.npos++ - return Lss - case '>': - switch byteAt(p.src, p.npos+1) { - case '>': - if byteAt(p.src, p.npos+2) == '=' { - p.npos += 3 - return ShrAssgn - } - p.npos += 2 - return Shr - case '=': - p.npos += 2 - return Geq - } - p.npos++ - return Gtr - case '+': - switch byteAt(p.src, p.npos+1) { - case '+': - p.npos += 2 - return Inc - case '=': - p.npos += 2 - return AddAssgn - } - p.npos++ - return Add - case '-': - switch byteAt(p.src, p.npos+1) { - case '-': - p.npos += 2 - return Dec - case '=': - p.npos += 2 - return SubAssgn - } - p.npos++ - return Sub - case '%': - if byteAt(p.src, p.npos+1) == '=' { - p.npos += 2 - return RemAssgn - } - p.npos++ - return Rem - case '*': - switch byteAt(p.src, p.npos+1) { - case '*': - p.npos += 2 - return Pow - case '=': - p.npos += 2 - return MulAssgn - } - p.npos++ - return Mul - case '/': - if byteAt(p.src, p.npos+1) == '=' { - p.npos += 2 - return QuoAssgn - } - p.npos++ - return Quo - case '^': - if byteAt(p.src, p.npos+1) == '=' { - p.npos += 2 - return XorAssgn - } - p.npos++ - return Xor - case ',': - p.npos++ - return Comma - case '?': - p.npos++ - return Quest - default: // ':' - p.npos++ - return Colon - } -} - -func (p *parser) advanceLitOther(q quoteState) { - bs := p.litBuf[:0] - for { - if p.npos >= len(p.src) { - p.tok, p.val = _LitWord, string(bs) - return - } - b := p.src[p.npos] - switch { - case b == '\\': // escaped byte follows - if p.npos == len(p.src)-1 { - p.npos++ - bs = append(bs, '\\') - p.tok, p.val = _LitWord, string(bs) - return - } - b = p.src[p.npos+1] - p.npos += 2 - if b == '\n' { - p.f.Lines = append(p.f.Lines, p.npos) - } else { - bs = append(bs, '\\', b) - } - continue - case q == sglQuotes: - switch b { - case '\n': - p.f.Lines = append(p.f.Lines, p.npos+1) - case '\'': - p.tok, p.val = _LitWord, string(bs) - return - } - case b == '`', b == '$': - p.tok, p.val = _Lit, string(bs) - return - case q == paramExpExp: - if b == '}' { - p.tok, p.val = _LitWord, string(bs) - return - } else if b == '"' { - p.tok, p.val = _Lit, string(bs) - return - } - case q == paramExpRepl: - if b == '}' || b == '/' { - p.tok, p.val = _LitWord, string(bs) - return - } - case wordBreak(b), regOps(b), q&allArithmExpr != 0 && arithmOps(b), - q == paramExpName && paramOps(b), - q&allRbrack != 0 && b == ']': - p.tok, p.val = _LitWord, string(bs) - return - } - bs = append(bs, p.src[p.npos]) - p.npos++ - } -} - -func (p *parser) advanceLitNone() { - var i int - tok := _Lit - p.asPos = 0 -loop: - for i = p.npos; i < len(p.src); i++ { - switch p.src[i] { - case '\\': // escaped byte follows - if i == len(p.src)-1 { - break - } - if i++; p.src[i] == '\n' { - p.f.Lines = append(p.f.Lines, i+1) - bs := p.src[p.npos : i-1] - p.npos = i + 1 - p.advanceLitNoneCont(bs) - return - } - case ' ', '\t', '\n', '\r', '&', '>', '<', '|', ';', '(', ')': - tok = _LitWord - break loop - case '?', '*', '+', '@', '!': - if p.bash() && i+1 < len(p.src) && p.src[i+1] == '(' { - break loop - } - case '`': - if p.quote == subCmdBckquo { - tok = _LitWord - } - break loop - case '"', '\'', '$': - break loop - case '=': - p.asPos = i - p.npos - if p.bash() && p.asPos > 0 && p.src[p.npos+p.asPos-1] == '+' { - p.asPos-- // a+=b - } - } - } - if i == len(p.src) { - tok = _LitWord - } - p.tok, p.val = tok, string(p.src[p.npos:i]) - p.npos = i -} - -func (p *parser) advanceLitNoneCont(bs []byte) { - for { - if p.npos >= len(p.src) { - p.tok, p.val = _LitWord, string(bs) - return - } - switch p.src[p.npos] { - case '\\': // escaped byte follows - if p.npos == len(p.src)-1 { - p.npos++ - bs = append(bs, '\\') - p.tok, p.val = _LitWord, string(bs) - return - } - b := p.src[p.npos+1] - p.npos += 2 - if b == '\n' { - p.f.Lines = append(p.f.Lines, p.npos) - } else { - bs = append(bs, '\\', b) - } - case ' ', '\t', '\n', '\r', '&', '>', '<', '|', ';', '(', ')': - p.tok, p.val = _LitWord, string(bs) - return - case '`': - if p.quote == subCmdBckquo { - p.tok, p.val = _LitWord, string(bs) - return - } - fallthrough - case '"', '\'', '$': - p.tok, p.val = _Lit, string(bs) - return - default: - bs = append(bs, p.src[p.npos]) - p.npos++ - } - } -} - -func (p *parser) advanceLitDquote() { - var i int - tok := _Lit -loop: - for i = p.npos; i < len(p.src); i++ { - switch p.src[i] { - case '\\': // escaped byte follows - if i == len(p.src)-1 { - break - } - if i++; p.src[i] == '\n' { - p.f.Lines = append(p.f.Lines, i+1) - } - case '"': - tok = _LitWord - break loop - case '`', '$': - break loop - case '\n': - p.f.Lines = append(p.f.Lines, i+1) - } - } - p.tok, p.val = tok, string(p.src[p.npos:i]) - p.npos = i -} - -func (p *parser) isHdocEnd(i int) bool { - end := p.hdocStop - if end == nil || len(p.src) < i+len(end) { - return false - } - if !bytes.Equal(end, p.src[i:i+len(end)]) { - return false - } - return len(p.src) == i+len(end) || p.src[i+len(end)] == '\n' -} - -func (p *parser) advanceLitHdoc() { - n := p.npos - if p.quote == hdocBodyTabs { - for n < len(p.src) && p.src[n] == '\t' { - n++ - } - } - if p.isHdocEnd(n) { - if n > p.npos { - p.tok, p.val = _LitWord, string(p.src[p.npos:n]) - } - p.npos = n + len(p.hdocStop) - p.hdocStop = nil - return - } - var i int -loop: - for i = p.npos; i < len(p.src); i++ { - switch p.src[i] { - case '\\': // escaped byte follows - if i++; i == len(p.src) { - break loop - } - if p.src[i] == '\n' { - p.f.Lines = append(p.f.Lines, i+1) - } - case '`', '$': - break loop - case '\n': - n := i + 1 - p.f.Lines = append(p.f.Lines, n) - if p.quote == hdocBodyTabs { - for n < len(p.src) && p.src[n] == '\t' { - n++ - } - } - if p.isHdocEnd(n) { - p.tok, p.val = _LitWord, string(p.src[p.npos:n]) - p.npos = n + len(p.hdocStop) - p.hdocStop = nil - return - } - } - } - p.tok, p.val = _Lit, string(p.src[p.npos:i]) - p.npos = i -} - -func (p *parser) hdocLitWord() Word { - pos := p.npos - end := pos - for p.npos < len(p.src) { - end = p.npos - bs, found := p.readUntil('\n') - p.npos += len(bs) + 1 - if found { - p.f.Lines = append(p.f.Lines, p.npos) - } - if p.quote == hdocBodyTabs { - for end < len(p.src) && p.src[end] == '\t' { - end++ - } - } - if p.isHdocEnd(end) { - break - } - } - if p.npos == len(p.src) { - end = p.npos - } - l := p.lit(Pos(pos+1), string(p.src[pos:end])) - return Word{Parts: p.singleWps(l)} -} - -func (p *parser) readUntil(b byte) ([]byte, bool) { - rem := p.src[p.npos:] - if i := bytes.IndexByte(rem, b); i >= 0 { - return rem[:i], true - } - return rem, false -} - -func (p *parser) advanceLitRe() { - end := bytes.Index(p.src[p.npos:], []byte(" ]]")) - p.tok = _LitWord - if end == -1 { - p.val = string(p.src[p.npos:]) - p.npos = len(p.src) - return - } - p.val = string(p.src[p.npos : p.npos+end]) - p.npos += end -} - -func testUnaryOp(val string) Token { - switch val { - case "!": - return Not - case "-e", "-a": - return tsExists - case "-f": - return tsRegFile - case "-d": - return tsDirect - case "-c": - return tsCharSp - case "-b": - return tsBlckSp - case "-p": - return tsNmPipe - case "-S": - return tsSocket - case "-L", "-h": - return tsSmbLink - case "-g": - return tsGIDSet - case "-u": - return tsUIDSet - case "-r": - return tsRead - case "-w": - return tsWrite - case "-x": - return tsExec - case "-s": - return tsNoEmpty - case "-t": - return tsFdTerm - case "-z": - return tsEmpStr - case "-n": - return tsNempStr - case "-o": - return tsOptSet - case "-v": - return tsVarSet - case "-R": - return tsRefVar - default: - return illegalTok - } -} - -func testBinaryOp(val string) Token { - switch val { - case "=": - return Assgn - case "==": - return Eql - case "!=": - return Neq - case "=~": - return tsReMatch - case "-nt": - return tsNewer - case "-ot": - return tsOlder - case "-ef": - return tsDevIno - case "-eq": - return tsEql - case "-ne": - return tsNeq - case "-le": - return tsLeq - case "-ge": - return tsGeq - case "-lt": - return tsLss - case "-gt": - return tsGtr - default: - return illegalTok - } -} diff --git a/vendor/github.com/mvdan/sh/syntax/nodes.go b/vendor/github.com/mvdan/sh/syntax/nodes.go deleted file mode 100644 index 786cafc4b2..0000000000 --- a/vendor/github.com/mvdan/sh/syntax/nodes.go +++ /dev/null @@ -1,717 +0,0 @@ -// Copyright (c) 2016, Daniel Martí -// See LICENSE for licensing information - -package syntax - -// Node represents an AST node. -type Node interface { - // Pos returns the first character of the node - Pos() Pos - // End returns the character immediately after the node - End() Pos -} - -// File is a shell program. -type File struct { - Name string - - Stmts []*Stmt - Comments []*Comment - - // Lines contains the offset of the first character for each - // line (the first entry is always 0) - Lines []int -} - -func (f *File) Pos() Pos { return stmtFirstPos(f.Stmts) } -func (f *File) End() Pos { return stmtLastEnd(f.Stmts) } - -func (f *File) Position(p Pos) (pos Position) { - intp := int(p) - pos.Offset = intp - 1 - if i := searchInts(f.Lines, intp); i >= 0 { - pos.Line, pos.Column = i+1, intp-f.Lines[i] - } - return -} - -// Inlined version of: -// sort.Search(len(a), func(i int) bool { return a[i] > x }) - 1 -func searchInts(a []int, x int) int { - i, j := 0, len(a) - for i < j { - h := i + (j-i)/2 - if a[h] <= x { - i = h + 1 - } else { - j = h - } - } - return i - 1 -} - -func posMax(p1, p2 Pos) Pos { - if p2 > p1 { - return p2 - } - return p1 -} - -// Comment represents a single comment on a single line. -type Comment struct { - Hash Pos - Text string -} - -func (c *Comment) Pos() Pos { return c.Hash } -func (c *Comment) End() Pos { return posAddStr(c.Hash, c.Text) } - -// Stmt represents a statement, otherwise known as a compound command. -// It is compromised of a command and other components that may come -// before or after it. -type Stmt struct { - Cmd Command - Position Pos - SemiPos Pos - Negated bool - Background bool - Assigns []*Assign - Redirs []*Redirect -} - -func (s *Stmt) Pos() Pos { return s.Position } -func (s *Stmt) End() Pos { - if s.SemiPos > 0 { - return s.SemiPos + 1 - } - end := s.Position - if s.Negated { - end = posAdd(end, 1) - } - if s.Cmd != nil { - end = s.Cmd.End() - } - if len(s.Assigns) > 0 { - assEnd := s.Assigns[len(s.Assigns)-1].End() - end = posMax(end, assEnd) - } - if len(s.Redirs) > 0 { - redEnd := s.Redirs[len(s.Redirs)-1].End() - end = posMax(end, redEnd) - } - return end -} - -// Command represents all nodes that are simple commands, which are -// directly placed in a Stmt. -type Command interface { - Node - commandNode() -} - -func (*CallExpr) commandNode() {} -func (*IfClause) commandNode() {} -func (*WhileClause) commandNode() {} -func (*UntilClause) commandNode() {} -func (*ForClause) commandNode() {} -func (*CaseClause) commandNode() {} -func (*Block) commandNode() {} -func (*Subshell) commandNode() {} -func (*BinaryCmd) commandNode() {} -func (*FuncDecl) commandNode() {} -func (*ArithmCmd) commandNode() {} -func (*TestClause) commandNode() {} -func (*DeclClause) commandNode() {} -func (*EvalClause) commandNode() {} -func (*LetClause) commandNode() {} -func (*CoprocClause) commandNode() {} - -// Assign represents an assignment to a variable. -type Assign struct { - Append bool - Name *Lit - Value Word -} - -func (a *Assign) Pos() Pos { - if a.Name == nil { - return a.Value.Pos() - } - return a.Name.Pos() -} - -func (a *Assign) End() Pos { - if a.Name != nil { - return posMax(a.Name.End(), a.Value.End()) - } - return a.Value.End() -} - -// Redirect represents an input/output redirection. -type Redirect struct { - OpPos Pos - Op RedirOperator - N *Lit - Word, Hdoc Word -} - -func (r *Redirect) Pos() Pos { - if r.N != nil { - return r.N.Pos() - } - return r.OpPos -} -func (r *Redirect) End() Pos { return r.Word.End() } - -// CallExpr represents a command execution or function call. -type CallExpr struct { - Args []Word -} - -func (c *CallExpr) Pos() Pos { return c.Args[0].Pos() } -func (c *CallExpr) End() Pos { return c.Args[len(c.Args)-1].End() } - -// Subshell represents a series of commands that should be executed in a -// nested shell environment. -type Subshell struct { - Lparen, Rparen Pos - Stmts []*Stmt -} - -func (s *Subshell) Pos() Pos { return s.Lparen } -func (s *Subshell) End() Pos { return posAdd(s.Rparen, 1) } - -// Block represents a series of commands that should be executed in a -// nested scope. -type Block struct { - Lbrace, Rbrace Pos - Stmts []*Stmt -} - -func (b *Block) Pos() Pos { return b.Rbrace } -func (b *Block) End() Pos { return posAdd(b.Rbrace, 1) } - -// IfClause represents an if statement. -type IfClause struct { - If, Then, Fi Pos - CondStmts []*Stmt - ThenStmts []*Stmt - Elifs []*Elif - Else Pos - ElseStmts []*Stmt -} - -func (c *IfClause) Pos() Pos { return c.If } -func (c *IfClause) End() Pos { return posAdd(c.Fi, 2) } - -// Elif represents an "else if" case in an if clause. -type Elif struct { - Elif, Then Pos - CondStmts []*Stmt - ThenStmts []*Stmt -} - -// WhileClause represents a while clause. -type WhileClause struct { - While, Do, Done Pos - CondStmts []*Stmt - DoStmts []*Stmt -} - -func (w *WhileClause) Pos() Pos { return w.While } -func (w *WhileClause) End() Pos { return posAdd(w.Done, 4) } - -// UntilClause represents an until clause. -type UntilClause struct { - Until, Do, Done Pos - CondStmts []*Stmt - DoStmts []*Stmt -} - -func (u *UntilClause) Pos() Pos { return u.Until } -func (u *UntilClause) End() Pos { return posAdd(u.Done, 4) } - -// ForClause represents a for clause. -type ForClause struct { - For, Do, Done Pos - Loop Loop - DoStmts []*Stmt -} - -func (f *ForClause) Pos() Pos { return f.For } -func (f *ForClause) End() Pos { return posAdd(f.Done, 4) } - -// Loop represents all nodes that can be loops in a for clause. -type Loop interface { - Node - loopNode() -} - -func (*WordIter) loopNode() {} -func (*CStyleLoop) loopNode() {} - -// WordIter represents the iteration of a variable over a series of -// words in a for clause. -type WordIter struct { - Name Lit - List []Word -} - -func (w *WordIter) Pos() Pos { return w.Name.Pos() } -func (w *WordIter) End() Pos { return posMax(w.Name.End(), wordLastEnd(w.List)) } - -// CStyleLoop represents the behaviour of a for clause similar to the C -// language. -// -// This node will never appear when in PosixConformant mode. -type CStyleLoop struct { - Lparen, Rparen Pos - Init, Cond, Post ArithmExpr -} - -func (c *CStyleLoop) Pos() Pos { return c.Lparen } -func (c *CStyleLoop) End() Pos { return posAdd(c.Rparen, 2) } - -// BinaryCmd represents a binary expression between two statements. -type BinaryCmd struct { - OpPos Pos - Op BinCmdOperator - X, Y *Stmt -} - -func (b *BinaryCmd) Pos() Pos { return b.X.Pos() } -func (b *BinaryCmd) End() Pos { return b.Y.End() } - -// FuncDecl represents the declaration of a function. -type FuncDecl struct { - Position Pos - BashStyle bool - Name Lit - Body *Stmt -} - -func (f *FuncDecl) Pos() Pos { return f.Position } -func (f *FuncDecl) End() Pos { return f.Body.End() } - -// Word represents a list of nodes that are contiguous to each other. -// The word is delimeted by word boundaries. -type Word struct { - Parts []WordPart -} - -func (w *Word) Pos() Pos { return partsFirstPos(w.Parts) } -func (w *Word) End() Pos { return partsLastEnd(w.Parts) } - -// WordPart represents all nodes that can form a word. -type WordPart interface { - Node - wordPartNode() -} - -func (*Lit) wordPartNode() {} -func (*SglQuoted) wordPartNode() {} -func (*DblQuoted) wordPartNode() {} -func (*ParamExp) wordPartNode() {} -func (*CmdSubst) wordPartNode() {} -func (*ArithmExp) wordPartNode() {} -func (*ProcSubst) wordPartNode() {} -func (*ArrayExpr) wordPartNode() {} -func (*ExtGlob) wordPartNode() {} - -// Lit represents an unquoted string consisting of characters that were -// not tokenized. -type Lit struct { - ValuePos Pos - Value string -} - -func (l *Lit) Pos() Pos { return l.ValuePos } -func (l *Lit) End() Pos { return posAddStr(l.ValuePos, l.Value) } - -// SglQuoted represents a string within single quotes. -type SglQuoted struct { - Position Pos - Dollar bool - Value string -} - -func (q *SglQuoted) Pos() Pos { return q.Position } -func (q *SglQuoted) End() Pos { - pos := posAdd(q.Position, 2+len(q.Value)) - if pos > 0 && q.Dollar { - pos++ - } - return pos -} - -// DblQuoted represents a list of nodes within double quotes. -type DblQuoted struct { - Position Pos - Dollar bool - Parts []WordPart -} - -func (q *DblQuoted) Pos() Pos { return q.Position } -func (q *DblQuoted) End() Pos { - if q.Position == 0 { - return defaultPos - } - end := q.Position - if len(q.Parts) > 0 { - end = partsLastEnd(q.Parts) - } else if q.Dollar { - end += 2 - } else { - end++ - } - return posAdd(end, 1) -} - -// CmdSubst represents a command substitution. -type CmdSubst struct { - Left, Right Pos - Stmts []*Stmt -} - -func (c *CmdSubst) Pos() Pos { return c.Left } -func (c *CmdSubst) End() Pos { return posAdd(c.Right, 1) } - -// ParamExp represents a parameter expansion. -type ParamExp struct { - Dollar, Rbrace Pos - Short, Length bool - Param Lit - Ind *Index - Slice *Slice - Repl *Replace - Exp *Expansion -} - -func (p *ParamExp) Pos() Pos { return p.Dollar } -func (p *ParamExp) End() Pos { - if p.Rbrace > 0 { - return p.Rbrace + 1 - } - return p.Param.End() -} - -// Index represents access to an array via an index inside a ParamExp. -// -// This node will never appear when in PosixConformant mode. -type Index struct { - Word Word -} - -// Slice represents character slicing inside a ParamExp. -// -// This node will never appear when in PosixConformant mode. -type Slice struct { - Offset, Length Word -} - -// Replace represents a search and replace inside a ParamExp. -type Replace struct { - All bool - Orig, With Word -} - -// Expansion represents string manipulation in a ParamExp other than -// those covered by Replace. -type Expansion struct { - Op ParExpOperator - Word Word -} - -// ArithmExp represents an arithmetic expansion. -type ArithmExp struct { - Left, Right Pos - Bracket bool - X ArithmExpr -} - -func (a *ArithmExp) Pos() Pos { return a.Left } -func (a *ArithmExp) End() Pos { - if a.Bracket { - return posAdd(a.Right, 1) - } - return posAdd(a.Right, 2) -} - -// ArithmCmd represents an arithmetic command. -// -// This node will never appear when in PosixConformant mode. -type ArithmCmd struct { - Left, Right Pos - X ArithmExpr -} - -func (a *ArithmCmd) Pos() Pos { return a.Left } -func (a *ArithmCmd) End() Pos { return posAdd(a.Right, 2) } - -// ArithmExpr represents all nodes that form arithmetic expressions. -type ArithmExpr interface { - Node - arithmExprNode() -} - -func (*BinaryArithm) arithmExprNode() {} -func (*UnaryArithm) arithmExprNode() {} -func (*ParenArithm) arithmExprNode() {} -func (*Word) arithmExprNode() {} - -// BinaryArithm represents a binary expression between two arithmetic -// expression. -type BinaryArithm struct { - OpPos Pos - Op Token - X, Y ArithmExpr -} - -func (b *BinaryArithm) Pos() Pos { return b.X.Pos() } -func (b *BinaryArithm) End() Pos { return b.Y.End() } - -// UnaryArithm represents an unary expression over a node, either before -// or after it. -type UnaryArithm struct { - OpPos Pos - Op Token - Post bool - X ArithmExpr -} - -func (u *UnaryArithm) Pos() Pos { - if u.Post { - return u.X.Pos() - } - return u.OpPos -} - -func (u *UnaryArithm) End() Pos { - if u.Post { - return posAdd(u.OpPos, 2) - } - return u.X.End() -} - -// ParenArithm represents an expression within parentheses inside an -// ArithmExp. -type ParenArithm struct { - Lparen, Rparen Pos - X ArithmExpr -} - -func (p *ParenArithm) Pos() Pos { return p.Lparen } -func (p *ParenArithm) End() Pos { return posAdd(p.Rparen, 1) } - -// CaseClause represents a case (switch) clause. -type CaseClause struct { - Case, Esac Pos - Word Word - List []*PatternList -} - -func (c *CaseClause) Pos() Pos { return c.Case } -func (c *CaseClause) End() Pos { return posAdd(c.Esac, 4) } - -// PatternList represents a pattern list (case) within a CaseClause. -type PatternList struct { - Op CaseOperator - OpPos Pos - Patterns []Word - Stmts []*Stmt -} - -// TestClause represents a Bash extended test clause. -// -// This node will never appear when in PosixConformant mode. -type TestClause struct { - Left, Right Pos - X TestExpr -} - -func (t *TestClause) Pos() Pos { return t.Left } -func (t *TestClause) End() Pos { return posAdd(t.Right, 2) } - -// TestExpr represents all nodes that form arithmetic expressions. -type TestExpr interface { - Node - testExprNode() -} - -func (*BinaryTest) testExprNode() {} -func (*UnaryTest) testExprNode() {} -func (*ParenTest) testExprNode() {} -func (*Word) testExprNode() {} - -// BinaryTest represents a binary expression between two arithmetic -// expression. -type BinaryTest struct { - OpPos Pos - Op BinTestOperator - X, Y TestExpr -} - -func (b *BinaryTest) Pos() Pos { return b.X.Pos() } -func (b *BinaryTest) End() Pos { return b.Y.End() } - -// UnaryTest represents an unary expression over a node, either before -// or after it. -type UnaryTest struct { - OpPos Pos - Op UnTestOperator - X TestExpr -} - -func (u *UnaryTest) Pos() Pos { return u.OpPos } -func (u *UnaryTest) End() Pos { return u.X.End() } - -// ParenTest represents an expression within parentheses inside an -// TestExp. -type ParenTest struct { - Lparen, Rparen Pos - X TestExpr -} - -func (p *ParenTest) Pos() Pos { return p.Lparen } -func (p *ParenTest) End() Pos { return posAdd(p.Rparen, 1) } - -// DeclClause represents a Bash declare clause. -// -// This node will never appear when in PosixConformant mode. -type DeclClause struct { - Position Pos - Variant string - Opts []Word - Assigns []*Assign -} - -func (d *DeclClause) Pos() Pos { return d.Position } -func (d *DeclClause) End() Pos { - end := wordLastEnd(d.Opts) - if len(d.Assigns) > 0 { - assignEnd := d.Assigns[len(d.Assigns)-1].End() - end = posMax(end, assignEnd) - } - return end -} - -// ArrayExpr represents a Bash array expression. -// -// This node will never appear when in PosixConformant mode. -type ArrayExpr struct { - Lparen, Rparen Pos - List []Word -} - -func (a *ArrayExpr) Pos() Pos { return a.Lparen } -func (a *ArrayExpr) End() Pos { return posAdd(a.Rparen, 1) } - -// ExtGlob represents a Bash extended globbing expression. Note that -// these are parsed independently of whether shopt has been called or -// not. -// -// This node will never appear when in PosixConformant mode. -type ExtGlob struct { - Op GlobOperator - Pattern Lit -} - -func (e *ExtGlob) Pos() Pos { return posAdd(e.Pattern.Pos(), -2) } -func (e *ExtGlob) End() Pos { return posAdd(e.Pattern.End(), 1) } - -// ProcSubst represents a Bash process substitution. -// -// This node will never appear when in PosixConformant mode. -type ProcSubst struct { - OpPos, Rparen Pos - Op ProcOperator - Stmts []*Stmt -} - -func (s *ProcSubst) Pos() Pos { return s.OpPos } -func (s *ProcSubst) End() Pos { return posAdd(s.Rparen, 1) } - -// EvalClause represents a Bash eval clause. -// -// This node will never appear when in PosixConformant mode. -type EvalClause struct { - Eval Pos - Stmt *Stmt -} - -func (e *EvalClause) Pos() Pos { return e.Eval } -func (e *EvalClause) End() Pos { - if e.Stmt == nil { - return posAdd(e.Eval, 4) - } - return e.Stmt.End() -} - -// CoprocClause represents a Bash coproc clause. -// -// This node will never appear when in PosixConformant mode. -type CoprocClause struct { - Coproc Pos - Name *Lit - Stmt *Stmt -} - -func (c *CoprocClause) Pos() Pos { return c.Coproc } -func (c *CoprocClause) End() Pos { return c.Stmt.End() } - -// LetClause represents a Bash let clause. -// -// This node will never appear when in PosixConformant mode. -type LetClause struct { - Let Pos - Exprs []ArithmExpr -} - -func (l *LetClause) Pos() Pos { return l.Let } -func (l *LetClause) End() Pos { return l.Exprs[len(l.Exprs)-1].End() } - -func posAdd(pos Pos, n int) Pos { - if pos == defaultPos { - return pos - } - return pos + Pos(n) -} - -func posAddStr(pos Pos, s string) Pos { - return posAdd(pos, len(s)) -} - -func stmtFirstPos(sts []*Stmt) Pos { - if len(sts) == 0 { - return defaultPos - } - return sts[0].Pos() -} - -func stmtLastEnd(sts []*Stmt) Pos { - if len(sts) == 0 { - return defaultPos - } - return sts[len(sts)-1].End() -} - -func partsFirstPos(ps []WordPart) Pos { - if len(ps) == 0 { - return defaultPos - } - return ps[0].Pos() -} - -func partsLastEnd(ps []WordPart) Pos { - if len(ps) == 0 { - return defaultPos - } - return ps[len(ps)-1].End() -} - -func wordLastEnd(ws []Word) Pos { - if len(ws) == 0 { - return defaultPos - } - return ws[len(ws)-1].End() -} diff --git a/vendor/github.com/mvdan/sh/syntax/parser.go b/vendor/github.com/mvdan/sh/syntax/parser.go deleted file mode 100644 index c9ef38eab2..0000000000 --- a/vendor/github.com/mvdan/sh/syntax/parser.go +++ /dev/null @@ -1,1659 +0,0 @@ -// Copyright (c) 2016, Daniel Martí -// See LICENSE for licensing information - -package syntax - -import ( - "bytes" - "fmt" - "strconv" - "sync" -) - -// ParseMode controls the parser behaviour via a set of flags. -type ParseMode uint - -const ( - ParseComments ParseMode = 1 << iota // add comments to the AST - PosixConformant // match the POSIX standard where it differs from bash -) - -var parserFree = sync.Pool{ - New: func() interface{} { - return &parser{helperBuf: new(bytes.Buffer)} - }, -} - -// Parse reads and parses a shell program with an optional name. It -// returns the parsed program if no issues were encountered. Otherwise, -// an error is returned. -func Parse(src []byte, name string, mode ParseMode) (*File, error) { - p := parserFree.Get().(*parser) - p.reset() - alloc := &struct { - f File - l [16]int - }{} - p.f = &alloc.f - p.f.Name = name - p.f.Lines = alloc.l[:1] - p.src, p.mode = src, mode - p.next() - p.f.Stmts = p.stmts() - parserFree.Put(p) - return p.f, p.err -} - -type parser struct { - src []byte - - f *File - mode ParseMode - - spaced, newLine bool - - err error - - tok Token - val string - - pos Pos - npos int - - quote quoteState - asPos int - - // list of pending heredoc bodies - buriedHdocs int - heredocs []*Redirect - hdocStop []byte - - helperBuf *bytes.Buffer - - litBatch []Lit - wpsBatch []WordPart - stmtBatch []Stmt - stListBatch []*Stmt - - litBuf [32]byte -} - -func (p *parser) lit(pos Pos, val string) *Lit { - if len(p.litBatch) == 0 { - p.litBatch = make([]Lit, 32) - } - l := &p.litBatch[0] - l.ValuePos = pos - l.Value = val - p.litBatch = p.litBatch[1:] - return l -} - -func (p *parser) singleWps(wp WordPart) []WordPart { - if len(p.wpsBatch) == 0 { - p.wpsBatch = make([]WordPart, 64) - } - wps := p.wpsBatch[:1:1] - p.wpsBatch = p.wpsBatch[1:] - wps[0] = wp - return wps -} - -func (p *parser) wps() []WordPart { - if len(p.wpsBatch) < 4 { - p.wpsBatch = make([]WordPart, 64) - } - wps := p.wpsBatch[:0:4] - p.wpsBatch = p.wpsBatch[4:] - return wps -} - -func (p *parser) stmt(pos Pos) *Stmt { - if len(p.stmtBatch) == 0 { - p.stmtBatch = make([]Stmt, 16) - } - s := &p.stmtBatch[0] - s.Position = pos - p.stmtBatch = p.stmtBatch[1:] - return s -} - -func (p *parser) stList() []*Stmt { - if len(p.stListBatch) == 0 { - p.stListBatch = make([]*Stmt, 128) - } - stmts := p.stListBatch[:0:4] - p.stListBatch = p.stListBatch[4:] - return stmts -} - -type quoteState int - -const ( - noState quoteState = 1 << iota - subCmd - subCmdBckquo - sglQuotes - dblQuotes - hdocWord - hdocBody - hdocBodyTabs - arithmExpr - arithmExprLet - arithmExprCmd - arithmExprBrack - testRegexp - switchCase - paramExpName - paramExpInd - paramExpRepl - paramExpExp - - allRegTokens = noState | subCmd | subCmdBckquo | hdocWord | switchCase - allArithmExpr = arithmExpr | arithmExprLet | arithmExprCmd | arithmExprBrack - allRbrack = arithmExprBrack | paramExpInd -) - -func (p *parser) bash() bool { return p.mode&PosixConformant == 0 } - -func (p *parser) reset() { - p.spaced, p.newLine = false, false - p.err = nil - p.npos = 0 - p.tok, p.quote = illegalTok, noState - p.heredocs = p.heredocs[:0] - p.buriedHdocs = 0 -} - -type saveState struct { - quote quoteState - buriedHdocs int -} - -func (p *parser) preNested(quote quoteState) (s saveState) { - s.quote = p.quote - s.buriedHdocs = p.buriedHdocs - p.buriedHdocs = len(p.heredocs) - p.quote = quote - return -} - -func (p *parser) postNested(s saveState) { - p.quote, p.buriedHdocs = s.quote, s.buriedHdocs -} - -func (p *parser) unquotedWordBytes(w Word) ([]byte, bool) { - p.helperBuf.Reset() - didUnquote := false - for _, wp := range w.Parts { - if p.unquotedWordPart(p.helperBuf, wp) { - didUnquote = true - } - } - return p.helperBuf.Bytes(), didUnquote -} - -func (p *parser) unquotedWordPart(b *bytes.Buffer, wp WordPart) bool { - switch x := wp.(type) { - case *Lit: - if x.Value[0] == '\\' { - b.WriteString(x.Value[1:]) - return true - } - b.WriteString(x.Value) - return false - case *SglQuoted: - b.WriteString(x.Value) - return true - case *DblQuoted: - for _, wp2 := range x.Parts { - p.unquotedWordPart(b, wp2) - } - return true - default: - // catch-all for unusual cases such as ParamExp - b.Write(p.src[wp.Pos()-1 : wp.End()-1]) - return false - } -} - -func (p *parser) doHeredocs() { - p.tok = illegalTok - old := p.quote - hdocs := p.heredocs[p.buriedHdocs:] - p.heredocs = p.heredocs[:p.buriedHdocs] - for i, r := range hdocs { - if r.Op == DashHdoc { - p.quote = hdocBodyTabs - } else { - p.quote = hdocBody - } - var quoted bool - p.hdocStop, quoted = p.unquotedWordBytes(r.Word) - if i > 0 && p.npos < len(p.src) && p.src[p.npos] == '\n' { - p.npos++ - p.f.Lines = append(p.f.Lines, p.npos) - } - if !quoted { - p.next() - r.Hdoc = p.word() - continue - } - r.Hdoc = p.hdocLitWord() - - } - p.quote = old -} - -func (p *parser) got(tok Token) bool { - if p.tok == tok { - p.next() - return true - } - return false -} - -func (p *parser) gotRsrv(val string) bool { - if p.tok == _LitWord && p.val == val { - p.next() - return true - } - return false -} - -func (p *parser) gotSameLine(tok Token) bool { - if !p.newLine && p.tok == tok { - p.next() - return true - } - return false -} - -func readableStr(s string) string { - // don't quote tokens like & or } - if s != "" && s[0] >= 'a' && s[0] <= 'z' { - return strconv.Quote(s) - } - return s -} - -func (p *parser) followErr(pos Pos, left, right string) { - leftStr := readableStr(left) - p.posErr(pos, "%s must be followed by %s", leftStr, right) -} - -func (p *parser) follow(lpos Pos, left string, tok Token) Pos { - pos := p.pos - if !p.got(tok) { - p.followErr(lpos, left, tok.String()) - } - return pos -} - -func (p *parser) followRsrv(lpos Pos, left, val string) Pos { - pos := p.pos - if !p.gotRsrv(val) { - p.followErr(lpos, left, fmt.Sprintf("%q", val)) - } - return pos -} - -func (p *parser) followStmts(left string, lpos Pos, stops ...string) []*Stmt { - if p.gotSameLine(semicolon) { - return nil - } - sts := p.stmts(stops...) - if len(sts) < 1 && !p.newLine { - p.followErr(lpos, left, "a statement list") - } - return sts -} - -func (p *parser) followWordTok(tok Token, pos Pos) Word { - w := p.word() - if w.Parts == nil { - p.followErr(pos, tok.String(), "a word") - } - return w -} - -func (p *parser) followWord(s string, pos Pos) Word { - w := p.word() - if w.Parts == nil { - p.followErr(pos, s, "a word") - } - return w -} - -func (p *parser) stmtEnd(n Node, start, end string) Pos { - pos := p.pos - if !p.gotRsrv(end) { - p.posErr(n.Pos(), "%s statement must end with %q", start, end) - } - return pos -} - -func (p *parser) quoteErr(lpos Pos, quote Token) { - p.posErr(lpos, "reached %s without closing quote %s", p.tok, quote) -} - -func (p *parser) matchingErr(lpos Pos, left, right interface{}) { - p.posErr(lpos, "reached %s without matching %s with %s", p.tok, left, right) -} - -func (p *parser) matched(lpos Pos, left, right Token) Pos { - pos := p.pos - if !p.got(right) { - p.matchingErr(lpos, left, right) - } - return pos -} - -func (p *parser) errPass(err error) { - if p.err == nil { - p.err = err - p.tok = _EOF - } -} - -// ParseError represents an error found when parsing a source file. -type ParseError struct { - Position - Filename, Text string -} - -func (e *ParseError) Error() string { - prefix := "" - if e.Filename != "" { - prefix = e.Filename + ":" - } - return fmt.Sprintf("%s%d:%d: %s", prefix, e.Line, e.Column, e.Text) -} - -func (p *parser) posErr(pos Pos, format string, a ...interface{}) { - p.errPass(&ParseError{ - Position: p.f.Position(pos), - Filename: p.f.Name, - Text: fmt.Sprintf(format, a...), - }) -} - -func (p *parser) curErr(format string, a ...interface{}) { - p.posErr(p.pos, format, a...) -} - -func (p *parser) stmts(stops ...string) (sts []*Stmt) { - q := p.quote - gotEnd := true - for p.tok != _EOF { - switch p.tok { - case _LitWord: - for _, stop := range stops { - if p.val == stop { - return - } - } - case rightParen: - if q == subCmd { - return - } - case bckQuote: - if q == subCmdBckquo { - return - } - case dblSemicolon, semiFall, dblSemiFall: - if q == switchCase { - return - } - p.curErr("%s can only be used in a case clause", p.tok) - } - if !p.newLine && !gotEnd { - p.curErr("statements must be separated by &, ; or a newline") - } - if p.tok == _EOF { - break - } - if s, end := p.getStmt(true); s == nil { - p.invalidStmtStart() - } else { - if sts == nil { - sts = p.stList() - } - sts = append(sts, s) - gotEnd = end - } - } - return -} - -func (p *parser) invalidStmtStart() { - switch p.tok { - case semicolon, And, Or, AndExpr, OrExpr: - p.curErr("%s can only immediately follow a statement", p.tok) - case rightParen: - p.curErr("%s can only be used to close a subshell", p.tok) - default: - p.curErr("%s is not a valid start for a statement", p.tok) - } -} - -func (p *parser) word() Word { - if p.tok == _LitWord { - w := Word{Parts: p.singleWps(p.lit(p.pos, p.val))} - p.next() - return w - } - return Word{Parts: p.wordParts()} -} - -func (p *parser) gotLit(l *Lit) bool { - l.ValuePos = p.pos - if p.tok == _Lit || p.tok == _LitWord { - l.Value = p.val - p.next() - return true - } - return false -} - -func (p *parser) wordParts() (wps []WordPart) { - for { - n := p.wordPart() - if n == nil { - return - } - if wps == nil { - wps = p.wps() - } - wps = append(wps, n) - if p.spaced { - return - } - } -} - -func (p *parser) wordPart() WordPart { - switch p.tok { - case _Lit, _LitWord: - l := p.lit(p.pos, p.val) - p.next() - return l - case dollBrace: - return p.paramExp() - case dollDblParen, dollBrack: - left := p.tok - ar := &ArithmExp{Left: p.pos, Bracket: left == dollBrack} - old := p.preNested(arithmExpr) - if ar.Bracket { - p.quote = arithmExprBrack - } else if !p.couldBeArithm() { - p.postNested(old) - p.npos = int(ar.Left) + 1 - p.tok = dollParen - p.pos = ar.Left - wp := p.wordPart() - if p.err != nil { - p.err = nil - p.matchingErr(ar.Left, dollDblParen, dblRightParen) - } - return wp - } - p.next() - ar.X = p.arithmExpr(left, ar.Left, 0, false) - if ar.Bracket { - if p.tok != rightBrack { - p.matchingErr(ar.Left, dollBrack, rightBrack) - } - p.postNested(old) - ar.Right = p.pos - p.next() - } else { - ar.Right = p.arithmEnd(dollDblParen, ar.Left, old) - } - return ar - case dollParen: - if p.quote == hdocWord { - p.curErr("nested statements not allowed in heredoc words") - } - cs := &CmdSubst{Left: p.pos} - old := p.preNested(subCmd) - p.next() - cs.Stmts = p.stmts() - p.postNested(old) - cs.Right = p.matched(cs.Left, leftParen, rightParen) - return cs - case dollar: - var b byte - if p.npos >= len(p.src) { - p.tok = _EOF - } else { - b = p.src[p.npos] - } - if p.tok == _EOF || wordBreak(b) || b == '"' || b == '\'' || b == '`' || b == '[' { - l := p.lit(p.pos, "$") - p.next() - return l - } - pe := &ParamExp{Dollar: p.pos, Short: true} - p.pos++ - switch b { - case '@', '*', '#', '$', '?', '!', '0', '-': - p.npos++ - p.tok, p.val = _Lit, string(b) - default: - p.advanceLitOther(p.quote) - } - p.gotLit(&pe.Param) - return pe - case cmdIn, cmdOut: - ps := &ProcSubst{Op: ProcOperator(p.tok), OpPos: p.pos} - old := p.preNested(subCmd) - p.next() - ps.Stmts = p.stmts() - p.postNested(old) - ps.Rparen = p.matched(ps.OpPos, Token(ps.Op), rightParen) - return ps - case sglQuote: - sq := &SglQuoted{Position: p.pos} - bs, found := p.readUntil('\'') - rem := bs - for { - i := bytes.IndexByte(rem, '\n') - if i < 0 { - p.npos += len(rem) - break - } - p.npos += i + 1 - p.f.Lines = append(p.f.Lines, p.npos) - rem = rem[i+1:] - } - p.npos++ - if !found { - p.posErr(sq.Pos(), "reached EOF without closing quote %s", sglQuote) - } - sq.Value = string(bs) - p.next() - return sq - case dollSglQuote: - sq := &SglQuoted{Position: p.pos, Dollar: true} - old := p.quote - p.quote = sglQuotes - p.next() - if p.tok == sglQuote { - p.quote = old - } else { - sq.Value = p.val - p.quote = old - p.next() - } - if !p.got(sglQuote) { - p.quoteErr(sq.Pos(), sglQuote) - } - return sq - case dblQuote: - if p.quote == dblQuotes { - return nil - } - fallthrough - case dollDblQuote: - q := &DblQuoted{Position: p.pos, Dollar: p.tok == dollDblQuote} - old := p.quote - p.quote = dblQuotes - p.next() - if p.tok == _LitWord { - q.Parts = p.singleWps(p.lit(p.pos, p.val)) - p.next() - } else { - q.Parts = p.wordParts() - } - p.quote = old - if !p.got(dblQuote) { - p.quoteErr(q.Pos(), dblQuote) - } - return q - case bckQuote: - switch p.quote { - case hdocWord: - p.curErr("nested statements not allowed in heredoc words") - case subCmdBckquo: - return nil - } - cs := &CmdSubst{Left: p.pos} - old := p.preNested(subCmdBckquo) - p.next() - cs.Stmts = p.stmts() - p.postNested(old) - cs.Right = p.pos - if !p.got(bckQuote) { - p.quoteErr(cs.Pos(), bckQuote) - } - return cs - case globQuest, globMul, globAdd, globAt, globNot: - eg := &ExtGlob{Op: GlobOperator(p.tok)} - eg.Pattern.ValuePos = Pos(p.npos + 1) - start := p.npos - lparens := 0 - for _, b := range p.src[start:] { - p.npos++ - if b == '(' { - lparens++ - } else if b == ')' { - if lparens--; lparens < 0 { - eg.Pattern.Value = string(p.src[start : p.npos-1]) - break - } - } - } - p.next() - if lparens != -1 { - p.matchingErr(p.pos, eg.Op, rightParen) - } - return eg - } - return nil -} - -func (p *parser) couldBeArithm() (could bool) { - // save state - oldTok := p.tok - oldNpos := p.npos - oldLines := len(p.f.Lines) - p.next() - lparens := 0 -tokLoop: - for p.tok != _EOF { - switch p.tok { - case leftParen, dollParen: - lparens++ - case dollDblParen, dblLeftParen: - lparens += 2 - case rightParen: - if lparens == 0 { - could = p.peekArithmEnd() - break tokLoop - } - lparens-- - } - p.next() - } - // recover state - p.tok = oldTok - p.npos = oldNpos - p.f.Lines = p.f.Lines[:oldLines] - return -} - -func arithmOpLevel(tok Token) int { - switch tok { - case Comma: - return 0 - case AddAssgn, SubAssgn, MulAssgn, QuoAssgn, RemAssgn, AndAssgn, - OrAssgn, XorAssgn, ShlAssgn, ShrAssgn: - return 1 - case Assgn: - return 2 - case Quest, Colon: - return 3 - case AndExpr, OrExpr: - return 4 - case And, Or, Xor: - return 5 - case Eql, Neq: - return 6 - case Lss, Gtr, Leq, Geq: - return 7 - case Shl, Shr: - return 8 - case Add, Sub: - return 9 - case Mul, Quo, Rem: - return 10 - case Pow: - return 11 - } - return -1 -} - -func (p *parser) arithmExpr(ftok Token, fpos Pos, level int, compact bool) ArithmExpr { - if p.tok == _EOF || p.peekArithmEnd() { - return nil - } - var left ArithmExpr - if level > 11 { - left = p.arithmExprBase(ftok, fpos, compact) - } else { - left = p.arithmExpr(ftok, fpos, level+1, compact) - } - if compact && p.spaced { - return left - } - newLevel := arithmOpLevel(p.tok) - if newLevel < 0 { - switch p.tok { - case _Lit, _LitWord: - p.curErr("not a valid arithmetic operator: %s", p.val) - return nil - case rightParen, _EOF: - default: - if p.quote == arithmExpr { - p.curErr("not a valid arithmetic operator: %v", p.tok) - return nil - } - } - } - if newLevel < 0 || newLevel < level { - return left - } - b := &BinaryArithm{ - OpPos: p.pos, - Op: p.tok, - X: left, - } - if p.next(); compact && p.spaced { - p.followErr(b.OpPos, b.Op.String(), "an expression") - } - if b.Y = p.arithmExpr(b.Op, b.OpPos, newLevel, compact); b.Y == nil { - p.followErr(b.OpPos, b.Op.String(), "an expression") - } - return b -} - -func (p *parser) arithmExprBase(ftok Token, fpos Pos, compact bool) ArithmExpr { - var x ArithmExpr - switch p.tok { - case Inc, Dec, Not: - pre := &UnaryArithm{OpPos: p.pos, Op: p.tok} - p.next() - pre.X = p.arithmExprBase(pre.Op, pre.OpPos, compact) - return pre - case leftParen: - pe := &ParenArithm{Lparen: p.pos} - p.next() - if pe.X = p.arithmExpr(leftParen, pe.Lparen, 0, false); pe.X == nil { - p.posErr(pe.Lparen, "parentheses must enclose an expression") - } - pe.Rparen = p.matched(pe.Lparen, leftParen, rightParen) - x = pe - case Add, Sub: - ue := &UnaryArithm{OpPos: p.pos, Op: p.tok} - if p.next(); compact && p.spaced { - p.followErr(ue.OpPos, ue.Op.String(), "an expression") - } - if ue.X = p.arithmExpr(ue.Op, ue.OpPos, 0, compact); ue.X == nil { - p.followErr(ue.OpPos, ue.Op.String(), "an expression") - } - x = ue - case bckQuote: - if p.quote == arithmExprLet { - return nil - } - fallthrough - default: - w := p.word() - if w.Parts == nil { - p.followErr(fpos, ftok.String(), "an expression") - } - x = &w - } - if compact && p.spaced { - return x - } - if p.tok == Inc || p.tok == Dec { - u := &UnaryArithm{ - Post: true, - OpPos: p.pos, - Op: p.tok, - X: x, - } - p.next() - return u - } - return x -} - -func (p *parser) gotParamLit(l *Lit) bool { - l.ValuePos = p.pos - switch p.tok { - case _Lit, _LitWord: - l.Value = p.val - case dollar: - l.Value = "$" - case Quest: - l.Value = "?" - case Hash: - l.Value = "#" - case Sub: - l.Value = "-" - default: - return false - } - p.next() - return true -} - -func (p *parser) paramExp() *ParamExp { - pe := &ParamExp{Dollar: p.pos} - old := p.preNested(paramExpName) - p.next() - switch p.tok { - case dblHash: - p.tok = Hash - p.npos-- - fallthrough - case Hash: - if p.npos < len(p.src) && p.src[p.npos] != '}' { - pe.Length = true - p.next() - } - } - if !p.gotParamLit(&pe.Param) && !pe.Length { - p.posErr(pe.Dollar, "parameter expansion requires a literal") - } - if p.tok == rightBrace { - pe.Rbrace = p.pos - p.postNested(old) - p.next() - return pe - } - if p.tok == leftBrack { - if !p.bash() { - p.curErr("arrays are a bash feature") - } - lpos := p.pos - p.quote = paramExpInd - p.next() - pe.Ind = &Index{Word: p.word()} - p.quote = paramExpName - p.matched(lpos, leftBrack, rightBrack) - } - switch p.tok { - case rightBrace: - pe.Rbrace = p.pos - p.postNested(old) - p.next() - return pe - case Quo, dblQuo: - pe.Repl = &Replace{All: p.tok == dblQuo} - p.quote = paramExpRepl - p.next() - pe.Repl.Orig = p.word() - if p.tok == Quo { - p.quote = paramExpExp - p.next() - pe.Repl.With = p.word() - } - case Colon: - if !p.bash() { - p.curErr("slicing is a bash feature") - } - pe.Slice = &Slice{} - colonPos := p.pos - p.next() - if p.tok != Colon { - pe.Slice.Offset = p.followWordTok(Colon, colonPos) - } - colonPos = p.pos - if p.got(Colon) { - pe.Slice.Length = p.followWordTok(Colon, colonPos) - } - case Xor, dblXor, Comma, dblComma: - if !p.bash() { - p.curErr("case expansions are a bash feature") - } - fallthrough - default: - pe.Exp = &Expansion{Op: ParExpOperator(p.tok)} - p.quote = paramExpExp - p.next() - pe.Exp.Word = p.word() - } - p.postNested(old) - pe.Rbrace = p.pos - p.matched(pe.Dollar, dollBrace, rightBrace) - return pe -} - -func (p *parser) peekArithmEnd() bool { - return p.tok == rightParen && p.npos < len(p.src) && p.src[p.npos] == ')' -} - -func (p *parser) arithmEnd(ltok Token, lpos Pos, old saveState) Pos { - if p.peekArithmEnd() { - p.npos++ - } else { - p.matchingErr(lpos, ltok, dblRightParen) - } - p.postNested(old) - pos := p.pos - p.next() - return pos -} - -func stopToken(tok Token) bool { - switch tok { - case _EOF, semicolon, And, Or, AndExpr, OrExpr, pipeAll, dblSemicolon, - semiFall, dblSemiFall, rightParen: - return true - } - return false -} - -func (p *parser) validIdent() bool { - if p.asPos <= 0 { - return false - } - s := p.val[:p.asPos] - for i, c := range s { - switch { - case 'a' <= c && c <= 'z': - case 'A' <= c && c <= 'Z': - case c == '_': - case i > 0 && '0' <= c && c <= '9': - case i > 0 && (c == '[' || c == ']') && p.bash(): - default: - return false - } - } - return true -} - -func (p *parser) getAssign() *Assign { - asPos := p.asPos - as := &Assign{Name: p.lit(p.pos, p.val[:asPos])} - if p.val[asPos] == '+' { - as.Append = true - asPos++ - } - start := p.lit(p.pos+1, p.val[asPos+1:]) - if start.Value != "" { - start.ValuePos += Pos(asPos) - as.Value.Parts = p.singleWps(start) - } - p.next() - if p.spaced { - return as - } - if start.Value == "" && p.tok == leftParen { - if !p.bash() { - p.curErr("arrays are a bash feature") - } - ae := &ArrayExpr{Lparen: p.pos} - p.next() - for p.tok != _EOF && p.tok != rightParen { - if w := p.word(); w.Parts == nil { - p.curErr("array elements must be words") - } else { - ae.List = append(ae.List, w) - } - } - ae.Rparen = p.matched(ae.Lparen, leftParen, rightParen) - as.Value.Parts = p.singleWps(ae) - } else if !p.newLine && !stopToken(p.tok) { - if w := p.word(); start.Value == "" { - as.Value = w - } else { - as.Value.Parts = append(as.Value.Parts, w.Parts...) - } - } - return as -} - -func litRedir(src []byte, npos int) bool { - return npos < len(src) && (src[npos] == '>' || src[npos] == '<') -} - -func (p *parser) peekRedir() bool { - switch p.tok { - case _LitWord: - return litRedir(p.src, p.npos) - case Gtr, Shr, Lss, dplIn, dplOut, clbOut, rdrInOut, Shl, dashHdoc, - wordHdoc, rdrAll, appAll: - return true - } - return false -} - -func (p *parser) doRedirect(s *Stmt) { - r := &Redirect{} - var l Lit - if p.gotLit(&l) { - r.N = &l - } - r.Op, r.OpPos = RedirOperator(p.tok), p.pos - p.next() - switch r.Op { - case Hdoc, DashHdoc: - old := p.quote - p.quote = hdocWord - if p.newLine { - p.curErr("heredoc stop word must be on the same line") - } - p.heredocs = append(p.heredocs, r) - r.Word = p.followWordTok(Token(r.Op), r.OpPos) - p.quote = old - p.next() - default: - if p.newLine { - p.curErr("redirect word must be on the same line") - } - r.Word = p.followWordTok(Token(r.Op), r.OpPos) - } - s.Redirs = append(s.Redirs, r) -} - -func (p *parser) getStmt(readEnd bool) (s *Stmt, gotEnd bool) { - s = p.stmt(p.pos) - if p.gotRsrv("!") { - s.Negated = true - } -preLoop: - for { - switch p.tok { - case _Lit, _LitWord: - if p.validIdent() { - s.Assigns = append(s.Assigns, p.getAssign()) - } else if litRedir(p.src, p.npos) { - p.doRedirect(s) - } else { - break preLoop - } - case Gtr, Shr, Lss, dplIn, dplOut, clbOut, rdrInOut, Shl, dashHdoc, - wordHdoc, rdrAll, appAll: - p.doRedirect(s) - default: - break preLoop - } - switch { - case p.newLine, p.tok == _EOF: - return - case p.tok == semicolon: - if readEnd { - s.SemiPos = p.pos - p.next() - gotEnd = true - } - return - } - } - if s = p.gotStmtPipe(s); s == nil { - return - } - switch p.tok { - case AndExpr, OrExpr: - b := &BinaryCmd{OpPos: p.pos, Op: BinCmdOperator(p.tok), X: s} - p.next() - if b.Y, _ = p.getStmt(false); b.Y == nil { - p.followErr(b.OpPos, b.Op.String(), "a statement") - } - s = p.stmt(s.Position) - s.Cmd = b - if readEnd && p.gotSameLine(semicolon) { - gotEnd = true - } - case And: - p.next() - s.Background = true - gotEnd = true - case semicolon: - if !p.newLine && readEnd { - s.SemiPos = p.pos - p.next() - gotEnd = true - } - } - return -} - -func bashDeclareWord(s string) bool { - switch s { - case "declare", "local", "export", "readonly", "typeset", "nameref": - return true - } - return false -} - -func (p *parser) gotStmtPipe(s *Stmt) *Stmt { - switch p.tok { - case leftParen: - s.Cmd = p.subshell() - case dblLeftParen: - s.Cmd = p.arithmExpCmd() - case _LitWord: - switch { - case p.val == "}": - p.curErr("%s can only be used to close a block", p.val) - case p.val == "{": - s.Cmd = p.block() - case p.val == "if": - s.Cmd = p.ifClause() - case p.val == "while": - s.Cmd = p.whileClause() - case p.val == "until": - s.Cmd = p.untilClause() - case p.val == "for": - s.Cmd = p.forClause() - case p.val == "case": - s.Cmd = p.caseClause() - case p.bash() && p.val == "[[": - s.Cmd = p.testClause() - case p.bash() && bashDeclareWord(p.val): - s.Cmd = p.declClause() - case p.bash() && p.val == "eval": - s.Cmd = p.evalClause() - case p.bash() && p.val == "coproc": - s.Cmd = p.coprocClause() - case p.bash() && p.val == "let": - s.Cmd = p.letClause() - case p.bash() && p.val == "function": - s.Cmd = p.bashFuncDecl() - default: - name := Lit{ValuePos: p.pos, Value: p.val} - p.next() - if p.gotSameLine(leftParen) { - p.follow(name.ValuePos, "foo(", rightParen) - s.Cmd = p.funcDecl(name, name.ValuePos) - } else { - s.Cmd = p.callExpr(s, Word{ - Parts: p.singleWps(&name), - }) - } - } - case _Lit, dollBrace, dollDblParen, dollParen, dollar, cmdIn, cmdOut, sglQuote, - dollSglQuote, dblQuote, dollDblQuote, bckQuote, dollBrack, globQuest, globMul, globAdd, - globAt, globNot: - w := Word{Parts: p.wordParts()} - if p.gotSameLine(leftParen) && p.err == nil { - rawName := string(p.src[w.Pos()-1 : w.End()-1]) - p.posErr(w.Pos(), "invalid func name: %q", rawName) - } - s.Cmd = p.callExpr(s, w) - } - for !p.newLine && p.peekRedir() { - p.doRedirect(s) - } - if s.Cmd == nil && len(s.Redirs) == 0 && !s.Negated && len(s.Assigns) == 0 { - return nil - } - if p.tok == Or || p.tok == pipeAll { - b := &BinaryCmd{OpPos: p.pos, Op: BinCmdOperator(p.tok), X: s} - p.next() - if b.Y = p.gotStmtPipe(p.stmt(p.pos)); b.Y == nil { - p.followErr(b.OpPos, b.Op.String(), "a statement") - } - s = p.stmt(s.Position) - s.Cmd = b - } - return s -} - -func (p *parser) subshell() *Subshell { - s := &Subshell{Lparen: p.pos} - old := p.preNested(subCmd) - p.next() - s.Stmts = p.stmts() - p.postNested(old) - s.Rparen = p.matched(s.Lparen, leftParen, rightParen) - return s -} - -func (p *parser) arithmExpCmd() Command { - ar := &ArithmCmd{Left: p.pos} - old := p.preNested(arithmExprCmd) - if !p.couldBeArithm() { - p.postNested(old) - p.npos = int(ar.Left) - p.tok = leftParen - p.pos = ar.Left - s := p.subshell() - if p.err != nil { - p.err = nil - p.matchingErr(ar.Left, dblLeftParen, dblRightParen) - } - return s - } - p.next() - ar.X = p.arithmExpr(dblLeftParen, ar.Left, 0, false) - ar.Right = p.arithmEnd(dblLeftParen, ar.Left, old) - return ar -} - -func (p *parser) block() *Block { - b := &Block{Lbrace: p.pos} - p.next() - b.Stmts = p.stmts("}") - b.Rbrace = p.pos - if !p.gotRsrv("}") { - p.matchingErr(b.Lbrace, "{", "}") - } - return b -} - -func (p *parser) ifClause() *IfClause { - ic := &IfClause{If: p.pos} - p.next() - ic.CondStmts = p.followStmts("if", ic.If, "then") - ic.Then = p.followRsrv(ic.If, "if ", "then") - ic.ThenStmts = p.followStmts("then", ic.Then, "fi", "elif", "else") - elifPos := p.pos - for p.gotRsrv("elif") { - elf := &Elif{Elif: elifPos} - elf.CondStmts = p.followStmts("elif", elf.Elif, "then") - elf.Then = p.followRsrv(elf.Elif, "elif ", "then") - elf.ThenStmts = p.followStmts("then", elf.Then, "fi", "elif", "else") - ic.Elifs = append(ic.Elifs, elf) - elifPos = p.pos - } - if elsePos := p.pos; p.gotRsrv("else") { - ic.Else = elsePos - ic.ElseStmts = p.followStmts("else", ic.Else, "fi") - } - ic.Fi = p.stmtEnd(ic, "if", "fi") - return ic -} - -func (p *parser) whileClause() *WhileClause { - wc := &WhileClause{While: p.pos} - p.next() - wc.CondStmts = p.followStmts("while", wc.While, "do") - wc.Do = p.followRsrv(wc.While, "while ", "do") - wc.DoStmts = p.followStmts("do", wc.Do, "done") - wc.Done = p.stmtEnd(wc, "while", "done") - return wc -} - -func (p *parser) untilClause() *UntilClause { - uc := &UntilClause{Until: p.pos} - p.next() - uc.CondStmts = p.followStmts("until", uc.Until, "do") - uc.Do = p.followRsrv(uc.Until, "until ", "do") - uc.DoStmts = p.followStmts("do", uc.Do, "done") - uc.Done = p.stmtEnd(uc, "until", "done") - return uc -} - -func (p *parser) forClause() *ForClause { - fc := &ForClause{For: p.pos} - p.next() - fc.Loop = p.loop(fc.For) - fc.Do = p.followRsrv(fc.For, "for foo [in words]", "do") - fc.DoStmts = p.followStmts("do", fc.Do, "done") - fc.Done = p.stmtEnd(fc, "for", "done") - return fc -} - -func (p *parser) loop(forPos Pos) Loop { - if p.tok == dblLeftParen { - cl := &CStyleLoop{Lparen: p.pos} - old := p.preNested(arithmExprCmd) - p.next() - if p.tok == dblSemicolon { - p.npos-- - p.tok = semicolon - } - if p.tok != semicolon { - cl.Init = p.arithmExpr(dblLeftParen, cl.Lparen, 0, false) - } - scPos := p.pos - p.follow(p.pos, "expression", semicolon) - if p.tok != semicolon { - cl.Cond = p.arithmExpr(semicolon, scPos, 0, false) - } - scPos = p.pos - p.follow(p.pos, "expression", semicolon) - if p.tok != semicolon { - cl.Post = p.arithmExpr(semicolon, scPos, 0, false) - } - cl.Rparen = p.arithmEnd(dblLeftParen, cl.Lparen, old) - p.gotSameLine(semicolon) - return cl - } - wi := &WordIter{} - if !p.gotLit(&wi.Name) { - p.followErr(forPos, "for", "a literal") - } - if p.gotRsrv("in") { - for !p.newLine && p.tok != _EOF && p.tok != semicolon { - if w := p.word(); w.Parts == nil { - p.curErr("word list can only contain words") - } else { - wi.List = append(wi.List, w) - } - } - p.gotSameLine(semicolon) - } else if !p.newLine && !p.got(semicolon) { - p.followErr(forPos, "for foo", `"in", ; or a newline`) - } - return wi -} - -func (p *parser) caseClause() *CaseClause { - cc := &CaseClause{Case: p.pos} - p.next() - cc.Word = p.followWord("case", cc.Case) - p.followRsrv(cc.Case, "case x", "in") - cc.List = p.patLists() - cc.Esac = p.stmtEnd(cc, "case", "esac") - return cc -} - -func (p *parser) patLists() (pls []*PatternList) { - for p.tok != _EOF && !(p.tok == _LitWord && p.val == "esac") { - pl := &PatternList{} - p.got(leftParen) - for p.tok != _EOF { - if w := p.word(); w.Parts == nil { - p.curErr("case patterns must consist of words") - } else { - pl.Patterns = append(pl.Patterns, w) - } - if p.tok == rightParen { - break - } - if !p.got(Or) { - p.curErr("case patterns must be separated with |") - } - } - old := p.preNested(switchCase) - p.next() - pl.Stmts = p.stmts("esac") - p.postNested(old) - pl.OpPos = p.pos - if p.tok != dblSemicolon && p.tok != semiFall && p.tok != dblSemiFall { - pl.Op = DblSemicolon - pls = append(pls, pl) - break - } - pl.Op = CaseOperator(p.tok) - p.next() - pls = append(pls, pl) - } - return -} - -func (p *parser) testClause() *TestClause { - tc := &TestClause{Left: p.pos} - p.next() - if p.tok == _EOF || p.gotRsrv("]]") { - p.posErr(tc.Left, "test clause requires at least one expression") - } - tc.X = p.testExpr(illegalTok, tc.Left, 0) - tc.Right = p.pos - if !p.gotRsrv("]]") { - p.matchingErr(tc.Left, "[[", "]]") - } - return tc -} - -func (p *parser) testExpr(ftok Token, fpos Pos, level int) TestExpr { - var left TestExpr - if level > 1 { - left = p.testExprBase(ftok, fpos) - } else { - left = p.testExpr(ftok, fpos, level+1) - } - if left == nil { - return left - } - var newLevel int - switch p.tok { - case AndExpr, OrExpr: - case _LitWord: - if p.val == "]]" { - return left - } - fallthrough - case Lss, Gtr: - newLevel = 1 - case _EOF, rightParen: - return left - default: - p.curErr("not a valid test operator: %v", p.tok) - } - if newLevel < level { - return left - } - if p.tok == _LitWord { - if p.tok = testBinaryOp(p.val); p.tok == illegalTok { - p.curErr("not a valid test operator: %s", p.val) - } - } - b := &BinaryTest{ - OpPos: p.pos, - Op: BinTestOperator(p.tok), - X: left, - } - if b.Op == TsReMatch { - old := p.preNested(testRegexp) - p.next() - p.postNested(old) - } else { - p.next() - } - if b.Y = p.testExpr(Token(b.Op), b.OpPos, newLevel); b.Y == nil { - p.followErr(b.OpPos, b.Op.String(), "an expression") - } - return b -} - -func (p *parser) testExprBase(ftok Token, fpos Pos) TestExpr { - switch p.tok { - case _EOF: - return nil - case _LitWord: - if op := testUnaryOp(p.val); op != illegalTok { - p.tok = op - } - } - switch p.tok { - case Not: - u := &UnaryTest{OpPos: p.pos, Op: TsNot} - p.next() - u.X = p.testExpr(Token(u.Op), u.OpPos, 0) - return u - case tsExists, tsRegFile, tsDirect, tsCharSp, tsBlckSp, tsNmPipe, tsSocket, tsSmbLink, - tsGIDSet, tsUIDSet, tsRead, tsWrite, tsExec, tsNoEmpty, tsFdTerm, tsEmpStr, - tsNempStr, tsOptSet, tsVarSet, tsRefVar: - u := &UnaryTest{OpPos: p.pos, Op: UnTestOperator(p.tok)} - p.next() - w := p.followWordTok(ftok, fpos) - u.X = &w - return u - case leftParen: - pe := &ParenTest{Lparen: p.pos} - p.next() - if pe.X = p.testExpr(leftParen, pe.Lparen, 0); pe.X == nil { - p.posErr(pe.Lparen, "parentheses must enclose an expression") - } - pe.Rparen = p.matched(pe.Lparen, leftParen, rightParen) - return pe - case rightParen: - default: - w := p.followWordTok(ftok, fpos) - return &w - } - return nil -} - -func (p *parser) declClause() *DeclClause { - name := p.val - ds := &DeclClause{Position: p.pos} - switch name { - case "declare", "typeset": // typeset is an obsolete synonym - default: - ds.Variant = name - } - p.next() - for p.tok == _LitWord && p.val[0] == '-' { - ds.Opts = append(ds.Opts, p.word()) - } - for !p.newLine && !stopToken(p.tok) && !p.peekRedir() { - if (p.tok == _Lit || p.tok == _LitWord) && p.validIdent() { - ds.Assigns = append(ds.Assigns, p.getAssign()) - } else if w := p.word(); w.Parts == nil { - p.followErr(p.pos, name, "words") - } else { - ds.Assigns = append(ds.Assigns, &Assign{Value: w}) - } - } - return ds -} - -func (p *parser) evalClause() *EvalClause { - ec := &EvalClause{Eval: p.pos} - p.next() - ec.Stmt, _ = p.getStmt(false) - return ec -} - -func isBashCompoundCommand(tok Token, val string) bool { - switch tok { - case leftParen, dblLeftParen: - return true - case _LitWord: - switch val { - case "{", "if", "while", "until", "for", "case", "[[", "eval", - "coproc", "let", "function": - return true - } - if bashDeclareWord(val) { - return true - } - } - return false -} - -func (p *parser) coprocClause() *CoprocClause { - cc := &CoprocClause{Coproc: p.pos} - p.next() - if isBashCompoundCommand(p.tok, p.val) { - // has no name - cc.Stmt, _ = p.getStmt(false) - return cc - } - if p.newLine { - p.posErr(cc.Coproc, "coproc clause requires a command") - } - var l Lit - if p.gotLit(&l) { - cc.Name = &l - } - cc.Stmt, _ = p.getStmt(false) - if cc.Stmt == nil { - if cc.Name == nil { - p.posErr(cc.Coproc, "coproc clause requires a command") - return nil - } - // name was in fact the stmt - cc.Stmt = &Stmt{ - Position: cc.Name.ValuePos, - Cmd: &CallExpr{Args: []Word{ - {Parts: p.singleWps(cc.Name)}, - }}, - } - cc.Name = nil - } else if cc.Name != nil { - if call, ok := cc.Stmt.Cmd.(*CallExpr); ok { - // name was in fact the start of a call - call.Args = append([]Word{{Parts: p.singleWps(cc.Name)}}, - call.Args...) - cc.Name = nil - } - } - return cc -} - -func (p *parser) letClause() *LetClause { - lc := &LetClause{Let: p.pos} - old := p.preNested(arithmExprLet) - p.next() - for !p.newLine && !stopToken(p.tok) && !p.peekRedir() { - x := p.arithmExpr(illegalTok, lc.Let, 0, true) - if x == nil { - break - } - lc.Exprs = append(lc.Exprs, x) - } - if len(lc.Exprs) == 0 { - p.posErr(lc.Let, "let clause requires at least one expression") - } - p.postNested(old) - if p.tok == illegalTok { - p.next() - } - return lc -} - -func (p *parser) bashFuncDecl() *FuncDecl { - fpos := p.pos - p.next() - if p.tok != _LitWord { - if w := p.followWord("function", fpos); p.err == nil { - rawName := string(p.src[w.Pos()-1 : w.End()-1]) - p.posErr(w.Pos(), "invalid func name: %q", rawName) - } - } - name := Lit{ValuePos: p.pos, Value: p.val} - p.next() - if p.gotSameLine(leftParen) { - p.follow(name.ValuePos, "foo(", rightParen) - } - return p.funcDecl(name, fpos) -} - -func (p *parser) callExpr(s *Stmt, w Word) *CallExpr { - alloc := &struct { - ce CallExpr - ws [4]Word - }{} - ce := &alloc.ce - ce.Args = alloc.ws[:1] - ce.Args[0] = w - for !p.newLine { - switch p.tok { - case _EOF, semicolon, And, Or, AndExpr, OrExpr, pipeAll, - dblSemicolon, semiFall, dblSemiFall: - return ce - case _LitWord: - if litRedir(p.src, p.npos) { - p.doRedirect(s) - continue - } - ce.Args = append(ce.Args, Word{ - Parts: p.singleWps(p.lit(p.pos, p.val)), - }) - p.next() - case bckQuote: - if p.quote == subCmdBckquo { - return ce - } - fallthrough - case _Lit, dollBrace, dollDblParen, dollParen, dollar, cmdIn, cmdOut, - sglQuote, dollSglQuote, dblQuote, dollDblQuote, dollBrack, globQuest, - globMul, globAdd, globAt, globNot: - ce.Args = append(ce.Args, Word{Parts: p.wordParts()}) - case Gtr, Shr, Lss, dplIn, dplOut, clbOut, rdrInOut, Shl, - dashHdoc, wordHdoc, rdrAll, appAll: - p.doRedirect(s) - case rightParen: - if p.quote == subCmd { - return ce - } - fallthrough - default: - p.curErr("a command can only contain words and redirects") - } - } - return ce -} - -func (p *parser) funcDecl(name Lit, pos Pos) *FuncDecl { - fd := &FuncDecl{ - Position: pos, - BashStyle: pos != name.ValuePos, - Name: name, - } - if fd.Body, _ = p.getStmt(false); fd.Body == nil { - p.followErr(fd.Pos(), "foo()", "a statement") - } - return fd -} diff --git a/vendor/github.com/mvdan/sh/syntax/printer.go b/vendor/github.com/mvdan/sh/syntax/printer.go deleted file mode 100644 index 4141f054d7..0000000000 --- a/vendor/github.com/mvdan/sh/syntax/printer.go +++ /dev/null @@ -1,1147 +0,0 @@ -// Copyright (c) 2016, Daniel Martí -// See LICENSE for licensing information - -package syntax - -import ( - "bufio" - "io" - "sync" -) - -// PrintConfig controls how the printing of an AST node will behave. -type PrintConfig struct { - Spaces int // 0 (default) for tabs, >0 for number of spaces -} - -var printerFree = sync.Pool{ - New: func() interface{} { - return &printer{bufWriter: bufio.NewWriter(nil)} - }, -} - -// Fprint "pretty-prints" the given AST file to the given writer. -func (c PrintConfig) Fprint(w io.Writer, f *File) error { - p := printerFree.Get().(*printer) - p.reset() - p.f, p.c = f, c - p.comments = f.Comments - p.bufWriter.Reset(w) - p.stmts(f.Stmts) - p.commentsUpTo(0) - p.newline(0) - err := p.bufWriter.Flush() - printerFree.Put(p) - return err -} - -// Fprint "pretty-prints" the given AST file to the given writer. It -// calls PrintConfig.Fprint with its default settings. -func Fprint(w io.Writer, f *File) error { - return PrintConfig{}.Fprint(w, f) -} - -type bufWriter interface { - WriteByte(byte) error - WriteString(string) (int, error) - Reset(io.Writer) - Flush() error -} - -type printer struct { - bufWriter - - f *File - c PrintConfig - - wantSpace bool - wantNewline bool - wroteSemi bool - - commentPadding int - - // nline is the position of the next newline - nline Pos - nlineIndex int - - // lastLevel is the last level of indentation that was used. - lastLevel int - // level is the current level of indentation. - level int - // levelIncs records which indentation level increments actually - // took place, to revert them once their section ends. - levelIncs []bool - - nestedBinary bool - - // comments is the list of pending comments to write. - comments []*Comment - - // pendingHdocs is the list of pending heredocs to write. - pendingHdocs []*Redirect - - // used in stmtLen to align comments - lenPrinter *printer - lenCounter byteCounter -} - -func (p *printer) reset() { - p.wantSpace, p.wantNewline = false, false - p.commentPadding = 0 - p.nline, p.nlineIndex = 0, 0 - p.lastLevel, p.level = 0, 0 - p.levelIncs = p.levelIncs[:0] - p.nestedBinary = false - p.pendingHdocs = p.pendingHdocs[:0] -} - -func (p *printer) incLine() { - if p.nlineIndex++; p.nlineIndex >= len(p.f.Lines) { - p.nline = maxPos - } else { - p.nline = Pos(p.f.Lines[p.nlineIndex]) - } -} - -func (p *printer) incLines(pos Pos) { - for p.nline < pos { - p.incLine() - } -} - -func (p *printer) space() { - p.WriteByte(' ') - p.wantSpace = false -} - -func (p *printer) spaces(n int) { - for i := 0; i < n; i++ { - p.WriteByte(' ') - } -} - -func (p *printer) tabs(n int) { - for i := 0; i < n; i++ { - p.WriteByte('\t') - } -} - -func (p *printer) bslashNewl() { - p.WriteString(" \\\n") - p.wantSpace = false - p.incLine() -} - -func (p *printer) spacedString(s string, spaceAfter bool) { - if p.wantSpace { - p.WriteByte(' ') - } - p.WriteString(s) - p.wantSpace = spaceAfter -} - -func (p *printer) semiOrNewl(s string, pos Pos) { - if p.wantNewline { - p.newline(pos) - p.indent() - } else { - if !p.wroteSemi { - p.WriteByte(';') - } - p.WriteByte(' ') - } - p.incLines(pos) - p.WriteString(s) - p.wantSpace = true -} - -func (p *printer) incLevel() { - inc := false - if p.level <= p.lastLevel { - p.level++ - inc = true - } else if last := &p.levelIncs[len(p.levelIncs)-1]; *last { - *last = false - inc = true - } - p.levelIncs = append(p.levelIncs, inc) -} - -func (p *printer) decLevel() { - if p.levelIncs[len(p.levelIncs)-1] { - p.level-- - } - p.levelIncs = p.levelIncs[:len(p.levelIncs)-1] -} - -func (p *printer) indent() { - p.lastLevel = p.level - switch { - case p.level == 0: - case p.c.Spaces == 0: - p.tabs(p.level) - case p.c.Spaces > 0: - p.spaces(p.c.Spaces * p.level) - } -} - -func (p *printer) newline(pos Pos) { - p.wantNewline, p.wantSpace = false, false - p.WriteByte('\n') - if pos > p.nline { - p.incLine() - } - hdocs := p.pendingHdocs - p.pendingHdocs = p.pendingHdocs[:0] - for _, r := range hdocs { - p.word(r.Hdoc) - p.incLines(r.Hdoc.End() + 1) - p.unquotedWord(r.Word) - p.WriteByte('\n') - p.incLine() - p.wantSpace = false - } -} - -func (p *printer) newlines(pos Pos) { - p.newline(pos) - if pos > p.nline { - // preserve single empty lines - p.WriteByte('\n') - p.incLine() - } - p.indent() -} - -func (p *printer) commentsAndSeparate(pos Pos) { - p.commentsUpTo(pos) - if p.wantNewline || pos > p.nline { - p.newlines(pos) - } -} - -func (p *printer) sepTok(s string, pos Pos) { - p.level++ - p.commentsUpTo(pos) - p.level-- - if p.wantNewline || pos > p.nline { - p.newlines(pos) - } - p.WriteString(s) - p.wantSpace = true -} - -func (p *printer) semiRsrv(s string, pos Pos, fallback bool) { - p.level++ - p.commentsUpTo(pos) - p.level-- - if p.wantNewline || pos > p.nline { - p.newlines(pos) - } else if fallback { - if !p.wroteSemi { - p.WriteByte(';') - } - p.WriteByte(' ') - } else if p.wantSpace { - p.WriteByte(' ') - } - p.WriteString(s) - p.wantSpace = true -} - -func (p *printer) commentsUpTo(pos Pos) { - if len(p.comments) < 1 { - return - } - c := p.comments[0] - if pos > 0 && c.Hash >= pos { - return - } - p.comments = p.comments[1:] - switch { - case p.nlineIndex == 0: - case c.Hash >= p.nline: - p.newlines(c.Hash) - default: - p.spaces(p.commentPadding + 1) - } - p.incLines(c.Hash) - p.WriteByte('#') - p.WriteString(c.Text) - p.commentsUpTo(pos) -} - -func (p *printer) expansionOp(op ParExpOperator) { - switch op { - case SubstAdd: - p.WriteByte('+') - case SubstColAdd: - p.WriteString(":+") - case SubstSub: - p.WriteByte('-') - case SubstColSub: - p.WriteString(":-") - case SubstQuest: - p.WriteByte('?') - case SubstColQuest: - p.WriteString(":?") - case SubstAssgn: - p.WriteByte('=') - case SubstColAssgn: - p.WriteString(":=") - case RemSmallSuffix: - p.WriteByte('%') - case RemLargeSuffix: - p.WriteString("%%") - case RemSmallPrefix: - p.WriteByte('#') - case RemLargePrefix: - p.WriteString("##") - case UpperFirst: - p.WriteByte('^') - case UpperAll: - p.WriteString("^^") - case LowerFirst: - p.WriteByte(',') - default: // LowerAll - p.WriteString(",,") - } -} - -func (p *printer) wordPart(wp WordPart) { - switch x := wp.(type) { - case *Lit: - p.WriteString(x.Value) - case *SglQuoted: - if x.Dollar { - p.WriteByte('$') - } - p.WriteByte('\'') - p.WriteString(x.Value) - p.WriteByte('\'') - p.incLines(x.End()) - case *DblQuoted: - if x.Dollar { - p.WriteByte('$') - } - p.WriteByte('"') - for i, n := range x.Parts { - p.wordPart(n) - if i == len(x.Parts)-1 { - p.incLines(n.End()) - } - } - p.WriteByte('"') - case *CmdSubst: - p.incLines(x.Pos()) - p.WriteString("$(") - p.wantSpace = len(x.Stmts) > 0 && startsWithLparen(x.Stmts[0]) - p.nestedStmts(x.Stmts, x.Right) - p.sepTok(")", x.Right) - case *ParamExp: - if x.Short { - p.WriteByte('$') - p.WriteString(x.Param.Value) - break - } - p.WriteString("${") - if x.Length { - p.WriteByte('#') - } - p.WriteString(x.Param.Value) - if x.Ind != nil { - p.WriteByte('[') - p.word(x.Ind.Word) - p.WriteByte(']') - } - if x.Slice != nil { - p.WriteByte(':') - p.word(x.Slice.Offset) - if w2 := x.Slice.Length; w2.Parts != nil { - p.WriteByte(':') - p.word(w2) - } - } else if x.Repl != nil { - if x.Repl.All { - p.WriteByte('/') - } - p.WriteByte('/') - p.word(x.Repl.Orig) - p.WriteByte('/') - p.word(x.Repl.With) - } else if x.Exp != nil { - p.expansionOp(x.Exp.Op) - p.word(x.Exp.Word) - } - p.WriteByte('}') - case *ArithmExp: - p.WriteString("$((") - p.arithmExpr(x.X, false) - p.WriteString("))") - case *ArrayExpr: - p.wantSpace = false - p.WriteByte('(') - p.wordJoin(x.List, false) - p.sepTok(")", x.Rparen) - case *ExtGlob: - p.wantSpace = false - p.WriteString(x.Op.String()) - p.WriteString(x.Pattern.Value) - p.WriteByte(')') - case *ProcSubst: - // avoid conflict with << and others - if p.wantSpace { - p.space() - } - switch x.Op { - case CmdIn: - p.WriteString("<(") - default: // CmdOut - p.WriteString(">(") - } - p.nestedStmts(x.Stmts, 0) - p.WriteByte(')') - } - p.wantSpace = true -} - -func (p *printer) loop(loop Loop) { - switch x := loop.(type) { - case *WordIter: - p.WriteString(x.Name.Value) - if len(x.List) > 0 { - p.WriteString(" in") - p.wordJoin(x.List, true) - } - case *CStyleLoop: - p.WriteString("((") - if x.Init == nil { - p.WriteByte(' ') - } - p.arithmExpr(x.Init, false) - p.WriteString("; ") - p.arithmExpr(x.Cond, false) - p.WriteString("; ") - p.arithmExpr(x.Post, false) - p.WriteString("))") - } -} - -func (p *printer) binaryExprOp(tok Token) { - switch tok { - case Assgn: - p.WriteByte('=') - case Add: - p.WriteByte('+') - case Sub: - p.WriteByte('-') - case Rem: - p.WriteByte('%') - case Mul: - p.WriteByte('*') - case Quo: - p.WriteByte('/') - case And: - p.WriteByte('&') - case Or: - p.WriteByte('|') - case AndExpr: - p.WriteString("&&") - case OrExpr: - p.WriteString("||") - case Xor: - p.WriteByte('^') - case Pow: - p.WriteString("**") - case Eql: - p.WriteString("==") - case Neq: - p.WriteString("!=") - case Leq: - p.WriteString("<=") - case Geq: - p.WriteString(">=") - case AddAssgn: - p.WriteString("+=") - case SubAssgn: - p.WriteString("-=") - case MulAssgn: - p.WriteString("*=") - case QuoAssgn: - p.WriteString("/=") - case RemAssgn: - p.WriteString("%=") - case AndAssgn: - p.WriteString("&=") - case OrAssgn: - p.WriteString("|=") - case XorAssgn: - p.WriteString("^=") - case ShlAssgn: - p.WriteString("<<=") - case ShrAssgn: - p.WriteString(">>=") - case Lss: - p.WriteByte('<') - case Gtr: - p.WriteByte('>') - case Shl: - p.WriteString("<<") - case Shr: - p.WriteString(">>") - case Quest: - p.WriteByte('?') - case Colon: - p.WriteByte(':') - default: // Comma - p.WriteByte(',') - } -} - -func (p *printer) unaryExprOp(tok Token) { - switch tok { - case Add: - p.WriteByte('+') - case Sub: - p.WriteByte('-') - case Not: - p.WriteByte('!') - case Inc: - p.WriteString("++") - default: // Dec - p.WriteString("--") - } -} - -func (p *printer) arithmExpr(expr ArithmExpr, compact bool) { - p.wantSpace = false - switch x := expr.(type) { - case *Word: - p.word(*x) - case *BinaryArithm: - if compact { - p.arithmExpr(x.X, compact) - p.binaryExprOp(x.Op) - p.arithmExpr(x.Y, compact) - } else { - p.arithmExpr(x.X, compact) - if x.Op != Comma { - p.WriteByte(' ') - } - p.binaryExprOp(x.Op) - p.space() - p.arithmExpr(x.Y, compact) - } - case *UnaryArithm: - if x.Post { - p.arithmExpr(x.X, compact) - p.unaryExprOp(x.Op) - } else { - p.unaryExprOp(x.Op) - p.arithmExpr(x.X, compact) - } - case *ParenArithm: - p.WriteByte('(') - p.arithmExpr(x.X, false) - p.WriteByte(')') - } -} - -func (p *printer) unaryTestOp(op UnTestOperator) { - switch op { - case TsNot: - p.WriteByte('!') - case TsExists: - p.WriteString("-e") - case TsRegFile: - p.WriteString("-f") - case TsDirect: - p.WriteString("-d") - case TsCharSp: - p.WriteString("-c") - case TsBlckSp: - p.WriteString("-b") - case TsNmPipe: - p.WriteString("-p") - case TsSocket: - p.WriteString("-S") - case TsSmbLink: - p.WriteString("-L") - case TsGIDSet: - p.WriteString("-g") - case TsUIDSet: - p.WriteString("-u") - case TsRead: - p.WriteString("-r") - case TsWrite: - p.WriteString("-w") - case TsExec: - p.WriteString("-x") - case TsNoEmpty: - p.WriteString("-s") - case TsFdTerm: - p.WriteString("-t") - case TsEmpStr: - p.WriteString("-z") - case TsNempStr: - p.WriteString("-n") - case TsOptSet: - p.WriteString("-o") - case TsVarSet: - p.WriteString("-v") - default: // TsRefVar - p.WriteString("-R") - } -} - -func (p *printer) binaryTestOp(op BinTestOperator) { - switch op { - case AndTest: - p.WriteString("&&") - case OrTest: - p.WriteString("||") - case TsAssgn: - p.WriteByte('=') - case TsEqual: - p.WriteString("==") - case TsNequal: - p.WriteString("!=") - case TsReMatch: - p.WriteString("=~") - case TsNewer: - p.WriteString("-nt") - case TsOlder: - p.WriteString("-ot") - case TsDevIno: - p.WriteString("-ef") - case TsEql: - p.WriteString("-eq") - case TsNeq: - p.WriteString("-ne") - case TsLeq: - p.WriteString("-le") - case TsGeq: - p.WriteString("-ge") - case TsLss: - p.WriteString("-lt") - case TsGtr: - p.WriteString("-gt") - case TsBefore: - p.WriteByte('<') - case TsAfter: - p.WriteByte('>') - } -} - -func (p *printer) testExpr(expr TestExpr) { - p.wantSpace = false - switch x := expr.(type) { - case *Word: - p.word(*x) - case *BinaryTest: - p.testExpr(x.X) - p.space() - p.binaryTestOp(x.Op) - p.space() - p.testExpr(x.Y) - case *UnaryTest: - p.unaryTestOp(x.Op) - p.space() - p.testExpr(x.X) - case *ParenTest: - p.WriteByte('(') - p.testExpr(x.X) - p.WriteByte(')') - } -} - -func (p *printer) word(w Word) { - for _, n := range w.Parts { - p.wordPart(n) - } -} - -func (p *printer) unquotedWord(w Word) { - for _, wp := range w.Parts { - switch x := wp.(type) { - case *SglQuoted: - p.WriteString(x.Value) - case *DblQuoted: - for _, qp := range x.Parts { - p.wordPart(qp) - } - case *Lit: - if x.Value[0] == '\\' { - p.WriteString(x.Value[1:]) - } else { - p.WriteString(x.Value) - } - default: - p.wordPart(wp) - } - } -} - -func (p *printer) wordJoin(ws []Word, backslash bool) { - anyNewline := false - for _, w := range ws { - if pos := w.Pos(); pos > p.nline { - p.commentsUpTo(pos) - if backslash { - p.bslashNewl() - } else { - p.WriteByte('\n') - p.incLine() - } - if !anyNewline { - p.incLevel() - anyNewline = true - } - p.indent() - } else if p.wantSpace { - p.space() - } - for _, n := range w.Parts { - p.wordPart(n) - } - } - if anyNewline { - p.decLevel() - } -} - -func (p *printer) stmt(s *Stmt) { - if s.Negated { - p.spacedString("!", true) - } - p.assigns(s.Assigns) - startRedirs := p.command(s.Cmd, s.Redirs) - anyNewline := false - for _, r := range s.Redirs[startRedirs:] { - if r.OpPos > p.nline { - p.bslashNewl() - if !anyNewline { - p.incLevel() - anyNewline = true - } - p.indent() - } - p.commentsAndSeparate(r.OpPos) - if p.wantSpace { - p.WriteByte(' ') - } - if r.N != nil { - p.WriteString(r.N.Value) - } - p.redirectOp(r.Op) - p.wantSpace = true - p.word(r.Word) - if r.Op == Hdoc || r.Op == DashHdoc { - p.pendingHdocs = append(p.pendingHdocs, r) - } - } - p.wroteSemi = false - if s.SemiPos > 0 && s.SemiPos > p.nline { - p.incLevel() - p.bslashNewl() - p.indent() - p.decLevel() - p.WriteByte(';') - p.wroteSemi = true - } else if s.Background { - p.WriteString(" &") - } - if anyNewline { - p.decLevel() - } -} - -func (p *printer) redirectOp(op RedirOperator) { - switch op { - case RdrIn: - p.WriteByte('<') - case RdrOut: - p.WriteByte('>') - case Hdoc: - p.WriteString("<<") - case AppOut: - p.WriteString(">>") - case RdrInOut: - p.WriteString("<>") - case DplIn: - p.WriteString("<&") - case DplOut: - p.WriteString(">&") - case ClbOut: - p.WriteString(">|") - case DashHdoc: - p.WriteString("<<-") - case WordHdoc: - p.WriteString("<<<") - case RdrAll: - p.WriteString("&>") - default: // AppAll - p.WriteString("&>>") - } -} - -func binaryCmdOp(op BinCmdOperator) string { - switch op { - case AndStmt: - return "&&" - case OrStmt: - return "||" - case Pipe: - return "|" - default: // PipeAll - return "|&" - } -} - -func caseClauseOp(op CaseOperator) string { - switch op { - case DblSemicolon: - return ";;" - case SemiFall: - return ";&" - default: // DblSemiFall - return ";;&" - } -} - -func (p *printer) command(cmd Command, redirs []*Redirect) (startRedirs int) { - switch x := cmd.(type) { - case *CallExpr: - if len(x.Args) <= 1 { - p.wordJoin(x.Args, true) - return 0 - } - p.wordJoin(x.Args[:1], true) - for _, r := range redirs { - if r.Pos() > x.Args[1].Pos() || r.Op == Hdoc || r.Op == DashHdoc { - break - } - if p.wantSpace { - p.space() - } - if r.N != nil { - p.WriteString(r.N.Value) - } - p.redirectOp(r.Op) - p.wantSpace = true - p.word(r.Word) - startRedirs++ - } - p.wordJoin(x.Args[1:], true) - case *Block: - p.spacedString("{", true) - p.nestedStmts(x.Stmts, x.Rbrace) - p.semiRsrv("}", x.Rbrace, true) - case *IfClause: - p.spacedString("if", true) - p.nestedStmts(x.CondStmts, 0) - p.semiOrNewl("then", x.Then) - p.nestedStmts(x.ThenStmts, 0) - for _, el := range x.Elifs { - p.semiRsrv("elif", el.Elif, true) - p.nestedStmts(el.CondStmts, 0) - p.semiOrNewl("then", el.Then) - p.nestedStmts(el.ThenStmts, 0) - } - if len(x.ElseStmts) > 0 { - p.semiRsrv("else", x.Else, true) - p.nestedStmts(x.ElseStmts, 0) - } else if x.Else > 0 { - p.incLines(x.Else) - } - p.semiRsrv("fi", x.Fi, true) - case *Subshell: - p.spacedString("(", false) - p.wantSpace = len(x.Stmts) > 0 && startsWithLparen(x.Stmts[0]) - p.nestedStmts(x.Stmts, x.Rparen) - p.sepTok(")", x.Rparen) - case *WhileClause: - p.spacedString("while", true) - p.nestedStmts(x.CondStmts, 0) - p.semiOrNewl("do", x.Do) - p.nestedStmts(x.DoStmts, 0) - p.semiRsrv("done", x.Done, true) - case *ForClause: - p.spacedString("for ", true) - p.loop(x.Loop) - p.semiOrNewl("do", x.Do) - p.nestedStmts(x.DoStmts, 0) - p.semiRsrv("done", x.Done, true) - case *BinaryCmd: - p.stmt(x.X) - indent := !p.nestedBinary - if indent { - p.incLevel() - } - _, p.nestedBinary = x.Y.Cmd.(*BinaryCmd) - if len(p.pendingHdocs) == 0 && x.Y.Pos() > p.nline { - p.bslashNewl() - p.indent() - } - p.spacedString(binaryCmdOp(x.Op), true) - p.incLines(x.Y.Pos()) - p.stmt(x.Y) - if indent { - p.decLevel() - } - p.nestedBinary = false - case *FuncDecl: - if x.BashStyle { - p.WriteString("function ") - } - p.WriteString(x.Name.Value) - p.WriteString("() ") - p.incLines(x.Body.Pos()) - p.stmt(x.Body) - case *CaseClause: - p.spacedString("case ", true) - p.word(x.Word) - p.WriteString(" in") - p.incLevel() - for _, pl := range x.List { - p.commentsAndSeparate(pl.Patterns[0].Pos()) - for i, w := range pl.Patterns { - if i > 0 { - p.spacedString("|", true) - } - if p.wantSpace { - p.WriteByte(' ') - } - for _, n := range w.Parts { - p.wordPart(n) - } - } - p.WriteByte(')') - sep := len(pl.Stmts) > 1 || (len(pl.Stmts) > 0 && pl.Stmts[0].Pos() > p.nline) - p.nestedStmts(pl.Stmts, 0) - p.level++ - if sep { - p.sepTok(caseClauseOp(pl.Op), pl.OpPos) - } else { - p.spacedString(caseClauseOp(pl.Op), true) - } - p.incLines(pl.OpPos) - p.level-- - if sep || pl.OpPos == x.Esac { - p.wantNewline = true - } - } - p.decLevel() - p.semiRsrv("esac", x.Esac, len(x.List) == 0) - case *UntilClause: - p.spacedString("until", true) - p.nestedStmts(x.CondStmts, 0) - p.semiOrNewl("do", x.Do) - p.nestedStmts(x.DoStmts, 0) - p.semiRsrv("done", x.Done, true) - case *ArithmCmd: - if p.wantSpace { - p.space() - } - p.WriteString("((") - p.arithmExpr(x.X, false) - p.WriteString("))") - case *TestClause: - p.spacedString("[[", true) - p.space() - p.testExpr(x.X) - p.spacedString("]]", true) - case *DeclClause: - name := x.Variant - if name == "" { - name = "declare" - } - p.spacedString(name, true) - for _, w := range x.Opts { - p.WriteByte(' ') - p.word(w) - } - p.assigns(x.Assigns) - case *EvalClause: - p.spacedString("eval", true) - if x.Stmt != nil { - p.stmt(x.Stmt) - } - case *CoprocClause: - p.spacedString("coproc", true) - if x.Name != nil { - p.WriteByte(' ') - p.WriteString(x.Name.Value) - } - p.stmt(x.Stmt) - case *LetClause: - p.spacedString("let", true) - for _, n := range x.Exprs { - p.space() - p.arithmExpr(n, true) - } - } - return startRedirs -} - -func startsWithLparen(s *Stmt) bool { - switch x := s.Cmd.(type) { - case *Subshell: - return true - case *BinaryCmd: - return startsWithLparen(x.X) - } - return false -} - -func (p *printer) hasInline(pos, npos, nline Pos) bool { - for _, c := range p.comments { - if c.Hash > nline { - return false - } - if c.Hash > pos && (npos == 0 || c.Hash < npos) { - return true - } - } - return false -} - -func (p *printer) stmts(stmts []*Stmt) { - switch len(stmts) { - case 0: - return - case 1: - s := stmts[0] - pos := s.Pos() - p.commentsUpTo(pos) - if pos <= p.nline { - p.stmt(s) - } else { - if p.nlineIndex > 0 { - p.newlines(pos) - } else { - p.incLines(pos) - } - p.stmt(s) - p.wantNewline = true - } - return - } - inlineIndent := 0 - for i, s := range stmts { - pos := s.Pos() - ind := p.nlineIndex - p.commentsUpTo(pos) - if p.nlineIndex > 0 { - p.newlines(pos) - } - p.incLines(pos) - p.stmt(s) - var npos Pos - if i+1 < len(stmts) { - npos = stmts[i+1].Pos() - } - if !p.hasInline(pos, npos, p.nline) { - inlineIndent = 0 - p.commentPadding = 0 - continue - } - if ind < len(p.f.Lines)-1 && s.End() > Pos(p.f.Lines[ind+1]) { - inlineIndent = 0 - } - if inlineIndent == 0 { - ind2 := p.nlineIndex - nline2 := p.nline - follow := stmts[i:] - for j, s2 := range follow { - pos2 := s2.Pos() - var npos2 Pos - if j+1 < len(follow) { - npos2 = follow[j+1].Pos() - } - if pos2 > nline2 || !p.hasInline(pos2, npos2, nline2) { - break - } - if l := p.stmtLen(s2); l > inlineIndent { - inlineIndent = l - } - if ind2++; ind2 >= len(p.f.Lines) { - nline2 = maxPos - } else { - nline2 = Pos(p.f.Lines[ind2]) - } - } - if ind2 == p.nlineIndex+1 { - // no inline comments directly after this one - continue - } - } - if inlineIndent > 0 { - p.commentPadding = inlineIndent - p.stmtLen(s) - } - } - p.wantNewline = true -} - -type byteCounter int - -func (c *byteCounter) WriteByte(b byte) error { - *c++ - return nil -} -func (c *byteCounter) WriteString(s string) (int, error) { - *c += byteCounter(len(s)) - return 0, nil -} -func (c *byteCounter) Reset(io.Writer) { *c = 0 } -func (c *byteCounter) Flush() error { return nil } - -func (p *printer) stmtLen(s *Stmt) int { - if p.lenPrinter == nil { - p.lenPrinter = new(printer) - } - *p.lenPrinter = printer{bufWriter: &p.lenCounter} - p.lenPrinter.bufWriter.Reset(nil) - p.lenPrinter.f = p.f - p.lenPrinter.incLines(s.Pos()) - p.lenPrinter.stmt(s) - return int(p.lenCounter) -} - -func (p *printer) nestedStmts(stmts []*Stmt, closing Pos) { - p.incLevel() - if len(stmts) == 1 && closing > p.nline && stmts[0].End() <= p.nline { - p.newline(0) - p.indent() - } - p.stmts(stmts) - p.decLevel() -} - -func (p *printer) assigns(assigns []*Assign) { - anyNewline := false - for _, a := range assigns { - if a.Pos() > p.nline { - p.bslashNewl() - if !anyNewline { - p.incLevel() - anyNewline = true - } - p.indent() - } else if p.wantSpace { - p.space() - } - if a.Name != nil { - p.WriteString(a.Name.Value) - if a.Append { - p.WriteByte('+') - } - p.WriteByte('=') - } - p.word(a.Value) - p.wantSpace = true - } - if anyNewline { - p.decLevel() - } -} diff --git a/vendor/github.com/mvdan/sh/syntax/tokens.go b/vendor/github.com/mvdan/sh/syntax/tokens.go deleted file mode 100644 index dee108a259..0000000000 --- a/vendor/github.com/mvdan/sh/syntax/tokens.go +++ /dev/null @@ -1,423 +0,0 @@ -// Copyright (c) 2016, Daniel Martí -// See LICENSE for licensing information - -package syntax - -// Token is the set of lexical tokens and reserved words. -type Token int - -// The list of all possible tokens and reserved words. -const ( - illegalTok Token = iota - _EOF - _Lit - _LitWord - - sglQuote // ' - dblQuote // " - bckQuote // ` - - And // & - AndExpr // && - OrExpr // || - Or // | - pipeAll // |& - bash - - dollar // $ - dollSglQuote // $' - bash - dollDblQuote // $" - bash - dollBrace // ${ - dollBrack // $[ - dollParen // $( - dollDblParen // $(( - leftBrack // [ - leftParen // ( - dblLeftParen // (( - bash - - rightBrace // } - rightBrack // ] - rightParen // ) - dblRightParen // )) - semicolon // ; - - dblSemicolon // ;; - semiFall // ;& - bash - dblSemiFall // ;;& - bash - - Mul // * - Not // ! - Inc // ++ - Dec // -- - Pow // ** - Eql // == - Neq // != - Leq // <= - Geq // >= - - AddAssgn // += - SubAssgn // -= - MulAssgn // *= - QuoAssgn // /= - RemAssgn // %= - AndAssgn // &= - OrAssgn // |= - XorAssgn // ^= - ShlAssgn // <<= - ShrAssgn // >>= - - Gtr // > - Shr // >> - Lss // < - rdrInOut // <> - dplIn // <& - dplOut // >& - clbOut // >| - Shl // << - dashHdoc // <<- - wordHdoc // <<< - bash - rdrAll // &> - bash - appAll // &>> - bash - - cmdIn // <( - bash - cmdOut // >( - bash - - Add // + - ColAdd // :+ - Sub // - - ColSub // :- - Quest // ? - ColQuest // :? - Assgn // = - ColAssgn // := - Rem // % - dblRem // %% - Hash // # - dblHash // ## - Xor // ^ - dblXor // ^^ - bash - Comma // , - dblComma // ,, - bash - Quo // / - dblQuo // // - Colon // : - - tsNot // ! - tsExists // -e - tsRegFile // -f - tsDirect // -d - tsCharSp // -c - tsBlckSp // -b - tsNmPipe // -p - tsSocket // -S - tsSmbLink // -L - tsGIDSet // -g - tsUIDSet // -u - tsRead // -r - tsWrite // -w - tsExec // -x - tsNoEmpty // -s - tsFdTerm // -t - tsEmpStr // -z - tsNempStr // -n - tsOptSet // -o - tsVarSet // -v - tsRefVar // -R - - tsReMatch // =~ - tsNewer // -nt - tsOlder // -ot - tsDevIno // -ef - tsEql // -eq - tsNeq // -ne - tsLeq // -le - tsGeq // -ge - tsLss // -lt - tsGtr // -gt - - globQuest // ?( - globMul // *( - globAdd // +( - globAt // @( - globNot // !( -) - -type RedirOperator Token - -const ( - RdrOut = RedirOperator(Gtr) + iota - AppOut - RdrIn - RdrInOut - DplIn - DplOut - ClbOut - Hdoc - DashHdoc - WordHdoc - RdrAll - AppAll -) - -type ProcOperator Token - -const ( - CmdIn = ProcOperator(cmdIn) + iota - CmdOut -) - -type GlobOperator Token - -const ( - GlobQuest = GlobOperator(globQuest) + iota - GlobMul - GlobAdd - GlobAt - GlobNot -) - -type BinCmdOperator Token - -const ( - AndStmt = BinCmdOperator(AndExpr) + iota - OrStmt - Pipe - PipeAll -) - -type CaseOperator Token - -const ( - DblSemicolon = CaseOperator(dblSemicolon) + iota - SemiFall - DblSemiFall -) - -type ParExpOperator Token - -const ( - SubstAdd = ParExpOperator(Add) + iota - SubstColAdd - SubstSub - SubstColSub - SubstQuest - SubstColQuest - SubstAssgn - SubstColAssgn - RemSmallSuffix - RemLargeSuffix - RemSmallPrefix - RemLargePrefix - UpperFirst - UpperAll - LowerFirst - LowerAll -) - -type UnTestOperator Token - -const ( - TsNot = UnTestOperator(tsNot) + iota - TsExists - TsRegFile - TsDirect - TsCharSp - TsBlckSp - TsNmPipe - TsSocket - TsSmbLink - TsGIDSet - TsUIDSet - TsRead - TsWrite - TsExec - TsNoEmpty - TsFdTerm - TsEmpStr - TsNempStr - TsOptSet - TsVarSet - TsRefVar -) - -type BinTestOperator Token - -const ( - TsReMatch = BinTestOperator(tsReMatch) + iota - TsNewer - TsOlder - TsDevIno - TsEql - TsNeq - TsLeq - TsGeq - TsLss - TsGtr - AndTest = BinTestOperator(AndExpr) - OrTest = BinTestOperator(OrExpr) - TsAssgn = BinTestOperator(Assgn) - TsEqual = BinTestOperator(Eql) - TsNequal = BinTestOperator(Neq) - TsBefore = BinTestOperator(Lss) - TsAfter = BinTestOperator(Gtr) -) - -func (o RedirOperator) String() string { return Token(o).String() } -func (o ProcOperator) String() string { return Token(o).String() } -func (o GlobOperator) String() string { return Token(o).String() } -func (o BinCmdOperator) String() string { return Token(o).String() } -func (o CaseOperator) String() string { return Token(o).String() } -func (o ParExpOperator) String() string { return Token(o).String() } -func (o UnTestOperator) String() string { return Token(o).String() } -func (o BinTestOperator) String() string { return Token(o).String() } - -// Pos is the internal representation of a position within a source -// file. -type Pos int - -var defaultPos Pos - -const maxPos = Pos(^uint(0) >> 1) - -// Position describes a position within a source file including the line -// and column location. A Position is valid if the line number is > 0. -type Position struct { - Offset int // byte offset, starting at 0 - Line int // line number, starting at 1 - Column int // column number, starting at 1 (in bytes) -} - -var tokNames = map[Token]string{ - illegalTok: "illegal", - _EOF: "EOF", - _Lit: "Lit", - _LitWord: "LitWord", - - sglQuote: "'", - dblQuote: `"`, - bckQuote: "`", - - And: "&", - AndExpr: "&&", - OrExpr: "||", - Or: "|", - pipeAll: "|&", - - dollar: "$", - dollSglQuote: "$'", - dollDblQuote: `$"`, - dollBrace: "${", - dollBrack: "$[", - dollParen: "$(", - dollDblParen: "$((", - leftBrack: "[", - leftParen: "(", - dblLeftParen: "((", - - rightBrace: "}", - rightBrack: "]", - rightParen: ")", - dblRightParen: "))", - semicolon: ";", - - dblSemicolon: ";;", - semiFall: ";&", - dblSemiFall: ";;&", - - Gtr: ">", - Shr: ">>", - Lss: "<", - rdrInOut: "<>", - dplIn: "<&", - dplOut: ">&", - clbOut: ">|", - Shl: "<<", - dashHdoc: "<<-", - wordHdoc: "<<<", - rdrAll: "&>", - appAll: "&>>", - - cmdIn: "<(", - cmdOut: ">(", - - Add: "+", - ColAdd: ":+", - Sub: "-", - ColSub: ":-", - Quest: "?", - ColQuest: ":?", - Assgn: "=", - ColAssgn: ":=", - Rem: "%", - dblRem: "%%", - Hash: "#", - dblHash: "##", - Xor: "^", - dblXor: "^^", - Comma: ",", - dblComma: ",,", - Quo: "/", - dblQuo: "//", - Colon: ":", - - Mul: "*", - Not: "!", - Inc: "++", - Dec: "--", - Pow: "**", - Eql: "==", - Neq: "!=", - Leq: "<=", - Geq: ">=", - - AddAssgn: "+=", - SubAssgn: "-=", - MulAssgn: "*=", - QuoAssgn: "/=", - RemAssgn: "%=", - AndAssgn: "&=", - OrAssgn: "|=", - XorAssgn: "^=", - ShlAssgn: "<<=", - ShrAssgn: ">>=", - - tsNot: "!", - tsExists: "-e", - tsRegFile: "-f", - tsDirect: "-d", - tsCharSp: "-c", - tsBlckSp: "-b", - tsNmPipe: "-p", - tsSocket: "-S", - tsSmbLink: "-L", - tsGIDSet: "-g", - tsUIDSet: "-u", - tsRead: "-r", - tsWrite: "-w", - tsExec: "-x", - tsNoEmpty: "-s", - tsFdTerm: "-t", - tsEmpStr: "-z", - tsNempStr: "-n", - tsOptSet: "-o", - tsVarSet: "-v", - tsRefVar: "-R", - - tsReMatch: "=~", - tsNewer: "-nt", - tsOlder: "-ot", - tsDevIno: "-ef", - tsEql: "-eq", - tsNeq: "-ne", - tsLeq: "-le", - tsGeq: "-ge", - tsLss: "-lt", - tsGtr: "-gt", - - globQuest: "?(", - globMul: "*(", - globAdd: "+(", - globAt: "@(", - globNot: "!(", -} - -func (t Token) String() string { return tokNames[t] } diff --git a/vendor/github.com/mvdan/sh/syntax/walk.go b/vendor/github.com/mvdan/sh/syntax/walk.go deleted file mode 100644 index 76d3339086..0000000000 --- a/vendor/github.com/mvdan/sh/syntax/walk.go +++ /dev/null @@ -1,189 +0,0 @@ -// Copyright (c) 2016, Daniel Martí -// See LICENSE for licensing information - -package syntax - -import "fmt" - -// Visitor holds a Visit method which is invoked for each node -// encountered by Walk. If the result visitor w is not nil, Walk visits -// each of the children of node with the visitor w, followed by a call -// of w.Visit(nil). -type Visitor interface { - Visit(node Node) (w Visitor) -} - -func walkStmts(v Visitor, stmts []*Stmt) { - for _, s := range stmts { - Walk(v, s) - } -} - -func walkWords(v Visitor, words []Word) { - for i := range words { - Walk(v, &words[i]) - } -} - -// Walk traverses an AST in depth-first order: It starts by calling -// v.Visit(node); node must not be nil. If the visitor w returned by -// v.Visit(node) is not nil, Walk is invoked recursively with visitor w -// for each of the non-nil children of node, followed by a call of -// w.Visit(nil). -func Walk(v Visitor, node Node) { - if v = v.Visit(node); v == nil { - return - } - - switch x := node.(type) { - case *File: - walkStmts(v, x.Stmts) - case *Stmt: - if x.Cmd != nil { - Walk(v, x.Cmd) - } - for _, a := range x.Assigns { - Walk(v, a) - } - for _, r := range x.Redirs { - Walk(v, r) - } - case *Assign: - if x.Name != nil { - Walk(v, x.Name) - } - Walk(v, &x.Value) - case *Redirect: - if x.N != nil { - Walk(v, x.N) - } - Walk(v, &x.Word) - if len(x.Hdoc.Parts) > 0 { - Walk(v, &x.Hdoc) - } - case *CallExpr: - walkWords(v, x.Args) - case *Subshell: - walkStmts(v, x.Stmts) - case *Block: - walkStmts(v, x.Stmts) - case *IfClause: - walkStmts(v, x.CondStmts) - walkStmts(v, x.ThenStmts) - for _, elif := range x.Elifs { - walkStmts(v, elif.CondStmts) - walkStmts(v, elif.ThenStmts) - } - walkStmts(v, x.ElseStmts) - case *WhileClause: - walkStmts(v, x.CondStmts) - walkStmts(v, x.DoStmts) - case *UntilClause: - walkStmts(v, x.CondStmts) - walkStmts(v, x.DoStmts) - case *ForClause: - Walk(v, x.Loop) - walkStmts(v, x.DoStmts) - case *WordIter: - Walk(v, &x.Name) - walkWords(v, x.List) - case *CStyleLoop: - if x.Init != nil { - Walk(v, x.Init) - } - if x.Cond != nil { - Walk(v, x.Cond) - } - if x.Post != nil { - Walk(v, x.Post) - } - case *BinaryCmd: - Walk(v, x.X) - Walk(v, x.Y) - case *FuncDecl: - Walk(v, &x.Name) - Walk(v, x.Body) - case *Word: - for _, wp := range x.Parts { - Walk(v, wp) - } - case *Lit: - case *SglQuoted: - case *DblQuoted: - for _, wp := range x.Parts { - Walk(v, wp) - } - case *CmdSubst: - walkStmts(v, x.Stmts) - case *ParamExp: - Walk(v, &x.Param) - if x.Ind != nil { - Walk(v, &x.Ind.Word) - } - if x.Repl != nil { - Walk(v, &x.Repl.Orig) - Walk(v, &x.Repl.With) - } - if x.Exp != nil { - Walk(v, &x.Exp.Word) - } - case *ArithmExp: - if x.X != nil { - Walk(v, x.X) - } - case *ArithmCmd: - if x.X != nil { - Walk(v, x.X) - } - case *BinaryArithm: - Walk(v, x.X) - Walk(v, x.Y) - case *BinaryTest: - Walk(v, x.X) - Walk(v, x.Y) - case *UnaryArithm: - Walk(v, x.X) - case *UnaryTest: - Walk(v, x.X) - case *ParenArithm: - Walk(v, x.X) - case *ParenTest: - Walk(v, x.X) - case *CaseClause: - Walk(v, &x.Word) - for _, pl := range x.List { - walkWords(v, pl.Patterns) - walkStmts(v, pl.Stmts) - } - case *TestClause: - Walk(v, x.X) - case *DeclClause: - walkWords(v, x.Opts) - for _, a := range x.Assigns { - Walk(v, a) - } - case *ArrayExpr: - walkWords(v, x.List) - case *ExtGlob: - Walk(v, &x.Pattern) - case *ProcSubst: - walkStmts(v, x.Stmts) - case *EvalClause: - if x.Stmt != nil { - Walk(v, x.Stmt) - } - case *CoprocClause: - if x.Name != nil { - Walk(v, x.Name) - } - Walk(v, x.Stmt) - case *LetClause: - for _, expr := range x.Exprs { - Walk(v, expr) - } - default: - panic(fmt.Sprintf("ast.Walk: unexpected node type %T", x)) - } - - v.Visit(nil) -} diff --git a/vendor/manifest b/vendor/manifest deleted file mode 100644 index f6627d3e3b..0000000000 --- a/vendor/manifest +++ /dev/null @@ -1,13 +0,0 @@ -{ - "version": 0, - "dependencies": [ - { - "importpath": "github.com/mvdan/sh", - "repository": "https://github.com/mvdan/sh", - "vcs": "git", - "revision": "0a4761ee498179b93fe0efcd37758320c6ec73cd", - "branch": "HEAD", - "notests": true - } - ] -} \ No newline at end of file