1 /* dirname.c -- return all but the last element in a path
2 Copyright (C) 1990, 1998, 2000 Free Software Foundation, Inc.
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software Foundation,
16 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
27 #if defined STDC_HEADERS || defined HAVE_STRING_H
32 # define strrchr rindex
37 #ifndef HAVE_DECL_MEMRCHR
38 "this configure-time declaration test was not run"
40 #if !HAVE_DECL_MEMRCHR
47 # define ISSLASH(C) ((C) == '/')
50 #define BACKSLASH_IS_PATH_SEPARATOR ISSLASH ('\\')
52 /* Return the length of the directory part of PATH.
53 Set *RESULT to point to PATH or to `"."', as appropriate. */
55 dir_name_r (const char *path, const char **result)
58 int length; /* Length of result, not including NUL. */
60 slash = strrchr (path, '/');
61 if (BACKSLASH_IS_PATH_SEPARATOR)
63 char *b = strrchr (path, '\\');
68 /* If the last byte of PATH is a slash, decrement SLASH until it's
69 pointing at the leftmost in a sequence of trailing slashes. */
70 if (slash && slash[1] == 0)
72 while (path < slash && ISSLASH (slash[-1]))
79 slash = memrchr (path, '/', slash - path);
80 if (BACKSLASH_IS_PATH_SEPARATOR)
82 char *b = memrchr (path, '\\', slash - path);
91 /* File is in the current directory. */
97 /* Remove any trailing slashes from the result. */
98 if (BACKSLASH_IS_PATH_SEPARATOR)
100 const char *lim = ((path[0] >= 'A' && path[0] <= 'z'
104 /* If canonicalized "d:/path", leave alone the root case "d:/". */
105 while (slash > lim && ISSLASH (*slash))
110 while (slash > path && ISSLASH (*slash))
114 length = slash - path + 1;
121 /* Return the leading directories part of PATH,
122 allocated with malloc. If out of memory, return 0.
123 Works properly even if there are trailing slashes
124 (by effectively ignoring them). */
127 dir_name (const char *path)
130 size_t length = dir_name_r (path, &result);
131 char *newpath = (char *) malloc (length + 1);
134 strncpy (newpath, result, length);
142 Run the test like this (expect no output):
143 gcc -DHAVE_CONFIG_H -DTEST_DIRNAME -I.. -O -Wall memrchr.c dirname.c
144 sed -n '/^BEGIN-DATA$/,/^END-DATA$/p' dirname.c|grep -v DATA|./a.out
157 # define MAX_BUFF_LEN 1024
164 char buff[MAX_BUFF_LEN + 1];
166 buff[MAX_BUFF_LEN] = 0;
167 while (fgets (buff, MAX_BUFF_LEN, stdin) && buff[0])
169 char path[MAX_BUFF_LEN];
170 char expected_result[MAX_BUFF_LEN];
172 sscanf (buff, "%s %s", path, expected_result);
173 result = dir_name (path);
174 if (strcmp (result, expected_result))
175 printf ("%s: got %s, expected %s\n", path, result, expected_result);