ruby-debug 0.7.5 → 0.8

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/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
- }