/* Note: copied from newlib */ #ifdef __cplusplus extern "C" { #endif #include #include #include /* * Copyright (C) 2004 CodeSourcery, LLC * * Permission to use, copy, modify, and distribute this file * for any purpose is hereby granted without fee, provided that * the above copyright notice and this notice appears in all * copies. * * This file is distributed WITHOUT ANY WARRANTY; without even the implied * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. */ /* Handle ELF .{pre_init,init,fini}_array sections. */ #include #ifndef HAVE_INITFINI_ARRAY #define HAVE_INITFINI_ARRAY #endif #undef HAVE_INIT_FINI #ifdef HAVE_INITFINI_ARRAY /* These magic symbols are provided by the linker. */ extern void (*__preinit_array_start []) (void) __attribute__((weak)); extern void (*__preinit_array_end []) (void) __attribute__((weak)); extern void (*__init_array_start []) (void) __attribute__((weak)); extern void (*__init_array_end []) (void) __attribute__((weak)); #ifdef HAVE_INIT_FINI extern void _init (void); #endif /* Iterate over all the init routines. */ void __libc_init_array (void) { size_t count; size_t i; count = __preinit_array_end - __preinit_array_start; for (i = 0; i < count; i++) __preinit_array_start[i] (); #ifdef HAVE_INIT_FINI _init (); #endif count = __init_array_end - __init_array_start; for (i = 0; i < count; i++) __init_array_start[i] (); } #endif #ifdef HAVE_INITFINI_ARRAY extern void (*__fini_array_start []) (void) __attribute__((weak)); extern void (*__fini_array_end []) (void) __attribute__((weak)); #ifdef HAVE_INIT_FINI extern void _fini (void); #endif /* Run all the cleanup routines. */ void __libc_fini_array (void) { size_t count; size_t i; count = __fini_array_end - __fini_array_start; for (i = count; i > 0; i--) __fini_array_start[i-1] (); #ifdef HAVE_INIT_FINI _fini (); #endif } #endif /* FUNCTION <>---move possibly overlapping memory INDEX memmove SYNOPSIS #include void *memmove(void *<[dst]>, const void *<[src]>, size_t <[length]>); DESCRIPTION This function moves <[length]> characters from the block of memory starting at <<*<[src]>>> to the memory starting at <<*<[dst]>>>. <> reproduces the characters correctly at <<*<[dst]>>> even if the two areas overlap. RETURNS The function returns <[dst]> as passed. PORTABILITY <> is ANSI C. <> requires no supporting OS subroutines. QUICKREF memmove ansi pure */ /* Nonzero if either X or Y is not aligned on a "long" boundary. */ #define UNALIGNED(X, Y) \ (((long)X & (sizeof (long) - 1)) | ((long)Y & (sizeof (long) - 1))) /* How many bytes are copied each iteration of the 4X unrolled loop. */ #define BIGBLOCKSIZE (sizeof (long) << 2) /* How many bytes are copied each iteration of the word copy loop. */ #define LITTLEBLOCKSIZE (sizeof (long)) /* Threshhold for punting to the byte copier. */ #undef TOO_SMALL #define TOO_SMALL(LEN) ((LEN) < BIGBLOCKSIZE) /*SUPPRESS 20*/ void * //__inhibit_loop_to_libcall memmove (void *dst_void, const void *src_void, size_t length) { #if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__) char *dst = dst_void; const char *src = src_void; if (src < dst && dst < src + length) { /* Have to copy backwards */ src += length; dst += length; while (length--) { *--dst = *--src; } } else { while (length--) { *dst++ = *src++; } } return dst_void; #else char *dst = dst_void; const char *src = src_void; long *aligned_dst; const long *aligned_src; if (src < dst && dst < src + length) { /* Destructive overlap...have to copy backwards */ src += length; dst += length; while (length--) { *--dst = *--src; } } else { /* Use optimizing algorithm for a non-destructive copy to closely match memcpy. If the size is small or either SRC or DST is unaligned, then punt into the byte copy loop. This should be rare. */ if (!TOO_SMALL(length) && !UNALIGNED (src, dst)) { aligned_dst = (long*)dst; aligned_src = (long*)src; /* Copy 4X long words at a time if possible. */ while (length >= BIGBLOCKSIZE) { *aligned_dst++ = *aligned_src++; *aligned_dst++ = *aligned_src++; *aligned_dst++ = *aligned_src++; *aligned_dst++ = *aligned_src++; length -= BIGBLOCKSIZE; } /* Copy one long word at a time if possible. */ while (length >= LITTLEBLOCKSIZE) { *aligned_dst++ = *aligned_src++; length -= LITTLEBLOCKSIZE; } /* Pick up any residual with a byte copier. */ dst = (char*)aligned_dst; src = (char*)aligned_src; } while (length--) { *dst++ = *src++; } } return dst_void; #endif /* not PREFER_SIZE_OVER_SPEED */ } /* FUNCTION <>---copy memory regions SYNOPSIS #include void* memcpy(void *restrict <[out]>, const void *restrict <[in]>, size_t <[n]>); DESCRIPTION This function copies <[n]> bytes from the memory region pointed to by <[in]> to the memory region pointed to by <[out]>. If the regions overlap, the behavior is undefined. RETURNS <> returns a pointer to the first byte of the <[out]> region. PORTABILITY <> is ANSI C. <> requires no supporting OS subroutines. QUICKREF memcpy ansi pure */ void * memcpy (void * dst0, const void * __restrict src0, size_t len0) { #if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__) char *dst = (char *) dst0; char *src = (char *) src0; void *save = dst0; while (len0--) { *dst++ = *src++; } return save; #else char *dst = dst0; const char *src = src0; long *aligned_dst; const long *aligned_src; /* If the size is small, or either SRC or DST is unaligned, then punt into the byte copy loop. This should be rare. */ if (!TOO_SMALL(len0) && !UNALIGNED (src, dst)) { aligned_dst = (long*)dst; aligned_src = (long*)src; /* Copy 4X long words at a time if possible. */ while (len0 >= BIGBLOCKSIZE) { *aligned_dst++ = *aligned_src++; *aligned_dst++ = *aligned_src++; *aligned_dst++ = *aligned_src++; *aligned_dst++ = *aligned_src++; len0 -= BIGBLOCKSIZE; } /* Copy one long word at a time if possible. */ while (len0 >= LITTLEBLOCKSIZE) { *aligned_dst++ = *aligned_src++; len0 -= LITTLEBLOCKSIZE; } /* Pick up any residual with a byte copier. */ dst = (char*)aligned_dst; src = (char*)aligned_src; } while (len0--) *dst++ = *src++; return dst0; #endif /* not PREFER_SIZE_OVER_SPEED */ } /* FUNCTION <>---set an area of memory INDEX memset SYNOPSIS #include void *memset(void *<[dst]>, int <[c]>, size_t <[length]>); DESCRIPTION This function converts the argument <[c]> into an unsigned char and fills the first <[length]> characters of the array pointed to by <[dst]> to the value. RETURNS <> returns the value of <[dst]>. PORTABILITY <> is ANSI C. <> requires no supporting OS subroutines. QUICKREF memset ansi pure */ #include #undef LBLOCKSIZE #undef UNALIGNED #undef TOO_SMALL #define LBLOCKSIZE (sizeof(long)) #define UNALIGNED(X) ((long)X & (LBLOCKSIZE - 1)) #define TOO_SMALL(LEN) ((LEN) < LBLOCKSIZE) void * memset (void *m, int c, size_t n) { char *s = (char *) m; #if !defined(PREFER_SIZE_OVER_SPEED) && !defined(__OPTIMIZE_SIZE__) unsigned int i; unsigned long buffer; unsigned long *aligned_addr; unsigned int d = c & 0xff; /* To avoid sign extension, copy C to an unsigned variable. */ while (UNALIGNED (s)) { if (n--) *s++ = (char) c; else return m; } if (!TOO_SMALL (n)) { /* If we get this far, we know that n is large and s is word-aligned. */ aligned_addr = (unsigned long *) s; /* Store D into each char sized location in BUFFER so that we can set large blocks quickly. */ buffer = (d << 8) | d; buffer |= (buffer << 16); for (i = 32; i < LBLOCKSIZE * 8; i <<= 1) buffer = (buffer << i) | buffer; /* Unroll the loop. */ while (n >= LBLOCKSIZE*4) { *aligned_addr++ = buffer; *aligned_addr++ = buffer; *aligned_addr++ = buffer; *aligned_addr++ = buffer; n -= 4*LBLOCKSIZE; } while (n >= LBLOCKSIZE) { *aligned_addr++ = buffer; n -= LBLOCKSIZE; } /* Pick up the remainder with a bytewise loop. */ s = (char*)aligned_addr; } #endif /* not PREFER_SIZE_OVER_SPEED */ while (n--) *s++ = (char) c; return m; } /* FUNCTION <>---find character in memory INDEX memchr SYNOPSIS #include void *memchr(const void *<[src]>, int <[c]>, size_t <[length]>); DESCRIPTION This function searches memory starting at <<*<[src]>>> for the character <[c]>. The search only ends with the first occurrence of <[c]>, or after <[length]> characters; in particular, <> does not terminate the search. RETURNS If the character <[c]> is found within <[length]> characters of <<*<[src]>>>, a pointer to the character is returned. If <[c]> is not found, then <> is returned. PORTABILITY <> is ANSI C. <> requires no supporting OS subroutines. QUICKREF memchr ansi pure */ #undef LBLOCKSIZE #undef UNALIGNED #undef TOO_SMALL /* Nonzero if either X or Y is not aligned on a "long" boundary. */ #define UNALIGNED(X) ((long)X & (sizeof (long) - 1)) /* How many bytes are loaded each iteration of the word copy loop. */ #define LBLOCKSIZE (sizeof (long)) /* Threshhold for punting to the bytewise iterator. */ #define TOO_SMALL(LEN) ((LEN) < LBLOCKSIZE) #if LONG_MAX == 2147483647L #define DETECTNULL(X) (((X) - 0x01010101) & ~(X) & 0x80808080) #else #if LONG_MAX == 9223372036854775807L /* Nonzero if X (a long int) contains a NULL byte. */ #define DETECTNULL(X) (((X) - 0x0101010101010101) & ~(X) & 0x8080808080808080) #else #error long int is not a 32bit or 64bit type. #endif #endif #ifndef DETECTNULL #error long int is not a 32bit or 64bit byte #endif /* DETECTCHAR returns nonzero if (long)X contains the byte used to fill (long)MASK. */ #define DETECTCHAR(X,MASK) (DETECTNULL(X ^ MASK)) void * memchr (const void *src_void, int c, size_t length) { const unsigned char *src = (const unsigned char *) src_void; unsigned char d = c; #if !defined(PREFER_SIZE_OVER_SPEED) && !defined(__OPTIMIZE_SIZE__) unsigned long *asrc; unsigned long mask; unsigned int i; while (UNALIGNED (src)) { if (!length--) return NULL; if (*src == d) return (void *) src; src++; } if (!TOO_SMALL (length)) { /* If we get this far, we know that length is large and src is word-aligned. */ /* The fast code reads the source one word at a time and only performs the bytewise search on word-sized segments if they contain the search character, which is detected by XORing the word-sized segment with a word-sized block of the search character and then detecting for the presence of NUL in the result. */ asrc = (unsigned long *) src; mask = d << 8 | d; mask = mask << 16 | mask; for (i = 32; i < LBLOCKSIZE * 8; i <<= 1) mask = (mask << i) | mask; while (length >= LBLOCKSIZE) { if (DETECTCHAR (*asrc, mask)) break; length -= LBLOCKSIZE; asrc++; } /* If there are fewer than LBLOCKSIZE characters left, then we resort to the bytewise loop. */ src = (unsigned char *) asrc; } #endif /* not PREFER_SIZE_OVER_SPEED */ while (length--) { if (*src == d) return (void *) src; src++; } return NULL; } /* FUNCTION <>---compare two memory areas INDEX memcmp SYNOPSIS #include int memcmp(const void *<[s1]>, const void *<[s2]>, size_t <[n]>); DESCRIPTION This function compares not more than <[n]> characters of the object pointed to by <[s1]> with the object pointed to by <[s2]>. RETURNS The function returns an integer greater than, equal to or less than zero according to whether the object pointed to by <[s1]> is greater than, equal to or less than the object pointed to by <[s2]>. PORTABILITY <> is ANSI C. <> requires no supporting OS subroutines. QUICKREF memcmp ansi pure */ #undef LBLOCKSIZE #undef UNALIGNED #undef TOO_SMALL /* Nonzero if either X or Y is not aligned on a "long" boundary. */ #define UNALIGNED(X, Y) \ (((long)X & (sizeof (long) - 1)) | ((long)Y & (sizeof (long) - 1))) /* How many bytes are copied each iteration of the word copy loop. */ #define LBLOCKSIZE (sizeof (long)) /* Threshhold for punting to the byte copier. */ #define TOO_SMALL(LEN) ((LEN) < LBLOCKSIZE) int memcmp (const void *m1, const void *m2, size_t n) { #if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__) unsigned char *s1 = (unsigned char *) m1; unsigned char *s2 = (unsigned char *) m2; while (n--) { if (*s1 != *s2) { return *s1 - *s2; } s1++; s2++; } return 0; #else unsigned char *s1 = (unsigned char *) m1; unsigned char *s2 = (unsigned char *) m2; unsigned long *a1; unsigned long *a2; /* If the size is too small, or either pointer is unaligned, then we punt to the byte compare loop. Hopefully this will not turn up in inner loops. */ if (!TOO_SMALL(n) && !UNALIGNED(s1,s2)) { /* Otherwise, load and compare the blocks of memory one word at a time. */ a1 = (unsigned long*) s1; a2 = (unsigned long*) s2; while (n >= LBLOCKSIZE) { if (*a1 != *a2) break; a1++; a2++; n -= LBLOCKSIZE; } /* check m mod LBLOCKSIZE remaining characters */ s1 = (unsigned char*)a1; s2 = (unsigned char*)a2; } while (n--) { if (*s1 != *s2) return *s1 - *s2; s1++; s2++; } return 0; #endif /* not PREFER_SIZE_OVER_SPEED */ } /* FUNCTION <>---search for character in string INDEX strchr SYNOPSIS #include char * strchr(const char *<[string]>, int <[c]>); DESCRIPTION This function finds the first occurence of <[c]> (converted to a char) in the string pointed to by <[string]> (including the terminating null character). RETURNS Returns a pointer to the located character, or a null pointer if <[c]> does not occur in <[string]>. PORTABILITY <> is ANSI C. <> requires no supporting OS subroutines. QUICKREF strchr ansi pure */ #undef LBLOCKSIZE #undef UNALIGNED #undef TOO_SMALL /* Nonzero if X is not aligned on a "long" boundary. */ #define UNALIGNED(X) ((long)X & (sizeof (long) - 1)) /* How many bytes are loaded each iteration of the word copy loop. */ #define LBLOCKSIZE (sizeof (long)) char * strchr (const char *s1, int i) { const unsigned char *s = (const unsigned char *)s1; unsigned char c = i; #if !defined(PREFER_SIZE_OVER_SPEED) && !defined(__OPTIMIZE_SIZE__) unsigned long mask,j; unsigned long *aligned_addr; /* Special case for finding 0. */ if (!c) { while (UNALIGNED (s)) { if (!*s) return (char *) s; s++; } /* Operate a word at a time. */ aligned_addr = (unsigned long *) s; while (!DETECTNULL (*aligned_addr)) aligned_addr++; /* Found the end of string. */ s = (const unsigned char *) aligned_addr; while (*s) s++; return (char *) s; } /* All other bytes. Align the pointer, then search a long at a time. */ while (UNALIGNED (s)) { if (!*s) return NULL; if (*s == c) return (char *) s; s++; } mask = c; for (j = 8; j < LBLOCKSIZE * 8; j <<= 1) mask = (mask << j) | mask; aligned_addr = (unsigned long *) s; while (!DETECTNULL (*aligned_addr) && !DETECTCHAR (*aligned_addr, mask)) aligned_addr++; /* The block of bytes currently pointed to by aligned_addr contains either a null or the target char, or both. We catch it using the bytewise search. */ s = (unsigned char *) aligned_addr; #endif /* not PREFER_SIZE_OVER_SPEED */ while (*s && *s != c) s++; if (*s == c) return (char *)s; return NULL; } /* FUNCTION <>---concatenate strings INDEX strcat ANSI_SYNOPSIS #include char *strcat(char *<[dst]>, const char *<[src]>); TRAD_SYNOPSIS #include char *strcat(<[dst]>, <[src]>) char *<[dst]>; char *<[src]>; DESCRIPTION <> appends a copy of the string pointed to by <[src]> (including the terminating null character) to the end of the string pointed to by <[dst]>. The initial character of <[src]> overwrites the null character at the end of <[dst]>. RETURNS This function returns the initial value of <[dst]> PORTABILITY <> is ANSI C. <> requires no supporting OS subroutines. QUICKREF strcat ansi pure */ /*SUPPRESS 560*/ /*SUPPRESS 530*/ char * strcat (char *s1, const char *s2) { #if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__) char *s = s1; while (*s1) s1++; while ((*s1++ = *s2++)) ; return s; #else char *s = s1; /* Skip over the data in s1 as quickly as possible. */ if (ALIGNED (s1)) { unsigned long *aligned_s1 = (unsigned long *)s1; while (!DETECTNULL (*aligned_s1)) aligned_s1++; s1 = (char *)aligned_s1; } while (*s1) s1++; /* s1 now points to the its trailing null character, we can just use strcpy to do the work for us now. ?!? We might want to just include strcpy here. Also, this will cause many more unaligned string copies because s1 is much less likely to be aligned. I don't know if its worth tweaking strcpy to handle this better. */ strcpy (s1, s2); return s; #endif /* not PREFER_SIZE_OVER_SPEED */ } /* FUNCTION <>---character string compare INDEX strcmp SYNOPSIS #include int strcmp(const char *<[a]>, const char *<[b]>); DESCRIPTION <> compares the string at <[a]> to the string at <[b]>. RETURNS If <<*<[a]>>> sorts lexicographically after <<*<[b]>>>, <> returns a number greater than zero. If the two strings match, <> returns zero. If <<*<[a]>>> sorts lexicographically before <<*<[b]>>>, <> returns a number less than zero. PORTABILITY <> is ANSI C. <> requires no supporting OS subroutines. QUICKREF strcmp ansi pure */ #undef LBLOCKSIZE #undef UNALIGNED #undef TOO_SMALL /* Nonzero if either X or Y is not aligned on a "long" boundary. */ #define UNALIGNED(X, Y) \ (((long)X & (sizeof (long) - 1)) | ((long)Y & (sizeof (long) - 1))) int strcmp (const char *s1, const char *s2) { #if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__) while (*s1 != '\0' && *s1 == *s2) { s1++; s2++; } return (*(unsigned char *) s1) - (*(unsigned char *) s2); #else unsigned long *a1; unsigned long *a2; /* If s1 or s2 are unaligned, then compare bytes. */ if (!UNALIGNED (s1, s2)) { /* If s1 and s2 are word-aligned, compare them a word at a time. */ a1 = (unsigned long*)s1; a2 = (unsigned long*)s2; while (*a1 == *a2) { /* To get here, *a1 == *a2, thus if we find a null in *a1, then the strings must be equal, so return zero. */ if (DETECTNULL (*a1)) return 0; a1++; a2++; } /* A difference was detected in last few bytes of s1, so search bytewise */ s1 = (char*)a1; s2 = (char*)a2; } while (*s1 != '\0' && *s1 == *s2) { s1++; s2++; } return (*(unsigned char *) s1) - (*(unsigned char *) s2); #endif /* not PREFER_SIZE_OVER_SPEED */ } /* FUNCTION <>---copy string INDEX strcpy SYNOPSIS #include char *strcpy(char *<[dst]>, const char *<[src]>); DESCRIPTION <> copies the string pointed to by <[src]> (including the terminating null character) to the array pointed to by <[dst]>. RETURNS This function returns the initial value of <[dst]>. PORTABILITY <> is ANSI C. <> requires no supporting OS subroutines. QUICKREF strcpy ansi pure */ /*SUPPRESS 560*/ /*SUPPRESS 530*/ #undef LBLOCKSIZE #undef UNALIGNED #undef TOO_SMALL /* Nonzero if either X or Y is not aligned on a "long" boundary. */ #define UNALIGNED(X, Y) \ (((long)X & (sizeof (long) - 1)) | ((long)Y & (sizeof (long) - 1))) char* strcpy (char *dst0, const char *src0) { #if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__) char *s = dst0; while ((*dst0++ = *src0++)) ; return s; #else char *dst = dst0; const char *src = src0; long *aligned_dst; const long *aligned_src; /* If SRC or DEST is unaligned, then copy bytes. */ if (!UNALIGNED (src, dst)) { aligned_dst = (long*)dst; aligned_src = (long*)src; /* SRC and DEST are both "long int" aligned, try to do "long int" sized copies. */ while (!DETECTNULL(*aligned_src)) { *aligned_dst++ = *aligned_src++; } dst = (char*)aligned_dst; src = (char*)aligned_src; } while ((*dst++ = *src++)) ; return dst0; #endif /* not PREFER_SIZE_OVER_SPEED */ } /* FUNCTION <>---character string length INDEX strlen SYNOPSIS #include size_t strlen(const char *<[str]>); DESCRIPTION The <> function works out the length of the string starting at <<*<[str]>>> by counting chararacters until it reaches a <> character. RETURNS <> returns the character count. PORTABILITY <> is ANSI C. <> requires no supporting OS subroutines. QUICKREF strlen ansi pure */ #undef LBLOCKSIZE #undef UNALIGNED #undef TOO_SMALL #define LBLOCKSIZE (sizeof (long)) #define UNALIGNED(X) ((long)X & (LBLOCKSIZE - 1)) size_t strlen (const char *str) { const char *start = str; #if !defined(PREFER_SIZE_OVER_SPEED) && !defined(__OPTIMIZE_SIZE__) unsigned long *aligned_addr; /* Align the pointer, so we can search a word at a time. */ while (UNALIGNED (str)) { if (!*str) return str - start; str++; } /* If the string is word-aligned, we can check for the presence of a null in each word-sized block. */ aligned_addr = (unsigned long *)str; while (!DETECTNULL (*aligned_addr)) aligned_addr++; /* Once a null is detected, we check each byte in that block for a precise position of the null. */ str = (char *) aligned_addr; #endif /* not PREFER_SIZE_OVER_SPEED */ while (*str) str++; return str - start; } /* FUNCTION <>---character string compare INDEX strncmp SYNOPSIS #include int strncmp(const char *<[a]>, const char * <[b]>, size_t <[length]>); DESCRIPTION <> compares up to <[length]> characters from the string at <[a]> to the string at <[b]>. RETURNS If <<*<[a]>>> sorts lexicographically after <<*<[b]>>>, <> returns a number greater than zero. If the two strings are equivalent, <> returns zero. If <<*<[a]>>> sorts lexicographically before <<*<[b]>>>, <> returns a number less than zero. PORTABILITY <> is ANSI C. <> requires no supporting OS subroutines. QUICKREF strncmp ansi pure */ #undef LBLOCKSIZE #undef UNALIGNED #undef TOO_SMALL #define UNALIGNED(X, Y) \ (((long)X & (sizeof (long) - 1)) | ((long)Y & (sizeof (long) - 1))) int strncmp (const char *s1, const char *s2, size_t n) { #if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__) if (n == 0) return 0; while (n-- != 0 && *s1 == *s2) { if (n == 0 || *s1 == '\0') break; s1++; s2++; } return (*(unsigned char *) s1) - (*(unsigned char *) s2); #else unsigned long *a1; unsigned long *a2; if (n == 0) return 0; /* If s1 or s2 are unaligned, then compare bytes. */ if (!UNALIGNED (s1, s2)) { /* If s1 and s2 are word-aligned, compare them a word at a time. */ a1 = (unsigned long*)s1; a2 = (unsigned long*)s2; while (n >= sizeof (long) && *a1 == *a2) { n -= sizeof (long); /* If we've run out of bytes or hit a null, return zero since we already know *a1 == *a2. */ if (n == 0 || DETECTNULL (*a1)) return 0; a1++; a2++; } /* A difference was detected in last few bytes of s1, so search bytewise */ s1 = (char*)a1; s2 = (char*)a2; } while (n-- > 0 && *s1 == *s2) { /* If we've run out of bytes or hit a null, return zero since we already know *s1 == *s2. */ if (n == 0 || *s1 == '\0') return 0; s1++; s2++; } return (*(unsigned char *) s1) - (*(unsigned char *) s2); #endif /* not PREFER_SIZE_OVER_SPEED */ } /* FUNCTION <>---counted copy string INDEX strncpy SYNOPSIS #include char *strncpy(char *restrict <[dst]>, const char *restrict <[src]>, size_t <[length]>); DESCRIPTION <> copies not more than <[length]> characters from the the string pointed to by <[src]> (including the terminating null character) to the array pointed to by <[dst]>. If the string pointed to by <[src]> is shorter than <[length]> characters, null characters are appended to the destination array until a total of <[length]> characters have been written. RETURNS This function returns the initial value of <[dst]>. PORTABILITY <> is ANSI C. <> requires no supporting OS subroutines. QUICKREF strncpy ansi pure */ /*SUPPRESS 560*/ /*SUPPRESS 530*/ #undef LBLOCKSIZE #undef UNALIGNED #undef TOO_SMALL #define UNALIGNED(X, Y) \ (((long)X & (sizeof (long) - 1)) | ((long)Y & (sizeof (long) - 1))) #define TOO_SMALL(LEN) ((LEN) < sizeof (long)) char * strncpy (char *__restrict dst0, const char *__restrict src0, size_t count) { #if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__) char *dscan; const char *sscan; dscan = dst0; sscan = src0; while (count > 0) { --count; if ((*dscan++ = *sscan++) == '\0') break; } while (count-- > 0) *dscan++ = '\0'; return dst0; #else char *dst = dst0; const char *src = src0; long *aligned_dst; const long *aligned_src; /* If SRC and DEST is aligned and count large enough, then copy words. */ if (!UNALIGNED (src, dst) && !TOO_SMALL (count)) { aligned_dst = (long*)dst; aligned_src = (long*)src; /* SRC and DEST are both "long int" aligned, try to do "long int" sized copies. */ while (count >= sizeof (long int) && !DETECTNULL(*aligned_src)) { count -= sizeof (long int); *aligned_dst++ = *aligned_src++; } dst = (char*)aligned_dst; src = (char*)aligned_src; } while (count > 0) { --count; if ((*dst++ = *src++) == '\0') break; } while (count-- > 0) *dst++ = '\0'; return dst0; #endif /* not PREFER_SIZE_OVER_SPEED */ } /* FUNCTION <>---character string length INDEX strnlen SYNOPSIS #include size_t strnlen(const char *<[str]>, size_t <[n]>); DESCRIPTION The <> function works out the length of the string starting at <<*<[str]>>> by counting chararacters until it reaches a NUL character or the maximum: <[n]> number of characters have been inspected. RETURNS <> returns the character count or <[n]>. PORTABILITY <> is a GNU extension. <> requires no supporting OS subroutines. */ size_t strnlen (const char *str, size_t n) { const char *start = str; while (n-- > 0 && *str) str++; return str - start; } #ifdef __cplusplus } /* extern "C" */ #endif