(FILESYSTEM_PREFIX_LEN, PARAMS, ISSLASH): Remove; now in dirname.h.
authorJim Meyering <jim@meyering.net>
Sat, 12 May 2001 14:23:49 +0000 (14:23 +0000)
committerJim Meyering <jim@meyering.net>
Sat, 12 May 2001 14:23:49 +0000 (14:23 +0000)
Do not include <stdio.h>, <assert.h>; no longer needed.
Include <string.h>, <dirname.h>.
(base_name): Allow file names ending in slashes, other than names
that are all slashes.  In this case, return the basename followed
by the slashes.  This is more general, and can be used in places
where the original base_name purposely had an assertion failure.
(base_len): New function.

lib/basename.c

index 36e0f62..ff55b58 100644 (file)
 # include <config.h>
 #endif
 
-#include <stdio.h>
-#include <assert.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
-#endif
-
-#ifndef ISSLASH
-# define ISSLASH(C) ((C) == '/')
+#if STDC_HEADERS || HAVE_STRING_H
+# include <string.h>
 #endif
-
-char *base_name PARAMS ((char const *name));
+#include <dirname.h>
 
 /* In general, we can't use the builtin `basename' function if available,
    since it has different meanings in different environments.
    In some environments the builtin `basename' modifies its argument.
-   If NAME is all slashes, be sure to return `/'.  */
+
+   Return the address of the last file name component of NAME.  If
+   NAME has no file name components because it is all slashes, return
+   NAME if it is empty, the address of its last slash otherwise.  */
 
 char *
 base_name (char const *name)
 {
-  char const *base = name += FILESYSTEM_PREFIX_LEN (name);
-  int all_slashes = 1;
+  char const *base = name + FILESYSTEM_PREFIX_LEN (name);
   char const *p;
 
-  for (p = name; *p; p++)
+  for (p = base; *p; p++)
     {
       if (ISSLASH (*p))
-       base = p + 1;
-      else
-       all_slashes = 0;
-    }
+       {
+         /* Treat multiple adjacent slashes like a single slash.  */
+         do p++;
+         while (ISSLASH (*p));
 
-  /* If NAME is all slashes, arrange to return `/'.  */
-  if (*base == '\0' && ISSLASH (*name) && all_slashes)
-    --base;
+         /* If the file name ends in slash, use the trailing slash as
+            the basename if no non-slashes have been found.  */
+         if (! *p)
+           {
+             if (ISSLASH (*base))
+               base = p - 1;
+             break;
+           }
 
-  /* Make sure the last byte is not a slash.  */
-  assert (all_slashes || !ISSLASH (*(p - 1)));
+         /* *P is a non-slash preceded by a slash.  */
+         base = p;
+       }
+    }
 
   return (char *) base;
 }
+
+/* Return the length of of the basename NAME.  Typically NAME is the
+   value returned by base_name.  Act like strlen (NAME), except omit
+   redundant trailing slashes.  */
+
+size_t
+base_len (char const *name)
+{
+  size_t len;
+
+  for (len = strlen (name);  1 < len && ISSLASH (name[len - 1]);  len--)
+    continue;
+
+  return len;
+}