ruby-debug 0.6.1-mswin32 → 0.6.2-mswin32
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.
- 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: []
|