* include/libgen.h: New file; required by...

* mingwex/basename.c, mingwex/dirname.c: New files.
* mingwex/Makefile.in (DISTFILES): Add them...
(POSIX_OBJS): ...with corresponding basename.o, dirname.o
(Dependencies): Typo; s/Dependancies/Dependencies/
This commit is contained in:
Keith Marshall 2006-12-31 18:03:33 +00:00
parent 75ea5758cd
commit 724dbeea36
5 changed files with 321 additions and 3 deletions

View File

@ -1,3 +1,11 @@
2006-12-31 Keith Marshall <keithmarshall@users.sourceforge.net>
* include/libgen.h: New file; required by...
* mingwex/basename.c, mingwex/dirname.c: New files.
* mingwex/Makefile.in (DISTFILES): Add them...
(POSIX_OBJS): ...with corresponding basename.o, dirname.o
(Dependencies): Typo; s/Dependancies/Dependencies/
2006-11-25 Keith Marshall <keithmarshall@users.sourceforge.net>
* Makefile.in (VERSION): Let configure define it.

31
winsup/mingw/include/libgen.h Executable file
View File

@ -0,0 +1,31 @@
#ifndef _LIBGEN_H_
/*
* libgen.h
*
* $Id$
*
* This file has no copyright assigned and is placed in the Public Domain.
* This file is a part of the mingw-runtime package.
* No warranty is given; refer to the file DISCLAIMER within the package.
*
* Functions for splitting pathnames into dirname and basename components.
*
*/
#define _LIBGEN_H_
/* All the headers include this file. */
#include <_mingw.h>
#ifdef __cplusplus
extern "C" {
#endif
extern __cdecl char *basename (char *);
extern __cdecl char *dirname (char *);
#ifdef __cplusplus
}
#endif
#endif /* _LIBGEN_H_: end of file */

View File

@ -36,7 +36,8 @@ DISTFILES = Makefile.in configure configure.in aclocal.m4 \
wcstoimax.c wcstold.c wcstoumax.c wctrans.c wctype.c \
wdirent.c wmemchr.c wmemcmp.c wmemcpy.c wmemmove.c wmemset.c wtoll.c \
wcrtomb.c wctob.c mbrtowc.c btowc.c mb_wc_common.h \
gettimeofday.c isblank.c iswblank.c
gettimeofday.c isblank.c iswblank.c \
basename.c dirname.c
MATH_DISTFILES = \
acosf.c acosl.c asinf.c asinl.c atan2f.c atan2l.c \
@ -172,7 +173,8 @@ FENV_OBJS = fesetround.o fegetround.o \
feclearexcept.o feholdexcept.o fegetexceptflag.o \
feraiseexcept.o fetestexcept.o fesetexceptflag.o
POSIX_OBJS = \
dirent.o wdirent.o getopt.o ftruncate.o gettimeofday.o
dirent.o wdirent.o getopt.o ftruncate.o gettimeofday.o \
basename.o dirname.o
REPLACE_OBJS = \
mingw-aligned-malloc.o mingw-fseek.o
COMPLEX_OBJS = \
@ -238,7 +240,7 @@ distclean:
#
# Dependancies
# Dependencies
#
wdirent.o: $(srcdir)/dirent.c $(srcdir)/wdirent.c

103
winsup/mingw/mingwex/basename.c Executable file
View File

@ -0,0 +1,103 @@
/* basename.c
*
* $Id$
*
* Provides an implementation of the "basename" 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 <string.h>
#include <libgen.h>
#ifndef __cdecl /* If compiling on any non-Win32 platform ... */
#define __cdecl /* this may not be defined. */
#endif
__cdecl char *basename( char *path )
{
char *retname;
static char retfail[] = ".";
if( path && *path )
{
/* step over the drive designator, if present ...
* (FIXME: maybe should confirm *path is a valid drive designator).
*/
if( path[1] == ':' )
path += 2;
/* check again, just to ensure we still have a non-empty path name ... */
if( *path )
{
/* and, when we do ...
* scan from left to right, to the char after the final dir separator
*/
for( retname = path ; *path ; ++path )
{
if( (*path == '/') || (*path == '\\') )
{
/* we found a dir separator ...
* step over it, and any others which immediately follow it
*/
while( (*path == '/') || (*path == '\\') )
++path;
/* if we didn't reach the end of the path string ... */
if( *path )
/* then we have a new candidate for the base name */
retname = path;
/* otherwise ...
* strip off any trailing dir separators which we found
*/
else while( (path > retname) && ((*--path == '/') || (*path == '\\')) )
*path = '\0';
}
}
/* retname now points at the resolved base name ...
* if it's not empty, then we return it as it is, otherwise ...
* we must have had only dir separators in the original path name,
* so we return "/".
*/
return *retname ? retname : strcpy( retfail, "/" );
}
/* or we had an empty residual path name, after the drive designator,
* in which case we simply fall through ...
*/
}
/* and, if we get to here ...
* the path name is either NULL, or it decomposes to an empty string;
* in either case, we return the default value of "." in our static buffer,
* (but strcpy it, just in case the caller trashed it after a previous call).
*/
return strcpy( retfail, "." );
}
/* $RCSfile$: end of file */

174
winsup/mingw/mingwex/dirname.c Executable file
View File

@ -0,0 +1,174 @@
/* 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 <string.h>
#include <libgen.h>
#ifndef __cdecl /* If compiling on any non-Win32 platform ... */
#define __cdecl /* this may not be defined. */
#endif
__cdecl char *dirname( char *path )
{
static char retfail[] = "?:.";
char *retname, *basename, *copyptr = retfail;
if( path && *path )
{
retname = path;
/* 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( (*path == '/') || (*path == '\\') )
{
if( (path[1] == *retname) && (path[2] == '\0') )
return retname;
}
/* For all other cases ...
* step over the drive designator, if present, copying it to retfail ...
* (FIXME: maybe should confirm *path is a valid drive designator).
*/
else if( *path && (path[1] == ':') )
{
*copyptr++ = *path++;
*copyptr++ = *path++;
}
if( *path )
{
/* 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).
*/
for( retname = basename = path ; *path ; ++path )
{
if( (*path == '/') || (*path == '\\') )
{
/* we found a dir separator ...
* step over it, and any others which immediately follow it
*/
while( (*path == '/') || (*path == '\\') )
++path;
/* if we didn't reach the end of the path string ... */
if( *path )
/* then we have a new candidate for the base name */
basename = path;
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 > retname )
{
/* 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 NULL terminator in their place.
*/
--basename;
while( (basename > retname) && ((*basename == '/') || (*basename == '\\')) )
--basename;
if( (basename == retname) && ((*retname == '/') || (*retname == '\\'))
&& (retname[1] == *retname) && (retname[2] != '/') && (retname[2] != '\\') )
++basename;
*++basename = '\0';
/* adjust the start point of the dirname,
* to accommodate the Win32 drive designator, if it was present.
*/
if( copyptr > retfail )
retname -= 2;
/* if the resultant dirname begins with EXACTLY two dir separators,
* AND both are identical, then we preserve them.
*/
path = copyptr = retname;
while( ((*path == '/') || (*path == '\\')) )
++path;
if( ((path - retname) == 2) && (*++copyptr == *retname) )
++copyptr;
/* and finally ...
* we remove any residual, redundantly duplicated separators from the dirname,
* reterminate, and return it.
*/
path = copyptr;
while( *path )
{
if( ((*copyptr++ = *path) == '/') || (*path++ == '\\') )
{
while( (*path == '/') || (*path == '\\') )
++path;
}
}
*copyptr = '\0';
return retname;
}
else if( (*retname == '/') || (*retname == '\\') )
{
*copyptr++ = *retname;
*copyptr = '\0';
return retfail;
}
}
}
/* path is NULL, or an empty string; default return value is "." ...
* return this in our own static buffer, but strcpy it, just in case
* the caller trashed it after a previous call.
*/
strcpy( copyptr, "." );
return retfail;
}
/* $RCSfile$: end of file */