Common subdirectories: ruby-1.6.5.virgin/cygwin and ruby-1.6.5/cygwin
Common subdirectories: ruby-1.6.5.virgin/djgpp and ruby-1.6.5/djgpp
Common subdirectories: ruby-1.6.5.virgin/doc and ruby-1.6.5/doc
diff --unified=2 ruby-1.6.5.virgin/eval.c ruby-1.6.5/eval.c
--- ruby-1.6.5.virgin/eval.c	Mon Sep 17 20:47:02 2001
+++ ruby-1.6.5/eval.c	Sun Oct 21 10:31:40 2001
@@ -111,4 +111,5 @@
 static VALUE umethod_bind _((VALUE, VALUE));
 static VALUE rb_mod_define_method _((int, VALUE*, VALUE));
+static VALUE rb_cStackFrame;
 
 static int scope_vmode;
@@ -543,4 +544,12 @@
 };
 
+struct STACK_FRAME {
+  VALUE klass;
+  VALUE object;
+  VALUE function;
+  VALUE file;
+  VALUE line;
+};
+
 #define BLOCK_D_SCOPE 1
 #define BLOCK_DYNAMIC 2
@@ -4750,4 +4759,152 @@
 }
 
+static VALUE
+stackframe_class(stackframe)
+     VALUE stackframe;
+{
+  struct STACK_FRAME * data;
+  Data_Get_Struct(stackframe, struct STACK_FRAME, data);
+  return data->klass;
+}
+
+static VALUE
+stackframe_function(stackframe)
+     VALUE stackframe;
+{
+  struct STACK_FRAME * data;
+  Data_Get_Struct(stackframe, struct STACK_FRAME, data);
+  return data->function;
+}
+
+static VALUE
+stackframe_object(stackframe)
+     VALUE stackframe;
+{
+  struct STACK_FRAME * data;
+  Data_Get_Struct(stackframe, struct STACK_FRAME, data);
+  return data->object;
+}
+
+static VALUE
+stackframe_file(stackframe)
+     VALUE stackframe;
+{
+  struct STACK_FRAME * data;
+  Data_Get_Struct(stackframe, struct STACK_FRAME, data);
+  return data->file;
+}
+
+static VALUE
+stackframe_line(stackframe)
+     VALUE stackframe;
+{
+  struct STACK_FRAME * data;
+  Data_Get_Struct(stackframe, struct STACK_FRAME, data);
+  return data->line;
+}
+
+static VALUE
+stackframe_inspect(stackframe)
+    VALUE stackframe;
+{
+    struct STACK_FRAME *data;
+    VALUE str;
+    const char *s;
+    Data_Get_Struct(stackframe, struct STACK_FRAME, data);
+    str = rb_str_new2("#<");
+    s = rb_class2name(CLASS_OF(stackframe));
+    rb_str_cat2(str, s);
+    rb_str_cat2(str, " class=");
+    rb_str_append(str, data->klass);
+    rb_str_cat2(str, " function=");
+    rb_str_append(str, data->function);
+    rb_str_cat2(str, " object=");
+    rb_str_append(str, rb_any_to_s(data->object));
+    rb_str_cat2(str, " file=");
+    rb_str_append(str, data->file);
+    rb_str_cat2(str, " line=");
+    rb_str_append(str, rb_fix2str(data->line, 10));
+    rb_str_cat2(str, ">");
+    return str;
+}
+
+static void
+stackframe_mark(data)
+     struct STACK_FRAME *data;
+{
+  rb_gc_mark(data->klass);
+  rb_gc_mark(data->object);
+  rb_gc_mark(data->function);
+  rb_gc_mark(data->file);
+  rb_gc_mark(data->line);
+}
+
+static VALUE 
+make_stackframe(frame, file, line)
+     struct FRAME *frame;
+     char *file;
+     int line;
+{
+  struct STACK_FRAME * stack_frame_data;
+  VALUE stack_frame;
+  stack_frame = Data_Make_Struct(rb_cStackFrame,struct STACK_FRAME,
+                                 stackframe_mark,free,stack_frame_data);
+  stack_frame_data->klass = 
+    rb_str_new2(rb_class2name(frame->last_class));
+  stack_frame_data->object = frame->self;
+  stack_frame_data->function = rb_str_new2(rb_id2name(frame->last_func));
+  stack_frame_data->file = rb_str_new2(file);
+  stack_frame_data->line = INT2FIX(line);
+  return stack_frame;
+}
+
+static VALUE
+stack_frames(lev)
+     int lev;
+{
+    struct FRAME *frame = ruby_frame;
+    VALUE ary;
+    VALUE stack_frame;
+
+    ary = rb_ary_new();
+    if (lev < 0) {
+        stack_frame = make_stackframe(frame, ruby_sourcefile, ruby_sourceline);
+	rb_ary_push(ary, stack_frame);
+    }
+    else {
+	while (lev-- > 0) {
+	    frame = frame->prev;
+	    if (!frame) {
+		ary = Qnil;
+		break;
+	    }
+	}
+    }
+    while (frame && frame->file) {
+        stack_frame = make_stackframe(frame, frame->file, frame->line);
+	rb_ary_push(ary, stack_frame);
+	frame = frame->prev;
+    }
+
+    return ary;
+}
+
+static VALUE
+rb_f_stack_frames(argc, argv)
+    int argc;
+    VALUE *argv;
+{
+    VALUE level;
+    int lev;
+
+    rb_scan_args(argc, argv, "01", &level);
+
+    if (NIL_P(level)) lev = 1;
+    else lev = NUM2INT(level);
+    if (lev < 0) rb_raise(rb_eArgError, "negative level(%d)", lev);
+
+    return stack_frames(lev);
+}
+
 void
 rb_backtrace()
@@ -5931,4 +6088,5 @@
 
     rb_define_global_function("caller", rb_f_caller, -1);
+    rb_define_global_function("stack_frames", rb_f_stack_frames, -1);
 
     rb_define_global_function("exit", rb_f_exit, -1);
@@ -6907,4 +7065,14 @@
     rb_define_method(rb_cUnboundMethod, "unbind", umethod_unbind, 0);
     rb_define_method(rb_cModule, "instance_method", rb_mod_method, 1);
+
+    rb_cStackFrame = rb_define_class("StackFrame", rb_cObject);
+    rb_define_method(rb_cStackFrame, "inspect", stackframe_inspect, 0);
+    rb_define_method(rb_cStackFrame, "to_s", stackframe_inspect, 0);
+    rb_define_method(rb_cStackFrame, "class", stackframe_class, 0);
+    rb_define_method(rb_cStackFrame, "function", stackframe_function, 0);
+    rb_define_method(rb_cStackFrame, "object", stackframe_object, 0);
+    rb_define_method(rb_cStackFrame, "file", stackframe_file, 0);
+    rb_define_method(rb_cStackFrame, "line", stackframe_line, 0);
+
 }
 
Common subdirectories: ruby-1.6.5.virgin/ext and ruby-1.6.5/ext
Common subdirectories: ruby-1.6.5.virgin/lib and ruby-1.6.5/lib
Common subdirectories: ruby-1.6.5.virgin/misc and ruby-1.6.5/misc
Common subdirectories: ruby-1.6.5.virgin/missing and ruby-1.6.5/missing
Common subdirectories: ruby-1.6.5.virgin/sample and ruby-1.6.5/sample
Common subdirectories: ruby-1.6.5.virgin/win32 and ruby-1.6.5/win32
Common subdirectories: ruby-1.6.5.virgin/x68 and ruby-1.6.5/x68

