debase 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: b4c8f78116379934df37e337705708147ce878c3
4
+ data.tar.gz: 6a037e645748a877e64fd2548025b9d72c2fb698
5
+ SHA512:
6
+ metadata.gz: f35b489310522fe41416655463caceb0c63c527c37e446d79629b6aa8850c00f7787b9a805b2d35ddf25cd1d96de57daa5dabc0fbab00ac1869fa1de9e0f3206
7
+ data.tar.gz: fcaf13c8b8eb973d419a2ead16c8a2c35904685888ea7382be6a9d627538126e5380666955fcd6d09c556fe723a3a991512622be725f5ac7745e6a932b7056d3
@@ -0,0 +1,8 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
5
+ ext/*.o
6
+ ext/*.bundle
7
+ ext/Makefile
8
+ ext/*.log
@@ -0,0 +1,4 @@
1
+ language: ruby
2
+ rvm:
3
+ - ruby-head
4
+ - 2.0.0
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in debase.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,23 @@
1
+ Copyright (C) 2005 Kent Sibilev <ksibilev@yahoo.com>
2
+ All rights reserved.
3
+ *
4
+ Redistribution and use in source and binary forms, with or without
5
+ modification, are permitted provided that the following conditions
6
+ are met:
7
+ 1. Redistributions of source code must retain the above copyright
8
+ notice, this list of conditions and the following disclaimer.
9
+ 2. Redistributions in binary form must reproduce the above copyright
10
+ notice, this list of conditions and the following disclaimer in the
11
+ documentation and/or other materials provided with the distribution.
12
+ *
13
+ THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
14
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16
+ ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
17
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19
+ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23
+ SUCH DAMAGE.
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2007-2008, debug-commons team
2
+ Copyright (c) 2012, Dennis Ushakov
3
+
4
+ Permission is hereby granted, free of charge, to any person obtaining
5
+ a copy of this software and associated documentation files (the
6
+ "Software"), to deal in the Software without restriction, including
7
+ without limitation the rights to use, copy, modify, merge, publish,
8
+ distribute, sublicense, and/or sell copies of the Software, and to
9
+ permit persons to whom the Software is furnished to do so, subject to
10
+ the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be
13
+ included in all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+
data/README ADDED
@@ -0,0 +1,22 @@
1
+ = debase
2
+
3
+ == Overview
4
+
5
+ debase is a fast implementation of the standard debugger debug.rb for
6
+ Ruby 2.0.0. The faster execution speed and 2.0.0 compatibility is achieved
7
+ by utilizing a TracePoint mechanism in the Ruby C API.
8
+
9
+ == Requirements
10
+
11
+ debase requires Ruby 2.0.0 or higher.
12
+
13
+ == Install
14
+
15
+ debase is provided as a RubyGem. To install:
16
+
17
+ <tt>gem install debase</tt>
18
+
19
+ == License
20
+
21
+ debase contains parts of the code from ruby-debug-base gem.
22
+ See MIT_LICENSE and LICENSE for license information.
@@ -0,0 +1,34 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rake/testtask'
3
+
4
+ BASE_TEST_FILE_LIST = Dir['test/**/test_*.rb']
5
+
6
+ desc "Remove built files"
7
+ task :clean do
8
+ cd "ext" do
9
+ if File.exists?("Makefile")
10
+ sh "make clean"
11
+ rm "Makefile"
12
+ end
13
+ derived_files = Dir.glob(".o") + Dir.glob("*.so") + Dir.glob("*.bundle")
14
+ rm derived_files unless derived_files.empty?
15
+ end
16
+ end
17
+
18
+ desc "Create the core debase shared library extension"
19
+ task :lib => :clean do
20
+ Dir.chdir("ext") do
21
+ system("#{Gem.ruby} extconf.rb && make")
22
+ exit $?.to_i if $?.to_i != 0
23
+ end
24
+ end
25
+
26
+ desc "Test debase."
27
+ Rake::TestTask.new(:test) do |t|
28
+ t.libs += ['./ext', './lib']
29
+ t.test_files = FileList[BASE_TEST_FILE_LIST]
30
+ t.verbose = true
31
+ end
32
+ task :test => :lib
33
+
34
+ task :default => :test
@@ -0,0 +1,30 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "debase/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "debase"
7
+ s.version = Debase::VERSION
8
+ s.authors = ["Dennis Ushakov"]
9
+ s.email = ["dennis.ushakov@gmail.com"]
10
+ s.homepage = ""
11
+ s.summary = %q{debase is a fast implementation of the standard Ruby debugger debug.rb for Ruby 2.0}
12
+ s.description = <<-EOF
13
+ debase is a fast implementation of the standard Ruby debugger debug.rb for Ruby 2.0.
14
+ It is implemented by utilizing a new Ruby TracePoint class. The core component
15
+ provides support that front-ends can build on. It provides breakpoint
16
+ handling, bindings for stack frames among other things.
17
+ EOF
18
+
19
+ s.rubyforge_project = "debase"
20
+
21
+ s.files = `git ls-files`.split("\n")
22
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
23
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
24
+ s.require_paths = ["lib"]
25
+
26
+ s.extensions = ["ext/extconf.rb"]
27
+
28
+ s.add_development_dependency "test-unit"
29
+ s.add_development_dependency "rake"
30
+ end
@@ -0,0 +1,233 @@
1
+ #include <debase_internals.h>
2
+
3
+ #ifdef _WIN32
4
+ #include <ctype.h>
5
+ #endif
6
+
7
+ #if defined DOSISH
8
+ #define isdirsep(x) ((x) == '/' || (x) == '\\')
9
+ #else
10
+ #define isdirsep(x) ((x) == '/')
11
+ #endif
12
+
13
+ static VALUE cBreakpoint;
14
+ static int breakpoint_max;
15
+
16
+ extern VALUE
17
+ catchpoint_hit_count(VALUE catchpoints, VALUE exception, VALUE *exception_name) {
18
+ VALUE ancestors;
19
+ VALUE expn_class;
20
+ VALUE aclass;
21
+ VALUE mod_name;
22
+ VALUE hit_count;
23
+ int i;
24
+
25
+ if (catchpoints == Qnil /*|| st_get_num_entries(RHASH_TBL(rdebug_catchpoints)) == 0)*/)
26
+ return Qnil;
27
+ expn_class = rb_obj_class(exception);
28
+ ancestors = rb_mod_ancestors(expn_class);
29
+ for(i = 0; i < RARRAY_LEN(ancestors); i++)
30
+ {
31
+ aclass = rb_ary_entry(ancestors, i);
32
+ mod_name = rb_mod_name(aclass);
33
+ hit_count = rb_hash_aref(catchpoints, mod_name);
34
+ if(hit_count != Qnil)
35
+ {
36
+ *exception_name = mod_name;
37
+ return hit_count;
38
+ }
39
+ }
40
+ return Qnil;
41
+ }
42
+
43
+ static void
44
+ Breakpoint_mark(breakpoint_t *breakpoint)
45
+ {
46
+ rb_gc_mark(breakpoint->source);
47
+ rb_gc_mark(breakpoint->expr);
48
+ }
49
+
50
+ static VALUE
51
+ Breakpoint_create(VALUE klass)
52
+ {
53
+ breakpoint_t *breakpoint;
54
+
55
+ breakpoint = ALLOC(breakpoint_t);
56
+ return Data_Wrap_Struct(klass, Breakpoint_mark, xfree, breakpoint);
57
+ }
58
+
59
+ static VALUE
60
+ Breakpoint_initialize(VALUE self, VALUE source, VALUE pos, VALUE expr)
61
+ {
62
+ breakpoint_t *breakpoint;
63
+
64
+ Data_Get_Struct(self, breakpoint_t, breakpoint);
65
+ breakpoint->id = ++breakpoint_max;
66
+ breakpoint->source = StringValue(source);
67
+ breakpoint->line = FIX2INT(pos);
68
+ breakpoint->enabled = Qtrue;
69
+ breakpoint->expr = NIL_P(expr) ? expr : StringValue(expr);
70
+
71
+ return Qnil;
72
+ }
73
+
74
+ static VALUE
75
+ Breakpoint_remove(VALUE self, VALUE breakpoints, VALUE id_value)
76
+ {
77
+ int i;
78
+ int id;
79
+ VALUE breakpoint_object;
80
+ breakpoint_t *breakpoint;
81
+
82
+ if (breakpoints == Qnil) return Qnil;
83
+
84
+ id = FIX2INT(id_value);
85
+
86
+ for(i = 0; i < RARRAY_LEN(breakpoints); i++)
87
+ {
88
+ breakpoint_object = rb_ary_entry(breakpoints, i);
89
+ Data_Get_Struct(breakpoint_object, breakpoint_t, breakpoint);
90
+ if(breakpoint->id == id)
91
+ {
92
+ rb_ary_delete_at(breakpoints, i);
93
+ return breakpoint_object;
94
+ }
95
+ }
96
+ return Qnil;
97
+ }
98
+
99
+ static VALUE
100
+ Breakpoint_id(VALUE self)
101
+ {
102
+ breakpoint_t *breakpoint;
103
+
104
+ Data_Get_Struct(self, breakpoint_t, breakpoint);
105
+ return INT2FIX(breakpoint->id);
106
+ }
107
+
108
+ static VALUE
109
+ Breakpoint_source(VALUE self)
110
+ {
111
+ breakpoint_t *breakpoint;
112
+
113
+ Data_Get_Struct(self, breakpoint_t, breakpoint);
114
+ return breakpoint->source;
115
+ }
116
+
117
+ static VALUE
118
+ Breakpoint_pos(VALUE self)
119
+ {
120
+ breakpoint_t *breakpoint;
121
+
122
+ Data_Get_Struct(self, breakpoint_t, breakpoint);
123
+ return INT2FIX(breakpoint->line);
124
+ }
125
+
126
+ int
127
+ filename_cmp_impl(VALUE source, char *file)
128
+ {
129
+ char *source_ptr, *file_ptr;
130
+ long s_len, f_len, min_len;
131
+ long s,f;
132
+ int dirsep_flag = 0;
133
+
134
+ s_len = RSTRING_LEN(source);
135
+ f_len = strlen(file);
136
+ min_len = s_len < f_len ? s_len : f_len;
137
+
138
+ source_ptr = RSTRING_PTR(source);
139
+ file_ptr = file;
140
+
141
+ for( s = s_len - 1, f = f_len - 1; s >= s_len - min_len && f >= f_len - min_len; s--, f-- )
142
+ {
143
+ if((source_ptr[s] == '.' || file_ptr[f] == '.') && dirsep_flag)
144
+ return 1;
145
+ if(isdirsep(source_ptr[s]) && isdirsep(file_ptr[f]))
146
+ dirsep_flag = 1;
147
+ #ifdef DOSISH_DRIVE_LETTER
148
+ else if (s == 0)
149
+ return(toupper(source_ptr[s]) == toupper(file_ptr[f]));
150
+ #endif
151
+ else if(source_ptr[s] != file_ptr[f])
152
+ return 0;
153
+ }
154
+ return 1;
155
+ }
156
+
157
+ int
158
+ filename_cmp(VALUE source, char *file)
159
+ {
160
+ #ifdef _WIN32
161
+ return filename_cmp_impl(source, file);
162
+ #else
163
+ #ifdef PATH_MAX
164
+ char path[PATH_MAX + 1];
165
+ path[PATH_MAX] = 0;
166
+ return filename_cmp_impl(source, realpath(file, path) != NULL ? path : file);
167
+ #else
168
+ char *path;
169
+ int result;
170
+ path = realpath(file, NULL);
171
+ result = filename_cmp_impl(source, path == NULL ? file : path);
172
+ free(path);
173
+ return result;
174
+ #endif
175
+ #endif
176
+ }
177
+
178
+ static int
179
+ check_breakpoint_by_pos(VALUE breakpoint_object, char *file, int line)
180
+ {
181
+ breakpoint_t *breakpoint;
182
+
183
+ if(breakpoint_object == Qnil)
184
+ return 0;
185
+ Data_Get_Struct(breakpoint_object, breakpoint_t, breakpoint);
186
+ if (Qtrue != breakpoint->enabled) return 0;
187
+ if(breakpoint->line != line)
188
+ return 0;
189
+ if(filename_cmp(breakpoint->source, file))
190
+ return 1;
191
+ return 0;
192
+ }
193
+
194
+ static VALUE
195
+ Breakpoint_find(VALUE self, VALUE breakpoints, VALUE source, VALUE pos, VALUE binding)
196
+ {
197
+ return breakpoint_find(breakpoints, source, pos, binding);
198
+ }
199
+
200
+ extern VALUE
201
+ breakpoint_find(VALUE breakpoints, VALUE source, VALUE pos, VALUE binding)
202
+ {
203
+ VALUE breakpoint_object;
204
+ char *file;
205
+ int line;
206
+ int i;
207
+
208
+ file = RSTRING_PTR(source);
209
+ line = FIX2INT(pos);
210
+ for(i = 0; i < RARRAY_LEN(breakpoints); i++)
211
+ {
212
+ breakpoint_object = rb_ary_entry(breakpoints, i);
213
+ if (check_breakpoint_by_pos(breakpoint_object, file, line))
214
+ {
215
+ return breakpoint_object;
216
+ }
217
+ }
218
+ return Qnil;
219
+ }
220
+
221
+ extern void
222
+ Init_breakpoint(VALUE mDebase)
223
+ {
224
+ breakpoint_max = 0;
225
+ cBreakpoint = rb_define_class_under(mDebase, "Breakpoint", rb_cObject);
226
+ rb_define_singleton_method(cBreakpoint, "find", Breakpoint_find, 4);
227
+ rb_define_singleton_method(cBreakpoint, "remove", Breakpoint_remove, 2);
228
+ rb_define_method(cBreakpoint, "initialize", Breakpoint_initialize, 3);
229
+ rb_define_method(cBreakpoint, "id", Breakpoint_id, 0);
230
+ rb_define_method(cBreakpoint, "source", Breakpoint_source, 0);
231
+ rb_define_method(cBreakpoint, "pos", Breakpoint_pos, 0);
232
+ rb_define_alloc_func(cBreakpoint, Breakpoint_create);
233
+ }
@@ -0,0 +1,377 @@
1
+ #include <debase_internals.h>
2
+
3
+ static VALUE cContext;
4
+ static int thnum_current = 0;
5
+
6
+ static VALUE idAlive;
7
+
8
+ /* "Step", "Next" and "Finish" do their work by saving information
9
+ about where to stop next. reset_stopping_points removes/resets this
10
+ information. */
11
+ extern void
12
+ reset_stepping_stop_points(debug_context_t *context)
13
+ {
14
+ context->dest_frame = -1;
15
+ context->stop_line = -1;
16
+ context->stop_next = -1;
17
+ }
18
+
19
+ static inline VALUE
20
+ Context_thnum(VALUE self) {
21
+ debug_context_t *context;
22
+ Data_Get_Struct(self, debug_context_t, context);
23
+ return INT2FIX(context->thnum);
24
+ }
25
+
26
+ static inline void
27
+ delete_frame(debug_context_t *context)
28
+ {
29
+ debug_frame_t *frame;
30
+
31
+ frame = context->stack;
32
+ context->stack = frame->prev;
33
+ context->stack_size--;
34
+ xfree(frame);
35
+ }
36
+
37
+ static inline void
38
+ fill_frame(debug_frame_t *frame, char* file, int line, VALUE binding, VALUE self)
39
+ {
40
+ frame->file = file;
41
+ frame->line = line;
42
+ frame->binding = binding;
43
+ frame->self = self;
44
+ }
45
+
46
+ static inline VALUE
47
+ Context_stack_size(VALUE self)
48
+ {
49
+ debug_context_t *context;
50
+ Data_Get_Struct(self, debug_context_t, context);
51
+ return INT2FIX(context->stack_size);
52
+ }
53
+
54
+ static inline VALUE
55
+ Context_thread(VALUE self)
56
+ {
57
+ debug_context_t *context;
58
+ Data_Get_Struct(self, debug_context_t, context);
59
+ return context->thread;
60
+ }
61
+
62
+ static inline VALUE
63
+ Context_dead(VALUE self)
64
+ {
65
+ debug_context_t *context;
66
+ Data_Get_Struct(self, debug_context_t, context);
67
+ return IS_THREAD_ALIVE(context->thread) ? Qfalse : Qtrue;
68
+ }
69
+
70
+ extern VALUE
71
+ Context_ignored(VALUE self)
72
+ {
73
+ debug_context_t *context;
74
+
75
+ if (self == Qnil) return Qtrue;
76
+ Data_Get_Struct(self, debug_context_t, context);
77
+ return CTX_FL_TEST(context, CTX_FL_IGNORE) ? Qtrue : Qfalse;
78
+ }
79
+
80
+ extern void
81
+ push_frame(VALUE context_object, char* file, int line, VALUE binding, VALUE self)
82
+ {
83
+ debug_context_t *context;
84
+ debug_frame_t *frame;
85
+ Data_Get_Struct(context_object, debug_context_t, context);
86
+
87
+ frame = ALLOC(debug_frame_t);
88
+ fill_frame(frame, file, line, binding, self);
89
+ frame->prev = context->stack;
90
+ context->stack = frame;
91
+ context->stack_size++;
92
+ }
93
+
94
+ extern void
95
+ pop_frame(VALUE context_object)
96
+ {
97
+ debug_context_t *context;
98
+ Data_Get_Struct(context_object, debug_context_t, context);
99
+
100
+ if (context->stack_size > 0) {
101
+ delete_frame(context);
102
+ }
103
+ }
104
+
105
+ extern void
106
+ update_frame(VALUE context_object, char* file, int line, VALUE binding, VALUE self)
107
+ {
108
+ debug_context_t *context;
109
+ Data_Get_Struct(context_object, debug_context_t, context);
110
+
111
+ if (context->stack_size == 0) {
112
+ push_frame(context_object, file, line, binding, self);
113
+ return;
114
+ }
115
+ fill_frame(context->stack, file, line, binding, self);
116
+ }
117
+
118
+ static void
119
+ Context_mark(debug_context_t *context)
120
+ {
121
+ debug_frame_t *frame;
122
+
123
+ rb_gc_mark(context->thread);
124
+ frame = context->stack;
125
+ while (frame != NULL) {
126
+ rb_gc_mark(frame->self);
127
+ rb_gc_mark(frame->binding);
128
+ frame = frame->prev;
129
+ }
130
+ }
131
+
132
+ static void
133
+ Context_free(debug_context_t *context) {
134
+ while(context->stack_size > 0) {
135
+ delete_frame(context);
136
+ }
137
+ xfree(context);
138
+ }
139
+
140
+ extern VALUE
141
+ context_create(VALUE thread, VALUE cDebugThread) {
142
+ debug_context_t *context;
143
+
144
+ context = ALLOC(debug_context_t);
145
+ context->stack_size = 0;
146
+ context->stack = NULL;
147
+ context->thnum = ++thnum_current;
148
+ context->thread = thread;
149
+ context->flags = 0;
150
+ context->last_file = NULL;
151
+ context->last_line = -1;
152
+ context->stop_frame = -1;
153
+ reset_stepping_stop_points(context);
154
+ if(rb_obj_class(thread) == cDebugThread) CTX_FL_SET(context, CTX_FL_IGNORE);
155
+ return Data_Wrap_Struct(cContext, Context_mark, Context_free, context);
156
+ }
157
+
158
+ static inline void
159
+ check_frame_number_valid(debug_context_t *context, int frame_no)
160
+ {
161
+ if (frame_no < 0 || frame_no >= context->stack_size) {
162
+ rb_raise(rb_eArgError, "Invalid frame number %d, stack (0...%d)",
163
+ frame_no, context->stack_size);
164
+ }
165
+ }
166
+
167
+ static debug_frame_t*
168
+ get_frame_no(debug_context_t *context, int frame_n)
169
+ {
170
+ debug_frame_t *frame;
171
+ int i;
172
+
173
+ check_frame_number_valid(context, frame_n);
174
+ frame = context->stack;
175
+ for (i = 0; i < frame_n; i++) {
176
+ frame = frame->prev;
177
+ }
178
+ return frame;
179
+ }
180
+
181
+ static VALUE
182
+ Context_frame_file(int argc, VALUE *argv, VALUE self)
183
+ {
184
+ debug_context_t *context;
185
+ debug_frame_t *frame;
186
+ VALUE frame_no;
187
+ int frame_n;
188
+
189
+ Data_Get_Struct(self, debug_context_t, context);
190
+ frame_n = rb_scan_args(argc, argv, "01", &frame_no) == 0 ? 0 : FIX2INT(frame_no);
191
+ frame = get_frame_no(context, frame_n);
192
+ return rb_str_new2(frame->file);
193
+ }
194
+
195
+ static VALUE
196
+ Context_frame_line(int argc, VALUE *argv, VALUE self)
197
+ {
198
+ debug_context_t *context;
199
+ debug_frame_t *frame;
200
+ VALUE frame_no;
201
+ int frame_n;
202
+
203
+ Data_Get_Struct(self, debug_context_t, context);
204
+ frame_n = rb_scan_args(argc, argv, "01", &frame_no) == 0 ? 0 : FIX2INT(frame_no);
205
+ frame = get_frame_no(context, frame_n);
206
+ return INT2FIX(frame->line);
207
+ }
208
+
209
+ static VALUE
210
+ Context_frame_binding(int argc, VALUE *argv, VALUE self)
211
+ {
212
+ debug_context_t *context;
213
+ debug_frame_t *frame;
214
+ VALUE frame_no;
215
+ int frame_n;
216
+
217
+ Data_Get_Struct(self, debug_context_t, context);
218
+ frame_n = rb_scan_args(argc, argv, "01", &frame_no) == 0 ? 0 : FIX2INT(frame_no);
219
+ frame = get_frame_no(context, frame_n);
220
+ return frame->binding;
221
+ }
222
+
223
+ static VALUE
224
+ Context_frame_self(int argc, VALUE *argv, VALUE self)
225
+ {
226
+ debug_context_t *context;
227
+ debug_frame_t *frame;
228
+ VALUE frame_no;
229
+ int frame_n;
230
+
231
+ Data_Get_Struct(self, debug_context_t, context);
232
+ frame_n = rb_scan_args(argc, argv, "01", &frame_no) == 0 ? 0 : FIX2INT(frame_no);
233
+ frame = get_frame_no(context, frame_n);
234
+ return frame->self;
235
+ }
236
+
237
+ static VALUE
238
+ Context_stop_reason(VALUE self)
239
+ {
240
+ debug_context_t *context;
241
+ const char *symbol;
242
+
243
+ Data_Get_Struct(self, debug_context_t, context);
244
+
245
+ switch(context->stop_reason)
246
+ {
247
+ case CTX_STOP_STEP:
248
+ symbol = "step";
249
+ break;
250
+ case CTX_STOP_BREAKPOINT:
251
+ symbol = "breakpoint";
252
+ break;
253
+ case CTX_STOP_CATCHPOINT:
254
+ symbol = "catchpoint";
255
+ break;
256
+ case CTX_STOP_NONE:
257
+ default:
258
+ symbol = "none";
259
+ }
260
+ if(CTX_FL_TEST(context, CTX_FL_DEAD))
261
+ symbol = "post-mortem";
262
+
263
+ return ID2SYM(rb_intern(symbol));
264
+ }
265
+
266
+ static VALUE
267
+ Context_stop_next(int argc, VALUE *argv, VALUE self)
268
+ {
269
+ VALUE steps;
270
+ VALUE force;
271
+ debug_context_t *context;
272
+
273
+ rb_scan_args(argc, argv, "11", &steps, &force);
274
+ if(FIX2INT(steps) < 0) rb_raise(rb_eRuntimeError, "Steps argument can't be negative.");
275
+
276
+ Data_Get_Struct(self, debug_context_t, context);
277
+ context->stop_next = FIX2INT(steps);
278
+ if(RTEST(force))
279
+ CTX_FL_SET(context, CTX_FL_FORCE_MOVE);
280
+ else
281
+ CTX_FL_UNSET(context, CTX_FL_FORCE_MOVE);
282
+
283
+ return steps;
284
+ }
285
+
286
+ static VALUE
287
+ Context_step_over(int argc, VALUE *argv, VALUE self)
288
+ {
289
+ VALUE lines, frame, force;
290
+ debug_context_t *context;
291
+
292
+ Data_Get_Struct(self, debug_context_t, context);
293
+ if(context->stack_size == 0)
294
+ rb_raise(rb_eRuntimeError, "No frames collected.");
295
+
296
+ rb_scan_args(argc, argv, "12", &lines, &frame, &force);
297
+ context->stop_line = FIX2INT(lines);
298
+ CTX_FL_UNSET(context, CTX_FL_STEPPED);
299
+ if(frame == Qnil)
300
+ {
301
+ context->dest_frame = context->stack_size;
302
+ }
303
+ else
304
+ {
305
+ if(FIX2INT(frame) < 0 && FIX2INT(frame) >= context->stack_size)
306
+ rb_raise(rb_eRuntimeError, "Destination frame is out of range.");
307
+ context->dest_frame = context->stack_size - FIX2INT(frame);
308
+ }
309
+ if(RTEST(force))
310
+ CTX_FL_SET(context, CTX_FL_FORCE_MOVE);
311
+ else
312
+ CTX_FL_UNSET(context, CTX_FL_FORCE_MOVE);
313
+
314
+ return Qnil;
315
+ }
316
+
317
+ static VALUE
318
+ Context_stop_frame(VALUE self, VALUE frame)
319
+ {
320
+ debug_context_t *debug_context;
321
+
322
+ Data_Get_Struct(self, debug_context_t, debug_context);
323
+ if(FIX2INT(frame) < 0 && FIX2INT(frame) >= debug_context->stack_size)
324
+ rb_raise(rb_eRuntimeError, "Stop frame is out of range.");
325
+ debug_context->stop_frame = debug_context->stack_size - FIX2INT(frame);
326
+
327
+ return frame;
328
+ }
329
+
330
+ /*
331
+ * Document-class: Context
332
+ *
333
+ * == Summary
334
+ *
335
+ * Debugger keeps a single instance of this class for each Ruby thread.
336
+ */
337
+ VALUE
338
+ Init_context(VALUE mDebase)
339
+ {
340
+ cContext = rb_define_class_under(mDebase, "Context", rb_cObject);
341
+ rb_define_method(cContext, "stack_size", Context_stack_size, 0);
342
+ rb_define_method(cContext, "thread", Context_thread, 0);
343
+ rb_define_method(cContext, "dead?", Context_dead, 0);
344
+ rb_define_method(cContext, "ignored?", Context_ignored, 0);
345
+ rb_define_method(cContext, "thnum", Context_thnum, 0);
346
+ rb_define_method(cContext, "stop_reason", Context_stop_reason, 0);
347
+ rb_define_method(cContext, "frame_file", Context_frame_file, -1);
348
+ rb_define_method(cContext, "frame_line", Context_frame_line, -1);
349
+ rb_define_method(cContext, "frame_binding", Context_frame_binding, -1);
350
+ rb_define_method(cContext, "frame_self", Context_frame_self, -1);
351
+ rb_define_method(cContext, "stop_next=", Context_stop_next, -1);
352
+ rb_define_method(cContext, "step", Context_stop_next, -1);
353
+ rb_define_method(cContext, "step_over", Context_step_over, -1);
354
+ rb_define_method(cContext, "stop_frame=", Context_stop_frame, 1);
355
+
356
+ idAlive = rb_intern("alive?");
357
+
358
+ return cContext;
359
+ // rb_define_method(cContext, "suspend", context_suspend, 0);
360
+ // rb_define_method(cContext, "suspended?", context_is_suspended, 0);
361
+ // rb_define_method(cContext, "resume", context_resume, 0);
362
+ // rb_define_method(cContext, "tracing", context_tracing, 0);
363
+ // rb_define_method(cContext, "tracing=", context_set_tracing, 1);
364
+ // rb_define_method(cContext, "ignored?", context_ignored, 0);
365
+ // rb_define_method(cContext, "frame_args", context_frame_args, -1);
366
+ // rb_define_method(cContext, "frame_args_info", context_frame_args_info, -1);
367
+ // rb_define_method(cContext, "frame_class", context_frame_class, -1);
368
+ // rb_define_method(cContext, "frame_id", context_frame_id, -1);
369
+ // rb_define_method(cContext, "frame_locals", context_frame_locals, -1);
370
+ // rb_define_method(cContext, "frame_method", context_frame_id, -1);
371
+ // rb_define_method(cContext, "breakpoint",
372
+ // context_breakpoint, 0); /* in breakpoint.c */
373
+ // rb_define_method(cContext, "set_breakpoint",
374
+ // context_set_breakpoint, -1); /* in breakpoint.c */
375
+ // rb_define_method(cContext, "jump", context_jump, 2);
376
+ // rb_define_method(cContext, "pause", context_pause, 0);
377
+ }