Branch: Tag:

2018-11-29

2018-11-29 03:13:19 by William Welliver <william@welliver.org>

debugger: multiple breakpoint support, enable/disable support.

516:   }       - PMOD_EXPORT - PIKEFUN int add_breakpoint(program p, string fname, int line_number) + PIKECLASS debug_breakpoint { +  +  PIKEVAR program prog flags ID_PROTECTED|ID_PRIVATE; +  PIKEVAR string fname flags ID_PROTECTED|ID_PRIVATE; +  PIKEVAR int line_number flags ID_PROTECTED|ID_PRIVATE; +  PIKEVAR int enabled flags ID_PROTECTED|ID_PRIVATE; +  +  CVAR struct debug_breakpoint * bp; +  +  PIKEFUN void create(string fname, int line_number) +  flags ID_PROTECTED;    optflags OPT_SIDE_EFFECT; - efun; +     { -  +  THIS->fname = fname; +  THIS->line_number = line_number; +  add_ref(fname); +  } +  +  PIKEFUN void create( + program p, string fname, int line_number) +  flags ID_PROTECTED; +  optflags OPT_SIDE_EFFECT; + { +  THIS->prog = p; +  THIS->fname = fname; +  THIS->line_number = line_number; +  add_ref(p); +  add_ref(fname); + } +  PIKEFUN program get_program() { +  if(THIS->prog) +  RETURN THIS->prog; +  else push_int(0); +  } +  +  PIKEFUN string get_filename() { +  add_ref(THIS->fname); /* it seems strange to need this, but whatever. */ +  RETURN THIS->fname; +  } +  +  PIKEFUN int get_line_number() { +  RETURN THIS->line_number; +  } +  +  PIKEFUN int get_enabled() { +  RETURN THIS->enabled; +  } +  +  PIKEFUN int enable() { +  ptrdiff_t offset; +  if(THIS->enabled) +  Pike_error("Breakpoint already enabled.\n"); +  /* This should eventually be a deferred breakpoint initialization. */ +  if(!(THIS->prog)) +  Pike_error("Program for breakpoint has not been resolved. Unable to enable.\n"); +  offset = low_get_offset_for_line(THIS->prog, THIS->fname, THIS->line_number); +  if(offset < 0) Pike_error("Unable to find offset of line number in program!\n"); + #ifdef PIKE_DEBUG +  struct debug_breakpoint * bp = malloc(sizeof(struct debug_breakpoint)); +  if(!bp) Pike_fatal("Unable to allocate memory for breakpoint\n"); +  if(THIS->prog->breakpoints) +  bp->next = THIS->prog->breakpoints; +  else +  bp->next = NULL; +  bp->prev = NULL; +  bp->offset = offset; +  /* this may be unnecessary */ +  bp->prog = THIS->prog; +  THIS->prog->breakpoints = bp; +  THIS->bp = bp; +  THIS->enabled = 1; + #else +  Pike_error("Cannot enable breakpoints if debug is not enabled.\n"); + #endif /*PIKE_DEBUG*/ +  } +  +  void low_disable_breakpoint() { +  struct debug_breakpoint * bp, *pbp; +  +  if((THIS->prog) && (bp = (THIS->prog->breakpoints)) != NULL) { +  while(bp != NULL) { +  if(bp == (THIS->bp)) { +  printf("found a breakpoint to free.\n"); +  if(bp->next && bp->prev) { // somewhere in the middle, connect the previous and next. +  bp->prev->next = bp->next; +  bp->next->prev = bp->prev; +  } else if(bp->next) { // only next pointer: at the beginning, so make next the new first. +  bp->next->prev = NULL; +  THIS->prog->breakpoints = bp->next; +  } else if(bp->prev) { // only prev pointer: at the end, just unlink us. +  bp->prev->next = NULL; +  } else { +  THIS->prog->breakpoints = NULL; +  } +  pbp = bp; +  bp = bp->next; +  free(pbp); +  THIS->bp = NULL; +  } else { +  bp = bp->next; +  } +  }; +  } +  } +  +  ptrdiff_t low_add_breakpoint() {    ptrdiff_t pc_offset;       // TODO: we need to develop the line search further: a file can be included multiple times within a program, and so    // in theory, a breakpoint for a line within a file could actually be multiple breakpoints. we stop at the first one. -  pc_offset = low_get_offset_for_line(p, fname, line_number); -  pop_n_elems(args); -  bp_offset = pc_offset; -  bp_prog = p; -  if(!pc_offset) Pike_error("Line number not found\n"); -  push_int(pc_offset); +  pc_offset = low_get_offset_for_line(THIS->prog, THIS->fname, THIS->line_number); +  if(!pc_offset) return -1; +  return pc_offset;   }    -  +  PIKEFUN int disable() { +  if(!(THIS->enabled)) +  Pike_error("Breakpoint not enabled.\n"); +  low_disable_breakpoint(); +  THIS->enabled = 0; +  } +  +  INIT { +  THIS->prog = NULL; +  THIS->fname = NULL; +  THIS->line_number = 0; +  THIS->enabled = 0; +  } +  +  EXIT { +  low_disable_breakpoint(); +  if(THIS->prog) +  free_program(THIS->prog); +  if(THIS->fname) +  free_string(THIS->fname); +  THIS->bp = NULL; /* should already have been freed by low_disable_breakpoint(). */ +  THIS->prog = NULL; +  THIS->fname = NULL; +  THIS->line_number = 0; +  } + } +    /*! @decl string basetype(mixed x)    *!    *! Same as sprintf("%t",x);
3026:   }      PMOD_EXPORT - PIKEFUN array(mixed) debug_backtrace() -  efun; + PIKEFUN array(mixed) __debug_backtrace() +  flags ID_PROTECTED;    optflags OPT_EXTERNAL_DEPEND;   {    low_low_backtrace(& Pike_interpreter, 1);