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@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 38Bool VG_(isspace) ( Char c ) 39{ 40 return (c == ' ' || c == '\n' || c == '\t' || 41 c == '\f' || c == '\v' || c == '\r'); 42} 43 44Bool VG_(isdigit) ( Char c ) 45{ 46 return (c >= '0' && c <= '9'); 47} 48 49/* --------------------------------------------------------------------- 50 Converting strings to numbers 51 ------------------------------------------------------------------ */ 52 53static 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 59static 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 67Long 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 92ULong 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 117Long 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 150ULong 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 183double 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 216Char 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 229SizeT VG_(strlen) ( const Char* str ) 230{ 231 SizeT i = 0; 232 while (str[i] != 0) i++; 233 return i; 234} 235 236Char* 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 245Char* 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 254Char* 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 267Char* 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. */ 277void 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 289Char* 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 303Int 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 316Int 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 331Int 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 346Int 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 365Char* 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 380Char* 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 395Char* 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 404Char* 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) */ 414static Char *olds; 415Char * 416VG_(strtok) (Char *s, const Char *delim) 417{ 418 return VG_(strtok_r) (s, delim, &olds); 419} 420 421Char * 422VG_(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 452static Bool isHex ( UChar c ) 453{ 454 return ((c >= '0' && c <= '9') || 455 (c >= 'a' && c <= 'f') || 456 (c >= 'A' && c <= 'F')); 457} 458 459static 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 472Bool 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 495SizeT 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 511SizeT 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 528void* 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 565void* 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 583void* 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 618Int 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 674static 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 681static 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 695static 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. */ 783Int 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. */ 794Int 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. 804void 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 818static UInt seed = 0; 819 820UInt 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