// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package filepath

import (
	
	
	
	
	
)

func walkSymlinks( string) (string, error) {
	 := volumeNameLen()
	 := string(os.PathSeparator)

	if  < len() && os.IsPathSeparator([]) {
		++
	}
	 := [:]
	 := 
	 := 0
	for ,  := , ;  < len();  =  {
		for  < len() && os.IsPathSeparator([]) {
			++
		}
		 = 
		for  < len() && !os.IsPathSeparator([]) {
			++
		}

		// On Windows, "." can be a symlink.
		// We look it up, and use the value if it is absolute.
		// If not, we just return ".".
		 := runtime.GOOS == "windows" && [volumeNameLen():] == "."

		// The next path component is in path[start:end].
		if  ==  {
			// No more path components.
			break
		} else if [:] == "." && ! {
			// Ignore path component ".".
			continue
		} else if [:] == ".." {
			// Back up to previous component if possible.
			// Note that volLen includes any leading slash.

			// Set r to the index of the last slash in dest,
			// after the volume.
			var  int
			for  = len() - 1;  >= ; -- {
				if os.IsPathSeparator([]) {
					break
				}
			}
			if  <  || [+1:] == ".." {
				// Either path has no slashes
				// (it's empty or just "C:")
				// or it ends in a ".." we had to keep.
				// Either way, keep this "..".
				if len() >  {
					 += 
				}
				 += ".."
			} else {
				// Discard everything since the last slash.
				 = [:]
			}
			continue
		}

		// Ordinary path component. Add it to result.

		if len() > volumeNameLen() && !os.IsPathSeparator([len()-1]) {
			 += 
		}

		 += [:]

		// Resolve symlink.

		,  := os.Lstat()
		if  != nil {
			return "", 
		}

		if .Mode()&fs.ModeSymlink == 0 {
			if !.Mode().IsDir() &&  < len() {
				return "", syscall.ENOTDIR
			}
			continue
		}

		// Found symlink.

		++
		if  > 255 {
			return "", errors.New("EvalSymlinks: too many links")
		}

		,  := os.Readlink()
		if  != nil {
			return "", 
		}

		if  && !IsAbs() {
			// On Windows, if "." is a relative symlink,
			// just return ".".
			break
		}

		 =  + [:]

		 := volumeNameLen()
		if  > 0 {
			// Symlink to drive name is an absolute path.
			if  < len() && os.IsPathSeparator([]) {
				++
			}
			 = [:]
			 = 
			 = len()
		} else if len() > 0 && os.IsPathSeparator([0]) {
			// Symlink to absolute path.
			 = [:1]
			 = 1
		} else {
			// Symlink to relative path; replace last
			// path component in dest.
			var  int
			for  = len() - 1;  >= ; -- {
				if os.IsPathSeparator([]) {
					break
				}
			}
			if  <  {
				 = 
			} else {
				 = [:]
			}
			 = 0
		}
	}
	return Clean(), nil
}