* 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:
parent
75ea5758cd
commit
724dbeea36
|
@ -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.
|
||||
|
|
|
@ -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 */
|
||||
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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 */
|
|
@ -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 */
|
Loading…
Reference in New Issue