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 leading directories part of PATH,
53 allocated with malloc. If out of memory, return 0.
54 Works properly even if there are trailing slashes
55 (by effectively ignoring them). */
58 dir_name (const char *path)
62 int length; /* Length of result, not including NUL. */
64 slash = strrchr (path, '/');
65 if (BACKSLASH_IS_PATH_SEPARATOR)
67 char *b = strrchr (path, '\\');
72 /* If the last byte of PATH is a slash, decrement SLASH until it's
73 pointing at the leftmost in a sequence of trailing slashes. */
74 if (slash && slash[1] == 0)
76 while (path < slash && ISSLASH (slash[-1]))
83 slash = memrchr (path, '/', slash - path);
84 if (BACKSLASH_IS_PATH_SEPARATOR)
86 char *b = memrchr (path, '\\', slash - path);
95 /* File is in the current directory. */
101 /* Remove any trailing slashes from the result. */
102 if (BACKSLASH_IS_PATH_SEPARATOR)
104 const char *lim = ((path[0] >= 'A' && path[0] <= 'z'
108 /* If canonicalized "d:/path", leave alone the root case "d:/". */
109 while (slash > lim && ISSLASH (*slash))
114 while (slash > path && ISSLASH (*slash))
118 length = slash - path + 1;
121 newpath = (char *) malloc (length + 1);
124 strncpy (newpath, path, length);
132 Run the test like this (expect no output):
133 gcc -DHAVE_CONFIG_H -DTEST_DIRNAME -I.. -O -Wall memrchr.c dirname.c
134 sed -n '/^BEGIN-DATA$/,/^END-DATA$/p' dirname.c|grep -v DATA|./a.out
147 # define MAX_BUFF_LEN 1024
154 char buff[MAX_BUFF_LEN + 1];
156 buff[MAX_BUFF_LEN] = 0;
157 while (fgets (buff, MAX_BUFF_LEN, stdin) && buff[0])
159 char path[MAX_BUFF_LEN];
160 char expected_result[MAX_BUFF_LEN];
162 sscanf (buff, "%s %s", path, expected_result);
163 result = dir_name (path);
164 if (strcmp (result, expected_result))
165 printf ("%s: got %s, expected %s\n", path, result, expected_result);