| ############################################################################### | |
| # Copyright (c) 2005, 2007 IBM Corporation and others. | |
| # All rights reserved. This program and the accompanying materials | |
| # are made available under the terms of the Eclipse Public License v1.0 | |
| # which accompanies this distribution, and is available at | |
| # http://www.eclipse.org/legal/epl-v10.html | |
| # | |
| ############################################################################### | |
| require 'thread' | |
| module XoredDebugger | |
| class Breakpoint | |
| COND_GREATER_OR_EQUALS = '>=' | |
| COND_EQUALS = '==' | |
| COND_MULTIPLE = '%' | |
| def initialize(id, state = true, temporary = false, expression = nil, hit_value = 1, hit_condition = COND_GREATER_OR_EQUALS) | |
| @id = id # Unique identifier | |
| @state = state # Enabled or disabled | |
| @temporary = temporary # Breakpoint should be removed after first hit | |
| @expression = expression | |
| @hit_count = 0 # Number of breakpoint hits | |
| @hit_value = hit_value # Special value used with hit_condition | |
| @hit_condition = hit_condition # The relation between hit_value and hit_count | |
| end | |
| attr_reader :id | |
| attr_reader :state | |
| attr_writer :state | |
| attr_reader :hit_count, :hit_value, :hit_condition | |
| def update(state, temporary, expression, hit_value, hit_condition) | |
| @state = state | |
| @temporary = temporary | |
| @expression = expression | |
| @hit_value = hit_value | |
| @hit_condition = hit_condition | |
| end | |
| def hit(stack) | |
| @hit_count += 1 | |
| # Expression | |
| unless @expression.nil? | |
| begin | |
| if not stack.eval(expression) | |
| return false # Expression evaluated to false | |
| end | |
| rescue Exception | |
| return false # Expression can not be evaluated | |
| end | |
| end | |
| # State | |
| if not @state | |
| return false # Breakpoint disabled | |
| end | |
| # Hit condition | |
| case @hit_condition | |
| when COND_GREATER_OR_EQUALS | |
| @hit_count >= @hit_value | |
| when COND_EQUALS | |
| @hit_count == @hit_value | |
| when COND_MULTIPLE | |
| (@hit_count % @hit_value) == 0 | |
| else | |
| false | |
| end | |
| end | |
| def exists | |
| @temporary ? @hit_count == 0 : true | |
| end | |
| protected :hit | |
| end # class Breakpoint | |
| # | |
| # N.B. Stores absolute path names | |
| # | |
| class LineBreakpoint < Breakpoint | |
| def initialize(id, file, line, state = true, temporary = false, expression = nil, hit_value = 1, hit_condition = COND_GREATER_OR_EQUALS) | |
| super(id, state, temporary, expression, hit_value, hit_condition) | |
| @file = file | |
| @line = line | |
| end | |
| attr_reader :line, :file | |
| def hit(stack, file, line) | |
| @file == file and @line == line and super(stack) | |
| end | |
| attr_reader :file, :line | |
| end # class LineBreakpoint | |
| class ExceptionBreakpoint < Breakpoint | |
| def initialize(id, exception, state = true, temporary = false) | |
| super(id, state, temporary) | |
| @exception = exception | |
| end | |
| def hit(stack, exception) | |
| @exception == exception and super(stack) | |
| end | |
| end # class ExceptionBreakpoint | |
| class Breakpoints | |
| private | |
| @@id = 0 | |
| def Breakpoints.next_id | |
| @@id += 1 | |
| end | |
| public | |
| def initialize | |
| @mutex = Mutex.new | |
| @line_bps = {} | |
| @exception_bps = {} | |
| end | |
| def [] (id) | |
| @line_bps[id] | |
| end | |
| def line_break?(stack, file, line) | |
| @mutex.synchronize do | |
| result = false | |
| for bp in @line_bps.values do | |
| if bp.hit(stack, file, line) | |
| result = true | |
| end | |
| end | |
| result | |
| end | |
| end | |
| def exception_break?(stack, exception) | |
| @mutex.synchronize do | |
| end | |
| end | |
| def set_line_bpt(file, line, state, temporary, expression, hit_value, hit_condition) | |
| @mutex.synchronize do | |
| id = Breakpoints.next_id | |
| @line_bps[id] = LineBreakpoint.new(id, file, line, state, temporary, expression, hit_value, hit_condition) | |
| id | |
| end | |
| end | |
| def set_exception_bpt(exception, state) | |
| @mutex.synchronize do | |
| id = Breakpoints.next_id | |
| # TODO: | |
| id | |
| end | |
| end | |
| def update(id, state, temporary, expression, hit_value, hit_condition) | |
| @mutex.synchronize do | |
| @line_bps[id].update(state, temporary, expression, hit_value, hit_condition) | |
| end | |
| end | |
| def remove(id) | |
| @mutex.synchronize do | |
| (not @line_bps.delete(id).nil?) or (not @exception_bps.delete(id).nil?) | |
| end | |
| end | |
| end # class Breakpoints | |
| end # module XoredDebugger |