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,
96NO_SANITIZE(
"unsigned-integer-overflow",
extern unsigned long 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>
211#if defined(HAVE_FCNTL_H)
216# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
219typedef int (cmpfunc_t)(
const void*,
const void*,
void*);
221#if !defined HAVE_GNU_QSORT_R
222#if defined HAVE_QSORT_S && defined RUBY_MSVCRT_VERSION
226# define qsort_r(base, nel, size, arg, cmp) qsort_s(base, nel, size, cmp, arg)
227# define cmp_bsd_qsort cmp_ms_qsort
228# define HAVE_BSD_QSORT_R 1
231#if defined HAVE_BSD_QSORT_R
232struct bsd_qsort_r_args {
238cmp_bsd_qsort(
void *d,
const void *a,
const void *b)
240 const struct bsd_qsort_r_args *args = d;
241 return (*args->cmp)(a, b, args->arg);
245ruby_qsort(
void* base,
const size_t nel,
const size_t size, cmpfunc_t *cmp,
void *d)
247 struct bsd_qsort_r_args args;
250 qsort_r(base, nel, size, &args, cmp_bsd_qsort);
252#elif defined HAVE_QSORT_S
256ruby_qsort(
void* base,
const size_t nel,
const size_t size, cmpfunc_t *cmp,
void *d)
258 if (!nel || !size)
return;
261 if (!base || !cmp)
return;
262 if (nel > RSIZE_MAX || size > RSIZE_MAX)
return;
264 qsort_s(base, nel, size, cmp, d);
266# define HAVE_GNU_QSORT_R 1
271#define mmcount (16 / SIZEOF_LONG)
272#define A ((mmtype*)a)
273#define B ((mmtype*)b)
274#define C ((mmtype*)c)
275#define D ((mmtype*)d)
277#define mmstep (sizeof(mmtype) * mmcount)
278#define mmprepare(base, size) do {\
279 if (((VALUE)(base) % sizeof(mmtype)) == 0 && ((size) % sizeof(mmtype)) == 0) \
280 if ((size) >= mmstep) mmkind = 1;\
283 high = ((size) / mmstep) * mmstep;\
284 low = ((size) % mmstep);\
287#define mmarg mmkind, size, high, low
288#define mmargdecl int mmkind, size_t size, size_t high, size_t low
290static void mmswap_(
register char *a,
register char *b, mmargdecl)
297 register char *t = a + high;
299 s = A[0]; A[0] = B[0]; B[0] = s;
300 s = A[1]; A[1] = B[1]; B[1] = s;
302 s = A[2]; A[2] = B[2]; B[2] = s;
304 s = A[3]; A[3] = B[3]; B[3] = s;
307 a += mmstep; b += mmstep;
311 if (low != 0) { s = A[0]; A[0] = B[0]; B[0] = s;
313 if (low >= 2 *
sizeof(mmtype)) { s = A[1]; A[1] = B[1]; B[1] = s;
315 if (low >= 3 *
sizeof(mmtype)) {s = A[2]; A[2] = B[2]; B[2] = s;}
322 register char *t = a + size, s;
323 do {s = *a; *a++ = *b; *b++ = s;}
while (a < t);
326#define mmswap(a,b) mmswap_((a),(b),mmarg)
329static void mmrot3_(
register char *a,
register char *b,
register char *c, mmargdecl)
335 register char *t = a + high;
337 s = A[0]; A[0] = B[0]; B[0] = C[0]; C[0] = s;
338 s = A[1]; A[1] = B[1]; B[1] = C[1]; C[1] = s;
340 s = A[2]; A[2] = B[2]; B[2] = C[2]; C[2] = s;
342 s = A[3]; A[3] = B[3]; B[3] = C[3]; C[3] = s;
345 a += mmstep; b += mmstep; c += mmstep;
349 if (low != 0) { s = A[0]; A[0] = B[0]; B[0] = C[0]; C[0] = s;
351 if (low >= 2 *
sizeof(mmtype)) { s = A[1]; A[1] = B[1]; B[1] = C[1]; C[1] = s;
353 if (low == 3 *
sizeof(mmtype)) {s = A[2]; A[2] = B[2]; B[2] = C[2]; C[2] = s;}
360 register char *t = a + size, s;
361 do {s = *a; *a++ = *b; *b++ = *c; *c++ = s;}
while (a < t);
364#define mmrot3(a,b,c) mmrot3_((a),(b),(c),mmarg)
376#define PUSH(ll,rr) do { top->LL = (ll); top->RR = (rr); ++top; } while (0)
377#define POP(ll,rr) do { --top; (ll) = top->LL; (rr) = top->RR; } while (0)
379#define med3(a,b,c) ((*cmp)((a),(b),d)<0 ? \
380 ((*cmp)((b),(c),d)<0 ? (b) : ((*cmp)((a),(c),d)<0 ? (c) : (a))) : \
381 ((*cmp)((b),(c),d)>0 ? (b) : ((*cmp)((a),(c),d)<0 ? (a) : (c))))
384ruby_qsort(
void* base,
const size_t nel,
const size_t size, cmpfunc_t *cmp,
void *d)
386 register char *l, *r, *m;
387 register int t, eq_l, eq_r;
389 char *R = (
char*)base + size*(nel-1);
391 enum {size_bits =
sizeof(size) * CHAR_BIT};
397 if (nel <= 1)
return;
398 mmprepare(base, size);
402 if (stack == top)
return;
408 if ((*cmp)(L,R,d) > 0) mmswap(L,R);
413 n = (r - l + size) / size;
414 m = l + size * (n >> 1);
422 register char *p1 = l + n;
423 register char *p2 = p1 + n;
424 register char *p3 = p2 + n;
425 m1 = med3(p1, p2, p3);
429 m3 = med3(p1, p2, p3);
440 if ((t = (*cmp)(l,m,d)) < 0) {
441 if ((t = (*cmp)(m,r,d)) < 0) {
442 if (chklim && nel >= chklim) {
445 for (p=l; p<r; p+=size)
if ((*cmp)(p,p+size,d) > 0)
goto fail;
451 if ((*cmp)(l,r,d) <= 0) {mmswap(m,r);
goto loopA;}
452 mmrot3(r,m,l);
goto loopA;
458 if ((t = (*cmp)(m,r,d)) > 0) {
459 if (chklim && nel >= chklim) {
462 for (p=l; p<r; p+=size)
if ((*cmp)(p,p+size,d) < 0)
goto fail2;
463 while (l<r) {mmswap(l,r); l+=size; r-=size;}
466 fail2: mmswap(l,r);
goto loopA;
469 if ((*cmp)(l,r,d) <= 0) {mmswap(l,m);
goto loopB;}
470 mmrot3(l,m,r);
goto loopA;
472 mmswap(l,r);
goto loopA;
475 if ((t = (*cmp)(m,r,d)) < 0) {
goto loopA;}
476 if (t > 0) {mmswap(l,r);
goto loopB;}
480 if ((l += size) == r)
goto nxt;
481 if (l == m)
continue;
482 if ((t = (*cmp)(l,m,d)) > 0) {mmswap(l,r); l = L;
goto loopA;}
483 if (t < 0) {mmswap(L,l); l = L;
goto loopB;}
486 loopA: eq_l = 1; eq_r = 1;
489 if ((l += size) == r)
490 {l -= size;
if (l != m) mmswap(m,l); l -= size;
goto fin;}
491 if (l == m)
continue;
492 if ((t = (*cmp)(l,m,d)) > 0) {eq_r = 0;
break;}
496 if (l == (r -= size))
497 {l -= size;
if (l != m) mmswap(m,l); l -= size;
goto fin;}
498 if (r == m) {m = l;
break;}
499 if ((t = (*cmp)(r,m,d)) < 0) {eq_l = 0;
break;}
505 loopB: eq_l = 1; eq_r = 1;
508 if (l == (r -= size))
509 {r += size;
if (r != m) mmswap(r,m); r += size;
goto fin;}
510 if (r == m)
continue;
511 if ((t = (*cmp)(r,m,d)) < 0) {eq_l = 0;
break;}
515 if ((l += size) == r)
516 {r += size;
if (r != m) mmswap(r,m); r += size;
goto fin;}
517 if (l == m) {m = r;
break;}
518 if ((t = (*cmp)(l,m,d)) > 0) {eq_r = 0;
break;}
527 if (l-L < R-r) {PUSH(r,R); R = l;}
528 else {PUSH(L,l); L = r;}
530 else if (eq_r == 0) L = r;
541 size_t len = strlen(str) + 1;
544 memcpy(tmp, str, len);
552#if defined HAVE_GETCWD
553# undef RUBY_UNTYPED_DATA_WARNING
554# define RUBY_UNTYPED_DATA_WARNING 0
555# if defined NO_GETCWD_MALLOC
560 while (!getcwd(buf, size)) {
573 char *buf, *cwd = getcwd(NULL, 0);
582# define PATH_MAX 8192
584 char *buf =
xmalloc(PATH_MAX+1);
596ruby_each_words(
const char *str,
void (*func)(
const char*,
int,
void*),
void *arg)
602 for (; *str; str = end) {
603 while (
ISSPACE(*str) || *str ==
',') str++;
606 while (*end && !
ISSPACE(*end) && *end !=
',') end++;
607 len = (int)(end - str);
608 (*func)(str, len, arg);
613#define strtod ruby_strtod
615#define dtoa ruby_dtoa
617#define hdtoa ruby_hdtoa
618#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.
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'->11etc.
char * ruby_strdup(const char *str)
This is our own version of strdup(3) that uses ruby_xmalloc() instead of system malloc (benefits our ...
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".
void ruby_qsort(void *, const size_t, const size_t, int(*)(const void *, const void *, void *), void *)
Reentrant implementation of quick sort.
char * ruby_getcwd(void)
This is our own version of getcwd(3) that uses ruby_xmalloc() instead of system malloc (benefits our ...
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.