12 #if defined __MINGW32__ || defined __MINGW64__
13 # define MINGW_HAS_SECURE_API 1
16 #ifndef __STDC_WANT_LIB_EXT1__
17 #define __STDC_WANT_LIB_EXT1__ 1
20 #include "ruby/internal/config.h"
29 # include "missing/file.h"
33 #include "internal/sanitizers.h"
34 #include "internal/imemo.h"
35 #include "internal/util.h"
37 #include "ruby_atomic.h"
40 #define hexdigit ruby_hexdigits
45 register const char *s = start;
46 register unsigned long retval = 0;
49 for (i = 0; i <
len; i++) {
50 if ((s[0] <
'0') || (
'7' < s[0])) {
56 *retlen = (size_t)(s - start);
63 register const char *s = start;
64 register unsigned long retval = 0;
68 for (i = 0; i <
len; i++) {
70 if (d < 0 || 15 < d) {
77 *retlen = (size_t)(s - start);
83 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
84 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
85 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
86 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1,-1,-1,-1,-1,
87 -1,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,
88 25,26,27,28,29,30,31,32,33,34,35,-1,-1,-1,-1,-1,
89 -1,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,
90 25,26,27,28,29,30,31,32,33,34,35,-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,
94 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
95 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
96 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
97 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
98 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
101 NO_SANITIZE(
"unsigned-integer-overflow",
extern unsigned long ruby_scan_digits(
const char *str, ssize_t
len,
int base,
size_t *retlen,
int *overflow));
108 const char *start = str;
109 unsigned long ret = 0, x;
110 unsigned long mul_overflow = (~(
unsigned long)0) / base;
121 if (d == -1 || base <= d) {
125 if (mul_overflow < ret)
132 }
while (
len < 0 || --
len);
133 *retlen = str - start;
144 const char *subject_found = str;
151 if (base == 1 || 36 < base) {
156 while ((c = *str) &&
ISSPACE(c))
169 subject_found = str+1;
170 if (base == 0 || base == 16) {
171 if (str[1] ==
'x' || str[1] ==
'X') {
176 b = base == 0 ? 8 : 16;
186 b = base == 0 ? 10 : base;
192 subject_found = str+
len;
195 *endptr = (
char*)subject_found;
203 ret = (
unsigned long)(-(
long)ret);
211 #if !defined HAVE_GNU_QSORT_R
212 #include <sys/types.h>
218 typedef int (cmpfunc_t)(
const void*,
const void*,
void*);
220 #if defined HAVE_QSORT_S && defined RUBY_MSVCRT_VERSION
224 # define qsort_r(base, nel, size, arg, cmp) qsort_s(base, nel, size, cmp, arg)
225 # define cmp_bsd_qsort cmp_ms_qsort
226 # define HAVE_BSD_QSORT_R 1
229 #if defined HAVE_BSD_QSORT_R
230 struct bsd_qsort_r_args {
236 cmp_bsd_qsort(
void *d,
const void *a,
const void *b)
238 const struct bsd_qsort_r_args *args = d;
239 return (*args->cmp)(a, b, args->arg);
243 ruby_qsort(
void* base,
const size_t nel,
const size_t size, cmpfunc_t *cmp,
void *d)
245 struct bsd_qsort_r_args args;
248 qsort_r(base, nel, size, &args, cmp_bsd_qsort);
250 #elif defined HAVE_QSORT_S
254 ruby_qsort(
void* base,
const size_t nel,
const size_t size, cmpfunc_t *cmp,
void *d)
256 if (!nel || !size)
return;
259 if (!base || !cmp)
return;
260 if (nel > RSIZE_MAX || size > RSIZE_MAX)
return;
262 qsort_s(base, nel, size, cmp, d);
264 # define HAVE_GNU_QSORT_R 1
269 #define mmcount (16 / SIZEOF_LONG)
270 #define A ((mmtype*)a)
271 #define B ((mmtype*)b)
272 #define C ((mmtype*)c)
273 #define D ((mmtype*)d)
275 #define mmstep (sizeof(mmtype) * mmcount)
276 #define mmprepare(base, size) do {\
277 if (((VALUE)(base) % sizeof(mmtype)) == 0 && ((size) % sizeof(mmtype)) == 0) \
278 if ((size) >= mmstep) mmkind = 1;\
281 high = ((size) / mmstep) * mmstep;\
282 low = ((size) % mmstep);\
285 #define mmarg mmkind, size, high, low
286 #define mmargdecl int mmkind, size_t size, size_t high, size_t low
288 static void mmswap_(
register char *a,
register char *b, mmargdecl)
295 register char *t = a + high;
297 s = A[0]; A[0] = B[0]; B[0] = s;
298 s = A[1]; A[1] = B[1]; B[1] = s;
300 s = A[2]; A[2] = B[2]; B[2] = s;
302 s = A[3]; A[3] = B[3]; B[3] = s;
305 a += mmstep; b += mmstep;
309 if (low != 0) { s = A[0]; A[0] = B[0]; B[0] = s;
311 if (low >= 2 *
sizeof(mmtype)) { s = A[1]; A[1] = B[1]; B[1] = s;
313 if (low >= 3 *
sizeof(mmtype)) {s = A[2]; A[2] = B[2]; B[2] = s;}
320 register char *t = a + size, s;
321 do {s = *a; *a++ = *b; *b++ = s;}
while (a < t);
324 #define mmswap(a,b) mmswap_((a),(b),mmarg)
327 static void mmrot3_(
register char *a,
register char *b,
register char *c, mmargdecl)
333 register char *t = a + high;
335 s = A[0]; A[0] = B[0]; B[0] = C[0]; C[0] = s;
336 s = A[1]; A[1] = B[1]; B[1] = C[1]; C[1] = s;
338 s = A[2]; A[2] = B[2]; B[2] = C[2]; C[2] = s;
340 s = A[3]; A[3] = B[3]; B[3] = C[3]; C[3] = s;
343 a += mmstep; b += mmstep; c += mmstep;
347 if (low != 0) { s = A[0]; A[0] = B[0]; B[0] = C[0]; C[0] = s;
349 if (low >= 2 *
sizeof(mmtype)) { s = A[1]; A[1] = B[1]; B[1] = C[1]; C[1] = s;
351 if (low == 3 *
sizeof(mmtype)) {s = A[2]; A[2] = B[2]; B[2] = C[2]; C[2] = s;}
358 register char *t = a + size, s;
359 do {s = *a; *a++ = *b; *b++ = *c; *c++ = s;}
while (a < t);
362 #define mmrot3(a,b,c) mmrot3_((a),(b),(c),mmarg)
374 #define PUSH(ll,rr) do { top->LL = (ll); top->RR = (rr); ++top; } while (0)
375 #define POP(ll,rr) do { --top; (ll) = top->LL; (rr) = top->RR; } while (0)
377 #define med3(a,b,c) ((*cmp)((a),(b),d)<0 ? \
378 ((*cmp)((b),(c),d)<0 ? (b) : ((*cmp)((a),(c),d)<0 ? (c) : (a))) : \
379 ((*cmp)((b),(c),d)>0 ? (b) : ((*cmp)((a),(c),d)<0 ? (a) : (c))))
382 ruby_qsort(
void* base,
const size_t nel,
const size_t size, cmpfunc_t *cmp,
void *d)
384 register char *l, *r, *m;
385 register int t, eq_l, eq_r;
387 char *R = (
char*)base + size*(nel-1);
389 enum {size_bits =
sizeof(size) * CHAR_BIT};
395 if (nel <= 1)
return;
396 mmprepare(base, size);
400 if (stack == top)
return;
406 if ((*cmp)(L,R,d) > 0) mmswap(L,R);
411 n = (r - l + size) / size;
412 m = l + size * (n >> 1);
420 register char *p1 = l + n;
421 register char *p2 = p1 + n;
422 register char *p3 = p2 + n;
423 m1 = med3(p1, p2, p3);
427 m3 = med3(p1, p2, p3);
438 if ((t = (*cmp)(l,m,d)) < 0) {
439 if ((t = (*cmp)(m,r,d)) < 0) {
440 if (chklim && nel >= chklim) {
443 for (p=l; p<r; p+=size)
if ((*cmp)(p,p+size,d) > 0)
goto fail;
449 if ((*cmp)(l,r,d) <= 0) {mmswap(m,r);
goto loopA;}
450 mmrot3(r,m,l);
goto loopA;
456 if ((t = (*cmp)(m,r,d)) > 0) {
457 if (chklim && nel >= chklim) {
460 for (p=l; p<r; p+=size)
if ((*cmp)(p,p+size,d) < 0)
goto fail2;
461 while (l<r) {mmswap(l,r); l+=size; r-=size;}
464 fail2: mmswap(l,r);
goto loopA;
467 if ((*cmp)(l,r,d) <= 0) {mmswap(l,m);
goto loopB;}
468 mmrot3(l,m,r);
goto loopA;
470 mmswap(l,r);
goto loopA;
473 if ((t = (*cmp)(m,r,d)) < 0) {
goto loopA;}
474 if (t > 0) {mmswap(l,r);
goto loopB;}
478 if ((l += size) == r)
goto nxt;
479 if (l == m)
continue;
480 if ((t = (*cmp)(l,m,d)) > 0) {mmswap(l,r); l = L;
goto loopA;}
481 if (t < 0) {mmswap(L,l); l = L;
goto loopB;}
484 loopA: eq_l = 1; eq_r = 1;
487 if ((l += size) == r)
488 {l -= size;
if (l != m) mmswap(m,l); l -= size;
goto fin;}
489 if (l == m)
continue;
490 if ((t = (*cmp)(l,m,d)) > 0) {eq_r = 0;
break;}
494 if (l == (r -= size))
495 {l -= size;
if (l != m) mmswap(m,l); l -= size;
goto fin;}
496 if (r == m) {m = l;
break;}
497 if ((t = (*cmp)(r,m,d)) < 0) {eq_l = 0;
break;}
503 loopB: eq_l = 1; eq_r = 1;
506 if (l == (r -= size))
507 {r += size;
if (r != m) mmswap(r,m); r += size;
goto fin;}
508 if (r == m)
continue;
509 if ((t = (*cmp)(r,m,d)) < 0) {eq_l = 0;
break;}
513 if ((l += size) == r)
514 {r += size;
if (r != m) mmswap(r,m); r += size;
goto fin;}
515 if (l == m) {m = r;
break;}
516 if ((t = (*cmp)(l,m,d)) > 0) {eq_r = 0;
break;}
525 if (l-L < R-r) {PUSH(r,R); R = l;}
526 else {PUSH(L,l); L = r;}
528 else if (eq_r == 0) L = r;
539 size_t len = strlen(str) + 1;
542 memcpy(tmp, str,
len);
547 #if defined HAVE_GETCWD
548 # if defined NO_GETCWD_MALLOC
553 VALUE guard = rb_imemo_tmpbuf_auto_free_pointer();
557 while (!getcwd(buf, size)) {
560 rb_free_tmp_buffer(&guard);
564 rb_imemo_tmpbuf_set_ptr(guard, buf);
567 rb_imemo_tmpbuf_set_ptr(guard, NULL);
578 .flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED
585 char *buf, *cwd = getcwd(NULL, 0);
598 # define PATH_MAX 8192
604 char *buf =
xmalloc(PATH_MAX+1);
617 ruby_each_words(
const char *str,
void (*func)(
const char*,
int,
void*),
void *arg)
623 for (; *str; str = end) {
624 while (
ISSPACE(*str) || *str ==
',') str++;
627 while (*end && !
ISSPACE(*end) && *end !=
',') end++;
628 len = (int)(end - str);
629 (*func)(str,
len, arg);
634 #define strtod ruby_strtod
636 #define dtoa ruby_dtoa
638 #define hdtoa ruby_hdtoa
639 #include "missing/dtoa.c"
#define RBIMPL_ASSERT_OR_ASSUME(...)
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.
int len
Length of the buffer.
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 RTYPEDDATA_DATA(v)
Convenient getter macro.
#define TypedData_Wrap_Struct(klass, data_type, sval)
Converts sval, a pointer to your struct, into a Ruby object.
#define errno
Ractor-aware version of errno.
This is the struct that holds necessary info for a struct.
const char * wrap_struct_name
Name of structs of this kind.
uintptr_t VALUE
Type that represents a Ruby object.