]>
Commit | Line | Data |
---|---|---|
9a0a462c | 1 | /* Machine-independant string function optimizations. |
482eec0d | 2 | Copyright (C) 1997, 1998, 1999 Free Software Foundation, Inc. |
9a0a462c UD |
3 | This file is part of the GNU C Library. |
4 | Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997. | |
5 | ||
6 | The GNU C Library is free software; you can redistribute it and/or | |
7 | modify it under the terms of the GNU Library General Public License as | |
8 | published by the Free Software Foundation; either version 2 of the | |
9 | License, or (at your option) any later version. | |
10 | ||
11 | The GNU C Library is distributed in the hope that it will be useful, | |
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
14 | Library General Public License for more details. | |
15 | ||
16 | You should have received a copy of the GNU Library General Public | |
17 | License along with the GNU C Library; see the file COPYING.LIB. If not, | |
18 | write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
19 | Boston, MA 02111-1307, USA. */ | |
20 | ||
61eb22d3 UD |
21 | #ifndef _STRING_H |
22 | # error "Never use <bits/string2.h> directly; include <string.h> instead." | |
23 | #endif | |
24 | ||
650425ce | 25 | #ifndef __NO_STRING_INLINES |
9a0a462c UD |
26 | |
27 | /* Unlike the definitions in the header <bits/string.h> the | |
61952351 UD |
28 | definitions contained here are not optimized down to assembler |
29 | level. Those optimizations are not always a good idea since this | |
9a0a462c | 30 | means the code size increases a lot. Instead the definitions here |
61952351 UD |
31 | optimize some functions in a way which do not dramatically |
32 | increase the code size and which do not use assembler. The main | |
9a0a462c UD |
33 | trick is to use GNU CC's `__builtin_constant_p' function. |
34 | ||
35 | Every function XXX which has a defined version in | |
61eb22d3 | 36 | <bits/string.h> must be accompanied by a symbol _HAVE_STRING_ARCH_XXX |
9a0a462c UD |
37 | to make sure we don't get redefinitions. |
38 | ||
39 | We must use here macros instead of inline functions since the | |
40 | trick won't work with the later. */ | |
41 | ||
42 | #ifdef __cplusplus | |
43 | # define __STRING_INLINE inline | |
44 | #else | |
45 | # define __STRING_INLINE extern __inline | |
46 | #endif | |
47 | ||
61eb22d3 UD |
48 | #if _STRING_ARCH_unaligned |
49 | /* If we can do unaligned memory accesses we must know the endianess. */ | |
50 | # include <endian.h> | |
51 | # include <bits/types.h> | |
52 | ||
53 | # if __BYTE_ORDER == __LITTLE_ENDIAN | |
54 | # define __STRING2_SMALL_GET16(src, idx) \ | |
fab6d621 UD |
55 | (((__const unsigned char *) (__const char *) (src))[idx + 1] << 8 \ |
56 | | ((__const unsigned char *) (__const char *) (src))[idx]) | |
61eb22d3 | 57 | # define __STRING2_SMALL_GET32(src, idx) \ |
fab6d621 UD |
58 | (((((__const unsigned char *) (__const char *) (src))[idx + 3] << 8 \ |
59 | | ((__const unsigned char *) (__const char *) (src))[idx + 2]) << 8 \ | |
60 | | ((__const unsigned char *) (__const char *) (src))[idx + 1]) << 8 \ | |
61 | | ((__const unsigned char *) (__const char *) (src))[idx]) | |
61eb22d3 UD |
62 | # else |
63 | # define __STRING2_SMALL_GET16(src, idx) \ | |
fab6d621 UD |
64 | (((__const unsigned char *) (__const char *) (src))[idx] << 8 \ |
65 | | ((__const unsigned char *) (__const char *) (src))[idx + 1]) | |
61eb22d3 | 66 | # define __STRING2_SMALL_GET32(src, idx) \ |
fab6d621 UD |
67 | (((((__const unsigned char *) (__const char *) (src))[idx] << 8 \ |
68 | | ((__const unsigned char *) (__const char *) (src))[idx + 1]) << 8 \ | |
69 | | ((__const unsigned char *) (__const char *) (src))[idx + 2]) << 8 \ | |
70 | | ((__const unsigned char *) (__const char *) (src))[idx + 3]) | |
61eb22d3 UD |
71 | # endif |
72 | #else | |
73 | /* These are a few types we need for the optimizations if we cannot | |
74 | use unaligned memory accesses. */ | |
75 | # define __STRING2_COPY_TYPE(N) \ | |
fab6d621 | 76 | typedef struct { unsigned char __arr[N]; } \ |
61eb22d3 UD |
77 | __STRING2_COPY_ARR##N __attribute__ ((packed)) |
78 | __STRING2_COPY_TYPE (2); | |
79 | __STRING2_COPY_TYPE (3); | |
80 | __STRING2_COPY_TYPE (4); | |
81 | __STRING2_COPY_TYPE (5); | |
82 | __STRING2_COPY_TYPE (6); | |
83 | __STRING2_COPY_TYPE (7); | |
84 | __STRING2_COPY_TYPE (8); | |
85 | # undef __STRING2_COPY_TYPE | |
86 | #endif | |
87 | ||
7ef90c15 UD |
88 | /* Dereferencing a pointer arg to run sizeof on it fails for the void |
89 | pointer case, so we use this instead. | |
90 | Note that __x is evaluated twice. */ | |
91 | #define __string2_1bptr_p(__x) \ | |
36ab45e1 | 92 | ((size_t)(const void *)((__x) + 1) - (size_t)(const void *)(__x) == 1) |
61eb22d3 UD |
93 | |
94 | /* Set N bytes of S to C. */ | |
95 | #ifndef _HAVE_STRING_ARCH_memset | |
96 | # define memset(s, c, n) \ | |
99434729 | 97 | (__extension__ (__builtin_constant_p (n) && (n) <= 16 \ |
c1d226e7 UD |
98 | ? ((n) == 1 \ |
99 | ? __memset_1 (s, c) \ | |
100 | : __memset_gc (s, (((__uint8_t) c) * 0x1010101), n)) \ | |
99434729 UD |
101 | : (__builtin_constant_p (c) && (c) == '\0' \ |
102 | ? ({ void *__s = (s); __bzero (__s, n); __s; }) \ | |
103 | : memset (s, c, n)))) | |
104 | ||
c1d226e7 UD |
105 | #define __memset_1(s, c) ({ void *__s = (s); *((__uint8_t *) __s) = c; __s; }) |
106 | ||
99434729 UD |
107 | #define __memset_gc(s, c, n) \ |
108 | ({ void *__s = (s); \ | |
109 | __uint32_t *__ts = (__uint32_t *) __s; \ | |
110 | \ | |
111 | /* This `switch' statement will be removed at compile-time. */ \ | |
112 | switch (n) \ | |
113 | { \ | |
114 | case 15: \ | |
115 | *__ts++ = c; \ | |
116 | case 11: \ | |
117 | *__ts++ = c; \ | |
118 | case 7: \ | |
119 | *__ts++ = c; \ | |
120 | case 3: \ | |
121 | *((__uint16_t *) __ts)++ = c; \ | |
122 | *((__uint8_t *) __ts) = c; \ | |
123 | break; \ | |
124 | \ | |
125 | case 14: \ | |
126 | *__ts++ = c; \ | |
127 | case 10: \ | |
128 | *__ts++ = c; \ | |
129 | case 6: \ | |
130 | *__ts++ = c; \ | |
131 | case 2: \ | |
132 | *((__uint16_t *) __ts) = c; \ | |
133 | break; \ | |
134 | \ | |
135 | case 13: \ | |
136 | *__ts++ = c; \ | |
137 | case 9: \ | |
138 | *__ts++ = c; \ | |
139 | case 5: \ | |
140 | *__ts++ = c; \ | |
141 | case 1: \ | |
142 | *((__uint8_t *) __ts) = c; \ | |
143 | break; \ | |
144 | \ | |
145 | case 16: \ | |
146 | *__ts++ = c; \ | |
147 | case 12: \ | |
148 | *__ts++ = c; \ | |
149 | case 8: \ | |
150 | *__ts++ = c; \ | |
151 | case 4: \ | |
152 | *__ts = c; \ | |
153 | case 0: \ | |
154 | break; \ | |
155 | } \ | |
156 | \ | |
157 | __s; }) | |
c1d226e7 UD |
158 | /* GCC optimizes memset(s, 0, n) but not bzero(s, n). */ |
159 | #if defined __GNUC__ && __GNUC__ >= 2 | |
160 | # define __bzero(s, n) __builtin_memset(s, '\0', n) | |
161 | #endif | |
162 | ||
61eb22d3 | 163 | #endif |
9a0a462c UD |
164 | |
165 | ||
e7c5513d UD |
166 | /* Copy N bytes from SRC to DEST, returning pointer to byte following the |
167 | last copied. */ | |
168 | #ifdef __USE_GNU | |
169 | # ifndef _HAVE_STRING_ARCH_mempcpy | |
170 | # define __mempcpy(dest, src, n) \ | |
171 | (__extension__ (__builtin_constant_p (src) && __builtin_constant_p (n) \ | |
172 | && __string2_1bptr_p (src) && n <= 8 \ | |
36ab45e1 | 173 | ? __mempcpy_small (dest, __mempcpy_args (src), n) \ |
e7c5513d UD |
174 | : __mempcpy (dest, src, n))) |
175 | /* In glibc we use this function frequently but for namespace reasons | |
176 | we have to use the name `__mempcpy'. */ | |
177 | # define mempcpy(dest, src, n) __mempcpy (dest, src, n) | |
178 | ||
179 | # if _STRING_ARCH_unaligned | |
36ab45e1 UD |
180 | # define __mempcpy_args(src) \ |
181 | ((char *) (src))[0], ((char *) (src))[2], ((char *) (src))[4], \ | |
182 | ((char *) (src))[6], \ | |
183 | __extension__ __STRING2_SMALL_GET16 (src, 0), \ | |
184 | __extension__ __STRING2_SMALL_GET16 (src, 4), \ | |
185 | __extension__ __STRING2_SMALL_GET32 (src, 0), \ | |
186 | __extension__ __STRING2_SMALL_GET32 (src, 4) | |
fcab9698 UD |
187 | __STRING_INLINE void *__mempcpy_small (void *, char, char, char, char, |
188 | __uint16_t, __uint16_t, __uint32_t, | |
189 | __uint32_t, size_t); | |
36ab45e1 UD |
190 | __STRING_INLINE void * |
191 | __mempcpy_small (void *__dest1, | |
192 | char __src0_1, char __src2_1, char __src4_1, char __src6_1, | |
193 | __uint16_t __src0_2, __uint16_t __src4_2, | |
194 | __uint32_t __src0_4, __uint32_t __src4_4, | |
195 | size_t __srclen) | |
196 | { | |
197 | char *__dest = (char *) __dest1; | |
198 | switch (__srclen) | |
199 | { | |
200 | case 1: | |
201 | *__dest++ = __src0_1; | |
202 | break; | |
203 | case 2: | |
204 | *((__uint16_t *) __dest) = __src0_2; | |
205 | __dest += 2; | |
206 | break; | |
207 | case 3: | |
208 | *((__uint16_t *) __dest) = __src0_2; | |
209 | __dest += 2; | |
210 | *__dest++ = __src2_1; | |
211 | break; | |
212 | case 4: | |
213 | *((__uint32_t *) __dest) = __src0_4; | |
214 | __dest += 4; | |
215 | break; | |
216 | case 5: | |
217 | *((__uint32_t *) __dest) = __src0_4; | |
218 | __dest += 4; | |
219 | *__dest++ = __src4_1; | |
220 | break; | |
221 | case 6: | |
222 | *((__uint32_t *) __dest) = __src0_4; | |
223 | *((__uint16_t *) (__dest + 4)) = __src4_2; | |
224 | __dest += 6; | |
225 | break; | |
226 | case 7: | |
227 | *((__uint32_t *) __dest) = __src0_4; | |
228 | *((__uint16_t *) (__dest + 4)) = __src4_2; | |
229 | __dest += 6; | |
230 | *__dest++ = __src6_1; | |
231 | break; | |
232 | case 8: | |
233 | *((__uint32_t *) __dest) = __src0_4; | |
234 | *((__uint32_t *) (__dest + 4)) = __src4_4; | |
235 | __dest += 8; | |
236 | break; | |
237 | } | |
238 | return (void *) __dest; | |
239 | } | |
e7c5513d | 240 | # else |
36ab45e1 | 241 | # define __mempcpy_args(src) \ |
431f91ba | 242 | ((__const char *) (src))[0], \ |
36ab45e1 UD |
243 | __extension__ ((__STRING2_COPY_ARR2) \ |
244 | { { ((__const char *) (src))[0], ((__const char *) (src))[1] } }), \ | |
245 | __extension__ ((__STRING2_COPY_ARR3) \ | |
246 | { { ((__const char *) (src))[0], ((__const char *) (src))[1], \ | |
247 | ((__const char *) (src))[2] } }), \ | |
248 | __extension__ ((__STRING2_COPY_ARR4) \ | |
249 | { { ((__const char *) (src))[0], ((__const char *) (src))[1], \ | |
250 | ((__const char *) (src))[2], ((__const char *) (src))[3] } }), \ | |
251 | __extension__ ((__STRING2_COPY_ARR5) \ | |
252 | { { ((__const char *) (src))[0], ((__const char *) (src))[1], \ | |
253 | ((__const char *) (src))[2], ((__const char *) (src))[3], \ | |
254 | ((__const char *) (src))[4] } }), \ | |
255 | __extension__ ((__STRING2_COPY_ARR6) \ | |
256 | { { ((__const char *) (src))[0], ((__const char *) (src))[1], \ | |
257 | ((__const char *) (src))[2], ((__const char *) (src))[3], \ | |
258 | ((__const char *) (src))[4], ((__const char *) (src))[5] } }), \ | |
259 | __extension__ ((__STRING2_COPY_ARR7) \ | |
260 | { { ((__const char *) (src))[0], ((__const char *) (src))[1], \ | |
261 | ((__const char *) (src))[2], ((__const char *) (src))[3], \ | |
262 | ((__const char *) (src))[4], ((__const char *) (src))[5], \ | |
263 | ((__const char *) (src))[6] } }), \ | |
264 | __extension__ ((__STRING2_COPY_ARR8) \ | |
265 | { { ((__const char *) (src))[0], ((__const char *) (src))[1], \ | |
266 | ((__const char *) (src))[2], ((__const char *) (src))[3], \ | |
267 | ((__const char *) (src))[4], ((__const char *) (src))[5], \ | |
268 | ((__const char *) (src))[6], ((__const char *) (src))[7] } }) | |
fcab9698 UD |
269 | __STRING_INLINE void *__mempcpy_small (void *, char, __STRING2_COPY_ARR2, |
270 | __STRING2_COPY_ARR3, | |
271 | __STRING2_COPY_ARR4, | |
272 | __STRING2_COPY_ARR5, | |
273 | __STRING2_COPY_ARR6, | |
274 | __STRING2_COPY_ARR7, | |
275 | __STRING2_COPY_ARR8, size_t); | |
36ab45e1 | 276 | __STRING_INLINE void * |
431f91ba | 277 | __mempcpy_small (void *__dest1, char __src1, |
36ab45e1 UD |
278 | __STRING2_COPY_ARR2 __src2, __STRING2_COPY_ARR3 __src3, |
279 | __STRING2_COPY_ARR4 __src4, __STRING2_COPY_ARR5 __src5, | |
280 | __STRING2_COPY_ARR6 __src6, __STRING2_COPY_ARR7 __src7, | |
281 | __STRING2_COPY_ARR8 __src8, size_t __srclen) | |
282 | { | |
283 | char *__dest = (char *) __dest1; | |
284 | switch (__srclen) | |
285 | { | |
286 | case 1: | |
431f91ba | 287 | *__dest = __src1; |
36ab45e1 UD |
288 | break; |
289 | case 2: | |
290 | __extension__ *((__STRING2_COPY_ARR2 *) __dest) = __src2; | |
291 | break; | |
292 | case 3: | |
293 | __extension__ *((__STRING2_COPY_ARR3 *) __dest) = __src3; | |
294 | break; | |
295 | case 4: | |
296 | __extension__ *((__STRING2_COPY_ARR4 *) __dest) = __src4; | |
297 | break; | |
298 | case 5: | |
299 | __extension__ *((__STRING2_COPY_ARR5 *) __dest) = __src5; | |
300 | break; | |
301 | case 6: | |
302 | __extension__ *((__STRING2_COPY_ARR6 *) __dest) = __src6; | |
303 | break; | |
304 | case 7: | |
305 | __extension__ *((__STRING2_COPY_ARR7 *) __dest) = __src7; | |
306 | break; | |
307 | case 8: | |
308 | __extension__ *((__STRING2_COPY_ARR8 *) __dest) = __src8; | |
309 | break; | |
310 | } | |
311 | return (void *) (__dest + __srclen); | |
312 | } | |
e7c5513d UD |
313 | # endif |
314 | # endif | |
315 | #endif | |
316 | ||
317 | ||
482eec0d UD |
318 | /* Return pointer to C in S. */ |
319 | #ifndef _HAVE_STRING_ARCH_strchr | |
320 | extern __ptr_t __rawmemchr (const __ptr_t __s, int __c); | |
321 | # define strchr(s, c) \ | |
322 | (__extension__ (__builtin_constant_p (c) && (c) == '\0' \ | |
323 | ? (char *) __rawmemchr (s, c) \ | |
324 | : strchr (s, c))) | |
325 | #endif | |
326 | ||
327 | ||
9a0a462c UD |
328 | /* Copy SRC to DEST. */ |
329 | #ifndef _HAVE_STRING_ARCH_strcpy | |
330 | # define strcpy(dest, src) \ | |
331 | (__extension__ (__builtin_constant_p (src) \ | |
dfd2257a | 332 | ? (__string2_1bptr_p (src) && strlen (src) + 1 <= 8 \ |
36ab45e1 UD |
333 | ? __strcpy_small (dest, __strcpy_args (src), \ |
334 | strlen (src) + 1) \ | |
9a0a462c UD |
335 | : (char *) memcpy (dest, src, strlen (src) + 1)) \ |
336 | : strcpy (dest, src))) | |
337 | ||
61eb22d3 | 338 | # if _STRING_ARCH_unaligned |
36ab45e1 UD |
339 | # define __strcpy_args(src) \ |
340 | __extension__ __STRING2_SMALL_GET16 (src, 0), \ | |
341 | __extension__ __STRING2_SMALL_GET16 (src, 4), \ | |
342 | __extension__ __STRING2_SMALL_GET32 (src, 0), \ | |
343 | __extension__ __STRING2_SMALL_GET32 (src, 4) | |
fcab9698 UD |
344 | __STRING_INLINE char *__strcpy_small (char *, __uint16_t, __uint16_t, |
345 | __uint32_t, __uint32_t, size_t); | |
36ab45e1 UD |
346 | __STRING_INLINE char * |
347 | __strcpy_small (char *__dest, | |
348 | __uint16_t __src0_2, __uint16_t __src4_2, | |
349 | __uint32_t __src0_4, __uint32_t __src4_4, | |
350 | size_t __srclen) | |
351 | { | |
352 | switch (__srclen) | |
353 | { | |
354 | case 1: | |
355 | *__dest = '\0'; | |
356 | break; | |
357 | case 2: | |
358 | *((__uint16_t *) __dest) = __src0_2; | |
359 | break; | |
360 | case 3: | |
361 | *((__uint16_t *) __dest) = __src0_2; | |
362 | *(__dest + 2) = '\0'; | |
363 | break; | |
364 | case 4: | |
365 | *((__uint32_t *) __dest) = __src0_4; | |
366 | break; | |
367 | case 5: | |
368 | *((__uint32_t *) __dest) = __src0_4; | |
369 | *(__dest + 4) = '\0'; | |
370 | break; | |
371 | case 6: | |
372 | *((__uint32_t *) __dest) = __src0_4; | |
373 | *((__uint16_t *) (__dest + 4)) = __src4_2; | |
374 | break; | |
375 | case 7: | |
376 | *((__uint32_t *) __dest) = __src0_4; | |
377 | *((__uint16_t *) (__dest + 4)) = __src4_2; | |
378 | *(__dest + 6) = '\0'; | |
379 | break; | |
380 | case 8: | |
381 | *((__uint32_t *) __dest) = __src0_4; | |
382 | *((__uint32_t *) (__dest + 4)) = __src4_4; | |
383 | break; | |
384 | } | |
385 | return __dest; | |
386 | } | |
61eb22d3 | 387 | # else |
36ab45e1 UD |
388 | # define __strcpy_args(src) \ |
389 | __extension__ ((__STRING2_COPY_ARR2) \ | |
390 | { { ((__const char *) (src))[0], '\0' } }), \ | |
391 | __extension__ ((__STRING2_COPY_ARR3) \ | |
392 | { { ((__const char *) (src))[0], ((__const char *) (src))[1], \ | |
393 | '\0' } }), \ | |
394 | __extension__ ((__STRING2_COPY_ARR4) \ | |
395 | { { ((__const char *) (src))[0], ((__const char *) (src))[1], \ | |
396 | ((__const char *) (src))[2], '\0' } }), \ | |
397 | __extension__ ((__STRING2_COPY_ARR5) \ | |
398 | { { ((__const char *) (src))[0], ((__const char *) (src))[1], \ | |
399 | ((__const char *) (src))[2], ((__const char *) (src))[3], \ | |
400 | '\0' } }), \ | |
401 | __extension__ ((__STRING2_COPY_ARR6) \ | |
402 | { { ((__const char *) (src))[0], ((__const char *) (src))[1], \ | |
403 | ((__const char *) (src))[2], ((__const char *) (src))[3], \ | |
404 | ((__const char *) (src))[4], '\0' } }), \ | |
405 | __extension__ ((__STRING2_COPY_ARR7) \ | |
406 | { { ((__const char *) (src))[0], ((__const char *) (src))[1], \ | |
407 | ((__const char *) (src))[2], ((__const char *) (src))[3], \ | |
408 | ((__const char *) (src))[4], ((__const char *) (src))[5], \ | |
409 | '\0' } }), \ | |
410 | __extension__ ((__STRING2_COPY_ARR8) \ | |
411 | { { ((__const char *) (src))[0], ((__const char *) (src))[1], \ | |
412 | ((__const char *) (src))[2], ((__const char *) (src))[3], \ | |
413 | ((__const char *) (src))[4], ((__const char *) (src))[5], \ | |
414 | ((__const char *) (src))[6], '\0' } }) | |
fcab9698 UD |
415 | __STRING_INLINE char *__strcpy_small (char *, __STRING2_COPY_ARR2, |
416 | __STRING2_COPY_ARR3, | |
417 | __STRING2_COPY_ARR4, | |
418 | __STRING2_COPY_ARR5, | |
419 | __STRING2_COPY_ARR6, | |
420 | __STRING2_COPY_ARR7, | |
421 | __STRING2_COPY_ARR8, size_t); | |
36ab45e1 UD |
422 | __STRING_INLINE char * |
423 | __strcpy_small (char *__dest, | |
424 | __STRING2_COPY_ARR2 __src2, __STRING2_COPY_ARR3 __src3, | |
425 | __STRING2_COPY_ARR4 __src4, __STRING2_COPY_ARR5 __src5, | |
426 | __STRING2_COPY_ARR6 __src6, __STRING2_COPY_ARR7 __src7, | |
427 | __STRING2_COPY_ARR8 __src8, size_t __srclen) | |
428 | { | |
429 | switch (__srclen) | |
430 | { | |
431 | case 1: | |
432 | *__dest = '\0'; | |
433 | break; | |
434 | case 2: | |
435 | __extension__ *((__STRING2_COPY_ARR2 *) __dest) = __src2; | |
436 | break; | |
437 | case 3: | |
438 | __extension__ *((__STRING2_COPY_ARR3 *) __dest) = __src3; | |
439 | break; | |
440 | case 4: | |
441 | __extension__ *((__STRING2_COPY_ARR4 *) __dest) = __src4; | |
442 | break; | |
443 | case 5: | |
444 | __extension__ *((__STRING2_COPY_ARR5 *) __dest) = __src5; | |
445 | break; | |
446 | case 6: | |
447 | __extension__ *((__STRING2_COPY_ARR6 *) __dest) = __src6; | |
448 | break; | |
449 | case 7: | |
450 | __extension__ *((__STRING2_COPY_ARR7 *) __dest) = __src7; | |
451 | break; | |
452 | case 8: | |
453 | __extension__ *((__STRING2_COPY_ARR8 *) __dest) = __src8; | |
454 | break; | |
455 | } | |
456 | return __dest; | |
457 | } | |
61eb22d3 | 458 | # endif |
9a0a462c UD |
459 | #endif |
460 | ||
461 | ||
462 | /* Copy SRC to DEST, returning pointer to final NUL byte. */ | |
463 | #ifdef __USE_GNU | |
464 | # ifndef _HAVE_STRING_ARCH_stpcpy | |
465 | # define __stpcpy(dest, src) \ | |
466 | (__extension__ (__builtin_constant_p (src) \ | |
dfd2257a | 467 | ? (__string2_1bptr_p (src) && strlen (src) + 1 <= 8 \ |
36ab45e1 UD |
468 | ? __stpcpy_small (dest, __stpcpy_args (src), \ |
469 | strlen (src) + 1) \ | |
9a0a462c UD |
470 | : ((char *) __mempcpy (dest, src, strlen (src) + 1) - 1))\ |
471 | : __stpcpy (dest, src))) | |
472 | /* In glibc we use this function frequently but for namespace reasons | |
473 | we have to use the name `__stpcpy'. */ | |
474 | # define stpcpy(dest, src) __stpcpy (dest, src) | |
475 | ||
61eb22d3 | 476 | # if _STRING_ARCH_unaligned |
36ab45e1 UD |
477 | # define __stpcpy_args(src) \ |
478 | __extension__ __STRING2_SMALL_GET16 (src, 0), \ | |
479 | __extension__ __STRING2_SMALL_GET16 (src, 4), \ | |
480 | __extension__ __STRING2_SMALL_GET32 (src, 0), \ | |
481 | __extension__ __STRING2_SMALL_GET32 (src, 4) | |
fcab9698 UD |
482 | __STRING_INLINE char *__stpcpy_small (char *, __uint16_t, __uint16_t, |
483 | __uint32_t, __uint32_t, size_t); | |
36ab45e1 UD |
484 | __STRING_INLINE char * |
485 | __stpcpy_small (char *__dest, | |
486 | __uint16_t __src0_2, __uint16_t __src4_2, | |
487 | __uint32_t __src0_4, __uint32_t __src4_4, | |
488 | size_t __srclen) | |
489 | { | |
490 | switch (__srclen) | |
491 | { | |
492 | case 1: | |
493 | *__dest = '\0'; | |
494 | break; | |
495 | case 2: | |
496 | *((__uint16_t *) __dest) = __src0_2; | |
497 | ++__dest; | |
498 | break; | |
499 | case 3: | |
500 | *((__uint16_t *) __dest) = __src0_2; | |
501 | __dest += sizeof (__uint16_t); | |
502 | *__dest = '\0'; | |
503 | break; | |
504 | case 4: | |
505 | *((__uint32_t *) __dest) = __src0_4; | |
506 | __dest += 3; | |
507 | break; | |
508 | case 5: | |
509 | *((__uint32_t *) __dest) = __src0_4; | |
510 | __dest += 4; | |
511 | *__dest = '\0'; | |
512 | break; | |
513 | case 6: | |
514 | *((__uint32_t *) __dest) = __src0_4; | |
515 | *((__uint16_t *) (__dest + 4)) = __src4_2; | |
516 | __dest += 5; | |
517 | break; | |
518 | case 7: | |
519 | *((__uint32_t *) __dest) = __src0_4; | |
520 | *((__uint16_t *) (__dest + 4)) = __src4_2; | |
521 | __dest += 6; | |
522 | *__dest = '\0'; | |
523 | break; | |
524 | case 8: | |
525 | *((__uint32_t *) __dest) = __src0_4; | |
526 | *((__uint32_t *) (__dest + 4)) = __src4_4; | |
527 | __dest += 7; | |
528 | break; | |
529 | } | |
530 | return __dest; | |
531 | } | |
61eb22d3 | 532 | # else |
36ab45e1 UD |
533 | # define __stpcpy_args(src) \ |
534 | __extension__ ((__STRING2_COPY_ARR2) \ | |
535 | { { ((__const char *) (src))[0], '\0' } }), \ | |
536 | __extension__ ((__STRING2_COPY_ARR3) \ | |
537 | { { ((__const char *) (src))[0], ((__const char *) (src))[1], \ | |
538 | '\0' } }), \ | |
539 | __extension__ ((__STRING2_COPY_ARR4) \ | |
540 | { { ((__const char *) (src))[0], ((__const char *) (src))[1], \ | |
541 | ((__const char *) (src))[2], '\0' } }), \ | |
542 | __extension__ ((__STRING2_COPY_ARR5) \ | |
543 | { { ((__const char *) (src))[0], ((__const char *) (src))[1], \ | |
544 | ((__const char *) (src))[2], ((__const char *) (src))[3], \ | |
545 | '\0' } }), \ | |
546 | __extension__ ((__STRING2_COPY_ARR6) \ | |
547 | { { ((__const char *) (src))[0], ((__const char *) (src))[1], \ | |
548 | ((__const char *) (src))[2], ((__const char *) (src))[3], \ | |
549 | ((__const char *) (src))[4], '\0' } }), \ | |
550 | __extension__ ((__STRING2_COPY_ARR7) \ | |
551 | { { ((__const char *) (src))[0], ((__const char *) (src))[1], \ | |
552 | ((__const char *) (src))[2], ((__const char *) (src))[3], \ | |
553 | ((__const char *) (src))[4], ((__const char *) (src))[5], \ | |
554 | '\0' } }), \ | |
555 | __extension__ ((__STRING2_COPY_ARR8) \ | |
556 | { { ((__const char *) (src))[0], ((__const char *) (src))[1], \ | |
557 | ((__const char *) (src))[2], ((__const char *) (src))[3], \ | |
558 | ((__const char *) (src))[4], ((__const char *) (src))[5], \ | |
559 | ((__const char *) (src))[6], '\0' } }) | |
fcab9698 UD |
560 | __STRING_INLINE char *__stpcpy_small (char *, __STRING2_COPY_ARR2, |
561 | __STRING2_COPY_ARR3, | |
562 | __STRING2_COPY_ARR4, | |
563 | __STRING2_COPY_ARR5, | |
564 | __STRING2_COPY_ARR6, | |
565 | __STRING2_COPY_ARR7, | |
566 | __STRING2_COPY_ARR8, size_t); | |
36ab45e1 UD |
567 | __STRING_INLINE char * |
568 | __stpcpy_small (char *__dest, | |
569 | __STRING2_COPY_ARR2 __src2, __STRING2_COPY_ARR3 __src3, | |
570 | __STRING2_COPY_ARR4 __src4, __STRING2_COPY_ARR5 __src5, | |
571 | __STRING2_COPY_ARR6 __src6, __STRING2_COPY_ARR7 __src7, | |
572 | __STRING2_COPY_ARR8 __src8, size_t __srclen) | |
573 | { | |
574 | switch (__srclen) | |
575 | { | |
576 | case 1: | |
577 | *__dest = '\0'; | |
578 | break; | |
579 | case 2: | |
580 | __extension__ *((__STRING2_COPY_ARR2 *) __dest) = __src2; | |
581 | break; | |
582 | case 3: | |
583 | __extension__ *((__STRING2_COPY_ARR3 *) __dest) = __src3; | |
584 | break; | |
585 | case 4: | |
586 | __extension__ *((__STRING2_COPY_ARR4 *) __dest) = __src4; | |
587 | break; | |
588 | case 5: | |
589 | __extension__ *((__STRING2_COPY_ARR5 *) __dest) = __src5; | |
590 | break; | |
591 | case 6: | |
592 | __extension__ *((__STRING2_COPY_ARR6 *) __dest) = __src6; | |
593 | break; | |
594 | case 7: | |
595 | __extension__ *((__STRING2_COPY_ARR7 *) __dest) = __src7; | |
596 | break; | |
597 | case 8: | |
598 | __extension__ *((__STRING2_COPY_ARR8 *) __dest) = __src8; | |
599 | break; | |
600 | } | |
601 | return __dest + __srclen - 1; | |
602 | } | |
61eb22d3 | 603 | # endif |
9a0a462c UD |
604 | # endif |
605 | #endif | |
606 | ||
607 | ||
608 | /* Copy no more than N characters of SRC to DEST. */ | |
609 | #ifndef _HAVE_STRING_ARCH_strncpy | |
610 | # if defined _HAVE_STRING_ARCH_memset && defined _HAVE_STRING_ARCH_mempcpy | |
611 | # define strncpy(dest, src, n) \ | |
650425ce UD |
612 | (__extension__ ({ char *__dest = (dest); \ |
613 | __builtin_constant_p (src) && __builtin_constant_p (n) \ | |
614 | ? (strlen (src) + 1 >= ((size_t) (n)) \ | |
615 | ? (char *) memcpy (__dest, src, n) \ | |
616 | : (memset (__mempcpy (__dest, src, strlen (src)), \ | |
617 | '\0', n - strlen (src)), \ | |
618 | __dest)) \ | |
619 | : strncpy (__dest, src, n); })) | |
9a0a462c UD |
620 | # else |
621 | # define strncpy(dest, src, n) \ | |
622 | (__extension__ (__builtin_constant_p (src) && __builtin_constant_p (n) \ | |
623 | ? (strlen (src) + 1 >= ((size_t) (n)) \ | |
624 | ? (char *) memcpy (dest, src, n) \ | |
625 | : strncpy (dest, src, n)) \ | |
626 | : strncpy (dest, src, n))) | |
627 | # endif | |
628 | #endif | |
629 | ||
630 | ||
631 | /* Append no more than N characters from SRC onto DEST. */ | |
632 | #ifndef _HAVE_STRING_ARCH_strncat | |
633 | # ifdef _HAVE_STRING_ARCH_strchr | |
634 | # define strncat(dest, src, n) \ | |
650425ce UD |
635 | (__extension__ ({ char *__dest = (dest); \ |
636 | __builtin_constant_p (src) && __builtin_constant_p (n) \ | |
637 | ? (strlen (src) < ((size_t) (n)) \ | |
638 | ? strcat (__dest, src) \ | |
639 | : (memcpy (strchr (__dest, '\0'), src, n), __dest)) \ | |
640 | : strncat (dest, src, n); })) | |
9a0a462c UD |
641 | # else |
642 | # define strncat(dest, src, n) \ | |
643 | (__extension__ (__builtin_constant_p (src) && __builtin_constant_p (n) \ | |
644 | ? (strlen (src) < ((size_t) (n)) \ | |
645 | ? strcat (dest, src) \ | |
646 | : strncat (dest, src, n)) \ | |
647 | : strncat (dest, src, n))) | |
648 | # endif | |
649 | #endif | |
650 | ||
651 | ||
650425ce UD |
652 | /* Compare characters of S1 and S2. */ |
653 | #ifndef _HAVE_STRING_ARCH_strcmp | |
654 | # define strcmp(s1, s2) \ | |
36ab45e1 UD |
655 | __extension__ \ |
656 | ({ size_t __s1_len, __s2_len; \ | |
fcab9698 | 657 | (__builtin_constant_p (s1) && __builtin_constant_p (s2) \ |
36ab45e1 UD |
658 | && (__s1_len = strlen (s1), __s2_len = strlen (s2), \ |
659 | (!__string2_1bptr_p (s1) || __s1_len >= 4) \ | |
660 | && (!__string2_1bptr_p (s2) || __s2_len >= 4)) \ | |
661 | ? memcmp ((__const char *) (s1), (__const char *) (s2), \ | |
662 | (__s1_len < __s2_len ? __s1_len : __s2_len) + 1) \ | |
fcab9698 | 663 | : (__builtin_constant_p (s1) && __string2_1bptr_p (s1) \ |
36ab45e1 | 664 | && (__s1_len = strlen (s1), __s1_len < 4) \ |
fcab9698 | 665 | ? (__builtin_constant_p (s2) && __string2_1bptr_p (s2) \ |
36ab45e1 UD |
666 | ? __strcmp_cc (s1, s2, __s1_len) \ |
667 | : __strcmp_cg (s1, s2, __s1_len)) \ | |
fcab9698 | 668 | : (__builtin_constant_p (s2) && __string2_1bptr_p (s2) \ |
36ab45e1 | 669 | && (__s2_len = strlen (s2), __s2_len < 4) \ |
fcab9698 | 670 | ? (__builtin_constant_p (s1) && __string2_1bptr_p (s1) \ |
36ab45e1 UD |
671 | ? __strcmp_cc (s1, s2, __s2_len) \ |
672 | : __strcmp_gc (s1, s2, __s2_len)) \ | |
673 | : strcmp (s1, s2)))); }) | |
650425ce | 674 | |
a5a0310d | 675 | # define __strcmp_cc(s1, s2, l) \ |
af6f3906 | 676 | (__extension__ ({ register int __result = \ |
fab6d621 UD |
677 | (((__const unsigned char *) (__const char *) (s1))[0] \ |
678 | - ((__const unsigned char *) (__const char *)(s2))[0]);\ | |
a5a0310d UD |
679 | if (l > 0 && __result == 0) \ |
680 | { \ | |
fab6d621 UD |
681 | __result = (((__const unsigned char *) \ |
682 | (__const char *) (s1))[1] \ | |
683 | - ((__const unsigned char *) \ | |
684 | (__const char *) (s2))[1]); \ | |
a5a0310d UD |
685 | if (l > 1 && __result == 0) \ |
686 | { \ | |
af6f3906 | 687 | __result = \ |
fab6d621 UD |
688 | (((__const unsigned char *) \ |
689 | (__const char *) (s1))[2] \ | |
690 | - ((__const unsigned char *) \ | |
691 | (__const char *) (s2))[2]); \ | |
a5a0310d | 692 | if (l > 2 && __result == 0) \ |
af6f3906 | 693 | __result = \ |
fab6d621 UD |
694 | (((__const unsigned char *) \ |
695 | (__const char *) (s1))[3] \ | |
696 | - ((__const unsigned char *) \ | |
697 | (__const char *) (s2))[3]); \ | |
a5a0310d UD |
698 | } \ |
699 | } \ | |
700 | __result; })) | |
701 | ||
650425ce | 702 | # define __strcmp_cg(s1, s2, l1) \ |
af6f3906 | 703 | (__extension__ ({ __const unsigned char *__s2 = \ |
fab6d621 | 704 | (__const unsigned char *) (__const char *) (s2); \ |
af6f3906 | 705 | register int __result = \ |
fab6d621 UD |
706 | (((__const unsigned char *) (__const char *) (s1))[0] \ |
707 | - __s2[0]); \ | |
650425ce UD |
708 | if (l1 > 0 && __result == 0) \ |
709 | { \ | |
fab6d621 UD |
710 | __result = (((__const unsigned char *) \ |
711 | (__const char *) (s1))[1] - __s2[1]); \ | |
650425ce UD |
712 | if (l1 > 1 && __result == 0) \ |
713 | { \ | |
fab6d621 UD |
714 | __result = (((__const unsigned char *) \ |
715 | (__const char *) (s1))[2] - __s2[2]);\ | |
650425ce | 716 | if (l1 > 2 && __result == 0) \ |
fab6d621 UD |
717 | __result = (((__const unsigned char *) \ |
718 | (__const char *) (s1))[3] \ | |
af6f3906 | 719 | - __s2[3]); \ |
650425ce UD |
720 | } \ |
721 | } \ | |
722 | __result; })) | |
723 | ||
724 | # define __strcmp_gc(s1, s2, l2) \ | |
af6f3906 | 725 | (__extension__ ({ __const unsigned char *__s1 = \ |
fab6d621 | 726 | (__const unsigned char *) (__const char *) (s1); \ |
af6f3906 | 727 | register int __result = \ |
fab6d621 UD |
728 | __s1[0] - ((__const unsigned char *) \ |
729 | (__const char *) (s2))[0]; \ | |
650425ce UD |
730 | if (l2 > 0 && __result == 0) \ |
731 | { \ | |
af6f3906 | 732 | __result = (__s1[1] \ |
fab6d621 UD |
733 | - ((__const unsigned char *) \ |
734 | (__const char *) (s2))[1]); \ | |
650425ce UD |
735 | if (l2 > 1 && __result == 0) \ |
736 | { \ | |
af6f3906 | 737 | __result = \ |
fab6d621 UD |
738 | (__s1[2] - ((__const unsigned char *) \ |
739 | (__const char *) (s2))[2]); \ | |
650425ce | 740 | if (l2 > 2 && __result == 0) \ |
af6f3906 UD |
741 | __result = \ |
742 | (__s1[3] \ | |
fab6d621 UD |
743 | - ((__const unsigned char *) \ |
744 | (__const char *) (s2))[3]); \ | |
650425ce UD |
745 | } \ |
746 | } \ | |
747 | __result; })) | |
748 | #endif | |
749 | ||
750 | ||
9a0a462c UD |
751 | /* Compare N characters of S1 and S2. */ |
752 | #ifndef _HAVE_STRING_ARCH_strncmp | |
d30da2a8 UD |
753 | # define strncmp(s1, s2, n) \ |
754 | (__extension__ (__builtin_constant_p (n) \ | |
755 | && ((__builtin_constant_p (s1) \ | |
756 | && strlen (s1) < ((size_t) (n))) \ | |
757 | || (__builtin_constant_p (s2) \ | |
758 | && strlen (s2) < ((size_t) (n)))) \ | |
759 | ? strcmp (s1, s2) : strncmp (s1, s2, n))) | |
9a0a462c UD |
760 | #endif |
761 | ||
762 | ||
763 | /* Return the length of the initial segment of S which | |
764 | consists entirely of characters not in REJECT. */ | |
765 | #ifndef _HAVE_STRING_ARCH_strcspn | |
766 | # define strcspn(s, reject) \ | |
36ab45e1 UD |
767 | __extension__ \ |
768 | ({ char __r0, __r1, __r2; \ | |
769 | (__builtin_constant_p (reject) && __string2_1bptr_p (reject) \ | |
770 | ? ((__r0 = ((__const char *) (reject))[0], __r0 == '\0') \ | |
771 | ? strlen (s) \ | |
772 | : ((__r1 = ((__const char *) (reject))[1], __r1 == '\0') \ | |
773 | ? __strcspn_c1 (s, __r0) \ | |
774 | : ((__r2 = ((__const char *) (reject))[2], __r2 == '\0') \ | |
775 | ? __strcspn_c2 (s, __r0, __r1) \ | |
776 | : (((__const char *) (reject))[3] == '\0' \ | |
777 | ? __strcspn_c3 (s, __r0, __r1, __r2) \ | |
778 | : strcspn (s, reject))))) \ | |
779 | : strcspn (s, reject)); }) | |
9a0a462c | 780 | |
61eb22d3 | 781 | __STRING_INLINE size_t __strcspn_c1 (__const char *__s, char __reject); |
9a0a462c UD |
782 | __STRING_INLINE size_t |
783 | __strcspn_c1 (__const char *__s, char __reject) | |
784 | { | |
785 | register size_t __result = 0; | |
786 | while (__s[__result] != '\0' && __s[__result] != __reject) | |
787 | ++__result; | |
788 | return __result; | |
789 | } | |
14c44e2e UD |
790 | |
791 | __STRING_INLINE size_t __strcspn_c2 (__const char *__s, char __reject1, | |
792 | char __reject2); | |
793 | __STRING_INLINE size_t | |
794 | __strcspn_c2 (__const char *__s, char __reject1, char __reject2) | |
795 | { | |
796 | register size_t __result = 0; | |
797 | while (__s[__result] != '\0' && __s[__result] != __reject1 | |
798 | && __s[__result] != __reject2) | |
799 | ++__result; | |
800 | return __result; | |
801 | } | |
802 | ||
803 | __STRING_INLINE size_t __strcspn_c3 (__const char *__s, char __reject1, | |
804 | char __reject2, char __reject3); | |
805 | __STRING_INLINE size_t | |
806 | __strcspn_c3 (__const char *__s, char __reject1, char __reject2, | |
807 | char __reject3) | |
808 | { | |
809 | register size_t __result = 0; | |
810 | while (__s[__result] != '\0' && __s[__result] != __reject1 | |
811 | && __s[__result] != __reject2 && __s[__result] != __reject3) | |
812 | ++__result; | |
813 | return __result; | |
814 | } | |
9a0a462c UD |
815 | #endif |
816 | ||
817 | ||
818 | /* Return the length of the initial segment of S which | |
819 | consists entirely of characters in ACCEPT. */ | |
820 | #ifndef _HAVE_STRING_ARCH_strspn | |
821 | # define strspn(s, accept) \ | |
36ab45e1 UD |
822 | __extension__ \ |
823 | ({ char __a0, __a1, __a2; \ | |
824 | (__builtin_constant_p (accept) && __string2_1bptr_p (accept) \ | |
825 | ? ((__a0 = ((__const char *) (accept))[0], __a0 == '\0') \ | |
826 | ? 0 \ | |
827 | : ((__a1 = ((__const char *) (accept))[1], __a1 == '\0') \ | |
828 | ? __strspn_c1 (s, __a0) \ | |
829 | : ((__a2 = ((__const char *) (accept))[2], __a2 == '\0') \ | |
830 | ? __strspn_c2 (s, __a0, __a1) \ | |
831 | : (((__const char *) (accept))[3] == '\0' \ | |
832 | ? __strspn_c3 (s, __a0, __a1, __a2) \ | |
833 | : strspn (s, accept))))) \ | |
834 | : strspn (s, accept)); }) | |
9a0a462c | 835 | |
61eb22d3 | 836 | __STRING_INLINE size_t __strspn_c1 (__const char *__s, char __accept); |
9a0a462c UD |
837 | __STRING_INLINE size_t |
838 | __strspn_c1 (__const char *__s, char __accept) | |
839 | { | |
840 | register size_t __result = 0; | |
841 | /* Please note that __accept never can be '\0'. */ | |
842 | while (__s[__result] == __accept) | |
843 | ++__result; | |
844 | return __result; | |
845 | } | |
14c44e2e UD |
846 | |
847 | __STRING_INLINE size_t __strspn_c2 (__const char *__s, char __accept1, | |
848 | char __accept2); | |
849 | __STRING_INLINE size_t | |
850 | __strspn_c2 (__const char *__s, char __accept1, char __accept2) | |
851 | { | |
852 | register size_t __result = 0; | |
853 | /* Please note that __accept1 and __accept2 never can be '\0'. */ | |
854 | while (__s[__result] == __accept1 || __s[__result] == __accept2) | |
855 | ++__result; | |
856 | return __result; | |
857 | } | |
858 | ||
859 | __STRING_INLINE size_t __strspn_c3 (__const char *__s, char __accept1, | |
860 | char __accept2, char __accept3); | |
861 | __STRING_INLINE size_t | |
862 | __strspn_c3 (__const char *__s, char __accept1, char __accept2, char __accept3) | |
863 | { | |
864 | register size_t __result = 0; | |
865 | /* Please note that __accept1 to __accept3 never can be '\0'. */ | |
866 | while (__s[__result] == __accept1 || __s[__result] == __accept2 | |
867 | || __s[__result] == __accept3) | |
868 | ++__result; | |
869 | return __result; | |
870 | } | |
9a0a462c UD |
871 | #endif |
872 | ||
873 | ||
874 | /* Find the first occurrence in S of any character in ACCEPT. */ | |
875 | #ifndef _HAVE_STRING_ARCH_strpbrk | |
876 | # define strpbrk(s, accept) \ | |
36ab45e1 UD |
877 | __extension__ \ |
878 | ({ char __a0, __a1, __a2; \ | |
879 | (__builtin_constant_p (accept) && __string2_1bptr_p (accept) \ | |
880 | ? ((__a0 = ((__const char *) (accept))[0], __a0 == '\0') \ | |
881 | ? NULL \ | |
882 | : ((__a1 = ((__const char *) (accept))[1], __a1 == '\0') \ | |
883 | ? strchr (s, __a0) \ | |
884 | : ((__a2 = ((__const char *) (accept))[2], __a2 == '\0') \ | |
885 | ? __strpbrk_c2 (s, __a0, __a1) \ | |
886 | : (((__const char *) (accept))[3] == '\0' \ | |
887 | ? __strpbrk_c3 (s, __a0, __a1, __a2) \ | |
888 | : strpbrk (s, accept))))) \ | |
889 | : strpbrk (s, accept)); }) | |
14c44e2e UD |
890 | |
891 | __STRING_INLINE char *__strpbrk_c2 (__const char *__s, char __accept1, | |
892 | char __accept2); | |
893 | __STRING_INLINE char * | |
894 | __strpbrk_c2 (__const char *__s, char __accept1, char __accept2) | |
895 | { | |
896 | /* Please note that __accept1 and __accept2 never can be '\0'. */ | |
897 | while (*__s != '\0' && *__s != __accept1 && *__s != __accept2) | |
898 | ++__s; | |
d2537a47 | 899 | return *__s == '\0' ? NULL : (char *) (size_t) __s; |
14c44e2e UD |
900 | } |
901 | ||
902 | __STRING_INLINE char *__strpbrk_c3 (__const char *__s, char __accept1, | |
903 | char __accept2, char __accept3); | |
904 | __STRING_INLINE char * | |
905 | __strpbrk_c3 (__const char *__s, char __accept1, char __accept2, | |
906 | char __accept3) | |
907 | { | |
908 | /* Please note that __accept1 to __accept3 never can be '\0'. */ | |
909 | while (*__s != '\0' && *__s != __accept1 && *__s != __accept2 | |
910 | && *__s != __accept3) | |
911 | ++__s; | |
d2537a47 | 912 | return *__s == '\0' ? NULL : (char *) (size_t) __s; |
14c44e2e | 913 | } |
9a0a462c UD |
914 | #endif |
915 | ||
916 | ||
917 | /* Find the first occurrence of NEEDLE in HAYSTACK. */ | |
918 | #ifndef _HAVE_STRING_ARCH_strstr | |
919 | # define strstr(haystack, needle) \ | |
dfd2257a | 920 | (__extension__ (__builtin_constant_p (needle) && __string2_1bptr_p (needle) \ |
fab6d621 | 921 | ? (((__const char *) (needle))[0] == '\0' \ |
d2537a47 | 922 | ? (char *) (size_t) (haystack) \ |
fab6d621 | 923 | : (((__const char *) (needle))[1] == '\0' \ |
af6f3906 | 924 | ? strchr (haystack, \ |
fab6d621 | 925 | ((__const char *) (needle))[0]) \ |
9a0a462c UD |
926 | : strstr (haystack, needle))) \ |
927 | : strstr (haystack, needle))) | |
928 | #endif | |
929 | ||
930 | ||
931 | #ifdef __USE_GNU | |
932 | # ifndef _HAVE_STRING_ARCH_strnlen | |
61eb22d3 UD |
933 | __STRING_INLINE size_t strnlen (__const char *__string, size_t __maxlen); |
934 | __STRING_INLINE size_t | |
9a0a462c UD |
935 | strnlen (__const char *__string, size_t __maxlen) |
936 | { | |
937 | __const char *__end = (__const char *) memchr (__string, '\0', __maxlen); | |
938 | return __end ? __end - __string : __maxlen; | |
939 | } | |
940 | # endif | |
941 | #endif | |
942 | ||
943 | ||
31161268 UD |
944 | #ifndef _HAVE_STRING_ARCH_strtok_r |
945 | # define __strtok_r(s, sep, nextp) \ | |
6973fc01 | 946 | (__extension__ (__builtin_constant_p (sep) && __string2_1bptr_p (sep) \ |
fab6d621 UD |
947 | ? (((__const char *) (sep))[0] != '\0' \ |
948 | && ((__const char *) (sep))[1] == '\0' \ | |
14c44e2e | 949 | ? __strtok_r_1c (s, ((__const char *) (sep))[0], nextp) \ |
7551a1e5 UD |
950 | : __strtok_r (s, sep, nextp)) \ |
951 | : __strtok_r (s, sep, nextp))) | |
6973fc01 UD |
952 | |
953 | __STRING_INLINE char *__strtok_r_1c (char *__s, char __sep, char **__nextp); | |
954 | __STRING_INLINE char * | |
955 | __strtok_r_1c (char *__s, char __sep, char **__nextp) | |
956 | { | |
957 | char *__result; | |
958 | if (__s == NULL) | |
959 | __s = *__nextp; | |
960 | while (*__s == __sep) | |
961 | ++__s; | |
962 | if (*__s == '\0') | |
963 | __result = NULL; | |
964 | else | |
965 | { | |
966 | __result = __s; | |
967 | while (*__s != '\0' && *__s != __sep) | |
968 | ++__s; | |
969 | if (*__s == '\0') | |
970 | *__nextp = __s; | |
971 | else | |
972 | { | |
973 | *__s = '\0'; | |
974 | *__nextp = __s + 1; | |
975 | } | |
976 | } | |
977 | return __result; | |
978 | } | |
31161268 | 979 | # if defined __USE_POSIX || defined __USE_MISC |
7551a1e5 | 980 | # define strtok_r(s, sep, nextp) __strtok_r ((s), (sep), (nextp)) |
6973fc01 UD |
981 | # endif |
982 | #endif | |
983 | ||
984 | ||
31161268 | 985 | #ifndef _HAVE_STRING_ARCH_strsep |
61eb22d3 | 986 | |
31161268 | 987 | # define __strsep(s, reject) \ |
36ab45e1 UD |
988 | __extension__ \ |
989 | ({ char __r0, __r1, __r2; \ | |
990 | (__builtin_constant_p (reject) && __string2_1bptr_p (reject) \ | |
991 | && (__r0 = ((__const char *) (reject))[0], __r0 != '\0') \ | |
992 | ? ((__r1 = ((__const char *) (reject))[1], __r1 == '\0') \ | |
993 | ? __strsep_1c (s, __r0) \ | |
994 | : ((__r2 = ((__const char *) (reject))[2], __r2 == '\0') \ | |
995 | ? __strsep_2c (s, __r0, __r1) \ | |
996 | : (((__const char *) (reject))[3] == '\0' \ | |
997 | ? __strsep_3c (s, __r0, __r1, __r2) \ | |
998 | : __strsep_g (s, reject)))) \ | |
999 | : __strsep_g (s, reject)); }) | |
61eb22d3 UD |
1000 | |
1001 | __STRING_INLINE char *__strsep_1c (char **__s, char __reject); | |
1002 | __STRING_INLINE char * | |
1003 | __strsep_1c (char **__s, char __reject) | |
1004 | { | |
650425ce | 1005 | register char *__retval = *__s; |
14c44e2e UD |
1006 | if (__retval == NULL) |
1007 | return *__s = NULL; | |
1008 | if (*__retval == __reject) | |
61eb22d3 | 1009 | *(*__s)++ = '\0'; |
14c44e2e UD |
1010 | else |
1011 | if ((*__s = strchr (__retval, __reject)) != NULL) | |
1012 | *(*__s)++ = '\0'; | |
1013 | else | |
1014 | *__s = NULL; | |
1015 | return __retval; | |
1016 | } | |
1017 | ||
1018 | __STRING_INLINE char *__strsep_2c (char **__s, char __reject1, char __reject2); | |
1019 | __STRING_INLINE char * | |
1020 | __strsep_2c (char **__s, char __reject1, char __reject2) | |
1021 | { | |
1022 | register char *__retval = *__s; | |
1023 | if (__retval == NULL) | |
1024 | return *__s = NULL; | |
1025 | if (*__retval == __reject1 || *__retval == __reject2) | |
1026 | *(*__s)++ = '\0'; | |
1027 | else | |
1028 | { | |
1029 | register char *__cp = __retval; | |
1030 | while (*__cp != '\0' && *__cp != __reject1 && *__cp != __reject2) | |
1031 | ++__cp; | |
1032 | if (*__cp != '\0') | |
1033 | { | |
1034 | *__s = __cp; | |
1035 | *(*__s)++ = '\0'; | |
1036 | } | |
1037 | else | |
1038 | *__s = NULL; | |
1039 | } | |
1040 | return __retval; | |
1041 | } | |
1042 | ||
1043 | __STRING_INLINE char *__strsep_3c (char **__s, char __reject1, char __reject2, | |
1044 | char __reject3); | |
1045 | __STRING_INLINE char * | |
1046 | __strsep_3c (char **__s, char __reject1, char __reject2, char __reject3) | |
1047 | { | |
1048 | register char *__retval = *__s; | |
1049 | if (__retval == NULL) | |
1050 | return *__s = NULL; | |
1051 | if (*__retval == __reject1 || *__retval == __reject2 | |
1052 | || *__retval == __reject3) | |
1053 | *(*__s)++ = '\0'; | |
1054 | else | |
1055 | { | |
1056 | register char *__cp = __retval; | |
1057 | while (*__cp != '\0' && *__cp != __reject1 && *__cp != __reject2 | |
1058 | && *__cp != __reject3) | |
1059 | ++__cp; | |
1060 | if (*__cp != '\0') | |
1061 | { | |
1062 | *__s = __cp; | |
1063 | *(*__s)++ = '\0'; | |
1064 | } | |
1065 | else | |
1066 | *__s = NULL; | |
1067 | } | |
650425ce | 1068 | return __retval; |
61eb22d3 UD |
1069 | } |
1070 | ||
1071 | __STRING_INLINE char *__strsep_g (char **__s, __const char *__reject); | |
1072 | __STRING_INLINE char * | |
1073 | __strsep_g (char **__s, __const char *__reject) | |
1074 | { | |
650425ce | 1075 | register char *__retval = *__s; |
61eb22d3 UD |
1076 | if (__retval == NULL || *__retval == '\0') |
1077 | return NULL; | |
76fbcfdd | 1078 | if ((*__s = strpbrk (__retval, __reject)) != NULL) |
61eb22d3 | 1079 | *(*__s)++ = '\0'; |
650425ce | 1080 | return __retval; |
61eb22d3 | 1081 | } |
31161268 | 1082 | # ifdef __USE_BSD |
7551a1e5 | 1083 | # define strsep(s, reject) __strsep ((s), (reject)) |
31161268 UD |
1084 | # endif |
1085 | #endif | |
1086 | ||
7ef90c15 | 1087 | /* We need the memory allocation functions for inline strdup(). |
d2537a47 | 1088 | Referring to stdlib.h (even minimally) is not allowed |
4a582094 | 1089 | in any of the tight standards compliant modes. */ |
6e2cc2c1 | 1090 | #ifdef __USE_MISC |
31161268 | 1091 | |
4a582094 UD |
1092 | # if !defined _HAVE_STRING_ARCH_strdup || !defined _HAVE_STRING_ARCH_strndup |
1093 | # define __need_malloc_and_calloc | |
1094 | # include <stdlib.h> | |
1095 | # endif | |
7ef90c15 | 1096 | |
4a582094 | 1097 | # ifndef _HAVE_STRING_ARCH_strdup |
31161268 | 1098 | |
4a582094 | 1099 | # define __strdup(s) \ |
7551a1e5 | 1100 | (__extension__ (__builtin_constant_p (s) && __string2_1bptr_p (s) \ |
fab6d621 | 1101 | ? (((__const char *) (s))[0] == '\0' \ |
7551a1e5 UD |
1102 | ? (char *) calloc (1, 1) \ |
1103 | : ({ size_t __len = strlen (s) + 1; \ | |
1104 | char *__retval = (char *) malloc (__len); \ | |
1105 | if (__retval != NULL) \ | |
1106 | __retval = (char *) memcpy (__retval, s, __len); \ | |
1107 | __retval; })) \ | |
1108 | : __strdup (s))) | |
31161268 | 1109 | |
4a582094 UD |
1110 | # if defined __USE_SVID || defined __USE_BSD || defined __USE_XOPEN_EXTENDED |
1111 | # define strdup(s) __strdup (s) | |
1112 | # endif | |
61eb22d3 | 1113 | # endif |
61eb22d3 | 1114 | |
4a582094 | 1115 | # ifndef _HAVE_STRING_ARCH_strndup |
7551a1e5 | 1116 | |
4a582094 | 1117 | # define __strndup(s, n) \ |
7551a1e5 | 1118 | (__extension__ (__builtin_constant_p (s) && __string2_1bptr_p (s) \ |
fab6d621 | 1119 | ? (((__const char *) (s))[0] == '\0' \ |
7551a1e5 UD |
1120 | ? (char *) calloc (1, 1) \ |
1121 | : ({ size_t __len = strlen (s) + 1; \ | |
1122 | size_t __n = (n); \ | |
1123 | char *__retval; \ | |
1124 | if (__n < __len) \ | |
1125 | __len = __n; \ | |
1126 | __retval = (char *) malloc (__len); \ | |
1127 | if (__retval != NULL) \ | |
1128 | { \ | |
1129 | __retval[__len - 1] = '\0'; \ | |
1130 | __retval = (char *) memcpy (__retval, s, \ | |
1131 | __len - 1); \ | |
1132 | } \ | |
1133 | __retval; })) \ | |
1134 | : __strndup ((s), (n)))) | |
1135 | ||
4a582094 UD |
1136 | # ifdef __GNU_SOURCE |
1137 | # define strndup(s, n) __strndup ((s), (n)) | |
1138 | # endif | |
7551a1e5 | 1139 | # endif |
7551a1e5 | 1140 | |
4a582094 | 1141 | #endif /* Use misc. or use GNU. */ |
7551a1e5 | 1142 | |
9a0a462c UD |
1143 | #undef __STRING_INLINE |
1144 | ||
61eb22d3 | 1145 | #endif /* No string inlines. */ |