/*
 * Copyright (C) 2016 Giacomo Tesio <giacomo@tesio.it>
 *
 * This file is part of the UCB release of Plan 9. It is subject to the license
 * terms in the LICENSE file found in the top-level directory of this
 * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
 * part of the UCB release of Plan 9, including this file, may be copied,
 * modified, propagated, or distributed except according to the terms contained
 * in the LICENSE file.
 */

#include <u.h>
#include <libc.h>

/*
 * In place, rewrite name to compress multiple /, eliminate ., and process ..
 */
#define SEP(x)	((x)=='/' || (x) == 0)
char*
jehanne_cleanname(char *name)
{
	char *s;	/* source of copy */
	char *d;	/* destination of copy */
	char *d0;	/* start of path after the root name */
	Rune r;
	int rooted;

	assert(name != nil);
	if(name[0] == 0)
		return jehanne_strcpy(name, ".");
	rooted = 0;
	d0 = name;
	if(d0[0] == '#'){
		if(d0[1] == 0)
			return d0;
		d0  += 1 + jehanne_chartorune(&r, d0+1); /* ignore slash: #/ */
		while(!SEP(*d0))
			d0 += jehanne_chartorune(&r, d0);
		if(*d0 == 0)
			return name;
		d0++;	/* keep / after #<name> */
		rooted = 1;
	}else if(d0[0] == '/'){
		rooted = 1;
		d0++;
	}

	s = d0;
	if(rooted){
		/* skip extra '/' at root name */
		for(; *s == '/'; s++)
			;
	}
	/* remove dup slashes */
	for(d = d0; *s != 0; s++){
		*d++ = *s;
		if(*s == '/')
			while(s[1] == '/')
				s++;
	}
	*d = 0;

	d = d0;
	s = d0;
	while(*s != 0){
		if(s[0] == '.' && SEP(s[1])){
			if(s[1] == 0)
				break;
			s+= 2;
			continue;
		}
		if(s[0] == '.' && s[1] == '.' && SEP(s[2])){
			if(d == d0){
				if(rooted){
					/* /../x -> /x */
					if(s[2] == 0)
						break;
					s += 3;
					continue;
				}else{
					/* ../x -> ../x; and never collect ../ */
					d0 += 3;
				}
			}
			if(d > d0){
				/* a/../x -> x */
				assert(d-2 >= d0 && d[-1] == '/');
				for(d -= 2; d > d0 && d[-1] != '/'; d--)
						;
				if(s[2] == 0)
					break;
				s += 3;
				continue;
			}
		}
		while(!SEP(*s))
			*d++ = *s++;
		if(*s == 0)
			break;
		
		*d++ = *s++;
	}
	*d = 0;
	if(d-1 > name && d[-1] == '/')	/* thanks to #/ */
		*--d = 0;
	if(name[0] == 0)
		jehanne_strcpy(name, ".");
	return name;
}
