diff options
Diffstat (limited to 'winsup/mingw/mingwex/dirname.c')
-rwxr-xr-x | winsup/mingw/mingwex/dirname.c | 235 |
1 files changed, 0 insertions, 235 deletions
diff --git a/winsup/mingw/mingwex/dirname.c b/winsup/mingw/mingwex/dirname.c deleted file mode 100755 index 20d7a30bb..000000000 --- a/winsup/mingw/mingwex/dirname.c +++ /dev/null @@ -1,235 +0,0 @@ -/* dirname.c - * - * $Id$ - * - * Provides an implementation of the "dirname" function, conforming - * to SUSv3, with extensions to accommodate Win32 drive designators, - * and suitable for use on native Microsoft(R) Win32 platforms. - * - * Written by Keith Marshall <keithmarshall@users.sourceforge.net> - * - * This is free software. You may redistribute and/or modify it as you - * see fit, without restriction of copyright. - * - * This software is provided "as is", in the hope that it may be useful, - * but WITHOUT WARRANTY OF ANY KIND, not even any implied warranty of - * MERCHANTABILITY, nor of FITNESS FOR ANY PARTICULAR PURPOSE. At no - * time will the author accept any form of liability for any damages, - * however caused, resulting from the use of this software. - * - */ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <libgen.h> -#include <locale.h> - -#ifndef __cdecl /* If compiling on any non-Win32 platform ... */ -#define __cdecl /* this may not be defined. */ -#endif - -__cdecl char *dirname( char *path ) -{ - size_t len; - static char *retfail = NULL; - - /* to handle path names for files in multibyte character locales, - * we need to set up LC_CTYPE to match the host file system locale. - */ - - char *locale = setlocale( LC_CTYPE, NULL ); - if( locale != NULL ) locale = strdup( locale ); - setlocale( LC_CTYPE, "" ); - - if( path && *path ) - { - /* allocate sufficient local storage space, - * in which to create a wide character reference copy of path - */ - - wchar_t refcopy[1 + (len = mbstowcs( NULL, path, 0 ))]; - - /* create the wide character reference copy of path */ - - wchar_t *refpath = refcopy; - len = mbstowcs( refpath, path, len ); - refcopy[ len ] = L'\0'; - - /* SUSv3 identifies a special case, where path is exactly equal to "//"; - * (we will also accept "\\" in the Win32 context, but not "/\" or "\/", - * and neither will we consider paths with an initial drive designator). - * For this special case, SUSv3 allows the implementation to choose to - * return "/" or "//", (or "\" or "\\", since this is Win32); we will - * simply return the path unchanged, (i.e. "//" or "\\"). - */ - - if( (len > 1) && ((refpath[0] == L'/') || (refpath[0] == L'\\')) ) - { - if( (refpath[1] == refpath[0]) && (refpath[2] == L'\0') ) - { - setlocale( LC_CTYPE, locale ); - free( locale ); - return path; - } - } - - /* For all other cases ... - * step over the drive designator, if present ... - */ - - else if( (len > 1) && (refpath[1] == L':') ) - { - /* FIXME: maybe should confirm *refpath is a valid drive designator */ - - refpath += 2; - } - - /* check again, just to ensure we still have a non-empty path name ... */ - - if( *refpath ) - { - /* reproduce the scanning logic of the "basename" function - * to locate the basename component of the current path string, - * (but also remember where the dirname component starts). - */ - - wchar_t *refname, *basename; - for( refname = basename = refpath ; *refpath ; ++refpath ) - { - if( (*refpath == L'/') || (*refpath == L'\\') ) - { - /* we found a dir separator ... - * step over it, and any others which immediately follow it - */ - - while( (*refpath == L'/') || (*refpath == L'\\') ) - ++refpath; - - /* if we didn't reach the end of the path string ... */ - - if( *refpath ) - - /* then we have a new candidate for the base name */ - - basename = refpath; - - else - - /* we struck an early termination of the path string, - * with trailing dir separators following the base name, - * so break out of the for loop, to avoid overrun. - */ - - break; - } - } - - /* now check, - * to confirm that we have distinct dirname and basename components - */ - - if( basename > refname ) - { - /* and, when we do ... - * backtrack over all trailing separators on the dirname component, - * (but preserve exactly two initial dirname separators, if identical), - * and add a NUL terminator in their place. - */ - - do --basename; - while( (basename > refname) && ((*basename == L'/') || (*basename == L'\\')) ); - if( (basename == refname) && ((refname[0] == L'/') || (refname[0] == L'\\')) - && (refname[1] == refname[0]) && (refname[2] != L'/') && (refname[2] != L'\\') ) - ++basename; - *++basename = L'\0'; - - /* if the resultant dirname begins with EXACTLY two dir separators, - * AND both are identical, then we preserve them. - */ - - refpath = refcopy; - while( ((*refpath == L'/') || (*refpath == L'\\')) ) - ++refpath; - if( ((refpath - refcopy) > 2) || (refcopy[1] != refcopy[0]) ) - refpath = refcopy; - - /* and finally ... - * we remove any residual, redundantly duplicated separators from the dirname, - * reterminate, and return it. - */ - - refname = refpath; - while( *refpath ) - { - if( ((*refname++ = *refpath) == L'/') || (*refpath++ == L'\\') ) - { - while( (*refpath == L'/') || (*refpath == L'\\') ) - ++refpath; - } - } - *refname = L'\0'; - - /* finally ... - * transform the resolved dirname back into the multibyte char domain, - * restore the caller's locale, and return the resultant dirname - */ - - if( (len = wcstombs( path, refcopy, len )) != (size_t)(-1) ) - path[ len ] = '\0'; - } - - else - { - /* either there were no dirname separators in the path name, - * or there was nothing else ... - */ - - if( (*refname == L'/') || (*refname == L'\\') ) - { - /* it was all separators, so return one */ - - ++refname; - } - - else - { - /* there were no separators, so return '.' */ - - *refname++ = L'.'; - } - - /* add a NUL terminator, in either case, - * then transform to the multibyte char domain, - * using our own buffer - */ - - *refname = L'\0'; - retfail = realloc( retfail, len = 1 + wcstombs( NULL, refcopy, 0 )); - wcstombs( path = retfail, refcopy, len ); - } - - /* restore caller's locale, clean up, and return the resolved dirname */ - - setlocale( LC_CTYPE, locale ); - free( locale ); - return path; - } - } - - /* path is NULL, or an empty string; default return value is "." ... - * return this in our own buffer, regenerated by wide char transform, - * in case the caller trashed it after a previous call. - */ - - retfail = realloc( retfail, len = 1 + wcstombs( NULL, L".", 0 )); - wcstombs( retfail, L".", len ); - - /* restore caller's locale, clean up, and return the default dirname */ - - setlocale( LC_CTYPE, locale ); - free( locale ); - return retfail; -} - -/* $RCSfile$$Revision$: end of file */ |