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