12 #if defined __MINGW32__ || defined __MINGW64__
13 # define MINGW_HAS_SECURE_API 1
16 #include "ruby/internal/config.h"
25 # include "missing/file.h"
29 #include "internal/sanitizers.h"
30 #include "internal/util.h"
32 #include "ruby_atomic.h"
35 #define hexdigit ruby_hexdigits
40 register const char *s = start;
41 register unsigned long retval = 0;
44 for (i = 0; i < len; i++) {
45 if ((s[0] <
'0') || (
'7' < s[0])) {
51 *retlen = (size_t)(s - start);
58 register const char *s = start;
59 register unsigned long retval = 0;
63 for (i = 0; i < len; i++) {
65 if (d < 0 || 15 < d) {
72 *retlen = (size_t)(s - start);
78 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
79 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
80 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
81 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1,-1,-1,-1,-1,
82 -1,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,
83 25,26,27,28,29,30,31,32,33,34,35,-1,-1,-1,-1,-1,
84 -1,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,
85 25,26,27,28,29,30,31,32,33,34,35,-1,-1,-1,-1,-1,
86 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
87 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
88 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
89 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
90 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
91 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
92 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
93 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
96 NO_SANITIZE(
"unsigned-integer-overflow",
extern unsigned long ruby_scan_digits(
const char *str, ssize_t len,
int base,
size_t *retlen,
int *overflow));
98 ruby_scan_digits(
const char *str, ssize_t len,
int base,
size_t *retlen,
int *overflow)
103 const char *start = str;
104 unsigned long ret = 0, x;
105 unsigned long mul_overflow = (~(
unsigned long)0) / base;
116 if (d == -1 || base <= d) {
120 if (mul_overflow < ret)
127 }
while (len < 0 || --len);
128 *retlen = str - start;
139 const char *subject_found = str;
146 if (base == 1 || 36 < base) {
151 while ((c = *str) &&
ISSPACE(c))
164 subject_found = str+1;
165 if (base == 0 || base == 16) {
166 if (str[1] ==
'x' || str[1] ==
'X') {
171 b = base == 0 ? 8 : 16;
181 b = base == 0 ? 10 : base;
187 subject_found = str+len;
190 *endptr = (
char*)subject_found;
198 ret = (
unsigned long)(-(
long)ret);
206 #include <sys/types.h>
207 #include <sys/stat.h>
211 #if defined(HAVE_FCNTL_H)
216 # define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
219 typedef int (cmpfunc_t)(
const void*,
const void*,
void*);
221 #if defined HAVE_QSORT_S && defined RUBY_MSVCRT_VERSION
225 # define qsort_r(base, nel, size, arg, cmp) qsort_s(base, nel, size, cmp, arg)
226 # define cmp_bsd_qsort cmp_ms_qsort
227 # define HAVE_BSD_QSORT_R 1
230 #if defined HAVE_BSD_QSORT_R
231 struct bsd_qsort_r_args {
237 cmp_bsd_qsort(
void *d,
const void *a,
const void *b)
239 const struct bsd_qsort_r_args *args = d;
240 return (*args->cmp)(a, b, args->arg);
244 ruby_qsort(
void* base,
const size_t nel,
const size_t size, cmpfunc_t *cmp,
void *d)
246 struct bsd_qsort_r_args args;
249 qsort_r(base, nel, size, &args, cmp_bsd_qsort);
251 #elif defined HAVE_QSORT_S
255 ruby_qsort(
void* base,
const size_t nel,
const size_t size, cmpfunc_t *cmp,
void *d)
257 if (!nel || !size)
return;
260 if (!base || !cmp)
return;
261 if (nel > RSIZE_MAX || size > RSIZE_MAX)
return;
263 qsort_s(base, nel, size, cmp, d);
265 # define HAVE_GNU_QSORT_R 1
266 #elif !defined HAVE_GNU_QSORT_R
270 #define mmcount (16 / SIZEOF_LONG)
271 #define A ((mmtype*)a)
272 #define B ((mmtype*)b)
273 #define C ((mmtype*)c)
274 #define D ((mmtype*)d)
276 #define mmstep (sizeof(mmtype) * mmcount)
277 #define mmprepare(base, size) do {\
278 if (((VALUE)(base) % sizeof(mmtype)) == 0 && ((size) % sizeof(mmtype)) == 0) \
279 if ((size) >= mmstep) mmkind = 1;\
282 high = ((size) / mmstep) * mmstep;\
283 low = ((size) % mmstep);\
286 #define mmarg mmkind, size, high, low
287 #define mmargdecl int mmkind, size_t size, size_t high, size_t low
289 static void mmswap_(
register char *a,
register char *b, mmargdecl)
296 register char *t = a + high;
298 s = A[0]; A[0] = B[0]; B[0] = s;
299 s = A[1]; A[1] = B[1]; B[1] = s;
301 s = A[2]; A[2] = B[2]; B[2] = s;
303 s = A[3]; A[3] = B[3]; B[3] = s;
306 a += mmstep; b += mmstep;
310 if (low != 0) { s = A[0]; A[0] = B[0]; B[0] = s;
312 if (low >= 2 *
sizeof(mmtype)) { s = A[1]; A[1] = B[1]; B[1] = s;
314 if (low >= 3 *
sizeof(mmtype)) {s = A[2]; A[2] = B[2]; B[2] = s;}
321 register char *t = a + size, s;
322 do {s = *a; *a++ = *b; *b++ = s;}
while (a < t);
325 #define mmswap(a,b) mmswap_((a),(b),mmarg)
328 static void mmrot3_(
register char *a,
register char *b,
register char *c, mmargdecl)
334 register char *t = a + high;
336 s = A[0]; A[0] = B[0]; B[0] = C[0]; C[0] = s;
337 s = A[1]; A[1] = B[1]; B[1] = C[1]; C[1] = s;
339 s = A[2]; A[2] = B[2]; B[2] = C[2]; C[2] = s;
341 s = A[3]; A[3] = B[3]; B[3] = C[3]; C[3] = s;
344 a += mmstep; b += mmstep; c += mmstep;
348 if (low != 0) { s = A[0]; A[0] = B[0]; B[0] = C[0]; C[0] = s;
350 if (low >= 2 *
sizeof(mmtype)) { s = A[1]; A[1] = B[1]; B[1] = C[1]; C[1] = s;
352 if (low == 3 *
sizeof(mmtype)) {s = A[2]; A[2] = B[2]; B[2] = C[2]; C[2] = s;}
359 register char *t = a + size, s;
360 do {s = *a; *a++ = *b; *b++ = *c; *c++ = s;}
while (a < t);
363 #define mmrot3(a,b,c) mmrot3_((a),(b),(c),mmarg)
375 #define PUSH(ll,rr) do { top->LL = (ll); top->RR = (rr); ++top; } while (0)
376 #define POP(ll,rr) do { --top; (ll) = top->LL; (rr) = top->RR; } while (0)
378 #define med3(a,b,c) ((*cmp)((a),(b),d)<0 ? \
379 ((*cmp)((b),(c),d)<0 ? (b) : ((*cmp)((a),(c),d)<0 ? (c) : (a))) : \
380 ((*cmp)((b),(c),d)>0 ? (b) : ((*cmp)((a),(c),d)<0 ? (a) : (c))))
383 ruby_qsort(
void* base,
const size_t nel,
const size_t size, cmpfunc_t *cmp,
void *d)
385 register char *l, *r, *m;
386 register int t, eq_l, eq_r;
388 char *R = (
char*)base + size*(nel-1);
390 enum {size_bits =
sizeof(size) * CHAR_BIT};
396 if (nel <= 1)
return;
397 mmprepare(base, size);
401 if (stack == top)
return;
407 if ((*cmp)(L,R,d) > 0) mmswap(L,R);
412 n = (r - l + size) / size;
413 m = l + size * (n >> 1);
421 register char *p1 = l + n;
422 register char *p2 = p1 + n;
423 register char *p3 = p2 + n;
424 m1 = med3(p1, p2, p3);
428 m3 = med3(p1, p2, p3);
439 if ((t = (*cmp)(l,m,d)) < 0) {
440 if ((t = (*cmp)(m,r,d)) < 0) {
441 if (chklim && nel >= chklim) {
444 for (p=l; p<r; p+=size)
if ((*cmp)(p,p+size,d) > 0)
goto fail;
450 if ((*cmp)(l,r,d) <= 0) {mmswap(m,r);
goto loopA;}
451 mmrot3(r,m,l);
goto loopA;
457 if ((t = (*cmp)(m,r,d)) > 0) {
458 if (chklim && nel >= chklim) {
461 for (p=l; p<r; p+=size)
if ((*cmp)(p,p+size,d) < 0)
goto fail2;
462 while (l<r) {mmswap(l,r); l+=size; r-=size;}
465 fail2: mmswap(l,r);
goto loopA;
468 if ((*cmp)(l,r,d) <= 0) {mmswap(l,m);
goto loopB;}
469 mmrot3(l,m,r);
goto loopA;
471 mmswap(l,r);
goto loopA;
474 if ((t = (*cmp)(m,r,d)) < 0) {
goto loopA;}
475 if (t > 0) {mmswap(l,r);
goto loopB;}
479 if ((l += size) == r)
goto nxt;
480 if (l == m)
continue;
481 if ((t = (*cmp)(l,m,d)) > 0) {mmswap(l,r); l = L;
goto loopA;}
482 if (t < 0) {mmswap(L,l); l = L;
goto loopB;}
485 loopA: eq_l = 1; eq_r = 1;
488 if ((l += size) == r)
489 {l -= size;
if (l != m) mmswap(m,l); l -= size;
goto fin;}
490 if (l == m)
continue;
491 if ((t = (*cmp)(l,m,d)) > 0) {eq_r = 0;
break;}
495 if (l == (r -= size))
496 {l -= size;
if (l != m) mmswap(m,l); l -= size;
goto fin;}
497 if (r == m) {m = l;
break;}
498 if ((t = (*cmp)(r,m,d)) < 0) {eq_l = 0;
break;}
504 loopB: eq_l = 1; eq_r = 1;
507 if (l == (r -= size))
508 {r += size;
if (r != m) mmswap(r,m); r += size;
goto fin;}
509 if (r == m)
continue;
510 if ((t = (*cmp)(r,m,d)) < 0) {eq_l = 0;
break;}
514 if ((l += size) == r)
515 {r += size;
if (r != m) mmswap(r,m); r += size;
goto fin;}
516 if (l == m) {m = r;
break;}
517 if ((t = (*cmp)(l,m,d)) > 0) {eq_r = 0;
break;}
526 if (l-L < R-r) {PUSH(r,R); R = l;}
527 else {PUSH(L,l); L = r;}
529 else if (eq_r == 0) L = r;
539 size_t len = strlen(str) + 1;
542 memcpy(tmp, str, len);
550 #if defined HAVE_GETCWD
551 # undef RUBY_UNTYPED_DATA_WARNING
552 # define RUBY_UNTYPED_DATA_WARNING 0
553 # if defined NO_GETCWD_MALLOC
558 while (!getcwd(buf, size)) {
571 char *buf, *cwd = getcwd(NULL, 0);
580 # define PATH_MAX 8192
582 char *buf =
xmalloc(PATH_MAX+1);
594 ruby_each_words(
const char *str,
void (*func)(
const char*,
int,
void*),
void *arg)
600 for (; *str; str = end) {
601 while (
ISSPACE(*str) || *str ==
',') str++;
604 while (*end && !
ISSPACE(*end) && *end !=
',') end++;
605 len = (int)(end - str);
606 (*func)(str, len, arg);
611 #define strtod ruby_strtod
613 #define dtoa ruby_dtoa
615 #define hdtoa ruby_hdtoa
616 #include "missing/dtoa.c"
#define RBIMPL_ASSERT_OR_ASSUME(expr)
This is either RUBY_ASSERT or RBIMPL_ASSUME, depending on RUBY_DEBUG.
unsigned long ruby_strtoul(const char *str, char **endptr, int base)
Our own locale-insensitive version of strtoul(3).
#define ISSPACE
Old name of rb_isspace.
#define xfree
Old name of ruby_xfree.
#define xrealloc
Old name of ruby_xrealloc.
#define xmalloc
Old name of ruby_xmalloc.
void rb_syserr_fail(int e, const char *mesg)
Raises appropriate exception that represents a C errno.
void rb_sys_fail(const char *mesg)
Converts a C errno into a Ruby exception, then raises it.
char * ruby_strdup(const char *str)
This is our own version of strdup(3) that uses ruby_xmalloc() instead of system malloc (benefits our ...
unsigned long ruby_scan_hex(const char *str, size_t len, size_t *ret)
Interprets the passed string a hexadecimal unsigned integer.
const signed char ruby_digit36_to_number_table[]
Character to number mapping like ‘'a’->10,'b'->11` etc.
void ruby_each_words(const char *str, void(*func)(const char *word, int len, void *argv), void *argv)
Scans the passed string, with calling the callback function every time it encounters a "word".
char * ruby_getcwd(void)
This is our own version of getcwd(3) that uses ruby_xmalloc() instead of system malloc (benefits our ...
void ruby_qsort(void *, const size_t, const size_t, int(*)(const void *, const void *, void *), void *)
Reentrant implementation of quick sort.
const char ruby_hexdigits[]
Characters that Ruby accepts as hexadecimal digits.
unsigned long ruby_scan_oct(const char *str, size_t len, size_t *consumed)
Interprets the passed string as an octal unsigned integer.
unsigned long ruby_scan_digits(const char *str, ssize_t len, int base, size_t *retlen, int *overflow)
Scans the passed string, assuming the string is a textual representation of an integer.
#define RB_GC_GUARD(v)
Prevents premature destruction of local objects.
#define Data_Wrap_Struct(klass, mark, free, sval)
Converts sval, a pointer to your struct, into a Ruby object.
#define DATA_PTR(obj)
Convenient getter macro.
#define RUBY_DEFAULT_FREE
This is a value you can set to RData::dfree.
uintptr_t VALUE
Type that represents a Ruby object.