summaryrefslogtreecommitdiffstats
path: root/winsup/mingw/mingwex/basename.c
blob: 768b9a0f4e14cb00669010b95db7aaeebf896297 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
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 */