comparison src/debug.cc @ 7082:ac7179f00422

[project @ 2007-10-31 01:24:12 by jwe]
author jwe
date Wed, 31 Oct 2007 01:24:12 +0000
parents a1dbe9d80eee
children 24fde8abfb90
comparison
equal deleted inserted replaced
7081:503001863427 7082:ac7179f00422
17 You should have received a copy of the GNU General Public License 17 You should have received a copy of the GNU General Public License
18 along with Octave; see the file COPYING. If not, see 18 along with Octave; see the file COPYING. If not, see
19 <http://www.gnu.org/licenses/>. 19 <http://www.gnu.org/licenses/>.
20 20
21 */ 21 */
22
23 #ifdef HAVE_CONFIG_H 22 #ifdef HAVE_CONFIG_H
24 #include <config.h> 23 #include <config.h>
25 #endif 24 #endif
26 25
27 #include <iostream> 26 #include <iostream>
28 #include <fstream> 27 #include <fstream>
29 #include <string> 28 #include <string>
29 #include <set>
30
30 31
31 #include "defun.h" 32 #include "defun.h"
32 #include "error.h" 33 #include "error.h"
34 #include "help.h"
33 #include "input.h" 35 #include "input.h"
34 #include "pager.h" 36 #include "pager.h"
35 #include "oct-obj.h" 37 #include "oct-obj.h"
36 #include "utils.h" 38 #include "utils.h"
37 #include "parse.h" 39 #include "parse.h"
38 #include "symtab.h" 40 #include "symtab.h"
39 #include "gripes.h" 41 #include "gripes.h"
40 #include "ov.h" 42 #include "ov.h"
41 #include "ov-usr-fcn.h" 43 #include "ov-usr-fcn.h"
42 #include "ov-fcn.h" 44 #include "ov-fcn.h"
45 #include "ov-list.h"
46 #include "ov-struct.h"
43 #include "pt-pr-code.h" 47 #include "pt-pr-code.h"
44 #include "pt.h" 48 #include "pt.h"
45 #include "pt-bp.h" 49 #include "pt-bp.h"
46 #include "pt-stmt.h" 50 #include "pt-stmt.h"
47 #include "toplev.h" 51 #include "toplev.h"
48 #include "unwind-prot.h" 52 #include "unwind-prot.h"
49 #include "variables.h" 53 #include "variables.h"
50 54
55 #include "debug.h"
56
57 // Initialize the singleton object
58 bp_table *bp_table::instance = NULL;
59
51 // Return a pointer to the user-defined function FNAME. If FNAME is 60 // Return a pointer to the user-defined function FNAME. If FNAME is
52 // empty, search backward for the first user-defined function in the 61 // empty, search backward for the first user-defined function in the
53 // current call stack. 62 // current call stack.
54
55 static octave_user_function * 63 static octave_user_function *
56 get_user_function (std::string fname = "") 64 get_user_function (const std::string& fname = "")
57 { 65 {
58 octave_user_function *dbg_fcn = 0; 66 octave_user_function *dbg_fcn = 0;
59 67
60 if (fname == "") 68 if (fname == "")
61 dbg_fcn = octave_call_stack::caller_user_function (); 69 dbg_fcn = octave_call_stack::caller_user_function ();
69 dbg_fcn = dynamic_cast<octave_user_function *> (tmp.function_value ()); 77 dbg_fcn = dynamic_cast<octave_user_function *> (tmp.function_value ());
70 } 78 }
71 else 79 else
72 { 80 {
73 ptr = lookup_by_name (fname, false); 81 ptr = lookup_by_name (fname, false);
74
75 if (ptr && ptr->is_user_function ()) 82 if (ptr && ptr->is_user_function ())
76 { 83 {
77 octave_value tmp = ptr->def (); 84 octave_value tmp = ptr->def ();
78 dbg_fcn = dynamic_cast<octave_user_function *> (tmp.function_value ()); 85 dbg_fcn = dynamic_cast<octave_user_function *> (tmp.function_value ());
79 } 86 }
81 } 88 }
82 89
83 return dbg_fcn; 90 return dbg_fcn;
84 } 91 }
85 92
93 static void
94 parse_dbfunction_params (const octave_value_list& args,
95 std::string& symbol_name,
96 intmap& lines)
97 {
98 octave_idx_type len = 0;
99 int nargin = args.length ();
100 int idx = 0;
101 int list_idx = 0;
102 symbol_name = std::string ();
103
104 // If we are already in a debugging function
105 if (octave_call_stack::caller_user_function () != NULL)
106 {
107 idx = 0;
108 }
109 else
110 {
111 symbol_name = args (0).string_value ();
112 if (error_state)
113 return;
114 idx = 1;
115 }
116
117 for (int i = idx; i < nargin; i++ )
118 {
119 if (args (i).is_string ())
120 len += 1;
121 else
122 len += args (i).numel ();
123 }
124
125 lines = intmap();
126 for (int i = idx; i < nargin; i++ )
127 {
128 if (args (i).is_string ())
129 {
130 int line = atoi (args (i).string_value ().c_str ());
131 if (error_state)
132 break;
133 lines[list_idx++] = line;
134 }
135 else
136 {
137 const NDArray arg = args (i).array_value ();
138
139 if (error_state)
140 break;
141
142 for (octave_idx_type j = 0; j < arg.nelem(); j++)
143 {
144 int line = static_cast<int> (arg.elem (j));
145 if (error_state)
146 break;
147 lines[list_idx++] = line;
148 }
149
150 if (error_state)
151 break;
152 }
153 }
154 }
155
156 intmap
157 bp_table::add_breakpoint (const std::string& fname,
158 const intmap& line)
159 {
160 if (!instance_ok ())
161 return intmap();
162
163 octave_idx_type len = line.size ();
164 intmap retval;
165 octave_user_function *dbg_fcn = get_user_function (fname);
166
167 if (dbg_fcn)
168 {
169 tree_statement_list *cmds = dbg_fcn->body ();
170 for (int i = 0; i < len; i++)
171 {
172 intmap::const_iterator p = line.find (i);
173 if (p != line.end ())
174 {
175 int lineno = p->second;
176 retval[i] = cmds->set_breakpoint (lineno);
177 if (retval[i] != 0)
178 instance->bp_map[fname] = dbg_fcn;
179 }
180 }
181 }
182 else
183 error ("add_breakpoint: unable to find the function requested\n");
184
185 return retval;
186 }
187
188
189 int
190 bp_table::remove_breakpoint (const std::string& fname,
191 const intmap& line)
192 {
193 if (!instance_ok ())
194 return 0;
195
196 octave_idx_type len = line.size ();
197 int retval = 0;
198
199 if (len == 0)
200 {
201 intmap results = remove_all_breakpoints_in_file (fname);
202 retval = results.size ();
203 }
204 else
205 {
206 octave_user_function *dbg_fcn = get_user_function (fname);
207 if (dbg_fcn)
208 {
209 tree_statement_list *cmds = dbg_fcn->body ();
210 for (int i = 0; i < len; i++)
211 {
212 intmap::const_iterator p = line.find (i);
213 if (p != line.end ())
214 {
215 int lineno = p->second;
216 cmds->delete_breakpoint (lineno);
217 }
218 }
219 octave_value_list results = cmds->list_breakpoints ();
220 if (results.length () == 0)
221 instance->bp_map.erase (instance->bp_map.find (fname));
222 retval = results.length ();
223 }
224 else
225 error ("remove_breakpoint: unable to find the function requested\n");
226 }
227 return retval;
228 }
229
230
231 intmap
232 bp_table::remove_all_breakpoints_in_file (const std::string& fname)
233 {
234 if (!instance_ok ())
235 return intmap();
236
237 octave_value_list bkpts;
238 intmap retval;
239 octave_user_function *dbg_fcn = get_user_function (fname);
240
241 if (dbg_fcn)
242 {
243 tree_statement_list *cmds = dbg_fcn->body ();
244 bkpts = cmds->list_breakpoints ();
245 for (int i = 0; i < bkpts.length (); i++)
246 {
247 int lineno = static_cast<int> (bkpts (i).int_value ());
248 cmds->delete_breakpoint (lineno);
249 retval[i] = lineno;
250 }
251 instance->bp_map.erase (instance->bp_map.find (fname));
252 }
253 else
254 error ("remove_all_breakpoint_in_file: "
255 "unable to find the function requested\n");
256
257 return retval;
258 }
259
260
261 void
262 bp_table::remove_all_breakpoints (void)
263 {
264 if (!instance_ok ())
265 return;
266
267 std::map< std::string, octave_user_function* >::iterator it;
268 for (it = instance->bp_map.begin (); it != instance->bp_map.end (); it++)
269 {
270 remove_all_breakpoints_in_file (it->first);
271 }
272 }
273
274 std::string
275 do_find_bkpt_list (octave_value_list slist,
276 std::string match)
277 {
278 std::string retval;
279 for (int i = 0; i < slist.length (); i++)
280 {
281 if (slist (i).string_value () == match)
282 {
283 retval = slist (i).string_value ();
284 break;
285 }
286 }
287 return retval;
288 }
289
290
291 std::map< std::string, intmap>
292 bp_table::get_breakpoint_list (const octave_value_list& fname_list)
293 {
294 std::map<std::string, intmap> retval;
295
296 if (!instance_ok ())
297 return retval;
298
299 // Iterate through each of the files in the map and get the
300 // name and list of breakpoints
301 std::map< std::string, octave_user_function* >::iterator it;
302 for (it = instance->bp_map.begin (); it != instance->bp_map.end (); it++)
303 {
304 if (fname_list.length () == 0 ||
305 do_find_bkpt_list (fname_list, it->first) != "")
306 {
307 octave_value_list bkpts = it->second->body ()->list_breakpoints ();
308 octave_idx_type len = bkpts.length ();
309 intmap bkpts_vec;
310 for (int i = 0; i < len; i++)
311 bkpts_vec[i] = bkpts (i).double_value ();
312 retval[ it->first ] = bkpts_vec;
313 }
314 }
315 return retval;
316 }
317
318 static octave_value
319 intmap_to_ov (const intmap& line)
320 {
321 int idx = 0;
322 NDArray retval (dim_vector (1, line.size()));
323 for (int i = 0; i < line.size(); i++ )
324 {
325 intmap::const_iterator p = line.find (i);
326 if (p != line.end ())
327 {
328 int lineno = p->second;
329 retval (idx++) = lineno;
330 }
331 }
332 retval.resize (dim_vector (1, idx));
333 return retval;
334 }
86 335
87 DEFCMD (dbstop, args, , 336 DEFCMD (dbstop, args, ,
88 "-*- texinfo -*-\n\ 337 "-*- texinfo -*-\n\
89 @deftypefn {Loadable Function} {rline =} dbstop (func, line, @dots{})\n\ 338 @deftypefn {Loadable Function} {rline =} dbstop (func, line, @dots{})\n\
90 Set a breakpoint in a function\n\ 339 Set a breakpoint in a function\n\
99 \n\ 348 \n\
100 The rline returned is the real line that the breakpoint was set at.\n\ 349 The rline returned is the real line that the breakpoint was set at.\n\
101 @seealso{dbclear, dbstatus, dbnext}\n\ 350 @seealso{dbclear, dbstatus, dbnext}\n\
102 @end deftypefn") 351 @end deftypefn")
103 { 352 {
104 octave_value retval; 353 intmap retval;
105 int nargin = args.length ();
106 int idx = 0;
107 std::string symbol_name = ""; 354 std::string symbol_name = "";
108 355 intmap lines;
109 if (nargin != 1 && args(0).is_string()) 356 parse_dbfunction_params (args, symbol_name, lines);
110 { 357
111 symbol_name = args(0).string_value (); 358 if (!error_state)
112 idx = 1; 359 retval = bp_table::add_breakpoint (symbol_name, lines);
113 } 360
114 361 return intmap_to_ov(retval);
115 octave_user_function *dbg_fcn = get_user_function (symbol_name);
116
117 if (dbg_fcn)
118 {
119 octave_idx_type nsize = 10;
120 RowVector results (nsize);
121 octave_idx_type nr = 0;
122
123 tree_statement_list *cmds = dbg_fcn->body ();
124
125 for (int i = idx; i < nargin; i++)
126 {
127 if (args(i).is_string ())
128 {
129 int line = atoi (args(i).string_value ().c_str ());
130
131 if (error_state)
132 break;
133
134 if (nr == nsize)
135 {
136 nsize *= 2;
137 results.resize (nsize);
138 }
139
140 results(nr++) = cmds->set_breakpoint (line);
141 }
142 else
143 {
144 const NDArray arg = args(i).array_value ();
145
146 if (error_state)
147 break;
148
149 for (octave_idx_type j = 0; j < arg.nelem(); j++)
150 {
151 int line = static_cast<int> (arg.elem (j));
152
153 if (error_state)
154 break;
155
156 if (nr == nsize)
157 {
158 nsize *= 2;
159 results.resize (nsize);
160 }
161
162 results(nr++) = cmds->set_breakpoint (line);
163 }
164
165 if (error_state)
166 break;
167 }
168 }
169
170 if (! error_state)
171 {
172 results.resize (nr);
173 retval = results;
174 }
175 }
176 else
177 error ("dbstop: unable to find the function requested\n");
178
179 return retval;
180 } 362 }
181 363
182 DEFCMD (dbclear, args, , 364 DEFCMD (dbclear, args, ,
183 "-*- texinfo -*-\n\ 365 "-*- texinfo -*-\n\
184 @deftypefn {Loadable Function} {} dbclear (func, line, @dots{})\n\ 366 @deftypefn {Loadable Function} {} dbclear (func, line, @dots{})\n\
195 a breakpoint. If you get the wrong line nothing will happen.\n\ 377 a breakpoint. If you get the wrong line nothing will happen.\n\
196 @seealso{dbstop, dbstatus, dbwhere}\n\ 378 @seealso{dbstop, dbstatus, dbwhere}\n\
197 @end deftypefn") 379 @end deftypefn")
198 { 380 {
199 octave_value retval; 381 octave_value retval;
200 int nargin = args.length ();
201 int idx = 0;
202 std::string symbol_name = ""; 382 std::string symbol_name = "";
203 383 intmap lines;
204 if (nargin != 1 && args(0).is_string()) 384 parse_dbfunction_params (args, symbol_name, lines);
205 { 385
206 symbol_name = args(0).string_value (); 386 if (!error_state)
207 idx = 1; 387 bp_table::remove_breakpoint (symbol_name, lines);
208 } 388
209 389 return retval;
210 octave_user_function *dbg_fcn = get_user_function (symbol_name); 390 }
211 391
212 if (dbg_fcn) 392 DEFCMD (dbstatus, args, nargout,
213 {
214 tree_statement_list *cmds = dbg_fcn->body ();
215
216 for (int i = idx; i < nargin; i++)
217 {
218 if (args(i).is_string ())
219 {
220 int line = atoi (args(i).string_value ().c_str ());
221
222 if (error_state)
223 break;
224
225 cmds->delete_breakpoint (line);
226 }
227 else
228 {
229 const NDArray arg = args(i).array_value ();
230
231 if (error_state)
232 break;
233
234 for (octave_idx_type j = 0; j < arg.nelem (); j++)
235 {
236 int line = static_cast<int> (arg.elem (j));
237
238 if (error_state)
239 break;
240
241 cmds->delete_breakpoint (line);
242 }
243
244 if (error_state)
245 break;
246 }
247 }
248 }
249 else
250 error ("dbclear: unable to find the function requested\n");
251
252 return retval;
253 }
254
255 DEFCMD (dbstatus, args, ,
256 "-*- texinfo -*-\n\ 393 "-*- texinfo -*-\n\
257 @deftypefn {Loadable Function} {lst =} dbstatus ([func])\n\ 394 @deftypefn {Loadable Function} {lst =} dbstatus ([func])\n\
258 Return a vector containing the lines on which a function has \n\ 395 Return a vector containing the lines on which a function has \n\
259 breakpoints set.\n\ 396 breakpoints set.\n\
260 @table @code\n\ 397 @table @code\n\
263 mode this should be left out.\n\ 400 mode this should be left out.\n\
264 @end table\n\ 401 @end table\n\
265 @seealso{dbclear, dbwhere}\n\ 402 @seealso{dbclear, dbwhere}\n\
266 @end deftypefn") 403 @end deftypefn")
267 { 404 {
268 octave_value retval; 405 Octave_map retval;
269
270 int nargin = args.length (); 406 int nargin = args.length ();
407 octave_value_list fcn_list;
408 std::map< std::string, intmap> bp_list;
409 std::string symbol_name = "";
271 410
272 if (nargin != 0 && nargin != 1) 411 if (nargin != 0 && nargin != 1)
273 { 412 {
274 error ("dbstatus: only zero or one arguements accepted\n"); 413 error ("dbstatus: only zero or one arguements accepted\n");
275 return retval; 414 return octave_value ();
276 } 415 }
277
278 std::string symbol_name = "";
279 416
280 if (nargin == 1) 417 if (nargin == 1)
281 { 418 {
282 if (args(0).is_string ()) 419 if (args(0).is_string ())
283 symbol_name = args(0).string_value (); 420 {
421 symbol_name = args (0).string_value ();
422 fcn_list (0) = symbol_name;
423 bp_list = bp_table::get_breakpoint_list (fcn_list);
424 }
284 else 425 else
285 gripe_wrong_type_arg ("dbstatus", args(0)); 426 gripe_wrong_type_arg ("dbstatus", args (0));
286 } 427 }
287 428 else
288 octave_user_function *dbg_fcn = get_user_function (symbol_name); 429 {
289 430 octave_user_function *dbg_fcn = get_user_function ();
290 if (dbg_fcn) 431 if (dbg_fcn)
291 { 432 {
292 tree_statement_list *cmds = dbg_fcn->body (); 433 symbol_name = dbg_fcn->name ();
293 434 fcn_list (0) = symbol_name;
294 octave_value_list lst = cmds->list_breakpoints (); 435 }
295 436 bp_list = bp_table::get_breakpoint_list (fcn_list);
296 RowVector vec (lst.length (), 0.0); 437 }
297 438
298 for (int i = 0; i < lst.length (); i++) 439 std::map< std::string, intmap>::iterator it;
299 { 440 if (nargout == 1)
300 vec(i) = lst(i).double_value (); 441 {
301 442 // Fill in an array for return
302 if (error_state) 443 int i = 0;
303 panic_impossible (); 444 Cell names (dim_vector (bp_list.size (), 1));
304 } 445 Cell file (dim_vector (bp_list.size (), 1));
305 446 Cell line (dim_vector (bp_list.size (), 1));
306 retval = octave_value (vec); 447 for (it = bp_list.begin (); it != bp_list.end (); it++)
307 } 448 {
308 else 449 names (i) = it->first;
309 error ("dbstatus: unable to find the function you requested\n"); 450 line (i) = intmap_to_ov(it->second);
310 451 file (i) = do_which (it->first);
311 return retval; 452 i++;
453 }
454 retval.assign ("name", names);
455 retval.assign ("file", file);
456 retval.assign ("line", line);
457 return octave_value (retval);
458 }
459 else
460 {
461 // Print out the breakpoint information
462 for (it = bp_list.begin(); it != bp_list.end(); it++)
463 {
464 octave_stdout << "Breakpoint in " << it->first << " at line(s) ";
465 for (int j = 0; j < it->second.size (); j++)
466 if (j < it->second.size()-1)
467 octave_stdout << it->second [j] << ", ";
468 else
469 octave_stdout << it->second [j] << "." << std::endl;
470 }
471 return octave_value ();
472 }
312 } 473 }
313 474
314 DEFCMD (dbwhere, , , 475 DEFCMD (dbwhere, , ,
315 "-*- texinfo -*-\n\ 476 "-*- texinfo -*-\n\
316 @deftypefn {Loadable Function} {} dbwhere ()\n\ 477 @deftypefn {Loadable Function} {} dbwhere ()\n\