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