github.com/sams1990/dockerrepo@v17.12.1-ce-rc2+incompatible/builder/dockerfile/parser/split_command.go (about) 1 package parser 2 3 import ( 4 "strings" 5 "unicode" 6 ) 7 8 // splitCommand takes a single line of text and parses out the cmd and args, 9 // which are used for dispatching to more exact parsing functions. 10 func splitCommand(line string) (string, []string, string, error) { 11 var args string 12 var flags []string 13 14 // Make sure we get the same results irrespective of leading/trailing spaces 15 cmdline := tokenWhitespace.Split(strings.TrimSpace(line), 2) 16 cmd := strings.ToLower(cmdline[0]) 17 18 if len(cmdline) == 2 { 19 var err error 20 args, flags, err = extractBuilderFlags(cmdline[1]) 21 if err != nil { 22 return "", nil, "", err 23 } 24 } 25 26 return cmd, flags, strings.TrimSpace(args), nil 27 } 28 29 func extractBuilderFlags(line string) (string, []string, error) { 30 // Parses the BuilderFlags and returns the remaining part of the line 31 32 const ( 33 inSpaces = iota // looking for start of a word 34 inWord 35 inQuote 36 ) 37 38 words := []string{} 39 phase := inSpaces 40 word := "" 41 quote := '\000' 42 blankOK := false 43 var ch rune 44 45 for pos := 0; pos <= len(line); pos++ { 46 if pos != len(line) { 47 ch = rune(line[pos]) 48 } 49 50 if phase == inSpaces { // Looking for start of word 51 if pos == len(line) { // end of input 52 break 53 } 54 if unicode.IsSpace(ch) { // skip spaces 55 continue 56 } 57 58 // Only keep going if the next word starts with -- 59 if ch != '-' || pos+1 == len(line) || rune(line[pos+1]) != '-' { 60 return line[pos:], words, nil 61 } 62 63 phase = inWord // found something with "--", fall through 64 } 65 if (phase == inWord || phase == inQuote) && (pos == len(line)) { 66 if word != "--" && (blankOK || len(word) > 0) { 67 words = append(words, word) 68 } 69 break 70 } 71 if phase == inWord { 72 if unicode.IsSpace(ch) { 73 phase = inSpaces 74 if word == "--" { 75 return line[pos:], words, nil 76 } 77 if blankOK || len(word) > 0 { 78 words = append(words, word) 79 } 80 word = "" 81 blankOK = false 82 continue 83 } 84 if ch == '\'' || ch == '"' { 85 quote = ch 86 blankOK = true 87 phase = inQuote 88 continue 89 } 90 if ch == '\\' { 91 if pos+1 == len(line) { 92 continue // just skip \ at end 93 } 94 pos++ 95 ch = rune(line[pos]) 96 } 97 word += string(ch) 98 continue 99 } 100 if phase == inQuote { 101 if ch == quote { 102 phase = inWord 103 continue 104 } 105 if ch == '\\' { 106 if pos+1 == len(line) { 107 phase = inWord 108 continue // just skip \ at end 109 } 110 pos++ 111 ch = rune(line[pos]) 112 } 113 word += string(ch) 114 } 115 } 116 117 return "", words, nil 118 }