GNU Octave  4.2.1
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
debug.cc
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 2001-2017 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 the
10 Free Software Foundation; either version 3 of the License, or (at your
11 option) any later version.
12 
13 Octave is distributed in the hope that it will be useful, but WITHOUT
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 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 <http://www.gnu.org/licenses/>.
21 
22 */
23 #if defined (HAVE_CONFIG_H)
24 # include "config.h"
25 #endif
26 
27 #include <deque>
28 #include <fstream>
29 #include <iomanip>
30 #include <iostream>
31 #include <limits>
32 #include <set>
33 #include <string>
34 
35 #include "file-stat.h"
36 #include "singleton-cleanup.h"
37 
38 #include "call-stack.h"
39 #include "defun.h"
40 #include "error.h"
41 #include "file-ops.h"
42 #include "help.h"
43 #include "input.h"
44 #include "pager.h"
45 #include "octave-link.h"
46 #include "ovl.h"
47 #include "utils.h"
48 #include "parse.h"
49 #include "symtab.h"
50 #include "errwarn.h"
52 #include "ov.h"
53 #include "ov-usr-fcn.h"
54 #include "ov-fcn.h"
55 #include "ov-struct.h"
56 #include "pt-pr-code.h"
57 #include "pt-bp.h"
58 #include "pt-eval.h"
59 #include "pt-exp.h"
60 #include "pt-stmt.h"
61 #include "sighandlers.h"
62 #include "interpreter.h"
63 #include "unwind-prot.h"
64 #include "utils.h"
65 #include "variables.h"
66 
67 #include "debug.h"
68 
69 // Initialize the singleton object
71 
72 std::set<std::string> bp_table::errors_that_stop;
73 std::set<std::string> bp_table::caught_that_stop;
74 std::set<std::string> bp_table::warnings_that_stop;
75 
76 // Read entire file called fname and return the contents as a string
77 static std::string
79 {
81 
82  octave::sys::file_stat fs (fname);
83 
84  if (fs)
85  {
86  size_t sz = fs.size ();
87 
88  std::ifstream file (fname.c_str (), std::ios::in | std::ios::binary);
89 
90  if (file)
91  {
92  std::string buf (sz+1, 0);
93 
94  file.read (&buf[0], sz+1);
95 
96  if (! file.eof ())
97  error ("error reading file %s", fname.c_str ());
98 
99  // Expected to read the entire file.
100  retval = buf;
101  }
102  }
103 
104  return retval;
105 }
106 
107 static std::deque<size_t>
109 {
110  // FIXME: This could maybe be smarter. Is deque the right thing to use here?
111 
112  std::deque<size_t> offsets;
113 
114  offsets.push_back (0);
115 
116  size_t len = buf.length ();
117 
118  for (size_t i = 0; i < len; i++)
119  {
120  char c = buf[i];
121 
122  if (c == '\r' && ++i < len)
123  {
124  c = buf[i];
125 
126  if (c == '\n')
127  offsets.push_back (i+1);
128  else
129  offsets.push_back (i);
130  }
131  else if (c == '\n')
132  offsets.push_back (i+1);
133  }
134 
135  offsets.push_back (len);
136 
137  return offsets;
138 }
139 
142 {
144 
145  static std::string last_fname;
146 
147  static std::string buf;
148 
149  static std::deque<size_t> offsets;
150 
151  if (fname != last_fname)
152  {
153  buf = snarf_file (fname);
154 
155  offsets = get_line_offsets (buf);
156  }
157 
158  if (line > 0)
159  line--;
160 
161  if (line < offsets.size () - 1)
162  {
163  size_t bol = offsets[line];
164  size_t eol = offsets[line+1];
165 
166  while (eol > 0 && eol > bol && (buf[eol-1] == '\n' || buf[eol-1] == '\r'))
167  eol--;
168 
169  retval = buf.substr (bol, eol - bol);
170  }
171 
172  return retval;
173 }
174 
175 // Return a pointer to the user-defined function FNAME. If FNAME is
176 // empty, search backward for the first user-defined function in the
177 // current call stack.
178 
179 static octave_user_code *
181 {
182  octave_user_code *dbg_fcn = 0;
183 
184  if (fname.empty ())
186  else
187  {
189 
190  if (octave::sys::file_ops::dir_sep_char () != '/' && name[0] == '@')
191  {
192  int len = name.length () - 1; // -1: can't have trailing '/'
193  for (int i = 2; i < len; i++) // 2: can't have @/method
194  if (name[i] == '/')
196  }
197 
198  size_t name_len = name.length ();
199 
200  if (! name.empty () && name_len > 2 && name.substr (name_len-2) == ".m")
201  name = name.substr (0, name_len-2);
202 
204 
205  if (fcn.is_defined () && fcn.is_user_code ())
206  dbg_fcn = fcn.user_code_value ();
207  }
208 
209  return dbg_fcn;
210 }
211 
212 #if defined (DBSTOP_NANINF)
213 # include "sigfpe.cc"
214 #endif
215 
216 enum
218 
219 // Parse parameters (args) of dbstop and dbclear commands.
220 // For dbstop, who=="dbstop"; for dbclear, who=="dbclear".
221 // The syntax is: dbstop [[in] symbol] [[at] line [line [...]]] [if condition]
222 // where the form of condition depends on whether or not a file or line has
223 // been seen.
224 // Also execute "if [error|warning|interrupt|naninf]" clauses.
225 void
227  std::string& symbol_name, bp_table::intmap& lines,
228  std::string& cond)
229 {
230  int nargin = args.length ();
231  int list_idx = 0;
232  symbol_name = "";
233  lines = bp_table::intmap ();
234 
235  if (nargin == 0 || ! args(0).is_string ())
236  print_usage (who);
237 
238  // elements already processed
239  bool seen_in = false, seen_at = false, seen_if = false;
240  int pos = 0;
242  while (pos < nargin)
243  {
244  // allow "in" and "at" to be implicit
245  if (args(pos).is_string ())
246  {
247  std::string arg = args(pos).string_value ();
248  if (arg == "in")
249  {
250  token = dbstop_in;
251  pos++;
252  }
253  else if (arg == "at")
254  {
255  token = dbstop_at;
256  pos++;
257  }
258  else if (arg == "if")
259  {
260  token = dbstop_if;
261  pos++;
262  }
263  else if (atoi (args(pos).string_value ().c_str ()) > 0)
264  token = dbstop_at;
265  else
266  token = dbstop_in;
267  }
268  else
269  token = dbstop_at;
270 
271  if (pos >= nargin)
272  error ("%s: '%s' missing argument", who,
273  ( token == dbstop_in ? "in" :
274  (token == dbstop_at ? "at" : "if")));
275 
276  // process the actual arguments
277  switch (token)
278  {
279  case dbstop_in:
280  symbol_name = args(pos).string_value ();
281  if (seen_in)
282  error ("%s: Too many function names specified -- %s",
283  who, symbol_name.c_str ());
284  else if (seen_at || seen_if)
285  error ("%s: function name must come before line number and 'if'",
286  who);
287  seen_in = true;
288  pos++;
289  break;
290 
291  case dbstop_at:
292  if (seen_at)
293  error ("%s: Only one 'at' clause is allowed -- %s",
294  who, args(pos).string_value ().c_str ());
295  else if (seen_if)
296  error ("%s: line number must come before 'if' clause\n");
297  seen_at = true;
298 
299  if (! seen_in)
300  {
301  // It was a line number. Get function name from debugger.
302  if (Vdebugging)
303  symbol_name = get_user_code ()->profiler_name ();
304  else
305  error ("%s: function name must come before line number "
306  "and 'if'", who);
307  seen_in = true;
308  }
309  else if (seen_if)
310  error ("%s: line number must come before 'if' clause\n");
311 
312  // Read a list of line numbers (or arrays thereof)
313  for ( ; pos < nargin; pos++)
314  {
315  if (args(pos).is_string ())
316  {
317  int line = atoi (args(pos).string_value ().c_str ());
318 
319  if (line > 0)
320  lines[list_idx++] = line;
321  else
322  break; // may be "if"
323  }
324  else if (args(pos).is_numeric_type ())
325  {
326  const NDArray arg = args(pos).array_value ();
327 
328  for (octave_idx_type j = 0; j < arg.numel (); j++)
329  lines[list_idx++] = static_cast<int> (arg.elem (j));
330  }
331  else
332  error ("%s: Invalid argument type %s",
333  args(pos).type_name ().c_str ());
334  }
335  break;
336 
337  case dbstop_if:
338  if (seen_in) // conditional breakpoint
339  {
340  cond = ""; // remaining arguments form condition
341  for (; pos < nargin; pos++)
342  {
343  if (args(pos).is_string ())
344  cond = cond + " " + args(pos).string_value ();
345  else
346  error ("%s: arguments to 'if' must all be strings", who);
347  }
348 
349  cond = cond.substr (1); // omit initial space
350  }
351  else // stop on event (error, warning, interrupt, NaN/inf)
352  {
353  std::string condition = args(pos).string_value ();
354  int on_off = ! strcmp(who, "dbstop");
355 
356  // list of error/warning IDs to update
357  std::set<std::string> *id_list = NULL;
358  bool *stop_flag = NULL; // Vdebug_on_... flag
359 
360  if (condition == "error")
361  {
362  id_list = &bp_table::errors_that_stop;
363  stop_flag = &Vdebug_on_error;
364  }
365  else if (condition == "warning")
366  {
367  id_list = &bp_table::warnings_that_stop;
368  stop_flag = &Vdebug_on_warning;
369  }
370  else if (condition == "caught" && nargin > pos+1
371  && args(pos+1).string_value () == "error")
372  {
373  id_list = &bp_table::caught_that_stop;
374  stop_flag = &Vdebug_on_caught;
375  pos++;
376  }
377  else if (condition == "interrupt")
378  {
380  }
381  else if (condition == "naninf")
382 #if defined (DBSTOP_NANINF)
383  {
384  Vdebug_on_naninf = on_off;
385  enable_fpe (on_off);
386  }
387 #else
388  warning ("%s: condition '%s' not yet supported",
389  who, condition.c_str ());
390 #endif
391  else
392  error ("%s: invalid condition %s",
393  who, condition.c_str ());
394 
395  // process ID list for "dbstop if error <error_ID>" etc
396  if (id_list != NULL)
397  {
398  pos++;
399  if (pos < nargin) // only affect a single error ID
400  {
401  if (! args(pos).is_string () || nargin > pos+1)
402  error ("%s: ID must be a single string", who);
403  else if (on_off == 1)
404  {
405  id_list->insert (args(pos).string_value ());
406  *stop_flag = 1;
407  }
408  else
409  {
410  id_list->erase (args(pos).string_value ());
411  if (id_list->empty ())
412  *stop_flag = 0;
413  }
414  }
415  else // unqualified. Turn all on or off
416  {
417  id_list->clear ();
418  *stop_flag = on_off;
419  if (stop_flag == &Vdebug_on_error)
420  {
421  // Matlab stops on both.
423  }
424  }
425  }
426 
427  pos = nargin;
428  }
429  break;
430 
431  default: // dbstop_none should never occur
432  break;
433  }
434  }
435 }
436 
437 /*
438 %!test
439 %! dbclear all; # Clear out breakpoints before test
440 %! dbstop help;
441 %! dbstop in ls;
442 %! dbstop help at 100;
443 %! dbstop in ls 100;
444 %! dbstop help 201 if a==5;
445 %! dbstop if error Octave:undefined-function;
446 %! s = dbstatus;
447 %! dbclear all;
448 %! assert ({s.bkpt(:).name}, {"help", "help", "help>do_contents", "ls", "ls"});
449 %! assert ([s.bkpt(:).line], [48, 100, 201, 58, 100]);
450 %! assert (s.errs, {"Octave:undefined-function"});
451 */
452 
453 // Return true if there is a valid breakpoint table, false otherwise.
454 // If no table exists, one is created; false is only returned if this fails.
455 bool
457 {
458  if (! instance)
459  {
460  instance = new bp_table ();
461 
462  if (instance)
464  }
465 
466  if (! instance)
467  error ("unable to create breakpoint table!");
468 
469  return true;
470 }
471 
472 // Clear all reasons to stop, other than breakpoints
473 void
475 {
476  Vdebug_on_error = false;
477  bp_table::errors_that_stop.clear ();
478 
479  Vdebug_on_caught = false;
480  bp_table::caught_that_stop.clear ();
481 
482  Vdebug_on_warning = false;
483  bp_table::warnings_that_stop.clear ();
484 
486 }
487 
488 // Process the "warn", "errs", "caught" and "intr" fields for a call of
489 // "dbstop (p)".
490 void
492 {
493  // process errs
494  // why so many levels of indirection needed?
495  bool fail = false;
496  Cell U = mv.contents ("errs");
497  if (U.numel () != 1)
498  fail = (U.numel () > 1);
499  else
500  {
501  Array<octave_value> W = U.index (static_cast<octave_idx_type> (0));
502  if (W.is_empty () || W(0).is_empty () == 0)
503  Vdebug_on_error = 1; // like "dbstop if error" with no identifier
504  else if (! W(0).is_cell ())
505  fail = true;
506  else
507  {
508  Cell V = W(0).cell_value ();
509  for (int i = 0; i < V.numel (); i++)
510  {
511  errors_that_stop.insert (V(i).string_value ());
512  Vdebug_on_error = 1;
513  }
514  }
515  }
516  if (fail)
517  error ("dbstop: invalid 'errs' field");
518 
519  // process caught
520  // why so many levels of indirection needed?
521  fail = false;
522  U = mv.contents ("caught");
523  if (U.numel () != 1)
524  fail = (U.numel () > 1);
525  else
526  {
527  Array<octave_value> W = U.index (static_cast<octave_idx_type> (0));
528  if (W.is_empty () || W(0).is_empty ())
529  Vdebug_on_caught = 1; // like "dbstop if caught error" with no ID
530  else if (! W(0).is_cell ())
531  fail = true;
532  else
533  {
534  Cell V = W(0).cell_value ();
535  for (int i = 0; i < V.numel (); i++)
536  {
537  caught_that_stop.insert (V(i).string_value ());
538  Vdebug_on_caught = 1;
539  }
540  }
541  }
542  if (fail)
543  error ("dbstop: invalid 'caught' field");
544 
545  // process warn
546  // why so many levels of indirection needed?
547  fail = false;
548  U = mv.contents ("warn");
549  if (U.numel () != 1)
550  fail = (U.numel () > 1);
551  else
552  {
553  Array<octave_value> W = U.index (static_cast<octave_idx_type> (0));
554  if (W.is_empty () || W(0).is_empty ())
555  Vdebug_on_warning = 1; // like "dbstop if warning" with no identifier
556  else if (! W(0).is_cell ())
557  fail = true;
558  else
559  {
560  Cell V = W(0).cell_value ();
561  for (int i = 0; i < V.numel (); i++)
562  {
563  warnings_that_stop.insert (V(i).string_value ());
564  Vdebug_on_warning = 1;
565  }
566  }
567  }
568  if (fail)
569  error ("dbstop: invalid 'warn' field");
570 
571  // process interrupt
572  if (mv.isfield ("intr"))
574 }
575 
576 // Insert a breakpoint in function fcn at line within file fname,
577 // to stop only when condition is true.
578 // Record in bp_set that fname contains a breakpoint.
579 bool
581  const std::string& fname,
582  const bp_table::intmap& line,
583  const std::string& condition,
585 {
586  bool found = false;
587 
588  tree_statement_list *cmds = fcn->body ();
589 
590  std::string file = fcn->fcn_file_name ();
591 
592  if (cmds)
593  {
594  retval = cmds->add_breakpoint (file, line, condition);
595 
596  for (auto& idx_line_p : retval)
597  {
598  if (idx_line_p.second != 0)
599  {
600  // Normalize to store only the file name.
601  // Otherwise, there can be an entry for both file>subfunction and
602  // file, which causes a crash on dbclear all
603  const char *s = strchr (fname.c_str (), Vfilemarker);
604  if (s)
605  bp_set.insert (fname.substr (0, s - fname.c_str ()));
606  else
607  bp_set.insert (fname);
608  found = true;
609  break;
610  }
611  }
612  }
613 
614  return found;
615 }
616 
617 // Cursory check that cond is a valid condition to use for a breakpoint.
618 // Currently allows conditions with side-effects, like 'y+=10' and 'y++';
619 // it is odd that the former is not flagged by "is_assignment_expression".
620 // Throws an exception if not valid.
621 bool
623 {
624  if (cond.length () > 0)
625  {
626  octave::parser parser (cond + " ;"); // ; to reject partial expr like "y=="
627  parser.reset ();
628  int parse_status = parser.run ();
629  if (parse_status)
630  error ("dbstop: Cannot parse condition '%s'", cond.c_str ());
631  else
632  {
633  tree_statement *stmt = 0;
634  if (! parser.stmt_list)
635  error ("dbstop: "
636  "condition is not empty, but has nothing to evaluate");
637  else
638  {
639  if (parser.stmt_list->length () == 1
640  && (stmt = parser.stmt_list->front ())
641  && stmt->is_expression ())
642  {
643  tree_expression *expr = stmt->expression ();
644  if (expr->is_assignment_expression ())
645  error ("dbstop: condition cannot be an assignment. "
646  "Did you mean '=='?");
647  }
648  else
649  error ("dbstop: condition must be an expression");
650  }
651  }
652  }
653  return true;
654 }
655 
656 // Return the sub/nested/main function of MAIN_FCN that contains
657 // line number LINENO of the source file.
658 // If END_LINE != 0, *END_LINE is set to last line of the returned function.
659 static octave_user_code*
660 find_fcn_by_line (octave_user_code *main_fcn, int lineno, int *end_line = 0)
661 {
663  octave_user_code *next_fcn = 0; // 1st function starting after lineno
664 
665  // Find innermost nested (or parent) function containing lineno.
666  int earliest_end = std::numeric_limits<int>::max ();
667 
668  std::map<std::string, octave_value> subfcns = main_fcn->subfunctions ();
669  for (const auto& str_val_p : subfcns)
670  {
671  if (str_val_p.second.is_user_function ())
672  {
673  auto *dbg_subfcn = str_val_p.second.user_function_value ();
674 
675  // Check if lineno is within dbg_subfcn.
676  // FIXME: we could break when beginning_line() > lineno,
677  // but that makes the code "fragile"
678  // if the order of walking subfcns changes,
679  // for a minor speed improvement in non-critical code.
680  if (dbg_subfcn->ending_line () < earliest_end
681  && dbg_subfcn->ending_line () >= lineno
682  && dbg_subfcn->beginning_line () <= lineno)
683  {
684  earliest_end = dbg_subfcn->ending_line ();
685  retval = find_fcn_by_line (dbg_subfcn, lineno, &earliest_end);
686  }
687 
688  // Find the first fcn starting after lineno.
689  // This is used if line is not inside any function.
690  if (dbg_subfcn->beginning_line () >= lineno && ! next_fcn)
691  next_fcn = dbg_subfcn;
692  }
693  }
694 
695  // The breakpoint is either in the subfunction found above,
696  // or in the main function, which we check now.
697  if (main_fcn->is_user_function ())
698  {
699  int e = dynamic_cast<octave_user_function*> (main_fcn)->ending_line ();
700  if (e >= lineno && e < earliest_end)
701  retval = main_fcn;
702 
703  if (! retval)
704  retval = next_fcn;
705  }
706  else // main_fcn is a script.
707  {
708  if (! retval)
709  retval = main_fcn;
710  }
711 
712  if (end_line != 0 && earliest_end < *end_line)
713  *end_line = earliest_end;
714 
715  return retval;
716 }
717 
718 // Given file name fname, find the subfunction at line and create
719 // a breakpoint there. Put the system into debug_mode.
722  const bp_table::intmap& line,
723  const std::string& condition)
724 {
725  octave_user_code *main_fcn = get_user_code (fname);
726 
727  if (! main_fcn)
728  error ("add_breakpoint: unable to find function '%s'\n", fname.c_str ());
729 
730  condition_valid (condition); // Throw error if condition not valid.
731 
732  intmap retval;
733 
734  octave_idx_type len = line.size ();
735 
736  for (int i = 0; i < len; i++)
737  {
738  const_intmap_iterator m = line.find (i);
739 
740  if (m != line.end ())
741  {
742  int lineno = m->second;
743 
744  octave_user_code *dbg_fcn = find_fcn_by_line (main_fcn, lineno);
745 
746  // We've found the right (sub)function. Now insert the breakpoint.
747  // We insert all breakpoints.
748  // If multiple are in the same function, we insert multiple times.
749  intmap ret_one;
750  if (dbg_fcn
751  && do_add_breakpoint_1 (dbg_fcn, fname, line, condition, ret_one))
752  retval.insert (std::pair<int,int> (i, ret_one.find (i)->second));
753  }
754  }
755 
757  || Vdebugging;
758 
759  return retval;
760 }
761 
762 int
764  const std::string& fname,
765  const bp_table::intmap& line)
766 {
767  int retval = 0;
768 
769  std::string file = fcn->fcn_file_name ();
770 
771  tree_statement_list *cmds = fcn->body ();
772 
773  // FIXME: move the operation on cmds to the tree_statement_list class?
774 
775  if (cmds)
776  {
777  octave_value_list results = cmds->list_breakpoints ();
778 
779  if (results.length () > 0)
780  {
781  octave_idx_type len = line.size ();
782 
783  for (int i = 0; i < len; i++)
784  {
785  const_intmap_iterator p = line.find (i);
786 
787  if (p != line.end ())
788  {
789  int lineno = p->second;
790 
791  cmds->delete_breakpoint (lineno);
792 
793  if (! file.empty ())
794  octave_link::update_breakpoint (false, file, lineno);
795  }
796  }
797 
798  results = cmds->list_breakpoints ();
799 
800  bp_set_iterator it = bp_set.find (fname);
801  if (results.empty () && it != bp_set.end ())
802  bp_set.erase (it);
803  }
804 
805  retval = results.length ();
806  }
807 
808  return retval;
809 }
810 
811 int
813  const bp_table::intmap& line)
814 {
815  int retval = 0;
816 
817  octave_idx_type len = line.size ();
818 
819  if (len == 0)
820  {
821  intmap results = remove_all_breakpoints_in_file (fname);
822  retval = results.size ();
823  }
824  else
825  {
826  octave_user_code *dbg_fcn = get_user_code (fname);
827 
828  if (! dbg_fcn)
829  error ("remove_breakpoint: unable to find function %s\n",
830  fname.c_str ());
831 
832  retval = do_remove_breakpoint_1 (dbg_fcn, fname, line);
833 
834  // Search subfunctions in the order they appear in the file.
835 
836  const std::list<std::string> subfcn_names
837  = dbg_fcn->subfunction_names ();
838 
839  std::map<std::string, octave_value> subfcns
840  = dbg_fcn->subfunctions ();
841 
842  for (const auto& subf_nm : subfcn_names)
843  {
844  const auto q = subfcns.find (subf_nm);
845 
846  if (q != subfcns.end ())
847  {
848  octave_user_code *dbg_subfcn = q->second.user_code_value ();
849 
850  retval += do_remove_breakpoint_1 (dbg_subfcn, fname, line);
851  }
852  }
853  }
854 
856  || Vdebugging;
857 
858  return retval;
859 }
860 
861 // Remove all breakpoints from a file, including those in subfunctions
864  bool silent)
865 {
866  intmap retval;
867 
868  octave_user_code *dbg_fcn = get_user_code (fname);
869 
870  if (dbg_fcn)
871  {
872  std::string file = dbg_fcn->fcn_file_name ();
873 
874  tree_statement_list *cmds = dbg_fcn->body ();
875 
876  if (cmds)
877  {
878  retval = cmds->remove_all_breakpoints (file);
879 
880  bp_set_iterator it = bp_set.find (fname);
881  if (it != bp_set.end ())
882  bp_set.erase (it);
883  }
884  }
885  else if (! silent)
886  error ("remove_all_breakpoint_in_file: "
887  "unable to find function %s\n", fname.c_str ());
888 
890  || Vdebugging;
891 
892  return retval;
893 }
894 
895 void
897 {
898  // Odd loop structure required because delete will invalidate bp_set iterators
899  for (const_bp_set_iterator it=bp_set.begin (), it_next=it;
900  it != bp_set.end ();
901  it=it_next)
902  {
903  ++it_next;
905  }
906 
908  || Vdebugging;
909 }
910 
913 {
915 
916  for (int i = 0; i < slist.length (); i++)
917  {
918  if (slist(i).string_value () == match)
919  {
920  retval = slist(i).string_value ();
921  break;
922  }
923  }
924 
925  return retval;
926 }
927 
930 {
932 
933  // make copy since changes may invalidate iters of bp_set.
934  std::set<std::string> tmp_bp_set = bp_set;
935 
936  for (auto& bp_fname : tmp_bp_set)
937  {
938  if (fname_list.empty ()
939  || do_find_bkpt_list (fname_list, bp_fname) != "")
940  {
941  octave_user_code *f = get_user_code (bp_fname);
942 
943  if (f)
944  {
945  tree_statement_list *cmds = f->body ();
946 
947  // FIXME: move the operation on cmds to the
948  // tree_statement_list class?
949  if (cmds)
950  {
951  std::list<bp_type> bkpts = cmds->breakpoints_and_conds ();
952 
953  if (! bkpts.empty ())
954  retval[bp_fname] = bkpts;
955  }
956 
957  // look for breakpoints in subfunctions
958  const std::list<std::string> subf_nm = f->subfunction_names ();
959 
960  std::map<std::string, octave_value> subf = f->subfunctions ();
961 
962  for (const auto& subfcn_nm : subf_nm)
963  {
964  const auto q = subf.find (subfcn_nm);
965 
966  if (q != subf.end ())
967  {
968  octave_user_code *ff = q->second.user_code_value ();
969 
970  cmds = ff->body ();
971  if (cmds)
972  {
973  std::list<bp_type> bkpts
974  = cmds->breakpoints_and_conds ();
975 
976  if (! bkpts.empty ())
977  retval[bp_fname + Vfilemarker + ff->name ()] = bkpts;
978  }
979  }
980  }
981  }
982  }
983  }
984 
985  return retval;
986 }
987 
988 static octave_value
990 {
991  int idx = 0;
992 
993  NDArray retval (dim_vector (1, line.size ()));
994 
995  for (size_t i = 0; i < line.size (); i++)
996  {
997  bp_table::const_intmap_iterator p = line.find (i);
998 
999  if (p != line.end ())
1000  {
1001  int lineno = p->second;
1002  retval(idx++) = lineno;
1003  }
1004  }
1005 
1006  retval.resize (dim_vector (1, idx));
1007 
1008  return retval;
1009 }
1010 
1011 DEFUN (dbstop, args, ,
1012  doc: /* -*- texinfo -*-
1013 @deftypefn {} {} dbstop @var{func}
1014 @deftypefnx {} {} dbstop @var{func} @var{line}
1015 @deftypefnx {} {} dbstop @var{func} @var{line1} @var{line2} @dots{}
1016 @deftypefnx {} {} dbstop @var{line1} @dots{}
1017 @deftypefnx {} {} dbstop in @var{func}
1018 @deftypefnx {} {} dbstop in @var{func} at @var{line}
1019 @deftypefnx {} {} dbstop in @var{func} at @var{line} if "@var{condition}"
1020 @deftypefnx {} {} dbstop if @var{event}
1021 @deftypefnx {} {} dbstop if @var{event} @var{ID}
1022 @deftypefnx {} {} dbstop (@var{bp_struct})
1023 @deftypefnx {} {@var{rline} =} dbstop @dots{}
1024 
1025 Set breakpoints for the built-in debugger.
1026 
1027 @var{func} is the name of a function on the current @code{path}. When
1028 already in debug mode the @var{func} argument can be omitted and the current
1029 function will be used. Breakpoints at subfunctions are set with the scope
1030 operator @samp{>}. For example, If @file{file.m} has a subfunction
1031 @code{func2}, then a breakpoint in @code{func2} can be specified by
1032 @code{file>func2}.
1033 
1034 @var{line} is the line number at which to break. If @var{line} is not
1035 specified, it defaults to the first executable line in the file
1036 @file{func.m}. Multiple lines can be specified in a single command; when
1037 function syntax is used, the lines may also be passed as a single vector
1038 argument (@code{[@var{line1}, @var{line2}, @dots{}]}).
1039 
1040 @var{condition} is any Octave expression that can be evaluated in the code
1041 context that exists at the breakpoint. When the breakpoint is encountered,
1042 @var{condition} will be evaluated, and execution will stop if
1043 @var{condition} is true. If @var{condition} cannot be evaluated, for
1044 example because it refers to an undefined variable, an error will be thrown.
1045  Expressions with side effects (such as @code{y++ > 1}) will alter
1046 variables, and should generally be avoided. Conditions containing quotes
1047 (@samp{"}, @samp{'}) or comment characters (@samp{#}, @samp{%}) must be
1048 enclosed in quotes. (This does not apply to conditions entered from the
1049 editor's context menu.) For example:
1050 
1051 @example
1052 dbstop in strread at 209 if 'any (format == "%f")'
1053 @end example
1054 
1055 The form specifying @var{event} does not cause a specific breakpoint at a
1056 given function and line number. Instead it causes debug mode to be entered
1057 when certain unexpected events are encountered. Possible values are
1058 
1059 @table @code
1060 @item error
1061 Stop when an error is reported. This is equivalent to specifying
1062 both @code{debug_on_error (true)} and @code{debug_on_interrupt (true)}.
1063 
1064 @item caught error
1065 Stop when an error is caught by a try-catch block (not yet implemented).
1066 
1067 @item interrupt
1068 Stop when an interrupt (@kbd{Ctrl-C}) occurs.
1069 
1070 @item naninf
1071 Stop when code returns a non-finite value (not yet implemented).
1072 
1073 @item warning
1074 Stop when a warning is reported. This is equivalent to specifying
1075 @code{debug_on_warning (true)}.
1076 @end table
1077 
1078 The events @code{error}, @code{caught error}, and @code{warning} can all be
1079 followed by a string specifying an error ID or warning ID@. If that is
1080 done, only errors with the specified ID will cause execution to stop. To
1081 stop on one of a set of IDs, multiple @code{dbstop} commands must be
1082 issued.
1083 
1084 Breakpoints and events can be removed using the @code{dbclear} command with
1085 the same syntax.
1086 
1087 It is possible to save all breakpoints and restore them at once by issuing
1088 the commands @code{bp_state = dbstatus; @dots{}; dbstop (bp_state)}.
1089 
1090 The optional output @var{rline} is the real line number where the breakpoint
1091 was set. This can differ from the specified line if the line is not
1092 executable. For example, if a breakpoint attempted on a blank line then
1093 Octave will set the real breakpoint at the next executable line.
1094 
1095 When a file is re-parsed, such as when it is modified outside the GUI,
1096 all breakpoints within the file are cleared.
1097 
1098 @seealso{dbclear, dbstatus, dbstep, debug_on_error, debug_on_warning, debug_on_interrupt}
1099 @end deftypefn */)
1100 {
1101  bp_table::intmap retmap;
1102  std::string symbol_name = ""; // stays empty for "dbstop if error" etc
1103  bp_table::intmap lines;
1104  std::string condition = "";
1106 
1107  if (args.length() >= 1 && ! args(0).is_map ())
1108  {
1109  // explicit function / line / condition
1110  parse_dbfunction_params ("dbstop", args, symbol_name, lines, condition);
1111 
1112  if (lines.size () == 0)
1113  lines[0] = 1;
1114 
1115  if (symbol_name != "")
1116  {
1117  retmap = bp_table::add_breakpoint (symbol_name, lines, condition);
1118  retval = intmap_to_ov (retmap);
1119  }
1120  }
1121  else if (args.length () != 1)
1122  {
1123  print_usage ();
1124  }
1125  else // structure of the form output by dbstatus
1126  {
1127  octave_map mv = args(0).map_value ();
1128  if (mv.isfield ("bkpt") || mv.isfield ("errs") || mv.isfield ("warn")
1129  || mv.isfield ("intr"))
1130  {
1132 
1133  // Replace mv by "bkpt", to use the processing below.
1134  octave_value bkpt = mv.getfield ("bkpt");
1135  if (bkpt.is_empty ())
1136  mv = octave_map ();
1137  else
1138  {
1139  if (bkpt.is_cell () && bkpt.cell_value ().numel () > 0
1140  && bkpt.cell_value () (0).is_map ())
1141  mv = bkpt.cell_value () (0).map_value ();
1142  else
1143  {
1144  error ("dbstop: invalid 'bkpt' field");
1145  mv = octave_map ();
1146  }
1147  }
1148  }
1149  if (mv.is_empty ())
1150  {
1151  // no changes requested. Occurs if "errs" non-empty but "bkpt" empty
1152  }
1153  else if (! mv.isfield ("name") || ! mv.isfield ("line"))
1154  {
1155  error ("dbstop: Cell array must contain fields 'name' and 'line'");
1156  retval = octave_value (0);
1157  }
1158  else
1159  {
1160  bool use_cond = mv.isfield ("cond");
1161  Cell name = mv.getfield ("name");
1162  Cell line = mv.getfield ("line");
1163  Cell cond = (use_cond ? mv.getfield ("cond") : Cell ());
1164  std::string unconditional = "";
1165  for (octave_idx_type i = 0; i < line.numel (); i++)
1166  {
1167  lines [0] = line(i).double_value ();
1168  bp_table::add_breakpoint (name(i).string_value (), lines,
1169  use_cond ? cond(i).string_value ()
1170  : unconditional );
1171  }
1172  retval = octave_value (line.numel ());
1173  }
1174  }
1175 
1176  return retval;
1177 }
1178 
1179 DEFUN (dbclear, args, ,
1180  doc: /* -*- texinfo -*-
1181 @deftypefn {} {} dbclear @var{func}
1182 @deftypefnx {} {} dbclear @var{func} @var{line}
1183 @deftypefnx {} {} dbclear @var{func} @var{line1} @var{line2} @dots{}
1184 @deftypefnx {} {} dbclear @var{line} @dots{}
1185 @deftypefnx {} {} dbclear all
1186 @deftypefnx {} {} dbclear in @var{func}
1187 @deftypefnx {} {} dbclear in @var{func} at @var{line}
1188 @deftypefnx {} {} dbclear if @var{event}
1189 @deftypefnx {} {} dbclear ("@var{func}")
1190 @deftypefnx {} {} dbclear ("@var{func}", @var{line})
1191 @deftypefnx {} {} dbclear ("@var{func}", @var{line1}, @var{line2}, @dots{})
1192 @deftypefnx {} {} dbclear ("@var{func}", @var{line1}, @dots{})
1193 @deftypefnx {} {} dbclear (@var{line}, @dots{})
1194 @deftypefnx {} {} dbclear ("all")
1195 Delete a breakpoint at line number @var{line} in the function @var{func}.
1196 
1197 Arguments are
1198 
1199 @table @var
1200 @item func
1201 Function name as a string variable. When already in debug mode this
1202 argument can be omitted and the current function will be used.
1203 
1204 @item line
1205 Line number from which to remove a breakpoint. Multiple lines may be given
1206 as separate arguments or as a vector.
1207 
1208 @item event
1209 An event such as @code{error}, @code{interrupt}, or @code{warning}
1210 (@pxref{XREFdbstop,,dbstop} for details).
1211 @end table
1212 
1213 When called without a line number specification all breakpoints in the named
1214 function are cleared.
1215 
1216 If the requested line is not a breakpoint no action is performed.
1217 
1218 The special keyword @qcode{"all"} will clear all breakpoints from all
1219 files.
1220 @seealso{dbstop, dbstatus, dbwhere}
1221 @end deftypefn */)
1222 {
1223  std::string symbol_name = ""; // stays empty for "dbclear if error" etc
1224  bp_table::intmap lines;
1225  std::string dummy; // "if" condition -- only used for dbstop
1226 
1227  int nargin = args.length ();
1228 
1229  parse_dbfunction_params ("dbclear", args, symbol_name, lines, dummy);
1230 
1231  if (nargin == 1 && symbol_name == "all")
1232  {
1235  }
1236  else
1237  {
1238  if (symbol_name != "")
1239  bp_table::remove_breakpoint (symbol_name, lines);
1240  }
1241 
1242  return ovl ();
1243 }
1244 
1245 // Report the status of "dbstop if error ..." and "dbstop if warning ..."
1246 // If to_screen is true, the output goes to octave_stdout; otherwise it is
1247 // returned.
1248 // If dbstop if error is true but no explicit IDs are specified, the return
1249 // value will have an empty field called "errs". If IDs are specified, the
1250 // "errs" field will have a row per ID. If dbstop if error is false, there
1251 // is no "errs" field. The "warn" field is set similarly by dbstop if warning
1252 octave_map
1253 bp_table::stop_on_err_warn_status (bool to_screen)
1254 {
1256 
1257  // print dbstop if error information
1258  if (Vdebug_on_error)
1259  {
1260  if (errors_that_stop.empty ())
1261  {
1262  if (to_screen)
1263  octave_stdout << "stop if error\n";
1264  else
1265  retval.assign ("errs", octave_value(""));
1266  }
1267  else
1268  {
1269  Cell errs (dim_vector (bp_table::errors_that_stop.size (), 1));
1270  int i = 0;
1271 
1272  for (const auto& e : errors_that_stop)
1273  {
1274  if (to_screen)
1275  octave_stdout << "stop if error " << e << "\n";
1276  else
1277  errs(i++) = e;
1278  }
1279  if (! to_screen)
1280  retval.assign ("errs", octave_value (errs));
1281  }
1282  }
1283 
1284  // print dbstop if caught error information
1285  if (Vdebug_on_caught)
1286  {
1287  if (caught_that_stop.empty ())
1288  {
1289  if (to_screen)
1290  octave_stdout << "stop if caught error\n";
1291  else
1292  retval.assign ("caught", octave_value(""));
1293  }
1294  else
1295  {
1296  Cell errs (dim_vector (caught_that_stop.size (), 1));
1297  int i = 0;
1298 
1299  for (const auto& e : caught_that_stop)
1300  {
1301  if (to_screen)
1302  octave_stdout << "stop if caught error " << e << "\n";
1303  else
1304  errs(i++) = e;
1305  }
1306  if (! to_screen)
1307  retval.assign ("caught", octave_value (errs));
1308  }
1309  }
1310 
1311  // print dbstop if warning information
1312  if (Vdebug_on_warning)
1313  {
1314  if (warnings_that_stop.empty ())
1315  {
1316  if (to_screen)
1317  octave_stdout << "stop if warning\n";
1318  else
1319  retval.assign ("warn", octave_value(""));
1320  }
1321  else
1322  {
1323  Cell warn (dim_vector (warnings_that_stop.size (), 1));
1324  int i = 0;
1325 
1326  for (const auto& w : warnings_that_stop)
1327  {
1328  if (to_screen)
1329  octave_stdout << "stop if warning " << w << "\n";
1330  else
1331  warn(i++) = w;
1332  }
1333  if (! to_screen)
1334  retval.assign ("warn", octave_value (warn));
1335  }
1336  }
1337 
1338  // print dbstop if interrupt information
1340  {
1341  if (to_screen)
1342  octave_stdout << "stop if interrupt\n";
1343  else
1344  retval.assign ("intr", octave_value ());
1345  }
1346 
1347  return retval;
1348 }
1349 
1350 DEFUN (dbstatus, args, nargout,
1351  doc: /* -*- texinfo -*-
1352 @deftypefn {} {} dbstatus
1353 @deftypefnx {} {} dbstatus @var{func}
1354 @deftypefnx {} {@var{bp_list} =} dbstatus @dots{}
1355 Report the location of active breakpoints.
1356 
1357 When called with no input or output arguments, print the list of all
1358 functions with breakpoints and the line numbers where those breakpoints are
1359 set.
1360 
1361 If a function name @var{func} is specified then only report breakpoints
1362 for the named function and its subfunctions.
1363 
1364 The optional return argument @var{bp_list} is a struct array with the
1365 following fields.
1366 
1367 @table @asis
1368 @item name
1369 The name of the function with a breakpoint. A subfunction, say @code{func2}
1370 within an m-file, say @file{file.m}, is specified as @code{file>func2}.
1371 
1372 @item file
1373 The name of the m-file where the function code is located.
1374 
1375 @item line
1376 The line number with the breakpoint.
1377 
1378 @item cond
1379 The condition that must be satisfied for the breakpoint to be active, or
1380 the empty string for unconditional breakpoints.
1381 @end table
1382 
1383 @c Note: When @code{dbstatus} is called from the debug prompt within a function,
1384 @c the list of breakpoints is automatically trimmed to the breakpoints in the
1385 @c current function.
1386 If @code{dbstop if error} is true but no explicit IDs are specified, the
1387 return value will have an empty field called @qcode{"errs"}. If IDs are
1388 specified, the @code{errs} field will have one row per ID@. If
1389 @code{dbstop if error} is false, there is no @qcode{"errs"} field.
1390 The @qcode{"warn"} field is set similarly by @code{dbstop if warning}.
1391 
1392 @seealso{dbstop, dbclear, dbwhere, dblist, dbstack}
1393 @end deftypefn */)
1394 {
1395  int nargin = args.length ();
1396 
1397  if (nargin != 0 && nargin != 1)
1398  error ("dbstatus: only zero or one arguments accepted\n");
1399 
1400  octave_value_list fcn_list;
1401  bp_table::fname_bp_map bp_list;
1402  std::string symbol_name;
1403 
1404  if (nargin == 1)
1405  {
1406  if (! args(0).is_string ())
1407  err_wrong_type_arg ("dbstatus", args(0));
1408 
1409  symbol_name = args(0).string_value ();
1410  fcn_list(0) = symbol_name;
1411  bp_list = bp_table::get_breakpoint_list (fcn_list);
1412  }
1413  else
1414  {
1415 /*
1416  if (Vdebugging)
1417  {
1418  octave_user_code *dbg_fcn = get_user_code ();
1419  if (dbg_fcn)
1420  {
1421  symbol_name = dbg_fcn->name ();
1422  fcn_list(0) = symbol_name;
1423  }
1424  }
1425 */
1426 
1427  bp_list = bp_table::get_breakpoint_list (fcn_list);
1428  }
1429 
1430  if (nargout == 0)
1431  {
1432  // Print out the breakpoint information.
1433 
1434  for (auto& fnm_bp_p: bp_list)
1435  {
1436  std::list<bp_type> m = fnm_bp_p.second;
1437 
1438  // print unconditional breakpoints, if any, on a single line
1439 
1440  // first, check to see if there are any
1441  int have_unconditional = 0;
1442  for (const auto& bp : m)
1443  {
1444  if (bp.cond == "")
1445  {
1446  if (have_unconditional++)
1447  break; // stop once we know its plural
1448  }
1449  }
1450  // If we actually have some, print line numbers only
1451  if (have_unconditional)
1452  {
1453  const char *_s_ = (have_unconditional > 1) ? "s" : "";
1454  octave_stdout << "breakpoint" << _s_ <<" in " << fnm_bp_p.first
1455  << " at line" << _s_ << " ";
1456 
1457  for (const auto& bp : m)
1458  {
1459  if (bp.cond == "")
1460  octave_stdout << bp.line << " ";
1461  }
1462  octave_stdout << std::endl;
1463  }
1464 
1465  // print conditional breakpoints, one per line, with conditions
1466  for (const auto& bp : m)
1467  {
1468  if (bp.cond != "")
1469  octave_stdout << "breakpoint in " << fnm_bp_p.first
1470  << " at line " << bp.line
1471  << " if " << bp.cond << "\n";
1472  }
1473  }
1474 
1476 
1477  return ovl ();
1478  }
1479  else
1480  {
1481  // Fill in an array for return.
1482  int i = 0;
1483  octave_map retmap;
1485 
1486  // count the number of breakpoints in all files
1487  int count = 0;
1488  for (const auto& fnm_bp_p : bp_list)
1489  count += fnm_bp_p.second.size ();
1490 
1491  Cell names (dim_vector (count, 1));
1492  Cell file (dim_vector (count, 1));
1493  Cell line (dim_vector (count, 1));
1494  Cell cond (dim_vector (count, 1));
1495 
1496  for (const auto& fnm_bp_p : bp_list)
1497  {
1498  std::string filename = fnm_bp_p.first;
1499  const char *sub_fun = strchr (filename.c_str (), Vfilemarker);
1500  if (sub_fun)
1501  filename = filename.substr(0, sub_fun - filename.c_str ());
1502  octave_value path_name;
1503  path_name = octave::sys::canonicalize_file_name (do_which (filename));
1504 
1505  for (const auto& bp : fnm_bp_p.second)
1506  {
1507  names(i) = fnm_bp_p.first;
1508  file(i) = path_name;
1509  line(i) = octave_value (bp.line);
1510  cond(i) = octave_value (bp.cond);
1511  i++;
1512  }
1513  }
1514 
1515  retmap.assign ("name", names);
1516  retmap.assign ("file", file);
1517  retmap.assign ("line", line);
1518  retmap.assign ("cond", cond);
1519 
1521  if (ew.is_empty ())
1522  {
1523  retval = octave_value (retmap);
1524  }
1525  else
1526  {
1527  octave_map outer (dim_vector (3,1));
1528  outer.assign ("bkpt", Cell (retmap));
1529  for (octave_map::const_iterator f = ew.begin (); f != ew.end (); f++)
1530  outer.setfield (f->first, ew.contents (f));
1531 
1532  retval = octave_value (outer);
1533  }
1534 
1535  return retval;
1536  }
1537 }
1538 
1539 /*
1540 %!test
1541 %! dbclear all; # Clear out breakpoints before test
1542 %! dbstop @ftp/dir;
1543 %! dbstop @audioplayer/set 70;
1544 %! dbstop quantile>__quantile__;
1545 %! dbstop ls;
1546 %! s = dbstatus;
1547 %! dbclear all;
1548 %! assert (s(1).name, "@audioplayer/set>setproperty");
1549 %! assert (s(2).name, "@ftp/dir");
1550 %! assert (s(3).name, "ls");
1551 %! assert (s(4).name, "quantile>__quantile__");
1552 %! assert (s(2).file(end-10:end), [filesep "@ftp" filesep "dir.m"]);
1553 */
1554 
1555 DEFUN (dbwhere, , ,
1556  doc: /* -*- texinfo -*-
1557 @deftypefn {} {} dbwhere
1558 In debugging mode, report the current file and line number where execution
1559 is stopped.
1560 @seealso{dbstack, dblist, dbstatus, dbcont, dbstep, dbup, dbdown}
1561 @end deftypefn */)
1562 {
1563  octave_user_code *dbg_fcn = get_user_code ();
1564 
1565  if (! dbg_fcn)
1566  {
1567  octave_stdout << "stopped at top level" << std::endl;
1568  return ovl ();
1569  }
1570 
1571  octave_stdout << "stopped in " << dbg_fcn->name () << " at ";
1572 
1574 
1575  if (l > 0)
1576  {
1577  octave_stdout << "line " << l;
1578 
1579  std::string file_name = dbg_fcn->fcn_file_name ();
1580 
1581  if (! file_name.empty ())
1582  {
1583  octave_stdout << " [" << file_name << "]" << std::endl;
1584 
1585  std::string line = get_file_line (file_name, l);
1586 
1587  if (! line.empty ())
1588  octave_stdout << l << ": " << line << std::endl;
1589  }
1590  else
1591  octave_stdout << std::endl;
1592  }
1593  else
1594  octave_stdout << "<unknown line>" << std::endl;
1595 
1596  return ovl ();
1597 }
1598 
1599 void
1600 do_dbtype (std::ostream& os, const std::string& name, int start, int end)
1601 {
1602  std::string ff = fcn_file_in_path (name);
1603 
1604  if (ff.empty ())
1605  os << "dbtype: unknown function " << name << "\n";
1606  else
1607  {
1608  std::ifstream fs (ff.c_str (), std::ios::in);
1609 
1610  if (! fs)
1611  os << "dbtype: unable to open '" << ff << "' for reading!\n";
1612  else
1613  {
1614  int line = 1;
1615  std::string text;
1616 
1617  while (std::getline (fs, text) && line <= end)
1618  {
1619  if (line >= start)
1620  os << line << "\t" << text << "\n";
1621 
1622  line++;
1623  }
1624  }
1625  }
1626 
1627  os.flush ();
1628 }
1629 
1630 DEFUN (dbtype, args, ,
1631  doc: /* -*- texinfo -*-
1632 @deftypefn {} {} dbtype
1633 @deftypefnx {} {} dbtype @var{lineno}
1634 @deftypefnx {} {} dbtype @var{startl:endl}
1635 @deftypefnx {} {} dbtype @var{startl:end}
1636 @deftypefnx {} {} dbtype @var{func}
1637 @deftypefnx {} {} dbtype @var{func} @var{lineno}
1638 @deftypefnx {} {} dbtype @var{func} @var{startl:endl}
1639 @deftypefnx {} {} dbtype @var{func} @var{startl:end}
1640 Display a script file with line numbers.
1641 
1642 When called with no arguments in debugging mode, display the script file
1643 currently being debugged.
1644 
1645 An optional range specification can be used to list only a portion of the
1646 file. The special keyword @qcode{"end"} is a valid line number
1647 specification for the last line of the file.
1648 
1649 When called with the name of a function, list that script file with line
1650 numbers.
1651 @seealso{dblist, dbwhere, dbstatus, dbstop}
1652 @end deftypefn */)
1653 {
1654  octave_user_code *dbg_fcn;
1655 
1656  string_vector argv = args.make_argv ("dbtype");
1657 
1658  switch (args.length ())
1659  {
1660  case 0: // dbtype
1661  dbg_fcn = get_user_code ();
1662 
1663  if (! dbg_fcn)
1664  error ("dbtype: must be inside a user function to give no arguments to dbtype\n");
1665 
1666  do_dbtype (octave_stdout, dbg_fcn->fcn_file_name (),
1668 
1669  break;
1670 
1671  case 1: // (dbtype start:end) || (dbtype func) || (dbtype lineno)
1672  {
1673  std::string arg = argv[1];
1674 
1675  size_t ind = arg.find (':');
1676 
1677  if (ind != std::string::npos) // (dbtype start:end)
1678  {
1679  dbg_fcn = get_user_code ();
1680 
1681  if (dbg_fcn)
1682  {
1683  std::string start_str = arg.substr (0, ind);
1684  std::string end_str = arg.substr (ind + 1);
1685 
1686  int start, end;
1687  start = atoi (start_str.c_str ());
1688  if (end_str == "end")
1690  else
1691  end = atoi (end_str.c_str ());
1692 
1693  if (std::min (start, end) <= 0)
1694  error ("dbtype: start and end lines must be >= 1\n");
1695 
1696  if (start > end)
1697  error ("dbtype: start line must be less than end line\n");
1698 
1699  do_dbtype (octave_stdout, dbg_fcn->fcn_file_name (),
1700  start, end);
1701  }
1702  }
1703  else // (dbtype func) || (dbtype lineno)
1704  {
1705  int line = atoi (arg.c_str ());
1706 
1707  if (line == 0) // (dbtype func)
1708  {
1709  dbg_fcn = get_user_code (arg);
1710 
1711  if (! dbg_fcn)
1712  error ("dbtype: function <%s> not found\n", arg.c_str ());
1713 
1714  do_dbtype (octave_stdout, dbg_fcn->fcn_file_name (),
1716  }
1717  else // (dbtype lineno)
1718  {
1719  if (line <= 0)
1720  error ("dbtype: start and end lines must be >= 1\n");
1721 
1722  dbg_fcn = get_user_code ();
1723 
1724  if (dbg_fcn)
1725  do_dbtype (octave_stdout, dbg_fcn->fcn_file_name (),
1726  line, line);
1727  }
1728  }
1729  }
1730  break;
1731 
1732  case 2: // (dbtype func start:end) || (dbtype func start)
1733  {
1734  dbg_fcn = get_user_code (argv[1]);
1735 
1736  if (! dbg_fcn)
1737  error ("dbtype: function <%s> not found\n", argv[1].c_str ());
1738 
1739  std::string arg = argv[2];
1740  int start, end;
1741  size_t ind = arg.find (':');
1742 
1743  if (ind != std::string::npos)
1744  {
1745  std::string start_str = arg.substr (0, ind);
1746  std::string end_str = arg.substr (ind + 1);
1747 
1748  start = atoi (start_str.c_str ());
1749  if (end_str == "end")
1751  else
1752  end = atoi (end_str.c_str ());
1753  }
1754  else
1755  {
1756  start = atoi (arg.c_str ());
1757  end = start;
1758  }
1759 
1760  if (std::min (start, end) <= 0)
1761  error ("dbtype: start and end lines must be >= 1\n");
1762 
1763  if (start > end)
1764  error ("dbtype: start line must be less than end line\n");
1765 
1766  do_dbtype (octave_stdout, dbg_fcn->fcn_file_name (), start, end);
1767  }
1768  break;
1769 
1770  default:
1771  error ("dbtype: expecting zero, one, or two arguments\n");
1772  }
1773 
1774  return ovl ();
1775 }
1776 
1777 DEFUN (dblist, args, ,
1778  doc: /* -*- texinfo -*-
1779 @deftypefn {} {} dblist
1780 @deftypefnx {} {} dblist @var{n}
1781 In debugging mode, list @var{n} lines of the function being debugged
1782 centered around the current line to be executed.
1783 
1784 If unspecified @var{n} defaults to 10 (+/- 5 lines)
1785 @seealso{dbwhere, dbtype, dbstack}
1786 @end deftypefn */)
1787 {
1788  int n = 10;
1789 
1790  if (args.length () == 1)
1791  {
1792  octave_value arg = args(0);
1793 
1794  if (arg.is_string ())
1795  {
1796  std::string s_arg = arg.string_value ();
1797 
1798  n = atoi (s_arg.c_str ());
1799  }
1800  else
1801  n = args(0).int_value ();
1802 
1803  if (n < 0)
1804  error ("dblist: N must be a non-negative integer");
1805  }
1806 
1807  octave_user_code *dbg_fcn = get_user_code ();
1808 
1809  if (! dbg_fcn)
1810  error ("dblist: must be inside a user function to use dblist\n");
1811 
1812  bool have_file = true;
1813 
1814  std::string name = dbg_fcn->fcn_file_name ();
1815 
1816  if (name.empty ())
1817  {
1818  have_file = false;
1819  name = dbg_fcn->name ();
1820  }
1821 
1823 
1824  if (l > 0)
1825  {
1826  if (have_file)
1827  {
1828  int l_min = std::max (l - n/2, 0);
1829  int l_max = l + n/2;
1830  do_dbtype (octave_stdout, name, l_min, l-1);
1831 
1832  std::string line = get_file_line (name, l);
1833  if (! line.empty ())
1834  octave_stdout << l << "-->\t" << line << std::endl;
1835 
1836  do_dbtype (octave_stdout, name, l+1, l_max);
1837  }
1838  }
1839  else
1840  {
1841  octave_stdout << "dblist: unable to determine source code line"
1842  << std::endl;
1843  }
1844 
1845  return ovl ();
1846 }
1847 
1848 static octave_value_list
1849 do_dbstack (const octave_value_list& args, int nargout, std::ostream& os)
1850 {
1851  int nargin = args.length ();
1852 
1853  if (nargin > 2)
1854  print_usage ();
1855 
1857 
1859 
1860  octave_idx_type curr_frame = -1;
1861 
1862  size_t nskip = 0;
1863 
1864  if (nargin == 1 || nargin == 2)
1865  {
1866  int n = 0;
1867 
1868  for (octave_idx_type i = 0; i < nargin; i++)
1869  {
1870  octave_value arg = args(i);
1871 
1872  if (arg.is_string ())
1873  {
1874  std::string s_arg = arg.string_value ();
1875 
1876  // Skip "-completenames", octave returns full names anyway.
1877  if (s_arg == "-completenames")
1878  continue;
1879 
1880  n = atoi (s_arg.c_str ());
1881  }
1882  else
1883  n = arg.int_value ();
1884 
1885  if (n <= 0)
1886  error ("dbstack: N must be a non-negative integer");
1887  }
1888 
1889  if (n > 0)
1890  nskip = n;
1891  }
1892 
1893  if (nargout == 0)
1894  {
1895  octave_map stk = octave_call_stack::backtrace (nskip, curr_frame);
1896  octave_idx_type nframes_to_display = stk.numel ();
1897 
1898  if (nframes_to_display > 0)
1899  {
1900  octave_preserve_stream_state stream_state (os);
1901 
1902  os << "stopped in:\n\n";
1903 
1904  Cell names = stk.contents ("name");
1905  Cell files = stk.contents ("file");
1906  Cell lines = stk.contents ("line");
1907 
1908  bool show_top_level = true;
1909 
1910  size_t max_name_len = 0;
1911 
1912  for (octave_idx_type i = 0; i < nframes_to_display; i++)
1913  {
1914  std::string name = names(i).string_value ();
1915 
1916  max_name_len = std::max (name.length (), max_name_len);
1917  }
1918 
1919  for (octave_idx_type i = 0; i < nframes_to_display; i++)
1920  {
1921  std::string name = names(i).string_value ();
1922  std::string file = files(i).string_value ();
1923  int line = lines(i).int_value ();
1924 
1925  if (show_top_level && i == curr_frame)
1926  show_top_level = false;
1927 
1928  os << (i == curr_frame ? " --> " : " ")
1929  << std::setw (max_name_len) << name
1930  << " at line " << line
1931  << " [" << file << "]"
1932  << std::endl;
1933  }
1934 
1935  if (show_top_level)
1936  os << " --> top level" << std::endl;
1937  }
1938  }
1939  else
1940  {
1941  octave_map stk = octave_call_stack::backtrace (nskip, curr_frame, false);
1942 
1943  retval = ovl (stk, curr_frame < 0 ? 1 : curr_frame + 1);
1944  }
1945 
1946  return retval;
1947 }
1948 
1949 // A function that can be easily called from a debugger print the Octave stack.
1950 // This can be useful for finding what line of code the interpreter is
1951 // currently executing when the debugger is stopped in some C++ function,
1952 // for example.
1953 
1954 void
1955 show_octave_dbstack (void)
1956 {
1957  do_dbstack (octave_value_list (), 0, std::cerr);
1958 }
1959 
1960 DEFUN (dbstack, args, nargout,
1961  doc: /* -*- texinfo -*-
1962 @deftypefn {} {} dbstack
1963 @deftypefnx {} {} dbstack @var{n}
1964 @deftypefnx {} {} dbstack @var{-completenames}
1965 @deftypefnx {} {[@var{stack}, @var{idx}] =} dbstack (@dots{})
1966 Display or return current debugging function stack information.
1967 
1968 With optional argument @var{n}, omit the @var{n} innermost stack frames.
1969 
1970 Although accepted, the argument @var{-completenames} is silently ignored.
1971 Octave always returns absolute filenames.
1972 
1973 The arguments @var{n} and @var{-completenames} can be both specified in any
1974 order.
1975 
1976 The optional return argument @var{stack} is a struct array with the
1977 following fields:
1978 
1979 @table @asis
1980 @item file
1981 The name of the m-file where the function code is located.
1982 
1983 @item name
1984 The name of the function with a breakpoint.
1985 
1986 @item line
1987 The line number of an active breakpoint.
1988 
1989 @item column
1990 The column number of the line where the breakpoint begins.
1991 
1992 @item scope
1993 Undocumented.
1994 
1995 @item context
1996 Undocumented.
1997 @end table
1998 
1999 The return argument @var{idx} specifies which element of the @var{stack}
2000 struct array is currently active.
2001 @seealso{dbup, dbdown, dbwhere, dblist, dbstatus}
2002 @end deftypefn */)
2003 {
2004  return do_dbstack (args, nargout, octave_stdout);
2005 }
2006 
2007 static void
2008 do_dbupdown (const octave_value_list& args, const std::string& who)
2009 {
2010  int n = 1;
2011 
2012  if (args.length () == 1)
2013  {
2014  octave_value arg = args(0);
2015 
2016  if (arg.is_string ())
2017  {
2018  std::string s_arg = arg.string_value ();
2019 
2020  n = atoi (s_arg.c_str ());
2021  }
2022  else
2023  n = args(0).int_value ();
2024  }
2025 
2026  if (who == "dbup")
2027  n = -n;
2028 
2030  error ("%s: invalid stack frame", who.c_str ());
2031 }
2032 
2033 DEFUN (dbup, args, ,
2034  doc: /* -*- texinfo -*-
2035 @deftypefn {} {} dbup
2036 @deftypefnx {} {} dbup @var{n}
2037 In debugging mode, move up the execution stack @var{n} frames.
2038 
2039 If @var{n} is omitted, move up one frame.
2040 @seealso{dbstack, dbdown}
2041 @end deftypefn */)
2042 {
2043  do_dbupdown (args, "dbup");
2044 
2045  return ovl ();
2046 }
2047 
2048 DEFUN (dbdown, args, ,
2049  doc: /* -*- texinfo -*-
2050 @deftypefn {} {} dbdown
2051 @deftypefnx {} {} dbdown @var{n}
2052 In debugging mode, move down the execution stack @var{n} frames.
2053 
2054 If @var{n} is omitted, move down one frame.
2055 @seealso{dbstack, dbup}
2056 @end deftypefn */)
2057 {
2058  do_dbupdown (args, "dbdown");
2059 
2060  return ovl ();
2061 }
2062 
2063 DEFUN (dbstep, args, ,
2064  doc: /* -*- texinfo -*-
2065 @deftypefn {} {} dbstep
2066 @deftypefnx {} {} dbstep @var{n}
2067 @deftypefnx {} {} dbstep in
2068 @deftypefnx {} {} dbstep out
2069 @deftypefnx {} {} dbnext @dots{}
2070 In debugging mode, execute the next @var{n} lines of code.
2071 
2072 If @var{n} is omitted, execute the next single line of code. If the next
2073 line of code is itself defined in terms of an m-file remain in the existing
2074 function.
2075 
2076 Using @code{dbstep in} will cause execution of the next line to step into
2077 any m-files defined on the next line.
2078 
2079 Using @code{dbstep out} will cause execution to continue until the current
2080 function returns.
2081 
2082 @code{dbnext} is an alias for @code{dbstep}.
2083 @seealso{dbcont, dbquit}
2084 @end deftypefn */)
2085 {
2086  if (! Vdebugging)
2087  error ("dbstep: can only be called in debug mode");
2088 
2089  int nargin = args.length ();
2090 
2091  if (nargin > 1)
2092  print_usage ();
2093 
2094  if (nargin == 1)
2095  {
2096  std::string arg = args(0).xstring_value ("dbstep: input argument must be a string");
2097 
2098  if (arg == "in")
2099  {
2100  Vdebugging = false;
2101  Vtrack_line_num = true;
2102 
2104  }
2105  else if (arg == "out")
2106  {
2107  Vdebugging = false;
2108  Vtrack_line_num = true;
2109 
2111  }
2112  else
2113  {
2114  int n = atoi (arg.c_str ());
2115 
2116  if (n < 1)
2117  error ("dbstep: invalid argument");
2118 
2119  Vdebugging = false;
2120  Vtrack_line_num = true;
2121 
2123  }
2124  }
2125  else
2126  {
2127  Vdebugging = false;
2128  Vtrack_line_num = true;
2129 
2131  }
2132 
2133  return ovl ();
2134 }
2135 
2136 DEFALIAS (dbnext, dbstep);
2137 
2138 DEFUN (dbcont, args, ,
2139  doc: /* -*- texinfo -*-
2140 @deftypefn {} {} dbcont
2141 Leave command-line debugging mode and continue code execution normally.
2142 @seealso{dbstep, dbquit}
2143 @end deftypefn */)
2144 {
2145  if (! Vdebugging)
2146  error ("dbcont: can only be called in debug mode");
2147 
2148  if (args.length () != 0)
2149  print_usage ();
2150 
2151  Vdebugging = false;
2152  Vtrack_line_num = true;
2153 
2155 
2156  return ovl ();
2157 }
2158 
2159 DEFUN (dbquit, args, ,
2160  doc: /* -*- texinfo -*-
2161 @deftypefn {} {} dbquit
2162 Quit debugging mode immediately without further code execution and return to
2163 the Octave prompt.
2164 @seealso{dbcont, dbstep}
2165 @end deftypefn */)
2166 {
2167  if (! Vdebugging)
2168  error ("dbquit: can only be called in debug mode");
2169 
2170  if (args.length () != 0)
2171  print_usage ();
2172 
2173  Vdebugging = false;
2174 
2176 
2178 
2179  return ovl ();
2180 }
2181 
2182 DEFUN (isdebugmode, args, ,
2183  doc: /* -*- texinfo -*-
2184 @deftypefn {} {} isdebugmode ()
2185 Return true if in debugging mode, otherwise false.
2186 @seealso{dbwhere, dbstack, dbstatus}
2187 @end deftypefn */)
2188 {
2189  if (args.length () != 0)
2190  print_usage ();
2191 
2192  return ovl (Vdebugging);
2193 }
2194 
2195 DEFUN (__db_next_breakpoint_quiet__, args, ,
2196  doc: /* -*- texinfo -*-
2197 @deftypefn {} {} __db_next_breakpoint_quiet__ ()
2198 @deftypefnx {} {} __db_next_breakpoint_quiet__ (@var{flag})
2199 Disable line info printing at the next breakpoint.
2200 
2201 With a logical argument @var{flag}, set the state on or off.
2202 @end deftypefn */)
2203 {
2204  int nargin = args.length ();
2205 
2206  if (nargin > 1)
2207  print_usage ();
2208 
2209  bool state = true;
2210 
2211  if (nargin == 1)
2212  state = args(0).bool_value ();
2213 
2215 
2216  return ovl ();
2217 }
bool Vdebug_on_error
Definition: error.cc:61
off_t size(void) const
Definition: file-stat.h:125
static void cleanup_instance(void)
Definition: debug.h:174
static std::deque< size_t > get_line_offsets(const std::string &buf)
Definition: debug.cc:108
virtual std::map< std::string, octave_value > subfunctions(void) const
Definition: ov-usr-fcn.cc:66
const Cell & contents(const_iterator p) const
Definition: oct-map.h:313
bool is_empty(void) const
Definition: Array.h:575
intmap do_remove_all_breakpoints_in_file(const std::string &fname, bool silent)
Definition: debug.cc:863
F77_RET_T const F77_INT const F77_INT const F77_INT const F77_DBLE const F77_DBLE F77_INT F77_DBLE * V
Definition: Cell.h:37
For example cd octave end example noindent changes the current working directory to file
Definition: dirfns.cc:120
static void dbstop_process_map_args(const octave_map &mv)
Definition: debug.cc:491
bool Vdebug_on_caught
Definition: error.cc:65
static fname_bp_map get_breakpoint_list(const octave_value_list &fname_list)
Definition: debug.h:112
bool Vdebug_on_warning
Definition: error.cc:69
std::string canonicalize_file_name(const std::string &name)
Definition: file-ops.cc:719
static intmap add_breakpoint(const std::string &fname="", const intmap &lines=intmap(), const std::string &condition=bp_empty_string)
Definition: debug.h:77
std::list< bp_type > breakpoints_and_conds(void)
Definition: pt-stmt.cc:234
fname
Definition: load-save.cc:754
void assign(const std::string &k, const Cell &val)
Definition: oct-map.h:347
static octave_user_code * find_fcn_by_line(octave_user_code *main_fcn, int lineno, int *end_line=0)
Definition: debug.cc:660
ind
Definition: sub2ind.cc:107
static int dbstep_flag
Definition: pt-eval.h:155
intmap::const_iterator const_intmap_iterator
Definition: debug.h:62
OCTAVE_EXPORT octave_value_list isa nd deftypefn *return ovl(args(0).is_integer_type())
OCTINTERP_API void print_usage(void)
Definition: defun.cc:52
bool is_user_code(void) const
Definition: ov.h:720
octave_idx_type numel(void) const
Number of elements in the array.
Definition: Array.h:363
F77_RET_T F77_REAL &F77_RET_T F77_DBLE &F77_RET_T F77_REAL &F77_RET_T F77_DBLE &F77_RET_T F77_REAL &F77_RET_T F77_DBLE &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 F77_REAL &F77_RET_T F77_DBLE &F77_RET_T F77_DBLE &F77_RET_T F77_REAL &F77_RET_T F77_REAL &F77_RET_T F77_DBLE &F77_RET_T const F77_DBLE F77_DBLE &F77_RET_T const F77_REAL F77_REAL &F77_RET_T F77_REAL F77_REAL &F77_RET_T F77_DBLE F77_DBLE &F77_RET_T const F77_DBLE const F77_DBLE * f
octave_idx_type length(void) const
Definition: ovl.h:96
static bool have_breakpoints(void)
Definition: debug.h:119
OCTINTERP_API std::string fcn_file_in_path(const std::string &)
octave_user_code * user_code_value(bool silent=false) const
Definition: ov.cc:1723
int do_remove_breakpoint(const std::string &, const intmap &lines)
Definition: debug.cc:812
bool is_defined(void) const
Definition: ov.h:536
void delete_breakpoint(int line)
Definition: pt-stmt.cc:202
void octave_throw_interrupt_exception(void)
Definition: quit.cc:60
int int_value(bool req_int=false, bool frc_str_conv=false) const
Definition: ov.h:746
#define DEFUN(name, args_name, nargout_name, doc)
Definition: defun.h:46
void error(const char *fmt,...)
Definition: error.cc:570
static void reset_debug_state(void)
Definition: pt-eval.cc:123
std::set< std::string >::iterator bp_set_iterator
Definition: debug.h:160
fname_bp_map do_get_breakpoint_list(const octave_value_list &fname_list)
Definition: debug.cc:929
std::string name(void) const
Definition: ov-fcn.h:163
std::set< std::string > bp_set
Definition: debug.h:163
static void dbclear_all_signals(void)
Definition: debug.cc:474
std::string filename
Definition: urlwrite.cc:340
bool is_cell(void) const
Definition: ov.h:545
static octave_map stop_on_err_warn_status(bool toScreen)
T & elem(octave_idx_type n)
Definition: Array.h:482
octave_idx_type numel(void) const
Definition: oct-map.h:371
s
Definition: file-io.cc:2682
Cell getfield(const std::string &key) const
Definition: oct-map.cc:263
static octave_user_code * get_user_code(const std::string &fname="")
Definition: debug.cc:180
i e
Definition: data.cc:2724
static octave_value find_function(const std::string &name, const octave_value_list &args=octave_value_list(), bool local_funcs=true)
Definition: symtab.cc:1276
const_iterator end(void) const
Definition: oct-map.h:304
void parse_dbfunction_params(const char *who, const octave_value_list &args, std::string &symbol_name, bp_table::intmap &lines, std::string &cond)
Definition: debug.cc:226
static bool quiet_breakpoint_flag
Definition: pt-eval.h:162
octave_value arg
Definition: pr-output.cc:3440
octave_function * fcn
Definition: ov-class.cc:1743
std::string do_find_bkpt_list(octave_value_list slist, std::string match)
Definition: debug.cc:912
string_vector argv
Definition: load-save.cc:635
This class gets nodes and searchs inside of 'info files'.
Definition: parser.h:52
OCTAVE_EXPORT octave_value_list search each directory of the loadpath for element of the cell array and return the first that matches If the second optional argument return a cell array containing the list of all files that have the same name in the path If no files are found
Definition: utils.cc:302
static std::set< std::string > caught_that_stop
Definition: debug.h:169
Cell cell_value(void) const
Definition: ovl.h:88
Cell cell_value(void) const
Definition: ov.cc:1687
JNIEnv void * args
Definition: ov-java.cc:67
#define DEFALIAS(alias, name)
Definition: defun.h:65
virtual tree_statement_list * body(void)=0
static int debug_user_code_line(void)
Definition: call-stack.h:196
static std::string snarf_file(const std::string &fname)
Definition: debug.cc:78
std::set< std::string >::const_iterator const_bp_set_iterator
Definition: debug.h:159
OCTAVE_EXPORT octave_value_list any number nd example oindent prints the prompt xample Pick a any number!nd example oindent and waits for the user to enter a value The string entered by the user is evaluated as an so it may be a literal a variable name
Definition: input.cc:871
static std::set< std::string > warnings_that_stop
Definition: debug.h:170
bool Vdebug_on_interrupt
Definition: sighandlers.cc:70
void do_remove_all_breakpoints(void)
Definition: debug.cc:896
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:935
bool isfield(const std::string &name) const
Definition: oct-map.h:329
Definition: debug.h:47
bool Vtrack_line_num
Definition: input.cc:114
std::string string_value(bool force=false) const
Definition: ov.h:908
static octave_user_code * debug_user_code(void)
Definition: call-stack.h:190
nd deftypefn *octave_map m
Definition: ov-struct.cc:2058
static void add(fptr f)
std::complex< double > w(std::complex< double > z, double relerr=0)
int nargin
Definition: graphics.cc:10115
std::map< int, int > intmap
Definition: debug.h:60
bool is_string(void) const
Definition: ov.h:578
bool strcmp(const T &str_a, const T &str_b)
True if strings are the same.
Definition: oct-string.cc:112
static char dir_sep_char(void)
Definition: file-ops.h:75
bool do_add_breakpoint_1(octave_user_code *fcn, const std::string &fname, const intmap &line, const std::string &condition, intmap &retval)
Definition: debug.cc:580
OCTINTERP_API std::string do_which(const std::string &name)
void resize(const dim_vector &dv, const T &rfv)
Definition: Array.cc:1028
OCTAVE_EXPORT octave_value_list W
Definition: qz.cc:216
std::map< std::string, std::list< bp_type > > fname_bp_map
Definition: debug.h:70
octave_value retval
Definition: data.cc:6294
virtual std::list< std::string > subfunction_names(void) const
Definition: ov-fcn.h:154
static intmap remove_all_breakpoints_in_file(const std::string &fname, bool silent=false)
Definition: debug.h:94
virtual bool is_user_function(void) const
Definition: ov-base.h:461
sz
Definition: data.cc:5342
the sparsity preserving column transformation such that that defines the pivoting threshold can be given in which case it defines the c
Definition: lu.cc:138
const_iterator begin(void) const
Definition: oct-map.h:303
static bool debug_mode
Definition: pt-eval.h:160
virtual octave_user_code * user_code_value(bool silent=false)
Definition: ov-base.cc:945
int do_remove_breakpoint_1(octave_user_code *fcn, const std::string &, const intmap &lines)
Definition: debug.cc:763
void err_wrong_type_arg(const char *name, const char *s)
Definition: errwarn.cc:156
static uint32_t state[624]
Definition: randmtzig.cc:184
static std::set< std::string > errors_that_stop
Definition: debug.h:168
void warning(const char *fmt,...)
Definition: error.cc:788
virtual std::string profiler_name(void) const
Definition: ov-fcn.h:69
octave::unwind_protect frame
Definition: graphics.cc:11584
charNDArray max(char d, const charNDArray &m)
Definition: chNDArray.cc:228
virtual std::string fcn_file_name(void) const
Definition: ov-fcn.h:64
bool is_empty(void) const
Definition: ov.h:542
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:191
int run(void)
Definition: oct-parse.cc:7953
bool empty(void) const
Definition: ovl.h:98
#define octave_stdout
Definition: pager.h:146
static bp_table * instance
Definition: debug.h:172
octave::sys::time start
Definition: graphics.cc:11731
static bool condition_valid(const std::string &cond)
Definition: debug.cc:622
char Vfilemarker
Definition: input.cc:124
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:2981
static void remove_all_breakpoints(void)
Definition: debug.h:103
=val(i)}if ode{val(i)}occurs in table i
Definition: lookup.cc:239
octave_value_list list_breakpoints(void)
Definition: pt-stmt.cc:224
static bool instance_ok(void)
Definition: debug.cc:456
p
Definition: lu.cc:138
tree_expression * expression(void)
Definition: pt-stmt.h:86
size_t length(void) const
Definition: base-list.h:50
bp_table(void)
Definition: debug.h:53
static int remove_breakpoint(const std::string &fname="", const intmap &lines=intmap())
Definition: debug.h:86
bp_table::intmap add_breakpoint(const std::string &file, const bp_table::intmap &line, const std::string &condition)
Definition: pt-stmt.cc:257
elt_type & front(void)
Definition: base-list.h:97
Cell index(const octave_value_list &idx, bool resize_ok=false) const
Definition: Cell.cc:155
dbstop_args
Definition: debug.cc:216
octave::sys::file_stat fs(filename)
virtual bool is_assignment_expression(void) const
Definition: pt-exp.h:65
intmap do_add_breakpoint(const std::string &fname, const intmap &lines, const std::string &condition)
Definition: debug.cc:721
bool is_empty(void) const
Definition: oct-map.h:373
tree_statement_list * stmt_list
Definition: parse.h:456
bool is_expression(void) const
Definition: pt-stmt.h:68
std::string get_file_line(const std::string &fname, size_t line)
Definition: debug.cc:141
OCTAVE_EXPORT octave_value_list any number nd example oindent prints the prompt xample Pick a any number!nd example oindent and waits for the user to enter a value The string entered by the user is evaluated as an so it may be a literal a variable or any other valid Octave code The number of return their size
Definition: input.cc:871
octave_fields::const_iterator const_iterator
Definition: oct-map.h:300
bp_table::intmap remove_all_breakpoints(const std::string &file)
Definition: pt-stmt.cc:284
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:109
static bool goto_frame_relative(int n, bool verbose=false)
Definition: call-stack.h:258
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:854
static octave_value intmap_to_ov(const bp_table::intmap &line)
Definition: debug.cc:989
Definition: token.h:32
return octave_value(v1.char_array_value().concat(v2.char_array_value(), ra_idx),((a1.is_sq_string()||a2.is_sq_string())? '\'': '"'))
charNDArray min(char d, const charNDArray &m)
Definition: chNDArray.cc:205
static octave_map backtrace(size_t nskip=0)
Definition: call-stack.h:276