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-2012 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 ULong VG_(strtoull10) ( Char* str, Char** endptr ) 93 { 94 Bool converted = False; 95 ULong n = 0; 96 Long digit = 0; 97 Char* str0 = str; 98 99 // Skip leading whitespace. 100 while (VG_(isspace)(*str)) str++; 101 102 // Allow a leading '+'. 103 if (*str == '+') { str++; } 104 105 while (is_dec_digit(*str, &digit)) { 106 converted = True; // Ok, we've actually converted a digit. 107 n = 10*n + digit; 108 str++; 109 } 110 111 if (!converted) str = str0; // If nothing converted, endptr points to 112 // the start of the string. 113 if (endptr) *endptr = str; // Record first failing character. 114 return n; 115 } 116 117 Long VG_(strtoll16) ( Char* str, Char** endptr ) 118 { 119 Bool neg = False, converted = False; 120 Long n = 0, digit = 0; 121 Char* str0 = str; 122 123 // Skip leading whitespace. 124 while (VG_(isspace)(*str)) str++; 125 126 // Allow a leading '-' or '+'. 127 if (*str == '-') { str++; neg = True; } 128 else if (*str == '+') { str++; } 129 130 // Allow leading "0x", but only if there's a hex digit 131 // following it. 132 if (*str == '0' 133 && (*(str+1) == 'x' || *(str+1) == 'X') 134 && is_hex_digit( *(str+2), &digit )) { 135 str += 2; 136 } 137 138 while (is_hex_digit(*str, &digit)) { 139 converted = True; // Ok, we've actually converted a digit. 140 n = 16*n + digit; 141 str++; 142 } 143 144 if (!converted) str = str0; // If nothing converted, endptr points to 145 if (neg) n = -n; // the start of the string. 146 if (endptr) *endptr = str; // Record first failing character. 147 return n; 148 } 149 150 ULong VG_(strtoull16) ( Char* str, Char** endptr ) 151 { 152 Bool converted = False; 153 ULong n = 0; 154 Long digit = 0; 155 Char* str0 = str; 156 157 // Skip leading whitespace. 158 while (VG_(isspace)(*str)) str++; 159 160 // Allow a leading '+'. 161 if (*str == '+') { str++; } 162 163 // Allow leading "0x", but only if there's a hex digit 164 // following it. 165 if (*str == '0' 166 && (*(str+1) == 'x' || *(str+1) == 'X') 167 && is_hex_digit( *(str+2), &digit )) { 168 str += 2; 169 } 170 171 while (is_hex_digit(*str, &digit)) { 172 converted = True; // Ok, we've actually converted a digit. 173 n = 16*n + digit; 174 str++; 175 } 176 177 if (!converted) str = str0; // If nothing converted, endptr points to 178 // the start of the string. 179 if (endptr) *endptr = str; // Record first failing character. 180 return n; 181 } 182 183 double VG_(strtod) ( Char* str, Char** endptr ) 184 { 185 Bool neg = False; 186 Long digit; 187 double n = 0, frac = 0, x = 0.1; 188 189 // Skip leading whitespace. 190 while (VG_(isspace)(*str)) str++; 191 192 // Allow a leading '-' or '+'. 193 if (*str == '-') { str++; neg = True; } 194 else if (*str == '+') { str++; } 195 196 while (is_dec_digit(*str, &digit)) { 197 n = 10*n + digit; 198 str++; 199 } 200 201 if (*str == '.') { 202 str++; 203 while (is_dec_digit(*str, &digit)) { 204 frac += x*digit; 205 x /= 10; 206 str++; 207 } 208 } 209 210 n += frac; 211 if (neg) n = -n; 212 if (endptr) *endptr = str; // Record first failing character. 213 return n; 214 } 215 216 Char VG_(tolower) ( Char c ) 217 { 218 if ( c >= 'A' && c <= 'Z' ) { 219 return c - 'A' + 'a'; 220 } else { 221 return c; 222 } 223 } 224 225 /* --------------------------------------------------------------------- 226 String functions 227 ------------------------------------------------------------------ */ 228 229 SizeT VG_(strlen) ( const Char* str ) 230 { 231 SizeT i = 0; 232 while (str[i] != 0) i++; 233 return i; 234 } 235 236 Char* VG_(strcat) ( Char* dest, const Char* src ) 237 { 238 Char* dest_orig = dest; 239 while (*dest) dest++; 240 while (*src) *dest++ = *src++; 241 *dest = 0; 242 return dest_orig; 243 } 244 245 Char* VG_(strncat) ( Char* dest, const Char* src, SizeT n ) 246 { 247 Char* dest_orig = dest; 248 while (*dest) dest++; 249 while (*src && n > 0) { *dest++ = *src++; n--; } 250 *dest = 0; 251 return dest_orig; 252 } 253 254 Char* VG_(strpbrk) ( const Char* s, const Char* accpt ) 255 { 256 const Char* a; 257 while (*s) { 258 a = accpt; 259 while (*a) 260 if (*a++ == *s) 261 return (Char *) s; 262 s++; 263 } 264 return NULL; 265 } 266 267 Char* VG_(strcpy) ( Char* dest, const Char* src ) 268 { 269 Char* dest_orig = dest; 270 while (*src) *dest++ = *src++; 271 *dest = 0; 272 return dest_orig; 273 } 274 275 /* Copy bytes, not overrunning the end of dest and always ensuring 276 zero termination. */ 277 void VG_(strncpy_safely) ( Char* dest, const Char* src, SizeT ndest ) 278 { 279 SizeT i = 0; 280 while (True) { 281 dest[i] = 0; 282 if (src[i] == 0) return; 283 if (i >= ndest-1) return; 284 dest[i] = src[i]; 285 i++; 286 } 287 } 288 289 Char* VG_(strncpy) ( Char* dest, const Char* src, SizeT ndest ) 290 { 291 SizeT i = 0; 292 while (True) { 293 if (i >= ndest) return dest; /* reached limit */ 294 dest[i] = src[i]; 295 if (src[i++] == 0) { 296 /* reached NUL; pad rest with zeroes as required */ 297 while (i < ndest) dest[i++] = 0; 298 return dest; 299 } 300 } 301 } 302 303 Int VG_(strcmp) ( const Char* s1, const Char* s2 ) 304 { 305 while (True) { 306 if (*(UChar*)s1 < *(UChar*)s2) return -1; 307 if (*(UChar*)s1 > *(UChar*)s2) return 1; 308 309 /* *s1 == *s2 */ 310 if (*s1 == 0) return 0; 311 312 s1++; s2++; 313 } 314 } 315 316 Int VG_(strcasecmp) ( const Char* s1, const Char* s2 ) 317 { 318 while (True) { 319 UChar c1 = (UChar)VG_(tolower)(*s1); 320 UChar c2 = (UChar)VG_(tolower)(*s2); 321 if (c1 < c2) return -1; 322 if (c1 > c2) return 1; 323 324 /* c1 == c2 */ 325 if (c1 == 0) return 0; 326 327 s1++; s2++; 328 } 329 } 330 331 Int VG_(strncmp) ( const Char* s1, const Char* s2, SizeT nmax ) 332 { 333 SizeT n = 0; 334 while (True) { 335 if (n >= nmax) return 0; 336 if (*(UChar*)s1 < *(UChar*)s2) return -1; 337 if (*(UChar*)s1 > *(UChar*)s2) return 1; 338 339 /* *s1 == *s2 */ 340 if (*s1 == 0) return 0; 341 342 s1++; s2++; n++; 343 } 344 } 345 346 Int VG_(strncasecmp) ( const Char* s1, const Char* s2, SizeT nmax ) 347 { 348 Int n = 0; 349 while (True) { 350 UChar c1; 351 UChar c2; 352 if (n >= nmax) return 0; 353 c1 = (UChar)VG_(tolower)(*s1); 354 c2 = (UChar)VG_(tolower)(*s2); 355 if (c1 < c2) return -1; 356 if (c1 > c2) return 1; 357 358 /* c1 == c2 */ 359 if (c1 == 0) return 0; 360 361 s1++; s2++; n++; 362 } 363 } 364 365 Char* VG_(strstr) ( const Char* haystack, Char* needle ) 366 { 367 SizeT n; 368 if (haystack == NULL) 369 return NULL; 370 n = VG_(strlen)(needle); 371 while (True) { 372 if (haystack[0] == 0) 373 return NULL; 374 if (VG_(strncmp)(haystack, needle, n) == 0) 375 return (Char*)haystack; 376 haystack++; 377 } 378 } 379 380 Char* VG_(strcasestr) ( const Char* haystack, Char* needle ) 381 { 382 Int n; 383 if (haystack == NULL) 384 return NULL; 385 n = VG_(strlen)(needle); 386 while (True) { 387 if (haystack[0] == 0) 388 return NULL; 389 if (VG_(strncasecmp)(haystack, needle, n) == 0) 390 return (Char*)haystack; 391 haystack++; 392 } 393 } 394 395 Char* VG_(strchr) ( const Char* s, Char c ) 396 { 397 while (True) { 398 if (*s == c) return (Char*)s; 399 if (*s == 0) return NULL; 400 s++; 401 } 402 } 403 404 Char* VG_(strrchr) ( const Char* s, Char c ) 405 { 406 Int n = VG_(strlen)(s); 407 while (--n > 0) { 408 if (s[n] == c) return (Char*)s + n; 409 } 410 return NULL; 411 } 412 413 /* (code copied from glib then updated to valgrind types) */ 414 static Char *olds; 415 Char * 416 VG_(strtok) (Char *s, const Char *delim) 417 { 418 return VG_(strtok_r) (s, delim, &olds); 419 } 420 421 Char * 422 VG_(strtok_r) (Char* s, const Char* delim, Char** saveptr) 423 { 424 Char *token; 425 426 if (s == NULL) 427 s = *saveptr; 428 429 /* Scan leading delimiters. */ 430 s += VG_(strspn (s, delim)); 431 if (*s == '\0') 432 { 433 *saveptr = s; 434 return NULL; 435 } 436 437 /* Find the end of the token. */ 438 token = s; 439 s = VG_(strpbrk (token, delim)); 440 if (s == NULL) 441 /* This token finishes the string. */ 442 *saveptr = token + VG_(strlen) (token); 443 else 444 { 445 /* Terminate the token and make OLDS point past it. */ 446 *s = '\0'; 447 *saveptr = s + 1; 448 } 449 return token; 450 } 451 452 static Bool isHex ( UChar c ) 453 { 454 return ((c >= '0' && c <= '9') || 455 (c >= 'a' && c <= 'f') || 456 (c >= 'A' && c <= 'F')); 457 } 458 459 static UInt fromHex ( UChar c ) 460 { 461 if (c >= '0' && c <= '9') 462 return (UInt)c - (UInt)'0'; 463 if (c >= 'a' && c <= 'f') 464 return 10 + (UInt)c - (UInt)'a'; 465 if (c >= 'A' && c <= 'F') 466 return 10 + (UInt)c - (UInt)'A'; 467 /*NOTREACHED*/ 468 // ??? need to vg_assert(0); 469 return 0; 470 } 471 472 Bool VG_(parse_Addr) ( UChar** ppc, Addr* result ) 473 { 474 Int used, limit = 2 * sizeof(Addr); 475 if (**ppc != '0') 476 return False; 477 (*ppc)++; 478 if (**ppc != 'x') 479 return False; 480 (*ppc)++; 481 *result = 0; 482 used = 0; 483 while (isHex(**ppc)) { 484 // ??? need to vg_assert(d < fromHex(**ppc)); 485 *result = ((*result) << 4) | fromHex(**ppc); 486 (*ppc)++; 487 used++; 488 if (used > limit) return False; 489 } 490 if (used == 0) 491 return False; 492 return True; 493 } 494 495 SizeT VG_(strspn) ( const Char* s, const Char* accpt ) 496 { 497 const Char *p, *a; 498 SizeT count = 0; 499 for (p = s; *p != '\0'; ++p) { 500 for (a = accpt; *a != '\0'; ++a) 501 if (*p == *a) 502 break; 503 if (*a == '\0') 504 return count; 505 else 506 ++count; 507 } 508 return count; 509 } 510 511 SizeT VG_(strcspn) ( const Char* s, const char* reject ) 512 { 513 SizeT count = 0; 514 while (*s != '\0') { 515 if (VG_(strchr) (reject, *s++) == NULL) 516 ++count; 517 else 518 return count; 519 } 520 return count; 521 } 522 523 524 /* --------------------------------------------------------------------- 525 mem* functions 526 ------------------------------------------------------------------ */ 527 528 void* VG_(memcpy) ( void *dest, const void *src, SizeT sz ) 529 { 530 const UChar* s = (const UChar*)src; 531 UChar* d = (UChar*)dest; 532 const UInt* sI = (const UInt*)src; 533 UInt* dI = (UInt*)dest; 534 535 if (VG_IS_4_ALIGNED(dI) && VG_IS_4_ALIGNED(sI)) { 536 while (sz >= 16) { 537 dI[0] = sI[0]; 538 dI[1] = sI[1]; 539 dI[2] = sI[2]; 540 dI[3] = sI[3]; 541 sz -= 16; 542 dI += 4; 543 sI += 4; 544 } 545 if (sz == 0) 546 return dest; 547 while (sz >= 4) { 548 dI[0] = sI[0]; 549 sz -= 4; 550 dI += 1; 551 sI += 1; 552 } 553 if (sz == 0) 554 return dest; 555 s = (const UChar*)sI; 556 d = (UChar*)dI; 557 } 558 559 while (sz--) 560 *d++ = *s++; 561 562 return dest; 563 } 564 565 void* VG_(memmove)(void *dest, const void *src, SizeT sz) 566 { 567 SizeT i; 568 if (sz == 0) 569 return dest; 570 if (dest < src) { 571 for (i = 0; i < sz; i++) { 572 ((UChar*)dest)[i] = ((UChar*)src)[i]; 573 } 574 } 575 else if (dest > src) { 576 for (i = 0; i < sz; i++) { 577 ((UChar*)dest)[sz-i-1] = ((UChar*)src)[sz-i-1]; 578 } 579 } 580 return dest; 581 } 582 583 void* VG_(memset) ( void *destV, Int c, SizeT sz ) 584 { 585 Int c4; 586 Char* d = (Char*)destV; 587 while ((!VG_IS_4_ALIGNED(d)) && sz >= 1) { 588 d[0] = c; 589 d++; 590 sz--; 591 } 592 if (sz == 0) 593 return destV; 594 c4 = c & 0xFF; 595 c4 |= (c4 << 8); 596 c4 |= (c4 << 16); 597 while (sz >= 16) { 598 ((Int*)d)[0] = c4; 599 ((Int*)d)[1] = c4; 600 ((Int*)d)[2] = c4; 601 ((Int*)d)[3] = c4; 602 d += 16; 603 sz -= 16; 604 } 605 while (sz >= 4) { 606 ((Int*)d)[0] = c4; 607 d += 4; 608 sz -= 4; 609 } 610 while (sz >= 1) { 611 d[0] = c; 612 d++; 613 sz--; 614 } 615 return destV; 616 } 617 618 Int VG_(memcmp) ( const void* s1, const void* s2, SizeT n ) 619 { 620 Int res; 621 const UChar *p1 = s1; 622 const UChar *p2 = s2; 623 UChar a0; 624 UChar b0; 625 626 while (n != 0) { 627 a0 = p1[0]; 628 b0 = p2[0]; 629 p1 += 1; 630 p2 += 1; 631 res = a0 - b0; 632 if (res != 0) 633 return res; 634 n -= 1; 635 } 636 return 0; 637 } 638 639 /* --------------------------------------------------------------------- 640 Misc useful functions 641 ------------------------------------------------------------------ */ 642 643 ///////////////////////////////////////////////////////////// 644 ///////////////////////////////////////////////////////////// 645 /// begin Bentley-McIlroy style quicksort 646 /// See "Engineering a Sort Function". Jon L Bentley, M. Douglas 647 /// McIlroy. Software Practice and Experience Vol 23(11), Nov 1993. 648 649 #define BM_MIN(a, b) \ 650 (a) < (b) ? a : b 651 652 #define BM_SWAPINIT(a, es) \ 653 swaptype = ((a-(Char*)0) | es) % sizeof(Word) ? 2 \ 654 : es > (SizeT)sizeof(Word) ? 1 \ 655 : 0 656 657 #define BM_EXCH(a, b, t) \ 658 (t = a, a = b, b = t) 659 660 #define BM_SWAP(a, b) \ 661 swaptype != 0 \ 662 ? bm_swapfunc(a, b, es, swaptype) \ 663 : (void)BM_EXCH(*(Word*)(a), *(Word*)(b), t) 664 665 #define BM_VECSWAP(a, b, n) \ 666 if (n > 0) bm_swapfunc(a, b, n, swaptype) 667 668 #define BM_PVINIT(pv, pm) \ 669 if (swaptype != 0) \ 670 pv = a, BM_SWAP(pv, pm); \ 671 else \ 672 pv = (Char*)&v, v = *(Word*)pm 673 674 static Char* bm_med3 ( Char* a, Char* b, Char* c, 675 Int (*cmp)(void*,void*) ) { 676 return cmp(a, b) < 0 677 ? (cmp(b, c) < 0 ? b : cmp(a, c) < 0 ? c : a) 678 : (cmp(b, c) > 0 ? b : cmp(a, c) > 0 ? c : a); 679 } 680 681 static void bm_swapfunc ( Char* a, Char* b, SizeT n, Int swaptype ) 682 { 683 if (swaptype <= 1) { 684 Word t; 685 for ( ; n > 0; a += sizeof(Word), b += sizeof(Word), 686 n -= sizeof(Word)) 687 BM_EXCH(*(Word*)a, *(Word*)b, t); 688 } else { 689 Char t; 690 for ( ; n > 0; a += 1, b += 1, n -= 1) 691 BM_EXCH(*a, *b, t); 692 } 693 } 694 695 static void bm_qsort ( Char* a, SizeT n, SizeT es, 696 Int (*cmp)(void*,void*) ) 697 { 698 Char *pa, *pb, *pc, *pd, *pl, *pm, *pn, *pv; 699 Int r, swaptype; 700 Word t, v; 701 SizeT s, s1, s2; 702 tailcall: 703 BM_SWAPINIT(a, es); 704 if (n < 7) { 705 for (pm = a + es; pm < a + n*es; pm += es) 706 for (pl = pm; pl > a && cmp(pl-es, pl) > 0; pl -= es) 707 BM_SWAP(pl, pl-es); 708 return; 709 } 710 pm = a + (n/2)*es; 711 if (n > 7) { 712 pl = a; 713 pn = a + (n-1)*es; 714 if (n > 40) { 715 s = (n/8)*es; 716 pl = bm_med3(pl, pl+s, pl+2*s, cmp); 717 pm = bm_med3(pm-s, pm, pm+s, cmp); 718 pn = bm_med3(pn-2*s, pn-s, pn, cmp); 719 } 720 pm = bm_med3(pl, pm, pn, cmp); 721 } 722 BM_PVINIT(pv, pm); 723 pa = pb = a; 724 pc = pd = a + (n-1)*es; 725 for (;;) { 726 while (pb <= pc && (r = cmp(pb, pv)) <= 0) { 727 if (r == 0) { BM_SWAP(pa, pb); pa += es; } 728 pb += es; 729 } 730 while (pc >= pb && (r = cmp(pc, pv)) >= 0) { 731 if (r == 0) { BM_SWAP(pc, pd); pd -= es; } 732 pc -= es; 733 } 734 if (pb > pc) break; 735 BM_SWAP(pb, pc); 736 pb += es; 737 pc -= es; 738 } 739 pn = a + n*es; 740 s = BM_MIN(pa-a, pb-pa ); BM_VECSWAP(a, pb-s, s); 741 s = BM_MIN(pd-pc, pn-pd-es); BM_VECSWAP(pb, pn-s, s); 742 /* Now recurse. Do the smaller partition first with an explicit 743 recursion, then do the larger partition using a tail call. 744 Except we can't rely on gcc to implement a tail call in any sane 745 way, so simply jump back to the start. This guarantees stack 746 growth can never exceed O(log N) even in the worst case. */ 747 s1 = pb-pa; 748 s2 = pd-pc; 749 if (s1 < s2) { 750 if (s1 > es) { 751 bm_qsort(a, s1/es, es, cmp); 752 } 753 if (s2 > es) { 754 /* bm_qsort(pn-s2, s2/es, es, cmp); */ 755 a = pn-s2; n = s2/es; es = es; cmp = cmp; 756 goto tailcall; 757 } 758 } else { 759 if (s2 > es) { 760 bm_qsort(pn-s2, s2/es, es, cmp); 761 } 762 if (s1 > es) { 763 /* bm_qsort(a, s1/es, es, cmp); */ 764 a = a; n = s1/es; es = es; cmp = cmp; 765 goto tailcall; 766 } 767 } 768 } 769 770 #undef BM_MIN 771 #undef BM_SWAPINIT 772 #undef BM_EXCH 773 #undef BM_SWAP 774 #undef BM_VECSWAP 775 #undef BM_PVINIT 776 777 /// end Bentley-McIlroy style quicksort 778 ///////////////////////////////////////////////////////////// 779 ///////////////////////////////////////////////////////////// 780 781 /* Returns the base-2 logarithm of x. Returns -1 if x is not a power 782 of two. */ 783 Int VG_(log2) ( UInt x ) 784 { 785 Int i; 786 /* Any more than 32 and we overflow anyway... */ 787 for (i = 0; i < 32; i++) { 788 if ((1U << i) == x) return i; 789 } 790 return -1; 791 } 792 793 /* Ditto for 64 bit numbers. */ 794 Int VG_(log2_64) ( ULong x ) 795 { 796 Int i; 797 for (i = 0; i < 64; i++) { 798 if ((1ULL << i) == x) return i; 799 } 800 return -1; 801 } 802 803 // Generic quick sort. 804 void VG_(ssort)( void* base, SizeT nmemb, SizeT size, 805 Int (*compar)(void*, void*) ) 806 { 807 bm_qsort(base,nmemb,size,compar); 808 } 809 810 811 // This random number generator is based on the one suggested in Kernighan 812 // and Ritchie's "The C Programming Language". 813 814 // A pseudo-random number generator returning a random UInt. If pSeed 815 // is NULL, it uses its own seed, which starts at zero. If pSeed is 816 // non-NULL, it uses and updates whatever pSeed points at. 817 818 static UInt seed = 0; 819 820 UInt VG_(random)( /*MOD*/UInt* pSeed ) 821 { 822 if (pSeed == NULL) 823 pSeed = &seed; 824 825 *pSeed = (1103515245 * *pSeed + 12345); 826 return *pSeed; 827 } 828 829 /*--------------------------------------------------------------------*/ 830 /*--- end ---*/ 831 /*--------------------------------------------------------------------*/ 832 833