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