xref: /netbsd-src/external/gpl3/gcc/dist/libiberty/filename_cmp.c (revision b1e838363e3c6fc78a55519254d99869742dd33c)
14fee23f9Smrg /* File name comparison routine.
24fee23f9Smrg 
3*b1e83836Smrg    Copyright (C) 2007-2022 Free Software Foundation, Inc.
44fee23f9Smrg 
54fee23f9Smrg    This program is free software; you can redistribute it and/or modify
64fee23f9Smrg    it under the terms of the GNU General Public License as published by
74fee23f9Smrg    the Free Software Foundation; either version 2, or (at your option)
84fee23f9Smrg    any later version.
94fee23f9Smrg 
104fee23f9Smrg    This program is distributed in the hope that it will be useful,
114fee23f9Smrg    but WITHOUT ANY WARRANTY; without even the implied warranty of
124fee23f9Smrg    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
134fee23f9Smrg    GNU General Public License for more details.
144fee23f9Smrg 
154fee23f9Smrg    You should have received a copy of the GNU General Public License
164fee23f9Smrg    along with this program; if not, write to the Free Software Foundation,
174fee23f9Smrg    Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
184fee23f9Smrg 
194fee23f9Smrg #ifdef HAVE_CONFIG_H
204fee23f9Smrg #include "config.h"
214fee23f9Smrg #endif
224fee23f9Smrg 
234fee23f9Smrg #ifdef HAVE_STRING_H
244fee23f9Smrg #include <string.h>
254fee23f9Smrg #endif
264fee23f9Smrg 
274d5abbe8Smrg #ifdef HAVE_STDLIB_H
284d5abbe8Smrg #include <stdlib.h>
294d5abbe8Smrg #endif
304d5abbe8Smrg 
314fee23f9Smrg #include "filenames.h"
324fee23f9Smrg #include "safe-ctype.h"
334d5abbe8Smrg #include "libiberty.h"
344fee23f9Smrg 
354fee23f9Smrg /*
364fee23f9Smrg 
374fee23f9Smrg @deftypefn Extension int filename_cmp (const char *@var{s1}, const char *@var{s2})
384fee23f9Smrg 
394fee23f9Smrg Return zero if the two file names @var{s1} and @var{s2} are equivalent.
404fee23f9Smrg If not equivalent, the returned value is similar to what @code{strcmp}
414fee23f9Smrg would return.  In other words, it returns a negative value if @var{s1}
424fee23f9Smrg is less than @var{s2}, or a positive value if @var{s2} is greater than
434fee23f9Smrg @var{s2}.
444fee23f9Smrg 
454fee23f9Smrg This function does not normalize file names.  As a result, this function
464fee23f9Smrg will treat filenames that are spelled differently as different even in
474fee23f9Smrg the case when the two filenames point to the same underlying file.
484fee23f9Smrg However, it does handle the fact that on DOS-like file systems, forward
494fee23f9Smrg and backward slashes are equal.
504fee23f9Smrg 
514fee23f9Smrg @end deftypefn
524fee23f9Smrg 
534fee23f9Smrg */
544fee23f9Smrg 
554fee23f9Smrg int
filename_cmp(const char * s1,const char * s2)564fee23f9Smrg filename_cmp (const char *s1, const char *s2)
574fee23f9Smrg {
5848fb7bfaSmrg #if !defined(HAVE_DOS_BASED_FILE_SYSTEM) \
5948fb7bfaSmrg     && !defined(HAVE_CASE_INSENSITIVE_FILE_SYSTEM)
604fee23f9Smrg   return strcmp(s1, s2);
614fee23f9Smrg #else
624fee23f9Smrg   for (;;)
634fee23f9Smrg     {
6448fb7bfaSmrg       int c1 = *s1;
6548fb7bfaSmrg       int c2 = *s2;
664fee23f9Smrg 
6748fb7bfaSmrg #if defined (HAVE_CASE_INSENSITIVE_FILE_SYSTEM)
6848fb7bfaSmrg       c1 = TOLOWER (c1);
6948fb7bfaSmrg       c2 = TOLOWER (c2);
7048fb7bfaSmrg #endif
7148fb7bfaSmrg 
7248fb7bfaSmrg #if defined (HAVE_DOS_BASED_FILE_SYSTEM)
734fee23f9Smrg       /* On DOS-based file systems, the '/' and the '\' are equivalent.  */
744fee23f9Smrg       if (c1 == '/')
754fee23f9Smrg         c1 = '\\';
764fee23f9Smrg       if (c2 == '/')
774fee23f9Smrg         c2 = '\\';
7848fb7bfaSmrg #endif
794fee23f9Smrg 
804fee23f9Smrg       if (c1 != c2)
814fee23f9Smrg         return (c1 - c2);
824fee23f9Smrg 
834fee23f9Smrg       if (c1 == '\0')
844fee23f9Smrg         return 0;
854fee23f9Smrg 
864fee23f9Smrg       s1++;
874fee23f9Smrg       s2++;
884fee23f9Smrg     }
894fee23f9Smrg #endif
904fee23f9Smrg }
914fee23f9Smrg 
9248fb7bfaSmrg /*
9348fb7bfaSmrg 
9448fb7bfaSmrg @deftypefn Extension int filename_ncmp (const char *@var{s1}, const char *@var{s2}, size_t @var{n})
9548fb7bfaSmrg 
9648fb7bfaSmrg Return zero if the two file names @var{s1} and @var{s2} are equivalent
9748fb7bfaSmrg in range @var{n}.
9848fb7bfaSmrg If not equivalent, the returned value is similar to what @code{strncmp}
9948fb7bfaSmrg would return.  In other words, it returns a negative value if @var{s1}
10048fb7bfaSmrg is less than @var{s2}, or a positive value if @var{s2} is greater than
10148fb7bfaSmrg @var{s2}.
10248fb7bfaSmrg 
10348fb7bfaSmrg This function does not normalize file names.  As a result, this function
10448fb7bfaSmrg will treat filenames that are spelled differently as different even in
10548fb7bfaSmrg the case when the two filenames point to the same underlying file.
10648fb7bfaSmrg However, it does handle the fact that on DOS-like file systems, forward
10748fb7bfaSmrg and backward slashes are equal.
10848fb7bfaSmrg 
10948fb7bfaSmrg @end deftypefn
11048fb7bfaSmrg 
11148fb7bfaSmrg */
11248fb7bfaSmrg 
11348fb7bfaSmrg int
filename_ncmp(const char * s1,const char * s2,size_t n)11448fb7bfaSmrg filename_ncmp (const char *s1, const char *s2, size_t n)
11548fb7bfaSmrg {
11648fb7bfaSmrg #if !defined(HAVE_DOS_BASED_FILE_SYSTEM) \
11748fb7bfaSmrg     && !defined(HAVE_CASE_INSENSITIVE_FILE_SYSTEM)
11848fb7bfaSmrg   return strncmp(s1, s2, n);
11948fb7bfaSmrg #else
12048fb7bfaSmrg   if (!n)
12148fb7bfaSmrg     return 0;
12248fb7bfaSmrg   for (; n > 0; --n)
12348fb7bfaSmrg   {
12448fb7bfaSmrg       int c1 = *s1;
12548fb7bfaSmrg       int c2 = *s2;
12648fb7bfaSmrg 
12748fb7bfaSmrg #if defined (HAVE_CASE_INSENSITIVE_FILE_SYSTEM)
12848fb7bfaSmrg       c1 = TOLOWER (c1);
12948fb7bfaSmrg       c2 = TOLOWER (c2);
13048fb7bfaSmrg #endif
13148fb7bfaSmrg 
13248fb7bfaSmrg #if defined (HAVE_DOS_BASED_FILE_SYSTEM)
13348fb7bfaSmrg       /* On DOS-based file systems, the '/' and the '\' are equivalent.  */
13448fb7bfaSmrg       if (c1 == '/')
13548fb7bfaSmrg         c1 = '\\';
13648fb7bfaSmrg       if (c2 == '/')
13748fb7bfaSmrg         c2 = '\\';
13848fb7bfaSmrg #endif
13948fb7bfaSmrg 
14048fb7bfaSmrg       if (c1 == '\0' || c1 != c2)
14148fb7bfaSmrg         return (c1 - c2);
14248fb7bfaSmrg 
14348fb7bfaSmrg       s1++;
14448fb7bfaSmrg       s2++;
14548fb7bfaSmrg   }
14648fb7bfaSmrg   return 0;
14748fb7bfaSmrg #endif
14848fb7bfaSmrg }
14948fb7bfaSmrg 
15048fb7bfaSmrg /*
15148fb7bfaSmrg 
15248fb7bfaSmrg @deftypefn Extension hashval_t filename_hash (const void *@var{s})
15348fb7bfaSmrg 
15448fb7bfaSmrg Return the hash value for file name @var{s} that will be compared
15548fb7bfaSmrg using filename_cmp.
15648fb7bfaSmrg This function is for use with hashtab.c hash tables.
15748fb7bfaSmrg 
15848fb7bfaSmrg @end deftypefn
15948fb7bfaSmrg 
16048fb7bfaSmrg */
16148fb7bfaSmrg 
16248fb7bfaSmrg hashval_t
filename_hash(const void * s)16348fb7bfaSmrg filename_hash (const void *s)
16448fb7bfaSmrg {
16548fb7bfaSmrg   /* The cast is for -Wc++-compat.  */
16648fb7bfaSmrg   const unsigned char *str = (const unsigned char *) s;
16748fb7bfaSmrg   hashval_t r = 0;
16848fb7bfaSmrg   unsigned char c;
16948fb7bfaSmrg 
17048fb7bfaSmrg   while ((c = *str++) != 0)
17148fb7bfaSmrg     {
17248fb7bfaSmrg       if (c == '\\')
17348fb7bfaSmrg 	c = '/';
17448fb7bfaSmrg       c = TOLOWER (c);
17548fb7bfaSmrg       r = r * 67 + c - 113;
17648fb7bfaSmrg     }
17748fb7bfaSmrg 
17848fb7bfaSmrg   return r;
17948fb7bfaSmrg }
18048fb7bfaSmrg 
18148fb7bfaSmrg /*
18248fb7bfaSmrg 
18348fb7bfaSmrg @deftypefn Extension int filename_eq (const void *@var{s1}, const void *@var{s2})
18448fb7bfaSmrg 
18548fb7bfaSmrg Return non-zero if file names @var{s1} and @var{s2} are equivalent.
18648fb7bfaSmrg This function is for use with hashtab.c hash tables.
18748fb7bfaSmrg 
18848fb7bfaSmrg @end deftypefn
18948fb7bfaSmrg 
19048fb7bfaSmrg */
19148fb7bfaSmrg 
19248fb7bfaSmrg int
filename_eq(const void * s1,const void * s2)19348fb7bfaSmrg filename_eq (const void *s1, const void *s2)
19448fb7bfaSmrg {
19548fb7bfaSmrg   /* The casts are for -Wc++-compat.  */
19648fb7bfaSmrg   return filename_cmp ((const char *) s1, (const char *) s2) == 0;
19748fb7bfaSmrg }
1984d5abbe8Smrg 
1994d5abbe8Smrg /*
2004d5abbe8Smrg 
2014d5abbe8Smrg @deftypefn Extension int canonical_filename_eq (const char *@var{a}, const char *@var{b})
2024d5abbe8Smrg 
2034d5abbe8Smrg Return non-zero if file names @var{a} and @var{b} are equivalent.
2044d5abbe8Smrg This function compares the canonical versions of the filenames as returned by
2054d5abbe8Smrg @code{lrealpath()}, so that so that different file names pointing to the same
2064d5abbe8Smrg underlying file are treated as being identical.
2074d5abbe8Smrg 
2084d5abbe8Smrg @end deftypefn
2094d5abbe8Smrg 
2104d5abbe8Smrg */
2114d5abbe8Smrg 
2124d5abbe8Smrg int
canonical_filename_eq(const char * a,const char * b)2134d5abbe8Smrg canonical_filename_eq (const char * a, const char * b)
2144d5abbe8Smrg {
2154d5abbe8Smrg   char * ca = lrealpath(a);
2164d5abbe8Smrg   char * cb = lrealpath(b);
2174d5abbe8Smrg   int res = filename_eq (ca, cb);
2184d5abbe8Smrg   free (ca);
2194d5abbe8Smrg   free (cb);
2204d5abbe8Smrg   return res;
2214d5abbe8Smrg }
222