# package to manage breakpoints with trace(), browser()

# breaks will be a list, indexed by quoted the names of the functions being
# debugged; breaks[["f"]] is then a vector of current breakpoints of
# f(); note that these are "step numbers" in R terminology, differing
# from line numbers within the function in that comments don't count and
# blocks count as just one step
breaks <- list()

# set a breakpoint using trace()
# note:  quotedftnname must be a quoted string!
setbp <- function(quotedftnname,stepnums) 
   trace(quotedftnname,browser,at=stepnums)

# bk() changes the current breakpoint set of the function quotedftnname,
# adding breakpoints at the steps specfied by toadd, and deleting those
# specfied by todel; if wipe is TRUE, then all breakpoints for this
# function are deleted, overriding toadd and todel, and calling
# untrace() on the function; example:
#   bk("g",c(5,8),12)
# will add breakpoints at steps 5 and 8 of g() while deleting the one at 12
bk <- function(quotedftnname,toadd=NULL,todel=NULL,wipe=F) {
   if (wipe) {
      breaks[[quotedftnname]] <<- NULL
      untrace(quotedftnname)
      return()
   }
   # since each call to trace() nullifies previous such actions, we must
   # update our breakpoint list, then call trace() with the new list
   if (!is.null(toadd)) 
      breaks[[quotedftnname]] <<- c(breaks[[quotedftnname]],toadd)
   if (!is.null(todel)) 
      breaks[[quotedftnname]] <<- setdiff(breaks[[quotedftnname]],todel)
   setbp(quotedftnname,breaks[[quotedftnname]])
}

# list step numbers (for use as "at" in trace())
lssns <- function(ftnname) 
   as.list(body(ftnname))
