blob: 8628feb9752e2771ddf74696f518e90f99ec2b73 [file] [log] [blame]
njn97405b22005-06-02 03:39:33 +00001
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
sewardj9ebd6e02007-01-08 06:01:59 +000010 Copyright (C) 2000-2007 Julian Seward
njn97405b22005-06-02 03:39:33 +000011 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
njnc7561b92005-06-19 01:24:32 +000031#include "pub_core_basics.h"
njn97405b22005-06-02 03:39:33 +000032#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
53Long VG_(atoll) ( Char* str )
54{
55 Bool neg = False;
56 Long n = 0;
57 if (*str == '-') { str++; neg = True; };
58 while (*str >= '0' && *str <= '9') {
59 n = 10*n + (Long)(*str - '0');
60 str++;
61 }
62 if (neg) n = -n;
63 return n;
64}
65
66Long VG_(atoll36) ( Char* str )
67{
68 Bool neg = False;
69 Long n = 0;
70 if (*str == '-') { str++; neg = True; };
71 while (True) {
72 Char c = *str;
73 if (c >= '0' && c <= (Char)'9') {
74 n = 36*n + (Long)(c - '0');
75 }
76 else
77 if (c >= 'A' && c <= (Char)'Z') {
78 n = 36*n + (Long)((c - 'A') + 10);
79 }
80 else
81 if (c >= 'a' && c <= (Char)'z') {
82 n = 36*n + (Long)((c - 'a') + 10);
83 }
84 else {
85 break;
86 }
87 str++;
88 }
89 if (neg) n = -n;
90 return n;
91}
92
93/* ---------------------------------------------------------------------
94 String functions
95 ------------------------------------------------------------------ */
96
97Int VG_(strlen) ( const Char* str )
98{
99 Int i = 0;
100 while (str[i] != 0) i++;
101 return i;
102}
103
104Char* VG_(strcat) ( Char* dest, const Char* src )
105{
106 Char* dest_orig = dest;
107 while (*dest) dest++;
108 while (*src) *dest++ = *src++;
109 *dest = 0;
110 return dest_orig;
111}
112
113Char* VG_(strncat) ( Char* dest, const Char* src, SizeT n )
114{
115 Char* dest_orig = dest;
116 while (*dest) dest++;
117 while (*src && n > 0) { *dest++ = *src++; n--; }
118 *dest = 0;
119 return dest_orig;
120}
121
122Char* VG_(strpbrk) ( const Char* s, const Char* accept )
123{
124 const Char* a;
125 while (*s) {
126 a = accept;
127 while (*a)
128 if (*a++ == *s)
129 return (Char *) s;
130 s++;
131 }
132 return NULL;
133}
134
135Char* VG_(strcpy) ( Char* dest, const Char* src )
136{
137 Char* dest_orig = dest;
138 while (*src) *dest++ = *src++;
139 *dest = 0;
140 return dest_orig;
141}
142
143/* Copy bytes, not overrunning the end of dest and always ensuring
144 zero termination. */
145void VG_(strncpy_safely) ( Char* dest, const Char* src, SizeT ndest )
146{
147 Int i = 0;
148 while (True) {
149 dest[i] = 0;
150 if (src[i] == 0) return;
151 if (i >= ndest-1) return;
152 dest[i] = src[i];
153 i++;
154 }
155}
156
157Char* VG_(strncpy) ( Char* dest, const Char* src, SizeT ndest )
158{
159 Int i = 0;
160 while (True) {
161 if (i >= ndest) return dest; /* reached limit */
162 dest[i] = src[i];
163 if (src[i++] == 0) {
164 /* reached NUL; pad rest with zeroes as required */
165 while (i < ndest) dest[i++] = 0;
166 return dest;
167 }
168 }
169}
170
171Int VG_(strcmp) ( const Char* s1, const Char* s2 )
172{
173 while (True) {
174 if (*s1 == 0 && *s2 == 0) return 0;
175 if (*s1 == 0) return -1;
176 if (*s2 == 0) return 1;
177
178 if (*(UChar*)s1 < *(UChar*)s2) return -1;
179 if (*(UChar*)s1 > *(UChar*)s2) return 1;
180
181 s1++; s2++;
182 }
183}
184
185static Bool isterm ( Char c )
186{
187 return ( VG_(isspace)(c) || 0 == c );
188}
189
190Int VG_(strcmp_ws) ( const Char* s1, const Char* s2 )
191{
192 while (True) {
193 if (isterm(*s1) && isterm(*s2)) return 0;
194 if (isterm(*s1)) return -1;
195 if (isterm(*s2)) return 1;
196
197 if (*(UChar*)s1 < *(UChar*)s2) return -1;
198 if (*(UChar*)s1 > *(UChar*)s2) return 1;
199
200 s1++; s2++;
201 }
202}
203
204Int VG_(strncmp) ( const Char* s1, const Char* s2, SizeT nmax )
205{
206 Int n = 0;
207 while (True) {
208 if (n >= nmax) return 0;
209 if (*s1 == 0 && *s2 == 0) return 0;
210 if (*s1 == 0) return -1;
211 if (*s2 == 0) return 1;
212
213 if (*(UChar*)s1 < *(UChar*)s2) return -1;
214 if (*(UChar*)s1 > *(UChar*)s2) return 1;
215
216 s1++; s2++; n++;
217 }
218}
219
220Int VG_(strncmp_ws) ( const Char* s1, const Char* s2, SizeT nmax )
221{
222 Int n = 0;
223 while (True) {
224 if (n >= nmax) return 0;
225 if (isterm(*s1) && isterm(*s2)) return 0;
226 if (isterm(*s1)) return -1;
227 if (isterm(*s2)) return 1;
228
229 if (*(UChar*)s1 < *(UChar*)s2) return -1;
230 if (*(UChar*)s1 > *(UChar*)s2) return 1;
231
232 s1++; s2++; n++;
233 }
234}
235
236Char* VG_(strstr) ( const Char* haystack, Char* needle )
237{
238 Int n;
239 if (haystack == NULL)
240 return NULL;
241 n = VG_(strlen)(needle);
242 while (True) {
243 if (haystack[0] == 0)
244 return NULL;
245 if (VG_(strncmp)(haystack, needle, n) == 0)
246 return (Char*)haystack;
247 haystack++;
248 }
249}
250
251Char* VG_(strchr) ( const Char* s, Char c )
252{
253 while (True) {
254 if (*s == c) return (Char*)s;
255 if (*s == 0) return NULL;
256 s++;
257 }
258}
259
260Char* VG_(strrchr) ( const Char* s, Char c )
261{
262 Int n = VG_(strlen)(s);
263 while (--n > 0) {
264 if (s[n] == c) return (Char*)s + n;
265 }
266 return NULL;
267}
268
269/* ---------------------------------------------------------------------
270 A simple string matching routine, purloined from Hugs98.
271 '*' matches any sequence of zero or more characters
272 '?' matches any single character exactly
273 '\c' matches the character c only (ignoring special chars)
274 c matches the character c only
275 ------------------------------------------------------------------ */
276
277/* Keep track of recursion depth. */
278static Int recDepth;
279
280// Nb: vg_assert disabled because we can't use it from this module...
281static Bool string_match_wrk ( const Char* pat, const Char* str )
282{
283 //vg_assert(recDepth >= 0 && recDepth < 500);
284 recDepth++;
285 for (;;) {
286 switch (*pat) {
287 case '\0':recDepth--;
288 return (*str=='\0');
289 case '*': do {
290 if (string_match_wrk(pat+1,str)) {
291 recDepth--;
292 return True;
293 }
294 } while (*str++);
295 recDepth--;
296 return False;
297 case '?': if (*str++=='\0') {
298 recDepth--;
299 return False;
300 }
301 pat++;
302 break;
303 case '\\':if (*++pat == '\0') {
304 recDepth--;
305 return False; /* spurious trailing \ in pattern */
306 }
307 /* falls through to ... */
308 default : if (*pat++ != *str++) {
309 recDepth--;
310 return False;
311 }
312 break;
313 }
314 }
315}
316
317Bool VG_(string_match) ( const Char* pat, const Char* str )
318{
319 Bool b;
320 recDepth = 0;
321 b = string_match_wrk ( pat, str );
322 //vg_assert(recDepth == 0);
323 /*
324 VG_(printf)("%s %s %s\n",
325 b?"TRUE ":"FALSE", pat, str);
326 */
327 return b;
328}
329
330
331/* ---------------------------------------------------------------------
332 mem* functions
333 ------------------------------------------------------------------ */
334
335void* VG_(memcpy) ( void *dest, const void *src, SizeT sz )
336{
sewardj45f4e7c2005-09-27 19:20:21 +0000337 const UChar* s = (const UChar*)src;
338 UChar* d = (UChar*)dest;
339 const UInt* sI = (const UInt*)src;
340 UInt* dI = (UInt*)dest;
341
342 if (VG_IS_4_ALIGNED(dI) && VG_IS_4_ALIGNED(sI)) {
343 while (sz >= 16) {
344 dI[0] = sI[0];
345 dI[1] = sI[1];
346 dI[2] = sI[2];
347 dI[3] = sI[3];
348 sz -= 16;
349 dI += 4;
350 sI += 4;
351 }
352 if (sz == 0)
353 return dest;
354 while (sz >= 4) {
355 dI[0] = sI[0];
356 sz -= 4;
357 dI += 1;
358 sI += 1;
359 }
360 if (sz == 0)
361 return dest;
362 s = (const UChar*)sI;
363 d = (UChar*)dI;
364 }
njn97405b22005-06-02 03:39:33 +0000365
366 while (sz--)
367 *d++ = *s++;
368
369 return dest;
370}
371
372void* VG_(memset) ( void *dest, Int c, SizeT sz )
373{
374 Char *d = (Char *)dest;
sewardj3187a4e2005-12-04 23:27:14 +0000375 while (sz >= 4) {
376 d[0] = c;
377 d[1] = c;
378 d[2] = c;
379 d[3] = c;
380 d += 4;
381 sz -= 4;
382 }
383 while (sz > 0) {
384 d[0] = c;
385 d++;
386 sz--;
387 }
njn97405b22005-06-02 03:39:33 +0000388 return dest;
389}
390
391Int VG_(memcmp) ( const void* s1, const void* s2, SizeT n )
392{
393 Int res;
tom151a6392005-11-11 12:30:36 +0000394 const UChar *p1 = s1;
395 const UChar *p2 = s2;
njn97405b22005-06-02 03:39:33 +0000396 UChar a0;
397 UChar b0;
398
399 while (n != 0) {
tom151a6392005-11-11 12:30:36 +0000400 a0 = p1[0];
401 b0 = p2[0];
402 p1 += 1;
403 p2 += 1;
njn97405b22005-06-02 03:39:33 +0000404 res = a0 - b0;
405 if (res != 0)
406 return res;
407 n -= 1;
408 }
409 return 0;
410}
411
412/* ---------------------------------------------------------------------
413 Misc useful functions
414 ------------------------------------------------------------------ */
415
njncda391f2005-12-22 19:50:45 +0000416/* Returns the base-2 logarithm of x. Returns -1 if x is not a power of two. */
njn97405b22005-06-02 03:39:33 +0000417Int VG_(log2) ( Int x )
418{
419 Int i;
420 /* Any more than 32 and we overflow anyway... */
421 for (i = 0; i < 32; i++) {
422 if (1 << i == x) return i;
423 }
424 return -1;
425}
426
427
428// Generic shell sort. Like stdlib.h's qsort().
429void VG_(ssort)( void* base, SizeT nmemb, SizeT size,
430 Int (*compar)(void*, void*) )
431{
432 Int incs[14] = { 1, 4, 13, 40, 121, 364, 1093, 3280,
433 9841, 29524, 88573, 265720,
434 797161, 2391484 };
435 Int lo = 0;
436 Int hi = nmemb-1;
437 Int i, j, h, bigN, hp;
438
439 bigN = hi - lo + 1; if (bigN < 2) return;
440 hp = 0; while (hp < 14 && incs[hp] < bigN) hp++; hp--;
441
442 #define SORT \
443 for ( ; hp >= 0; hp--) { \
444 h = incs[hp]; \
445 for (i = lo + h; i <= hi; i++) { \
446 ASSIGN(v,0, a,i); \
447 j = i; \
448 while (COMPAR(a,(j-h), v,0) > 0) { \
449 ASSIGN(a,j, a,(j-h)); \
450 j = j - h; \
451 if (j <= (lo + h - 1)) break; \
452 } \
453 ASSIGN(a,j, v,0); \
454 } \
455 }
456
457 // Specialised cases
458 if (sizeof(ULong) == size) {
459
460 #define ASSIGN(dst, dsti, src, srci) \
461 (dst)[(dsti)] = (src)[(srci)];
462
463 #define COMPAR(dst, dsti, src, srci) \
464 compar( (void*)(& (dst)[(dsti)]), (void*)(& (src)[(srci)]) )
465
466 ULong* a = (ULong*)base;
467 ULong v[1];
468
469 SORT;
470
471 } else if (sizeof(UInt) == size) {
472
473 UInt* a = (UInt*)base;
474 UInt v[1];
475
476 SORT;
477
478 } else if (sizeof(UShort) == size) {
479 UShort* a = (UShort*)base;
480 UShort v[1];
481
482 SORT;
483
484 } else if (sizeof(UChar) == size) {
485 UChar* a = (UChar*)base;
486 UChar v[1];
487
488 SORT;
489
490 #undef ASSIGN
491 #undef COMPAR
492
sewardj085f9362007-02-08 16:25:56 +0000493 } else if ( (4*sizeof(UWord)) == size ) {
494 /* special-case 4 word-elements. This captures a lot of cases
495 from symbol table reading/canonicalisaton, because both DiLoc
496 and DiSym are 4 word structures. */
497 HChar* a = base;
498 HChar v[size];
499
500 #define ASSIGN(dst, dsti, src, srci) \
501 do { UWord* dP = (UWord*)&dst[size*(dsti)]; \
502 UWord* sP = (UWord*)&src[size*(srci)]; \
503 dP[0] = sP[0]; \
504 dP[1] = sP[1]; \
505 dP[2] = sP[2]; \
506 dP[3] = sP[3]; \
507 } while (0)
508
509 #define COMPAR(dst, dsti, src, srci) \
510 compar( &dst[size*(dsti)], &src[size*(srci)] )
511
512 SORT;
513
514 #undef ASSIGN
515 #undef COMPAR
516
njn97405b22005-06-02 03:39:33 +0000517 // General case
518 } else {
sewardj085f9362007-02-08 16:25:56 +0000519 HChar* a = base;
520 HChar v[size]; // will be at least 'size' bytes
njn97405b22005-06-02 03:39:33 +0000521
522 #define ASSIGN(dst, dsti, src, srci) \
523 VG_(memcpy)( &dst[size*(dsti)], &src[size*(srci)], size );
524
525 #define COMPAR(dst, dsti, src, srci) \
526 compar( &dst[size*(dsti)], &src[size*(srci)] )
527
528 SORT;
529
530 #undef ASSIGN
531 #undef COMPAR
532 }
533 #undef SORT
534}
535
njn9828b342005-07-08 04:08:59 +0000536// This random number generator is based on the one suggested in Kernighan
537// and Ritchie's "The C Programming Language".
sewardj45f4e7c2005-09-27 19:20:21 +0000538
539// A pseudo-random number generator returning a random UInt. If pSeed
540// is NULL, it uses its own seed, which starts at zero. If pSeed is
541// non-NULL, it uses and updates whatever pSeed points at.
542
543static UInt seed = 0;
544
545UInt VG_(random)( /*MOD*/UInt* pSeed )
njn9828b342005-07-08 04:08:59 +0000546{
sewardj45f4e7c2005-09-27 19:20:21 +0000547 if (pSeed == NULL)
548 pSeed = &seed;
549
550 *pSeed = (1103515245 * *pSeed + 12345);
551 return *pSeed;
njn9828b342005-07-08 04:08:59 +0000552}
553
njn97405b22005-06-02 03:39:33 +0000554/*--------------------------------------------------------------------*/
555/*--- end ---*/
556/*--------------------------------------------------------------------*/
557