ruby-debug 0.6.1-mswin32 → 0.6.2-mswin32

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