00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include "ruby.h"
00014
00015 #include <ctype.h>
00016 #include <stdio.h>
00017 #include <errno.h>
00018
00019 #ifdef _WIN32
00020 #include "missing/file.h"
00021 #endif
00022
00023 #include "util.h"
00024 #ifndef HAVE_STRING_H
00025 char *strchr (char*,char);
00026 #endif
00027
00028 unsigned long
00029 scan_oct(start, len, retlen)
00030 const char *start;
00031 int len;
00032 int *retlen;
00033 {
00034 register const char *s = start;
00035 register unsigned long retval = 0;
00036
00037 while (len-- && *s >= '0' && *s <= '7') {
00038 retval <<= 3;
00039 retval |= *s++ - '0';
00040 }
00041 *retlen = s - start;
00042 return retval;
00043 }
00044
00045 unsigned long
00046 scan_hex(start, len, retlen)
00047 const char *start;
00048 int len;
00049 int *retlen;
00050 {
00051 static char hexdigit[] = "0123456789abcdef0123456789ABCDEF";
00052 register const char *s = start;
00053 register unsigned long retval = 0;
00054 char *tmp;
00055
00056 while (len-- && *s && (tmp = strchr(hexdigit, *s))) {
00057 retval <<= 4;
00058 retval |= (tmp - hexdigit) & 15;
00059 s++;
00060 }
00061 *retlen = s - start;
00062 return retval;
00063 }
00064
00065 #include <sys/types.h>
00066 #include <sys/stat.h>
00067 #ifdef HAVE_UNISTD_H
00068 #include <unistd.h>
00069 #endif
00070 #if defined(HAVE_FCNTL_H)
00071 #include <fcntl.h>
00072 #endif
00073
00074 #ifndef S_ISDIR
00075 # define S_ISDIR(m) ((m & S_IFMT) == S_IFDIR)
00076 #endif
00077
00078 #if defined(MSDOS) || defined(__CYGWIN32__) || defined(_WIN32)
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148 static int valid_filename(char *s);
00149
00150 static char suffix1[] = ".$$$";
00151 static char suffix2[] = ".~~~";
00152
00153 #define ext (&buf[1000])
00154
00155 #define strEQ(s1,s2) (strcmp(s1,s2) == 0)
00156
00157 void
00158 ruby_add_suffix(str, suffix)
00159 VALUE str;
00160 char *suffix;
00161 {
00162 int baselen;
00163 int extlen = strlen(suffix);
00164 char *s, *t, *p;
00165 long slen;
00166 char buf[1024];
00167
00168 if (RSTRING(str)->len > 1000)
00169 rb_fatal("Cannot do inplace edit on long filename (%ld characters)",
00170 RSTRING(str)->len);
00171
00172 #if defined(DJGPP) || defined(__CYGWIN32__) || defined(_WIN32)
00173
00174 slen = RSTRING(str)->len;
00175 rb_str_cat(str, suffix, extlen);
00176 #if defined(DJGPP)
00177 if (_USE_LFN) return;
00178 #else
00179 if (valid_filename(RSTRING(str)->ptr)) return;
00180 #endif
00181
00182
00183 RSTRING(str)->ptr[RSTRING(str)->len = slen] = '\0';
00184 #endif
00185
00186 slen = extlen;
00187 t = buf; baselen = 0; s = RSTRING(str)->ptr;
00188 while ((*t = *s) && *s != '.') {
00189 baselen++;
00190 if (*s == '\\' || *s == '/') baselen = 0;
00191 s++; t++;
00192 }
00193 p = t;
00194
00195 t = ext; extlen = 0;
00196 while (*t++ = *s++) extlen++;
00197 if (extlen == 0) { ext[0] = '.'; ext[1] = 0; extlen++; }
00198
00199 if (*suffix == '.') {
00200 if (strEQ(ext, suffix)) goto fallback;
00201 strcpy(p, suffix);
00202 }
00203 else if (suffix[1] == '\0') {
00204 if (extlen < 4) {
00205 ext[extlen] = *suffix;
00206 ext[++extlen] = '\0';
00207 }
00208 else if (baselen < 8) {
00209 *p++ = *suffix;
00210 }
00211 else if (ext[3] != *suffix) {
00212 ext[3] = *suffix;
00213 }
00214 else if (buf[7] != *suffix) {
00215 buf[7] = *suffix;
00216 }
00217 else goto fallback;
00218 strcpy(p, ext);
00219 }
00220 else {
00221 fallback:
00222 (void)memcpy(p, strEQ(ext, suffix1) ? suffix2 : suffix1, 5);
00223 }
00224 rb_str_resize(str, strlen(buf));
00225 memcpy(RSTRING(str)->ptr, buf, RSTRING(str)->len);
00226 }
00227
00228 #if defined(__CYGWIN32__) || defined(_WIN32)
00229 static int
00230 valid_filename(char *s)
00231 {
00232 int fd;
00233
00234
00235
00236
00237
00238 if (_access(s, 0) == 0) {
00239 return 1;
00240 }
00241
00242
00243
00244
00245
00246 if ((fd = _open(s, O_CREAT, 0666)) >= 0) {
00247 _close(fd);
00248 _unlink(s);
00249 return 1;
00250 }
00251 return 0;
00252 }
00253 #endif
00254 #endif
00255
00256 #if defined __DJGPP__
00257
00258 #include <dpmi.h>
00259
00260 static char dbcs_table[256];
00261
00262 int
00263 make_dbcs_table()
00264 {
00265 __dpmi_regs r;
00266 struct {
00267 unsigned char start;
00268 unsigned char end;
00269 } vec;
00270 int offset;
00271
00272 memset(&r, 0, sizeof(r));
00273 r.x.ax = 0x6300;
00274 __dpmi_int(0x21, &r);
00275 offset = r.x.ds * 16 + r.x.si;
00276
00277 for (;;) {
00278 int i;
00279 dosmemget(offset, sizeof vec, &vec);
00280 if (!vec.start && !vec.end)
00281 break;
00282 for (i = vec.start; i <= vec.end; i++)
00283 dbcs_table[i] = 1;
00284 offset += 2;
00285 }
00286 }
00287
00288 int
00289 mblen(const char *s, size_t n)
00290 {
00291 static int need_init = 1;
00292 if (need_init) {
00293 make_dbcs_table();
00294 need_init = 0;
00295 }
00296 if (s) {
00297 if (n == 0 || *s == 0)
00298 return 0;
00299 else if (!s[1])
00300 return 1;
00301 return dbcs_table[(unsigned char)*s] + 1;
00302 }
00303 else
00304 return 1;
00305 }
00306
00307 struct PathList {
00308 struct PathList *next;
00309 char *path;
00310 };
00311
00312 struct PathInfo {
00313 struct PathList *head;
00314 int count;
00315 };
00316
00317 static void
00318 push_element(const char *path, VALUE vinfo)
00319 {
00320 struct PathList *p;
00321 struct PathInfo *info = (struct PathInfo *)vinfo;
00322
00323 p = ALLOC(struct PathList);
00324 MEMZERO(p, struct PathList, 1);
00325 p->path = ruby_strdup(path);
00326 p->next = info->head;
00327 info->head = p;
00328 info->count++;
00329 }
00330
00331 #include <dirent.h>
00332 int __opendir_flags = __OPENDIR_PRESERVE_CASE;
00333
00334 char **
00335 __crt0_glob_function(char *path)
00336 {
00337 int len = strlen(path);
00338 int i;
00339 char **rv;
00340 char path_buffer[PATH_MAX];
00341 char *buf = path_buffer;
00342 char *p;
00343 struct PathInfo info;
00344 struct PathList *plist;
00345
00346 if (PATH_MAX <= len)
00347 buf = ruby_xmalloc(len + 1);
00348
00349 strncpy(buf, path, len);
00350 buf[len] = '\0';
00351
00352 for (p = buf; *p; p += mblen(p, MB_CUR_MAX))
00353 if (*p == '\\')
00354 *p = '/';
00355
00356 info.count = 0;
00357 info.head = 0;
00358
00359 rb_globi(buf, push_element, (VALUE)&info);
00360
00361 if (buf != path_buffer)
00362 ruby_xfree(buf);
00363
00364 if (info.count == 0)
00365 return 0;
00366
00367 rv = ruby_xmalloc((info.count + 1) * sizeof (char *));
00368
00369 plist = info.head;
00370 i = 0;
00371 while (plist) {
00372 struct PathList *cur;
00373 rv[i] = plist->path;
00374 cur = plist;
00375 plist = plist->next;
00376 ruby_xfree(cur);
00377 i++;
00378 }
00379 rv[i] = 0;
00380 return rv;
00381 }
00382
00383 #endif
00384
00385
00386
00387 #define A ((int*)a)
00388 #define B ((int*)b)
00389 #define C ((int*)c)
00390 #define D ((int*)d)
00391
00392 #define mmprepare(base, size) do {\
00393 if (((long)base & (0x3)) == 0)\
00394 if (size >= 16) mmkind = 1;\
00395 else mmkind = 0;\
00396 else mmkind = -1;\
00397 high = (size & (~0xf));\
00398 low = (size & 0x0c);\
00399 } while (0)\
00400
00401 #define mmarg mmkind, size, high, low
00402
00403 static void mmswap_(a, b, mmarg)
00404 register char *a, *b;
00405 int mmarg;
00406 {
00407 register int s;
00408 if (a == b) return;
00409 if (mmkind >= 0) {
00410 if (mmkind > 0) {
00411 register char *t = a + high;
00412 do {
00413 s = A[0]; A[0] = B[0]; B[0] = s;
00414 s = A[1]; A[1] = B[1]; B[1] = s;
00415 s = A[2]; A[2] = B[2]; B[2] = s;
00416 s = A[3]; A[3] = B[3]; B[3] = s; a += 16; b += 16;
00417 } while (a < t);
00418 }
00419 if (low != 0) { s = A[0]; A[0] = B[0]; B[0] = s;
00420 if (low >= 8) { s = A[1]; A[1] = B[1]; B[1] = s;
00421 if (low == 12) {s = A[2]; A[2] = B[2]; B[2] = s;}}}
00422 }
00423 else {
00424 register char *t = a + size;
00425 do {s = *a; *a++ = *b; *b++ = s;} while (a < t);
00426 }
00427 }
00428 #define mmswap(a,b) mmswap_((a),(b),mmarg)
00429
00430 static void mmrot3_(a, b, c, mmarg)
00431 register char *a, *b, *c;
00432 int mmarg;
00433 {
00434 register int s;
00435 if (mmkind >= 0) {
00436 if (mmkind > 0) {
00437 register char *t = a + high;
00438 do {
00439 s = A[0]; A[0] = B[0]; B[0] = C[0]; C[0] = s;
00440 s = A[1]; A[1] = B[1]; B[1] = C[1]; C[1] = s;
00441 s = A[2]; A[2] = B[2]; B[2] = C[2]; C[2] = s;
00442 s = A[3]; A[3] = B[3]; B[3] = C[3]; C[3] = s; a += 16; b += 16; c += 16;
00443 } while (a < t);
00444 }
00445 if (low != 0) { s = A[0]; A[0] = B[0]; B[0] = C[0]; C[0] = s;
00446 if (low >= 8) { s = A[1]; A[1] = B[1]; B[1] = C[1]; C[1] = s;
00447 if (low == 12) {s = A[2]; A[2] = B[2]; B[2] = C[2]; C[2] = s;}}}
00448 }
00449 else {
00450 register char *t = a + size;
00451 do {s = *a; *a++ = *b; *b++ = *c; *c++ = s;} while (a < t);
00452 }
00453 }
00454 #define mmrot3(a,b,c) mmrot3_((a),(b),(c),mmarg)
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465 typedef struct { char *LL, *RR; } stack_node;
00466 #define PUSH(ll,rr) do { top->LL = (ll); top->RR = (rr); ++top; } while (0)
00467 #define POP(ll,rr) do { --top; ll = top->LL; rr = top->RR; } while (0)
00468
00469 #define med3(a,b,c) ((*cmp)(a,b,d)<0 ? \
00470 ((*cmp)(b,c,d)<0 ? b : ((*cmp)(a,c,d)<0 ? c : a)) : \
00471 ((*cmp)(b,c,d)>0 ? b : ((*cmp)(a,c,d)<0 ? a : c)))
00472
00473 void ruby_qsort (base, nel, size, cmp, d)
00474 void* base;
00475 const int nel;
00476 const int size;
00477 int (*cmp)();
00478 void *d;
00479 {
00480 register char *l, *r, *m;
00481 register int t, eq_l, eq_r;
00482 char *L = base;
00483 char *R = (char*)base + size*(nel-1);
00484 int chklim = 63;
00485 stack_node stack[32], *top = stack;
00486 int mmkind, high, low;
00487
00488 if (nel <= 1) return;
00489 mmprepare(base, size);
00490 goto start;
00491
00492 nxt:
00493 if (stack == top) return;
00494 POP(L,R);
00495
00496 for (;;) {
00497 start:
00498 if (L + size == R) {
00499 if ((*cmp)(L,R,d) > 0) mmswap(L,R); goto nxt;
00500 }
00501
00502 l = L; r = R;
00503 t = (r - l + size) / size;
00504 m = l + size * (t >> 1);
00505
00506 if (t >= 60) {
00507 register char *m1;
00508 register char *m3;
00509 if (t >= 200) {
00510 t = size*(t>>3);
00511 {
00512 register char *p1 = l + t;
00513 register char *p2 = p1 + t;
00514 register char *p3 = p2 + t;
00515 m1 = med3(p1, p2, p3);
00516 p1 = m + t;
00517 p2 = p1 + t;
00518 p3 = p2 + t;
00519 m3 = med3(p1, p2, p3);
00520 }
00521 }
00522 else {
00523 t = size*(t>>2);
00524 m1 = l + t;
00525 m3 = m + t;
00526 }
00527 m = med3(m1, m, m3);
00528 }
00529
00530 if ((t = (*cmp)(l,m,d)) < 0) {
00531 if ((t = (*cmp)(m,r,d)) < 0) {
00532 if (chklim && nel >= chklim) {
00533 char *p;
00534 chklim = 0;
00535 for (p=l; p<r; p+=size) if ((*cmp)(p,p+size,d) > 0) goto fail;
00536 goto nxt;
00537 }
00538 fail: goto loopA;
00539 }
00540 if (t > 0) {
00541 if ((*cmp)(l,r,d) <= 0) {mmswap(m,r); goto loopA;}
00542 mmrot3(r,m,l); goto loopA;
00543 }
00544 goto loopB;
00545 }
00546
00547 if (t > 0) {
00548 if ((t = (*cmp)(m,r,d)) > 0) {
00549 if (chklim && nel >= chklim) {
00550 char *p;
00551 chklim = 0;
00552 for (p=l; p<r; p+=size) if ((*cmp)(p,p+size,d) < 0) goto fail2;
00553 while (l<r) {mmswap(l,r); l+=size; r-=size;}
00554 goto nxt;
00555 }
00556 fail2: mmswap(l,r); goto loopA;
00557 }
00558 if (t < 0) {
00559 if ((*cmp)(l,r,d) <= 0) {mmswap(l,m); goto loopB;}
00560 mmrot3(l,m,r); goto loopA;
00561 }
00562 mmswap(l,r); goto loopA;
00563 }
00564
00565 if ((t = (*cmp)(m,r,d)) < 0) {goto loopA;}
00566 if (t > 0) {mmswap(l,r); goto loopB;}
00567
00568
00569 for (;;) {
00570 if ((l += size) == r) goto nxt;
00571 if (l == m) continue;
00572 if ((t = (*cmp)(l,m,d)) > 0) {mmswap(l,r); l = L; goto loopA;}
00573 if (t < 0) {mmswap(L,l); l = L; goto loopB;}
00574 }
00575
00576 loopA: eq_l = 1; eq_r = 1;
00577 for (;;) {
00578 for (;;) {
00579 if ((l += size) == r)
00580 {l -= size; if (l != m) mmswap(m,l); l -= size; goto fin;}
00581 if (l == m) continue;
00582 if ((t = (*cmp)(l,m,d)) > 0) {eq_r = 0; break;}
00583 if (t < 0) eq_l = 0;
00584 }
00585 for (;;) {
00586 if (l == (r -= size))
00587 {l -= size; if (l != m) mmswap(m,l); l -= size; goto fin;}
00588 if (r == m) {m = l; break;}
00589 if ((t = (*cmp)(r,m,d)) < 0) {eq_l = 0; break;}
00590 if (t == 0) break;
00591 }
00592 mmswap(l,r);
00593 }
00594
00595 loopB: eq_l = 1; eq_r = 1;
00596 for (;;) {
00597 for (;;) {
00598 if (l == (r -= size))
00599 {r += size; if (r != m) mmswap(r,m); r += size; goto fin;}
00600 if (r == m) continue;
00601 if ((t = (*cmp)(r,m,d)) < 0) {eq_l = 0; break;}
00602 if (t > 0) eq_r = 0;
00603 }
00604 for (;;) {
00605 if ((l += size) == r)
00606 {r += size; if (r != m) mmswap(r,m); r += size; goto fin;}
00607 if (l == m) {m = r; break;}
00608 if ((t = (*cmp)(l,m,d)) > 0) {eq_r = 0; break;}
00609 if (t == 0) break;
00610 }
00611 mmswap(l,r);
00612 }
00613
00614 fin:
00615 if (eq_l == 0)
00616 if (eq_r == 0)
00617 if (l-L < R-r) {PUSH(r,R); R = l;}
00618 else {PUSH(L,l); L = r;}
00619 else R = l;
00620 else if (eq_r == 0) L = r;
00621 else goto nxt;
00622 }
00623 }
00624
00625 char *
00626 ruby_strdup(str)
00627 const char *str;
00628 {
00629 char *tmp;
00630 int len = strlen(str) + 1;
00631
00632 tmp = xmalloc(len);
00633 memcpy(tmp, str, len);
00634
00635 return tmp;
00636 }
00637
00638 char *
00639 ruby_getcwd()
00640 {
00641 #ifdef HAVE_GETCWD
00642 int size = 200;
00643 char *buf = xmalloc(size);
00644
00645 while (!getcwd(buf, size)) {
00646 if (errno != ERANGE) {
00647 free(buf);
00648 rb_sys_fail("getcwd");
00649 }
00650 size *= 2;
00651 buf = xrealloc(buf, size);
00652 }
00653 #else
00654 # ifndef PATH_MAX
00655 # define PATH_MAX 8192
00656 # endif
00657 char *buf = xmalloc(PATH_MAX+1);
00658
00659 if (!getwd(buf)) {
00660 free(buf);
00661 rb_sys_fail("getwd");
00662 }
00663 #endif
00664 return buf;
00665 }
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682 #define TRUE 1
00683 #define FALSE 0
00684
00685 static int MDMINEXPT = -323;
00686 static int MDMAXEXPT = 309;
00687 static double powersOf10[] = {
00688 10.0,
00689 100.0,
00690 1.0e4,
00691 1.0e8,
00692 1.0e16,
00693 1.0e32,
00694 1.0e64,
00695 1.0e128,
00696 1.0e256
00697 };
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720 double
00721 ruby_strtod(string, endPtr)
00722 const char *string;
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735 char **endPtr;
00736
00737 {
00738 int sign, expSign = FALSE;
00739 double fraction, dblExp, *d;
00740 register const char *p;
00741 register int c;
00742 int exp = 0;
00743 int fracExp = 0;
00744
00745
00746
00747
00748
00749
00750
00751
00752 int mantSize = 0;
00753 int hasPoint = FALSE;
00754 int hasDigit = FALSE;
00755 const char *pMant;
00756
00757 const char *pExp;
00758
00759
00760
00761
00762
00763
00764 errno = 0;
00765 p = string;
00766 while (ISSPACE(*p)) {
00767 p += 1;
00768 }
00769 if (*p == '-') {
00770 sign = TRUE;
00771 p += 1;
00772 }
00773 else {
00774 if (*p == '+') {
00775 p += 1;
00776 }
00777 sign = FALSE;
00778 }
00779
00780
00781
00782
00783
00784
00785 for ( ; c = *p; p += 1) {
00786 if (!ISDIGIT(c)) {
00787 if (c != '.' || hasPoint) {
00788 break;
00789 }
00790 hasPoint = TRUE;
00791 }
00792 else {
00793 if (hasPoint) {
00794 fracExp -= 1;
00795 }
00796 if (mantSize) {
00797 mantSize += 1;
00798 }
00799 else if (c != '0') {
00800 mantSize += 1;
00801 pMant = p;
00802 }
00803 hasDigit = TRUE;
00804 }
00805 }
00806
00807
00808
00809
00810
00811
00812
00813
00814 pExp = p;
00815 if (mantSize) {
00816 p = pMant;
00817 }
00818 if (mantSize > 18) {
00819 fracExp += (mantSize - 18);
00820 mantSize = 18;
00821 }
00822 if (!hasDigit) {
00823 fraction = 0.0;
00824 p = string;
00825 }
00826 else {
00827 int frac1, frac2;
00828 frac1 = 0;
00829 for ( ; mantSize > 9; mantSize -= 1) {
00830 c = *p;
00831 p += 1;
00832 if (c == '.') {
00833 c = *p;
00834 p += 1;
00835 }
00836 frac1 = 10*frac1 + (c - '0');
00837 }
00838 frac2 = 0;
00839 for (; mantSize > 0; mantSize -= 1) {
00840 c = *p;
00841 p += 1;
00842 if (c == '.') {
00843 c = *p;
00844 p += 1;
00845 }
00846 frac2 = 10*frac2 + (c - '0');
00847 }
00848
00849
00850
00851
00852
00853 p = pExp;
00854 if ((*p == 'E') || (*p == 'e')) {
00855 p += 1;
00856 if (*p == '-') {
00857 expSign = TRUE;
00858 p += 1;
00859 }
00860 else {
00861 if (*p == '+') {
00862 p += 1;
00863 }
00864 expSign = FALSE;
00865 }
00866 while (ISDIGIT(*p)) {
00867 exp = exp * 10 + (*p - '0');
00868 p += 1;
00869 }
00870 }
00871 if (expSign) {
00872 exp = fracExp - exp;
00873 }
00874 else {
00875 exp = fracExp + exp;
00876 }
00877
00878
00879
00880
00881
00882
00883
00884
00885 if (exp >= MDMAXEXPT - 18) {
00886 exp = MDMAXEXPT;
00887 errno = ERANGE;
00888 }
00889 else if (exp < MDMINEXPT + 18) {
00890 exp = MDMINEXPT;
00891 errno = ERANGE;
00892 }
00893 fracExp = exp;
00894 exp += 9;
00895 if (exp < 0) {
00896 expSign = TRUE;
00897 exp = -exp;
00898 }
00899 else {
00900 expSign = FALSE;
00901 }
00902 dblExp = 1.0;
00903 for (d = powersOf10; exp != 0; exp >>= 1, d += 1) {
00904 if (exp & 01) {
00905 dblExp *= *d;
00906 }
00907 }
00908 if (expSign) {
00909 fraction = frac1 / dblExp;
00910 }
00911 else {
00912 fraction = frac1 * dblExp;
00913 }
00914 exp = fracExp;
00915 if (exp < 0) {
00916 expSign = TRUE;
00917 exp = -exp;
00918 }
00919 else {
00920 expSign = FALSE;
00921 }
00922 dblExp = 1.0;
00923 for (d = powersOf10; exp != 0; exp >>= 1, d += 1) {
00924 if (exp & 01) {
00925 dblExp *= *d;
00926 }
00927 }
00928 if (expSign) {
00929 fraction += frac2 / dblExp;
00930 }
00931 else {
00932 fraction += frac2 * dblExp;
00933 }
00934 }
00935
00936 if (endPtr != NULL) {
00937 *endPtr = (char *) p;
00938 }
00939
00940 if (sign) {
00941 return -fraction;
00942 }
00943 return fraction;
00944 }
00945