m_libcbase.c revision 9abd608244d8123868d027f616fa928156615d5a
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-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
31#include "core.h"       // XXX: temporary, for NULL, VG_(), Char, etc
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
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
474/*--------------------------------------------------------------------*/
475/*--- end                                                          ---*/
476/*--------------------------------------------------------------------*/
477
478