summaryrefslogtreecommitdiff
path: root/coregrind/.svn/text-base/m_libcbase.c.svn-base
diff options
context:
space:
mode:
Diffstat (limited to 'coregrind/.svn/text-base/m_libcbase.c.svn-base')
-rw-r--r--coregrind/.svn/text-base/m_libcbase.c.svn-base627
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 ---*/
+/*--------------------------------------------------------------------*/
+