Ruby: util.c Source File

Ruby 3.0.5p211 (2022-11-24 revision ba5cf0f7c52d4d35cc6a173c89eda98ceffa2dcf)

util.c
Go to the documentation of this file.
1/**********************************************************************
2
3 util.c -
4
5 $Author$
6 created at: Fri Mar 10 17:22:34 JST 1995
7
8 Copyright (C) 1993-2008 Yukihiro Matsumoto
9
10**********************************************************************/
11
12#if defined __MINGW32__ || defined __MINGW64__
13# define MINGW_HAS_SECURE_API 1
14#endif
15
16#include "ruby/internal/config.h"
17
18#include <ctype.h>
19#include <errno.h>
20#include <float.h>
21#include <math.h>
22#include <stdio.h>
23
24#ifdef _WIN32
25# include "missing/file.h"
26#endif
27
28#include "internal.h"
29#include "internal/sanitizers.h"
30#include "internal/util.h"
31#include "ruby/util.h"
32#include "ruby_atomic.h"
33
34 const char ruby_hexdigits[] = "0123456789abcdef0123456789ABCDEF";
35#define hexdigit ruby_hexdigits
36
37unsigned long
38 ruby_scan_oct(const char *start, size_t len, size_t *retlen)
39{
40 register const char *s = start;
41 register unsigned long retval = 0;
42 size_t i;
43
44 for (i = 0; i < len; i++) {
45 if ((s[0] < '0') || ('7' < s[0])) {
46 break;
47 }
48 retval <<= 3;
49 retval |= *s++ - '0';
50 }
51 *retlen = (int)(s - start); /* less than len */
52 return retval;
53}
54
55unsigned long
56 ruby_scan_hex(const char *start, size_t len, size_t *retlen)
57{
58 register const char *s = start;
59 register unsigned long retval = 0;
60 const char *tmp;
61 size_t i = 0;
62
63 for (i = 0; i < len; i++) {
64 if (! s[0]) {
65 break;
66 }
67 tmp = strchr(hexdigit, *s);
68 if (! tmp) {
69 break;
70 }
71 retval <<= 4;
72 retval |= (tmp - hexdigit) & 15;
73 s++;
74 }
75 *retlen = (int)(s - start); /* less than len */
76 return retval;
77}
78
79 const signed char ruby_digit36_to_number_table[] = {
80 /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
81 /*0*/ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
82 /*1*/ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
83 /*2*/ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
84 /*3*/ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1,-1,-1,-1,-1,
85 /*4*/ -1,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,
86 /*5*/ 25,26,27,28,29,30,31,32,33,34,35,-1,-1,-1,-1,-1,
87 /*6*/ -1,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,
88 /*7*/ 25,26,27,28,29,30,31,32,33,34,35,-1,-1,-1,-1,-1,
89 /*8*/ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
90 /*9*/ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
91 /*a*/ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
92 /*b*/ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
93 /*c*/ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
94 /*d*/ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
95 /*e*/ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
96 /*f*/ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
97};
98
99 NO_SANITIZE("unsigned-integer-overflow", extern unsigned long ruby_scan_digits(const char *str, ssize_t len, int base, size_t *retlen, int *overflow));
100unsigned long
101 ruby_scan_digits(const char *str, ssize_t len, int base, size_t *retlen, int *overflow)
102{
103
104 const char *start = str;
105 unsigned long ret = 0, x;
106 unsigned long mul_overflow = (~(unsigned long)0) / base;
107
108 *overflow = 0;
109
110 if (!len) {
111 *retlen = 0;
112 return 0;
113 }
114
115 do {
116 int d = ruby_digit36_to_number_table[(unsigned char)*str++];
117 if (d == -1 || base <= d) {
118 --str;
119 break;
120 }
121 if (mul_overflow < ret)
122 *overflow = 1;
123 ret *= base;
124 x = ret;
125 ret += d;
126 if (ret < x)
127 *overflow = 1;
128 } while (len < 0 || --len);
129 *retlen = str - start;
130 return ret;
131}
132
133unsigned long
134 ruby_strtoul(const char *str, char **endptr, int base)
135{
136 int c, b, overflow;
137 int sign = 0;
138 size_t len;
139 unsigned long ret;
140 const char *subject_found = str;
141
142 if (base == 1 || 36 < base) {
143 errno = EINVAL;
144 return 0;
145 }
146
147 while ((c = *str) && ISSPACE(c))
148 str++;
149
150 if (c == '+') {
151 sign = 1;
152 str++;
153 }
154 else if (c == '-') {
155 sign = -1;
156 str++;
157 }
158
159 if (str[0] == '0') {
160 subject_found = str+1;
161 if (base == 0 || base == 16) {
162 if (str[1] == 'x' || str[1] == 'X') {
163 b = 16;
164 str += 2;
165 }
166 else {
167 b = base == 0 ? 8 : 16;
168 str++;
169 }
170 }
171 else {
172 b = base;
173 str++;
174 }
175 }
176 else {
177 b = base == 0 ? 10 : base;
178 }
179
180 ret = ruby_scan_digits(str, -1, b, &len, &overflow);
181
182 if (0 < len)
183 subject_found = str+len;
184
185 if (endptr)
186 *endptr = (char*)subject_found;
187
188 if (overflow) {
189 errno = ERANGE;
190 return ULONG_MAX;
191 }
192
193 if (sign < 0) {
194 ret = (unsigned long)(-(long)ret);
195 return ret;
196 }
197 else {
198 return ret;
199 }
200}
201
202#include <sys/types.h>
203#include <sys/stat.h>
204#ifdef HAVE_UNISTD_H
205#include <unistd.h>
206#endif
207#if defined(HAVE_FCNTL_H)
208#include <fcntl.h>
209#endif
210
211#ifndef S_ISDIR
212# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
213#endif
214
215 typedef int (cmpfunc_t)(const void*, const void*, void*);
216
217#if defined HAVE_QSORT_S && defined RUBY_MSVCRT_VERSION
218/* In contrast to its name, Visual Studio qsort_s is incompatible with
219 * C11 in the order of the comparison function's arguments, and same
220 * as BSD qsort_r rather. */
221# define qsort_r(base, nel, size, arg, cmp) qsort_s(base, nel, size, cmp, arg)
222# define cmp_bsd_qsort cmp_ms_qsort
223# define HAVE_BSD_QSORT_R 1
224#endif
225
226#if defined HAVE_BSD_QSORT_R
227struct bsd_qsort_r_args {
228 cmpfunc_t *cmp;
229 void *arg;
230};
231
232static int
233cmp_bsd_qsort(void *d, const void *a, const void *b)
234{
235 const struct bsd_qsort_r_args *args = d;
236 return (*args->cmp)(a, b, args->arg);
237}
238
239void
240 ruby_qsort(void* base, const size_t nel, const size_t size, cmpfunc_t *cmp, void *d)
241{
242 struct bsd_qsort_r_args args;
243 args.cmp = cmp;
244 args.arg = d;
245 qsort_r(base, nel, size, &args, cmp_bsd_qsort);
246}
247#elif defined HAVE_QSORT_S
248/* C11 qsort_s has the same arguments as GNU's, but uses
249 * runtime-constraints handler. */
250void
251 ruby_qsort(void* base, const size_t nel, const size_t size, cmpfunc_t *cmp, void *d)
252{
253 if (!nel || !size) return; /* nothing to sort */
254
255 /* get rid of runtime-constraints handler for MT-safeness */
256 if (!base || !cmp) return;
257 if (nel > RSIZE_MAX || size > RSIZE_MAX) return;
258
259 qsort_s(base, nel, size, cmp, d);
260}
261# define HAVE_GNU_QSORT_R 1
262#elif !defined HAVE_GNU_QSORT_R
263/* mm.c */
264
265#define mmtype long
266#define mmcount (16 / SIZEOF_LONG)
267#define A ((mmtype*)a)
268#define B ((mmtype*)b)
269#define C ((mmtype*)c)
270#define D ((mmtype*)d)
271
272#define mmstep (sizeof(mmtype) * mmcount)
273#define mmprepare(base, size) do {\
274 if (((VALUE)(base) % sizeof(mmtype)) == 0 && ((size) % sizeof(mmtype)) == 0) \
275 if ((size) >= mmstep) mmkind = 1;\
276 else mmkind = 0;\
277 else mmkind = -1;\
278 high = ((size) / mmstep) * mmstep;\
279 low = ((size) % mmstep);\
280} while (0)\
281
282#define mmarg mmkind, size, high, low
283#define mmargdecl int mmkind, size_t size, size_t high, size_t low
284
285static void mmswap_(register char *a, register char *b, mmargdecl)
286{
287 if (a == b) return;
288 if (mmkind >= 0) {
289 register mmtype s;
290#if mmcount > 1
291 if (mmkind > 0) {
292 register char *t = a + high;
293 do {
294 s = A[0]; A[0] = B[0]; B[0] = s;
295 s = A[1]; A[1] = B[1]; B[1] = s;
296#if mmcount > 2
297 s = A[2]; A[2] = B[2]; B[2] = s;
298#if mmcount > 3
299 s = A[3]; A[3] = B[3]; B[3] = s;
300#endif
301#endif
302 a += mmstep; b += mmstep;
303 } while (a < t);
304 }
305#endif
306 if (low != 0) { s = A[0]; A[0] = B[0]; B[0] = s;
307#if mmcount > 2
308 if (low >= 2 * sizeof(mmtype)) { s = A[1]; A[1] = B[1]; B[1] = s;
309#if mmcount > 3
310 if (low >= 3 * sizeof(mmtype)) {s = A[2]; A[2] = B[2]; B[2] = s;}
311#endif
312 }
313#endif
314 }
315 }
316 else {
317 register char *t = a + size, s;
318 do {s = *a; *a++ = *b; *b++ = s;} while (a < t);
319 }
320}
321#define mmswap(a,b) mmswap_((a),(b),mmarg)
322
323/* a, b, c = b, c, a */
324static void mmrot3_(register char *a, register char *b, register char *c, mmargdecl)
325{
326 if (mmkind >= 0) {
327 register mmtype s;
328#if mmcount > 1
329 if (mmkind > 0) {
330 register char *t = a + high;
331 do {
332 s = A[0]; A[0] = B[0]; B[0] = C[0]; C[0] = s;
333 s = A[1]; A[1] = B[1]; B[1] = C[1]; C[1] = s;
334#if mmcount > 2
335 s = A[2]; A[2] = B[2]; B[2] = C[2]; C[2] = s;
336#if mmcount > 3
337 s = A[3]; A[3] = B[3]; B[3] = C[3]; C[3] = s;
338#endif
339#endif
340 a += mmstep; b += mmstep; c += mmstep;
341 } while (a < t);
342 }
343#endif
344 if (low != 0) { s = A[0]; A[0] = B[0]; B[0] = C[0]; C[0] = s;
345#if mmcount > 2
346 if (low >= 2 * sizeof(mmtype)) { s = A[1]; A[1] = B[1]; B[1] = C[1]; C[1] = s;
347#if mmcount > 3
348 if (low == 3 * sizeof(mmtype)) {s = A[2]; A[2] = B[2]; B[2] = C[2]; C[2] = s;}
349#endif
350 }
351#endif
352 }
353 }
354 else {
355 register char *t = a + size, s;
356 do {s = *a; *a++ = *b; *b++ = *c; *c++ = s;} while (a < t);
357 }
358}
359#define mmrot3(a,b,c) mmrot3_((a),(b),(c),mmarg)
360
361/* qs6.c */
362/*****************************************************/
363/* */
364/* qs6 (Quick sort function) */
365/* */
366/* by Tomoyuki Kawamura 1995.4.21 */
367/* kawamura@tokuyama.ac.jp */
368/*****************************************************/
369
370 typedef struct { char *LL, *RR; } stack_node; /* Stack structure for L,l,R,r */
371#define PUSH(ll,rr) do { top->LL = (ll); top->RR = (rr); ++top; } while (0) /* Push L,l,R,r */
372#define POP(ll,rr) do { --top; (ll) = top->LL; (rr) = top->RR; } while (0) /* Pop L,l,R,r */
373
374#define med3(a,b,c) ((*cmp)((a),(b),d)<0 ? \
375 ((*cmp)((b),(c),d)<0 ? (b) : ((*cmp)((a),(c),d)<0 ? (c) : (a))) : \
376 ((*cmp)((b),(c),d)>0 ? (b) : ((*cmp)((a),(c),d)<0 ? (a) : (c))))
377
378void
379ruby_qsort(void* base, const size_t nel, const size_t size, cmpfunc_t *cmp, void *d)
380{
381 register char *l, *r, *m; /* l,r:left,right group m:median point */
382 register int t, eq_l, eq_r; /* eq_l: all items in left group are equal to S */
383 char *L = base; /* left end of current region */
384 char *R = (char*)base + size*(nel-1); /* right end of current region */
385 size_t chklim = 63; /* threshold of ordering element check */
386 enum {size_bits = sizeof(size) * CHAR_BIT};
387 stack_node stack[size_bits]; /* enough for size_t size */
388 stack_node *top = stack;
389 int mmkind;
390 size_t high, low, n;
391
392 if (nel <= 1) return; /* need not to sort */
393 mmprepare(base, size);
394 goto start;
395
396 nxt:
397 if (stack == top) return; /* return if stack is empty */
398 POP(L,R);
399
400 for (;;) {
401 start:
402 if (L + size == R) { /* 2 elements */
403 if ((*cmp)(L,R,d) > 0) mmswap(L,R); goto nxt;
404 }
405
406 l = L; r = R;
407 n = (r - l + size) / size; /* number of elements */
408 m = l + size * (n >> 1); /* calculate median value */
409
410 if (n >= 60) {
411 register char *m1;
412 register char *m3;
413 if (n >= 200) {
414 n = size*(n>>3); /* number of bytes in splitting 8 */
415 {
416 register char *p1 = l + n;
417 register char *p2 = p1 + n;
418 register char *p3 = p2 + n;
419 m1 = med3(p1, p2, p3);
420 p1 = m + n;
421 p2 = p1 + n;
422 p3 = p2 + n;
423 m3 = med3(p1, p2, p3);
424 }
425 }
426 else {
427 n = size*(n>>2); /* number of bytes in splitting 4 */
428 m1 = l + n;
429 m3 = m + n;
430 }
431 m = med3(m1, m, m3);
432 }
433
434 if ((t = (*cmp)(l,m,d)) < 0) { /*3-5-?*/
435 if ((t = (*cmp)(m,r,d)) < 0) { /*3-5-7*/
436 if (chklim && nel >= chklim) { /* check if already ascending order */
437 char *p;
438 chklim = 0;
439 for (p=l; p<r; p+=size) if ((*cmp)(p,p+size,d) > 0) goto fail;
440 goto nxt;
441 }
442 fail: goto loopA; /*3-5-7*/
443 }
444 if (t > 0) {
445 if ((*cmp)(l,r,d) <= 0) {mmswap(m,r); goto loopA;} /*3-5-4*/
446 mmrot3(r,m,l); goto loopA; /*3-5-2*/
447 }
448 goto loopB; /*3-5-5*/
449 }
450
451 if (t > 0) { /*7-5-?*/
452 if ((t = (*cmp)(m,r,d)) > 0) { /*7-5-3*/
453 if (chklim && nel >= chklim) { /* check if already ascending order */
454 char *p;
455 chklim = 0;
456 for (p=l; p<r; p+=size) if ((*cmp)(p,p+size,d) < 0) goto fail2;
457 while (l<r) {mmswap(l,r); l+=size; r-=size;} /* reverse region */
458 goto nxt;
459 }
460 fail2: mmswap(l,r); goto loopA; /*7-5-3*/
461 }
462 if (t < 0) {
463 if ((*cmp)(l,r,d) <= 0) {mmswap(l,m); goto loopB;} /*7-5-8*/
464 mmrot3(l,m,r); goto loopA; /*7-5-6*/
465 }
466 mmswap(l,r); goto loopA; /*7-5-5*/
467 }
468
469 if ((t = (*cmp)(m,r,d)) < 0) {goto loopA;} /*5-5-7*/
470 if (t > 0) {mmswap(l,r); goto loopB;} /*5-5-3*/
471
472 /* determining splitting type in case 5-5-5 */ /*5-5-5*/
473 for (;;) {
474 if ((l += size) == r) goto nxt; /*5-5-5*/
475 if (l == m) continue;
476 if ((t = (*cmp)(l,m,d)) > 0) {mmswap(l,r); l = L; goto loopA;}/*575-5*/
477 if (t < 0) {mmswap(L,l); l = L; goto loopB;} /*535-5*/
478 }
479
480 loopA: eq_l = 1; eq_r = 1; /* splitting type A */ /* left <= median < right */
481 for (;;) {
482 for (;;) {
483 if ((l += size) == r)
484 {l -= size; if (l != m) mmswap(m,l); l -= size; goto fin;}
485 if (l == m) continue;
486 if ((t = (*cmp)(l,m,d)) > 0) {eq_r = 0; break;}
487 if (t < 0) eq_l = 0;
488 }
489 for (;;) {
490 if (l == (r -= size))
491 {l -= size; if (l != m) mmswap(m,l); l -= size; goto fin;}
492 if (r == m) {m = l; break;}
493 if ((t = (*cmp)(r,m,d)) < 0) {eq_l = 0; break;}
494 if (t == 0) break;
495 }
496 mmswap(l,r); /* swap left and right */
497 }
498
499 loopB: eq_l = 1; eq_r = 1; /* splitting type B */ /* left < median <= right */
500 for (;;) {
501 for (;;) {
502 if (l == (r -= size))
503 {r += size; if (r != m) mmswap(r,m); r += size; goto fin;}
504 if (r == m) continue;
505 if ((t = (*cmp)(r,m,d)) < 0) {eq_l = 0; break;}
506 if (t > 0) eq_r = 0;
507 }
508 for (;;) {
509 if ((l += size) == r)
510 {r += size; if (r != m) mmswap(r,m); r += size; goto fin;}
511 if (l == m) {m = r; break;}
512 if ((t = (*cmp)(l,m,d)) > 0) {eq_r = 0; break;}
513 if (t == 0) break;
514 }
515 mmswap(l,r); /* swap left and right */
516 }
517
518 fin:
519 if (eq_l == 0) /* need to sort left side */
520 if (eq_r == 0) /* need to sort right side */
521 if (l-L < R-r) {PUSH(r,R); R = l;} /* sort left side first */
522 else {PUSH(L,l); L = r;} /* sort right side first */
523 else R = l; /* need to sort left side only */
524 else if (eq_r == 0) L = r; /* need to sort right side only */
525 else goto nxt; /* need not to sort both sides */
526 }
527}
528#endif /* HAVE_GNU_QSORT_R */
529
530char *
531 ruby_strdup(const char *str)
532{
533 char *tmp;
534 size_t len = strlen(str) + 1;
535
536 tmp = xmalloc(len);
537 memcpy(tmp, str, len);
538
539 return tmp;
540}
541
542char *
543 ruby_getcwd(void)
544{
545#if defined HAVE_GETCWD
546# undef RUBY_UNTYPED_DATA_WARNING
547# define RUBY_UNTYPED_DATA_WARNING 0
548# if defined NO_GETCWD_MALLOC
549 VALUE guard = Data_Wrap_Struct((VALUE)0, NULL, RUBY_DEFAULT_FREE, NULL);
550 int size = 200;
551 char *buf = xmalloc(size);
552
553 while (!getcwd(buf, size)) {
554 int e = errno;
555 if (e != ERANGE) {
556 xfree(buf);
557 DATA_PTR(guard) = NULL;
558 rb_syserr_fail(e, "getcwd");
559 }
560 size *= 2;
561 DATA_PTR(guard) = buf;
562 buf = xrealloc(buf, size);
563 }
564# else
565 VALUE guard = Data_Wrap_Struct((VALUE)0, NULL, free, NULL);
566 char *buf, *cwd = getcwd(NULL, 0);
567 DATA_PTR(guard) = cwd;
568 if (!cwd) rb_sys_fail("getcwd");
569 buf = ruby_strdup(cwd); /* allocate by xmalloc */
570 free(cwd);
571# endif
572 DATA_PTR(RB_GC_GUARD(guard)) = NULL;
573#else
574# ifndef PATH_MAX
575# define PATH_MAX 8192
576# endif
577 char *buf = xmalloc(PATH_MAX+1);
578
579 if (!getwd(buf)) {
580 int e = errno;
581 xfree(buf);
582 rb_syserr_fail(e, "getwd");
583 }
584#endif
585 return buf;
586}
587
588void
589 ruby_each_words(const char *str, void (*func)(const char*, int, void*), void *arg)
590{
591 const char *end;
592 int len;
593
594 if (!str) return;
595 for (; *str; str = end) {
596 while (ISSPACE(*str) || *str == ',') str++;
597 if (!*str) break;
598 end = str;
599 while (*end && !ISSPACE(*end) && *end != ',') end++;
600 len = (int)(end - str); /* assume no string exceeds INT_MAX */
601 (*func)(str, len, arg);
602 }
603}
604
605#undef strtod
606#define strtod ruby_strtod
607#undef dtoa
608#define dtoa ruby_dtoa
609#undef hdtoa
610#define hdtoa ruby_hdtoa
611#include "missing/dtoa.c"
L
#define L(x)
Definition: asm.h:125
ctype.h
Our own, locale independent, character handling routines.
ISSPACE
#define ISSPACE
Definition: ctype.h:38
fail
#define fail()
Definition: date_strptime.c:123
strchr
char * strchr(char *, char)
free
#define free(x)
Definition: dln.c:52
dtoa.c
len
uint8_t len
Definition: escape.c:17
str
char str[HTML_ESCAPE_MAX_LEN+1]
Definition: escape.c:18
memcpy
#define memcpy(d, s, n)
Definition: ffi_common.h:55
rb_syserr_fail
void rb_syserr_fail(int e, const char *mesg)
Definition: error.c:3029
rb_sys_fail
void rb_sys_fail(const char *mesg)
Definition: error.c:3041
config.h
Thin wrapper to ruby/config.h.
util.h
util.h
Internal header corresponding util.c.
internal.h
size
voidpf void uLong size
Definition: ioapi.h:138
long
typedef long(ZCALLBACK *tell_file_func) OF((voidpf opaque
int
typedef int(ZCALLBACK *close_file_func) OF((voidpf opaque
buf
voidpf void * buf
Definition: ioapi.h:138
CHAR_BIT
#define CHAR_BIT
Definition: limits.h:44
math.h
Internal header for Math.
RB_GC_GUARD
#define RB_GC_GUARD(v)
Definition: memory.h:91
file.h
top
unsigned int top
Definition: nkf.c:4323
Data_Wrap_Struct
#define Data_Wrap_Struct(klass, mark, free, sval)
Definition: rdata.h:80
DATA_PTR
#define DATA_PTR(obj)
Definition: rdata.h:56
RUBY_DEFAULT_FREE
#define RUBY_DEFAULT_FREE
Definition: rdata.h:58
NULL
#define NULL
Definition: regenc.h:69
ruby_atomic.h
sanitizers.h
Internal header for ASAN / MSAN / etc.
NO_SANITIZE
#define NO_SANITIZE(x, y)
Definition: sanitizers.h:61
R
#define R(b, x)
Definition: sha2.c:203
strlen
size_t strlen(const char *)
A
Definition: nested_struct10.c:12
B
Definition: nested_struct10.c:17
C
Definition: nested_struct10.c:23
stack_node
Definition: util.c:370
stack_node::LL
char * LL
Definition: util.c:370
t
#define t
Definition: symbol.c:253
mmstep
#define mmstep
Definition: util.c:272
med3
#define med3(a, b, c)
Definition: util.c:374
mmswap
#define mmswap(a, b)
Definition: util.c:321
hexdigit
#define hexdigit
Definition: util.c:35
ruby_digit36_to_number_table
const signed char ruby_digit36_to_number_table[]
Definition: util.c:79
ruby_strdup
char * ruby_strdup(const char *str)
Definition: util.c:531
mmtype
#define mmtype
Definition: util.c:265
POP
#define POP(ll, rr)
Definition: util.c:372
PUSH
#define PUSH(ll, rr)
Definition: util.c:371
mmargdecl
#define mmargdecl
Definition: util.c:283
ruby_qsort
void ruby_qsort(void *base, const size_t nel, const size_t size, cmpfunc_t *cmp, void *d)
Definition: util.c:379
ruby_each_words
void ruby_each_words(const char *str, void(*func)(const char *, int, void *), void *arg)
Definition: util.c:589
ruby_strtoul
unsigned long ruby_strtoul(const char *str, char **endptr, int base)
Definition: util.c:134
mmrot3
#define mmrot3(a, b, c)
Definition: util.c:359
ruby_scan_oct
unsigned long ruby_scan_oct(const char *start, size_t len, size_t *retlen)
Definition: util.c:38
ruby_getcwd
char * ruby_getcwd(void)
Definition: util.c:543
ruby_hexdigits
const char ruby_hexdigits[]
Definition: util.c:34
ruby_scan_hex
unsigned long ruby_scan_hex(const char *start, size_t len, size_t *retlen)
Definition: util.c:56
mmprepare
#define mmprepare(base, size)
Definition: util.c:273
ruby_scan_digits
unsigned long ruby_scan_digits(const char *str, ssize_t len, int base, size_t *retlen, int *overflow)
Definition: util.c:101
PATH_MAX
#define PATH_MAX
cmpfunc_t
int() cmpfunc_t(const void *, const void *, void *)
Definition: util.c:215
VALUE
unsigned long VALUE
Definition: value.h:38
getcwd
#define getcwd(b, s)
Definition: dir.h:48
xfree
#define xfree
Definition: xmalloc.h:49
xrealloc
#define xrealloc
Definition: xmalloc.h:47
xmalloc
#define xmalloc
Definition: xmalloc.h:44