blob: f8c4275edd7ed7ce6880268ab7bd78604efcce6f [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
10 Copyright (C) 2000-2005 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
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{
337 const Char *s = (const Char *)src;
338 Char *d = (Char *)dest;
339
340 while (sz--)
341 *d++ = *s++;
342
343 return dest;
344}
345
346void* VG_(memset) ( void *dest, Int c, SizeT sz )
347{
348 Char *d = (Char *)dest;
349
350 while (sz--)
351 *d++ = c;
352
353 return dest;
354}
355
356Int VG_(memcmp) ( const void* s1, const void* s2, SizeT n )
357{
358 Int res;
359 UChar a0;
360 UChar b0;
361
362 while (n != 0) {
363 a0 = ((UChar *) s1)[0];
364 b0 = ((UChar *) s2)[0];
365 s1 += 1;
366 s2 += 1;
367 res = a0 - b0;
368 if (res != 0)
369 return res;
370 n -= 1;
371 }
372 return 0;
373}
374
375/* ---------------------------------------------------------------------
376 Misc useful functions
377 ------------------------------------------------------------------ */
378
379Int VG_(log2) ( Int x )
380{
381 Int i;
382 /* Any more than 32 and we overflow anyway... */
383 for (i = 0; i < 32; i++) {
384 if (1 << i == x) return i;
385 }
386 return -1;
387}
388
389
390// Generic shell sort. Like stdlib.h's qsort().
391void VG_(ssort)( void* base, SizeT nmemb, SizeT size,
392 Int (*compar)(void*, void*) )
393{
394 Int incs[14] = { 1, 4, 13, 40, 121, 364, 1093, 3280,
395 9841, 29524, 88573, 265720,
396 797161, 2391484 };
397 Int lo = 0;
398 Int hi = nmemb-1;
399 Int i, j, h, bigN, hp;
400
401 bigN = hi - lo + 1; if (bigN < 2) return;
402 hp = 0; while (hp < 14 && incs[hp] < bigN) hp++; hp--;
403
404 #define SORT \
405 for ( ; hp >= 0; hp--) { \
406 h = incs[hp]; \
407 for (i = lo + h; i <= hi; i++) { \
408 ASSIGN(v,0, a,i); \
409 j = i; \
410 while (COMPAR(a,(j-h), v,0) > 0) { \
411 ASSIGN(a,j, a,(j-h)); \
412 j = j - h; \
413 if (j <= (lo + h - 1)) break; \
414 } \
415 ASSIGN(a,j, v,0); \
416 } \
417 }
418
419 // Specialised cases
420 if (sizeof(ULong) == size) {
421
422 #define ASSIGN(dst, dsti, src, srci) \
423 (dst)[(dsti)] = (src)[(srci)];
424
425 #define COMPAR(dst, dsti, src, srci) \
426 compar( (void*)(& (dst)[(dsti)]), (void*)(& (src)[(srci)]) )
427
428 ULong* a = (ULong*)base;
429 ULong v[1];
430
431 SORT;
432
433 } else if (sizeof(UInt) == size) {
434
435 UInt* a = (UInt*)base;
436 UInt v[1];
437
438 SORT;
439
440 } else if (sizeof(UShort) == size) {
441 UShort* a = (UShort*)base;
442 UShort v[1];
443
444 SORT;
445
446 } else if (sizeof(UChar) == size) {
447 UChar* a = (UChar*)base;
448 UChar v[1];
449
450 SORT;
451
452 #undef ASSIGN
453 #undef COMPAR
454
455 // General case
456 } else {
457 char* a = base;
458 char v[size]; // will be at least 'size' bytes
459
460 #define ASSIGN(dst, dsti, src, srci) \
461 VG_(memcpy)( &dst[size*(dsti)], &src[size*(srci)], size );
462
463 #define COMPAR(dst, dsti, src, srci) \
464 compar( &dst[size*(dsti)], &src[size*(srci)] )
465
466 SORT;
467
468 #undef ASSIGN
469 #undef COMPAR
470 }
471 #undef SORT
472}
473
njn9828b342005-07-08 04:08:59 +0000474static UInt seed = 0;
475
476void VG_(srandom)(UInt s)
477{
478 seed = s;
479}
480
481// This random number generator is based on the one suggested in Kernighan
482// and Ritchie's "The C Programming Language".
483UInt VG_(random)(void)
484{
485 seed = (1103515245*seed + 12345);
486 return seed;
487}
488
njn97405b22005-06-02 03:39:33 +0000489/*--------------------------------------------------------------------*/
490/*--- end ---*/
491/*--------------------------------------------------------------------*/
492