1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

* enum.c (enum_sort_by): do not use qsort directly. use

rb_ary_sort_bang() instead.  [ruby-dev:24291]

* enum.c (enum_sort_by): pedantic type check added.
  [ruby-dev:24291]

* hash.c (rb_hash_foreach_iter): check iter_lev after each
  iteration.  [ruby-dev:24289]

* array.c (rb_ary_and): element size might change during
  comparison.  [ruby-dev:24290]

* array.c (rb_ary_or): ditto. [ruby-dev:24292]

* array.c (rb_ary_equal): wrong fix. [ruby-dev:24286]


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@6939 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
matz 2004-09-21 03:08:33 +00:00
parent 90ae99b0f0
commit bfabc05a43
11 changed files with 232 additions and 93 deletions

View file

@ -99,6 +99,47 @@ Mon Sep 20 03:37:59 2004 Tanaka Akira <akr@m17n.org>
* ext/zlib/zlib.c (gzfile_read_raw): call readpartial at first.
(Zlib::GzipReader#readpartial): new method.
Mon Sep 20 00:24:19 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
* enum.c (enum_sort_by): do not use qsort directly. use
rb_ary_sort_bang() instead. [ruby-dev:24291]
* enum.c (enum_sort_by): pedantic type check added.
[ruby-dev:24291]
* hash.c (rb_hash_foreach_iter): check iter_lev after each
iteration. [ruby-dev:24289]
* array.c (rb_ary_and): element size might change during
comparison. [ruby-dev:24290]
* array.c (rb_ary_or): ditto. [ruby-dev:24292]
* array.c (rb_ary_equal): wrong fix. [ruby-dev:24286]
Sat Sep 18 15:02:22 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
* array.c (rb_ary_equal): element size might change during
comparison. [ruby-dev:24254]
* array.c (rb_ary_diff): ditto. [ruby-dev:24274]
* array.c (rb_ary_select): ditto. [ruby-dev:24278]
* array.c (rb_ary_delete): ditto. [ruby-dev:24283]
* array.c (rb_ary_rindex): ditto. [ruby-dev:24275]
* array.c (rb_ary_initialize): element size might change during
initializing block. [ruby-dev:24284]
Sat Sep 18 14:10:23 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
* dir.c (dir_s_chdir): avoid memory leak and unnecessary chdir to
the original directory when exception has caused in changing
direcotry or within block. thanks to Johan Holmberg
<holmberg@iar.se> [ruby-core:03446]
Fri Sep 17 20:29:33 2004 NAKAMURA Usaku <usa@ruby-lang.org>
* parse.y: add prototypes for Microsoft compiler.

94
array.c
View file

@ -393,7 +393,7 @@ rb_ary_initialize(argc, argv, ary)
rb_warn("block supersedes default value argument");
}
for (i=0; i<len; i++) {
RARRAY(ary)->ptr[i] = rb_yield(LONG2NUM(i));
rb_ary_store(ary, i, rb_yield(LONG2NUM(i)));
RARRAY(ary)->len = i + 1;
}
}
@ -715,21 +715,28 @@ rb_ary_unshift_m(argc, argv, ary)
return ary;
}
/* faster version - use this if you don't need to treat negative offset */
static inline VALUE
rb_ary_elt(ary, offset)
VALUE ary;
long offset;
{
if (RARRAY(ary)->len == 0) return Qnil;
if (offset < 0 || RARRAY(ary)->len <= offset) {
return Qnil;
}
return RARRAY(ary)->ptr[offset];
}
VALUE
rb_ary_entry(ary, offset)
VALUE ary;
long offset;
{
if (RARRAY(ary)->len == 0) return Qnil;
if (offset < 0) {
offset += RARRAY(ary)->len;
}
if (offset < 0 || RARRAY(ary)->len <= offset) {
return Qnil;
}
return RARRAY(ary)->ptr[offset];
return rb_ary_elt(ary, offset);
}
static VALUE
@ -1011,6 +1018,10 @@ rb_ary_rindex(ary, val)
long i = RARRAY(ary)->len;
while (i--) {
if (i > RARRAY(ary)->len) {
i = RARRAY(ary)->len;
continue;
}
if (rb_equal(RARRAY(ary)->ptr[i], val))
return LONG2NUM(i);
}
@ -1641,17 +1652,36 @@ rb_ary_reverse_m(ary)
return rb_ary_reverse(rb_ary_dup(ary));
}
struct ary_sort_data {
VALUE ary;
VALUE *ptr;
long len;
};
static void
ary_sort_check(data)
struct ary_sort_data *data;
{
if (RARRAY(data->ary)->ptr != data->ptr || RARRAY(data->ary)->len != data->len) {
rb_raise(rb_eArgError, "array modified during sort");
}
}
static int
sort_1(a, b)
sort_1(a, b, data)
VALUE *a, *b;
struct ary_sort_data *data;
{
VALUE retval = rb_yield_values(2, *a, *b);
ary_sort_check(data);
return rb_cmpint(retval, *a, *b);
}
static int
sort_2(ap, bp)
sort_2(ap, bp, data)
VALUE *ap, *bp;
struct ary_sort_data *data;
{
VALUE retval;
long a = (long)*ap, b = (long)*bp;
@ -1666,6 +1696,7 @@ sort_2(ap, bp)
}
retval = rb_funcall(a, id_cmp, 1, b);
ary_sort_check(data);
return rb_cmpint(retval, a, b);
}
@ -1673,8 +1704,12 @@ static VALUE
sort_internal(ary)
VALUE ary;
{
struct ary_sort_data data;
data.ary = ary;
data.ptr = RARRAY(ary)->ptr; data.len = RARRAY(ary)->len;
qsort(RARRAY(ary)->ptr, RARRAY(ary)->len, sizeof(VALUE),
rb_block_given_p()?sort_1:sort_2);
rb_block_given_p()?sort_1:sort_2, &data);
return ary;
}
@ -1878,7 +1913,7 @@ rb_ary_select(ary)
result = rb_ary_new2(RARRAY(ary)->len);
for (i = 0; i < RARRAY(ary)->len; i++) {
if (RTEST(rb_yield(RARRAY(ary)->ptr[i]))) {
rb_ary_push(result, RARRAY(ary)->ptr[i]);
rb_ary_push(result, rb_ary_elt(ary, i));
}
}
return result;
@ -1910,9 +1945,12 @@ rb_ary_delete(ary, item)
rb_ary_modify(ary);
for (i1 = i2 = 0; i1 < RARRAY(ary)->len; i1++) {
if (rb_equal(RARRAY(ary)->ptr[i1], item)) continue;
VALUE e = RARRAY(ary)->ptr[i1];
if (rb_equal(e, item)) continue;
if (i1 != i2) {
RARRAY(ary)->ptr[i2] = RARRAY(ary)->ptr[i1];
if (RARRAY(ary)->len < i2) break;
RARRAY(ary)->ptr[i2] = e;
}
i2++;
}
@ -2138,9 +2176,9 @@ rb_ary_zip(argc, argv, ary)
for (i=0; i<RARRAY(ary)->len; i++) {
VALUE tmp = rb_ary_new2(argc+1);
rb_ary_push(tmp, rb_ary_entry(ary, i));
rb_ary_push(tmp, rb_ary_elt(ary, i));
for (j=0; j<argc; j++) {
rb_ary_push(tmp, rb_ary_entry(argv[j], i));
rb_ary_push(tmp, rb_ary_elt(argv[j], i));
}
rb_yield(tmp);
}
@ -2151,9 +2189,9 @@ rb_ary_zip(argc, argv, ary)
for (i=0; i<len; i++) {
VALUE tmp = rb_ary_new2(argc+1);
rb_ary_push(tmp, rb_ary_entry(ary, i));
rb_ary_push(tmp, rb_ary_elt(ary, i));
for (j=0; j<argc; j++) {
rb_ary_push(tmp, rb_ary_entry(argv[j], i));
rb_ary_push(tmp, rb_ary_elt(argv[j], i));
}
rb_ary_push(result, tmp);
}
@ -2181,7 +2219,7 @@ rb_ary_transpose(ary)
alen = RARRAY(ary)->len;
if (alen == 0) return rb_ary_dup(ary);
for (i=0; i<alen; i++) {
tmp = to_ary(RARRAY(ary)->ptr[i]);
tmp = to_ary(rb_ary_elt(ary, i));
if (elen < 0) { /* first element */
elen = RARRAY(tmp)->len;
result = rb_ary_new2(elen);
@ -2194,7 +2232,7 @@ rb_ary_transpose(ary)
RARRAY(tmp)->len, elen);
}
for (j=0; j<elen; j++) {
rb_ary_store(RARRAY(result)->ptr[j], i, RARRAY(tmp)->ptr[j]);
rb_ary_store(rb_ary_elt(result, j), i, rb_ary_elt(tmp, j));
}
}
return result;
@ -2541,7 +2579,7 @@ rb_ary_equal(ary1, ary2)
}
if (RARRAY(ary1)->len != RARRAY(ary2)->len) return Qfalse;
for (i=0; i<RARRAY(ary1)->len; i++) {
if (!rb_equal(RARRAY(ary1)->ptr[i], RARRAY(ary2)->ptr[i]))
if (!rb_equal(rb_ary_elt(ary1, i), rb_ary_elt(ary2, i)))
return Qfalse;
}
return Qtrue;
@ -2709,7 +2747,7 @@ rb_ary_diff(ary1, ary2)
for (i=0; i<RARRAY(ary1)->len; i++) {
if (st_lookup(RHASH(hash)->tbl, RARRAY(ary1)->ptr[i], 0)) continue;
rb_ary_push(ary3, RARRAY(ary1)->ptr[i]);
rb_ary_push(ary3, rb_ary_elt(ary1, i));
}
return ary3;
}
@ -2738,9 +2776,9 @@ rb_ary_and(ary1, ary2)
hash = ary_make_hash(ary2, 0);
for (i=0; i<RARRAY(ary1)->len; i++) {
VALUE v = RARRAY(ary1)->ptr[i];
VALUE v = rb_ary_elt(ary1, i);
if (st_delete(RHASH(hash)->tbl, (st_data_t*)&v, 0)) {
rb_ary_push(ary3, RARRAY(ary1)->ptr[i]);
rb_ary_push(ary3, v);
}
}
@ -2771,15 +2809,15 @@ rb_ary_or(ary1, ary2)
hash = ary_make_hash(ary1, ary2);
for (i=0; i<RARRAY(ary1)->len; i++) {
v = RARRAY(ary1)->ptr[i];
v = rb_ary_elt(ary1, i);
if (st_delete(RHASH(hash)->tbl, (st_data_t*)&v, 0)) {
rb_ary_push(ary3, RARRAY(ary1)->ptr[i]);
rb_ary_push(ary3, v);
}
}
for (i=0; i<RARRAY(ary2)->len; i++) {
v = RARRAY(ary2)->ptr[i];
v = rb_ary_elt(ary2, i);
if (st_delete(RHASH(hash)->tbl, (st_data_t*)&v, 0)) {
rb_ary_push(ary3, RARRAY(ary2)->ptr[i]);
rb_ary_push(ary3, v);
}
}
return ary3;

View file

@ -380,7 +380,7 @@ AC_CHECK_HEADERS(stdlib.h string.h unistd.h limits.h sys/file.h sys/ioctl.h\
fcntl.h sys/fcntl.h sys/select.h sys/time.h sys/times.h sys/param.h\
syscall.h pwd.h grp.h a.out.h utime.h memory.h direct.h sys/resource.h \
sys/mkdev.h sys/utime.h netinet/in_systm.h float.h ieeefp.h pthread.h \
ucontext.h intrinsics.h)
ucontext.h intrinsics.h unwind.h)
dnl Checks for typedefs, structures, and compiler characteristics.
AC_TYPE_UID_T
@ -522,6 +522,22 @@ AC_C_CHAR_UNSIGNED
AC_C_INLINE
AC_C_VOLATILE
if test x"$target_cpu" = xia64; then
if test x"$ac_cv_header_unwind_h" = xyes; then
LIBS="-lunwind $LIBS"
else
AC_CACHE_CHECK(IA64 backing store member in mcontext_t, rb_cv_ia64_bspstore,
[rb_cv_ia64_bspstore=no;
for mem in mc_special.bspstore sc_ar_bsp; do
AC_TRY_COMPILE([#include <ucontext.h>
],[ucontext_t ctx; ctx.uc_mcontext.$mem = 0;], [rb_cv_ia64_bspstore=$mem; break])
done])
if test "$rb_cv_ia64_bspstore" != no; then
AC_DEFINE_UNQUOTED(IA64_BSPSTORE, $rb_cv_ia64_bspstore)
fi
fi
fi
AC_CACHE_CHECK(whether right shift preserve sign bit, rb_cv_rshift_sign,
[AC_TRY_RUN([
int

51
dir.c
View file

@ -677,36 +677,42 @@ dir_close(dir)
static void
dir_chdir(path)
const char *path;
VALUE path;
{
if (chdir(path) < 0)
rb_sys_fail(path);
if (chdir(RSTRING(path)->ptr) < 0)
rb_sys_fail(RSTRING(path)->ptr);
}
static int chdir_blocking = 0;
static VALUE chdir_thread = Qnil;
struct chdir_data {
char *dist;
VALUE path;
VALUE old_path, new_path;
int done;
};
static VALUE
chdir_yield(args)
struct chdir_data *args;
{
dir_chdir(args->dist);
return rb_yield(args->path);
dir_chdir(args->new_path);
args->done = Qtrue;
chdir_blocking++;
if (chdir_thread == Qnil)
chdir_thread = rb_thread_current();
return rb_yield(args->new_path);
}
static VALUE
chdir_restore(path)
char *path;
chdir_restore(args)
struct chdir_data *args;
{
chdir_blocking--;
if (chdir_blocking == 0)
chdir_thread = Qnil;
dir_chdir(path);
if (args->done) {
chdir_blocking--;
if (chdir_blocking == 0)
chdir_thread = Qnil;
dir_chdir(args->old_path);
}
return Qnil;
}
@ -756,19 +762,18 @@ dir_s_chdir(argc, argv, obj)
VALUE obj;
{
VALUE path = Qnil;
char *dist = "";
rb_secure(2);
if (rb_scan_args(argc, argv, "01", &path) == 1) {
FilePathValue(path);
dist = RSTRING(path)->ptr;
}
else {
dist = getenv("HOME");
const char *dist = getenv("HOME");
if (!dist) {
dist = getenv("LOGDIR");
if (!dist) rb_raise(rb_eArgError, "HOME/LOGDIR not set");
}
path = rb_str_new2(dist);
}
if (chdir_blocking > 0) {
@ -777,17 +782,15 @@ dir_s_chdir(argc, argv, obj)
}
if (rb_block_given_p()) {
char *cwd = my_getcwd();
struct chdir_data args;
char *cwd = my_getcwd();
chdir_blocking++;
if (chdir_thread == Qnil)
chdir_thread = rb_thread_current();
args.dist = dist;
args.path = path;
return rb_ensure(chdir_yield, (VALUE)&args, chdir_restore, (VALUE)cwd);
args.old_path = rb_tainted_str_new2(cwd); free(cwd);
args.new_path = path;
args.done = Qfalse;
return rb_ensure(chdir_yield, (VALUE)&args, chdir_restore, (VALUE)&args);
}
dir_chdir(dist);
dir_chdir(path);
return INT2FIX(0);
}

17
enum.c
View file

@ -397,14 +397,17 @@ sort_by_i(i, ary)
return Qnil;
}
static int
sort_by_cmp(a, b)
VALUE *a, *b;
static VALUE
sort_by_cmp(values, ary)
VALUE values;
{
VALUE retval;
VALUE a = RARRAY(values)->ptr[0];
VALUE b = RARRAY(values)->ptr[1];
retval = rb_funcall(RARRAY(*a)->ptr[0], id_cmp, 1, RARRAY(*b)->ptr[0]);
return rb_cmpint(retval, *a, *b);
/* pedantic check; they must be arrays */
Check_Type(a, T_ARRAY);
Check_Type(b, T_ARRAY);
return rb_funcall(RARRAY(a)->ptr[0], id_cmp, 1, RARRAY(b)->ptr[0]);
}
/*
@ -491,7 +494,7 @@ enum_sort_by(obj)
}
rb_iterate(rb_each, obj, sort_by_i, ary);
if (RARRAY(ary)->len > 1) {
qsort(RARRAY(ary)->ptr, RARRAY(ary)->len, sizeof(VALUE), sort_by_cmp);
rb_iterate(rb_ary_sort_bang, ary, sort_by_cmp, ary);
}
for (i=0; i<RARRAY(ary)->len; i++) {
VALUE e = RARRAY(ary)->ptr[i];

35
eval.c
View file

@ -9316,10 +9316,14 @@ Init_Binding()
*/
#define __libc_ia64_register_backing_store_base (4ULL<<61)
#else
#ifdef HAVE_UNWIND_H
#include <unwind.h>
#else
#pragma weak __libc_ia64_register_backing_store_base
extern unsigned long __libc_ia64_register_backing_store_base;
#endif
#endif
#endif
/* Windows SEH refers data on the stack. */
#undef SAVE_WIN32_EXCEPTION_LIST
@ -9779,19 +9783,24 @@ rb_thread_save_context(th)
MEMCPY(th->stk_ptr, th->stk_pos, VALUE, th->stk_len);
#ifdef __ia64__
{
ucontext_t ctx;
VALUE *top, *bot;
#ifdef HAVE_UNWIND_H
_Unwind_Context *unwctx = _UNW_createContextForSelf();
_UNW_currentContext(unwctx);
bot = (VALUE*)(long)_UNW_getAR(unwctx, _UNW_AR_BSP);
top = (VALUE*)(long)_UNW_getAR(unwctx, _UNW_AR_BSPSTORE);
_UNW_destroyContext(unwctx);
#else
ucontext_t ctx;
getcontext(&ctx);
bot = (VALUE*)__libc_ia64_register_backing_store_base;
#if defined(__FreeBSD__)
top = (VALUE*)ctx.uc_mcontext.mc_special.bspstore;
#else
top = (VALUE*)ctx.uc_mcontext.sc_ar_bsp;
top = (VALUE*)ctx.uc_mcontext.IA64_BSPSTORE;
#endif
th->bstr_len = top - bot;
REALLOC_N(th->bstr_ptr, VALUE, th->bstr_len);
MEMCPY(th->bstr_ptr, (VALUE*)__libc_ia64_register_backing_store_base, VALUE, th->bstr_len);
MEMCPY(th->bstr_ptr, bot, VALUE, th->bstr_len);
}
#endif
#ifdef SAVE_WIN32_EXCEPTION_LIST
@ -9934,7 +9943,19 @@ rb_thread_restore_context(th, exit)
FLUSH_REGISTER_WINDOWS;
MEMCPY(tmp->stk_pos, tmp->stk_ptr, VALUE, tmp->stk_len);
#ifdef __ia64__
MEMCPY((VALUE*)__libc_ia64_register_backing_store_base, tmp->bstr_ptr, VALUE, tmp->bstr_len);
{
VALUE *base;
#ifdef HAVE_UNWIND_H
_Unwind_Context *unwctx = _UNW_createContextForSelf();
_UNW_currentContext(unwctx);
base = (VALUE*)(long)_UNW_getAR(unwctx, _UNW_AR_BSP);
_UNW_destroyContext(unwctx);
#else
base = (VALUE*)__libc_ia64_register_backing_store_base;
#endif
MEMCPY(base, tmp->bstr_ptr, VALUE, tmp->bstr_len);
}
#endif
tval = rb_lastline_get();

21
gc.c
View file

@ -39,10 +39,14 @@
*/
#define __libc_ia64_register_backing_store_base (4ULL<<61)
#else
#ifdef HAVE_UNWIND_H
#include <unwind.h>
#else
#pragma weak __libc_ia64_register_backing_store_base
extern unsigned long __libc_ia64_register_backing_store_base;
#endif
#endif
#endif
#if defined _WIN32 || defined __CYGWIN__
#include <windows.h>
@ -610,6 +614,8 @@ mark_locations_array(x, n)
register VALUE *x;
register long n;
{
VALUE tmp;
while (n--) {
if (is_pointer_to_heap((void *)*x)) {
gc_mark(*x, 0);
@ -1345,14 +1351,21 @@ rb_gc()
{
ucontext_t ctx;
VALUE *top, *bot;
#ifdef HAVE_UNWIND_H
_Unwind_Context *unwctx = _UNW_createContextForSelf();
#endif
getcontext(&ctx);
mark_locations_array((VALUE*)&ctx.uc_mcontext,
((size_t)(sizeof(VALUE)-1 + sizeof ctx.uc_mcontext)/sizeof(VALUE)));
bot = (VALUE*)__libc_ia64_register_backing_store_base;
#if defined(__FreeBSD__)
top = (VALUE*)ctx.uc_mcontext.mc_special.bspstore;
#ifdef HAVE_UNWIND_H
_UNW_currentContext(unwctx);
bot = (VALUE*)(long)_UNW_getAR(unwctx, _UNW_AR_BSP);
top = (VALUE*)(long)_UNW_getAR(unwctx, _UNW_AR_BSPSTORE);
_UNW_destroyContext(unwctx);
#else
top = (VALUE*)ctx.uc_mcontext.sc_ar_bsp;
bot = (VALUE*)__libc_ia64_register_backing_store_base;
top = (VALUE*)ctx.uc_mcontext.IA64_BSPSTORE;
#endif
rb_gc_mark_locations(bot, top);
}

6
hash.c
View file

@ -131,9 +131,13 @@ rb_hash_foreach_iter(key, value, arg)
if (key == Qundef) return ST_CONTINUE;
status = (*arg->func)(key, value, arg->arg);
if (RHASH(arg->hash)->tbl != tbl || RHASH(arg->hash)->tbl->bins != bins){
if (RHASH(arg->hash)->tbl != tbl ||
RHASH(arg->hash)->tbl->bins != bins) {
rb_raise(rb_eIndexError, "rehash occurred during iteration");
}
if (RHASH(arg->hash)->iter_lev == 0) {
rb_raise(rb_eArgError, "block re-entered");
}
return status;
}

View file

@ -92,7 +92,6 @@ def DelegateClass(superclass)
@_dc_obj = obj
end
def method_missing(m, *args)
p [m, *args]
unless @_dc_obj.respond_to?(m)
super(m, *args)
end

37
util.c
View file

@ -466,15 +466,16 @@ typedef struct { char *LL, *RR; } stack_node; /* Stack structure for L,l,R,r */
#define PUSH(ll,rr) do { top->LL = (ll); top->RR = (rr); ++top; } while (0) /* Push L,l,R,r */
#define POP(ll,rr) do { --top; ll = top->LL; rr = top->RR; } while (0) /* 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)))
#define med3(a,b,c) ((*cmp)(a,b,d)<0 ? \
((*cmp)(b,c,d)<0 ? b : ((*cmp)(a,c,d)<0 ? c : a)) : \
((*cmp)(b,c,d)>0 ? b : ((*cmp)(a,c,d)<0 ? a : c)))
void ruby_qsort (base, nel, size, cmp)
void ruby_qsort (base, nel, size, cmp, d)
void* base;
const int nel;
const int size;
int (*cmp)();
void *d;
{
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 */
@ -495,7 +496,7 @@ void ruby_qsort (base, nel, size, cmp)
for (;;) {
start:
if (L + size == R) { /* 2 elements */
if ((*cmp)(L,R) > 0) mmswap(L,R); goto nxt;
if ((*cmp)(L,R,d) > 0) mmswap(L,R); goto nxt;
}
l = L; r = R;
@ -526,49 +527,49 @@ void ruby_qsort (base, nel, size, cmp)
m = med3(m1, m, m3);
}
if ((t = (*cmp)(l,m)) < 0) { /*3-5-?*/
if ((t = (*cmp)(m,r)) < 0) { /*3-5-7*/
if ((t = (*cmp)(l,m,d)) < 0) { /*3-5-?*/
if ((t = (*cmp)(m,r,d)) < 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;
for (p=l; p<r; p+=size) if ((*cmp)(p,p+size,d) > 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*/
if ((*cmp)(l,r,d) <= 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 ((t = (*cmp)(m,r,d)) > 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;
for (p=l; p<r; p+=size) if ((*cmp)(p,p+size,d) < 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*/
if ((*cmp)(l,r,d) <= 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 = (*cmp)(m,r,d)) < 0) {goto loopA;} /*5-5-7*/
if (t > 0) {mmswap(l,r); goto loopB;} /*5-5-3*/
/* determining 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 = (*cmp)(l,m,d)) > 0) {mmswap(l,r); l = L; goto loopA;}/*575-5*/
if (t < 0) {mmswap(L,l); l = L; goto loopB;} /*535-5*/
}
@ -578,14 +579,14 @@ void ruby_qsort (base, nel, size, cmp)
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 = (*cmp)(l,m,d)) > 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 = (*cmp)(r,m,d)) < 0) {eq_l = 0; break;}
if (t == 0) break;
}
mmswap(l,r); /* swap left and right */
@ -597,14 +598,14 @@ void ruby_qsort (base, nel, size, cmp)
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 = (*cmp)(r,m,d)) < 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 = (*cmp)(l,m,d)) > 0) {eq_r = 0; break;}
if (t == 0) break;
}
mmswap(l,r); /* swap left and right */

4
util.h
View file

@ -43,8 +43,8 @@ unsigned long scan_hex _((const char*, int, int*));
void ruby_add_suffix();
#endif
void ruby_qsort _((void*, const int, const int, int (*)()));
#define qsort(b,n,s,c) ruby_qsort(b,n,s,c)
void ruby_qsort _((void*, const int, const int, int (*)(), void*));
#define qsort(b,n,s,c,d) ruby_qsort(b,n,s,c,d)
void ruby_setenv _((const char*, const char*));
void ruby_unsetenv _((const char*));