ruby-debug 0.7.5 → 0.8

Sign up to get free protection for your applications and to get access to all the features.
data/ext/extconf.rb DELETED
@@ -1,18 +0,0 @@
1
- require "mkmf"
2
-
3
- if RUBY_VERSION >= "1.9"
4
- if RUBY_RELEASE_DATE < "2005-03-17"
5
- STDERR.print("Ruby version is too old\n")
6
- exit(1)
7
- end
8
- elsif RUBY_VERSION >= "1.8"
9
- if RUBY_RELEASE_DATE < "2005-03-22"
10
- STDERR.print("Ruby version is too old\n")
11
- exit(1)
12
- end
13
- else
14
- STDERR.print("Ruby version is too old\n")
15
- exit(1)
16
- end
17
-
18
- create_makefile("ruby_debug")
data/ext/ruby_debug.c DELETED
@@ -1,2167 +0,0 @@
1
- #include <stdio.h>
2
- #include <ruby.h>
3
- #include <node.h>
4
- #include <rubysig.h>
5
- #include <st.h>
6
-
7
- #define DEBUG_VERSION "0.7.5"
8
-
9
- #ifdef _WIN32
10
- struct FRAME {
11
- VALUE self;
12
- int argc;
13
- ID last_func;
14
- ID orig_func;
15
- VALUE last_class;
16
- struct FRAME *prev;
17
- struct FRAME *tmp;
18
- struct RNode *node;
19
- int iter;
20
- int flags;
21
- unsigned long uniq;
22
- };
23
-
24
- struct SCOPE {
25
- struct RBasic super;
26
- ID *local_tbl;
27
- VALUE *local_vars;
28
- int flags;
29
- };
30
-
31
- struct RVarmap {
32
- struct RBasic super;
33
- ID id;
34
- VALUE val;
35
- struct RVarmap *next;
36
- };
37
-
38
- RUBY_EXTERN struct SCOPE *ruby_scope;
39
- RUBY_EXTERN struct FRAME *ruby_frame;
40
- RUBY_EXTERN struct RVarmap *ruby_dyna_vars;
41
- #else
42
- #include <env.h>
43
- #endif
44
-
45
- #define CTX_FL_MOVED (1<<1)
46
- #define CTX_FL_SUSPEND (1<<2)
47
- #define CTX_FL_TRACING (1<<3)
48
- #define CTX_FL_SKIPPED (1<<4)
49
- #define CTX_FL_IGNORE (1<<5)
50
- #define CTX_FL_DEAD (1<<6)
51
- #define CTX_FL_WAS_RUNNING (1<<7)
52
-
53
- #define CTX_FL_TEST(c,f) ((c)->flags & (f))
54
- #define CTX_FL_SET(c,f) do { (c)->flags |= (f); } while (0)
55
- #define CTX_FL_UNSET(c,f) do { (c)->flags &= ~(f); } while (0)
56
-
57
- #define DID_MOVED (debug_context->last_line != line || \
58
- debug_context->last_file == NULL || \
59
- strcmp(debug_context->last_file, file) != 0)
60
-
61
- #define IS_STARTED (threads_tbl != Qnil)
62
- #define FRAME_N(n) (&debug_context->frames[debug_context->stack_size-(n)-1])
63
- #define GET_FRAME (FRAME_N(check_frame_number(debug_context, frame)))
64
-
65
- #ifndef min
66
- #define min(x,y) ((x) < (y) ? (x) : (y))
67
- #endif
68
-
69
- #define STACK_SIZE_INCREMENT 128
70
-
71
- typedef struct {
72
- VALUE binding;
73
- ID id;
74
- ID orig_id;
75
- int line;
76
- const char * file;
77
- short dead;
78
- VALUE self;
79
- union {
80
- struct {
81
- struct FRAME *frame;
82
- struct SCOPE *scope;
83
- struct RVarmap *dyna_vars;
84
- } runtime;
85
- struct {
86
- VALUE locals;
87
- } copy;
88
- } info;
89
- } debug_frame_t;
90
-
91
- typedef struct {
92
- VALUE thread_id;
93
- int thnum;
94
- int flags;
95
- int stop_next;
96
- int dest_frame;
97
- int stop_line;
98
- int stop_frame;
99
- int stack_size;
100
- int stack_len;
101
- debug_frame_t *frames;
102
- const char * last_file;
103
- int last_line;
104
- } debug_context_t;
105
-
106
- enum bp_type {BP_POS_TYPE, BP_METHOD_TYPE};
107
-
108
- typedef struct {
109
- int id;
110
- int type;
111
- VALUE source;
112
- union
113
- {
114
- int line;
115
- ID mid;
116
- } pos;
117
- VALUE expr;
118
- } debug_breakpoint_t;
119
-
120
- typedef struct {
121
- st_table *tbl;
122
- } threads_table_t;
123
-
124
- static VALUE threads_tbl = Qnil;
125
- static VALUE breakpoints = Qnil;
126
- static VALUE catchpoint = Qnil;
127
- static VALUE tracing = Qfalse;
128
- static VALUE locker = Qnil;
129
- static VALUE post_mortem = Qfalse;
130
- static VALUE keep_frame_binding = Qfalse;
131
- static VALUE debug = Qfalse;
132
-
133
- static VALUE last_context = Qnil;
134
- static VALUE last_thread = Qnil;
135
- static debug_context_t *last_debug_context = NULL;
136
-
137
- static VALUE mDebugger;
138
- static VALUE cThreadsTable;
139
- static VALUE cContext;
140
- static VALUE cBreakpoint;
141
- static VALUE cDebugThread;
142
-
143
- static VALUE rb_mObjectSpace;
144
-
145
- static ID idAtLine;
146
- static ID idAtBreakpoint;
147
- static ID idAtCatchpoint;
148
- static ID idAtTracing;
149
- static ID idEval;
150
- static ID idList;
151
-
152
- static int start_count = 0;
153
- static int thnum_max = 0;
154
- static int bkp_count = 0;
155
- static int last_debugged_thnum = -1;
156
- static unsigned long last_check = 0;
157
- static unsigned long hook_count = 0;
158
-
159
- static VALUE create_binding(VALUE);
160
- static VALUE debug_stop(VALUE);
161
- static void save_current_position(debug_context_t *);
162
- static VALUE context_copy_locals(debug_frame_t *);
163
- static void context_suspend_0(debug_context_t *);
164
- static void context_resume_0(debug_context_t *);
165
-
166
- typedef struct locked_thread_t {
167
- VALUE thread_id;
168
- struct locked_thread_t *next;
169
- } locked_thread_t;
170
-
171
- static locked_thread_t *locked_head = NULL;
172
- static locked_thread_t *locked_tail = NULL;
173
-
174
- inline static void *
175
- ruby_method_ptr(VALUE class, ID meth_id)
176
- {
177
- NODE *body, *method;
178
- st_lookup(RCLASS(class)->m_tbl, meth_id, (st_data_t *)&body);
179
- method = (NODE *)body->u2.value;
180
- return (void *)method->u1.value;
181
- }
182
-
183
- inline static VALUE
184
- ref2id(VALUE obj)
185
- {
186
- return rb_obj_id(obj);
187
- }
188
-
189
- static VALUE
190
- id2ref_unprotected(VALUE id)
191
- {
192
- typedef VALUE (*id2ref_func_t)(VALUE, VALUE);
193
- static id2ref_func_t f_id2ref = NULL;
194
- if(f_id2ref == NULL)
195
- {
196
- f_id2ref = (id2ref_func_t)ruby_method_ptr(rb_mObjectSpace, rb_intern("_id2ref"));
197
- }
198
- return f_id2ref(rb_mObjectSpace, id);
199
- }
200
-
201
- static VALUE
202
- id2ref_error()
203
- {
204
- rb_p(ruby_errinfo);
205
- return Qnil;
206
- }
207
-
208
- static VALUE
209
- id2ref(VALUE id)
210
- {
211
- return rb_rescue(id2ref_unprotected, id, id2ref_error, 0);
212
- }
213
-
214
- inline static VALUE
215
- context_thread_0(debug_context_t *debug_context)
216
- {
217
- return id2ref(debug_context->thread_id);
218
- }
219
-
220
- static int
221
- is_in_locked(VALUE thread_id)
222
- {
223
- locked_thread_t *node;
224
-
225
- if(!locked_head)
226
- return 0;
227
-
228
- for(node = locked_head; node != locked_tail; node = node->next)
229
- {
230
- if(node->thread_id == thread_id) return 1;
231
- }
232
- return 0;
233
- }
234
-
235
- static void
236
- add_to_locked(VALUE thread)
237
- {
238
- locked_thread_t *node;
239
- VALUE thread_id = ref2id(thread);
240
-
241
- if(is_in_locked(thread_id))
242
- return;
243
-
244
- node = ALLOC(locked_thread_t);
245
- node->thread_id = thread_id;
246
- node->next = NULL;
247
- if(locked_tail)
248
- locked_tail->next = node;
249
- locked_tail = node;
250
- if(!locked_head)
251
- locked_head = node;
252
- }
253
-
254
- static VALUE
255
- remove_from_locked()
256
- {
257
- VALUE thread;
258
- locked_thread_t *node;
259
-
260
- if(locked_head == NULL)
261
- return Qnil;
262
- node = locked_head;
263
- locked_head = locked_head->next;
264
- if(locked_tail == node)
265
- locked_tail = NULL;
266
- thread = id2ref(node->thread_id);
267
- xfree(node);
268
- return thread;
269
- }
270
-
271
- static int
272
- threads_table_mark_keyvalue(VALUE key, VALUE value, int dummy)
273
- {
274
- rb_gc_mark(value);
275
- return ST_CONTINUE;
276
- }
277
-
278
- static void
279
- threads_table_mark(void* data)
280
- {
281
- threads_table_t *threads_table = (threads_table_t*)data;
282
- st_foreach(threads_table->tbl, threads_table_mark_keyvalue, 0);
283
- }
284
-
285
- static void
286
- threads_table_free(void* data)
287
- {
288
- threads_table_t *threads_table = (threads_table_t*)data;
289
- st_free_table(threads_table->tbl);
290
- xfree(threads_table);
291
- }
292
-
293
- static VALUE
294
- threads_table_create()
295
- {
296
- threads_table_t *threads_table;
297
-
298
- threads_table = ALLOC(threads_table_t);
299
- threads_table->tbl = st_init_numtable();
300
- return Data_Wrap_Struct(cThreadsTable, threads_table_mark, threads_table_free, threads_table);
301
- }
302
-
303
- static int
304
- threads_table_clear_i(VALUE key, VALUE value, VALUE dummy)
305
- {
306
- return ST_DELETE;
307
- }
308
-
309
- static void
310
- threads_table_clear(VALUE table)
311
- {
312
- threads_table_t *threads_table;
313
-
314
- Data_Get_Struct(table, threads_table_t, threads_table);
315
- st_foreach(threads_table->tbl, threads_table_clear_i, 0);
316
- }
317
-
318
- static VALUE
319
- is_thread_alive(VALUE thread)
320
- {
321
- typedef VALUE (*thread_alive_func_t)(VALUE);
322
- static thread_alive_func_t f_thread_alive = NULL;
323
- if(!f_thread_alive)
324
- {
325
- f_thread_alive = (thread_alive_func_t)ruby_method_ptr(rb_cThread, rb_intern("alive?"));
326
- }
327
- return f_thread_alive(thread);
328
- }
329
-
330
- static int
331
- threads_table_check_i(VALUE key, VALUE value, VALUE dummy)
332
- {
333
- VALUE thread;
334
-
335
- thread = id2ref(key);
336
- if(!rb_obj_is_kind_of(thread, rb_cThread))
337
- {
338
- return ST_DELETE;
339
- }
340
- if(rb_protect(is_thread_alive, thread, 0) != Qtrue)
341
- {
342
- return ST_DELETE;
343
- }
344
- return ST_CONTINUE;
345
- }
346
-
347
- static void
348
- check_thread_contexts()
349
- {
350
- threads_table_t *threads_table;
351
-
352
- Data_Get_Struct(threads_tbl, threads_table_t, threads_table);
353
- st_foreach(threads_table->tbl, threads_table_check_i, 0);
354
- }
355
-
356
- /*
357
- * call-seq:
358
- * Debugger.started? -> bool
359
- *
360
- * Returns +true+ the debugger is started.
361
- */
362
- static VALUE
363
- debug_is_started(VALUE self)
364
- {
365
- return IS_STARTED ? Qtrue : Qfalse;
366
- }
367
-
368
- static void
369
- debug_check_started()
370
- {
371
- if(!IS_STARTED)
372
- {
373
- rb_raise(rb_eRuntimeError, "Debugger.start is not called yet.");
374
- }
375
- }
376
-
377
- static void
378
- debug_context_mark(void *data)
379
- {
380
- debug_frame_t *frame;
381
- int i;
382
-
383
- debug_context_t *debug_context = (debug_context_t *)data;
384
- for(i = 0; i < debug_context->stack_size; i++)
385
- {
386
- frame = &(debug_context->frames[i]);
387
- rb_gc_mark(frame->binding);
388
- rb_gc_mark(frame->self);
389
- if(frame->dead)
390
- {
391
- rb_gc_mark(frame->info.copy.locals);
392
- }
393
- }
394
- }
395
-
396
- static void
397
- debug_context_free(void *data)
398
- {
399
- debug_context_t *debug_context = (debug_context_t *)data;
400
- xfree(debug_context->frames);
401
- }
402
-
403
- static VALUE
404
- debug_context_create(VALUE thread)
405
- {
406
- debug_context_t *debug_context;
407
-
408
- debug_context = ALLOC(debug_context_t);
409
- debug_context-> thnum = ++thnum_max;
410
-
411
- debug_context->last_file = NULL;
412
- debug_context->last_line = 0;
413
- debug_context->flags = 0;
414
-
415
- debug_context->stop_next = -1;
416
- debug_context->dest_frame = -1;
417
- debug_context->stop_line = -1;
418
- debug_context->stop_frame = -1;
419
- debug_context->stack_len = STACK_SIZE_INCREMENT;
420
- debug_context->frames = ALLOC_N(debug_frame_t, STACK_SIZE_INCREMENT);
421
- debug_context->stack_size = 0;
422
- debug_context->thread_id = ref2id(thread);
423
- if(rb_obj_class(thread) == cDebugThread)
424
- CTX_FL_SET(debug_context, CTX_FL_IGNORE);
425
- return Data_Wrap_Struct(cContext, debug_context_mark, debug_context_free, debug_context);
426
- }
427
-
428
- static VALUE
429
- debug_context_dup(debug_context_t *debug_context)
430
- {
431
- debug_context_t *new_debug_context;
432
- debug_frame_t *new_frame, *old_frame;
433
- int i;
434
-
435
- new_debug_context = ALLOC(debug_context_t);
436
- memcpy(new_debug_context, debug_context, sizeof(debug_context_t));
437
- new_debug_context->stop_next = -1;
438
- new_debug_context->dest_frame = -1;
439
- new_debug_context->stop_line = -1;
440
- new_debug_context->stop_frame = -1;
441
- CTX_FL_SET(new_debug_context, CTX_FL_DEAD);
442
- new_debug_context->frames = ALLOC_N(debug_frame_t, debug_context->stack_size);
443
- new_debug_context->stack_len = debug_context->stack_size;
444
- memcpy(new_debug_context->frames, debug_context->frames, sizeof(debug_frame_t) * debug_context->stack_size);
445
- for(i = 0; i < debug_context->stack_size; i++)
446
- {
447
- new_frame = &(new_debug_context->frames[i]);
448
- old_frame = &(debug_context->frames[i]);
449
- new_frame->dead = 1;
450
- new_frame->info.copy.locals = context_copy_locals(old_frame);
451
- }
452
- return Data_Wrap_Struct(cContext, debug_context_mark, debug_context_free, new_debug_context);
453
- }
454
-
455
- static void
456
- thread_context_lookup(VALUE thread, VALUE *context, debug_context_t **debug_context)
457
- {
458
- threads_table_t *threads_table;
459
- VALUE thread_id;
460
- debug_context_t *l_debug_context;
461
-
462
- debug_check_started();
463
-
464
- if(last_thread == thread && last_context != Qnil)
465
- {
466
- *context = last_context;
467
- if(debug_context)
468
- *debug_context = last_debug_context;
469
- return;
470
- }
471
- thread_id = ref2id(thread);
472
- Data_Get_Struct(threads_tbl, threads_table_t, threads_table);
473
- if(!st_lookup(threads_table->tbl, thread_id, context))
474
- {
475
- *context = debug_context_create(thread);
476
- st_insert(threads_table->tbl, thread_id, *context);
477
- }
478
-
479
- Data_Get_Struct(*context, debug_context_t, l_debug_context);
480
- if(debug_context)
481
- *debug_context = l_debug_context;
482
-
483
- last_thread = thread;
484
- last_context = *context;
485
- last_debug_context = l_debug_context;
486
- }
487
-
488
- static VALUE
489
- call_at_line_unprotected(VALUE args)
490
- {
491
- VALUE context;
492
- context = *RARRAY(args)->ptr;
493
- return rb_funcall2(context, idAtLine, RARRAY(args)->len - 1, RARRAY(args)->ptr + 1);
494
- }
495
-
496
- static VALUE
497
- call_at_line(VALUE context, debug_context_t *debug_context, VALUE file, VALUE line)
498
- {
499
- VALUE args;
500
-
501
- last_debugged_thnum = debug_context->thnum;
502
- save_current_position(debug_context);
503
-
504
- args = rb_ary_new3(3, context, file, line);
505
- return rb_protect(call_at_line_unprotected, args, 0);
506
- }
507
-
508
- static void
509
- save_call_frame(rb_event_t event, VALUE self, char *file, int line, ID mid, debug_context_t *debug_context)
510
- {
511
- VALUE binding;
512
- debug_frame_t *debug_frame;
513
- int frame_n;
514
-
515
- binding = self && RTEST(keep_frame_binding)? create_binding(self) : Qnil;
516
-
517
- frame_n = debug_context->stack_size++;
518
- if(frame_n >= debug_context->stack_len)
519
- {
520
- debug_context->stack_len += STACK_SIZE_INCREMENT;
521
- debug_context->frames = REALLOC_N(debug_context->frames, debug_frame_t, debug_context->stack_len);
522
- }
523
- debug_frame = &debug_context->frames[frame_n];
524
- debug_frame->file = file;
525
- debug_frame->line = line;
526
- debug_frame->binding = binding;
527
- debug_frame->id = mid;
528
- debug_frame->orig_id = mid;
529
- debug_frame->dead = 0;
530
- debug_frame->self = self;
531
- debug_frame->info.runtime.frame = ruby_frame;
532
- debug_frame->info.runtime.scope = ruby_scope;
533
- debug_frame->info.runtime.dyna_vars = event == RUBY_EVENT_LINE ? ruby_dyna_vars : NULL;
534
- }
535
-
536
- #if defined DOSISH
537
- #define isdirsep(x) ((x) == '/' || (x) == '\\')
538
- #else
539
- #define isdirsep(x) ((x) == '/')
540
- #endif
541
-
542
- static int
543
- filename_cmp(VALUE source, char *file)
544
- {
545
- char *source_ptr, *file_ptr;
546
- int s_len, f_len, min_len;
547
- int s,f;
548
- int dirsep_flag = 0;
549
-
550
- s_len = RSTRING(source)->len;
551
- f_len = strlen(file);
552
- min_len = min(s_len, f_len);
553
-
554
- source_ptr = RSTRING(source)->ptr;
555
- file_ptr = file;
556
-
557
- for( s = s_len - 1, f = f_len - 1; s >= s_len - min_len && f >= f_len - min_len; s--, f-- )
558
- {
559
- if((source_ptr[s] == '.' || file_ptr[f] == '.') && dirsep_flag)
560
- return 1;
561
- if(source_ptr[s] != file_ptr[f])
562
- return 0;
563
- if(isdirsep(source_ptr[s]))
564
- dirsep_flag = 1;
565
- }
566
- return 1;
567
- }
568
-
569
- static int
570
- check_breakpoints_by_pos(debug_context_t *debug_context, char *file, int line)
571
- {
572
- VALUE breakpoint;
573
- debug_breakpoint_t *debug_breakpoint;
574
- int i;
575
-
576
- if(RARRAY(breakpoints)->len == 0)
577
- return -1;
578
- if(!CTX_FL_TEST(debug_context, CTX_FL_MOVED))
579
- return -1;
580
-
581
- for(i = 0; i < RARRAY(breakpoints)->len; i++)
582
- {
583
- breakpoint = rb_ary_entry(breakpoints, i);
584
- Data_Get_Struct(breakpoint, debug_breakpoint_t, debug_breakpoint);
585
- if(debug_breakpoint->type != BP_POS_TYPE)
586
- continue;
587
- if(debug_breakpoint->pos.line != line)
588
- continue;
589
- if(filename_cmp(debug_breakpoint->source, file))
590
- return i;
591
- }
592
- return -1;
593
- }
594
-
595
- inline static int
596
- classname_cmp(VALUE name, VALUE klass)
597
- {
598
- return (klass != Qnil && rb_str_cmp(name, rb_mod_name(klass)) == 0);
599
- }
600
-
601
- static int
602
- check_breakpoints_by_method(debug_context_t *debug_context, VALUE klass, ID mid)
603
- {
604
- VALUE breakpoint;
605
- debug_breakpoint_t *debug_breakpoint;
606
- int i;
607
-
608
- if(RARRAY(breakpoints)->len == 0)
609
- return -1;
610
- if(!CTX_FL_TEST(debug_context, CTX_FL_MOVED))
611
- return -1;
612
- for(i = 0; i < RARRAY(breakpoints)->len; i++)
613
- {
614
- breakpoint = rb_ary_entry(breakpoints, i);
615
- Data_Get_Struct(breakpoint, debug_breakpoint_t, debug_breakpoint);
616
- if(debug_breakpoint->type != BP_METHOD_TYPE)
617
- continue;
618
- if(debug_breakpoint->pos.mid != mid)
619
- continue;
620
- if(classname_cmp(debug_breakpoint->source, klass))
621
- return i;
622
- }
623
- return -1;
624
- }
625
-
626
- /*
627
- * This is a NASTY HACK. For some reasons rb_f_binding is decalred
628
- * static in eval.c
629
- */
630
- static VALUE
631
- create_binding(VALUE self)
632
- {
633
- typedef VALUE (*bind_func_t)(VALUE);
634
- static bind_func_t f_binding = NULL;
635
-
636
- if(f_binding == NULL)
637
- {
638
- f_binding = (bind_func_t)ruby_method_ptr(rb_mKernel, rb_intern("binding"));
639
- }
640
- return f_binding(self);
641
- }
642
-
643
- static VALUE
644
- get_breakpoint_at(int index)
645
- {
646
- return rb_ary_entry(breakpoints, index);
647
- }
648
-
649
- static VALUE
650
- eval_expression(VALUE args)
651
- {
652
- return rb_funcall2(rb_mKernel, idEval, 2, RARRAY(args)->ptr);
653
- }
654
-
655
- inline static int
656
- check_breakpoint_expression(VALUE breakpoint, VALUE binding)
657
- {
658
- debug_breakpoint_t *debug_breakpoint;
659
- VALUE args, expr_result;
660
-
661
- Data_Get_Struct(breakpoint, debug_breakpoint_t, debug_breakpoint);
662
- if(NIL_P(debug_breakpoint->expr))
663
- return 1;
664
-
665
- args = rb_ary_new3(2, debug_breakpoint->expr, binding);
666
- expr_result = rb_protect(eval_expression, args, 0);
667
- return RTEST(expr_result);
668
- }
669
-
670
- inline static debug_frame_t *
671
- get_top_frame(debug_context_t *debug_context)
672
- {
673
- if(debug_context->stack_size == 0)
674
- return NULL;
675
- else
676
- return &(debug_context->frames[debug_context->stack_size-1]);
677
- }
678
-
679
- inline static void
680
- save_top_binding(debug_context_t *debug_context, VALUE binding)
681
- {
682
- debug_frame_t *debug_frame;
683
- debug_frame = get_top_frame(debug_context);
684
- if(debug_frame)
685
- debug_frame->binding = binding;
686
- }
687
-
688
- inline static void
689
- set_frame_source(rb_event_t event, debug_context_t *debug_context, VALUE self, char *file, int line, ID mid)
690
- {
691
- debug_frame_t *top_frame;
692
- top_frame = get_top_frame(debug_context);
693
- if(top_frame)
694
- {
695
- top_frame->self = self;
696
- top_frame->file = file;
697
- top_frame->line = line;
698
- top_frame->id = mid;
699
- top_frame->info.runtime.dyna_vars = event == RUBY_EVENT_C_CALL ? NULL : ruby_dyna_vars;
700
- }
701
- }
702
-
703
- static void
704
- save_current_position(debug_context_t *debug_context)
705
- {
706
- debug_frame_t *debug_frame;
707
-
708
- debug_frame = get_top_frame(debug_context);
709
- if(!debug_frame) return;
710
- debug_context->last_file = debug_frame->file;
711
- debug_context->last_line = debug_frame->line;
712
- CTX_FL_UNSET(debug_context, CTX_FL_MOVED);
713
- }
714
-
715
- static char *
716
- get_event_name(rb_event_t event)
717
- {
718
- switch (event) {
719
- case RUBY_EVENT_LINE:
720
- return "line";
721
- case RUBY_EVENT_CLASS:
722
- return "class";
723
- case RUBY_EVENT_END:
724
- return "end";
725
- case RUBY_EVENT_CALL:
726
- return "call";
727
- case RUBY_EVENT_RETURN:
728
- return "return";
729
- case RUBY_EVENT_C_CALL:
730
- return "c-call";
731
- case RUBY_EVENT_C_RETURN:
732
- return "c-return";
733
- case RUBY_EVENT_RAISE:
734
- return "raise";
735
- default:
736
- return "unknown";
737
- }
738
- }
739
-
740
-
741
- static void
742
- debug_event_hook(rb_event_t event, NODE *node, VALUE self, ID mid, VALUE klass)
743
- {
744
- VALUE thread, context, breakpoint;
745
- VALUE binding = Qnil;
746
- debug_context_t *debug_context;
747
- char *file;
748
- int line;
749
- int breakpoint_index = -1;
750
-
751
- hook_count++;
752
-
753
- if (mid == ID_ALLOCATOR) return;
754
-
755
- thread = rb_thread_current();
756
- thread_context_lookup(thread, &context, &debug_context);
757
-
758
- /* return if thread is marked as 'ignored'.
759
- debugger's threads are marked this way
760
- */
761
- if(CTX_FL_TEST(debug_context, CTX_FL_IGNORE)) return;
762
-
763
- while(1)
764
- {
765
- /* halt execution of the current thread if the debugger
766
- is activated in another
767
- */
768
- while(locker != Qnil && locker != thread)
769
- {
770
- add_to_locked(thread);
771
- rb_thread_stop();
772
- }
773
-
774
- /* stop the current thread if it's marked as suspended */
775
- if(CTX_FL_TEST(debug_context, CTX_FL_SUSPEND))
776
- {
777
- CTX_FL_SET(debug_context, CTX_FL_WAS_RUNNING);
778
- rb_thread_stop();
779
- }
780
- else break;
781
- }
782
-
783
- /* return if the current thread is the locker */
784
- if(locker != Qnil) return;
785
-
786
- /* only the current thread can proceed */
787
- locker = thread;
788
-
789
- /* ignore a skipped section of code */
790
- if(CTX_FL_TEST(debug_context, CTX_FL_SKIPPED)) goto cleanup;
791
-
792
- if(node)
793
- {
794
- file = node->nd_file;
795
- line = nd_line(node);
796
-
797
- if(debug == Qtrue)
798
- fprintf(stderr, "%s:%d [%s] %s\n", file, line, get_event_name(event), rb_id2name(mid));
799
-
800
- if(DID_MOVED)
801
- CTX_FL_SET(debug_context, CTX_FL_MOVED);
802
- }
803
- else if(event != RUBY_EVENT_RETURN && event != RUBY_EVENT_C_RETURN)
804
- {
805
- if(debug == Qtrue)
806
- fprintf(stderr, "return [%s] %s\n", get_event_name(event), rb_id2name(mid));
807
- goto cleanup;
808
- }
809
-
810
- switch(event)
811
- {
812
- case RUBY_EVENT_LINE:
813
- {
814
- set_frame_source(event, debug_context, self, file, line, mid);
815
-
816
- if(RTEST(tracing) || CTX_FL_TEST(debug_context, CTX_FL_TRACING))
817
- rb_funcall(context, idAtTracing, 2, rb_str_new2(file), INT2FIX(line));
818
-
819
- if(debug_context->dest_frame == -1 ||
820
- debug_context->stack_size == debug_context->dest_frame)
821
- {
822
- debug_context->stop_next--;
823
- if(debug_context->stop_next < 0)
824
- debug_context->stop_next = -1;
825
- /* we check that we actualy moved to another line */
826
- if(DID_MOVED)
827
- debug_context->stop_line--;
828
- }
829
- else if(debug_context->stack_size < debug_context->dest_frame)
830
- {
831
- debug_context->stop_next = 0;
832
- }
833
-
834
- if(debug_context->stack_size == 0)
835
- save_call_frame(event, self, file, line, mid, debug_context);
836
-
837
- if(debug_context->stop_next == 0 || debug_context->stop_line == 0 ||
838
- (breakpoint_index = check_breakpoints_by_pos(debug_context, file, line)) != -1)
839
- {
840
- binding = self? create_binding(self) : Qnil;
841
- /* check breakpoint expression */
842
- if(breakpoint_index != -1)
843
- {
844
- breakpoint = get_breakpoint_at(breakpoint_index);
845
- if(check_breakpoint_expression(breakpoint, binding))
846
- rb_funcall(context, idAtBreakpoint, 1, breakpoint);
847
- else
848
- break;
849
- }
850
-
851
- /* reset all pointers */
852
- debug_context->dest_frame = -1;
853
- debug_context->stop_line = -1;
854
- debug_context->stop_next = -1;
855
-
856
- save_top_binding(debug_context, binding);
857
- call_at_line(context, debug_context, rb_str_new2(file), INT2FIX(line));
858
- }
859
- break;
860
- }
861
- case RUBY_EVENT_C_CALL:
862
- {
863
- set_frame_source(event, debug_context, self, file, line, mid);
864
- break;
865
- }
866
- case RUBY_EVENT_CALL:
867
- {
868
- save_call_frame(event, self, file, line, mid, debug_context);
869
- breakpoint_index = check_breakpoints_by_method(debug_context, klass, mid);
870
- if(breakpoint_index != -1)
871
- {
872
- debug_frame_t *debug_frame;
873
- debug_frame = get_top_frame(debug_context);
874
- if(debug_frame)
875
- binding = debug_frame->binding;
876
- if(NIL_P(binding) && self)
877
- binding = create_binding(self);
878
- breakpoint = get_breakpoint_at(breakpoint_index);
879
- if(check_breakpoint_expression(breakpoint, binding))
880
- {
881
- save_top_binding(debug_context, binding);
882
- rb_funcall(context, idAtBreakpoint, 1, breakpoint);
883
- call_at_line(context, debug_context, rb_str_new2(file), INT2FIX(line));
884
- }
885
- }
886
- break;
887
- }
888
- case RUBY_EVENT_RETURN:
889
- case RUBY_EVENT_END:
890
- {
891
- if(debug_context->stack_size == debug_context->stop_frame)
892
- {
893
- debug_context->stop_next = 1;
894
- debug_context->stop_frame = 0;
895
- }
896
- while(debug_context->stack_size > 0)
897
- {
898
- debug_context->stack_size--;
899
- if(debug_context->frames[debug_context->stack_size].orig_id == mid)
900
- break;
901
- }
902
- break;
903
- }
904
- case RUBY_EVENT_CLASS:
905
- {
906
- save_call_frame(event, self, file, line, mid, debug_context);
907
- break;
908
- }
909
- case RUBY_EVENT_RAISE:
910
- {
911
- VALUE ancestors;
912
- VALUE expn_class, aclass;
913
- int i;
914
-
915
- set_frame_source(event, debug_context, self, file, line, mid);
916
-
917
- if(post_mortem == Qtrue && self)
918
- {
919
- binding = create_binding(self);
920
- rb_ivar_set(ruby_errinfo, rb_intern("@__debug_file"), rb_str_new2(file));
921
- rb_ivar_set(ruby_errinfo, rb_intern("@__debug_line"), INT2FIX(line));
922
- rb_ivar_set(ruby_errinfo, rb_intern("@__debug_binding"), binding);
923
- rb_ivar_set(ruby_errinfo, rb_intern("@__debug_context"), debug_context_dup(debug_context));
924
- }
925
-
926
- expn_class = rb_obj_class(ruby_errinfo);
927
- if( !NIL_P(rb_class_inherited_p(expn_class, rb_eSystemExit)) )
928
- {
929
- debug_stop(mDebugger);
930
- break;
931
- }
932
-
933
- if(catchpoint == Qnil)
934
- break;
935
-
936
- ancestors = rb_mod_ancestors(expn_class);
937
- for(i = 0; i < RARRAY(ancestors)->len; i++)
938
- {
939
- aclass = rb_ary_entry(ancestors, i);
940
- if(rb_str_cmp(rb_mod_name(aclass), catchpoint) == 0)
941
- {
942
- rb_funcall(context, idAtCatchpoint, 1, ruby_errinfo);
943
- if(self && binding == Qnil)
944
- binding = create_binding(self);
945
- save_top_binding(debug_context, binding);
946
- call_at_line(context, debug_context, rb_str_new2(file), INT2FIX(line));
947
- break;
948
- }
949
- }
950
-
951
- break;
952
- }
953
- case RUBY_EVENT_C_RETURN:
954
- {
955
- break;
956
- }
957
- }
958
-
959
- cleanup:
960
-
961
- /* check that all contexts point to alive threads */
962
- if(hook_count - last_check > 3000)
963
- {
964
- check_thread_contexts();
965
- last_check = hook_count;
966
- }
967
-
968
- /* release a lock */
969
- locker = Qnil;
970
- /* let the next thread to run */
971
- thread = remove_from_locked();
972
- if(thread != Qnil)
973
- rb_thread_run(thread);
974
- }
975
-
976
- static VALUE
977
- debug_stop_i(VALUE self)
978
- {
979
- if(IS_STARTED)
980
- debug_stop(self);
981
- return Qnil;
982
- }
983
-
984
- /*
985
- * call-seq:
986
- * Debugger.start -> bool
987
- * Debugger.start { ... } -> obj
988
- *
989
- * This method activates the debugger.
990
- * If it's called without a block it returns +true+, unless debugger was already started.
991
- * If a block is given, it starts debugger and yields to block. When the block is finished
992
- * executing it stops the debugger with Debugger.stop method.
993
- *
994
- * <i>Note that if you want to stop debugger, you must call Debugger.stop as many time as you
995
- * called Debugger.start method.</i>
996
- */
997
- static VALUE
998
- debug_start(VALUE self)
999
- {
1000
- VALUE result;
1001
- start_count++;
1002
-
1003
- if(IS_STARTED)
1004
- result = Qfalse;
1005
- else
1006
- {
1007
- breakpoints = rb_ary_new();
1008
- locker = Qnil;
1009
- threads_tbl = threads_table_create();
1010
-
1011
- rb_add_event_hook(debug_event_hook, RUBY_EVENT_ALL);
1012
- result = Qtrue;
1013
- }
1014
-
1015
- if(rb_block_given_p())
1016
- return rb_ensure(rb_yield, self, debug_stop_i, self);
1017
- return result;
1018
- }
1019
-
1020
- /*
1021
- * call-seq:
1022
- * Debugger.stop -> bool
1023
- *
1024
- * This method disacivates the debugger. It returns +true+ if the debugger is disacivated,
1025
- * otherwise it returns +false+.
1026
- *
1027
- * <i>Note that if you want to stop debugger, you must call Debugger.stop as many time as you
1028
- * called Debugger.start method.</i>
1029
- */
1030
- static VALUE
1031
- debug_stop(VALUE self)
1032
- {
1033
- debug_check_started();
1034
-
1035
- start_count--;
1036
- if(start_count)
1037
- return Qfalse;
1038
-
1039
- rb_remove_event_hook(debug_event_hook);
1040
-
1041
- locker = Qnil;
1042
- breakpoints = Qnil;
1043
- threads_tbl = Qnil;
1044
-
1045
- return Qtrue;
1046
- }
1047
-
1048
- static void
1049
- breakpoint_mark(void *data)
1050
- {
1051
- debug_breakpoint_t *breakpoint;
1052
- breakpoint = (debug_breakpoint_t *)data;
1053
- rb_gc_mark(breakpoint->source);
1054
- rb_gc_mark(breakpoint->expr);
1055
- }
1056
-
1057
- /*
1058
- * call-seq:
1059
- * Debugger.add_breakpoint(source, pos, condition = nil) -> breakpoint
1060
- *
1061
- * Adds a new breakpoint.
1062
- * <i>source</i> is a name of a file or a class.
1063
- * <i>pos</i> is a line number or a method name if <i>source</i> is a class name.
1064
- * <i>condition</i> is a string which is evaluated to +true+ when this breakpoint
1065
- * is activated.
1066
- */
1067
- static VALUE
1068
- debug_add_breakpoint(int argc, VALUE *argv, VALUE self)
1069
- {
1070
- VALUE source, pos, expr;
1071
- VALUE result;
1072
- debug_breakpoint_t *breakpoint;
1073
- int type;
1074
-
1075
- debug_check_started();
1076
-
1077
- if(rb_scan_args(argc, argv, "21", &source, &pos, &expr) == 2)
1078
- {
1079
- expr = Qnil;
1080
- }
1081
- type = FIXNUM_P(pos) ? BP_POS_TYPE : BP_METHOD_TYPE;
1082
- if(type == BP_POS_TYPE)
1083
- source = StringValue(source);
1084
- else
1085
- pos = StringValue(pos);
1086
- breakpoint = ALLOC(debug_breakpoint_t);
1087
- breakpoint->id = ++bkp_count;
1088
- breakpoint->source = source;
1089
- breakpoint->type = type;
1090
- if(type == BP_POS_TYPE)
1091
- breakpoint->pos.line = FIX2INT(pos);
1092
- else
1093
- breakpoint->pos.mid = rb_intern(RSTRING(pos)->ptr);
1094
- breakpoint->expr = NIL_P(expr) ? expr: StringValue(expr);
1095
- result = Data_Wrap_Struct(cBreakpoint, breakpoint_mark, xfree, breakpoint);
1096
- rb_ary_push(breakpoints, result);
1097
- return result;
1098
- }
1099
-
1100
- /*
1101
- * call-seq:
1102
- * Debugger.remove_breakpoint(id) -> breakpoint
1103
- *
1104
- * Removes breakpoint by its id.
1105
- * <i>id</i> is an identificator of a breakpoint.
1106
- */
1107
- static VALUE
1108
- debug_remove_breakpoint(VALUE self, VALUE id_value)
1109
- {
1110
- int i;
1111
- int id;
1112
- VALUE breakpoint;
1113
- debug_breakpoint_t *debug_breakpoint;
1114
-
1115
- id = FIX2INT(id_value);
1116
-
1117
- for( i = 0; i < RARRAY(breakpoints)->len; i += 1 )
1118
- {
1119
- breakpoint = rb_ary_entry(breakpoints, i);
1120
- Data_Get_Struct(breakpoint, debug_breakpoint_t, debug_breakpoint);
1121
- if(debug_breakpoint->id == id)
1122
- {
1123
- rb_ary_delete_at(breakpoints, i);
1124
- return breakpoint;
1125
- }
1126
- }
1127
- return Qnil;
1128
- }
1129
-
1130
- /*
1131
- * call-seq:
1132
- * Debugger.breakpoints -> array
1133
- *
1134
- * Returns an array of breakpoints.
1135
- */
1136
- static VALUE
1137
- debug_breakpoints(VALUE self)
1138
- {
1139
- debug_check_started();
1140
-
1141
- return breakpoints;
1142
- }
1143
-
1144
- /*
1145
- * call-seq:
1146
- * Debugger.checkpoint -> string
1147
- *
1148
- * Returns a current checkpoint, which is a name of exception that will
1149
- * trigger a debugger when raised.
1150
- */
1151
- static VALUE
1152
- debug_catchpoint(VALUE self)
1153
- {
1154
- debug_check_started();
1155
-
1156
- return catchpoint;
1157
- }
1158
-
1159
- /*
1160
- * call-seq:
1161
- * Debugger.checkpoint = string -> string
1162
- *
1163
- * Sets checkpoint.
1164
- */
1165
- static VALUE
1166
- debug_set_catchpoint(VALUE self, VALUE value)
1167
- {
1168
- debug_check_started();
1169
-
1170
- if (!NIL_P(value) && TYPE(value) != T_STRING) {
1171
- rb_raise(rb_eTypeError, "value of checkpoint must be String");
1172
- }
1173
- if(NIL_P(value))
1174
- catchpoint = Qnil;
1175
- else
1176
- catchpoint = rb_str_dup(value);
1177
- return value;
1178
- }
1179
-
1180
- static int
1181
- find_last_context_func(VALUE key, VALUE value, VALUE *result)
1182
- {
1183
- debug_context_t *debug_context;
1184
- Data_Get_Struct(value, debug_context_t, debug_context);
1185
- if(debug_context->thnum == last_debugged_thnum)
1186
- {
1187
- *result = value;
1188
- return ST_STOP;
1189
- }
1190
- return ST_CONTINUE;
1191
- }
1192
-
1193
- /*
1194
- * call-seq:
1195
- * Debugger.last_interrupted -> context
1196
- *
1197
- * Returns last debugged context.
1198
- */
1199
- static VALUE
1200
- debug_last_interrupted(VALUE self)
1201
- {
1202
- VALUE result = Qnil;
1203
- threads_table_t *threads_table;
1204
-
1205
- debug_check_started();
1206
-
1207
- Data_Get_Struct(threads_tbl, threads_table_t, threads_table);
1208
-
1209
- st_foreach(threads_table->tbl, find_last_context_func, (st_data_t)&result);
1210
- return result;
1211
- }
1212
-
1213
- /*
1214
- * call-seq:
1215
- * Debugger.current_context -> context
1216
- *
1217
- * Returns current context.
1218
- * <i>Note:</i> Debugger.current_context.thread == Thread.current
1219
- */
1220
- static VALUE
1221
- debug_current_context(VALUE self)
1222
- {
1223
- VALUE thread, context;
1224
-
1225
- debug_check_started();
1226
-
1227
- thread = rb_thread_current();
1228
- thread_context_lookup(thread, &context, NULL);
1229
-
1230
- return context;
1231
- }
1232
-
1233
- /*
1234
- * call-seq:
1235
- * Debugger.thread_context(thread) -> context
1236
- *
1237
- * Returns context of the thread passed as an argument.
1238
- */
1239
- static VALUE
1240
- debug_thread_context(VALUE self, VALUE thread)
1241
- {
1242
- VALUE context;
1243
-
1244
- debug_check_started();
1245
- thread_context_lookup(thread, &context, NULL);
1246
- return context;
1247
- }
1248
-
1249
- /*
1250
- * call-seq:
1251
- * Debugger.contexts -> array
1252
- *
1253
- * Returns an array of all contexts.
1254
- */
1255
- static VALUE
1256
- debug_contexts(VALUE self)
1257
- {
1258
- volatile VALUE list;
1259
- volatile VALUE new_list;
1260
- VALUE thread, context;
1261
- threads_table_t *threads_table;
1262
- debug_context_t *debug_context;
1263
- int i;
1264
-
1265
- debug_check_started();
1266
-
1267
- new_list = rb_ary_new();
1268
- list = rb_funcall(rb_cThread, idList, 0);
1269
- for(i = 0; i < RARRAY(list)->len; i++)
1270
- {
1271
- thread = rb_ary_entry(list, i);
1272
- thread_context_lookup(thread, &context, NULL);
1273
- rb_ary_push(new_list, context);
1274
- }
1275
- threads_table_clear(threads_tbl);
1276
- Data_Get_Struct(threads_tbl, threads_table_t, threads_table);
1277
- for(i = 0; i < RARRAY(new_list)->len; i++)
1278
- {
1279
- context = rb_ary_entry(new_list, i);
1280
- Data_Get_Struct(context, debug_context_t, debug_context);
1281
- st_insert(threads_table->tbl, debug_context->thread_id, context);
1282
- }
1283
-
1284
- return new_list;
1285
- }
1286
-
1287
- /*
1288
- * call-seq:
1289
- * Debugger.suspend -> Debugger
1290
- *
1291
- * Suspends all contexts.
1292
- */
1293
- static VALUE
1294
- debug_suspend(VALUE self)
1295
- {
1296
- VALUE current, context;
1297
- VALUE saved_crit;
1298
- VALUE context_list;
1299
- debug_context_t *debug_context;
1300
- int i;
1301
-
1302
- debug_check_started();
1303
-
1304
- saved_crit = rb_thread_critical;
1305
- rb_thread_critical = Qtrue;
1306
- context_list = debug_contexts(self);
1307
- thread_context_lookup(rb_thread_current(), &current, NULL);
1308
-
1309
- for(i = 0; i < RARRAY(context_list)->len; i++)
1310
- {
1311
- context = rb_ary_entry(context_list, i);
1312
- if(current == context)
1313
- continue;
1314
- Data_Get_Struct(context, debug_context_t, debug_context);
1315
- context_suspend_0(debug_context);
1316
- }
1317
- rb_thread_critical = saved_crit;
1318
-
1319
- if(rb_thread_critical == Qfalse)
1320
- rb_thread_schedule();
1321
-
1322
- return self;
1323
- }
1324
-
1325
- /*
1326
- * call-seq:
1327
- * Debugger.resume -> Debugger
1328
- *
1329
- * Resumes all contexts.
1330
- */
1331
- static VALUE
1332
- debug_resume(VALUE self)
1333
- {
1334
- VALUE current, context;
1335
- VALUE saved_crit;
1336
- VALUE context_list;
1337
- debug_context_t *debug_context;
1338
- int i;
1339
-
1340
- debug_check_started();
1341
-
1342
- saved_crit = rb_thread_critical;
1343
- rb_thread_critical = Qtrue;
1344
- context_list = debug_contexts(self);
1345
-
1346
- thread_context_lookup(rb_thread_current(), &current, NULL);
1347
- for(i = 0; i < RARRAY(context_list)->len; i++)
1348
- {
1349
- context = rb_ary_entry(context_list, i);
1350
- if(current == context)
1351
- continue;
1352
- Data_Get_Struct(context, debug_context_t, debug_context);
1353
- context_resume_0(debug_context);
1354
- }
1355
- rb_thread_critical = saved_crit;
1356
-
1357
- rb_thread_schedule();
1358
-
1359
- return self;
1360
- }
1361
-
1362
- /*
1363
- * call-seq:
1364
- * Debugger.tracing -> bool
1365
- *
1366
- * Returns +true+ if the global tracing is activated.
1367
- */
1368
- static VALUE
1369
- debug_tracing(VALUE self)
1370
- {
1371
- return tracing;
1372
- }
1373
-
1374
- /*
1375
- * call-seq:
1376
- * Debugger.tracing = bool
1377
- *
1378
- * Sets the global tracing flag.
1379
- */
1380
- static VALUE
1381
- debug_set_tracing(VALUE self, VALUE value)
1382
- {
1383
- tracing = RTEST(value) ? Qtrue : Qfalse;
1384
- return value;
1385
- }
1386
-
1387
- /*
1388
- * call-seq:
1389
- * Debugger.post_mortem? -> bool
1390
- *
1391
- * Returns +true+ if post-moterm debugging is enabled.
1392
- */
1393
- static VALUE
1394
- debug_post_mortem(VALUE self)
1395
- {
1396
- return post_mortem;
1397
- }
1398
-
1399
- /*
1400
- * call-seq:
1401
- * Debugger.post_mortem = bool
1402
- *
1403
- * Sets post-moterm flag.
1404
- * FOR INTERNAL USE ONLY.
1405
- */
1406
- static VALUE
1407
- debug_set_post_mortem(VALUE self, VALUE value)
1408
- {
1409
- debug_check_started();
1410
-
1411
- post_mortem = RTEST(value) ? Qtrue : Qfalse;
1412
- return value;
1413
- }
1414
-
1415
- /*
1416
- * call-seq:
1417
- * Debugger.keep_frame_binding? -> bool
1418
- *
1419
- * Returns +true+ if the debugger will collect frame bindings.
1420
- */
1421
- static VALUE
1422
- debug_keep_frame_binding(VALUE self)
1423
- {
1424
- return keep_frame_binding;
1425
- }
1426
-
1427
- /*
1428
- * call-seq:
1429
- * Debugger.keep_frame_binding = bool
1430
- *
1431
- * Setting to +true+ will make the debugger create frame bindings.
1432
- */
1433
- static VALUE
1434
- debug_set_keep_frame_binding(VALUE self, VALUE value)
1435
- {
1436
- keep_frame_binding = RTEST(value) ? Qtrue : Qfalse;
1437
- return value;
1438
- }
1439
-
1440
- static VALUE
1441
- debug_debug(VALUE self)
1442
- {
1443
- return debug;
1444
- }
1445
-
1446
- static VALUE
1447
- debug_set_debug(VALUE self, VALUE value)
1448
- {
1449
- debug = RTEST(value) ? Qtrue : Qfalse;
1450
- return value;
1451
- }
1452
-
1453
- static VALUE
1454
- debug_thread_inherited(VALUE klass)
1455
- {
1456
- rb_raise(rb_eRuntimeError, "Can't inherite Debugger::DebugThread class");
1457
- }
1458
-
1459
- /*
1460
- * call-seq:
1461
- * Debugger.debug_load(file) -> nil
1462
- *
1463
- * Same as Kernel#load but resets current context's frames.
1464
- * FOR INTERNAL USE ONLY. Use Debugger.post_mortem method instead.
1465
- */
1466
- static VALUE
1467
- debug_debug_load(VALUE self, VALUE file)
1468
- {
1469
- VALUE context;
1470
- debug_context_t *debug_context;
1471
-
1472
- debug_start(self);
1473
-
1474
- context = debug_current_context(self);
1475
- Data_Get_Struct(context, debug_context_t, debug_context);
1476
- debug_context->stack_size = 0;
1477
- rb_load(file, 0);
1478
-
1479
- debug_stop(self);
1480
- return Qnil;
1481
- }
1482
-
1483
- static VALUE
1484
- set_current_skipped_status(VALUE status)
1485
- {
1486
- VALUE context;
1487
- debug_context_t *debug_context;
1488
-
1489
- context = debug_current_context(Qnil);
1490
- Data_Get_Struct(context, debug_context_t, debug_context);
1491
- if(status)
1492
- CTX_FL_SET(debug_context, CTX_FL_SKIPPED);
1493
- else
1494
- CTX_FL_UNSET(debug_context, CTX_FL_SKIPPED);
1495
- return Qnil;
1496
- }
1497
-
1498
- /*
1499
- * call-seq:
1500
- * Debugger.skip { block } -> obj or nil
1501
- *
1502
- * The code inside of the block is escaped from the debugger.
1503
- */
1504
- static VALUE
1505
- debug_skip(VALUE self)
1506
- {
1507
- if (!rb_block_given_p()) {
1508
- rb_raise(rb_eArgError, "called without a block");
1509
- }
1510
- if(!IS_STARTED)
1511
- return rb_yield(Qnil);
1512
- set_current_skipped_status(Qtrue);
1513
- return rb_ensure(rb_yield, Qnil, set_current_skipped_status, Qfalse);
1514
- }
1515
-
1516
- static VALUE
1517
- debug_at_exit_c(VALUE proc)
1518
- {
1519
- return rb_funcall(proc, rb_intern("call"), 0);
1520
- }
1521
-
1522
- static void
1523
- debug_at_exit_i(VALUE proc)
1524
- {
1525
- if(!IS_STARTED)
1526
- {
1527
- debug_at_exit_c(proc);
1528
- }
1529
- else
1530
- {
1531
- set_current_skipped_status(Qtrue);
1532
- rb_ensure(debug_at_exit_c, proc, set_current_skipped_status, Qfalse);
1533
- }
1534
- }
1535
-
1536
- /*
1537
- * call-seq:
1538
- * Debugger.debug_at_exit { block } -> proc
1539
- *
1540
- * Register <tt>at_exit</tt> hook which is escaped from the debugger.
1541
- * FOR INTERNAL USE ONLY.
1542
- */
1543
- static VALUE
1544
- debug_at_exit(VALUE self)
1545
- {
1546
- VALUE proc;
1547
- if (!rb_block_given_p()) {
1548
- rb_raise(rb_eArgError, "called without a block");
1549
- }
1550
- proc = rb_block_proc();
1551
- rb_set_end_proc(debug_at_exit_i, proc);
1552
- return proc;
1553
- }
1554
-
1555
- /*
1556
- * call-seq:
1557
- * context.stop_next = steps
1558
- *
1559
- * Stops the current context after a number +steps+ are made.
1560
- */
1561
- static VALUE
1562
- context_stop_next(VALUE self, VALUE steps)
1563
- {
1564
- debug_context_t *debug_context;
1565
-
1566
- debug_check_started();
1567
- Data_Get_Struct(self, debug_context_t, debug_context);
1568
- if(FIX2INT(steps) < 0)
1569
- rb_raise(rb_eRuntimeError, "Steps argument can't be negative.");
1570
- debug_context->stop_next = FIX2INT(steps);
1571
-
1572
- return steps;
1573
- }
1574
-
1575
- /*
1576
- * call-seq:
1577
- * context.step_over(steps)
1578
- *
1579
- * Steps over a +steps+ number of times.
1580
- */
1581
- static VALUE
1582
- context_step_over(int argc, VALUE *argv, VALUE self)
1583
- {
1584
- VALUE lines, frame;
1585
- debug_context_t *debug_context;
1586
-
1587
- debug_check_started();
1588
- Data_Get_Struct(self, debug_context_t, debug_context);
1589
- if(debug_context->stack_size == 0)
1590
- rb_raise(rb_eRuntimeError, "No frames collected.");
1591
-
1592
- rb_scan_args(argc, argv, "11", &lines, &frame);
1593
- debug_context->stop_line = FIX2INT(lines);
1594
- if(argc == 1)
1595
- {
1596
- debug_context->dest_frame = debug_context->stack_size;
1597
- }
1598
- else
1599
- {
1600
- if(FIX2INT(frame) < 0 && FIX2INT(frame) >= debug_context->stack_size)
1601
- rb_raise(rb_eRuntimeError, "Destination frame is out of range.");
1602
- debug_context->dest_frame = debug_context->stack_size - FIX2INT(frame);
1603
- }
1604
-
1605
- return Qnil;
1606
- }
1607
-
1608
- /*
1609
- * call-seq:
1610
- * context.stop_frame(frame)
1611
- *
1612
- * Stops when a frame with number +frame+ is activated. Implements +up+ and +down+ commands.
1613
- */
1614
- static VALUE
1615
- context_stop_frame(VALUE self, VALUE frame)
1616
- {
1617
- debug_context_t *debug_context;
1618
-
1619
- debug_check_started();
1620
- Data_Get_Struct(self, debug_context_t, debug_context);
1621
- if(FIX2INT(frame) < 0 && FIX2INT(frame) >= debug_context->stack_size)
1622
- rb_raise(rb_eRuntimeError, "Stop frame is out of range.");
1623
- debug_context->stop_frame = debug_context->stack_size - FIX2INT(frame);
1624
-
1625
- return frame;
1626
- }
1627
-
1628
- inline static int
1629
- check_frame_number(debug_context_t *debug_context, VALUE frame)
1630
- {
1631
- int frame_n;
1632
-
1633
- frame_n = FIX2INT(frame);
1634
- if(frame_n < 0 || frame_n >= debug_context->stack_size)
1635
- rb_raise(rb_eArgError, "Invalid frame number %d, stack (0...%d)",
1636
- frame_n, debug_context->stack_size);
1637
- return frame_n;
1638
- }
1639
-
1640
- /*
1641
- * call-seq:
1642
- * context.frame_binding(frame) -> binding
1643
- *
1644
- * Returns frame's binding.
1645
- */
1646
- static VALUE
1647
- context_frame_binding(VALUE self, VALUE frame)
1648
- {
1649
- debug_context_t *debug_context;
1650
-
1651
- debug_check_started();
1652
- Data_Get_Struct(self, debug_context_t, debug_context);
1653
- return GET_FRAME->binding;
1654
- }
1655
-
1656
- /*
1657
- * call-seq:
1658
- * context.frame_id(frame) -> sym
1659
- *
1660
- * Returns the sym of the called method.
1661
- */
1662
- static VALUE
1663
- context_frame_id(VALUE self, VALUE frame)
1664
- {
1665
-
1666
- debug_context_t *debug_context;
1667
- ID id;
1668
-
1669
- debug_check_started();
1670
- Data_Get_Struct(self, debug_context_t, debug_context);
1671
-
1672
- id = GET_FRAME->id;
1673
- return id ? ID2SYM(id): Qnil;
1674
- }
1675
-
1676
- /*
1677
- * call-seq:
1678
- * context.frame_line(frame) -> int
1679
- *
1680
- * Returns the line number in the file.
1681
- */
1682
- static VALUE
1683
- context_frame_line(VALUE self, VALUE frame)
1684
- {
1685
- debug_context_t *debug_context;
1686
-
1687
- debug_check_started();
1688
- Data_Get_Struct(self, debug_context_t, debug_context);
1689
-
1690
- return INT2FIX(GET_FRAME->line);
1691
- }
1692
-
1693
- /*
1694
- * call-seq:
1695
- * context.frame_file(frame) -> string
1696
- *
1697
- * Returns the name of the file.
1698
- */
1699
- static VALUE
1700
- context_frame_file(VALUE self, VALUE frame)
1701
- {
1702
- debug_context_t *debug_context;
1703
-
1704
- debug_check_started();
1705
- Data_Get_Struct(self, debug_context_t, debug_context);
1706
-
1707
- return rb_str_new2(GET_FRAME->file);
1708
- }
1709
-
1710
- static VALUE
1711
- context_copy_locals(debug_frame_t *debug_frame)
1712
- {
1713
- ID *tbl;
1714
- int n, i;
1715
- struct SCOPE *scope;
1716
- struct RVarmap *vars;
1717
- VALUE hash = rb_hash_new();
1718
-
1719
- scope = debug_frame->info.runtime.scope;
1720
- tbl = scope->local_tbl;
1721
-
1722
- if (tbl && scope->local_vars)
1723
- {
1724
- n = *tbl++;
1725
- for (i=2; i<n; i++)
1726
- { /* skip first 2 ($_ and $~) */
1727
- if (!rb_is_local_id(tbl[i])) continue; /* skip flip states */
1728
- rb_hash_aset(hash, rb_str_new2(rb_id2name(tbl[i])), scope->local_vars[i]);
1729
- }
1730
- }
1731
-
1732
- vars = debug_frame->info.runtime.dyna_vars;
1733
- while (vars)
1734
- {
1735
- if (vars->id && rb_is_local_id(vars->id))
1736
- { /* skip $_, $~ and flip states */
1737
- rb_hash_aset(hash, rb_str_new2(rb_id2name(vars->id)), vars->val);
1738
- }
1739
- vars = vars->next;
1740
- }
1741
- return hash;
1742
- }
1743
-
1744
- /*
1745
- * call-seq:
1746
- * context.frame_locals(frame) -> hash
1747
- *
1748
- * Returns frame's local variables.
1749
- */
1750
- static VALUE
1751
- context_frame_locals(VALUE self, VALUE frame)
1752
- {
1753
- debug_context_t *debug_context;
1754
- debug_frame_t *debug_frame;
1755
-
1756
- debug_check_started();
1757
- Data_Get_Struct(self, debug_context_t, debug_context);
1758
-
1759
- debug_frame = GET_FRAME;
1760
- if(debug_frame->dead)
1761
- return debug_frame->info.copy.locals;
1762
- else
1763
- return context_copy_locals(debug_frame);
1764
- }
1765
-
1766
- /*
1767
- * call-seq:
1768
- * context.frame_self(frame) -> obj
1769
- *
1770
- * Returns self object of the frame.
1771
- */
1772
- static VALUE
1773
- context_frame_self(VALUE self, VALUE frame)
1774
- {
1775
- debug_context_t *debug_context;
1776
- debug_frame_t *debug_frame;
1777
-
1778
- debug_check_started();
1779
- Data_Get_Struct(self, debug_context_t, debug_context);
1780
-
1781
- debug_frame = GET_FRAME;
1782
- return debug_frame->self;
1783
- }
1784
-
1785
- /*
1786
- * call-seq:
1787
- * context.stack_size-> int
1788
- *
1789
- * Returns the size of the context stack.
1790
- */
1791
- static VALUE
1792
- context_stack_size(VALUE self)
1793
- {
1794
- debug_context_t *debug_context;
1795
-
1796
- debug_check_started();
1797
- Data_Get_Struct(self, debug_context_t, debug_context);
1798
-
1799
- return INT2FIX(debug_context->stack_size);
1800
- }
1801
-
1802
- /*
1803
- * call-seq:
1804
- * context.thread -> trhread
1805
- *
1806
- * Returns a thread this context is associated with.
1807
- */
1808
- static VALUE
1809
- context_thread(VALUE self)
1810
- {
1811
- debug_context_t *debug_context;
1812
-
1813
- debug_check_started();
1814
- Data_Get_Struct(self, debug_context_t, debug_context);
1815
- return context_thread_0(debug_context);
1816
- }
1817
-
1818
- /*
1819
- * call-seq:
1820
- * context.thnum -> int
1821
- *
1822
- * Returns the context's number.
1823
- */
1824
- static VALUE
1825
- context_thnum(VALUE self)
1826
- {
1827
- debug_context_t *debug_context;
1828
-
1829
- Data_Get_Struct(self, debug_context_t, debug_context);
1830
- return INT2FIX(debug_context->thnum);
1831
- }
1832
-
1833
- static void
1834
- context_suspend_0(debug_context_t *debug_context)
1835
- {
1836
- VALUE status;
1837
-
1838
- status = rb_funcall(context_thread_0(debug_context), rb_intern("status"), 0);
1839
- if(rb_str_cmp(status, rb_str_new2("run")) == 0)
1840
- CTX_FL_SET(debug_context, CTX_FL_WAS_RUNNING);
1841
- else if(rb_str_cmp(status, rb_str_new2("sleep")) == 0)
1842
- CTX_FL_UNSET(debug_context, CTX_FL_WAS_RUNNING);
1843
- else
1844
- return;
1845
- CTX_FL_SET(debug_context, CTX_FL_SUSPEND);
1846
- }
1847
-
1848
- static void
1849
- context_resume_0(debug_context_t *debug_context)
1850
- {
1851
- if(!CTX_FL_TEST(debug_context, CTX_FL_SUSPEND))
1852
- return;
1853
- CTX_FL_UNSET(debug_context, CTX_FL_SUSPEND);
1854
- if(CTX_FL_TEST(debug_context, CTX_FL_WAS_RUNNING))
1855
- rb_thread_wakeup(context_thread_0(debug_context));
1856
- }
1857
-
1858
- /*
1859
- * call-seq:
1860
- * context.suspend -> nil
1861
- *
1862
- * Suspends the thread when it is running.
1863
- */
1864
- static VALUE
1865
- context_suspend(VALUE self)
1866
- {
1867
- debug_context_t *debug_context;
1868
-
1869
- debug_check_started();
1870
-
1871
- Data_Get_Struct(self, debug_context_t, debug_context);
1872
- if(CTX_FL_TEST(debug_context, CTX_FL_SUSPEND))
1873
- rb_raise(rb_eRuntimeError, "Already suspended.");
1874
- context_suspend_0(debug_context);
1875
- return Qnil;
1876
- }
1877
-
1878
- /*
1879
- * call-seq:
1880
- * context.suspended? -> bool
1881
- *
1882
- * Returns +true+ if the thread is suspended by debugger.
1883
- */
1884
- static VALUE
1885
- context_is_suspended(VALUE self)
1886
- {
1887
- debug_context_t *debug_context;
1888
-
1889
- debug_check_started();
1890
-
1891
- Data_Get_Struct(self, debug_context_t, debug_context);
1892
- return CTX_FL_TEST(debug_context, CTX_FL_SUSPEND) ? Qtrue : Qfalse;
1893
- }
1894
-
1895
- /*
1896
- * call-seq:
1897
- * context.resume -> nil
1898
- *
1899
- * Resumes the thread from the suspended mode.
1900
- */
1901
- static VALUE
1902
- context_resume(VALUE self)
1903
- {
1904
- debug_context_t *debug_context;
1905
-
1906
- debug_check_started();
1907
-
1908
- Data_Get_Struct(self, debug_context_t, debug_context);
1909
- if(!CTX_FL_TEST(debug_context, CTX_FL_SUSPEND))
1910
- rb_raise(rb_eRuntimeError, "Thread is not suspended.");
1911
- context_resume_0(debug_context);
1912
- return Qnil;
1913
- }
1914
-
1915
- /*
1916
- * call-seq:
1917
- * context.tracing -> bool
1918
- *
1919
- * Returns the tracing flag for the current context.
1920
- */
1921
- static VALUE
1922
- context_tracing(VALUE self)
1923
- {
1924
- debug_context_t *debug_context;
1925
-
1926
- debug_check_started();
1927
-
1928
- Data_Get_Struct(self, debug_context_t, debug_context);
1929
- return CTX_FL_TEST(debug_context, CTX_FL_TRACING) ? Qtrue : Qfalse;
1930
- }
1931
-
1932
- /*
1933
- * call-seq:
1934
- * context.tracking = bool
1935
- *
1936
- * Controls the tracing for this context.
1937
- */
1938
- static VALUE
1939
- context_set_tracing(VALUE self, VALUE value)
1940
- {
1941
- debug_context_t *debug_context;
1942
-
1943
- debug_check_started();
1944
-
1945
- Data_Get_Struct(self, debug_context_t, debug_context);
1946
- if(RTEST(value))
1947
- CTX_FL_SET(debug_context, CTX_FL_TRACING);
1948
- else
1949
- CTX_FL_UNSET(debug_context, CTX_FL_TRACING);
1950
- return value;
1951
- }
1952
-
1953
- /*
1954
- * call-seq:
1955
- * context.ignored? -> bool
1956
- *
1957
- * Returns the ignore flag for the current context.
1958
- */
1959
- static VALUE
1960
- context_ignored(VALUE self)
1961
- {
1962
- debug_context_t *debug_context;
1963
-
1964
- debug_check_started();
1965
-
1966
- Data_Get_Struct(self, debug_context_t, debug_context);
1967
- return CTX_FL_TEST(debug_context, CTX_FL_IGNORE) ? Qtrue : Qfalse;
1968
- }
1969
-
1970
- /*
1971
- * call-seq:
1972
- * context.dead? = bool
1973
- *
1974
- * Returns +true+ if context doesn't represent a live context and is created
1975
- * during post-mortem exception handling.
1976
- */
1977
- static VALUE
1978
- context_dead(VALUE self)
1979
- {
1980
- debug_context_t *debug_context;
1981
-
1982
- debug_check_started();
1983
-
1984
- Data_Get_Struct(self, debug_context_t, debug_context);
1985
- return CTX_FL_TEST(debug_context, CTX_FL_DEAD) ? Qtrue : Qfalse;
1986
- }
1987
-
1988
- /*
1989
- * call-seq:
1990
- * breakpoint.source -> string
1991
- *
1992
- * Returns a source of the breakpoint.
1993
- */
1994
- static VALUE
1995
- breakpoint_source(VALUE self)
1996
- {
1997
- debug_breakpoint_t *breakpoint;
1998
-
1999
- Data_Get_Struct(self, debug_breakpoint_t, breakpoint);
2000
- return breakpoint->source;
2001
- }
2002
-
2003
- /*
2004
- * call-seq:
2005
- * breakpoint.pos -> string or int
2006
- *
2007
- * Returns a position of this breakpoint.
2008
- */
2009
- static VALUE
2010
- breakpoint_pos(VALUE self)
2011
- {
2012
- debug_breakpoint_t *breakpoint;
2013
-
2014
- Data_Get_Struct(self, debug_breakpoint_t, breakpoint);
2015
- if(breakpoint->type == BP_METHOD_TYPE)
2016
- return rb_str_new2(rb_id2name(breakpoint->pos.mid));
2017
- else
2018
- return INT2FIX(breakpoint->pos.line);
2019
- }
2020
-
2021
- /*
2022
- * call-seq:
2023
- * breakpoint.expr -> string
2024
- *
2025
- * Returns a codition expression when this breakpoint should be activated.
2026
- */
2027
- static VALUE
2028
- breakpoint_expr(VALUE self)
2029
- {
2030
- debug_breakpoint_t *breakpoint;
2031
-
2032
- Data_Get_Struct(self, debug_breakpoint_t, breakpoint);
2033
- return breakpoint->expr;
2034
- }
2035
-
2036
- /*
2037
- * call-seq:
2038
- * breakpoint.id -> int
2039
- *
2040
- * Returns id of the breakpoint.
2041
- */
2042
- static VALUE
2043
- breakpoint_id(VALUE self)
2044
- {
2045
- debug_breakpoint_t *breakpoint;
2046
-
2047
- Data_Get_Struct(self, debug_breakpoint_t, breakpoint);
2048
- return INT2FIX(breakpoint->id);
2049
- }
2050
-
2051
- /*
2052
- * Document-class: Context
2053
- *
2054
- * == Summary
2055
- *
2056
- * Debugger keeps a single instance of this class for each Ruby thread.
2057
- */
2058
- static void
2059
- Init_context()
2060
- {
2061
- cContext = rb_define_class_under(mDebugger, "Context", rb_cObject);
2062
- rb_define_method(cContext, "stop_next=", context_stop_next, 1);
2063
- rb_define_method(cContext, "step_over", context_step_over, -1);
2064
- rb_define_method(cContext, "stop_frame=", context_stop_frame, 1);
2065
- rb_define_method(cContext, "thread", context_thread, 0);
2066
- rb_define_method(cContext, "thnum", context_thnum, 0);
2067
- rb_define_method(cContext, "suspend", context_suspend, 0);
2068
- rb_define_method(cContext, "suspended?", context_is_suspended, 0);
2069
- rb_define_method(cContext, "resume", context_resume, 0);
2070
- rb_define_method(cContext, "tracing", context_tracing, 0);
2071
- rb_define_method(cContext, "tracing=", context_set_tracing, 1);
2072
- rb_define_method(cContext, "ignored?", context_ignored, 0);
2073
- rb_define_method(cContext, "frame_binding", context_frame_binding, 1);
2074
- rb_define_method(cContext, "frame_id", context_frame_id, 1);
2075
- rb_define_method(cContext, "frame_line", context_frame_line, 1);
2076
- rb_define_method(cContext, "frame_file", context_frame_file, 1);
2077
- rb_define_method(cContext, "frame_locals", context_frame_locals, 1);
2078
- rb_define_method(cContext, "frame_self", context_frame_self, 1);
2079
- rb_define_method(cContext, "stack_size", context_stack_size, 0);
2080
- rb_define_method(cContext, "dead?", context_dead, 0);
2081
- }
2082
-
2083
- /*
2084
- * Document-class: Breakpoint
2085
- *
2086
- * == Summary
2087
- *
2088
- * This class represents a breakpoint. It defines position of the breakpoint and
2089
- * condition when this breakpoint should be triggered.
2090
- */
2091
- static void
2092
- Init_breakpoint()
2093
- {
2094
- cBreakpoint = rb_define_class_under(mDebugger, "Breakpoint", rb_cObject);
2095
- rb_define_method(cBreakpoint, "source", breakpoint_source, 0);
2096
- rb_define_method(cBreakpoint, "pos", breakpoint_pos, 0);
2097
- rb_define_method(cBreakpoint, "expr", breakpoint_expr, 0);
2098
- rb_define_method(cBreakpoint, "id", breakpoint_id, 0);
2099
- }
2100
-
2101
-
2102
- /*
2103
- * Document-class: Debugger
2104
- *
2105
- * == Summary
2106
- *
2107
- * This is a singleton class allows controlling the debugger. Use it to start/stop debugger,
2108
- * set/remove breakpoints, etc.
2109
- */
2110
- #if defined(_WIN32)
2111
- __declspec(dllexport)
2112
- #endif
2113
- void
2114
- Init_ruby_debug()
2115
- {
2116
- mDebugger = rb_define_module("Debugger");
2117
- rb_define_const(mDebugger, "VERSION", rb_str_new2(DEBUG_VERSION));
2118
- rb_define_module_function(mDebugger, "start", debug_start, 0);
2119
- rb_define_module_function(mDebugger, "stop", debug_stop, 0);
2120
- rb_define_module_function(mDebugger, "started?", debug_is_started, 0);
2121
- rb_define_module_function(mDebugger, "breakpoints", debug_breakpoints, 0);
2122
- rb_define_module_function(mDebugger, "add_breakpoint", debug_add_breakpoint, -1);
2123
- rb_define_module_function(mDebugger, "remove_breakpoint", debug_remove_breakpoint, 1);
2124
- rb_define_module_function(mDebugger, "catchpoint", debug_catchpoint, 0);
2125
- rb_define_module_function(mDebugger, "catchpoint=", debug_set_catchpoint, 1);
2126
- rb_define_module_function(mDebugger, "last_context", debug_last_interrupted, 0);
2127
- rb_define_module_function(mDebugger, "contexts", debug_contexts, 0);
2128
- rb_define_module_function(mDebugger, "current_context", debug_current_context, 0);
2129
- rb_define_module_function(mDebugger, "thread_context", debug_thread_context, 1);
2130
- rb_define_module_function(mDebugger, "suspend", debug_suspend, 0);
2131
- rb_define_module_function(mDebugger, "resume", debug_resume, 0);
2132
- rb_define_module_function(mDebugger, "tracing", debug_tracing, 0);
2133
- rb_define_module_function(mDebugger, "tracing=", debug_set_tracing, 1);
2134
- rb_define_module_function(mDebugger, "debug_load", debug_debug_load, 1);
2135
- rb_define_module_function(mDebugger, "skip", debug_skip, 0);
2136
- rb_define_module_function(mDebugger, "debug_at_exit", debug_at_exit, 0);
2137
- rb_define_module_function(mDebugger, "post_mortem?", debug_post_mortem, 0);
2138
- rb_define_module_function(mDebugger, "post_mortem=", debug_set_post_mortem, 1);
2139
- rb_define_module_function(mDebugger, "keep_frame_binding?", debug_keep_frame_binding, 0);
2140
- rb_define_module_function(mDebugger, "keep_frame_binding=", debug_set_keep_frame_binding, 1);
2141
- rb_define_module_function(mDebugger, "debug", debug_debug, 0);
2142
- rb_define_module_function(mDebugger, "debug=", debug_set_debug, 1);
2143
-
2144
- cThreadsTable = rb_define_class_under(mDebugger, "ThreadsTable", rb_cObject);
2145
-
2146
- cDebugThread = rb_define_class_under(mDebugger, "DebugThread", rb_cThread);
2147
- rb_define_singleton_method(cDebugThread, "inherited", debug_thread_inherited, 1);
2148
-
2149
- Init_context();
2150
- Init_breakpoint();
2151
-
2152
- idAtLine = rb_intern("at_line");
2153
- idAtBreakpoint = rb_intern("at_breakpoint");
2154
- idAtCatchpoint = rb_intern("at_catchpoint");
2155
- idAtTracing = rb_intern("at_tracing");
2156
- idEval = rb_intern("eval");
2157
- idList = rb_intern("list");
2158
-
2159
- rb_mObjectSpace = rb_const_get(rb_mKernel, rb_intern("ObjectSpace"));
2160
-
2161
- rb_global_variable(&threads_tbl);
2162
- rb_global_variable(&breakpoints);
2163
- rb_global_variable(&catchpoint);
2164
- rb_global_variable(&locker);
2165
- rb_global_variable(&last_context);
2166
- rb_global_variable(&last_thread);
2167
- }