diff options
Diffstat (limited to 'util.c')
-rw-r--r-- | util.c | 208 |
1 files changed, 106 insertions, 102 deletions
@@ -13,6 +13,10 @@ # define MINGW_HAS_SECURE_API 1 #endif +#ifndef __STDC_WANT_LIB_EXT1__ +#define __STDC_WANT_LIB_EXT1__ 1 /* for qsort_s() */ +#endif + #include "ruby/internal/config.h" #include <ctype.h> @@ -45,10 +49,10 @@ ruby_scan_oct(const char *start, size_t len, size_t *retlen) if ((s[0] < '0') || ('7' < s[0])) { break; } - retval <<= 3; - retval |= *s++ - '0'; + retval <<= 3; + retval |= *s++ - '0'; } - *retlen = (int)(s - start); /* less than len */ + *retlen = (size_t)(s - start); return retval; } @@ -57,22 +61,19 @@ ruby_scan_hex(const char *start, size_t len, size_t *retlen) { register const char *s = start; register unsigned long retval = 0; - const char *tmp; + signed char d; size_t i = 0; for (i = 0; i < len; i++) { - if (! s[0]) { + d = ruby_digit36_to_number_table[(unsigned char)*s]; + if (d < 0 || 15 < d) { break; } - tmp = strchr(hexdigit, *s); - if (! tmp) { - break; - } - retval <<= 4; - retval |= (tmp - hexdigit) & 15; - s++; + retval <<= 4; + retval |= d; + s++; } - *retlen = (int)(s - start); /* less than len */ + *retlen = (size_t)(s - start); return retval; } @@ -100,6 +101,8 @@ NO_SANITIZE("unsigned-integer-overflow", extern unsigned long ruby_scan_digits(c unsigned long ruby_scan_digits(const char *str, ssize_t len, int base, size_t *retlen, int *overflow) { + RBIMPL_ASSERT_OR_ASSUME(base >= 2); + RBIMPL_ASSERT_OR_ASSUME(base <= 36); const char *start = str; unsigned long ret = 0, x; @@ -108,15 +111,15 @@ ruby_scan_digits(const char *str, ssize_t len, int base, size_t *retlen, int *ov *overflow = 0; if (!len) { - *retlen = 0; - return 0; + *retlen = 0; + return 0; } do { - int d = ruby_digit36_to_number_table[(unsigned char)*str++]; + int d = ruby_digit36_to_number_table[(unsigned char)*str++]; if (d == -1 || base <= d) { - --str; - break; + --str; + break; } if (mul_overflow < ret) *overflow = 1; @@ -139,6 +142,11 @@ ruby_strtoul(const char *str, char **endptr, int base) unsigned long ret; const char *subject_found = str; + if (base < 0) { + errno = EINVAL; + return 0; + } + if (base == 1 || 36 < base) { errno = EINVAL; return 0; @@ -199,18 +207,12 @@ ruby_strtoul(const char *str, char **endptr, int base) } } +#if !defined HAVE_GNU_QSORT_R #include <sys/types.h> -#include <sys/stat.h> +#include <stdint.h> #ifdef HAVE_UNISTD_H #include <unistd.h> #endif -#if defined(HAVE_FCNTL_H) -#include <fcntl.h> -#endif - -#ifndef S_ISDIR -# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) -#endif typedef int (cmpfunc_t)(const void*, const void*, void*); @@ -259,7 +261,7 @@ ruby_qsort(void* base, const size_t nel, const size_t size, cmpfunc_t *cmp, void qsort_s(base, nel, size, cmp, d); } # define HAVE_GNU_QSORT_R 1 -#elif !defined HAVE_GNU_QSORT_R +#else /* mm.c */ #define mmtype long @@ -400,7 +402,8 @@ ruby_qsort(void* base, const size_t nel, const size_t size, cmpfunc_t *cmp, void for (;;) { start: if (L + size == R) { /* 2 elements */ - if ((*cmp)(L,R,d) > 0) mmswap(L,R); goto nxt; + if ((*cmp)(L,R,d) > 0) mmswap(L,R); + goto nxt; } l = L; r = R; @@ -411,57 +414,57 @@ ruby_qsort(void* base, const size_t nel, const size_t size, cmpfunc_t *cmp, void register char *m1; register char *m3; if (n >= 200) { - n = size*(n>>3); /* number of bytes in splitting 8 */ - { - register char *p1 = l + n; - register char *p2 = p1 + n; - register char *p3 = p2 + n; - m1 = med3(p1, p2, p3); - p1 = m + n; - p2 = p1 + n; - p3 = p2 + n; - m3 = med3(p1, p2, p3); - } + n = size*(n>>3); /* number of bytes in splitting 8 */ + { + register char *p1 = l + n; + register char *p2 = p1 + n; + register char *p3 = p2 + n; + m1 = med3(p1, p2, p3); + p1 = m + n; + p2 = p1 + n; + p3 = p2 + n; + m3 = med3(p1, p2, p3); + } } else { - n = size*(n>>2); /* number of bytes in splitting 4 */ - m1 = l + n; - m3 = m + n; + n = size*(n>>2); /* number of bytes in splitting 4 */ + m1 = l + n; + m3 = m + n; } m = med3(m1, m, m3); } if ((t = (*cmp)(l,m,d)) < 0) { /*3-5-?*/ if ((t = (*cmp)(m,r,d)) < 0) { /*3-5-7*/ - if (chklim && nel >= chklim) { /* check if already ascending order */ - char *p; - chklim = 0; - for (p=l; p<r; p+=size) if ((*cmp)(p,p+size,d) > 0) goto fail; - goto nxt; - } - fail: goto loopA; /*3-5-7*/ + if (chklim && nel >= chklim) { /* check if already ascending order */ + char *p; + chklim = 0; + for (p=l; p<r; p+=size) if ((*cmp)(p,p+size,d) > 0) goto fail; + goto nxt; + } + fail: goto loopA; /*3-5-7*/ } if (t > 0) { - if ((*cmp)(l,r,d) <= 0) {mmswap(m,r); goto loopA;} /*3-5-4*/ - mmrot3(r,m,l); goto loopA; /*3-5-2*/ + if ((*cmp)(l,r,d) <= 0) {mmswap(m,r); goto loopA;} /*3-5-4*/ + mmrot3(r,m,l); goto loopA; /*3-5-2*/ } goto loopB; /*3-5-5*/ } if (t > 0) { /*7-5-?*/ if ((t = (*cmp)(m,r,d)) > 0) { /*7-5-3*/ - if (chklim && nel >= chklim) { /* check if already ascending order */ - char *p; - chklim = 0; - for (p=l; p<r; p+=size) if ((*cmp)(p,p+size,d) < 0) goto fail2; - while (l<r) {mmswap(l,r); l+=size; r-=size;} /* reverse region */ - goto nxt; - } - fail2: mmswap(l,r); goto loopA; /*7-5-3*/ + if (chklim && nel >= chklim) { /* check if already ascending order */ + char *p; + chklim = 0; + for (p=l; p<r; p+=size) if ((*cmp)(p,p+size,d) < 0) goto fail2; + while (l<r) {mmswap(l,r); l+=size; r-=size;} /* reverse region */ + goto nxt; + } + fail2: mmswap(l,r); goto loopA; /*7-5-3*/ } if (t < 0) { - if ((*cmp)(l,r,d) <= 0) {mmswap(l,m); goto loopB;} /*7-5-8*/ - mmrot3(l,m,r); goto loopA; /*7-5-6*/ + if ((*cmp)(l,r,d) <= 0) {mmswap(l,m); goto loopB;} /*7-5-8*/ + mmrot3(l,m,r); goto loopA; /*7-5-6*/ } mmswap(l,r); goto loopA; /*7-5-5*/ } @@ -480,18 +483,18 @@ ruby_qsort(void* base, const size_t nel, const size_t size, cmpfunc_t *cmp, void loopA: eq_l = 1; eq_r = 1; /* splitting type A */ /* left <= median < right */ for (;;) { for (;;) { - if ((l += size) == r) - {l -= size; if (l != m) mmswap(m,l); l -= size; goto fin;} - if (l == m) continue; - if ((t = (*cmp)(l,m,d)) > 0) {eq_r = 0; break;} - if (t < 0) eq_l = 0; + if ((l += size) == r) + {l -= size; if (l != m) mmswap(m,l); l -= size; goto fin;} + if (l == m) continue; + if ((t = (*cmp)(l,m,d)) > 0) {eq_r = 0; break;} + if (t < 0) eq_l = 0; } for (;;) { - if (l == (r -= size)) - {l -= size; if (l != m) mmswap(m,l); l -= size; goto fin;} - if (r == m) {m = l; break;} - if ((t = (*cmp)(r,m,d)) < 0) {eq_l = 0; break;} - if (t == 0) break; + if (l == (r -= size)) + {l -= size; if (l != m) mmswap(m,l); l -= size; goto fin;} + if (r == m) {m = l; break;} + if ((t = (*cmp)(r,m,d)) < 0) {eq_l = 0; break;} + if (t == 0) break; } mmswap(l,r); /* swap left and right */ } @@ -499,18 +502,18 @@ ruby_qsort(void* base, const size_t nel, const size_t size, cmpfunc_t *cmp, void loopB: eq_l = 1; eq_r = 1; /* splitting type B */ /* left < median <= right */ for (;;) { for (;;) { - if (l == (r -= size)) - {r += size; if (r != m) mmswap(r,m); r += size; goto fin;} - if (r == m) continue; - if ((t = (*cmp)(r,m,d)) < 0) {eq_l = 0; break;} - if (t > 0) eq_r = 0; + if (l == (r -= size)) + {r += size; if (r != m) mmswap(r,m); r += size; goto fin;} + if (r == m) continue; + if ((t = (*cmp)(r,m,d)) < 0) {eq_l = 0; break;} + if (t > 0) eq_r = 0; } for (;;) { - if ((l += size) == r) - {r += size; if (r != m) mmswap(r,m); r += size; goto fin;} - if (l == m) {m = r; break;} - if ((t = (*cmp)(l,m,d)) > 0) {eq_r = 0; break;} - if (t == 0) break; + if ((l += size) == r) + {r += size; if (r != m) mmswap(r,m); r += size; goto fin;} + if (l == m) {m = r; break;} + if ((t = (*cmp)(l,m,d)) > 0) {eq_r = 0; break;} + if (t == 0) break; } mmswap(l,r); /* swap left and right */ } @@ -518,14 +521,15 @@ ruby_qsort(void* base, const size_t nel, const size_t size, cmpfunc_t *cmp, void fin: if (eq_l == 0) /* need to sort left side */ if (eq_r == 0) /* need to sort right side */ - if (l-L < R-r) {PUSH(r,R); R = l;} /* sort left side first */ - else {PUSH(L,l); L = r;} /* sort right side first */ + if (l-L < R-r) {PUSH(r,R); R = l;} /* sort left side first */ + else {PUSH(L,l); L = r;} /* sort right side first */ else R = l; /* need to sort left side only */ else if (eq_r == 0) L = r; /* need to sort right side only */ else goto nxt; /* need not to sort both sides */ } } -#endif /* HAVE_GNU_QSORT_R */ +#endif +#endif /* !HAVE_GNU_QSORT_R */ char * ruby_strdup(const char *str) @@ -551,15 +555,15 @@ ruby_getcwd(void) char *buf = xmalloc(size); while (!getcwd(buf, size)) { - int e = errno; - if (e != ERANGE) { - xfree(buf); - DATA_PTR(guard) = NULL; - rb_syserr_fail(e, "getcwd"); - } - size *= 2; - DATA_PTR(guard) = buf; - buf = xrealloc(buf, size); + int e = errno; + if (e != ERANGE) { + xfree(buf); + DATA_PTR(guard) = NULL; + rb_syserr_fail(e, "getcwd"); + } + size *= 2; + DATA_PTR(guard) = buf; + buf = xrealloc(buf, size); } # else VALUE guard = Data_Wrap_Struct((VALUE)0, NULL, free, NULL); @@ -577,9 +581,9 @@ ruby_getcwd(void) char *buf = xmalloc(PATH_MAX+1); if (!getwd(buf)) { - int e = errno; - xfree(buf); - rb_syserr_fail(e, "getwd"); + int e = errno; + xfree(buf); + rb_syserr_fail(e, "getwd"); } #endif return buf; @@ -593,12 +597,12 @@ ruby_each_words(const char *str, void (*func)(const char*, int, void*), void *ar if (!str) return; for (; *str; str = end) { - while (ISSPACE(*str) || *str == ',') str++; - if (!*str) break; - end = str; - while (*end && !ISSPACE(*end) && *end != ',') end++; - len = (int)(end - str); /* assume no string exceeds INT_MAX */ - (*func)(str, len, arg); + while (ISSPACE(*str) || *str == ',') str++; + if (!*str) break; + end = str; + while (*end && !ISSPACE(*end) && *end != ',') end++; + len = (int)(end - str); /* assume no string exceeds INT_MAX */ + (*func)(str, len, arg); } } |