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 ( 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].
No more path components.
			break
Ignore path component ".".
			continue
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
				}
			}
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() >  {
					 += 
				}
				 += ".."
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 "", 
		}

On Windows, if "." is a relative symlink, just return ".".
			break
		}

		 =  + [:]

		 := volumeNameLen()
Symlink to drive name is an absolute path.
			if  < len() && os.IsPathSeparator([]) {
				++
			}
			 = [:]
			 = 
			 = len()
Symlink to absolute path.
			 = [:1]
			 = 1
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