0fd981f3032e09dbd35c276e6ef6224dcb5d40ce
[gnulib.git] / lib / basename.c
1 /* basename.c -- return the last element in a path */
2
3 #if HAVE_CONFIG_H
4 # include <config.h>
5 #endif
6
7 #ifndef FILESYSTEM_PREFIX_LEN
8 # define FILESYSTEM_PREFIX_LEN(f) 0
9 #endif
10
11 #ifndef ISSLASH
12 # define ISSLASH(c) ((c) == '/')
13 #endif
14
15 /* In general, we can't use the builtin `basename' function if available,
16    since it has different meanings in different environments.
17    In some environments the builtin `basename' modifies its argument.  */
18
19 char *
20 base_name (name)
21      char const *name;
22 {
23   char const *base = name += FILESYSTEM_PREFIX_LEN (name);
24
25   for (; *name; name++)
26     if (ISSLASH (*name))
27       base = name + 1;
28
29   return (char *) base;
30 }
31
32 #ifdef STDC_HEADERS
33 # include <stdlib.h>
34 #else
35 char *malloc ();
36 #endif
37
38 char *
39 base_name_strip_trailing_slashes (name)
40      char const *name;
41 {
42   char const *end_p = name += FILESYSTEM_PREFIX_LEN (name);
43   char const *first, *p;
44   char *base;
45   int length;
46
47   /* Make END_P point to the byte after the last non-slash character
48      in NAME if one exists.  */
49   for (p = name; *p; p++)
50     if (!ISSLASH (*p))
51       end_p = p + 1;
52
53   if (end_p == name)
54     {
55       first = end_p;
56     }
57   else
58     {
59       first = end_p - 1;
60       while (first > name && !ISSLASH (*(first - 1)))
61         --first;
62     }
63
64   length = end_p - first;
65   base = (char *) malloc (length + 1);
66   if (base == 0)
67     return 0;
68
69   memcpy (base, first, length);
70   base[length] = '\0';
71
72   return base;
73 }
74
75 #ifdef TEST
76 # include <assert.h>
77 # include <stdlib.h>
78
79 # define CHECK(a,b) assert (strcmp (base_name_strip_trailing_slashes(a), b) \
80                             == 0)
81
82 int
83 main ()
84 {
85   CHECK ("a", "a");
86   CHECK ("ab", "ab");
87   CHECK ("ab/c", "c");
88   CHECK ("/ab/c", "c");
89   CHECK ("/ab/c/", "c");
90   CHECK ("/ab/c////", "c");
91   CHECK ("/", "");
92   CHECK ("////", "");
93   CHECK ("////a", "a");
94   CHECK ("//a//", "a");
95   CHECK ("/a", "a");
96   exit (0);
97 }
98 #endif