config/shconf/scan.go
func (s *Scanner) Scan() bool {
	var thisRune rune
	var n int
	var err error

	for s.line++; ; s.line++ {
		// Skip leading spaces.
		for thisRune, n, err = s.buf.ReadRune(); ; thisRune, _, err = s.buf.ReadRune() {
			if err != nil {
				s.err = err
				return false
			}

			if thisRune == '\n' {
				s.line++
				continue
			}
			if !unicode.IsSpace(thisRune) {
				break
			}
		}

		// Skip line comment and section.
		if thisRune == '#' || thisRune == '[' {
			if _, err = s.buf.ReadBytes('\n'); err != nil {
				s.err = err
				return false
			}
			continue
		}
		break
	}

	if thisRune == '=' {
		s.err = keyError(s.line)
		return false
	}

	var key, value, separator []rune

	// Get key

	for ; ; thisRune, n, err = s.buf.ReadRune() {
		if err != nil {
			if err != io.EOF {
				s.err = err
			} else {
				s.err = valueError(s.line)
			}
			return false
		}

		// The separator charater could the the equal sign or space.
		if thisRune == '=' || unicode.IsSpace(thisRune) {
			break
		}

		if n > 1 || !isValidChar(thisRune) {
			s.err = noASCIIKeyError(s.line)
			return false
		}
		key = append(key, thisRune)
	}

	// Skip spaces before and after of the separator character.

	if unicode.IsSpace(thisRune) {
		separator = append(separator, thisRune)

		for thisRune, _, err = s.buf.ReadRune(); ; thisRune, _, err = s.buf.ReadRune() {
			if err != nil {
				if err != io.EOF {
					s.err = err
				} else {
					s.err = valueError(s.line)
				}
				return false
			}

			if !unicode.IsSpace(thisRune) {
				break
			}
			separator = append(separator, thisRune)
		}
	}
	if thisRune == '=' {
		separator = append(separator, thisRune)

		if thisRune, _, err = s.buf.ReadRune(); err != nil {
			if err != io.EOF {
				s.err = err
			} else {
				s.err = valueError(s.line)
			}
			return false
		}
	}
	if unicode.IsSpace(thisRune) {
		separator = append(separator, thisRune)

		for thisRune, _, err = s.buf.ReadRune(); ; thisRune, _, err = s.buf.ReadRune() {
			if err != nil {
				if err != io.EOF {
					s.err = err
				} else {
					s.err = valueError(s.line)
				}
				return false
			}

			if !unicode.IsSpace(thisRune) {
				break
			}
			separator = append(separator, thisRune)
		}
	}

	// Get value

	var valueIsString, valueInDQuote bool
	var lastRune rune

	if thisRune == '"' { // The value is between double quotes
		valueIsString = true
		valueInDQuote = true
	} else if thisRune == '\'' { // between single quotes
		valueIsString = true
	} else {
		value = append(value, thisRune)
	}

	for thisRune, _, err = s.buf.ReadRune(); ; thisRune, _, err = s.buf.ReadRune() {
		if err != nil {
			if err != io.EOF {
				s.err = err
				return false
			}

			if valueIsString {
				s.err = openQuoteError(s.line)
				return false
			}
			s.err = err
			break
		}

		if valueIsString {
			if valueInDQuote {
				if thisRune == '"' && lastRune != '\\' {
					break
				}
			} else if thisRune == '\'' && lastRune != '\\' {
				break
			}
			lastRune = thisRune // To checking if it is a quote escaped.
			value = append(value, thisRune)

		} else {
			if unicode.IsSpace(thisRune) {
				break
			}
			value = append(value, thisRune)
		}
	}

	// Sanity check
	if thisRune != '\n' && thisRune != '\r' {
		doCheck := true
		last, _, err := s.buf.ReadLine()
		if err != nil {
			if err != io.EOF {
				s.err = err
				return false
			} else {
				doCheck = false
			}
		}

		if doCheck {
			for _, char := range last {
				if unicode.IsSpace(rune(char)) {
					continue
				} else if char == '#' {
					break
				} else {
					s.err = extraCharError(s.line)
					return false
				}
			}
		}
	}

	// Store key and value

	var bufKey, bufValue, bufSep bytes.Buffer
	var bytes []byte

	for _, r := range key {
		bytes = make([]byte, utf8.RuneLen(r))
		utf8.EncodeRune(bytes, r)
		bufKey.Write(bytes)
	}
	s.key = bufKey.Bytes()

	for _, r := range value {
		bytes = make([]byte, utf8.RuneLen(r))
		utf8.EncodeRune(bytes, r)
		bufValue.Write(bytes)
	}
	s.value = bufValue.Bytes()

	// Store separator character
	if s.separator == nil {
		for _, r := range separator {
			bytes = make([]byte, utf8.RuneLen(r))
			utf8.EncodeRune(bytes, r)
			bufSep.Write(bytes)
		}
		s.separator = bufSep.Bytes()
	}

	return true
}
func (s *Scanner) Scan() bool {
	var thisRune rune
	var n int
	var err error

	for s.line++; ; s.line++ {
		// Skip leading spaces.
		for thisRune, n, err = s.buf.ReadRune(); ; thisRune, _, err = s.buf.ReadRune() {
			if err != nil {
				s.err = err
				return false
			}

			if thisRune == '\n' {
				s.line++
				continue
			}
			if !unicode.IsSpace(thisRune) {
				break
			}
		}

		// Skip line comment and section.
		if thisRune == '#' || thisRune == '[' {
			if _, err = s.buf.ReadBytes('\n'); err != nil {
				s.err = err
				return false
			}
			continue
		}
		break
	}

	if thisRune == '=' {
		s.err = keyError(s.line)
		return false
	}

	var key, value, separator []rune

	// Get key

	for ; ; thisRune, n, err = s.buf.ReadRune() {
		if err != nil {
			if err != io.EOF {
				s.err = err
			} else {
				s.err = valueError(s.line)
			}
			return false
		}

		// The separator charater could the the equal sign or space.
		if thisRune == '=' || unicode.IsSpace(thisRune) {
			break
		}

		if n > 1 || !isValidChar(thisRune) {
			s.err = noASCIIKeyError(s.line)
			return false
		}
		key = append(key, thisRune)
	}

	// Skip spaces before and after of the separator character.

	if unicode.IsSpace(thisRune) {
		separator = append(separator, thisRune)

		for thisRune, _, err = s.buf.ReadRune(); ; thisRune, _, err = s.buf.ReadRune() {
			if err != nil {
				if err != io.EOF {
					s.err = err
				} else {
					s.err = valueError(s.line)
				}
				return false
			}

			if !unicode.IsSpace(thisRune) {
				break
			}
			separator = append(separator, thisRune)
		}
	}
	if thisRune == '=' {
		separator = append(separator, thisRune)

		if thisRune, _, err = s.buf.ReadRune(); err != nil {
			if err != io.EOF {
				s.err = err
			} else {
				s.err = valueError(s.line)
			}
			return false
		}
	}
	if unicode.IsSpace(thisRune) {
		separator = append(separator, thisRune)

		for thisRune, _, err = s.buf.ReadRune(); ; thisRune, _, err = s.buf.ReadRune() {
			if err != nil {
				if err != io.EOF {
					s.err = err
				} else {
					s.err = valueError(s.line)
				}
				return false
			}

			if !unicode.IsSpace(thisRune) {
				break
			}
			separator = append(separator, thisRune)
		}
	}

	// Get value

	var valueIsString, valueInDQuote bool
	var lastRune rune

	if thisRune == '"' { // The value is between double quotes
		valueIsString = true
		valueInDQuote = true
	} else if thisRune == '\'' { // between single quotes
		valueIsString = true
	} else {
		value = append(value, thisRune)
	}

	for thisRune, _, err = s.buf.ReadRune(); ; thisRune, _, err = s.buf.ReadRune() {
		if err != nil {
			if err != io.EOF {
				s.err = err
				return false
			}

			if valueIsString {
				s.err = openQuoteError(s.line)
				return false
			}
			s.err = err
			break
		}

		if valueIsString {
			if valueInDQuote {
				if thisRune == '"' && lastRune != '\\' {
					break
				}
			} else if thisRune == '\'' && lastRune != '\\' {
				break
			}
			lastRune = thisRune // To checking if it is a quote escaped.
			value = append(value, thisRune)

		} else {
			if unicode.IsSpace(thisRune) {
				break
			}
			value = append(value, thisRune)
		}
	}

	// Sanity check
	if thisRune != '\n' && thisRune != '\r' {
		doCheck := true
		last, _, err := s.buf.ReadLine()
		if err != nil {
			if err != io.EOF {
				s.err = err
				return false
			} else {
				doCheck = false
			}
		}

		if doCheck {
			for _, char := range last {
				if unicode.IsSpace(rune(char)) {
					continue
				} else if char == '#' {
					break
				} else {
					s.err = extraCharError(s.line)
					return false
				}
			}
		}
	}

	// Store key and value

	var bufKey, bufValue, bufSep bytes.Buffer
	var bytes []byte

	for _, r := range key {
		bytes = make([]byte, utf8.RuneLen(r))
		utf8.EncodeRune(bytes, r)
		bufKey.Write(bytes)
	}
	s.key = bufKey.Bytes()

	for _, r := range value {
		bytes = make([]byte, utf8.RuneLen(r))
		utf8.EncodeRune(bytes, r)
		bufValue.Write(bytes)
	}
	s.value = bufValue.Bytes()

	// Store separator character
	if s.separator == nil {
		for _, r := range separator {
			bytes = make([]byte, utf8.RuneLen(r))
			utf8.EncodeRune(bytes, r)
			bufSep.Write(bytes)
		}
		s.separator = bufSep.Bytes()
	}

	return true
}
// Scan advances the Scanner to the next tokens, which will then be available
// through the Bytes or Text method. It returns false when the scan stops, either
// by reaching the end of the input or an error. After Scan returns false, the Err
// method will return any error that occurred during scanning, except that if it
// was io.EOF, Err will return nil.