Mercurial > hg > octave-kai > gnulib-hg
comparison lib/dirname.c @ 3038:e42896c5352d
(FILESYSTEM_PREFIX_LEN): Define.
(dir_name_r): Declare this function as static.
[BACKSLASH_IS_PATH_SEPARATOR]: Fix a bug that'd
manifest itself on a name containing a mix of slashes and
backslashes.
Make this function work with names starting with a DOS-style
drive letter and colon prefix.
(dir_name): Append `.' if necessary.
Based mostly on patches from Prashant TR and Eli Zaretskii.
author | Jim Meyering <jim@meyering.net> |
---|---|
date | Thu, 07 Dec 2000 14:10:21 +0000 |
parents | 0fdc03087206 |
children | c98368348dc3 |
comparison
equal
deleted
inserted
replaced
3037:e6757ccfb526 | 3038:e42896c5352d |
---|---|
41 void *memrchr (); | 41 void *memrchr (); |
42 #endif | 42 #endif |
43 | 43 |
44 #include "dirname.h" | 44 #include "dirname.h" |
45 | 45 |
46 #ifndef FILESYSTEM_PREFIX_LEN | |
47 # define FILESYSTEM_PREFIX_LEN(Filename) 0 | |
48 #endif | |
49 | |
46 #ifndef ISSLASH | 50 #ifndef ISSLASH |
47 # define ISSLASH(C) ((C) == '/') | 51 # define ISSLASH(C) ((C) == '/') |
48 #endif | 52 #endif |
49 | 53 |
50 #define BACKSLASH_IS_PATH_SEPARATOR ISSLASH ('\\') | 54 #define BACKSLASH_IS_PATH_SEPARATOR ISSLASH ('\\') |
51 | 55 |
52 /* Return the length of `dirname (PATH)' and set *RESULT | 56 /* Return the length of `dirname (PATH)' and set *RESULT to point |
53 to point to PATH or to `"."', as appropriate. | 57 to PATH or to `"."', as appropriate. Works properly even if |
54 Works properly even if there are trailing slashes | 58 there are trailing slashes (by effectively ignoring them). |
55 (by effectively ignoring them). */ | 59 WARNING: This function doesn't work for cwd-relative names like |
56 size_t | 60 `a:foo' that are specified with a drive-letter prefix. That case |
61 is handled in the caller. */ | |
62 static size_t | |
57 dir_name_r (char const *path, char const **result) | 63 dir_name_r (char const *path, char const **result) |
58 { | 64 { |
59 char const *slash; | 65 char const *slash; |
60 size_t length; /* Length of result, not including NUL. */ | 66 size_t length; /* Length of result, not including NUL. */ |
61 | 67 |
76 --slash; | 82 --slash; |
77 } | 83 } |
78 | 84 |
79 if (path < slash) | 85 if (path < slash) |
80 { | 86 { |
81 slash = memrchr (path, '/', slash - path); | 87 size_t len = slash - path; |
88 slash = memrchr (path, '/', len); | |
82 if (BACKSLASH_IS_PATH_SEPARATOR) | 89 if (BACKSLASH_IS_PATH_SEPARATOR) |
83 { | 90 { |
84 char const *b = memrchr (path, '\\', slash - path); | 91 char const *b = memrchr (path, '\\', len); |
85 if (b && slash < b) | 92 if (b && slash < b) |
86 slash = b; | 93 slash = b; |
87 } | 94 } |
88 } | 95 } |
89 } | 96 } |
90 | 97 |
91 if (slash == 0) | 98 if (slash == 0) |
92 { | 99 { |
93 /* File is in the current directory. */ | 100 /* File is in the current directory. */ |
94 path = "."; | 101 |
95 length = 1; | 102 length = FILESYSTEM_PREFIX_LEN (path); |
103 | |
104 if (length == 0) | |
105 { | |
106 path = "."; | |
107 length = 1; | |
108 } | |
96 } | 109 } |
97 else | 110 else |
98 { | 111 { |
99 /* Remove any trailing slashes from the result. */ | 112 /* Remove any trailing slashes from the result. If we have a |
100 if (BACKSLASH_IS_PATH_SEPARATOR) | 113 canonicalized "d:/path", leave alone the root case "d:/". */ |
101 { | 114 char const *lim = path + FILESYSTEM_PREFIX_LEN (path); |
102 char const *lim = ((path[0] >= 'A' && path[0] <= 'z' | |
103 && path[1] == ':') | |
104 ? path + 2 : path); | |
105 | 115 |
106 /* If canonicalized "d:/path", leave alone the root case "d:/". */ | 116 while (slash > lim && ISSLASH (*slash)) |
107 while (slash > lim && ISSLASH (*slash)) | 117 --slash; |
108 --slash; | |
109 } | |
110 else | |
111 { | |
112 while (slash > path && ISSLASH (*slash)) | |
113 --slash; | |
114 } | |
115 | 118 |
116 length = slash - path + 1; | 119 length = slash - path + 1; |
117 } | 120 } |
118 | 121 |
119 *result = path; | 122 *result = path; |
128 char * | 131 char * |
129 dir_name (char const *path) | 132 dir_name (char const *path) |
130 { | 133 { |
131 char const *result; | 134 char const *result; |
132 size_t length = dir_name_r (path, &result); | 135 size_t length = dir_name_r (path, &result); |
133 char *newpath = (char *) malloc (length + 1); | 136 int append_dot = (length && length == FILESYSTEM_PREFIX_LEN (newpath)); |
137 char *newpath = (char *) malloc (length + append_dot + 1); | |
134 if (newpath == 0) | 138 if (newpath == 0) |
135 return 0; | 139 return 0; |
136 strncpy (newpath, result, length); | 140 strncpy (newpath, result, length); |
141 /* If PATH is "d:foo", return "d:.", the CWD on drive d: */ | |
142 if (append_dot) | |
143 newpath[length++] = '.'; | |
137 newpath[length] = 0; | 144 newpath[length] = 0; |
138 return newpath; | 145 return newpath; |
139 } | 146 } |
140 | 147 |
141 #ifdef TEST_DIRNAME | 148 #ifdef TEST_DIRNAME |