Started modularising vg_mylibc. Put all the standalone stuff -- ie. not
relying on any other modules -- in m_libcbase.
Also converted the 'size' parameters to functions like VG_(memcpy) and
VG_(strncpy) from Int to SizeT, as they should be.
Also removed VG_(atoll16) and VG_(toupper), which weren't being used.
Also made VG_(atoll36) less flexible -- it now only does base-36 numbers
instead of any base in the range 2..36, since base-36 is the only one we
need. As part of that, I fixed a horrible bug in it which caused it to
return incorrect answers for any number containing the digits 'A'..'I'!
(Eg. for "A; it would return 17 instead of 10!)
Had to disable the assertions in VG_(string_match), since this module can't
see vg_assert, which wasn't ideal but also isn't a disaster.
git-svn-id: svn://svn.valgrind.org/valgrind/trunk@3838 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/coregrind/m_libcbase.c b/coregrind/m_libcbase.c
new file mode 100644
index 0000000..33608ef
--- /dev/null
+++ b/coregrind/m_libcbase.c
@@ -0,0 +1,477 @@
+
+/*--------------------------------------------------------------------*/
+/*--- Entirely standalone libc stuff. m_libcbase.c ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+ This file is part of Valgrind, a dynamic binary instrumentation
+ framework.
+
+ Copyright (C) 2000-2005 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 "tool.h" // XXX: temporary, for NULL, VG_(), Char, etc
+#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
+ ------------------------------------------------------------------ */
+
+Long VG_(atoll) ( Char* str )
+{
+ Bool neg = False;
+ Long n = 0;
+ if (*str == '-') { str++; neg = True; };
+ while (*str >= '0' && *str <= '9') {
+ n = 10*n + (Long)(*str - '0');
+ str++;
+ }
+ if (neg) n = -n;
+ return n;
+}
+
+Long VG_(atoll36) ( Char* str )
+{
+ Bool neg = False;
+ Long n = 0;
+ if (*str == '-') { str++; neg = True; };
+ while (True) {
+ Char c = *str;
+ if (c >= '0' && c <= (Char)'9') {
+ n = 36*n + (Long)(c - '0');
+ }
+ else
+ if (c >= 'A' && c <= (Char)'Z') {
+ n = 36*n + (Long)((c - 'A') + 10);
+ }
+ else
+ if (c >= 'a' && c <= (Char)'z') {
+ n = 36*n + (Long)((c - 'a') + 10);
+ }
+ else {
+ break;
+ }
+ str++;
+ }
+ if (neg) n = -n;
+ return n;
+}
+
+/* ---------------------------------------------------------------------
+ String functions
+ ------------------------------------------------------------------ */
+
+Int VG_(strlen) ( const Char* str )
+{
+ Int 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 )
+{
+ Int 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 )
+{
+ Int 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++;
+ }
+}
+
+static Bool isterm ( Char c )
+{
+ return ( VG_(isspace)(c) || 0 == c );
+}
+
+Int VG_(strcmp_ws) ( const Char* s1, const Char* s2 )
+{
+ while (True) {
+ if (isterm(*s1) && isterm(*s2)) return 0;
+ if (isterm(*s1)) return -1;
+ if (isterm(*s2)) 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 )
+{
+ Int 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++;
+ }
+}
+
+Int VG_(strncmp_ws) ( const Char* s1, const Char* s2, SizeT nmax )
+{
+ Int n = 0;
+ while (True) {
+ if (n >= nmax) return 0;
+ if (isterm(*s1) && isterm(*s2)) return 0;
+ if (isterm(*s1)) return -1;
+ if (isterm(*s2)) 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 )
+{
+ Int 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;
+}
+
+/* ---------------------------------------------------------------------
+ A simple string matching routine, purloined from Hugs98.
+ '*' matches any sequence of zero or more characters
+ '?' matches any single character exactly
+ '\c' matches the character c only (ignoring special chars)
+ c matches the character c only
+ ------------------------------------------------------------------ */
+
+/* Keep track of recursion depth. */
+static Int recDepth;
+
+// Nb: vg_assert disabled because we can't use it from this module...
+static Bool string_match_wrk ( const Char* pat, const Char* str )
+{
+ //vg_assert(recDepth >= 0 && recDepth < 500);
+ recDepth++;
+ for (;;) {
+ switch (*pat) {
+ case '\0':recDepth--;
+ return (*str=='\0');
+ case '*': do {
+ if (string_match_wrk(pat+1,str)) {
+ recDepth--;
+ return True;
+ }
+ } while (*str++);
+ recDepth--;
+ return False;
+ case '?': if (*str++=='\0') {
+ recDepth--;
+ return False;
+ }
+ pat++;
+ break;
+ case '\\':if (*++pat == '\0') {
+ recDepth--;
+ return False; /* spurious trailing \ in pattern */
+ }
+ /* falls through to ... */
+ default : if (*pat++ != *str++) {
+ recDepth--;
+ return False;
+ }
+ break;
+ }
+ }
+}
+
+Bool VG_(string_match) ( const Char* pat, const Char* str )
+{
+ Bool b;
+ recDepth = 0;
+ b = string_match_wrk ( pat, str );
+ //vg_assert(recDepth == 0);
+ /*
+ VG_(printf)("%s %s %s\n",
+ b?"TRUE ":"FALSE", pat, str);
+ */
+ return b;
+}
+
+
+/* ---------------------------------------------------------------------
+ mem* functions
+ ------------------------------------------------------------------ */
+
+void* VG_(memcpy) ( void *dest, const void *src, SizeT sz )
+{
+ const Char *s = (const Char *)src;
+ Char *d = (Char *)dest;
+
+ while (sz--)
+ *d++ = *s++;
+
+ return dest;
+}
+
+void* VG_(memset) ( void *dest, Int c, SizeT sz )
+{
+ Char *d = (Char *)dest;
+
+ while (sz--)
+ *d++ = c;
+
+ return dest;
+}
+
+Int VG_(memcmp) ( const void* s1, const void* s2, SizeT n )
+{
+ Int res;
+ UChar a0;
+ UChar b0;
+
+ while (n != 0) {
+ a0 = ((UChar *) s1)[0];
+ b0 = ((UChar *) s2)[0];
+ s1 += 1;
+ s2 += 1;
+ res = a0 - b0;
+ if (res != 0)
+ return res;
+ n -= 1;
+ }
+ return 0;
+}
+
+/* ---------------------------------------------------------------------
+ Misc useful functions
+ ------------------------------------------------------------------ */
+
+Int VG_(log2) ( Int x )
+{
+ Int i;
+ /* Any more than 32 and we overflow anyway... */
+ for (i = 0; i < 32; i++) {
+ if (1 << i == x) return i;
+ }
+ return -1;
+}
+
+
+// Generic shell sort. Like stdlib.h's qsort().
+void VG_(ssort)( void* base, SizeT nmemb, SizeT size,
+ Int (*compar)(void*, void*) )
+{
+ Int incs[14] = { 1, 4, 13, 40, 121, 364, 1093, 3280,
+ 9841, 29524, 88573, 265720,
+ 797161, 2391484 };
+ Int lo = 0;
+ Int hi = nmemb-1;
+ Int i, j, h, bigN, hp;
+
+ bigN = hi - lo + 1; if (bigN < 2) return;
+ hp = 0; while (hp < 14 && incs[hp] < bigN) hp++; hp--;
+
+ #define SORT \
+ for ( ; hp >= 0; hp--) { \
+ h = incs[hp]; \
+ for (i = lo + h; i <= hi; i++) { \
+ ASSIGN(v,0, a,i); \
+ j = i; \
+ while (COMPAR(a,(j-h), v,0) > 0) { \
+ ASSIGN(a,j, a,(j-h)); \
+ j = j - h; \
+ if (j <= (lo + h - 1)) break; \
+ } \
+ ASSIGN(a,j, v,0); \
+ } \
+ }
+
+ // Specialised cases
+ if (sizeof(ULong) == size) {
+
+ #define ASSIGN(dst, dsti, src, srci) \
+ (dst)[(dsti)] = (src)[(srci)];
+
+ #define COMPAR(dst, dsti, src, srci) \
+ compar( (void*)(& (dst)[(dsti)]), (void*)(& (src)[(srci)]) )
+
+ ULong* a = (ULong*)base;
+ ULong v[1];
+
+ SORT;
+
+ } else if (sizeof(UInt) == size) {
+
+ UInt* a = (UInt*)base;
+ UInt v[1];
+
+ SORT;
+
+ } else if (sizeof(UShort) == size) {
+ UShort* a = (UShort*)base;
+ UShort v[1];
+
+ SORT;
+
+ } else if (sizeof(UChar) == size) {
+ UChar* a = (UChar*)base;
+ UChar v[1];
+
+ SORT;
+
+ #undef ASSIGN
+ #undef COMPAR
+
+ // General case
+ } else {
+ char* a = base;
+ char v[size]; // will be at least 'size' bytes
+
+ #define ASSIGN(dst, dsti, src, srci) \
+ VG_(memcpy)( &dst[size*(dsti)], &src[size*(srci)], size );
+
+ #define COMPAR(dst, dsti, src, srci) \
+ compar( &dst[size*(dsti)], &src[size*(srci)] )
+
+ SORT;
+
+ #undef ASSIGN
+ #undef COMPAR
+ }
+ #undef SORT
+}
+
+/*--------------------------------------------------------------------*/
+/*--- end ---*/
+/*--------------------------------------------------------------------*/
+