* 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:
		| @@ -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
									
								
							
							
						
						
									
										31
									
								
								winsup/mingw/include/libgen.h
									
									
									
									
									
										Executable 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 */ | ||||
|  | ||||
| @@ -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
									
								
							
							
						
						
									
										103
									
								
								winsup/mingw/mingwex/basename.c
									
									
									
									
									
										Executable 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
									
								
							
							
						
						
									
										174
									
								
								winsup/mingw/mingwex/dirname.c
									
									
									
									
									
										Executable 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 */ | ||||
		Reference in New Issue
	
	Block a user