summaryrefslogtreecommitdiff
path: root/util.c
diff options
context:
space:
mode:
Diffstat (limited to 'util.c')
-rw-r--r--util.c353
1 files changed, 336 insertions, 17 deletions
diff --git a/util.c b/util.c
index 21e0a55639..ae0914d217 100644
--- a/util.c
+++ b/util.c
@@ -6,21 +6,39 @@
$Date$
created at: Fri Mar 10 17:22:34 JST 1995
- Copyright (C) 1993-1996 Yukihiro Matsumoto
+ Copyright (C) 1993-1998 Yukihiro Matsumoto
************************************************/
+#include <stdio.h>
+
+#ifdef NT
+#include "missing/file.h"
+#endif
+
#define RUBY_NO_INLINE
#include "ruby.h"
+VALUE
+rb_class_of(obj)
+ VALUE obj;
+{
+ if (FIXNUM_P(obj)) return rb_cFixnum;
+ if (obj == Qnil) return rb_cNilClass;
+ if (obj == Qfalse) return rb_cFalseClass;
+ if (obj == Qtrue) return rb_cTrueClass;
+
+ return RBASIC(obj)->klass;
+}
+
int
rb_type(obj)
VALUE obj;
{
if (FIXNUM_P(obj)) return T_FIXNUM;
if (obj == Qnil) return T_NIL;
- if (obj == FALSE) return T_FALSE;
- if (obj == TRUE) return T_TRUE;
+ if (obj == Qfalse) return T_FALSE;
+ if (obj == Qtrue) return T_TRUE;
return BUILTIN_TYPE(obj);
}
@@ -29,24 +47,24 @@ int
rb_special_const_p(obj)
VALUE obj;
{
- if (FIXNUM_P(obj)) return TRUE;
- if (obj == Qnil) return TRUE;
- if (obj == FALSE) return TRUE;
- if (obj == TRUE) return TRUE;
+ if (FIXNUM_P(obj)) return Qtrue;
+ if (obj == Qnil) return Qtrue;
+ if (obj == Qfalse) return Qtrue;
+ if (obj == Qtrue) return Qtrue;
- return FALSE;
+ return Qfalse;
}
int
rb_test_false_or_nil(v)
VALUE v;
{
- return (v != Qnil) && (v != FALSE);
+ return (v != Qnil) && (v != Qfalse);
}
#include "util.h"
#ifndef HAVE_STRING_H
-char *strchr();
+char *strchr _((char*,char));
#endif
unsigned long
@@ -86,8 +104,55 @@ int *retlen;
return retval;
}
-#if defined(MSDOS) || defined(__CYGWIN32__) || defined(NT)
+#include <sys/types.h>
+#include <sys/stat.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#if defined(HAVE_FCNTL)
#include <fcntl.h>
+#endif
+
+#ifndef S_ISDIR
+# define S_ISDIR(m) ((m & S_IFMT) == S_IFDIR)
+#endif
+
+#ifdef NT
+#include "missing/file.h"
+#endif
+
+static char *
+check_dir(dir)
+ char *dir;
+{
+ struct stat st;
+
+ if (dir == NULL) return NULL;
+ if (stat(dir, &st) < 0) return NULL;
+ if (!S_ISDIR(st.st_mode)) return NULL;
+ if (eaccess(dir, W_OK) < 0) return NULL;
+ return dir;
+}
+
+char *
+ruby_mktemp()
+{
+ char *dir;
+ char *buf;
+
+ dir = check_dir(getenv("TMP"));
+ if (!dir) dir = check_dir(getenv("TMPDIR"));
+ if (!dir) dir = "/tmp";
+
+ buf = ALLOC_N(char,strlen(dir)+10);
+ sprintf(buf, "%s/rbXXXXXX", dir);
+ dir = mktemp(buf);
+ if (dir == NULL) free(buf);
+
+ return dir;
+}
+
+#if defined(MSDOS) || defined(__CYGWIN32__) || defined(NT)
/*
* Copyright (c) 1993, Intergraph Corporation
*
@@ -167,7 +232,9 @@ static char suffix2[] = ".~~~";
#define strEQ(s1,s2) (strcmp(s1,s2) == 0)
void
-add_suffix(VALUE str, char *suffix)
+ruby_add_suffix(str, suffix)
+ VALUE str;
+ char *suffix;
{
int baselen;
int extlen = strlen(suffix);
@@ -176,12 +243,13 @@ add_suffix(VALUE str, char *suffix)
char buf[1024];
if (RSTRING(str)->len > 1000)
- Fatal("Cannot do inplace edit on long filename (%d characters)", RSTRING(str)->len);
+ rb_fatal("Cannot do inplace edit on long filename (%d characters)",
+ RSTRING(str)->len);
#if defined(DJGPP) || defined(__CYGWIN32__) || defined(NT)
/* Style 0 */
slen = RSTRING(str)->len;
- str_cat(str, suffix, extlen);
+ rb_str_cat(str, suffix, extlen);
#if defined(DJGPP)
if (_USE_LFN) return;
#else
@@ -224,7 +292,7 @@ add_suffix(VALUE str, char *suffix)
fallback:
(void)memcpy(p, strEQ(ext, suffix1) ? suffix2 : suffix1, 5);
}
- str_resize(str, strlen(buf));
+ rb_str_resize(str, strlen(buf));
memcpy(RSTRING(str)->ptr, buf, RSTRING(str)->len);
}
@@ -262,12 +330,10 @@ valid_filename(char *s)
#include <libc/stubs.h>
#include <stdio.h> /* For FILENAME_MAX */
#include <errno.h> /* For errno */
-#include <ctype.h> /* For tolower */
#include <fcntl.h> /* For LFN stuff */
#include <go32.h>
#include <dpmi.h> /* For dpmisim */
#include <crt0.h> /* For crt0 flags */
-#include <sys/stat.h>
#include <libc/dosio.h>
static unsigned use_lfn;
@@ -486,3 +552,256 @@ int main (int argc, char *argv[])
#endif
#endif
+
+/* mm.c */
+
+static int mmkind, mmsize, high, low;
+
+#define A ((int*)a)
+#define B ((int*)b)
+#define C ((int*)c)
+#define D ((int*)d)
+
+static void mmprepare(base, size) void *base; int size;
+{
+#ifdef DEBUG
+ if (sizeof(int) != 4) die("sizeof(int) != 4");
+ if (size <= 0) die("mmsize <= 0");
+#endif
+
+ if ( ((int)base & (4-1)) == 0 && (size & (4-1)) == 0 )
+ if (size >= 16) mmkind = 1;
+ else mmkind = 0;
+ else mmkind = -1;
+
+ mmsize = size;
+ high = (size & (-16));
+ low = (size & 0x0C );
+}
+
+static void mmswap(a, b) register char *a, *b;
+{
+ register int s;
+ if (a == b) return;
+ if (mmkind >= 0) {
+ if (mmkind > 0) {
+ register char *t = a + high;
+ do {
+ s = A[0]; A[0] = B[0]; B[0] = s;
+ s = A[1]; A[1] = B[1]; B[1] = s;
+ s = A[2]; A[2] = B[2]; B[2] = s;
+ s = A[3]; A[3] = B[3]; B[3] = s; a += 16; b += 16;
+ }while (a < t);
+ }
+ if (low != 0) { s = A[0]; A[0] = B[0]; B[0] = s;
+ if (low >= 8) { s = A[1]; A[1] = B[1]; B[1] = s;
+ if (low == 12) {s = A[2]; A[2] = B[2]; B[2] = s;}}}
+ }else{
+ register char *t = a + mmsize;
+ do {s = *a; *a++ = *b; *b++ = s;} while (a < t);
+ }
+}
+
+static void mmswapblock(a, b, size) register char *a, *b; int size;
+{
+ register int s;
+ if (mmkind >= 0) {
+ register char *t = a + (size & (-16)); register int lo = (size & 0x0C);
+ if (size >= 16) {
+ do {
+ s = A[0]; A[0] = B[0]; B[0] = s;
+ s = A[1]; A[1] = B[1]; B[1] = s;
+ s = A[2]; A[2] = B[2]; B[2] = s;
+ s = A[3]; A[3] = B[3]; B[3] = s; a += 16; b += 16;
+ }while (a < t);
+ }
+ if (lo != 0) { s = A[0]; A[0] = B[0]; B[0] = s;
+ if (lo >= 8) { s = A[1]; A[1] = B[1]; B[1] = s;
+ if (lo == 12) {s = A[2]; A[2] = B[2]; B[2] = s;}}}
+ }else{
+ register char *t = a + size;
+ do {s = *a; *a++ = *b; *b++ = s;} while (a < t);
+ }
+}
+
+static void mmrot3(a, b, c) register char *a, *b, *c;
+{
+ register int s;
+ if (mmkind >= 0) {
+ if (mmkind > 0) {
+ register char *t = a + high;
+ do {
+ s = A[0]; A[0] = B[0]; B[0] = C[0]; C[0] = s;
+ s = A[1]; A[1] = B[1]; B[1] = C[1]; C[1] = s;
+ s = A[2]; A[2] = B[2]; B[2] = C[2]; C[2] = s;
+ s = A[3]; A[3] = B[3]; B[3] = C[3]; C[3] = s; a += 16; b += 16; c += 16;
+ }while (a < t);
+ }
+ if (low != 0) { s = A[0]; A[0] = B[0]; B[0] = C[0]; C[0] = s;
+ if (low >= 8) { s = A[1]; A[1] = B[1]; B[1] = C[1]; C[1] = s;
+ if (low == 12) {s = A[2]; A[2] = B[2]; B[2] = C[2]; C[2] = s;}}}
+ }else{
+ register char *t = a + mmsize;
+ do {s = *a; *a++ = *b; *b++ = *c; *c++ = s;} while (a < t);
+ }
+}
+
+/* qs6.c */
+/*****************************************************/
+/* */
+/* qs6 (Quick sort function) */
+/* */
+/* by Tomoyuki Kawamura 1995.4.21 */
+/* kawamura@tokuyama.ac.jp */
+/*****************************************************/
+
+typedef struct { char *LL, *RR; } stack_node; /* Stack structure for L,l,R,r */
+#define PUSH(ll,rr) {top->LL = (ll); top->RR = (rr); ++top;} /* Push L,l,R,r */
+#define POP(ll,rr) {--top; ll = top->LL; rr = top->RR;} /* Pop L,l,R,r */
+
+#define med3(a,b,c) ((*cmp)(a,b)<0 ? \
+ ((*cmp)(b,c)<0 ? b : ((*cmp)(a,c)<0 ? c : a)) : \
+ ((*cmp)(b,c)>0 ? b : ((*cmp)(a,c)<0 ? a : c)) )
+
+void ruby_qsort (base, nel, size, cmp) void* base; int nel; int size; int (*cmp)();
+{
+ register char *l, *r, *m; /* l,r:left,right group m:median point */
+ register int t, eq_l, eq_r; /* eq_l: all items in left group are equal to S */
+ char *L = base; /* left end of curren region */
+ char *R = (char*)base + size*(nel-1); /* right end of current region */
+ int chklim = 63; /* threshold of ordering element check */
+ stack_node stack[32], *top = stack; /* 32 is enough for 32bit CPU */
+
+ if (nel <= 1) return; /* need not to sort */
+ mmprepare( base, size );
+ goto start;
+
+ nxt:
+ if (stack == top) return; /* return if stack is empty */
+ POP(L,R);
+
+ for (;;) {
+ start:
+ if (L + size == R) {if ((*cmp)(L,R) > 0) mmswap(L,R); goto nxt;}/* 2 elements */
+
+ l = L; r = R;
+ t = (r - l + size) / size; /* number of elements */
+ m = l + size * (t >> 1); /* calculate median value */
+
+ if (t >= 60) {
+ register char *m1;
+ register char *m3;
+ if (t >= 200) {
+ t = size*(t>>3); /* number of bytes in splitting 8 */
+ {
+ register char *p1 = l + t;
+ register char *p2 = p1 + t;
+ register char *p3 = p2 + t;
+ m1 = med3( p1, p2, p3 );
+ p1 = m + t;
+ p2 = p1 + t;
+ p3 = p2 + t;
+ m3 = med3( p1, p2, p3 );
+ }
+ }else{
+ t = size*(t>>2); /* number of bytes in splitting 4 */
+ m1 = l + t;
+ m3 = m + t;
+ }
+ m = med3( m1, m, m3 );
+ }
+
+ if ((t = (*cmp)(l,m)) < 0) { /*3-5-?*/
+ if ((t = (*cmp)(m,r)) < 0) { /*3-5-7*/
+ if (chklim && nel >= chklim) { /* check if already ascending order */
+ char *p;
+ chklim = 0;
+ for (p=l; p<r; p+=size) if ((*cmp)(p,p+size) > 0) goto fail;
+ goto nxt;
+ }
+ fail: goto loopA; /*3-5-7*/
+ }
+ if (t > 0) {
+ if ((*cmp)(l,r) <= 0) {mmswap(m,r); goto loopA;} /*3-5-4*/
+ mmrot3(r,m,l); goto loopA; /*3-5-2*/
+ }
+ goto loopB; /*3-5-5*/
+ }
+
+ if (t > 0) { /*7-5-?*/
+ if ((t = (*cmp)(m,r)) > 0) { /*7-5-3*/
+ if (chklim && nel >= chklim) { /* check if already ascending order */
+ char *p;
+ chklim = 0;
+ for (p=l; p<r; p+=size) if ((*cmp)(p,p+size) < 0) goto fail2;
+ while (l<r) {mmswap(l,r); l+=size; r-=size;} /* reverse region */
+ goto nxt;
+ }
+ fail2: mmswap(l,r); goto loopA; /*7-5-3*/
+ }
+ if (t < 0) {
+ if ((*cmp)(l,r) <= 0) {mmswap(l,m); goto loopB;} /*7-5-8*/
+ mmrot3(l,m,r); goto loopA; /*7-5-6*/
+ }
+ mmswap(l,r); goto loopA; /*7-5-5*/
+ }
+
+ if ((t = (*cmp)(m,r)) < 0) {goto loopA;} /*5-5-7*/
+ if (t > 0) {mmswap(l,r); goto loopB;} /*5-5-3*/
+
+ /* deteming splitting type in case 5-5-5 */ /*5-5-5*/
+ for (;;) {
+ if ((l += size) == r) goto nxt; /*5-5-5*/
+ if (l == m) continue;
+ if ((t = (*cmp)(l,m)) > 0) {mmswap(l,r); l = L; goto loopA;} /*575-5*/
+ if (t < 0) {mmswap(L,l); l = L; goto loopB;} /*535-5*/
+ }
+
+ loopA: eq_l = 1; eq_r = 1; /* splitting type A */ /* left <= median < right±¦*/
+ for (;;) {
+ for (;;) {
+ if ((l += size) == r)
+ {l -= size; if (l != m) mmswap(m,l); l -= size; goto fin;}
+ if (l == m) continue;
+ if ((t = (*cmp)(l,m)) > 0) {eq_r = 0; break;}
+ if (t < 0) eq_l = 0;
+ }
+ for (;;) {
+ if (l == (r -= size))
+ {l -= size; if (l != m) mmswap(m,l); l -= size; goto fin;}
+ if (r == m) {m = l; break;}
+ if ((t = (*cmp)(r,m)) < 0) {eq_l = 0; break;}
+ if (t == 0) break;
+ }
+ mmswap(l,r); /* swap left and right */
+ }
+
+ loopB: eq_l = 1; eq_r = 1; /* splitting type B */ /* left < median <= right */
+ for (;;) {
+ for (;;) {
+ if (l == (r -= size))
+ {r += size; if (r != m) mmswap(r,m); r += size; goto fin;}
+ if (r == m) continue;
+ if ((t = (*cmp)(r,m)) < 0) {eq_l = 0; break;}
+ if (t > 0) eq_r = 0;
+ }
+ for (;;) {
+ if ((l += size) == r)
+ {r += size; if (r != m) mmswap(r,m); r += size; goto fin;}
+ if (l == m) {m = r; break;}
+ if ((t = (*cmp)(l,m)) > 0) {eq_r = 0; break;}
+ if (t == 0) break;
+ }
+ mmswap(l,r); /* swap left and right */
+ }
+
+ fin:
+ if (eq_l == 0) /* need to sort left side */
+ if (eq_r == 0) /* need to sort right side */
+ if (l-L < R-r) {PUSH(r,R); R = l;} /* sort left side first */
+ else {PUSH(L,l); L = r;} /* sort right side first */
+ else R = l; /* need to sort left side only */
+ else if (eq_r == 0) L = r; /* need to sort right side only */
+ else goto nxt; /* need not to sort both sides */
+ }
+}