19 |
# include <config.h> |
# include <config.h> |
20 |
#endif |
#endif |
21 |
|
|
22 |
#include <stdio.h> |
#if STDC_HEADERS || HAVE_STRING_H |
23 |
#include <assert.h> |
# include <string.h> |
|
|
|
|
#ifndef FILESYSTEM_PREFIX_LEN |
|
|
# define FILESYSTEM_PREFIX_LEN(Filename) 0 |
|
|
#endif |
|
|
|
|
|
#ifndef PARAMS |
|
|
# if defined PROTOTYPES || (defined __STDC__ && __STDC__) |
|
|
# define PARAMS(Args) Args |
|
|
# else |
|
|
# define PARAMS(Args) () |
|
|
# endif |
|
24 |
#endif |
#endif |
25 |
|
#include "dirname.h" |
|
#ifndef ISSLASH |
|
|
# define ISSLASH(C) ((C) == '/') |
|
|
#endif |
|
|
|
|
|
char *base_name PARAMS ((char const *name)); |
|
26 |
|
|
27 |
/* In general, we can't use the builtin `basename' function if available, |
/* In general, we can't use the builtin `basename' function if available, |
28 |
since it has different meanings in different environments. |
since it has different meanings in different environments. |
29 |
In some environments the builtin `basename' modifies its argument. |
In some environments the builtin `basename' modifies its argument. |
30 |
If NAME is all slashes, be sure to return `/'. */ |
|
31 |
|
Return the address of the last file name component of NAME. If |
32 |
|
NAME has no file name components because it is all slashes, return |
33 |
|
NAME if it is empty, the address of its last slash otherwise. */ |
34 |
|
|
35 |
char * |
char * |
36 |
base_name (char const *name) |
base_name (char const *name) |
37 |
{ |
{ |
38 |
char const *base = name += FILESYSTEM_PREFIX_LEN (name); |
char const *base = name + FILESYSTEM_PREFIX_LEN (name); |
|
int all_slashes = 1; |
|
39 |
char const *p; |
char const *p; |
40 |
|
|
41 |
for (p = name; *p; p++) |
for (p = base; *p; p++) |
42 |
{ |
{ |
43 |
if (ISSLASH (*p)) |
if (ISSLASH (*p)) |
44 |
base = p + 1; |
{ |
45 |
else |
/* Treat multiple adjacent slashes like a single slash. */ |
46 |
all_slashes = 0; |
do p++; |
47 |
|
while (ISSLASH (*p)); |
48 |
|
|
49 |
|
/* If the file name ends in slash, use the trailing slash as |
50 |
|
the basename if no non-slashes have been found. */ |
51 |
|
if (! *p) |
52 |
|
{ |
53 |
|
if (ISSLASH (*base)) |
54 |
|
base = p - 1; |
55 |
|
break; |
56 |
|
} |
57 |
|
|
58 |
|
/* *P is a non-slash preceded by a slash. */ |
59 |
|
base = p; |
60 |
|
} |
61 |
} |
} |
62 |
|
|
63 |
/* If NAME is all slashes, arrange to return `/'. */ |
return (char *) base; |
64 |
if (*base == '\0' && ISSLASH (*name) && all_slashes) |
} |
|
--base; |
|
65 |
|
|
66 |
/* Make sure the last byte is not a slash. */ |
/* Return the length of of the basename NAME. Typically NAME is the |
67 |
assert (all_slashes || !ISSLASH (*(p - 1))); |
value returned by base_name. Act like strlen (NAME), except omit |
68 |
|
redundant trailing slashes. */ |
69 |
|
|
70 |
return (char *) base; |
size_t |
71 |
|
base_len (char const *name) |
72 |
|
{ |
73 |
|
size_t len; |
74 |
|
|
75 |
|
for (len = strlen (name); 1 < len && ISSLASH (name[len - 1]); len--) |
76 |
|
continue; |
77 |
|
|
78 |
|
return len; |
79 |
} |
} |