]>
Commit | Line | Data |
---|---|---|
9c577e89 DD |
1 | /* File name comparison routine. |
2 | ||
3 | Copyright (C) 2007 Free Software Foundation, Inc. | |
4 | ||
5 | This program is free software; you can redistribute it and/or modify | |
6 | it under the terms of the GNU General Public License as published by | |
7 | the Free Software Foundation; either version 2, or (at your option) | |
8 | any later version. | |
9 | ||
10 | This program is distributed in the hope that it will be useful, | |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
13 | GNU General Public License for more details. | |
14 | ||
15 | You should have received a copy of the GNU General Public License | |
16 | along with this program; if not, write to the Free Software Foundation, | |
17 | Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ | |
18 | ||
2657faa6 AS |
19 | #ifdef HAVE_CONFIG_H |
20 | #include "config.h" | |
21 | #endif | |
22 | ||
9c577e89 DD |
23 | #ifdef HAVE_STRING_H |
24 | #include <string.h> | |
25 | #endif | |
26 | ||
abdef8eb JBG |
27 | #ifdef HAVE_STDLIB_H |
28 | #include <stdlib.h> | |
29 | #endif | |
30 | ||
9c577e89 | 31 | #include "filenames.h" |
73bdefcf | 32 | #include "safe-ctype.h" |
abdef8eb | 33 | #include "libiberty.h" |
9c577e89 DD |
34 | |
35 | /* | |
36 | ||
37 | @deftypefn Extension int filename_cmp (const char *@var{s1}, const char *@var{s2}) | |
38 | ||
34d8f01b JB |
39 | Return zero if the two file names @var{s1} and @var{s2} are equivalent. |
40 | If not equivalent, the returned value is similar to what @code{strcmp} | |
41 | would return. In other words, it returns a negative value if @var{s1} | |
42 | is less than @var{s2}, or a positive value if @var{s2} is greater than | |
43 | @var{s2}. | |
9c577e89 | 44 | |
34d8f01b | 45 | This function does not normalize file names. As a result, this function |
9c577e89 DD |
46 | will treat filenames that are spelled differently as different even in |
47 | the case when the two filenames point to the same underlying file. | |
48 | However, it does handle the fact that on DOS-like file systems, forward | |
49 | and backward slashes are equal. | |
50 | ||
51 | @end deftypefn | |
52 | ||
53 | */ | |
54 | ||
55 | int | |
56 | filename_cmp (const char *s1, const char *s2) | |
57 | { | |
7d6b320b JB |
58 | #if !defined(HAVE_DOS_BASED_FILE_SYSTEM) \ |
59 | && !defined(HAVE_CASE_INSENSITIVE_FILE_SYSTEM) | |
9c577e89 DD |
60 | return strcmp(s1, s2); |
61 | #else | |
62 | for (;;) | |
63 | { | |
7d6b320b JB |
64 | int c1 = *s1; |
65 | int c2 = *s2; | |
9c577e89 | 66 | |
7d6b320b JB |
67 | #if defined (HAVE_CASE_INSENSITIVE_FILE_SYSTEM) |
68 | c1 = TOLOWER (c1); | |
69 | c2 = TOLOWER (c2); | |
70 | #endif | |
71 | ||
72 | #if defined (HAVE_DOS_BASED_FILE_SYSTEM) | |
9c577e89 DD |
73 | /* On DOS-based file systems, the '/' and the '\' are equivalent. */ |
74 | if (c1 == '/') | |
75 | c1 = '\\'; | |
76 | if (c2 == '/') | |
77 | c2 = '\\'; | |
7d6b320b | 78 | #endif |
9c577e89 DD |
79 | |
80 | if (c1 != c2) | |
81 | return (c1 - c2); | |
82 | ||
83 | if (c1 == '\0') | |
84 | return 0; | |
85 | ||
86 | s1++; | |
87 | s2++; | |
88 | } | |
89 | #endif | |
90 | } | |
91 | ||
007d6189 KT |
92 | /* |
93 | ||
94 | @deftypefn Extension int filename_ncmp (const char *@var{s1}, const char *@var{s2}, size_t @var{n}) | |
95 | ||
96 | Return zero if the two file names @var{s1} and @var{s2} are equivalent | |
97 | in range @var{n}. | |
98 | If not equivalent, the returned value is similar to what @code{strncmp} | |
99 | would return. In other words, it returns a negative value if @var{s1} | |
100 | is less than @var{s2}, or a positive value if @var{s2} is greater than | |
101 | @var{s2}. | |
102 | ||
103 | This function does not normalize file names. As a result, this function | |
104 | will treat filenames that are spelled differently as different even in | |
105 | the case when the two filenames point to the same underlying file. | |
106 | However, it does handle the fact that on DOS-like file systems, forward | |
107 | and backward slashes are equal. | |
108 | ||
109 | @end deftypefn | |
110 | ||
111 | */ | |
112 | ||
113 | int | |
114 | filename_ncmp (const char *s1, const char *s2, size_t n) | |
115 | { | |
7d6b320b JB |
116 | #if !defined(HAVE_DOS_BASED_FILE_SYSTEM) \ |
117 | && !defined(HAVE_CASE_INSENSITIVE_FILE_SYSTEM) | |
007d6189 KT |
118 | return strncmp(s1, s2, n); |
119 | #else | |
120 | if (!n) | |
121 | return 0; | |
122 | for (; n > 0; --n) | |
123 | { | |
7d6b320b JB |
124 | int c1 = *s1; |
125 | int c2 = *s2; | |
007d6189 | 126 | |
7d6b320b JB |
127 | #if defined (HAVE_CASE_INSENSITIVE_FILE_SYSTEM) |
128 | c1 = TOLOWER (c1); | |
129 | c2 = TOLOWER (c2); | |
130 | #endif | |
131 | ||
132 | #if defined (HAVE_DOS_BASED_FILE_SYSTEM) | |
007d6189 KT |
133 | /* On DOS-based file systems, the '/' and the '\' are equivalent. */ |
134 | if (c1 == '/') | |
135 | c1 = '\\'; | |
136 | if (c2 == '/') | |
137 | c2 = '\\'; | |
7d6b320b | 138 | #endif |
007d6189 KT |
139 | |
140 | if (c1 == '\0' || c1 != c2) | |
141 | return (c1 - c2); | |
142 | ||
143 | s1++; | |
144 | s2++; | |
145 | } | |
146 | return 0; | |
147 | #endif | |
148 | } | |
0429544a DE |
149 | |
150 | /* | |
151 | ||
152 | @deftypefn Extension hashval_t filename_hash (const void *@var{s}) | |
153 | ||
154 | Return the hash value for file name @var{s} that will be compared | |
155 | using filename_cmp. | |
156 | This function is for use with hashtab.c hash tables. | |
157 | ||
158 | @end deftypefn | |
159 | ||
160 | */ | |
161 | ||
162 | hashval_t | |
163 | filename_hash (const void *s) | |
164 | { | |
165 | /* The cast is for -Wc++-compat. */ | |
166 | const unsigned char *str = (const unsigned char *) s; | |
167 | hashval_t r = 0; | |
168 | unsigned char c; | |
169 | ||
170 | while ((c = *str++) != 0) | |
171 | { | |
172 | if (c == '\\') | |
173 | c = '/'; | |
174 | c = TOLOWER (c); | |
175 | r = r * 67 + c - 113; | |
176 | } | |
177 | ||
178 | return r; | |
179 | } | |
180 | ||
181 | /* | |
182 | ||
183 | @deftypefn Extension int filename_eq (const void *@var{s1}, const void *@var{s2}) | |
184 | ||
185 | Return non-zero if file names @var{s1} and @var{s2} are equivalent. | |
186 | This function is for use with hashtab.c hash tables. | |
187 | ||
188 | @end deftypefn | |
189 | ||
190 | */ | |
191 | ||
192 | int | |
193 | filename_eq (const void *s1, const void *s2) | |
194 | { | |
195 | /* The casts are for -Wc++-compat. */ | |
196 | return filename_cmp ((const char *) s1, (const char *) s2) == 0; | |
197 | } | |
abdef8eb JBG |
198 | |
199 | /* | |
200 | ||
201 | @deftypefn Extension int canonical_filename_eq (const char *@var{a}, const char *@var{b}) | |
202 | ||
203 | Return non-zero if file names @var{a} and @var{b} are equivalent. | |
204 | This function compares the canonical versions of the filenames as returned by | |
205 | @code{lrealpath()}, so that so that different file names pointing to the same | |
206 | underlying file are treated as being identical. | |
207 | ||
208 | @end deftypefn | |
209 | ||
210 | */ | |
211 | ||
212 | int | |
213 | canonical_filename_eq (const char * a, const char * b) | |
214 | { | |
215 | char * ca = lrealpath(a); | |
216 | char * cb = lrealpath(b); | |
217 | int res = filename_eq (ca, cb); | |
218 | free (ca); | |
219 | free (cb); | |
220 | return res; | |
221 | } |