ruby-debug 0.6.1-mswin32 → 0.6.2-mswin32
Sign up to get free protection for your applications and to get access to all the features.
- data/AUTHORS +6 -0
- data/CHANGES +5 -0
- data/Rakefile +1 -0
- data/bin/rdebug +20 -3
- data/ext/ruby_debug.c +89 -72
- data/lib/ruby-debug.rb +26 -17
- data/lib/ruby-debug/commands/control.rb +1 -1
- data/lib/ruby-debug/commands/frame.rb +91 -40
- data/lib/ruby_debug.so +0 -0
- metadata +4 -3
data/AUTHORS
ADDED
data/CHANGES
CHANGED
data/Rakefile
CHANGED
data/bin/rdebug
CHANGED
@@ -27,14 +27,15 @@ EOB
|
|
27
27
|
opts.separator ""
|
28
28
|
opts.separator "Options:"
|
29
29
|
opts.on("-s", "--server", "Listen for remote connections") {options.server = true}
|
30
|
+
opts.on("-w", "--wait", "Wait for a client connection, implies -s option") {options.wait = true}
|
30
31
|
opts.on("-c", "--client", "Connect to remote debugger") {options.client = true}
|
31
32
|
opts.on("-h", "--host HOST", "Host name used for remote debugging") {|options.host|}
|
32
|
-
opts.on("-
|
33
|
+
opts.on("-p", "--port PORT", Integer, "Port used for remote debugging") {|options.port|}
|
34
|
+
opts.on("--cport PORT", Integer, "Port used for contol commands, implies -s option") {|options.port|}
|
33
35
|
opts.on("-x", "--trace", "turn on line tracing") {options.tracing = true}
|
34
36
|
opts.on("-n", "--nostop", "Do not stop when stript is loaded") {options.nostop = true}
|
35
37
|
opts.on("-f", "--keep-frame-info", "Keep frame info") {options.frame_info = true}
|
36
38
|
opts.on("-m", "--post-mortem", "Activate post-mortem mode") {options.post_mortem = true}
|
37
|
-
opts.on("-p", "--port PORT", Integer, "Port used for remote debugging") {|options.port|}
|
38
39
|
opts.on("-I", "--include PATH", String, "Add PATH to $LOAD_PATH") do |path|
|
39
40
|
$LOAD_PATH.unshift(path)
|
40
41
|
end
|
@@ -44,7 +45,6 @@ EOB
|
|
44
45
|
exit
|
45
46
|
end
|
46
47
|
end
|
47
|
-
opts.on("--cport PORT", Integer, "Port used for contol commands, implies -s option") {|options.port|}
|
48
48
|
opts.separator ""
|
49
49
|
opts.separator "Common options:"
|
50
50
|
opts.on_tail("--help", "Show this message") do
|
@@ -82,26 +82,43 @@ else
|
|
82
82
|
exit(-1)
|
83
83
|
end
|
84
84
|
|
85
|
+
# save script name
|
85
86
|
Debugger::PROG_SCRIPT = ARGV.shift
|
87
|
+
|
88
|
+
# install interruption handler
|
86
89
|
trap('INT') { Debugger.interrupt_last }
|
90
|
+
|
91
|
+
# set options
|
87
92
|
Debugger.stop_on_connect = !options.nostop
|
88
93
|
Debugger.wait_connection = options.wait
|
89
94
|
Debugger.keep_frame_info = options.frame_info
|
95
|
+
|
96
|
+
# load user script
|
90
97
|
load "#{ENV["HOME"]}/.rdebugrc" if File.exists?("#{ENV["HOME"]}/.rdebugrc")
|
98
|
+
|
91
99
|
if options.server
|
100
|
+
# start remote mode
|
92
101
|
Debugger.start_remote(options.host, [options.port, options.cport], options.post_mortem)
|
102
|
+
# load script
|
93
103
|
Debugger.debug_load Debugger::PROG_SCRIPT
|
94
104
|
else
|
105
|
+
# activate debugger
|
95
106
|
Debugger.start
|
107
|
+
# start control thread
|
108
|
+
Debugger.start_control(options.host, options.cport)
|
109
|
+
|
110
|
+
# run startup script if specified
|
96
111
|
if options.script
|
97
112
|
Debugger.run_script(options.script)
|
98
113
|
end
|
114
|
+
# activate post-mortem
|
99
115
|
Debugger.post_mortem if options.post_mortem
|
100
116
|
if options.tracing
|
101
117
|
Debugger.tracing = true
|
102
118
|
else
|
103
119
|
debugger 2 unless options.nostop
|
104
120
|
end
|
121
|
+
# load script
|
105
122
|
Debugger.debug_load Debugger::PROG_SCRIPT
|
106
123
|
end
|
107
124
|
end
|
data/ext/ruby_debug.c
CHANGED
@@ -4,7 +4,7 @@
|
|
4
4
|
#include <rubysig.h>
|
5
5
|
#include <st.h>
|
6
6
|
|
7
|
-
#define DEBUG_VERSION "0.6.
|
7
|
+
#define DEBUG_VERSION "0.6.2"
|
8
8
|
|
9
9
|
#define CTX_FL_MOVED (1<<1)
|
10
10
|
#define CTX_FL_SUSPEND (1<<2)
|
@@ -26,6 +26,13 @@
|
|
26
26
|
#define min(x,y) ((x) < (y) ? (x) : (y))
|
27
27
|
#endif
|
28
28
|
|
29
|
+
typedef struct {
|
30
|
+
ID id;
|
31
|
+
VALUE binding;
|
32
|
+
int line;
|
33
|
+
const char * file;
|
34
|
+
} debug_frame_t;
|
35
|
+
|
29
36
|
typedef struct {
|
30
37
|
int thnum;
|
31
38
|
int flags;
|
@@ -35,17 +42,11 @@ typedef struct {
|
|
35
42
|
int stop_frame;
|
36
43
|
unsigned long thread_id;
|
37
44
|
VALUE frames;
|
45
|
+
debug_frame_t *top_frame;
|
38
46
|
const char * last_file;
|
39
47
|
int last_line;
|
40
48
|
} debug_context_t;
|
41
49
|
|
42
|
-
typedef struct {
|
43
|
-
ID id;
|
44
|
-
VALUE binding;
|
45
|
-
int line;
|
46
|
-
const char * file;
|
47
|
-
} debug_frame_t;
|
48
|
-
|
49
50
|
enum bp_type {BP_POS_TYPE, BP_METHOD_TYPE};
|
50
51
|
|
51
52
|
typedef struct {
|
@@ -72,6 +73,10 @@ static VALUE locker = Qnil;
|
|
72
73
|
static VALUE post_mortem = Qfalse;
|
73
74
|
static VALUE keep_frame_info = Qfalse;
|
74
75
|
|
76
|
+
static VALUE last_context = Qnil;
|
77
|
+
static VALUE last_thread = Qnil;
|
78
|
+
static debug_context_t *last_debug_context = NULL;
|
79
|
+
|
75
80
|
static VALUE mDebugger;
|
76
81
|
static VALUE cThreadsTable;
|
77
82
|
static VALUE cContext;
|
@@ -86,8 +91,6 @@ static ID idAtCatchpoint;
|
|
86
91
|
static ID idAtTracing;
|
87
92
|
static ID idEval;
|
88
93
|
static ID idList;
|
89
|
-
static ID idClear;
|
90
|
-
static ID idIndex;
|
91
94
|
|
92
95
|
static int start_count = 0;
|
93
96
|
static int thnum_max = 0;
|
@@ -130,7 +133,7 @@ id2ref_unprotected(VALUE id)
|
|
130
133
|
static id2ref_func_t f_id2ref = NULL;
|
131
134
|
if(f_id2ref == NULL)
|
132
135
|
{
|
133
|
-
f_id2ref = ruby_method_ptr(rb_mObjectSpace, rb_intern("_id2ref"));
|
136
|
+
f_id2ref = (id2ref_func_t)ruby_method_ptr(rb_mObjectSpace, rb_intern("_id2ref"));
|
134
137
|
}
|
135
138
|
return f_id2ref(rb_mObjectSpace, id);
|
136
139
|
}
|
@@ -204,25 +207,6 @@ remove_from_locked()
|
|
204
207
|
return thread;
|
205
208
|
}
|
206
209
|
|
207
|
-
static int
|
208
|
-
thread_hash(unsigned long thread_id)
|
209
|
-
{
|
210
|
-
return (int)thread_id;
|
211
|
-
}
|
212
|
-
|
213
|
-
static int
|
214
|
-
thread_cmp(VALUE a, VALUE b)
|
215
|
-
{
|
216
|
-
if(a == b) return 0;
|
217
|
-
if(a < b) return -1;
|
218
|
-
return 1;
|
219
|
-
}
|
220
|
-
|
221
|
-
static struct st_hash_type st_thread_hash = {
|
222
|
-
thread_cmp,
|
223
|
-
thread_hash
|
224
|
-
};
|
225
|
-
|
226
210
|
static int
|
227
211
|
threads_table_mark_keyvalue(VALUE key, VALUE value, int dummy)
|
228
212
|
{
|
@@ -251,7 +235,7 @@ threads_table_create()
|
|
251
235
|
threads_table_t *threads_table;
|
252
236
|
|
253
237
|
threads_table = ALLOC(threads_table_t);
|
254
|
-
threads_table->tbl =
|
238
|
+
threads_table->tbl = st_init_numtable();
|
255
239
|
return Data_Wrap_Struct(cThreadsTable, threads_table_mark, threads_table_free, threads_table);
|
256
240
|
}
|
257
241
|
|
@@ -273,12 +257,13 @@ threads_table_clear(VALUE table)
|
|
273
257
|
static VALUE
|
274
258
|
is_thread_alive(VALUE thread)
|
275
259
|
{
|
276
|
-
|
277
|
-
|
260
|
+
typedef VALUE (*thread_alive_func_t)(VALUE);
|
261
|
+
static thread_alive_func_t f_thread_alive = NULL;
|
262
|
+
if(!f_thread_alive)
|
278
263
|
{
|
279
|
-
|
264
|
+
f_thread_alive = (thread_alive_func_t)ruby_method_ptr(rb_cThread, rb_intern("alive?"));
|
280
265
|
}
|
281
|
-
return
|
266
|
+
return f_thread_alive(thread);
|
282
267
|
}
|
283
268
|
|
284
269
|
static int
|
@@ -353,27 +338,43 @@ debug_context_create(VALUE thread)
|
|
353
338
|
debug_context->stop_line = -1;
|
354
339
|
debug_context->stop_frame = -1;
|
355
340
|
debug_context->frames = rb_ary_new();
|
341
|
+
debug_context->top_frame = NULL;
|
356
342
|
debug_context->thread_id = ref2id(thread);
|
357
343
|
result = Data_Wrap_Struct(cContext, debug_context_mark, xfree, debug_context);
|
358
344
|
return result;
|
359
345
|
}
|
360
346
|
|
361
|
-
static
|
362
|
-
thread_context_lookup(VALUE thread)
|
347
|
+
static void
|
348
|
+
thread_context_lookup(VALUE thread, VALUE *context, debug_context_t **debug_context)
|
363
349
|
{
|
364
|
-
VALUE context;
|
365
350
|
threads_table_t *threads_table;
|
366
|
-
unsigned long thread_id
|
351
|
+
unsigned long thread_id;
|
352
|
+
debug_context_t *l_debug_context;
|
367
353
|
|
368
354
|
debug_check_started();
|
369
355
|
|
356
|
+
if(last_thread == thread && last_context != Qnil)
|
357
|
+
{
|
358
|
+
*context = last_context;
|
359
|
+
if(debug_context)
|
360
|
+
*debug_context = last_debug_context;
|
361
|
+
return;
|
362
|
+
}
|
363
|
+
thread_id = ref2id(thread);
|
370
364
|
Data_Get_Struct(threads_tbl, threads_table_t, threads_table);
|
371
|
-
if(!st_lookup(threads_table->tbl, thread_id,
|
365
|
+
if(!st_lookup(threads_table->tbl, thread_id, context))
|
372
366
|
{
|
373
|
-
context = debug_context_create(thread);
|
374
|
-
st_insert(threads_table->tbl, thread_id, context);
|
367
|
+
*context = debug_context_create(thread);
|
368
|
+
st_insert(threads_table->tbl, thread_id, *context);
|
375
369
|
}
|
376
|
-
|
370
|
+
|
371
|
+
Data_Get_Struct(*context, debug_context_t, l_debug_context);
|
372
|
+
if(debug_context)
|
373
|
+
*debug_context = l_debug_context;
|
374
|
+
|
375
|
+
last_thread = thread;
|
376
|
+
last_context = *context;
|
377
|
+
last_debug_context = l_debug_context;
|
377
378
|
}
|
378
379
|
|
379
380
|
static void
|
@@ -383,22 +384,6 @@ debug_frame_mark(void *data)
|
|
383
384
|
rb_gc_mark(debug_frame->binding);
|
384
385
|
}
|
385
386
|
|
386
|
-
static VALUE
|
387
|
-
debug_frame_create(char *file, int line, VALUE binding, ID id)
|
388
|
-
{
|
389
|
-
VALUE result;
|
390
|
-
debug_frame_t *debug_frame;
|
391
|
-
|
392
|
-
debug_frame = ALLOC(debug_frame_t);
|
393
|
-
debug_frame->file = file;
|
394
|
-
debug_frame->line = line;
|
395
|
-
debug_frame->binding = binding;
|
396
|
-
debug_frame->id = id;
|
397
|
-
result = Data_Wrap_Struct(cFrame, debug_frame_mark, xfree, debug_frame);
|
398
|
-
|
399
|
-
return result;
|
400
|
-
}
|
401
|
-
|
402
387
|
static VALUE
|
403
388
|
call_at_line_unprotected(VALUE args)
|
404
389
|
{
|
@@ -423,9 +408,17 @@ static void
|
|
423
408
|
save_call_frame(VALUE self, char *file, int line, ID mid, debug_context_t *debug_context)
|
424
409
|
{
|
425
410
|
VALUE frame, binding;
|
411
|
+
debug_frame_t *debug_frame;
|
426
412
|
|
427
413
|
binding = self && RTEST(keep_frame_info)? create_binding(self) : Qnil;
|
428
|
-
|
414
|
+
debug_frame = ALLOC(debug_frame_t);
|
415
|
+
debug_frame->file = file;
|
416
|
+
debug_frame->line = line;
|
417
|
+
debug_frame->binding = binding;
|
418
|
+
debug_frame->id = mid;
|
419
|
+
frame = Data_Wrap_Struct(cFrame, debug_frame_mark, xfree, debug_frame);
|
420
|
+
|
421
|
+
debug_context->top_frame = debug_frame;
|
429
422
|
rb_ary_push(debug_context->frames, frame);
|
430
423
|
}
|
431
424
|
|
@@ -570,9 +563,16 @@ get_top_frame(debug_context_t *debug_context)
|
|
570
563
|
debug_frame_t *debug_frame;
|
571
564
|
if(RARRAY(debug_context->frames)->len == 0)
|
572
565
|
return NULL;
|
573
|
-
else
|
574
|
-
|
575
|
-
|
566
|
+
else
|
567
|
+
{
|
568
|
+
if(debug_context->top_frame == NULL)
|
569
|
+
{
|
570
|
+
frame = RARRAY(debug_context->frames)->ptr[RARRAY(debug_context->frames)->len-1];
|
571
|
+
Data_Get_Struct(frame, debug_frame_t, debug_frame);
|
572
|
+
debug_context->top_frame = debug_frame;
|
573
|
+
}
|
574
|
+
else
|
575
|
+
debug_frame = debug_context->top_frame;
|
576
576
|
return debug_frame;
|
577
577
|
}
|
578
578
|
}
|
@@ -626,8 +626,7 @@ debug_event_hook(rb_event_t event, NODE *node, VALUE self, ID mid, VALUE klass)
|
|
626
626
|
if(!node) return;
|
627
627
|
|
628
628
|
thread = rb_thread_current();
|
629
|
-
|
630
|
-
Data_Get_Struct(context, debug_context_t, debug_context);
|
629
|
+
thread_context_lookup(thread, &context, &debug_context);
|
631
630
|
|
632
631
|
/* return if thread is marked as 'ignored'.
|
633
632
|
debugger's threads are marked this way
|
@@ -753,6 +752,7 @@ debug_event_hook(rb_event_t event, NODE *node, VALUE self, ID mid, VALUE klass)
|
|
753
752
|
debug_context->stop_frame = 0;
|
754
753
|
}
|
755
754
|
rb_ary_pop(debug_context->frames);
|
755
|
+
debug_context->top_frame = NULL;
|
756
756
|
break;
|
757
757
|
}
|
758
758
|
case RUBY_EVENT_CLASS:
|
@@ -811,7 +811,7 @@ debug_event_hook(rb_event_t event, NODE *node, VALUE self, ID mid, VALUE klass)
|
|
811
811
|
cleanup:
|
812
812
|
|
813
813
|
/* check that all contexts point to alive threads */
|
814
|
-
if(hook_count - last_check >
|
814
|
+
if(hook_count - last_check > 3000)
|
815
815
|
{
|
816
816
|
check_thread_contexts();
|
817
817
|
last_check = hook_count;
|
@@ -1077,8 +1077,24 @@ debug_current_context(VALUE self)
|
|
1077
1077
|
debug_check_started();
|
1078
1078
|
|
1079
1079
|
thread = rb_thread_current();
|
1080
|
-
|
1080
|
+
thread_context_lookup(thread, &context, NULL);
|
1081
|
+
|
1082
|
+
return context;
|
1083
|
+
}
|
1081
1084
|
|
1085
|
+
/*
|
1086
|
+
* call-seq:
|
1087
|
+
* Debugger.thread_context(thread) -> context
|
1088
|
+
*
|
1089
|
+
* Returns context of the thread passed as an argument.
|
1090
|
+
*/
|
1091
|
+
static VALUE
|
1092
|
+
debug_thread_context(VALUE self, VALUE thread)
|
1093
|
+
{
|
1094
|
+
VALUE context;
|
1095
|
+
|
1096
|
+
debug_check_started();
|
1097
|
+
thread_context_lookup(thread, &context, NULL);
|
1082
1098
|
return context;
|
1083
1099
|
}
|
1084
1100
|
|
@@ -1105,7 +1121,7 @@ debug_contexts(VALUE self)
|
|
1105
1121
|
for(i = 0; i < RARRAY(list)->len; i++)
|
1106
1122
|
{
|
1107
1123
|
thread = rb_ary_entry(list, i);
|
1108
|
-
|
1124
|
+
thread_context_lookup(thread, &context, NULL);
|
1109
1125
|
rb_ary_push(new_list, context);
|
1110
1126
|
}
|
1111
1127
|
threads_table_clear(threads_tbl);
|
@@ -1140,7 +1156,7 @@ debug_suspend(VALUE self)
|
|
1140
1156
|
saved_crit = rb_thread_critical;
|
1141
1157
|
rb_thread_critical = Qtrue;
|
1142
1158
|
context_list = debug_contexts(self);
|
1143
|
-
|
1159
|
+
thread_context_lookup(rb_thread_current(), ¤t, NULL);
|
1144
1160
|
|
1145
1161
|
for(i = 0; i < RARRAY(context_list)->len; i++)
|
1146
1162
|
{
|
@@ -1179,7 +1195,7 @@ debug_resume(VALUE self)
|
|
1179
1195
|
rb_thread_critical = Qtrue;
|
1180
1196
|
context_list = debug_contexts(self);
|
1181
1197
|
|
1182
|
-
|
1198
|
+
thread_context_lookup(rb_thread_current(), ¤t, NULL);
|
1183
1199
|
for(i = 0; i < RARRAY(context_list)->len; i++)
|
1184
1200
|
{
|
1185
1201
|
context = rb_ary_entry(context_list, i);
|
@@ -1823,6 +1839,7 @@ Init_ruby_debug()
|
|
1823
1839
|
rb_define_module_function(mDebugger, "last_context", debug_last_interrupted, 0);
|
1824
1840
|
rb_define_module_function(mDebugger, "contexts", debug_contexts, 0);
|
1825
1841
|
rb_define_module_function(mDebugger, "current_context", debug_current_context, 0);
|
1842
|
+
rb_define_module_function(mDebugger, "thread_context", debug_thread_context, 1);
|
1826
1843
|
rb_define_module_function(mDebugger, "suspend", debug_suspend, 0);
|
1827
1844
|
rb_define_module_function(mDebugger, "resume", debug_resume, 0);
|
1828
1845
|
rb_define_module_function(mDebugger, "tracing", debug_tracing, 0);
|
@@ -1847,8 +1864,6 @@ Init_ruby_debug()
|
|
1847
1864
|
idAtTracing = rb_intern("at_tracing");
|
1848
1865
|
idEval = rb_intern("eval");
|
1849
1866
|
idList = rb_intern("list");
|
1850
|
-
idClear = rb_intern("clear");
|
1851
|
-
idIndex = rb_intern("index");
|
1852
1867
|
|
1853
1868
|
rb_mObjectSpace = rb_const_get(rb_mKernel, rb_intern("ObjectSpace"));
|
1854
1869
|
|
@@ -1856,4 +1871,6 @@ Init_ruby_debug()
|
|
1856
1871
|
rb_global_variable(&breakpoints);
|
1857
1872
|
rb_global_variable(&catchpoint);
|
1858
1873
|
rb_global_variable(&locker);
|
1874
|
+
rb_global_variable(&last_context);
|
1875
|
+
rb_global_variable(&last_thread);
|
1859
1876
|
}
|
data/lib/ruby-debug.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'pp'
|
2
2
|
require 'stringio'
|
3
|
+
require "socket"
|
3
4
|
require 'thread'
|
4
5
|
require 'ruby_debug.so'
|
5
6
|
require 'ruby-debug/processor'
|
@@ -56,11 +57,10 @@ module Debugger
|
|
56
57
|
attr_reader :thread, :control_thread
|
57
58
|
|
58
59
|
#
|
59
|
-
# Interrupts the
|
60
|
+
# Interrupts the current thread
|
60
61
|
#
|
61
62
|
def interrupt
|
62
|
-
|
63
|
-
context.interrupt
|
63
|
+
current_context.interrupt
|
64
64
|
end
|
65
65
|
|
66
66
|
#
|
@@ -89,29 +89,18 @@ module Debugger
|
|
89
89
|
start
|
90
90
|
self.post_mortem if post_mortem
|
91
91
|
|
92
|
-
require "socket"
|
93
|
-
|
94
92
|
if port.kind_of?(Array)
|
95
93
|
cmd_port, ctrl_port = port
|
96
94
|
else
|
97
95
|
cmd_port, ctrl_port = port, port + 1
|
98
96
|
end
|
99
97
|
|
100
|
-
|
101
|
-
current_context.ignore = true
|
102
|
-
server = TCPServer.new(host, ctrl_port)
|
103
|
-
while (session = server.accept)
|
104
|
-
interface = RemoteInterface.new(session)
|
105
|
-
processor = ControlCommandProcessor.new(interface)
|
106
|
-
processor.process_commands
|
107
|
-
end
|
108
|
-
end
|
98
|
+
start_control(host, ctrl_port)
|
109
99
|
|
110
100
|
mutex = Mutex.new
|
111
101
|
proceed = ConditionVariable.new
|
112
102
|
|
113
|
-
@thread =
|
114
|
-
current_context.ignore = true
|
103
|
+
@thread = DebugThread.new do
|
115
104
|
server = TCPServer.new(host, cmd_port)
|
116
105
|
while (session = server.accept)
|
117
106
|
self.interface = RemoteInterface.new(session)
|
@@ -133,6 +122,19 @@ module Debugger
|
|
133
122
|
end
|
134
123
|
alias start_server start_remote
|
135
124
|
|
125
|
+
def start_control(host = nil, ctrl_port = PORT + 1)
|
126
|
+
raise "Debugger is not started" unless started?
|
127
|
+
return if @control_thread
|
128
|
+
@control_thread = DebugThread.new do
|
129
|
+
server = TCPServer.new(host, ctrl_port)
|
130
|
+
while (session = server.accept)
|
131
|
+
interface = RemoteInterface.new(session)
|
132
|
+
processor = ControlCommandProcessor.new(interface)
|
133
|
+
processor.process_commands
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
136
138
|
#
|
137
139
|
# Connects to the remote debugger
|
138
140
|
#
|
@@ -164,7 +166,7 @@ module Debugger
|
|
164
166
|
def stop_main_thread # :nodoc:
|
165
167
|
return unless stop_on_connect
|
166
168
|
|
167
|
-
context =
|
169
|
+
context = thread_context(Thread.main)
|
168
170
|
context.stop_next = 2
|
169
171
|
end
|
170
172
|
private :stop_main_thread
|
@@ -272,6 +274,13 @@ class Exception # :nodoc:
|
|
272
274
|
attr_reader :__debug_file, :__debug_line, :__debug_binding, :__debug_frames
|
273
275
|
end
|
274
276
|
|
277
|
+
class DebugThread < Thread # :nodoc:
|
278
|
+
def initialize(*args, &b)
|
279
|
+
Debugger.thread_context(self).ignore = true
|
280
|
+
super
|
281
|
+
end
|
282
|
+
end
|
283
|
+
|
275
284
|
module Kernel
|
276
285
|
#
|
277
286
|
# Stops the current thread after a number of _steps_ made.
|
@@ -1,5 +1,41 @@
|
|
1
1
|
module Debugger
|
2
2
|
module FrameFunctions # :nodoc:
|
3
|
+
def adjust_frame(frame_pos, absolute)
|
4
|
+
if absolute
|
5
|
+
if frame_pos < 0
|
6
|
+
abs_frame_pos = @state.frames.size + frame_pos
|
7
|
+
else
|
8
|
+
abs_frame_pos = frame_pos
|
9
|
+
end
|
10
|
+
else
|
11
|
+
abs_frame_pos = @state.frame_pos + frame_pos
|
12
|
+
end
|
13
|
+
|
14
|
+
if abs_frame_pos >= @state.frames.size then
|
15
|
+
print "Adjusting would put us beyond the oldest (initial) frame.\n"
|
16
|
+
return
|
17
|
+
elsif abs_frame_pos < 0 then
|
18
|
+
print "Adjusting would put us beyond the newest (innermost) frame.\n"
|
19
|
+
return
|
20
|
+
end
|
21
|
+
if @state.frame_pos != abs_frame_pos then
|
22
|
+
@state.previous_line = nil
|
23
|
+
@state.frame_pos = abs_frame_pos
|
24
|
+
end
|
25
|
+
frame = @state.frames[-1-@state.frame_pos]
|
26
|
+
@state.binding, @state.file, @state.line = frame.binding, frame.file, frame.line
|
27
|
+
print format_frame(frame, @state.frame_pos)
|
28
|
+
end
|
29
|
+
|
30
|
+
def get_int(str, cmd)
|
31
|
+
begin
|
32
|
+
return Integer(@match[1])
|
33
|
+
rescue
|
34
|
+
print "%s argument needs to be a number.\n" % cmd
|
35
|
+
return nil
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
3
39
|
def format_frame(frame, pos)
|
4
40
|
printf "\032\032" if ENV['EMACS']
|
5
41
|
file, line, id = frame.file, frame.line, frame.id
|
@@ -11,7 +47,7 @@ module Debugger
|
|
11
47
|
include FrameFunctions
|
12
48
|
|
13
49
|
def regexp
|
14
|
-
/^\s*(?:w(?:here)?|
|
50
|
+
/^\s*(?:w(?:here)?|bt|backtrace)$/
|
15
51
|
end
|
16
52
|
|
17
53
|
def execute
|
@@ -37,7 +73,7 @@ module Debugger
|
|
37
73
|
}
|
38
74
|
else
|
39
75
|
%{
|
40
|
-
|
76
|
+
bt|backtrace\t\talias for where
|
41
77
|
}
|
42
78
|
end
|
43
79
|
end
|
@@ -48,46 +84,28 @@ module Debugger
|
|
48
84
|
include FrameFunctions
|
49
85
|
|
50
86
|
def regexp
|
51
|
-
/^\s*(?:
|
87
|
+
/^\s* u(?:p)? (?:\s+(.*))? .*$/x
|
52
88
|
end
|
53
89
|
|
54
90
|
def execute
|
55
|
-
|
56
|
-
|
57
|
-
else
|
58
|
-
cmd, arg = @match.captures[2..-1]
|
59
|
-
end
|
60
|
-
@state.previous_line = nil
|
61
|
-
if cmd == 'f'
|
62
|
-
@state.frame_pos = arg.to_i - 1
|
91
|
+
unless @match[1]
|
92
|
+
pos = 1
|
63
93
|
else
|
64
|
-
|
94
|
+
pos = get_int(@match[1], "Up")
|
95
|
+
return unless pos
|
65
96
|
end
|
66
|
-
|
67
|
-
if @state.frame_pos >= @state.frames.size
|
68
|
-
@state.frame_pos = @state.frames.size - 1
|
69
|
-
print "At toplevel\n"
|
70
|
-
end
|
71
|
-
frame = @state.frames[-1 - @state.frame_pos]
|
72
|
-
@state.binding, @state.file, @state.line = frame.binding, frame.file, frame.line
|
73
|
-
print format_frame(frame, @state.frame_pos)
|
97
|
+
adjust_frame(pos, false)
|
74
98
|
end
|
75
99
|
|
76
100
|
class << self
|
77
101
|
def help_command
|
78
|
-
|
102
|
+
up
|
79
103
|
end
|
80
104
|
|
81
105
|
def help(cmd)
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
}
|
86
|
-
else
|
87
|
-
%{
|
88
|
-
f[rame] n\tselect nth frame
|
89
|
-
}
|
90
|
-
end
|
106
|
+
%{
|
107
|
+
up[count]\tmove to higher frame
|
108
|
+
}
|
91
109
|
end
|
92
110
|
end
|
93
111
|
end
|
@@ -96,19 +114,17 @@ module Debugger
|
|
96
114
|
include FrameFunctions
|
97
115
|
|
98
116
|
def regexp
|
99
|
-
/^\s*
|
117
|
+
/^\s* d(?:own)? (?:\s+(.*))? .*$/x
|
100
118
|
end
|
101
119
|
|
102
120
|
def execute
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
121
|
+
if not @match[1]
|
122
|
+
pos = 1
|
123
|
+
else
|
124
|
+
pos = get_int(@match[1], "Down")
|
125
|
+
return unless pos
|
108
126
|
end
|
109
|
-
|
110
|
-
@state.binding, @state.file, @state.line = frame.binding, frame.file, frame.line
|
111
|
-
print format_frame(frame, @state.frame_pos)
|
127
|
+
adjust_frame(-pos, false)
|
112
128
|
end
|
113
129
|
|
114
130
|
class << self
|
@@ -118,7 +134,42 @@ module Debugger
|
|
118
134
|
|
119
135
|
def help(cmd)
|
120
136
|
%{
|
121
|
-
down[
|
137
|
+
down[count]\tmove to lower frame
|
138
|
+
}
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
class FrameCommand < Command # :nodoc:
|
144
|
+
include FrameFunctions
|
145
|
+
def regexp
|
146
|
+
/^\s* f(?:rame)? (?:\s+ (.*))? \s*$/x
|
147
|
+
end
|
148
|
+
|
149
|
+
def execute
|
150
|
+
if not @match[1]
|
151
|
+
print "Missing a frame number argument.\n"
|
152
|
+
return
|
153
|
+
else
|
154
|
+
pos = get_int(@match[1], "Frame")
|
155
|
+
return unless pos
|
156
|
+
end
|
157
|
+
adjust_frame(pos < 0 ? pos : pos-1, true)
|
158
|
+
end
|
159
|
+
|
160
|
+
class << self
|
161
|
+
def help_command
|
162
|
+
'frame'
|
163
|
+
end
|
164
|
+
|
165
|
+
def help(cmd)
|
166
|
+
%{
|
167
|
+
f[rame] frame-number
|
168
|
+
Move the current frame to the specified frame number.
|
169
|
+
|
170
|
+
A negative number indicates position from the other end. So
|
171
|
+
'frame -1' moves to the oldest frame, and 'frame 0' moves to
|
172
|
+
the newest frame.
|
122
173
|
}
|
123
174
|
end
|
124
175
|
end
|
data/lib/ruby_debug.so
CHANGED
Binary file
|
metadata
CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.1
|
|
3
3
|
specification_version: 1
|
4
4
|
name: ruby-debug
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.6.
|
7
|
-
date: 2007-01-
|
6
|
+
version: 0.6.2
|
7
|
+
date: 2007-01-28 14:26:27 -05:00
|
8
8
|
summary: Fast Ruby debugger
|
9
9
|
require_paths:
|
10
10
|
- lib
|
@@ -33,9 +33,9 @@ files:
|
|
33
33
|
- README
|
34
34
|
- LICENSE
|
35
35
|
- CHANGES
|
36
|
+
- AUTHORS
|
36
37
|
- lib/ruby-debug
|
37
38
|
- lib/ruby-debug.rb
|
38
|
-
- lib/ruby_debug.so
|
39
39
|
- lib/ruby-debug/command.rb
|
40
40
|
- lib/ruby-debug/commands
|
41
41
|
- lib/ruby-debug/interface.rb
|
@@ -61,6 +61,7 @@ files:
|
|
61
61
|
- ext/tags
|
62
62
|
- ext/win32
|
63
63
|
- bin/rdebug
|
64
|
+
- lib/ruby_debug.so
|
64
65
|
test_files: []
|
65
66
|
|
66
67
|
rdoc_options: []
|