1 2 /*--------------------------------------------------------------------*/ 3 /*--- Entirely standalone libc stuff. m_libcbase.c ---*/ 4 /*--------------------------------------------------------------------*/ 5 6 /* 7 This file is part of Valgrind, a dynamic binary instrumentation 8 framework. 9 10 Copyright (C) 2000-2010 Julian Seward 11 jseward (at) acm.org 12 13 This program is free software; you can redistribute it and/or 14 modify it under the terms of the GNU General Public License as 15 published by the Free Software Foundation; either version 2 of the 16 License, or (at your option) any later version. 17 18 This program is distributed in the hope that it will be useful, but 19 WITHOUT ANY WARRANTY; without even the implied warranty of 20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 21 General Public License for more details. 22 23 You should have received a copy of the GNU General Public License 24 along with this program; if not, write to the Free Software 25 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 26 02111-1307, USA. 27 28 The GNU General Public License is contained in the file COPYING. 29 */ 30 31 #include "pub_core_basics.h" 32 #include "pub_core_libcbase.h" 33 34 /* --------------------------------------------------------------------- 35 Char functions. 36 ------------------------------------------------------------------ */ 37 38 Bool VG_(isspace) ( Char c ) 39 { 40 return (c == ' ' || c == '\n' || c == '\t' || 41 c == '\f' || c == '\v' || c == '\r'); 42 } 43 44 Bool VG_(isdigit) ( Char c ) 45 { 46 return (c >= '0' && c <= '9'); 47 } 48 49 /* --------------------------------------------------------------------- 50 Converting strings to numbers 51 ------------------------------------------------------------------ */ 52 53 static Bool is_dec_digit(Char c, Long* digit) 54 { 55 if (c >= '0' && c <= '9') { *digit = (Long)(c - '0'); return True; } 56 return False; 57 } 58 59 static Bool is_hex_digit(Char c, Long* digit) 60 { 61 if (c >= '0' && c <= '9') { *digit = (Long)(c - '0'); return True; } 62 if (c >= 'A' && c <= 'F') { *digit = (Long)((c - 'A') + 10); return True; } 63 if (c >= 'a' && c <= 'f') { *digit = (Long)((c - 'a') + 10); return True; } 64 return False; 65 } 66 67 Long VG_(strtoll10) ( Char* str, Char** endptr ) 68 { 69 Bool neg = False, converted = False; 70 Long n = 0, digit = 0; 71 Char* str0 = str; 72 73 // Skip leading whitespace. 74 while (VG_(isspace)(*str)) str++; 75 76 // Allow a leading '-' or '+'. 77 if (*str == '-') { str++; neg = True; } 78 else if (*str == '+') { str++; } 79 80 while (is_dec_digit(*str, &digit)) { 81 converted = True; // Ok, we've actually converted a digit. 82 n = 10*n + digit; 83 str++; 84 } 85 86 if (!converted) str = str0; // If nothing converted, endptr points to 87 if (neg) n = -n; // the start of the string. 88 if (endptr) *endptr = str; // Record first failing character. 89 return n; 90 } 91 92 Long VG_(strtoll16) ( Char* str, Char** endptr ) 93 { 94 Bool neg = False, converted = False; 95 Long n = 0, digit = 0; 96 Char* str0 = str; 97 98 // Skip leading whitespace. 99 while (VG_(isspace)(*str)) str++; 100 101 // Allow a leading '-' or '+'. 102 if (*str == '-') { str++; neg = True; } 103 else if (*str == '+') { str++; } 104 105 // Allow leading "0x", but only if there's a hex digit 106 // following it. 107 if (*str == '0' 108 && (*(str+1) == 'x' || *(str+1) == 'X') 109 && is_hex_digit( *(str+2), &digit )) { 110 str += 2; 111 } 112 113 while (is_hex_digit(*str, &digit)) { 114 converted = True; // Ok, we've actually converted a digit. 115 n = 16*n + digit; 116 str++; 117 } 118 119 if (!converted) str = str0; // If nothing converted, endptr points to 120 if (neg) n = -n; // the start of the string. 121 if (endptr) *endptr = str; // Record first failing character. 122 return n; 123 } 124 125 double VG_(strtod) ( Char* str, Char** endptr ) 126 { 127 Bool neg = False; 128 Long digit; 129 double n = 0, frac = 0, x = 0.1; 130 131 // Skip leading whitespace. 132 while (VG_(isspace)(*str)) str++; 133 134 // Allow a leading '-' or '+'. 135 if (*str == '-') { str++; neg = True; } 136 else if (*str == '+') { str++; } 137 138 while (is_dec_digit(*str, &digit)) { 139 n = 10*n + digit; 140 str++; 141 } 142 143 if (*str == '.') { 144 str++; 145 while (is_dec_digit(*str, &digit)) { 146 frac += x*digit; 147 x /= 10; 148 str++; 149 } 150 } 151 152 n += frac; 153 if (neg) n = -n; 154 if (endptr) *endptr = str; // Record first failing character. 155 return n; 156 } 157 158 Char VG_(tolower) ( Char c ) 159 { 160 if ( c >= 'A' && c <= 'Z' ) { 161 return c - 'A' + 'a'; 162 } else { 163 return c; 164 } 165 } 166 167 /* --------------------------------------------------------------------- 168 String functions 169 ------------------------------------------------------------------ */ 170 171 SizeT VG_(strlen) ( const Char* str ) 172 { 173 SizeT i = 0; 174 while (str[i] != 0) i++; 175 return i; 176 } 177 178 Char* VG_(strcat) ( Char* dest, const Char* src ) 179 { 180 Char* dest_orig = dest; 181 while (*dest) dest++; 182 while (*src) *dest++ = *src++; 183 *dest = 0; 184 return dest_orig; 185 } 186 187 Char* VG_(strncat) ( Char* dest, const Char* src, SizeT n ) 188 { 189 Char* dest_orig = dest; 190 while (*dest) dest++; 191 while (*src && n > 0) { *dest++ = *src++; n--; } 192 *dest = 0; 193 return dest_orig; 194 } 195 196 Char* VG_(strpbrk) ( const Char* s, const Char* accpt ) 197 { 198 const Char* a; 199 while (*s) { 200 a = accpt; 201 while (*a) 202 if (*a++ == *s) 203 return (Char *) s; 204 s++; 205 } 206 return NULL; 207 } 208 209 Char* VG_(strcpy) ( Char* dest, const Char* src ) 210 { 211 Char* dest_orig = dest; 212 while (*src) *dest++ = *src++; 213 *dest = 0; 214 return dest_orig; 215 } 216 217 /* Copy bytes, not overrunning the end of dest and always ensuring 218 zero termination. */ 219 void VG_(strncpy_safely) ( Char* dest, const Char* src, SizeT ndest ) 220 { 221 SizeT i = 0; 222 while (True) { 223 dest[i] = 0; 224 if (src[i] == 0) return; 225 if (i >= ndest-1) return; 226 dest[i] = src[i]; 227 i++; 228 } 229 } 230 231 Char* VG_(strncpy) ( Char* dest, const Char* src, SizeT ndest ) 232 { 233 SizeT i = 0; 234 while (True) { 235 if (i >= ndest) return dest; /* reached limit */ 236 dest[i] = src[i]; 237 if (src[i++] == 0) { 238 /* reached NUL; pad rest with zeroes as required */ 239 while (i < ndest) dest[i++] = 0; 240 return dest; 241 } 242 } 243 } 244 245 Int VG_(strcmp) ( const Char* s1, const Char* s2 ) 246 { 247 while (True) { 248 if (*s1 == 0 && *s2 == 0) return 0; 249 if (*s1 == 0) return -1; 250 if (*s2 == 0) return 1; 251 252 if (*(UChar*)s1 < *(UChar*)s2) return -1; 253 if (*(UChar*)s1 > *(UChar*)s2) return 1; 254 255 s1++; s2++; 256 } 257 } 258 259 Int VG_(strcasecmp) ( const Char* s1, const Char* s2 ) 260 { 261 while (True) { 262 UChar c1 = (UChar)VG_(tolower)(*s1); 263 UChar c2 = (UChar)VG_(tolower)(*s2); 264 if (c1 == 0 && c2 == 0) return 0; 265 if (c1 == 0) return -1; 266 if (c2 == 0) return 1; 267 268 if (c1 < c2) return -1; 269 if (c1 > c2) return 1; 270 271 s1++; s2++; 272 } 273 } 274 275 Int VG_(strncmp) ( const Char* s1, const Char* s2, SizeT nmax ) 276 { 277 SizeT n = 0; 278 while (True) { 279 if (n >= nmax) return 0; 280 if (*s1 == 0 && *s2 == 0) return 0; 281 if (*s1 == 0) return -1; 282 if (*s2 == 0) return 1; 283 284 if (*(UChar*)s1 < *(UChar*)s2) return -1; 285 if (*(UChar*)s1 > *(UChar*)s2) return 1; 286 287 s1++; s2++; n++; 288 } 289 } 290 291 Int VG_(strncasecmp) ( const Char* s1, const Char* s2, SizeT nmax ) 292 { 293 Int n = 0; 294 while (True) { 295 UChar c1; 296 UChar c2; 297 if (n >= nmax) return 0; 298 c1 = (UChar)VG_(tolower)(*s1); 299 c2 = (UChar)VG_(tolower)(*s2); 300 if (c1 == 0 && c2 == 0) return 0; 301 if (c1 == 0) return -1; 302 if (c2 == 0) return 1; 303 304 if (c1 < c2) return -1; 305 if (c1 > c2) return 1; 306 307 s1++; s2++; n++; 308 } 309 } 310 311 Char* VG_(strstr) ( const Char* haystack, Char* needle ) 312 { 313 SizeT n; 314 if (haystack == NULL) 315 return NULL; 316 n = VG_(strlen)(needle); 317 while (True) { 318 if (haystack[0] == 0) 319 return NULL; 320 if (VG_(strncmp)(haystack, needle, n) == 0) 321 return (Char*)haystack; 322 haystack++; 323 } 324 } 325 326 Char* VG_(strcasestr) ( const Char* haystack, Char* needle ) 327 { 328 Int n; 329 if (haystack == NULL) 330 return NULL; 331 n = VG_(strlen)(needle); 332 while (True) { 333 if (haystack[0] == 0) 334 return NULL; 335 if (VG_(strncasecmp)(haystack, needle, n) == 0) 336 return (Char*)haystack; 337 haystack++; 338 } 339 } 340 341 Char* VG_(strchr) ( const Char* s, Char c ) 342 { 343 while (True) { 344 if (*s == c) return (Char*)s; 345 if (*s == 0) return NULL; 346 s++; 347 } 348 } 349 350 Char* VG_(strrchr) ( const Char* s, Char c ) 351 { 352 Int n = VG_(strlen)(s); 353 while (--n > 0) { 354 if (s[n] == c) return (Char*)s + n; 355 } 356 return NULL; 357 } 358 359 SizeT VG_(strspn) ( const Char* s, const Char* accpt ) 360 { 361 const Char *p, *a; 362 SizeT count = 0; 363 for (p = s; *p != '\0'; ++p) { 364 for (a = accpt; *a != '\0'; ++a) 365 if (*p == *a) 366 break; 367 if (*a == '\0') 368 return count; 369 else 370 ++count; 371 } 372 return count; 373 } 374 375 SizeT VG_(strcspn) ( const Char* s, const char* reject ) 376 { 377 SizeT count = 0; 378 while (*s != '\0') { 379 if (VG_(strchr) (reject, *s++) == NULL) 380 ++count; 381 else 382 return count; 383 } 384 return count; 385 } 386 387 388 /* --------------------------------------------------------------------- 389 mem* functions 390 ------------------------------------------------------------------ */ 391 392 void* VG_(memcpy) ( void *dest, const void *src, SizeT sz ) 393 { 394 const UChar* s = (const UChar*)src; 395 UChar* d = (UChar*)dest; 396 const UInt* sI = (const UInt*)src; 397 UInt* dI = (UInt*)dest; 398 399 if (VG_IS_4_ALIGNED(dI) && VG_IS_4_ALIGNED(sI)) { 400 while (sz >= 16) { 401 dI[0] = sI[0]; 402 dI[1] = sI[1]; 403 dI[2] = sI[2]; 404 dI[3] = sI[3]; 405 sz -= 16; 406 dI += 4; 407 sI += 4; 408 } 409 if (sz == 0) 410 return dest; 411 while (sz >= 4) { 412 dI[0] = sI[0]; 413 sz -= 4; 414 dI += 1; 415 sI += 1; 416 } 417 if (sz == 0) 418 return dest; 419 s = (const UChar*)sI; 420 d = (UChar*)dI; 421 } 422 423 while (sz--) 424 *d++ = *s++; 425 426 return dest; 427 } 428 429 void* VG_(memmove)(void *dest, const void *src, SizeT sz) 430 { 431 SizeT i; 432 if (sz == 0) 433 return dest; 434 if (dest < src) { 435 for (i = 0; i < sz; i++) { 436 ((UChar*)dest)[i] = ((UChar*)src)[i]; 437 } 438 } 439 else if (dest > src) { 440 for (i = 0; i < sz; i++) { 441 ((UChar*)dest)[sz-i-1] = ((UChar*)src)[sz-i-1]; 442 } 443 } 444 return dest; 445 } 446 447 void* VG_(memset) ( void *destV, Int c, SizeT sz ) 448 { 449 Int c4; 450 Char* d = (Char*)destV; 451 while ((!VG_IS_4_ALIGNED(d)) && sz >= 1) { 452 d[0] = c; 453 d++; 454 sz--; 455 } 456 if (sz == 0) 457 return destV; 458 c4 = c & 0xFF; 459 c4 |= (c4 << 8); 460 c4 |= (c4 << 16); 461 while (sz >= 16) { 462 ((Int*)d)[0] = c4; 463 ((Int*)d)[1] = c4; 464 ((Int*)d)[2] = c4; 465 ((Int*)d)[3] = c4; 466 d += 16; 467 sz -= 16; 468 } 469 while (sz >= 4) { 470 ((Int*)d)[0] = c4; 471 d += 4; 472 sz -= 4; 473 } 474 while (sz >= 1) { 475 d[0] = c; 476 d++; 477 sz--; 478 } 479 return destV; 480 } 481 482 Int VG_(memcmp) ( const void* s1, const void* s2, SizeT n ) 483 { 484 Int res; 485 const UChar *p1 = s1; 486 const UChar *p2 = s2; 487 UChar a0; 488 UChar b0; 489 490 while (n != 0) { 491 a0 = p1[0]; 492 b0 = p2[0]; 493 p1 += 1; 494 p2 += 1; 495 res = a0 - b0; 496 if (res != 0) 497 return res; 498 n -= 1; 499 } 500 return 0; 501 } 502 503 /* --------------------------------------------------------------------- 504 Misc useful functions 505 ------------------------------------------------------------------ */ 506 507 ///////////////////////////////////////////////////////////// 508 ///////////////////////////////////////////////////////////// 509 /// begin Bentley-McIlroy style quicksort 510 /// See "Engineering a Sort Function". Jon L Bentley, M. Douglas 511 /// McIlroy. Software Practice and Experience Vol 23(11), Nov 1993. 512 513 #define BM_MIN(a, b) \ 514 (a) < (b) ? a : b 515 516 #define BM_SWAPINIT(a, es) \ 517 swaptype = ((a-(Char*)0) | es) % sizeof(Word) ? 2 \ 518 : es > (SizeT)sizeof(Word) ? 1 \ 519 : 0 520 521 #define BM_EXCH(a, b, t) \ 522 (t = a, a = b, b = t) 523 524 #define BM_SWAP(a, b) \ 525 swaptype != 0 \ 526 ? bm_swapfunc(a, b, es, swaptype) \ 527 : (void)BM_EXCH(*(Word*)(a), *(Word*)(b), t) 528 529 #define BM_VECSWAP(a, b, n) \ 530 if (n > 0) bm_swapfunc(a, b, n, swaptype) 531 532 #define BM_PVINIT(pv, pm) \ 533 if (swaptype != 0) \ 534 pv = a, BM_SWAP(pv, pm); \ 535 else \ 536 pv = (Char*)&v, v = *(Word*)pm 537 538 static Char* bm_med3 ( Char* a, Char* b, Char* c, 539 Int (*cmp)(void*,void*) ) { 540 return cmp(a, b) < 0 541 ? (cmp(b, c) < 0 ? b : cmp(a, c) < 0 ? c : a) 542 : (cmp(b, c) > 0 ? b : cmp(a, c) > 0 ? c : a); 543 } 544 545 static void bm_swapfunc ( Char* a, Char* b, SizeT n, Int swaptype ) 546 { 547 if (swaptype <= 1) { 548 Word t; 549 for ( ; n > 0; a += sizeof(Word), b += sizeof(Word), 550 n -= sizeof(Word)) 551 BM_EXCH(*(Word*)a, *(Word*)b, t); 552 } else { 553 Char t; 554 for ( ; n > 0; a += 1, b += 1, n -= 1) 555 BM_EXCH(*a, *b, t); 556 } 557 } 558 559 static void bm_qsort ( Char* a, SizeT n, SizeT es, 560 Int (*cmp)(void*,void*) ) 561 { 562 Char *pa, *pb, *pc, *pd, *pl, *pm, *pn, *pv; 563 Int r, swaptype; 564 Word t, v; 565 SizeT s, s1, s2; 566 tailcall: 567 BM_SWAPINIT(a, es); 568 if (n < 7) { 569 for (pm = a + es; pm < a + n*es; pm += es) 570 for (pl = pm; pl > a && cmp(pl-es, pl) > 0; pl -= es) 571 BM_SWAP(pl, pl-es); 572 return; 573 } 574 pm = a + (n/2)*es; 575 if (n > 7) { 576 pl = a; 577 pn = a + (n-1)*es; 578 if (n > 40) { 579 s = (n/8)*es; 580 pl = bm_med3(pl, pl+s, pl+2*s, cmp); 581 pm = bm_med3(pm-s, pm, pm+s, cmp); 582 pn = bm_med3(pn-2*s, pn-s, pn, cmp); 583 } 584 pm = bm_med3(pl, pm, pn, cmp); 585 } 586 BM_PVINIT(pv, pm); 587 pa = pb = a; 588 pc = pd = a + (n-1)*es; 589 for (;;) { 590 while (pb <= pc && (r = cmp(pb, pv)) <= 0) { 591 if (r == 0) { BM_SWAP(pa, pb); pa += es; } 592 pb += es; 593 } 594 while (pc >= pb && (r = cmp(pc, pv)) >= 0) { 595 if (r == 0) { BM_SWAP(pc, pd); pd -= es; } 596 pc -= es; 597 } 598 if (pb > pc) break; 599 BM_SWAP(pb, pc); 600 pb += es; 601 pc -= es; 602 } 603 pn = a + n*es; 604 s = BM_MIN(pa-a, pb-pa ); BM_VECSWAP(a, pb-s, s); 605 s = BM_MIN(pd-pc, pn-pd-es); BM_VECSWAP(pb, pn-s, s); 606 /* Now recurse. Do the smaller partition first with an explicit 607 recursion, then do the larger partition using a tail call. 608 Except we can't rely on gcc to implement a tail call in any sane 609 way, so simply jump back to the start. This guarantees stack 610 growth can never exceed O(log N) even in the worst case. */ 611 s1 = pb-pa; 612 s2 = pd-pc; 613 if (s1 < s2) { 614 if (s1 > es) { 615 bm_qsort(a, s1/es, es, cmp); 616 } 617 if (s2 > es) { 618 /* bm_qsort(pn-s2, s2/es, es, cmp); */ 619 a = pn-s2; n = s2/es; es = es; cmp = cmp; 620 goto tailcall; 621 } 622 } else { 623 if (s2 > es) { 624 bm_qsort(pn-s2, s2/es, es, cmp); 625 } 626 if (s1 > es) { 627 /* bm_qsort(a, s1/es, es, cmp); */ 628 a = a; n = s1/es; es = es; cmp = cmp; 629 goto tailcall; 630 } 631 } 632 } 633 634 #undef BM_MIN 635 #undef BM_SWAPINIT 636 #undef BM_EXCH 637 #undef BM_SWAP 638 #undef BM_VECSWAP 639 #undef BM_PVINIT 640 641 /// end Bentley-McIlroy style quicksort 642 ///////////////////////////////////////////////////////////// 643 ///////////////////////////////////////////////////////////// 644 645 /* Returns the base-2 logarithm of x. Returns -1 if x is not a power 646 of two. */ 647 Int VG_(log2) ( UInt x ) 648 { 649 Int i; 650 /* Any more than 32 and we overflow anyway... */ 651 for (i = 0; i < 32; i++) { 652 if ((1U << i) == x) return i; 653 } 654 return -1; 655 } 656 657 658 // Generic quick sort. 659 void VG_(ssort)( void* base, SizeT nmemb, SizeT size, 660 Int (*compar)(void*, void*) ) 661 { 662 bm_qsort(base,nmemb,size,compar); 663 } 664 665 666 // This random number generator is based on the one suggested in Kernighan 667 // and Ritchie's "The C Programming Language". 668 669 // A pseudo-random number generator returning a random UInt. If pSeed 670 // is NULL, it uses its own seed, which starts at zero. If pSeed is 671 // non-NULL, it uses and updates whatever pSeed points at. 672 673 static UInt seed = 0; 674 675 UInt VG_(random)( /*MOD*/UInt* pSeed ) 676 { 677 if (pSeed == NULL) 678 pSeed = &seed; 679 680 *pSeed = (1103515245 * *pSeed + 12345); 681 return *pSeed; 682 } 683 684 /*--------------------------------------------------------------------*/ 685 /*--- end ---*/ 686 /*--------------------------------------------------------------------*/ 687 688