summaryrefslogtreecommitdiffstats
path: root/gnulib-local/lib/basename.c
blob: 5874420c9a05968182288dadcfeb280af838ae82 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
/* Return the name-within-directory of a file name.
   Copyright (C) 1996-1999, 2000-2002, 2004, 2006, 2010, 2012 Free Software Foundation, Inc.

   NOTE: The canonical source of this file is maintained with the GNU C Library.
   Bugs can be reported to bug-glibc@gnu.org.

   This program is free software: you can redistribute it and/or modify it
   under the terms of the GNU General Public License as published by the
   Free Software Foundation; either version 3 of the License, or any
   later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */

#include <config.h>

/* Specification.  */
#include "basename.h"

#if !(__GLIBC__ >= 2 || defined __UCLIBC__)

#include <stdio.h>
#include <assert.h>

#if defined _WIN32 || defined __WIN32__ || defined __CYGWIN__ || defined __EMX__ || defined __DJGPP__
  /* Win32, Cygwin, OS/2, DOS */
# define HAS_DEVICE(P) \
    ((((P)[0] >= 'A' && (P)[0] <= 'Z') || ((P)[0] >= 'a' && (P)[0] <= 'z')) \
     && (P)[1] == ':')
# define FILE_SYSTEM_PREFIX_LEN(P) (HAS_DEVICE (P) ? 2 : 0)
# define ISSLASH(C) ((C) == '/' || (C) == '\\')
#endif

#ifndef FILE_SYSTEM_PREFIX_LEN
# define FILE_SYSTEM_PREFIX_LEN(Filename) 0
#endif

#ifndef ISSLASH
# define ISSLASH(C) ((C) == '/')
#endif

#ifndef _LIBC
/* We cannot generally use the name 'basename' since XPG defines an unusable
   variant of the function but we cannot use it.  */
# undef basename
# define basename gnu_basename
#endif

/* 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 '/'.  */

char *
basename (char const *name)
{
  char const *base = name += FILE_SYSTEM_PREFIX_LEN (name);
  int all_slashes = 1;
  char const *p;

  for (p = name; *p; p++)
    {
      if (ISSLASH (*p))
        base = p + 1;
      else
        all_slashes = 0;
    }

  /* If NAME is all slashes, arrange to return '/'.  */
  if (*base == '\0' && ISSLASH (*name) && all_slashes)
    --base;

  /* Make sure the last byte is not a slash.  */
  assert (all_slashes || !ISSLASH (*(p - 1)));

  return (char *) base;
}

#endif