xref: /netbsd-src/external/gpl3/binutils.old/dist/libiberty/filename_cmp.c (revision e992f068c547fd6e84b3f104dc2340adcc955732)
116dce513Schristos /* File name comparison routine.
216dce513Schristos 
3*e992f068Schristos    Copyright (C) 2007-2022 Free Software Foundation, Inc.
416dce513Schristos 
516dce513Schristos    This program is free software; you can redistribute it and/or modify
616dce513Schristos    it under the terms of the GNU General Public License as published by
716dce513Schristos    the Free Software Foundation; either version 2, or (at your option)
816dce513Schristos    any later version.
916dce513Schristos 
1016dce513Schristos    This program is distributed in the hope that it will be useful,
1116dce513Schristos    but WITHOUT ANY WARRANTY; without even the implied warranty of
1216dce513Schristos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1316dce513Schristos    GNU General Public License for more details.
1416dce513Schristos 
1516dce513Schristos    You should have received a copy of the GNU General Public License
1616dce513Schristos    along with this program; if not, write to the Free Software Foundation,
1716dce513Schristos    Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
1816dce513Schristos 
1916dce513Schristos #ifdef HAVE_CONFIG_H
2016dce513Schristos #include "config.h"
2116dce513Schristos #endif
2216dce513Schristos 
2316dce513Schristos #ifdef HAVE_STRING_H
2416dce513Schristos #include <string.h>
2516dce513Schristos #endif
2616dce513Schristos 
2716dce513Schristos #ifdef HAVE_STDLIB_H
2816dce513Schristos #include <stdlib.h>
2916dce513Schristos #endif
3016dce513Schristos 
3116dce513Schristos #include "filenames.h"
3216dce513Schristos #include "safe-ctype.h"
3316dce513Schristos #include "libiberty.h"
3416dce513Schristos 
3516dce513Schristos /*
3616dce513Schristos 
3716dce513Schristos @deftypefn Extension int filename_cmp (const char *@var{s1}, const char *@var{s2})
3816dce513Schristos 
3916dce513Schristos Return zero if the two file names @var{s1} and @var{s2} are equivalent.
4016dce513Schristos If not equivalent, the returned value is similar to what @code{strcmp}
4116dce513Schristos would return.  In other words, it returns a negative value if @var{s1}
4216dce513Schristos is less than @var{s2}, or a positive value if @var{s2} is greater than
4316dce513Schristos @var{s2}.
4416dce513Schristos 
4516dce513Schristos This function does not normalize file names.  As a result, this function
4616dce513Schristos will treat filenames that are spelled differently as different even in
4716dce513Schristos the case when the two filenames point to the same underlying file.
4816dce513Schristos However, it does handle the fact that on DOS-like file systems, forward
4916dce513Schristos and backward slashes are equal.
5016dce513Schristos 
5116dce513Schristos @end deftypefn
5216dce513Schristos 
5316dce513Schristos */
5416dce513Schristos 
5516dce513Schristos int
filename_cmp(const char * s1,const char * s2)5616dce513Schristos filename_cmp (const char *s1, const char *s2)
5716dce513Schristos {
5816dce513Schristos #if !defined(HAVE_DOS_BASED_FILE_SYSTEM) \
5916dce513Schristos     && !defined(HAVE_CASE_INSENSITIVE_FILE_SYSTEM)
6016dce513Schristos   return strcmp(s1, s2);
6116dce513Schristos #else
6216dce513Schristos   for (;;)
6316dce513Schristos     {
6416dce513Schristos       int c1 = *s1;
6516dce513Schristos       int c2 = *s2;
6616dce513Schristos 
6716dce513Schristos #if defined (HAVE_CASE_INSENSITIVE_FILE_SYSTEM)
6816dce513Schristos       c1 = TOLOWER (c1);
6916dce513Schristos       c2 = TOLOWER (c2);
7016dce513Schristos #endif
7116dce513Schristos 
7216dce513Schristos #if defined (HAVE_DOS_BASED_FILE_SYSTEM)
7316dce513Schristos       /* On DOS-based file systems, the '/' and the '\' are equivalent.  */
7416dce513Schristos       if (c1 == '/')
7516dce513Schristos         c1 = '\\';
7616dce513Schristos       if (c2 == '/')
7716dce513Schristos         c2 = '\\';
7816dce513Schristos #endif
7916dce513Schristos 
8016dce513Schristos       if (c1 != c2)
8116dce513Schristos         return (c1 - c2);
8216dce513Schristos 
8316dce513Schristos       if (c1 == '\0')
8416dce513Schristos         return 0;
8516dce513Schristos 
8616dce513Schristos       s1++;
8716dce513Schristos       s2++;
8816dce513Schristos     }
8916dce513Schristos #endif
9016dce513Schristos }
9116dce513Schristos 
9216dce513Schristos /*
9316dce513Schristos 
9416dce513Schristos @deftypefn Extension int filename_ncmp (const char *@var{s1}, const char *@var{s2}, size_t @var{n})
9516dce513Schristos 
9616dce513Schristos Return zero if the two file names @var{s1} and @var{s2} are equivalent
9716dce513Schristos in range @var{n}.
9816dce513Schristos If not equivalent, the returned value is similar to what @code{strncmp}
9916dce513Schristos would return.  In other words, it returns a negative value if @var{s1}
10016dce513Schristos is less than @var{s2}, or a positive value if @var{s2} is greater than
10116dce513Schristos @var{s2}.
10216dce513Schristos 
10316dce513Schristos This function does not normalize file names.  As a result, this function
10416dce513Schristos will treat filenames that are spelled differently as different even in
10516dce513Schristos the case when the two filenames point to the same underlying file.
10616dce513Schristos However, it does handle the fact that on DOS-like file systems, forward
10716dce513Schristos and backward slashes are equal.
10816dce513Schristos 
10916dce513Schristos @end deftypefn
11016dce513Schristos 
11116dce513Schristos */
11216dce513Schristos 
11316dce513Schristos int
filename_ncmp(const char * s1,const char * s2,size_t n)11416dce513Schristos filename_ncmp (const char *s1, const char *s2, size_t n)
11516dce513Schristos {
11616dce513Schristos #if !defined(HAVE_DOS_BASED_FILE_SYSTEM) \
11716dce513Schristos     && !defined(HAVE_CASE_INSENSITIVE_FILE_SYSTEM)
11816dce513Schristos   return strncmp(s1, s2, n);
11916dce513Schristos #else
12016dce513Schristos   if (!n)
12116dce513Schristos     return 0;
12216dce513Schristos   for (; n > 0; --n)
12316dce513Schristos   {
12416dce513Schristos       int c1 = *s1;
12516dce513Schristos       int c2 = *s2;
12616dce513Schristos 
12716dce513Schristos #if defined (HAVE_CASE_INSENSITIVE_FILE_SYSTEM)
12816dce513Schristos       c1 = TOLOWER (c1);
12916dce513Schristos       c2 = TOLOWER (c2);
13016dce513Schristos #endif
13116dce513Schristos 
13216dce513Schristos #if defined (HAVE_DOS_BASED_FILE_SYSTEM)
13316dce513Schristos       /* On DOS-based file systems, the '/' and the '\' are equivalent.  */
13416dce513Schristos       if (c1 == '/')
13516dce513Schristos         c1 = '\\';
13616dce513Schristos       if (c2 == '/')
13716dce513Schristos         c2 = '\\';
13816dce513Schristos #endif
13916dce513Schristos 
14016dce513Schristos       if (c1 == '\0' || c1 != c2)
14116dce513Schristos         return (c1 - c2);
14216dce513Schristos 
14316dce513Schristos       s1++;
14416dce513Schristos       s2++;
14516dce513Schristos   }
14616dce513Schristos   return 0;
14716dce513Schristos #endif
14816dce513Schristos }
14916dce513Schristos 
15016dce513Schristos /*
15116dce513Schristos 
15216dce513Schristos @deftypefn Extension hashval_t filename_hash (const void *@var{s})
15316dce513Schristos 
15416dce513Schristos Return the hash value for file name @var{s} that will be compared
15516dce513Schristos using filename_cmp.
15616dce513Schristos This function is for use with hashtab.c hash tables.
15716dce513Schristos 
15816dce513Schristos @end deftypefn
15916dce513Schristos 
16016dce513Schristos */
16116dce513Schristos 
16216dce513Schristos hashval_t
filename_hash(const void * s)16316dce513Schristos filename_hash (const void *s)
16416dce513Schristos {
16516dce513Schristos   /* The cast is for -Wc++-compat.  */
16616dce513Schristos   const unsigned char *str = (const unsigned char *) s;
16716dce513Schristos   hashval_t r = 0;
16816dce513Schristos   unsigned char c;
16916dce513Schristos 
17016dce513Schristos   while ((c = *str++) != 0)
17116dce513Schristos     {
17216dce513Schristos       if (c == '\\')
17316dce513Schristos 	c = '/';
17416dce513Schristos       c = TOLOWER (c);
17516dce513Schristos       r = r * 67 + c - 113;
17616dce513Schristos     }
17716dce513Schristos 
17816dce513Schristos   return r;
17916dce513Schristos }
18016dce513Schristos 
18116dce513Schristos /*
18216dce513Schristos 
18316dce513Schristos @deftypefn Extension int filename_eq (const void *@var{s1}, const void *@var{s2})
18416dce513Schristos 
18516dce513Schristos Return non-zero if file names @var{s1} and @var{s2} are equivalent.
18616dce513Schristos This function is for use with hashtab.c hash tables.
18716dce513Schristos 
18816dce513Schristos @end deftypefn
18916dce513Schristos 
19016dce513Schristos */
19116dce513Schristos 
19216dce513Schristos int
filename_eq(const void * s1,const void * s2)19316dce513Schristos filename_eq (const void *s1, const void *s2)
19416dce513Schristos {
19516dce513Schristos   /* The casts are for -Wc++-compat.  */
19616dce513Schristos   return filename_cmp ((const char *) s1, (const char *) s2) == 0;
19716dce513Schristos }
19816dce513Schristos 
19916dce513Schristos /*
20016dce513Schristos 
20116dce513Schristos @deftypefn Extension int canonical_filename_eq (const char *@var{a}, const char *@var{b})
20216dce513Schristos 
20316dce513Schristos Return non-zero if file names @var{a} and @var{b} are equivalent.
20416dce513Schristos This function compares the canonical versions of the filenames as returned by
20516dce513Schristos @code{lrealpath()}, so that so that different file names pointing to the same
20616dce513Schristos underlying file are treated as being identical.
20716dce513Schristos 
20816dce513Schristos @end deftypefn
20916dce513Schristos 
21016dce513Schristos */
21116dce513Schristos 
21216dce513Schristos int
canonical_filename_eq(const char * a,const char * b)21316dce513Schristos canonical_filename_eq (const char * a, const char * b)
21416dce513Schristos {
21516dce513Schristos   char * ca = lrealpath(a);
21616dce513Schristos   char * cb = lrealpath(b);
21716dce513Schristos   int res = filename_eq (ca, cb);
21816dce513Schristos   free (ca);
21916dce513Schristos   free (cb);
22016dce513Schristos   return res;
22116dce513Schristos }
222