summaryrefslogtreecommitdiff
path: root/util.c
diff options
context:
space:
mode:
Diffstat (limited to 'util.c')
-rw-r--r--util.c208
1 files changed, 106 insertions, 102 deletions
diff --git a/util.c b/util.c
index 8ec0cd60e5..3c08879ce5 100644
--- a/util.c
+++ b/util.c
@@ -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);
}
}