diff options
Diffstat (limited to 'coregrind/.svn/text-base/m_libcbase.c.svn-base')
-rw-r--r-- | coregrind/.svn/text-base/m_libcbase.c.svn-base | 627 |
1 files changed, 627 insertions, 0 deletions
diff --git a/coregrind/.svn/text-base/m_libcbase.c.svn-base b/coregrind/.svn/text-base/m_libcbase.c.svn-base new file mode 100644 index 0000000..0d6a6b1 --- /dev/null +++ b/coregrind/.svn/text-base/m_libcbase.c.svn-base @@ -0,0 +1,627 @@ + +/*--------------------------------------------------------------------*/ +/*--- Entirely standalone libc stuff. m_libcbase.c ---*/ +/*--------------------------------------------------------------------*/ + +/* + This file is part of Valgrind, a dynamic binary instrumentation + framework. + + Copyright (C) 2000-2009 Julian Seward + jseward@acm.org + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307, USA. + + The GNU General Public License is contained in the file COPYING. +*/ + +#include "pub_core_basics.h" +#include "pub_core_libcbase.h" + +/* --------------------------------------------------------------------- + Char functions. + ------------------------------------------------------------------ */ + +Bool VG_(isspace) ( Char c ) +{ + return (c == ' ' || c == '\n' || c == '\t' || + c == '\f' || c == '\v' || c == '\r'); +} + +Bool VG_(isdigit) ( Char c ) +{ + return (c >= '0' && c <= '9'); +} + +/* --------------------------------------------------------------------- + Converting strings to numbers + ------------------------------------------------------------------ */ + +static Bool is_dec_digit(Char c, Long* digit) +{ + if (c >= '0' && c <= '9') { *digit = (Long)(c - '0'); return True; } + return False; +} + +static Bool is_hex_digit(Char c, Long* digit) +{ + if (c >= '0' && c <= '9') { *digit = (Long)(c - '0'); return True; } + if (c >= 'A' && c <= 'F') { *digit = (Long)((c - 'A') + 10); return True; } + if (c >= 'a' && c <= 'f') { *digit = (Long)((c - 'a') + 10); return True; } + return False; +} + +Long VG_(strtoll10) ( Char* str, Char** endptr ) +{ + Bool neg = False, converted = False; + Long n = 0, digit = 0; + Char* str0 = str; + + // Skip leading whitespace. + while (VG_(isspace)(*str)) str++; + + // Allow a leading '-' or '+'. + if (*str == '-') { str++; neg = True; } + else if (*str == '+') { str++; } + + while (is_dec_digit(*str, &digit)) { + converted = True; // Ok, we've actually converted a digit. + n = 10*n + digit; + str++; + } + + if (!converted) str = str0; // If nothing converted, endptr points to + if (neg) n = -n; // the start of the string. + if (endptr) *endptr = str; // Record first failing character. + return n; +} + +Long VG_(strtoll16) ( Char* str, Char** endptr ) +{ + Bool neg = False, converted = False; + Long n = 0, digit = 0; + Char* str0 = str; + + // Skip leading whitespace. + while (VG_(isspace)(*str)) str++; + + // Allow a leading '-' or '+'. + if (*str == '-') { str++; neg = True; } + else if (*str == '+') { str++; } + + // Allow leading "0x", but only if there's a hex digit + // following it. + if (*str == '0' + && (*(str+1) == 'x' || *(str+1) == 'X') + && is_hex_digit( *(str+2), &digit )) { + str += 2; + } + + while (is_hex_digit(*str, &digit)) { + converted = True; // Ok, we've actually converted a digit. + n = 16*n + digit; + str++; + } + + if (!converted) str = str0; // If nothing converted, endptr points to + if (neg) n = -n; // the start of the string. + if (endptr) *endptr = str; // Record first failing character. + return n; +} + +double VG_(strtod) ( Char* str, Char** endptr ) +{ + Bool neg = False; + Long digit; + double n = 0, frac = 0, x = 0.1; + + // Skip leading whitespace. + while (VG_(isspace)(*str)) str++; + + // Allow a leading '-' or '+'. + if (*str == '-') { str++; neg = True; } + else if (*str == '+') { str++; } + + while (is_dec_digit(*str, &digit)) { + n = 10*n + digit; + str++; + } + + if (*str == '.') { + str++; + while (is_dec_digit(*str, &digit)) { + frac += x*digit; + x /= 10; + str++; + } + } + + n += frac; + if (neg) n = -n; + if (endptr) *endptr = str; // Record first failing character. + return n; +} + +/* --------------------------------------------------------------------- + String functions + ------------------------------------------------------------------ */ + +SizeT VG_(strlen) ( const Char* str ) +{ + SizeT i = 0; + while (str[i] != 0) i++; + return i; +} + +Char* VG_(strcat) ( Char* dest, const Char* src ) +{ + Char* dest_orig = dest; + while (*dest) dest++; + while (*src) *dest++ = *src++; + *dest = 0; + return dest_orig; +} + +Char* VG_(strncat) ( Char* dest, const Char* src, SizeT n ) +{ + Char* dest_orig = dest; + while (*dest) dest++; + while (*src && n > 0) { *dest++ = *src++; n--; } + *dest = 0; + return dest_orig; +} + +Char* VG_(strpbrk) ( const Char* s, const Char* accept ) +{ + const Char* a; + while (*s) { + a = accept; + while (*a) + if (*a++ == *s) + return (Char *) s; + s++; + } + return NULL; +} + +Char* VG_(strcpy) ( Char* dest, const Char* src ) +{ + Char* dest_orig = dest; + while (*src) *dest++ = *src++; + *dest = 0; + return dest_orig; +} + +/* Copy bytes, not overrunning the end of dest and always ensuring + zero termination. */ +void VG_(strncpy_safely) ( Char* dest, const Char* src, SizeT ndest ) +{ + SizeT i = 0; + while (True) { + dest[i] = 0; + if (src[i] == 0) return; + if (i >= ndest-1) return; + dest[i] = src[i]; + i++; + } +} + +Char* VG_(strncpy) ( Char* dest, const Char* src, SizeT ndest ) +{ + SizeT i = 0; + while (True) { + if (i >= ndest) return dest; /* reached limit */ + dest[i] = src[i]; + if (src[i++] == 0) { + /* reached NUL; pad rest with zeroes as required */ + while (i < ndest) dest[i++] = 0; + return dest; + } + } +} + +Int VG_(strcmp) ( const Char* s1, const Char* s2 ) +{ + while (True) { + if (*s1 == 0 && *s2 == 0) return 0; + if (*s1 == 0) return -1; + if (*s2 == 0) return 1; + + if (*(UChar*)s1 < *(UChar*)s2) return -1; + if (*(UChar*)s1 > *(UChar*)s2) return 1; + + s1++; s2++; + } +} + +Int VG_(strncmp) ( const Char* s1, const Char* s2, SizeT nmax ) +{ + SizeT n = 0; + while (True) { + if (n >= nmax) return 0; + if (*s1 == 0 && *s2 == 0) return 0; + if (*s1 == 0) return -1; + if (*s2 == 0) return 1; + + if (*(UChar*)s1 < *(UChar*)s2) return -1; + if (*(UChar*)s1 > *(UChar*)s2) return 1; + + s1++; s2++; n++; + } +} + +Char* VG_(strstr) ( const Char* haystack, Char* needle ) +{ + SizeT n; + if (haystack == NULL) + return NULL; + n = VG_(strlen)(needle); + while (True) { + if (haystack[0] == 0) + return NULL; + if (VG_(strncmp)(haystack, needle, n) == 0) + return (Char*)haystack; + haystack++; + } +} + +Char* VG_(strchr) ( const Char* s, Char c ) +{ + while (True) { + if (*s == c) return (Char*)s; + if (*s == 0) return NULL; + s++; + } +} + +Char* VG_(strrchr) ( const Char* s, Char c ) +{ + Int n = VG_(strlen)(s); + while (--n > 0) { + if (s[n] == c) return (Char*)s + n; + } + return NULL; +} + +SizeT VG_(strspn) ( const Char* s, const Char* accept ) +{ + const Char *p, *a; + SizeT count = 0; + for (p = s; *p != '\0'; ++p) { + for (a = accept; *a != '\0'; ++a) + if (*p == *a) + break; + if (*a == '\0') + return count; + else + ++count; + } + return count; +} + +SizeT VG_(strcspn) ( const Char* s, const char* reject ) +{ + SizeT count = 0; + while (*s != '\0') { + if (VG_(strchr) (reject, *s++) == NULL) + ++count; + else + return count; + } + return count; +} + + +/* --------------------------------------------------------------------- + mem* functions + ------------------------------------------------------------------ */ + +void* VG_(memcpy) ( void *dest, const void *src, SizeT sz ) +{ + const UChar* s = (const UChar*)src; + UChar* d = (UChar*)dest; + const UInt* sI = (const UInt*)src; + UInt* dI = (UInt*)dest; + + if (VG_IS_4_ALIGNED(dI) && VG_IS_4_ALIGNED(sI)) { + while (sz >= 16) { + dI[0] = sI[0]; + dI[1] = sI[1]; + dI[2] = sI[2]; + dI[3] = sI[3]; + sz -= 16; + dI += 4; + sI += 4; + } + if (sz == 0) + return dest; + while (sz >= 4) { + dI[0] = sI[0]; + sz -= 4; + dI += 1; + sI += 1; + } + if (sz == 0) + return dest; + s = (const UChar*)sI; + d = (UChar*)dI; + } + + while (sz--) + *d++ = *s++; + + return dest; +} + +void* VG_(memmove)(void *dest, const void *src, SizeT sz) +{ + SizeT i; + if (sz == 0) + return dest; + if (dest < src) { + for (i = 0; i < sz; i++) { + ((UChar*)dest)[i] = ((UChar*)src)[i]; + } + } + else if (dest > src) { + for (i = sz - 1; i >= 0; i--) { + ((UChar*)dest)[i] = ((UChar*)src)[i]; + } + } + return dest; +} + +void* VG_(memset) ( void *destV, Int c, SizeT sz ) +{ + Int c4; + Char* d = (Char*)destV; + while ((!VG_IS_4_ALIGNED(d)) && sz >= 1) { + d[0] = c; + d++; + sz--; + } + if (sz == 0) + return destV; + c4 = c & 0xFF; + c4 |= (c4 << 8); + c4 |= (c4 << 16); + while (sz >= 16) { + ((Int*)d)[0] = c4; + ((Int*)d)[1] = c4; + ((Int*)d)[2] = c4; + ((Int*)d)[3] = c4; + d += 16; + sz -= 16; + } + while (sz >= 4) { + ((Int*)d)[0] = c4; + d += 4; + sz -= 4; + } + while (sz >= 1) { + d[0] = c; + d++; + sz--; + } + return destV; +} + +Int VG_(memcmp) ( const void* s1, const void* s2, SizeT n ) +{ + Int res; + const UChar *p1 = s1; + const UChar *p2 = s2; + UChar a0; + UChar b0; + + while (n != 0) { + a0 = p1[0]; + b0 = p2[0]; + p1 += 1; + p2 += 1; + res = a0 - b0; + if (res != 0) + return res; + n -= 1; + } + return 0; +} + +/* --------------------------------------------------------------------- + Misc useful functions + ------------------------------------------------------------------ */ + +///////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////// +/// begin Bentley-McIlroy style quicksort +/// See "Engineering a Sort Function". Jon L Bentley, M. Douglas +/// McIlroy. Software Practice and Experience Vol 23(11), Nov 1993. + +#define BM_MIN(a, b) \ + (a) < (b) ? a : b + +#define BM_SWAPINIT(a, es) \ + swaptype = ((a-(Char*)0) | es) % sizeof(Word) ? 2 \ + : es > (SizeT)sizeof(Word) ? 1 \ + : 0 + +#define BM_EXCH(a, b, t) \ + (t = a, a = b, b = t) + +#define BM_SWAP(a, b) \ + swaptype != 0 \ + ? bm_swapfunc(a, b, es, swaptype) \ + : (void)BM_EXCH(*(Word*)(a), *(Word*)(b), t) + +#define BM_VECSWAP(a, b, n) \ + if (n > 0) bm_swapfunc(a, b, n, swaptype) + +#define BM_PVINIT(pv, pm) \ + if (swaptype != 0) \ + pv = a, BM_SWAP(pv, pm); \ + else \ + pv = (Char*)&v, v = *(Word*)pm + +static Char* bm_med3 ( Char* a, Char* b, Char* c, + Int (*cmp)(void*,void*) ) { + return cmp(a, b) < 0 + ? (cmp(b, c) < 0 ? b : cmp(a, c) < 0 ? c : a) + : (cmp(b, c) > 0 ? b : cmp(a, c) > 0 ? c : a); +} + +static void bm_swapfunc ( Char* a, Char* b, SizeT n, Int swaptype ) +{ + if (swaptype <= 1) { + Word t; + for ( ; n > 0; a += sizeof(Word), b += sizeof(Word), + n -= sizeof(Word)) + BM_EXCH(*(Word*)a, *(Word*)b, t); + } else { + Char t; + for ( ; n > 0; a += 1, b += 1, n -= 1) + BM_EXCH(*a, *b, t); + } +} + +static void bm_qsort ( Char* a, SizeT n, SizeT es, + Int (*cmp)(void*,void*) ) +{ + Char *pa, *pb, *pc, *pd, *pl, *pm, *pn, *pv; + Int r, swaptype; + Word t, v; + SizeT s, s1, s2; + tailcall: + BM_SWAPINIT(a, es); + if (n < 7) { + for (pm = a + es; pm < a + n*es; pm += es) + for (pl = pm; pl > a && cmp(pl-es, pl) > 0; pl -= es) + BM_SWAP(pl, pl-es); + return; + } + pm = a + (n/2)*es; + if (n > 7) { + pl = a; + pn = a + (n-1)*es; + if (n > 40) { + s = (n/8)*es; + pl = bm_med3(pl, pl+s, pl+2*s, cmp); + pm = bm_med3(pm-s, pm, pm+s, cmp); + pn = bm_med3(pn-2*s, pn-s, pn, cmp); + } + pm = bm_med3(pl, pm, pn, cmp); + } + BM_PVINIT(pv, pm); + pa = pb = a; + pc = pd = a + (n-1)*es; + for (;;) { + while (pb <= pc && (r = cmp(pb, pv)) <= 0) { + if (r == 0) { BM_SWAP(pa, pb); pa += es; } + pb += es; + } + while (pc >= pb && (r = cmp(pc, pv)) >= 0) { + if (r == 0) { BM_SWAP(pc, pd); pd -= es; } + pc -= es; + } + if (pb > pc) break; + BM_SWAP(pb, pc); + pb += es; + pc -= es; + } + pn = a + n*es; + s = BM_MIN(pa-a, pb-pa ); BM_VECSWAP(a, pb-s, s); + s = BM_MIN(pd-pc, pn-pd-es); BM_VECSWAP(pb, pn-s, s); + /* Now recurse. Do the smaller partition first with an explicit + recursion, then do the larger partition using a tail call. + Except we can't rely on gcc to implement a tail call in any sane + way, so simply jump back to the start. This guarantees stack + growth can never exceed O(log N) even in the worst case. */ + s1 = pb-pa; + s2 = pd-pc; + if (s1 < s2) { + if (s1 > es) { + bm_qsort(a, s1/es, es, cmp); + } + if (s2 > es) { + /* bm_qsort(pn-s2, s2/es, es, cmp); */ + a = pn-s2; n = s2/es; es = es; cmp = cmp; + goto tailcall; + } + } else { + if (s2 > es) { + bm_qsort(pn-s2, s2/es, es, cmp); + } + if (s1 > es) { + /* bm_qsort(a, s1/es, es, cmp); */ + a = a; n = s1/es; es = es; cmp = cmp; + goto tailcall; + } + } +} + +#undef BM_MIN +#undef BM_SWAPINIT +#undef BM_EXCH +#undef BM_SWAP +#undef BM_VECSWAP +#undef BM_PVINIT + +/// end Bentley-McIlroy style quicksort +///////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////// + +/* Returns the base-2 logarithm of x. Returns -1 if x is not a power + of two. */ +Int VG_(log2) ( UInt x ) +{ + Int i; + /* Any more than 32 and we overflow anyway... */ + for (i = 0; i < 32; i++) { + if ((1U << i) == x) return i; + } + return -1; +} + + +// Generic quick sort. +void VG_(ssort)( void* base, SizeT nmemb, SizeT size, + Int (*compar)(void*, void*) ) +{ + bm_qsort(base,nmemb,size,compar); +} + + +// This random number generator is based on the one suggested in Kernighan +// and Ritchie's "The C Programming Language". + +// A pseudo-random number generator returning a random UInt. If pSeed +// is NULL, it uses its own seed, which starts at zero. If pSeed is +// non-NULL, it uses and updates whatever pSeed points at. + +static UInt seed = 0; + +UInt VG_(random)( /*MOD*/UInt* pSeed ) +{ + if (pSeed == NULL) + pSeed = &seed; + + *pSeed = (1103515245 * *pSeed + 12345); + return *pSeed; +} + +/*--------------------------------------------------------------------*/ +/*--- end ---*/ +/*--------------------------------------------------------------------*/ + |