package shellquote

import (
	
	
	
	
)

var (
	UnterminatedSingleQuoteError = errors.New("Unterminated single-quoted string")
	UnterminatedDoubleQuoteError = errors.New("Unterminated double-quoted string")
	UnterminatedEscapeError      = errors.New("Unterminated backslash-escape")
)

var (
	splitChars        = " \n\t"
	singleChar        = '\''
	doubleChar        = '"'
	escapeChar        = '\\'
	doubleEscapeChars = "$`\"\n\\"
)

// Split splits a string according to /bin/sh's word-splitting rules. It
// supports backslash-escapes, single-quotes, and double-quotes. Notably it does
// not support the $'' style of quoting. It also doesn't attempt to perform any
// other sort of expansion, including brace expansion, shell expansion, or
// pathname expansion.
//
// If the given input has an unterminated quoted string or ends in a
// backslash-escape, one of UnterminatedSingleQuoteError,
// UnterminatedDoubleQuoteError, or UnterminatedEscapeError is returned.
func ( string) ( []string,  error) {
	var  bytes.Buffer
	 = make([]string, 0)

	for len() > 0 {
		// skip any splitChars at the start
		,  := utf8.DecodeRuneInString()
		if strings.ContainsRune(splitChars, ) {
			 = [:]
			continue
		} else if  == escapeChar {
			// Look ahead for escaped newline so we can skip over it
			 := [:]
			if len() == 0 {
				 = UnterminatedEscapeError
				return
			}
			,  := utf8.DecodeRuneInString()
			if  == '\n' {
				 = [:]
				continue
			}
		}

		var  string
		, ,  = splitWord(, &)
		if  != nil {
			return
		}
		 = append(, )
	}
	return
}

func splitWord( string,  *bytes.Buffer) ( string,  string,  error) {
	.Reset()

:
	{
		 := 
		for len() > 0 {
			,  := utf8.DecodeRuneInString()
			 = [:]
			if  == singleChar {
				.WriteString([0 : len()-len()-])
				 = 
				goto 
			} else if  == doubleChar {
				.WriteString([0 : len()-len()-])
				 = 
				goto 
			} else if  == escapeChar {
				.WriteString([0 : len()-len()-])
				 = 
				goto 
			} else if strings.ContainsRune(splitChars, ) {
				.WriteString([0 : len()-len()-])
				return .String(), , nil
			}
		}
		if len() > 0 {
			.WriteString()
			 = ""
		}
		goto 
	}

:
	{
		if len() == 0 {
			return "", "", UnterminatedEscapeError
		}
		,  := utf8.DecodeRuneInString()
		if  == '\n' {
			// a backslash-escaped newline is elided from the output entirely
		} else {
			.WriteString([:])
		}
		 = [:]
	}
	goto 

:
	{
		 := strings.IndexRune(, singleChar)
		if  == -1 {
			return "", "", UnterminatedSingleQuoteError
		}
		.WriteString([0:])
		 = [+1:]
		goto 
	}

:
	{
		 := 
		for len() > 0 {
			,  := utf8.DecodeRuneInString()
			 = [:]
			if  == doubleChar {
				.WriteString([0 : len()-len()-])
				 = 
				goto 
			} else if  == escapeChar {
				// bash only supports certain escapes in double-quoted strings
				,  := utf8.DecodeRuneInString()
				 = [:]
				if strings.ContainsRune(doubleEscapeChars, ) {
					.WriteString([0 : len()-len()--])
					if  == '\n' {
						// newline is special, skip the backslash entirely
					} else {
						.WriteRune()
					}
					 = 
				}
			}
		}
		return "", "", UnterminatedDoubleQuoteError
	}

:
	return .String(), , nil
}