/*
 *   Copyright (C) 1988-2006 Lucent Technologies Inc. and others.
 *   All Rights Reserved.
 */

/*
 *	compath(pathname)
 *
 *	This compresses pathnames.  All strings of multiple slashes are
 *	changed to a single slash.  All occurrences of "./" are removed.
 *	Whenever possible, strings of "/.." are removed together with
 *	the directory names that they follow.
 *
 *	WARNING: since pathname is altered by this function, it should
 *		 be located in a temporary buffer. This avoids the problem
 *		 of accidently changing strings obtained from makefiles
 *		 and stored in global structures.
 */

#if BSD
#define	strchr	index
char	*strchr(), *strcpy();
#else
#include <string.h>
#endif
#include <stdio.h>	/* for library.h */
#include "library.h"

char *
compath(pathname)			/*FDEF*/
char *pathname;
{
	register char	*nextchar;
	register char	*lastchar;
	char	*sofar;
	char	*pnend;

	int	pnlen;

		/*
		 *	do not change the path if it has no "/"
		 */

#ifdef __BORLANDC__
	extern strtoupper(char *);

	strtoupper(pathname);	/* make sure all upper case */
#endif

#if defined(__BORLANDC__) || defined(FOR_WIN32)
	if (strchr(pathname, '/') == 0 && strchr(pathname, '\\') == 0)
		return(pathname);
	
	/* Use / as directory separator until return */
	for(nextchar = pathname; *nextchar; nextchar++) {
		if(*nextchar == '\\') *nextchar = '/';
	}
#else
	if (strchr(pathname, '/') == 0)
		return(pathname);
#endif
	

		/*
		 *	find all strings consisting of more than one '/'
		 */

	for (lastchar = pathname + 1; *lastchar != '\0'; lastchar++)
		if ((*lastchar == '/') && (*(lastchar - 1) == '/'))
		{

			/*
			 *	find the character after the last slash
			 */

			nextchar = lastchar;
			while (*++lastchar == '/')
			{
			}

			/*
			 *	eliminate the extra slashes by copying
			 *	everything after the slashes over the slashes
			 */

			sofar = nextchar;
			while ((*nextchar++ = *lastchar++) != '\0')
				;
			lastchar = sofar;
		}

		/*
		 *	find all strings of "./"
		 */

	for (lastchar = pathname + 1; *lastchar != '\0'; lastchar++)

		if ((*lastchar == '/') && (*(lastchar - 1) == '.') &&
		    ((lastchar - 1 == pathname) || (*(lastchar - 2) == '/')))
		{

			/*
			 *	copy everything after the "./" over the "./"
			 */

			nextchar = lastchar - 1;
			sofar = nextchar;
			while ((*nextchar++ = *++lastchar) != '\0')
				;
			lastchar = sofar;
		}

		/*
		 *	find each occurrence of "/.."
		 */

	for (lastchar = pathname + 1; *lastchar != '\0'; lastchar++)

		if ((lastchar != pathname) && (*lastchar == '/') &&
		    (*(lastchar + 1) == '.') && (*(lastchar + 2) == '.') &&
		    ((*(lastchar + 3) == '/') || (*(lastchar + 3) == '\0')))
		{

			/*
			 *	find the directory name preceding the "/.."
			 */

			nextchar = lastchar - 1;
			while ((nextchar != pathname) &&
			    (*(nextchar - 1) != '/'))
				--nextchar;

			/*
			 *	make sure the preceding directory's name
			 *	is not "." or ".."
			 */

			if ((*nextchar == '.') &&
			    (*(nextchar + 1) == '/') ||
			    ((*(nextchar + 1) == '.') && (*(nextchar + 2) == '/')))
				/* EMPTY */;
			else
			{

				/*
				 * 	prepare to eliminate either
				 *	"dir_name/../" or "dir_name/.."
				 */

				if (*(lastchar + 3) == '/')
					lastchar += 4;
				else
					lastchar += 3;

				/*
				 *	copy everything after the "/.." to
				 *	before the preceding directory name
				 */

				sofar = nextchar - 1;
				while ((*nextchar++ = *lastchar++) != '\0');
					
				lastchar = sofar;

				/*
				 *	if the character before what was taken
				 *	out is '/', set up to check if the
				 *	slash is part of "/.."
				 */

				if ((sofar + 1 != pathname) && (*sofar == '/'))
					--lastchar;
			}
		}

	/*
 	 *	if the string is more than a character long and ends
	 *	in '/', eliminate the '/'.
	 */

	pnlen = strlen(pathname);
	pnend = strchr(pathname, '\0') - 1;

	if ((pnlen > 1) && (*pnend == '/'))
	{
		*pnend-- = '\0';
		pnlen--;
	}

	/*
	 *	if the string has more than two characters and ends in
	 *	"/.", remove the "/.".
	 */

	if ((pnlen > 2) && (*(pnend - 1) == '/') && (*pnend == '.'))
		*--pnend = '\0';

	/*
	 *	if all characters were deleted, return ".";
	 *	otherwise return pathname
	 */

	if (*pathname == '\0')
		(void) strcpy(pathname, ".");

#ifdef __BORLANDC__
	/* Use \ as directory separator */
	for(nextchar = pathname; *nextchar; nextchar++) {
		if(*nextchar == '/') *nextchar = '\\';
	}
#endif
	
	return(pathname);
}


/* allocate a string and join paths */

#if defined(__BORLANDC__) || defined(FOR_WIN32)
#define PATHDELIM '\\'
#else
#define PATHDELIM '/'
#endif

char *
pathjoin(s,s2)
char	*s,*s2;
{
        unsigned l = strlen(s),alloclen = l;
	char *ret;
        if(s[l-1] != PATHDELIM) ++alloclen;
     	alloclen += strlen(s2);
	ret = (char *) mymalloc(alloclen + 1);
	strcpy(ret, s);
        if(s[l-1] != PATHDELIM) {
		ret[l] = PATHDELIM;
		++l;
		ret[l] = '\0';
 	}
	strcat(ret + l,s2);
	return(ret);
}
