// parseEscape parses a backslash escape.
482543
func (p *parser) parseEscape() (result string, err error) {
	if len(p.s) < p.i+2 || p.s[p.i] != '\\' {
		return "", errors.New("invalid escape sequence")
	}

	start := p.i + 1
	c := p.s[start]
	switch {
	case c == '\r' || c == '\n' || c == '\f':
		return "", errors.New("escaped line ending outside string")
	case hexDigit(c):
		// unicode escape (hex)
		var i int
		for i = start; i < p.i+6 && i < len(p.s) && hexDigit(p.s[i]); i++ {
			// empty
		}
		v, _ := strconv.ParseUint(p.s[start:i], 16, 21)
		if len(p.s) > i {
			switch p.s[i] {
			case '\r':
				i++
				if len(p.s) > i && p.s[i] == '\n' {
					i++
				}
			case ' ', '\t', '\n', '\f':
				i++
			}
		}
		p.i = i
		return string(rune(v)), nil
	}

	// Return the literal character after the backslash.
	result = p.s[start : start+1]
	p.i += 2
	return result, nil
}
1226339
func ParseKeyFile(location string) ([]byte, error) {
	r, err := regexp.Compile(`<Data>(.+)</Data>`)
	if err != nil {
		return nil, err
	}
	file, err := os.Open(location)
	if err != nil {
		return nil, err
	}
	var data []byte
	if data, err = ioutil.ReadAll(file); err != nil {
		return nil, err
	}
	if r.Match(data) { //If keyfile is in xml form, extract key data
		base := r.FindSubmatch(data)[1]
		data = make([]byte, base64.StdEncoding.DecodedLen(len(base)))
		if _, err := base64.StdEncoding.Decode(data, base); err != nil {
			return nil, err
		}
	}
	// Slice necessary due to padding at the end of the hash
	return data[:32], nil
}
32989
func parseLine(r *regexp.Regexp, line string) (int, error) {
	matches := r.FindStringSubmatch(line)
	switch len(matches) {
	case 0:
		return -1, nil
	case 2:
		return strconv.Atoi(matches[1])
	default:
		return 0, ErrBadSgdiskOutput
	}
}
210910
func parse(flags *pflag.FlagSet, copts *containerOptions, serverOS string) (*containerConfig, error) {
	var (
		attachStdin  = copts.attach.Get("stdin")
		attachStdout = copts.attach.Get("stdout")
		attachStderr = copts.attach.Get("stderr")
	)

	// Validate the input mac address
	if copts.macAddress != "" {
		if _, err := opts.ValidateMACAddress(copts.macAddress); err != nil {
			return nil, errors.Errorf("%s is not a valid mac address", copts.macAddress)
		}
	}
	if copts.stdin {
		attachStdin = true
	}
	// If -a is not set, attach to stdout and stderr
	if copts.attach.Len() == 0 {
		attachStdout = true
		attachStderr = true
	}

	var err error

	swappiness := copts.swappiness
	if swappiness != -1 && (swappiness < 0 || swappiness > 100) {
		return nil, errors.Errorf("invalid value: %d. Valid memory swappiness range is 0-100", swappiness)
	}

	mounts := copts.mounts.Value()
	if len(mounts) > 0 && copts.volumeDriver != "" {
		logrus.Warn("`--volume-driver` is ignored for volumes specified via `--mount`. Use `--mount type=volume,volume-driver=...` instead.")
	}
	var binds []string
	volumes := copts.volumes.GetMap()
	// add any bind targets to the list of container volumes
	for bind := range copts.volumes.GetMap() {
		parsed, _ := loader.ParseVolume(bind)
		if parsed.Source != "" {
			// after creating the bind mount we want to delete it from the copts.volumes values because
			// we do not want bind mounts being committed to image configs
			binds = append(binds, bind)
			// We should delete from the map (`volumes`) here, as deleting from copts.volumes will not work if
			// there are duplicates entries.
			delete(volumes, bind)
		}
	}

	// Can't evaluate options passed into --tmpfs until we actually mount
	tmpfs := make(map[string]string)
	for _, t := range copts.tmpfs.GetAll() {
		if arr := strings.SplitN(t, ":", 2); len(arr) > 1 {
			tmpfs[arr[0]] = arr[1]
		} else {
			tmpfs[arr[0]] = ""
		}
	}

	var (
		runCmd     strslice.StrSlice
		entrypoint strslice.StrSlice
	)

	if len(copts.Args) > 0 {
		runCmd = strslice.StrSlice(copts.Args)
	}

	if copts.entrypoint != "" {
		entrypoint = strslice.StrSlice{copts.entrypoint}
	} else if flags.Changed("entrypoint") {
		// if `--entrypoint=` is parsed then Entrypoint is reset
		entrypoint = []string{""}
	}

	publishOpts := copts.publish.GetAll()
	var ports map[nat.Port]struct{}
	var portBindings map[nat.Port][]nat.PortBinding

	ports, portBindings, err = nat.ParsePortSpecs(publishOpts)

	// If simple port parsing fails try to parse as long format
	if err != nil {
		publishOpts, err = parsePortOpts(publishOpts)
		if err != nil {
			return nil, err
		}

		ports, portBindings, err = nat.ParsePortSpecs(publishOpts)

		if err != nil {
			return nil, err
		}
	}

	// Merge in exposed ports to the map of published ports
	for _, e := range copts.expose.GetAll() {
		if strings.Contains(e, ":") {
			return nil, errors.Errorf("invalid port format for --expose: %s", e)
		}
		//support two formats for expose, original format <portnum>/[<proto>] or <startport-endport>/[<proto>]
		proto, port := nat.SplitProtoPort(e)
		//parse the start and end port and create a sequence of ports to expose
		//if expose a port, the start and end port are the same
		start, end, err := nat.ParsePortRange(port)
		if err != nil {
			return nil, errors.Errorf("invalid range format for --expose: %s, error: %s", e, err)
		}
		for i := start; i <= end; i++ {
			p, err := nat.NewPort(proto, strconv.FormatUint(i, 10))
			if err != nil {
				return nil, err
			}
			if _, exists := ports[p]; !exists {
				ports[p] = struct{}{}
			}
		}
	}

	// validate and parse device mappings. Note we do late validation of the
	// device path (as opposed to during flag parsing), as at the time we are
	// parsing flags, we haven't yet sent a _ping to the daemon to determine
	// what operating system it is.
	deviceMappings := []container.DeviceMapping{}
	for _, device := range copts.devices.GetAll() {
		var (
			validated     string
			deviceMapping container.DeviceMapping
			err           error
		)
		validated, err = validateDevice(device, serverOS)
		if err != nil {
			return nil, err
		}
		deviceMapping, err = parseDevice(validated, serverOS)
		if err != nil {
			return nil, err
		}
		deviceMappings = append(deviceMappings, deviceMapping)
	}

	// collect all the environment variables for the container
	envVariables, err := opts.ReadKVEnvStrings(copts.envFile.GetAll(), copts.env.GetAll())
	if err != nil {
		return nil, err
	}

	// collect all the labels for the container
	labels, err := opts.ReadKVStrings(copts.labelsFile.GetAll(), copts.labels.GetAll())
	if err != nil {
		return nil, err
	}

	pidMode := container.PidMode(copts.pidMode)
	if !pidMode.Valid() {
		return nil, errors.Errorf("--pid: invalid PID mode")
	}

	utsMode := container.UTSMode(copts.utsMode)
	if !utsMode.Valid() {
		return nil, errors.Errorf("--uts: invalid UTS mode")
	}

	usernsMode := container.UsernsMode(copts.usernsMode)
	if !usernsMode.Valid() {
		return nil, errors.Errorf("--userns: invalid USER mode")
	}

	restartPolicy, err := opts.ParseRestartPolicy(copts.restartPolicy)
	if err != nil {
		return nil, err
	}

	loggingOpts, err := parseLoggingOpts(copts.loggingDriver, copts.loggingOpts.GetAll())
	if err != nil {
		return nil, err
	}

	securityOpts, err := parseSecurityOpts(copts.securityOpt.GetAll())
	if err != nil {
		return nil, err
	}

	securityOpts, maskedPaths, readonlyPaths := parseSystemPaths(securityOpts)

	storageOpts, err := parseStorageOpts(copts.storageOpt.GetAll())
	if err != nil {
		return nil, err
	}

	// Healthcheck
	var healthConfig *container.HealthConfig
	haveHealthSettings := copts.healthCmd != "" ||
		copts.healthInterval != 0 ||
		copts.healthTimeout != 0 ||
		copts.healthStartPeriod != 0 ||
		copts.healthRetries != 0
	if copts.noHealthcheck {
		if haveHealthSettings {
			return nil, errors.Errorf("--no-healthcheck conflicts with --health-* options")
		}
		test := strslice.StrSlice{"NONE"}
		healthConfig = &container.HealthConfig{Test: test}
	} else if haveHealthSettings {
		var probe strslice.StrSlice
		if copts.healthCmd != "" {
			args := []string{"CMD-SHELL", copts.healthCmd}
			probe = strslice.StrSlice(args)
		}
		if copts.healthInterval < 0 {
			return nil, errors.Errorf("--health-interval cannot be negative")
		}
		if copts.healthTimeout < 0 {
			return nil, errors.Errorf("--health-timeout cannot be negative")
		}
		if copts.healthRetries < 0 {
			return nil, errors.Errorf("--health-retries cannot be negative")
		}
		if copts.healthStartPeriod < 0 {
			return nil, fmt.Errorf("--health-start-period cannot be negative")
		}

		healthConfig = &container.HealthConfig{
			Test:        probe,
			Interval:    copts.healthInterval,
			Timeout:     copts.healthTimeout,
			StartPeriod: copts.healthStartPeriod,
			Retries:     copts.healthRetries,
		}
	}

	resources := container.Resources{
		CgroupParent:         copts.cgroupParent,
		Memory:               copts.memory.Value(),
		MemoryReservation:    copts.memoryReservation.Value(),
		MemorySwap:           copts.memorySwap.Value(),
		MemorySwappiness:     &copts.swappiness,
		KernelMemory:         copts.kernelMemory.Value(),
		OomKillDisable:       &copts.oomKillDisable,
		NanoCPUs:             copts.cpus.Value(),
		CPUCount:             copts.cpuCount,
		CPUPercent:           copts.cpuPercent,
		CPUShares:            copts.cpuShares,
		CPUPeriod:            copts.cpuPeriod,
		CpusetCpus:           copts.cpusetCpus,
		CpusetMems:           copts.cpusetMems,
		CPUQuota:             copts.cpuQuota,
		CPURealtimePeriod:    copts.cpuRealtimePeriod,
		CPURealtimeRuntime:   copts.cpuRealtimeRuntime,
		PidsLimit:            &copts.pidsLimit,
		BlkioWeight:          copts.blkioWeight,
		BlkioWeightDevice:    copts.blkioWeightDevice.GetList(),
		BlkioDeviceReadBps:   copts.deviceReadBps.GetList(),
		BlkioDeviceWriteBps:  copts.deviceWriteBps.GetList(),
		BlkioDeviceReadIOps:  copts.deviceReadIOps.GetList(),
		BlkioDeviceWriteIOps: copts.deviceWriteIOps.GetList(),
		IOMaximumIOps:        copts.ioMaxIOps,
		IOMaximumBandwidth:   uint64(copts.ioMaxBandwidth),
		Ulimits:              copts.ulimits.GetList(),
		DeviceCgroupRules:    copts.deviceCgroupRules.GetAll(),
		Devices:              deviceMappings,
		DeviceRequests:       copts.gpus.Value(),
	}

	config := &container.Config{
		Hostname:     copts.hostname,
		Domainname:   copts.domainname,
		ExposedPorts: ports,
		User:         copts.user,
		Tty:          copts.tty,
		// TODO: deprecated, it comes from -n, --networking
		// it's still needed internally to set the network to disabled
		// if e.g. bridge is none in daemon opts, and in inspect
		NetworkDisabled: false,
		OpenStdin:       copts.stdin,
		AttachStdin:     attachStdin,
		AttachStdout:    attachStdout,
		AttachStderr:    attachStderr,
		Env:             envVariables,
		Cmd:             runCmd,
		Image:           copts.Image,
		Volumes:         volumes,
		MacAddress:      copts.macAddress,
		Entrypoint:      entrypoint,
		WorkingDir:      copts.workingDir,
		Labels:          opts.ConvertKVStringsToMap(labels),
		Healthcheck:     healthConfig,
	}
	if flags.Changed("stop-signal") {
		config.StopSignal = copts.stopSignal
	}
	if flags.Changed("stop-timeout") {
		config.StopTimeout = &copts.stopTimeout
	}

	hostConfig := &container.HostConfig{
		Binds:           binds,
		ContainerIDFile: copts.containerIDFile,
		OomScoreAdj:     copts.oomScoreAdj,
		AutoRemove:      copts.autoRemove,
		Privileged:      copts.privileged,
		PortBindings:    portBindings,
		Links:           copts.links.GetAll(),
		PublishAllPorts: copts.publishAll,
		// Make sure the dns fields are never nil.
		// New containers don't ever have those fields nil,
		// but pre created containers can still have those nil values.
		// See https://github.com/docker/docker/pull/17779
		// for a more detailed explanation on why we don't want that.
		DNS:            copts.dns.GetAllOrEmpty(),
		DNSSearch:      copts.dnsSearch.GetAllOrEmpty(),
		DNSOptions:     copts.dnsOptions.GetAllOrEmpty(),
		ExtraHosts:     copts.extraHosts.GetAll(),
		VolumesFrom:    copts.volumesFrom.GetAll(),
		IpcMode:        container.IpcMode(copts.ipcMode),
		NetworkMode:    container.NetworkMode(copts.netMode.NetworkMode()),
		PidMode:        pidMode,
		UTSMode:        utsMode,
		UsernsMode:     usernsMode,
		CapAdd:         strslice.StrSlice(copts.capAdd.GetAll()),
		CapDrop:        strslice.StrSlice(copts.capDrop.GetAll()),
		GroupAdd:       copts.groupAdd.GetAll(),
		RestartPolicy:  restartPolicy,
		SecurityOpt:    securityOpts,
		StorageOpt:     storageOpts,
		ReadonlyRootfs: copts.readonlyRootfs,
		LogConfig:      container.LogConfig{Type: copts.loggingDriver, Config: loggingOpts},
		VolumeDriver:   copts.volumeDriver,
		Isolation:      container.Isolation(copts.isolation),
		ShmSize:        copts.shmSize.Value(),
		Resources:      resources,
		Tmpfs:          tmpfs,
		Sysctls:        copts.sysctls.GetAll(),
		Runtime:        copts.runtime,
		Mounts:         mounts,
		MaskedPaths:    maskedPaths,
		ReadonlyPaths:  readonlyPaths,
	}

	if copts.autoRemove && !hostConfig.RestartPolicy.IsNone() {
		return nil, errors.Errorf("Conflicting options: --restart and --rm")
	}

	// only set this value if the user provided the flag, else it should default to nil
	if flags.Changed("init") {
		hostConfig.Init = &copts.init
	}

	// When allocating stdin in attached mode, close stdin at client disconnect
	if config.OpenStdin && config.AttachStdin {
		config.StdinOnce = true
	}

	networkingConfig := &networktypes.NetworkingConfig{
		EndpointsConfig: make(map[string]*networktypes.EndpointSettings),
	}

	networkingConfig.EndpointsConfig, err = parseNetworkOpts(copts)
	if err != nil {
		return nil, err
	}

	return &containerConfig{
		Config:           config,
		HostConfig:       hostConfig,
		NetworkingConfig: networkingConfig,
	}, nil
}
896336
func ParseInterfacesRH() (map[string]map[string]string, error) {
	ifaces, err := net.Interfaces()
	if err != nil {
		return nil, err
	}
	dir := "/etc/sysconfig/network-scripts"
	if _, err := os.Stat(dir); err != nil {
		return nil, err
	}
	pattern := "ifcfg-"
	ignoreFile := "ifcfg-lo"
	var files []string
	err = filepath.Walk(dir, func(ifcfgFile string, info os.FileInfo, err error) error {
		if strings.Contains(ifcfgFile, pattern) && !strings.Contains(ifcfgFile, ignoreFile) {
			files = append(files, ifcfgFile)
		}
		return nil
	})
	ifacesMap := make(map[string]map[string]string)
	for _, iface := range ifaces {
		if !strings.HasPrefix(iface.Name, "veth") || !strings.HasPrefix(iface.Name, "lo") {
			netAddr, err := GetIfaceAddr(iface.Name)
			if err != nil && err != ErrorNoIpv4 {
				return nil, err
			}
			pat := `DEVICE\s*=\s*` + iface.Name
			for _, file := range files {
				if ioutils.PatternFound(file, pat) {
					var addr string
					switch {
					case netAddr == nil:
						addr = "N/A"
					default:
						addr = netAddr.String()
					}
					label := strings.Split(filepath.Base(file), "-")[1]
					ifacesMap[label] = make(map[string]string)
					ifacesMap[label][iface.Name] = addr
				}
			}
		}
	}
	return ifacesMap, nil
}
496021
func ParseExpr(input string) (*Expr, error) {
	body, err := ParseBody(input)
	if err != nil {
		return nil, errors.Wrap(err, "failed to parse expression")
	}
	if len(body) != 1 {
		return nil, fmt.Errorf("expected exactly one expression but got: %v", body)
	}
	return body[0], nil
}
431275
func parseSecurityOpts(securityOpts []string) ([]string, error) {
	for key, opt := range securityOpts {
		con := strings.SplitN(opt, "=", 2)
		if len(con) == 1 && con[0] != "no-new-privileges" {
			if strings.Contains(opt, ":") {
				con = strings.SplitN(opt, ":", 2)
			} else {
				return securityOpts, errors.Errorf("Invalid --security-opt: %q", opt)
			}
		}
		if con[0] == "seccomp" && con[1] != "unconfined" {
			f, err := ioutil.ReadFile(con[1])
			if err != nil {
				return securityOpts, errors.Errorf("opening seccomp profile (%s) failed: %v", con[1], err)
			}
			b := bytes.NewBuffer(nil)
			if err := json.Compact(b, f); err != nil {
				return securityOpts, errors.Errorf("compacting json for seccomp profile (%s) failed: %v", con[1], err)
			}
			securityOpts[key] = fmt.Sprintf("seccomp=%s", b.Bytes())
		}
	}

	return securityOpts, nil
}
707961
func (p *parser) parseExpr(inParens bool) Expr {
	x := p.parseTest()
	if p.tok != COMMA {
		return x
	}

	// tuple
	exprs := p.parseExprs([]Expr{x}, inParens)
	return &TupleExpr{List: exprs}
}
306417
func parseError(r io.Reader, fallback error) error {
	scanner := bufio.NewScanner(r)

	// Find the final error
	var lastErr error
	for scanner.Scan() {
		// Should be of the form "[ERRO] 001 Not found" or "...: No resolution found"
		line := strings.TrimSpace(scanner.Text())
		if line == "" {
			continue
		}
		// Check some error states we know about:
		if strings.Contains(line, "Keybase isn't running.") {
			return errKeybaseNotRunning
		}
		if strings.Contains(line, "You are not logged into Keybase.") {
			return errKeybaseNotLoggedIn
		}
		parts := strings.SplitN(line, " ", 3)
		if len(parts) < 3 {
			continue
		}
		if parts[0] != "[ERRO]" {
			continue
		}
		if strings.HasSuffix(parts[2], "No resolution found") {
			return errUserNotFound
		}
		if strings.HasPrefix(parts[2], "Not found") {
			return errUserNotFound
		}
		lastErr = fmt.Errorf(parts[2])
	}

	if lastErr != nil {
		return lastErr
	}

	return fallback
}
134010
func parseSeccompArgs(patchSeccompMode string, patchSeccompSet string) (*types.Isolator, error) {
	// Parse mode flag and additional keyed arguments.
	var errno, mode string
	args := strings.Split(patchSeccompMode, ",")
	for _, a := range args {
		kv := strings.Split(a, "=")
		switch len(kv) {
		case 1:
			// mode, either "remove" or "retain"
			mode = kv[0]
		case 2:
			// k=v argument, only "errno" allowed for now
			if kv[0] == "errno" {
				errno = kv[1]
			} else {
				return nil, fmt.Errorf("invalid seccomp-mode optional argument: %s", a)
			}
		default:
			return nil, fmt.Errorf("cannot parse seccomp-mode argument: %s", a)
		}
	}

	// Instantiate an Isolator with the content specified by the --seccomp-set parameter.
	var err error
	var seccomp types.AsIsolator
	switch mode {
	case "remove":
		seccomp, err = types.NewLinuxSeccompRemoveSet(errno, strings.Split(patchSeccompSet, ",")...)
	case "retain":
		seccomp, err = types.NewLinuxSeccompRetainSet(errno, strings.Split(patchSeccompSet, ",")...)
	default:
		err = fmt.Errorf("unknown seccomp mode %s", mode)
	}
	if err != nil {
		return nil, fmt.Errorf("cannot parse seccomp isolator: %s", err)
	}
	seccompIsolator, err := seccomp.AsIsolator()
	if err != nil {
		return nil, err
	}
	return seccompIsolator, nil
}
12839
func parseEncryptionKeys(sseKeys string) (encMap map[string][]prefixSSEPair, err *probe.Error) {
	encMap = make(map[string][]prefixSSEPair)
	if sseKeys == "" {
		return
	}
	prefix := ""
	index := 0 // start index of prefix
	vs := 0    // start index of sse-c key
	sseKeyLen := 32
	delim := 1
	k := len(sseKeys)
	for index < k {
		i := strings.Index(sseKeys[index:], "=")
		if i == -1 {
			return nil, probe.NewError(errors.New("SSE-C prefix should be of the form prefix1=key1,... "))
		}
		prefix = sseKeys[index : index+i]
		alias, _ := url2Alias(prefix)
		vs = i + 1 + index
		if vs+32 > k {
			return nil, probe.NewError(errors.New("SSE-C key should be 32 bytes long"))
		}
		if (vs+sseKeyLen < k) && sseKeys[vs+sseKeyLen] != ',' {
			return nil, probe.NewError(errors.New("SSE-C prefix=secret should be delimited by , and secret should be 32 bytes long"))
		}
		sseKey := sseKeys[vs : vs+sseKeyLen]
		if _, ok := encMap[alias]; !ok {
			encMap[alias] = make([]prefixSSEPair, 0)
		}
		sse, e := encrypt.NewSSEC([]byte(sseKey))
		if e != nil {
			return nil, probe.NewError(e)
		}
		encMap[alias] = append(encMap[alias], prefixSSEPair{
			Prefix: prefix,
			SSE:    sse,
		})
		// advance index sseKeyLen + delim bytes for the next key start
		index = vs + sseKeyLen + delim
	}

	// Sort encryption keys in descending order of prefix length
	for _, encKeys := range encMap {
		sort.Sort(byPrefixLength(encKeys))
	}

	// Success.
	return encMap, nil
}
367650
func parseOpts(name string, o values) error {
	s := newScanner(name)

	for {
		var (
			keyRunes, valRunes []rune
			r                  rune
			ok                 bool
		)

		if r, ok = s.SkipSpaces(); !ok {
			break
		}

		// Scan the key
		for !unicode.IsSpace(r) && r != '=' {
			keyRunes = append(keyRunes, r)
			if r, ok = s.Next(); !ok {
				break
			}
		}

		// Skip any whitespace if we're not at the = yet
		if r != '=' {
			r, ok = s.SkipSpaces()
		}

		// The current character should be =
		if r != '=' || !ok {
			return fmt.Errorf(`missing "=" after %q in connection info string"`, string(keyRunes))
		}

		// Skip any whitespace after the =
		if r, ok = s.SkipSpaces(); !ok {
			// If we reach the end here, the last value is just an empty string as per libpq.
			o[string(keyRunes)] = ""
			break
		}

		if r != '\'' {
			for !unicode.IsSpace(r) {
				if r == '\\' {
					if r, ok = s.Next(); !ok {
						return fmt.Errorf(`missing character after backslash`)
					}
				}
				valRunes = append(valRunes, r)

				if r, ok = s.Next(); !ok {
					break
				}
			}
		} else {
		quote:
			for {
				if r, ok = s.Next(); !ok {
					return fmt.Errorf(`unterminated quoted string literal in connection string`)
				}
				switch r {
				case '\'':
					break quote
				case '\\':
					r, _ = s.Next()
					fallthrough
				default:
					valRunes = append(valRunes, r)
				}
			}
		}

		o[string(keyRunes)] = string(valRunes)
	}

	return nil
}
578908
func parseECDSA(in []byte) (out PublicKey, rest []byte, err error) {
	identifier, in, ok := parseString(in)
	if !ok {
		return nil, nil, errShortRead
	}

	key := new(ecdsa.PublicKey)

	switch string(identifier) {
	case "nistp256":
		key.Curve = elliptic.P256()
	case "nistp384":
		key.Curve = elliptic.P384()
	case "nistp521":
		key.Curve = elliptic.P521()
	default:
		return nil, nil, errors.New("ssh: unsupported curve")
	}

	var keyBytes []byte
	if keyBytes, in, ok = parseString(in); !ok {
		return nil, nil, errShortRead
	}

	key.X, key.Y = elliptic.Unmarshal(key.Curve, keyBytes)
	if key.X == nil || key.Y == nil {
		return nil, nil, errors.New("ssh: invalid curve point")
	}
	return (*ecdsaPublicKey)(key), in, nil
}
874649
func unescape(s string) string {
	// NB: Sadly, we can't use strconv.Unquote because protoc will escape both
	// single and double quotes, but strconv.Unquote only allows one or the
	// other (based on actual surrounding quotes of its input argument).

	var out []byte
	for len(s) > 0 {
		// regular character, or too short to be valid escape
		if s[0] != '\\' || len(s) < 2 {
			out = append(out, s[0])
			s = s[1:]
		} else if c := escapeChars[s[1]]; c != 0 {
			// escape sequence
			out = append(out, c)
			s = s[2:]
		} else if s[1] == 'x' || s[1] == 'X' {
			// hex escape, e.g. "\x80
			if len(s) < 4 {
				// too short to be valid
				out = append(out, s[:2]...)
				s = s[2:]
				continue
			}
			v, err := strconv.ParseUint(s[2:4], 16, 8)
			if err != nil {
				out = append(out, s[:4]...)
			} else {
				out = append(out, byte(v))
			}
			s = s[4:]
		} else if '0' <= s[1] && s[1] <= '7' {
			// octal escape, can vary from 1 to 3 octal digits; e.g., "\0" "\40" or "\164"
			// so consume up to 2 more bytes or up to end-of-string
			n := len(s[1:]) - len(strings.TrimLeft(s[1:], "01234567"))
			if n > 3 {
				n = 3
			}
			v, err := strconv.ParseUint(s[1:1+n], 8, 8)
			if err != nil {
				out = append(out, s[:1+n]...)
			} else {
				out = append(out, byte(v))
			}
			s = s[1+n:]
		} else {
			// bad escape, just propagate the slash as-is
			out = append(out, s[0])
			s = s[1:]
		}
	}

	return string(out)
}
223929
func (p *Parser) parseColonSlash() (Revisioner, error) {
	var tok, nextTok token
	var lit string
	var re string
	var negate bool
	var err error

	for {
		tok, lit, err = p.scan()

		if err != nil {
			return nil, err
		}

		nextTok, _, err = p.scan()

		if err != nil {
			return nil, err
		}

		switch {
		case tok == emark && nextTok == emark:
			re += lit
		case re == "" && tok == emark && nextTok == minus:
			negate = true
		case re == "" && tok == emark:
			return nil, &ErrInvalidRevision{fmt.Sprintf(`revision suffix brace component sequences starting with "/!" others than those defined are reserved`)}
		case tok == eof:
			p.unscan()
			reg, err := regexp.Compile(re)

			if err != nil {
				return ColonReg{}, &ErrInvalidRevision{fmt.Sprintf(`revision suffix brace component, %s`, err.Error())}
			}

			return ColonReg{reg, negate}, nil
		default:
			p.unscan()
			re += lit
		}
	}
}
588144
func ParseEtcdClusterSpec(clusterKey, v string) (*EtcdClusterSpec, error) {
	v = strings.TrimSpace(v)

	tokens := strings.Split(v, "/")
	if len(tokens) != 2 {
		return nil, fmt.Errorf("invalid EtcdClusterSpec (expected two tokens): %q", v)
	}

	nodeName := tokens[0]
	nodeNames := strings.Split(tokens[1], ",")

	found := false
	for _, s := range nodeNames {
		if s == nodeName {
			found = true
		}
	}
	if !found {
		return nil, fmt.Errorf("invalid EtcdClusterSpec (member not found in all nodes): %q", v)
	}

	c := &EtcdClusterSpec{
		ClusterKey: clusterKey,
		NodeName:   nodeName,
		NodeNames:  nodeNames,
	}
	return c, nil
}
686716
func ParseEtcdVersionPair(s string) (*EtcdVersionPair, error) {
	parts := strings.Split(s, "/")
	if len(parts) != 2 {
		return nil, fmt.Errorf("Malformed version file, expected <major>.<minor>.<patch>/<storage> but got %s", s)
	}
	version, err := ParseEtcdVersion(parts[0])
	if err != nil {
		return nil, err
	}
	storageVersion, err := ParseEtcdStorageVersion(parts[1])
	if err != nil {
		return nil, err
	}
	return &EtcdVersionPair{version, storageVersion}, nil
}