GNU Octave  4.4.1
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
debug.cc
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 2001-2018 Ben Sapp
4 Copyright (C) 2007-2009 John Swensen
5 
6 This file is part of Octave.
7 
8 Octave is free software: you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
12 
13 Octave is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17 
18 You should have received a copy of the GNU General Public License
19 along with Octave; see the file COPYING. If not, see
20 <https://www.gnu.org/licenses/>.
21 
22 */
23 
24 #if defined (HAVE_CONFIG_H)
25 # include "config.h"
26 #endif
27 
28 #include <deque>
29 #include <fstream>
30 #include <iomanip>
31 #include <iostream>
32 #include <limits>
33 #include <set>
34 #include <string>
35 
36 #include "dNDArray.h"
37 
38 #include "bp-table.h"
39 #include "call-stack.h"
40 #include "defun.h"
41 #include "error.h"
42 #include "errwarn.h"
43 #include "file-ops.h"
44 #include "help.h"
45 #include "input.h"
46 #include "interpreter-private.h"
47 #include "interpreter.h"
49 #include "ov-usr-fcn.h"
50 #include "ov.h"
51 #include "ovl.h"
52 #include "pager.h"
53 #include "parse.h"
54 #include "pt-eval.h"
55 #include "unwind-prot.h"
56 #include "utils.h"
57 #include "utils.h"
58 #include "variables.h"
59 
60 static octave_value
62 {
63  int idx = 0;
64 
65  NDArray retval (dim_vector (1, line.size ()));
66 
67  for (size_t i = 0; i < line.size (); i++)
68  {
70 
71  if (p != line.end ())
72  {
73  int lineno = p->second;
74  retval(idx++) = lineno;
75  }
76  }
77 
78  retval.resize (dim_vector (1, idx));
79 
80  return retval;
81 }
82 
83 DEFUN (dbstop, args, ,
84  doc: /* -*- texinfo -*-
85 @deftypefn {} {} dbstop @var{func}
86 @deftypefnx {} {} dbstop @var{func} @var{line}
87 @deftypefnx {} {} dbstop @var{func} @var{line1} @var{line2} @dots{}
88 @deftypefnx {} {} dbstop @var{line1} @dots{}
89 @deftypefnx {} {} dbstop in @var{func}
90 @deftypefnx {} {} dbstop in @var{func} at @var{line}
91 @deftypefnx {} {} dbstop in @var{func} at @var{line} if "@var{condition}"
92 @deftypefnx {} {} dbstop if @var{event}
93 @deftypefnx {} {} dbstop if @var{event} @var{ID}
94 @deftypefnx {} {} dbstop (@var{bp_struct})
95 @deftypefnx {} {@var{rline} =} dbstop @dots{}
96 
97 Set breakpoints for the built-in debugger.
98 
99 @var{func} is the name of a function on the current @code{path}. When
100 already in debug mode the @var{func} argument can be omitted and the current
101 function will be used. Breakpoints at subfunctions are set with the scope
102 operator @samp{>}. For example, If @file{file.m} has a subfunction
103 @code{func2}, then a breakpoint in @code{func2} can be specified by
104 @code{file>func2}.
105 
106 @var{line} is the line number at which to break. If @var{line} is not
107 specified, it defaults to the first executable line in the file
108 @file{func.m}. Multiple lines can be specified in a single command; when
109 function syntax is used, the lines may also be passed as a single vector
110 argument (@code{[@var{line1}, @var{line2}, @dots{}]}).
111 
112 @var{condition} is any Octave expression that can be evaluated in the code
113 context that exists at the breakpoint. When the breakpoint is encountered,
114 @var{condition} will be evaluated, and execution will stop if
115 @var{condition} is true. If @var{condition} cannot be evaluated, for
116 example because it refers to an undefined variable, an error will be thrown.
117  Expressions with side effects (such as @code{y++ > 1}) will alter
118 variables, and should generally be avoided. Conditions containing quotes
119 (@samp{"}, @samp{'}) or comment characters (@samp{#}, @samp{%}) must be
120 enclosed in quotes. (This does not apply to conditions entered from the
121 editor's context menu.) For example:
122 
123 @example
124 dbstop in strread at 209 if 'any (format == "%f")'
125 @end example
126 
127 The form specifying @var{event} does not cause a specific breakpoint at a
128 given function and line number. Instead it causes debug mode to be entered
129 when certain unexpected events are encountered. Possible values are
130 
131 @table @code
132 @item error
133 Stop when an error is reported. This is equivalent to specifying
134 both @code{debug_on_error (true)} and @code{debug_on_interrupt (true)}.
135 
136 @item caught error
137 Stop when an error is caught by a try-catch block (not yet implemented).
138 
139 @item interrupt
140 Stop when an interrupt (@kbd{Ctrl-C}) occurs.
141 
142 @item naninf
143 Stop when code returns a non-finite value (not yet implemented).
144 
145 @item warning
146 Stop when a warning is reported. This is equivalent to specifying
147 @code{debug_on_warning (true)}.
148 @end table
149 
150 The events @code{error}, @code{caught error}, and @code{warning} can all be
151 followed by a string specifying an error ID or warning ID@. If that is
152 done, only errors with the specified ID will cause execution to stop. To
153 stop on one of a set of IDs, multiple @code{dbstop} commands must be
154 issued.
155 
156 Breakpoints and events can be removed using the @code{dbclear} command with
157 the same syntax.
158 
159 It is possible to save all breakpoints and restore them at once by issuing
160 the commands @code{bp_state = dbstatus; @dots{}; dbstop (bp_state)}.
161 
162 The optional output @var{rline} is the real line number where the breakpoint
163 was set. This can differ from the specified line if the line is not
164 executable. For example, if a breakpoint attempted on a blank line then
165 Octave will set the real breakpoint at the next executable line.
166 
167 When a file is re-parsed, such as when it is modified outside the GUI,
168 all breakpoints within the file are cleared.
169 
170 @seealso{dbclear, dbstatus, dbstep, debug_on_error, debug_on_warning, debug_on_interrupt}
171 @end deftypefn */)
172 {
174  std::string symbol_name = ""; // stays empty for "dbstop if error" etc
176  std::string condition = "";
178 
179  octave::bp_table& bptab = octave::__get_bp_table__ ("Fdbstop");
180 
181  if (args.length() >= 1 && ! args(0).isstruct ())
182  {
183  // explicit function / line / condition
184  bptab.parse_dbfunction_params ("dbstop", args, symbol_name,
185  lines, condition);
186 
187  if (lines.size () == 0)
188  lines[0] = 1;
189 
190  if (symbol_name != "")
191  {
192  retmap = bptab.add_breakpoint (symbol_name, lines, condition);
193  retval = intmap_to_ov (retmap);
194  }
195  }
196  else if (args.length () != 1)
197  {
198  print_usage ();
199  }
200  else // structure of the form output by dbstatus
201  {
202  octave_map mv = args(0).map_value ();
203  if (mv.isfield ("bkpt") || mv.isfield ("errs") || mv.isfield ("warn")
204  || mv.isfield ("intr"))
205  {
206  bptab.dbstop_process_map_args (mv);
207 
208  // Replace mv by "bkpt", to use the processing below.
209  octave_value bkpt = mv.getfield ("bkpt");
210  if (bkpt.isempty ())
211  mv = octave_map ();
212  else
213  {
214  if (bkpt.iscell () && bkpt.cell_value ().numel () > 0
215  && bkpt.cell_value () (0).isstruct ())
216  mv = bkpt.cell_value () (0).map_value ();
217  else
218  {
219  error ("dbstop: invalid 'bkpt' field");
220  mv = octave_map ();
221  }
222  }
223  }
224  if (mv.isempty ())
225  {
226  // no changes requested. Occurs if "errs" non-empty but "bkpt" empty
227  }
228  else if (! mv.isfield ("name") || ! mv.isfield ("line"))
229  {
230  error ("dbstop: Cell array must contain fields 'name' and 'line'");
231  retval = octave_value (0);
232  }
233  else
234  {
235  bool use_cond = mv.isfield ("cond");
236  Cell name = mv.getfield ("name");
237  Cell line = mv.getfield ("line");
238  Cell cond = (use_cond ? mv.getfield ("cond") : Cell ());
239  std::string unconditional = "";
240  for (octave_idx_type i = 0; i < line.numel (); i++)
241  {
242  lines [0] = line(i).double_value ();
243  bptab.add_breakpoint (name(i).string_value (), lines,
244  (use_cond
245  ? cond(i).string_value ()
246  : unconditional));
247  }
248  retval = octave_value (line.numel ());
249  }
250  }
251 
252  return retval;
253 }
254 
255 DEFUN (dbclear, args, ,
256  doc: /* -*- texinfo -*-
257 @deftypefn {} {} dbclear @var{func}
258 @deftypefnx {} {} dbclear @var{func} @var{line}
259 @deftypefnx {} {} dbclear @var{func} @var{line1} @var{line2} @dots{}
260 @deftypefnx {} {} dbclear @var{line} @dots{}
261 @deftypefnx {} {} dbclear all
262 @deftypefnx {} {} dbclear in @var{func}
263 @deftypefnx {} {} dbclear in @var{func} at @var{line}
264 @deftypefnx {} {} dbclear if @var{event}
265 @deftypefnx {} {} dbclear ("@var{func}")
266 @deftypefnx {} {} dbclear ("@var{func}", @var{line})
267 @deftypefnx {} {} dbclear ("@var{func}", @var{line1}, @var{line2}, @dots{})
268 @deftypefnx {} {} dbclear ("@var{func}", @var{line1}, @dots{})
269 @deftypefnx {} {} dbclear (@var{line}, @dots{})
270 @deftypefnx {} {} dbclear ("all")
271 Delete a breakpoint at line number @var{line} in the function @var{func}.
272 
273 Arguments are
274 
275 @table @var
276 @item func
277 Function name as a string variable. When already in debug mode this
278 argument can be omitted and the current function will be used.
279 
280 @item line
281 Line number from which to remove a breakpoint. Multiple lines may be given
282 as separate arguments or as a vector.
283 
284 @item event
285 An event such as @code{error}, @code{interrupt}, or @code{warning}
286 (@pxref{XREFdbstop,,dbstop} for details).
287 @end table
288 
289 When called without a line number specification all breakpoints in the named
290 function are cleared.
291 
292 If the requested line is not a breakpoint no action is performed.
293 
294 The special keyword @qcode{"all"} will clear all breakpoints from all
295 files.
296 @seealso{dbstop, dbstatus, dbwhere}
297 @end deftypefn */)
298 {
299  std::string symbol_name = ""; // stays empty for "dbclear if error" etc
301  std::string dummy; // "if" condition -- only used for dbstop
302 
303  int nargin = args.length ();
304 
305  octave::bp_table& bptab = octave::__get_bp_table__ ("Fdbclear");
306 
307  bptab.parse_dbfunction_params ("dbclear", args, symbol_name, lines, dummy);
308 
309  if (nargin == 1 && symbol_name == "all")
310  {
311  bptab.remove_all_breakpoints ();
312  bptab.dbclear_all_signals ();
313  }
314  else
315  {
316  if (symbol_name != "")
317  bptab.remove_breakpoint (symbol_name, lines);
318  }
319 
320  return ovl ();
321 }
322 
323 DEFMETHOD (dbstatus, interp, args, nargout,
324  doc: /* -*- texinfo -*-
325 @deftypefn {} {} dbstatus
326 @deftypefnx {} {} dbstatus @var{func}
327 @deftypefnx {} {@var{bp_list} =} dbstatus @dots{}
328 Report the location of active breakpoints.
329 
330 When called with no input or output arguments, print the list of all
331 functions with breakpoints and the line numbers where those breakpoints are
332 set.
333 
334 If a function name @var{func} is specified then only report breakpoints
335 for the named function and its subfunctions.
336 
337 The optional return argument @var{bp_list} is a struct array with the
338 following fields.
339 
340 @table @asis
341 @item name
342 The name of the function with a breakpoint. A subfunction, say @code{func2}
343 within an m-file, say @file{file.m}, is specified as @code{file>func2}.
344 
345 @item file
346 The name of the m-file where the function code is located.
347 
348 @item line
349 The line number with the breakpoint.
350 
351 @item cond
352 The condition that must be satisfied for the breakpoint to be active, or
353 the empty string for unconditional breakpoints.
354 @end table
355 
356 @c Note: When @code{dbstatus} is called from the debug prompt within a function,
357 @c the list of breakpoints is automatically trimmed to the breakpoints in the
358 @c current function.
359 If @code{dbstop if error} is true but no explicit IDs are specified, the
360 return value will have an empty field called @qcode{"errs"}. If IDs are
361 specified, the @code{errs} field will have one row per ID@. If
362 @code{dbstop if error} is false, there is no @qcode{"errs"} field.
363 The @qcode{"warn"} field is set similarly by @code{dbstop if warning}.
364 
365 @seealso{dbstop, dbclear, dbwhere, dblist, dbstack}
366 @end deftypefn */)
367 {
368  int nargin = args.length ();
369 
370  if (nargin != 0 && nargin != 1)
371  error ("dbstatus: only zero or one arguments accepted\n");
372 
373  octave_value_list fcn_list;
375  std::string symbol_name;
376 
377  octave::bp_table& bptab = octave::__get_bp_table__ ("Fdbstatus");
378 
379  if (nargin == 1)
380  {
381  if (! args(0).is_string ())
382  err_wrong_type_arg ("dbstatus", args(0));
383 
384  symbol_name = args(0).string_value ();
385  fcn_list(0) = symbol_name;
386  bp_list = bptab.get_breakpoint_list (fcn_list);
387  }
388  else
389  {
390 /*
391  if (Vdebugging)
392  {
393  octave_user_code *dbg_fcn = get_user_code ();
394  if (dbg_fcn)
395  {
396  symbol_name = dbg_fcn->name ();
397  fcn_list(0) = symbol_name;
398  }
399  }
400 */
401 
402  bp_list = bptab.get_breakpoint_list (fcn_list);
403  }
404 
405  if (nargout == 0)
406  {
407  // Print out the breakpoint information.
408 
409  for (auto& fnm_bp_p: bp_list)
410  {
411  std::list<octave::bp_type> m = fnm_bp_p.second;
412 
413  // print unconditional breakpoints, if any, on a single line
414 
415  // first, check to see if there are any
416  int have_unconditional = 0;
417  for (const auto& bp : m)
418  {
419  if (bp.cond == "")
420  {
421  if (have_unconditional++)
422  break; // stop once we know its plural
423  }
424  }
425  // If we actually have some, print line numbers only
426  if (have_unconditional)
427  {
428  const char *_s_ = (have_unconditional > 1) ? "s" : "";
429  octave_stdout << "breakpoint" << _s_ << " in " << fnm_bp_p.first
430  << " at line" << _s_ << ' ';
431 
432  for (const auto& bp : m)
433  {
434  if (bp.cond == "")
435  octave_stdout << bp.line << ' ';
436  }
437  octave_stdout << std::endl;
438  }
439 
440  // print conditional breakpoints, one per line, with conditions
441  for (const auto& bp : m)
442  {
443  if (bp.cond != "")
444  octave_stdout << "breakpoint in " << fnm_bp_p.first
445  << " at line " << bp.line
446  << " if " << bp.cond << "\n";
447  }
448  }
449 
450  bptab.stop_on_err_warn_status (true);
451 
452  return ovl ();
453  }
454  else
455  {
456  octave::help_system& help_sys = interp.get_help_system ();
457 
458  // Fill in an array for return.
459  int i = 0;
460  octave_map retmap;
462 
463  // count the number of breakpoints in all files
464  int count = 0;
465  for (const auto& fnm_bp_p : bp_list)
466  count += fnm_bp_p.second.size ();
467 
468  Cell names (dim_vector (count, 1));
469  Cell file (dim_vector (count, 1));
470  Cell line (dim_vector (count, 1));
471  Cell cond (dim_vector (count, 1));
472 
473  for (const auto& fnm_bp_p : bp_list)
474  {
475  std::string filename = fnm_bp_p.first;
476  const char *sub_fun = strchr (filename.c_str (), '>');
477  if (sub_fun)
478  filename = filename.substr(0, sub_fun - filename.c_str ());
479  octave_value path_name;
480  path_name
482 
483  for (const auto& bp : fnm_bp_p.second)
484  {
485  names(i) = fnm_bp_p.first;
486  file(i) = path_name;
487  line(i) = octave_value (bp.line);
488  cond(i) = octave_value (bp.cond);
489  i++;
490  }
491  }
492 
493  retmap.assign ("name", names);
494  retmap.assign ("file", file);
495  retmap.assign ("line", line);
496  retmap.assign ("cond", cond);
497 
498  octave_map ew = bptab.stop_on_err_warn_status (false);
499  if (ew.isempty ())
500  {
501  retval = octave_value (retmap);
502  }
503  else
504  {
505  octave_map outer (dim_vector (3,1));
506  outer.assign ("bkpt", Cell (retmap));
507  for (octave_map::const_iterator f = ew.begin (); f != ew.end (); f++)
508  outer.setfield (f->first, ew.contents (f));
509 
510  retval = octave_value (outer);
511  }
512 
513  return retval;
514  }
515 }
516 
517 /*
518 %!test
519 %! dbclear all; # Clear out breakpoints before test
520 %! dbstop @ftp/dir;
521 %! dbstop @audioplayer/set 70;
522 %! dbstop quantile>__quantile__;
523 %! dbstop ls;
524 %! s = dbstatus;
525 %! dbclear all;
526 %! assert (s(1).name, "@audioplayer/set>setproperty");
527 %! assert (s(2).name, "@ftp/dir");
528 %! assert (s(3).name, "ls");
529 %! assert (s(4).name, "quantile>__quantile__");
530 %! assert (s(2).file(end-10:end), [filesep "@ftp" filesep "dir.m"]);
531 */
532 
533 DEFMETHOD (dbwhere, interp, , ,
534  doc: /* -*- texinfo -*-
535 @deftypefn {} {} dbwhere
536 In debugging mode, report the current file and line number where execution
537 is stopped.
538 @seealso{dbstack, dblist, dbstatus, dbcont, dbstep, dbup, dbdown}
539 @end deftypefn */)
540 {
542 
543  if (! dbg_fcn)
544  {
545  octave_stdout << "stopped at top level" << std::endl;
546  return ovl ();
547  }
548 
549  octave_stdout << "stopped in " << dbg_fcn->name () << " at ";
550 
551  octave::call_stack& cs = interp.get_call_stack ();
552 
553  int l = cs.debug_user_code_line ();
554 
555  if (l > 0)
556  {
557  octave_stdout << "line " << l;
558 
559  std::string file_name = dbg_fcn->fcn_file_name ();
560 
561  if (! file_name.empty ())
562  {
563  octave_stdout << " [" << file_name << ']' << std::endl;
564 
565  std::string line = dbg_fcn->get_code_line (l);
566 
567  if (! line.empty ())
568  octave_stdout << l << ": " << line << std::endl;
569  }
570  else
571  octave_stdout << std::endl;
572  }
573  else
574  octave_stdout << "<unknown line>" << std::endl;
575 
576  return ovl ();
577 }
578 
579 static void
580 do_dbtype (std::ostream& os, const std::string& name, int start, int end)
581 {
583 
584  if (ff.empty ())
585  os << "dbtype: unknown function " << name << "\n";
586  else
587  {
588  std::ifstream fs (ff.c_str (), std::ios::in);
589 
590  if (! fs)
591  os << "dbtype: unable to open '" << ff << "' for reading!\n";
592  else
593  {
594  int line = 1;
596 
597  while (std::getline (fs, text) && line <= end)
598  {
599  if (line >= start)
600  os << line << "\t" << text << "\n";
601 
602  line++;
603  }
604  }
605  }
606 
607  os.flush ();
608 }
609 
610 DEFUN (dbtype, args, ,
611  doc: /* -*- texinfo -*-
612 @deftypefn {} {} dbtype
613 @deftypefnx {} {} dbtype @var{lineno}
614 @deftypefnx {} {} dbtype @var{startl:endl}
615 @deftypefnx {} {} dbtype @var{startl:end}
616 @deftypefnx {} {} dbtype @var{func}
617 @deftypefnx {} {} dbtype @var{func} @var{lineno}
618 @deftypefnx {} {} dbtype @var{func} @var{startl:endl}
619 @deftypefnx {} {} dbtype @var{func} @var{startl:end}
620 Display a script file with line numbers.
621 
622 When called with no arguments in debugging mode, display the script file
623 currently being debugged.
624 
625 An optional range specification can be used to list only a portion of the
626 file. The special keyword @qcode{"end"} is a valid line number
627 specification for the last line of the file.
628 
629 When called with the name of a function, list that script file with line
630 numbers.
631 @seealso{dblist, dbwhere, dbstatus, dbstop}
632 @end deftypefn */)
633 {
634  octave_user_code *dbg_fcn;
635 
636  string_vector argv = args.make_argv ("dbtype");
637 
638  switch (args.length ())
639  {
640  case 0: // dbtype
641  dbg_fcn = octave::get_user_code ();
642 
643  if (! dbg_fcn)
644  error ("dbtype: must be inside a user function to give no arguments to dbtype\n");
645 
646  do_dbtype (octave_stdout, dbg_fcn->fcn_file_name (),
648 
649  break;
650 
651  case 1: // (dbtype start:end) || (dbtype func) || (dbtype lineno)
652  {
653  std::string arg = argv[1];
654 
655  size_t ind = arg.find (':');
656 
657  if (ind != std::string::npos) // (dbtype start:end)
658  {
659  dbg_fcn = octave::get_user_code ();
660 
661  if (dbg_fcn)
662  {
663  std::string start_str = arg.substr (0, ind);
664  std::string end_str = arg.substr (ind + 1);
665 
666  int start, end;
667  start = atoi (start_str.c_str ());
668  if (end_str == "end")
670  else
671  end = atoi (end_str.c_str ());
672 
673  if (std::min (start, end) <= 0)
674  error ("dbtype: start and end lines must be >= 1\n");
675 
676  if (start > end)
677  error ("dbtype: start line must be less than end line\n");
678 
679  do_dbtype (octave_stdout, dbg_fcn->fcn_file_name (),
680  start, end);
681  }
682  }
683  else // (dbtype func) || (dbtype lineno)
684  {
685  int line = atoi (arg.c_str ());
686 
687  if (line == 0) // (dbtype func)
688  {
689  dbg_fcn = octave::get_user_code (arg);
690 
691  if (! dbg_fcn)
692  error ("dbtype: function <%s> not found\n", arg.c_str ());
693 
694  do_dbtype (octave_stdout, dbg_fcn->fcn_file_name (),
696  }
697  else // (dbtype lineno)
698  {
699  if (line <= 0)
700  error ("dbtype: start and end lines must be >= 1\n");
701 
702  dbg_fcn = octave::get_user_code ();
703 
704  if (dbg_fcn)
705  do_dbtype (octave_stdout, dbg_fcn->fcn_file_name (),
706  line, line);
707  }
708  }
709  }
710  break;
711 
712  case 2: // (dbtype func start:end) || (dbtype func start)
713  {
714  dbg_fcn = octave::get_user_code (argv[1]);
715 
716  if (! dbg_fcn)
717  error ("dbtype: function <%s> not found\n", argv[1].c_str ());
718 
719  std::string arg = argv[2];
720  int start, end;
721  size_t ind = arg.find (':');
722 
723  if (ind != std::string::npos)
724  {
725  std::string start_str = arg.substr (0, ind);
726  std::string end_str = arg.substr (ind + 1);
727 
728  start = atoi (start_str.c_str ());
729  if (end_str == "end")
731  else
732  end = atoi (end_str.c_str ());
733  }
734  else
735  {
736  start = atoi (arg.c_str ());
737  end = start;
738  }
739 
740  if (std::min (start, end) <= 0)
741  error ("dbtype: start and end lines must be >= 1\n");
742 
743  if (start > end)
744  error ("dbtype: start line must be less than end line\n");
745 
746  do_dbtype (octave_stdout, dbg_fcn->fcn_file_name (), start, end);
747  }
748  break;
749 
750  default:
751  error ("dbtype: expecting zero, one, or two arguments\n");
752  }
753 
754  return ovl ();
755 }
756 
757 DEFMETHOD (dblist, interp, args, ,
758  doc: /* -*- texinfo -*-
759 @deftypefn {} {} dblist
760 @deftypefnx {} {} dblist @var{n}
761 In debugging mode, list @var{n} lines of the function being debugged
762 centered around the current line to be executed.
763 
764 If unspecified @var{n} defaults to 10 (+/- 5 lines)
765 @seealso{dbwhere, dbtype, dbstack}
766 @end deftypefn */)
767 {
768  int n = 10;
769 
770  if (args.length () == 1)
771  {
772  octave_value arg = args(0);
773 
774  if (arg.is_string ())
775  {
776  std::string s_arg = arg.string_value ();
777 
778  n = atoi (s_arg.c_str ());
779  }
780  else
781  n = args(0).int_value ();
782 
783  if (n < 0)
784  error ("dblist: N must be a non-negative integer");
785  }
786 
788 
789  if (! dbg_fcn)
790  error ("dblist: must be inside a user function to use dblist\n");
791 
792  bool have_file = true;
793 
794  std::string name = dbg_fcn->fcn_file_name ();
795 
796  if (name.empty ())
797  {
798  have_file = false;
799  name = dbg_fcn->name ();
800  }
801 
802  octave::call_stack& cs = interp.get_call_stack ();
803 
804  int l = cs.debug_user_code_line ();
805 
806  if (l > 0)
807  {
808  if (have_file)
809  {
810  int l_min = std::max (l - n/2, 0);
811  int l_max = l + n/2;
812  do_dbtype (octave_stdout, name, l_min, l-1);
813 
814  std::string line = dbg_fcn->get_code_line (l);
815 
816  if (! line.empty ())
817  octave_stdout << l << "-->\t" << line << std::endl;
818 
819  do_dbtype (octave_stdout, name, l+1, l_max);
820  }
821  }
822  else
823  {
824  octave_stdout << "dblist: unable to determine source code line"
825  << std::endl;
826  }
827 
828  return ovl ();
829 }
830 
831 static octave_value_list
832 do_dbstack (octave::interpreter& interp, const octave_value_list& args,
833  int nargout, std::ostream& os)
834 {
835  int nargin = args.length ();
836 
837  if (nargin > 2)
838  print_usage ();
839 
841 
843 
844  octave_idx_type curr_frame = -1;
845 
846  size_t nskip = 0;
847 
848  if (nargin == 1 || nargin == 2)
849  {
850  int n = 0;
851 
852  for (octave_idx_type i = 0; i < nargin; i++)
853  {
854  octave_value arg = args(i);
855 
856  if (arg.is_string ())
857  {
858  std::string s_arg = arg.string_value ();
859 
860  // Skip "-completenames", octave returns full names anyway.
861  if (s_arg == "-completenames")
862  continue;
863 
864  n = atoi (s_arg.c_str ());
865  }
866  else
867  n = arg.int_value ();
868 
869  if (n <= 0)
870  error ("dbstack: N must be a non-negative integer");
871  }
872 
873  if (n > 0)
874  nskip = n;
875  }
876 
877  octave::call_stack& cs = interp.get_call_stack ();
878 
879  if (nargout == 0)
880  {
881  octave_map stk = cs.backtrace (nskip, curr_frame);
882  octave_idx_type nframes_to_display = stk.numel ();
883 
884  if (nframes_to_display > 0)
885  {
886  octave::preserve_stream_state stream_state (os);
887 
888  os << "stopped in:\n\n";
889 
890  Cell names = stk.contents ("name");
891  Cell files = stk.contents ("file");
892  Cell lines = stk.contents ("line");
893 
894  bool show_top_level = true;
895 
896  size_t max_name_len = 0;
897 
898  for (octave_idx_type i = 0; i < nframes_to_display; i++)
899  {
900  std::string name = names(i).string_value ();
901 
902  max_name_len = std::max (name.length (), max_name_len);
903  }
904 
905  for (octave_idx_type i = 0; i < nframes_to_display; i++)
906  {
907  std::string name = names(i).string_value ();
908  std::string file = files(i).string_value ();
909  int line = lines(i).int_value ();
910 
911  if (show_top_level && i == curr_frame)
912  show_top_level = false;
913 
914  os << (i == curr_frame ? " --> " : " ")
915  << std::setw (max_name_len) << name
916  << " at line " << line
917  << " [" << file << ']'
918  << std::endl;
919  }
920 
921  if (show_top_level)
922  os << " --> top level" << std::endl;
923  }
924  }
925  else
926  {
927  octave_map stk = cs.backtrace (nskip, curr_frame, false);
928 
929  retval = ovl (stk, curr_frame < 0 ? 1 : curr_frame + 1);
930  }
931 
932  return retval;
933 }
934 
935 // A function that can be easily called from a debugger print the Octave stack.
936 // This can be useful for finding what line of code the interpreter is
937 // currently executing when the debugger is stopped in some C++ function,
938 // for example.
939 
940 void
941 show_octave_dbstack (void)
942 {
943  do_dbstack (octave::__get_interpreter__ ("show_octave_dbstack"),
944  octave_value_list (), 0, std::cerr);
945 }
946 
947 DEFMETHOD (dbstack, interp, args, nargout,
948  doc: /* -*- texinfo -*-
949 @deftypefn {} {} dbstack
950 @deftypefnx {} {} dbstack @var{n}
951 @deftypefnx {} {} dbstack @var{-completenames}
952 @deftypefnx {} {[@var{stack}, @var{idx}] =} dbstack (@dots{})
953 Display or return current debugging function stack information.
954 
955 With optional argument @var{n}, omit the @var{n} innermost stack frames.
956 
957 Although accepted, the argument @var{-completenames} is silently ignored.
958 Octave always returns absolute filenames.
959 
960 The arguments @var{n} and @var{-completenames} can be both specified in any
961 order.
962 
963 The optional return argument @var{stack} is a struct array with the
964 following fields:
965 
966 @table @asis
967 @item file
968 The name of the m-file where the function code is located.
969 
970 @item name
971 The name of the function with a breakpoint.
972 
973 @item line
974 The line number of an active breakpoint.
975 
976 @item column
977 The column number of the line where the breakpoint begins.
978 
979 @item scope
980 Undocumented.
981 
982 @item context
983 Undocumented.
984 @end table
985 
986 The return argument @var{idx} specifies which element of the @var{stack}
987 struct array is currently active.
988 @seealso{dbup, dbdown, dbwhere, dblist, dbstatus}
989 @end deftypefn */)
990 {
991  return do_dbstack (interp, args, nargout, octave_stdout);
992 }
993 
994 static void
995 do_dbupdown (octave::interpreter& interp, const octave_value_list& args,
996  const std::string& who)
997 {
998  int n = 1;
999 
1000  if (args.length () == 1)
1001  {
1002  octave_value arg = args(0);
1003 
1004  if (arg.is_string ())
1005  {
1006  std::string s_arg = arg.string_value ();
1007 
1008  n = atoi (s_arg.c_str ());
1009  }
1010  else
1011  n = args(0).int_value ();
1012  }
1013 
1014  if (who == "dbup")
1015  n = -n;
1016 
1017  octave::call_stack& cs = interp.get_call_stack ();
1018 
1019  if (! cs.goto_frame_relative (n, true))
1020  error ("%s: invalid stack frame", who.c_str ());
1021 }
1022 
1023 DEFMETHOD (dbup, interp, args, ,
1024  doc: /* -*- texinfo -*-
1025 @deftypefn {} {} dbup
1026 @deftypefnx {} {} dbup @var{n}
1027 In debugging mode, move up the execution stack @var{n} frames.
1028 
1029 If @var{n} is omitted, move up one frame.
1030 @seealso{dbstack, dbdown}
1031 @end deftypefn */)
1032 {
1033  do_dbupdown (interp, args, "dbup");
1034 
1035  return ovl ();
1036 }
1037 
1038 DEFMETHOD (dbdown, interp, args, ,
1039  doc: /* -*- texinfo -*-
1040 @deftypefn {} {} dbdown
1041 @deftypefnx {} {} dbdown @var{n}
1042 In debugging mode, move down the execution stack @var{n} frames.
1043 
1044 If @var{n} is omitted, move down one frame.
1045 @seealso{dbstack, dbup}
1046 @end deftypefn */)
1047 {
1048  do_dbupdown (interp, args, "dbdown");
1049 
1050  return ovl ();
1051 }
1052 
1053 DEFUN (dbstep, args, ,
1054  doc: /* -*- texinfo -*-
1055 @deftypefn {} {} dbstep
1056 @deftypefnx {} {} dbstep @var{n}
1057 @deftypefnx {} {} dbstep in
1058 @deftypefnx {} {} dbstep out
1059 @deftypefnx {} {} dbnext @dots{}
1060 In debugging mode, execute the next @var{n} lines of code.
1061 
1062 If @var{n} is omitted, execute the next single line of code. If the next
1063 line of code is itself defined in terms of an m-file remain in the existing
1064 function.
1065 
1066 Using @code{dbstep in} will cause execution of the next line to step into
1067 any m-files defined on the next line.
1068 
1069 Using @code{dbstep out} will cause execution to continue until the current
1070 function returns.
1071 
1072 @code{dbnext} is an alias for @code{dbstep}.
1073 @seealso{dbcont, dbquit}
1074 @end deftypefn */)
1075 {
1076  if (! Vdebugging)
1077  error ("dbstep: can only be called in debug mode");
1078 
1079  int nargin = args.length ();
1080 
1081  if (nargin > 1)
1082  print_usage ();
1083 
1084  if (nargin == 1)
1085  {
1086  std::string arg = args(0).xstring_value ("dbstep: input argument must be a string");
1087 
1088  if (arg == "in")
1089  {
1090  Vdebugging = false;
1091  Vtrack_line_num = true;
1092 
1094  }
1095  else if (arg == "out")
1096  {
1097  Vdebugging = false;
1098  Vtrack_line_num = true;
1099 
1101  }
1102  else
1103  {
1104  int n = atoi (arg.c_str ());
1105 
1106  if (n < 1)
1107  error ("dbstep: invalid argument");
1108 
1109  Vdebugging = false;
1110  Vtrack_line_num = true;
1111 
1113  }
1114  }
1115  else
1116  {
1117  Vdebugging = false;
1118  Vtrack_line_num = true;
1119 
1121  }
1122 
1123  return ovl ();
1124 }
1125 
1126 DEFALIAS (dbnext, dbstep);
1127 
1128 DEFUN (dbcont, args, ,
1129  doc: /* -*- texinfo -*-
1130 @deftypefn {} {} dbcont
1131 Leave command-line debugging mode and continue code execution normally.
1132 @seealso{dbstep, dbquit}
1133 @end deftypefn */)
1134 {
1135  if (! Vdebugging)
1136  error ("dbcont: can only be called in debug mode");
1137 
1138  if (args.length () != 0)
1139  print_usage ();
1140 
1141  Vdebugging = false;
1142  Vtrack_line_num = true;
1143 
1145 
1146  return ovl ();
1147 }
1148 
1149 DEFUN (dbquit, args, ,
1150  doc: /* -*- texinfo -*-
1151 @deftypefn {} {} dbquit
1152 Quit debugging mode immediately without further code execution and return to
1153 the Octave prompt.
1154 @seealso{dbcont, dbstep}
1155 @end deftypefn */)
1156 {
1157  if (! Vdebugging)
1158  error ("dbquit: can only be called in debug mode");
1159 
1160  if (args.length () != 0)
1161  print_usage ();
1162 
1163  // FIXME: there are too many debug mode flags!
1164 
1165  Vdebugging = false;
1166 
1169 
1170  throw octave::interrupt_exception ();
1171 
1172  return ovl ();
1173 }
1174 
1175 DEFUN (isdebugmode, args, ,
1176  doc: /* -*- texinfo -*-
1177 @deftypefn {} {} isdebugmode ()
1178 Return true if in debugging mode, otherwise false.
1179 @seealso{dbwhere, dbstack, dbstatus}
1180 @end deftypefn */)
1181 {
1182  if (args.length () != 0)
1183  print_usage ();
1184 
1185  return ovl (Vdebugging);
1186 }
1187 
1188 DEFUN (__db_next_breakpoint_quiet__, args, ,
1189  doc: /* -*- texinfo -*-
1190 @deftypefn {} {} __db_next_breakpoint_quiet__ ()
1191 @deftypefnx {} {} __db_next_breakpoint_quiet__ (@var{flag})
1192 Disable line info printing at the next breakpoint.
1193 
1194 With a logical argument @var{flag}, set the state on or off.
1195 @end deftypefn */)
1196 {
1197  int nargin = args.length ();
1198 
1199  if (nargin > 1)
1200  print_usage ();
1201 
1202  bool state = true;
1203 
1204  if (nargin == 1)
1205  state = args(0).bool_value ();
1206 
1208 
1209  return ovl ();
1210 }
scalar structure containing the one value The second produces an empty struct array with one field and no values since being passed an empty cell array of struct array values When the value is a cell array containing a single entry this becomes a scalar struct with that single entry as the value of the field That single entry happens to be an empty cell array Finally if the value is a non scalar cell array then ode isstruct
Definition: Cell.h:37
For example cd octave end example noindent changes the current working directory to file
Definition: dirfns.cc:124
int int_value(bool req_int=false, bool frc_str_conv=false) const
Definition: ov.h:793
#define DEFMETHOD(name, interp_name, args_name, nargout_name, doc)
Macro to define a builtin method.
Definition: defun.h:135
std::string canonicalize_file_name(const std::string &name)
Definition: file-ops.cc:685
interpreter & __get_interpreter__(const std::string &who)
octave_user_code * get_user_code(const std::string &fname)
Definition: bp-table.cc:936
int flush(void)
Definition: oct-stream.cc:5996
std::string string_value(bool force=false) const
Definition: ov.h:955
bool isempty(void) const
Definition: ov.h:529
void assign(const std::string &k, const Cell &val)
Definition: oct-map.h:351
ind
Definition: sub2ind.cc:107
static int dbstep_flag
Definition: pt-eval.h:247
int debug_user_code_line(void) const
Definition: call-stack.cc:272
OCTINTERP_API void print_usage(void)
Definition: defun.cc:54
F77_RET_T const F77_REAL const F77_REAL F77_REAL &F77_RET_T const F77_DBLE const F77_DBLE F77_DBLE &F77_RET_T const F77_DBLE F77_DBLE &F77_RET_T const F77_REAL F77_REAL &F77_RET_T const F77_DBLE const F77_DBLE * f
OCTINTERP_API std::string fcn_file_in_path(const std::string &)
octave_map backtrace(size_t nskip, octave_idx_type &curr_user_frame, bool print_subfn=true) const
Definition: call-stack.cc:573
std::string get_code_line(size_t line)
Definition: ov-usr-fcn.cc:85
bool goto_frame_relative(int n, bool verbose=false)
Definition: call-stack.cc:412
#define DEFUN(name, args_name, nargout_name, doc)
Macro to define a builtin function.
Definition: defun.h:53
intmap::const_iterator const_intmap_iterator
Definition: bp-table.h:62
void error(const char *fmt,...)
Definition: error.cc:578
static void reset_debug_state(void)
Definition: pt-eval.cc:439
std::string filename
Definition: urlwrite.cc:121
const_iterator end(void) const
Definition: oct-map.h:308
std::map< std::string, std::list< bp_type > > fname_bp_map
Definition: bp-table.h:70
intmap add_breakpoint(const std::string &fname="", const intmap &lines=intmap(), const std::string &condition="")
Definition: bp-table.cc:554
int remove_breakpoint(const std::string &fname="", const intmap &lines=intmap())
Definition: bp-table.cc:643
virtual std::string fcn_file_name(void) const
Definition: ov-fcn.h:74
static octave_value intmap_to_ov(const octave::bp_table::intmap &line)
Definition: debug.cc:61
static bool quiet_breakpoint_flag
Definition: pt-eval.h:254
octave_value arg
Definition: pr-output.cc:3244
string_vector argv
Definition: load-save.cc:648
octave_value resize(const dim_vector &dv, bool fill=false) const
Definition: ov.h:511
void dbclear_all_signals(void)
Definition: bp-table.cc:62
octave::call_stack & cs
Definition: ov-class.cc:1752
#define DEFALIAS(alias, name)
Macro to define an alias for another existing function name.
Definition: defun.h:211
Cell getfield(const std::string &key) const
Definition: oct-map.cc:276
bool isfield(const std::string &name) const
Definition: oct-map.h:333
nd deftypefn *std::string name
Definition: sysdep.cc:647
void parse_dbfunction_params(const char *, const octave_value_list &, std::string &, bp_table::intmap &, std::string &)
Definition: bp-table.cc:260
OCTAVE_EXPORT octave_value_list return the number of command line arguments passed to Octave If called with the optional argument the function xample nargout(@histc)
Definition: ov-usr-fcn.cc:997
bool Vtrack_line_num
Definition: input.cc:102
bool iscell(void) const
Definition: ov.h:536
octave_value retval
Definition: data.cc:6246
const Cell & contents(const_iterator p) const
Definition: oct-map.h:317
std::map< int, int > intmap
Definition: bp-table.h:60
static bool debug_mode
Definition: pt-eval.h:252
octave_map stop_on_err_warn_status(bool to_screen)
Definition: bp-table.cc:834
octave_idx_type numel(void) const
Definition: oct-map.h:375
void err_wrong_type_arg(const char *name, const char *s)
Definition: errwarn.cc:162
static uint32_t state[624]
Definition: randmtzig.cc:183
octave::unwind_protect frame
Definition: graphics.cc:12190
return octave_value(v1.char_array_value() . concat(v2.char_array_value(), ra_idx),((a1.is_sq_string()||a2.is_sq_string()) ? '\'' :'"'))
void dbstop_process_map_args(const octave_map &mv)
Definition: bp-table.cc:79
charNDArray max(char d, const charNDArray &m)
Definition: chNDArray.cc:227
OCTAVE_EXPORT octave_value_list the first data row corresponds to an index of zero The a spreadsheet style form such as the file is read until end of file is reached The such as text
Definition: dlmread.cc:194
fname_bp_map get_breakpoint_list(const octave_value_list &fname_list)
Definition: bp-table.cc:759
#define octave_stdout
Definition: pager.h:174
octave::sys::time start
Definition: graphics.cc:12337
OCTAVE_EXPORT octave_value_list isa nd deftypefn *return ovl(args(0).isinteger())
std::string which(const std::string &name) const
otherwise an error message is printed The permission mask is a UNIX concept used when creating new objects on a file system such as files
Definition: file-io.cc:3038
bp_table & __get_bp_table__(const std::string &who)
p
Definition: lu.cc:138
void remove_all_breakpoints(void)
Definition: bp-table.cc:727
Matrix size(void)
Definition: ov.h:409
octave_idx_type length(void) const
Definition: ovl.h:96
call_stack & get_call_stack(void)
bool isempty(void) const
Definition: oct-map.h:377
octave::sys::file_stat fs(filename)
args.length() nargin
Definition: file-io.cc:589
for i
Definition: data.cc:5264
bool is_string(void) const
Definition: ov.h:577
octave_fields::const_iterator const_iterator
Definition: oct-map.h:304
octave_idx_type numel(void) const
Number of elements in the array.
Definition: Array.h:366
string_vector names
Definition: ovl.h:160
Vector representing the dimensions (size) of an Array.
Definition: dim-vector.h:87
bool Vdebugging
Definition: input.cc:97
const_iterator begin(void) const
Definition: oct-map.h:307
std::string name(void) const
Definition: ov-fcn.h:182
If this string is the system will ring the terminal sometimes it is useful to be able to print the original representation of the string
Definition: utils.cc:888
octave::stream os
Definition: file-io.cc:627
Cell cell_value(void) const
charNDArray min(char d, const charNDArray &m)
Definition: chNDArray.cc:204