require 'cgi' require 'yaml' module Debugger class XmlPrinter # :nodoc: attr_accessor :interface def initialize(interface) @interface = interface end def print_msg(*args) msg, *args = args xml_message = CGI.escapeHTML(msg % args) print "#{xml_message}" end def print_error(*args) print_element("error") do msg, *args = args print CGI.escapeHTML(msg % args) end end # Convenient delegate to Debugger#print_debug def print_debug(*args) Debugger.print_debug(*args) end def print_frames(context, cur_idx) print_element("frames") do (0...context.stack_size).each do |idx| print_frame(context, idx, cur_idx) end end end def print_current_frame(context, frame_pos) print_debug "Selected frame no #{frame_pos}" end def print_frame(context, idx, cur_idx) # idx + 1: one-based numbering as classic-debugger print "", idx + 1, context.frame_file(idx), context.frame_line(idx) end def print_contexts(contexts) print_element("threads") do contexts.each do |c| print_context(c) unless c.ignored? end end end def print_context(context) current = 'current="yes"' if context.thread == Thread.current print "", context.thnum, context.thread.status end def print_variables(vars, kind) print_element("variables") do # print self at top position print_variable('self', yield('self'), kind) if vars.include?('self') vars.sort.each do |v| print_variable(v, yield(v), kind) unless v == 'self' end end end def print_array(array) print_element("variables") do index = 0 array.each { |e| print_variable('[' + index.to_s + ']', e, 'instance') index += 1 } end end def print_hash(hash) print_element("variables") do hash.keys.each { | k | if k.class.name == "String" name = '\'' + k + '\'' else name = k.to_s end print_variable(name, hash[k], 'instance') } end end def print_variable(name, value, kind) unless value print("", CGI.escapeHTML(name), kind) return end if value.is_a?(Array) || value.is_a?(Hash) has_children = !value.empty? unless has_children value_str = "Empty #{value.class}" else value_str = "#{value.class} (#{value.size} element(s))" end else has_children = !value.instance_variables.empty? || !value.class.class_variables.empty? value_str = value.to_s || 'nil' rescue "<#to_s method raised exception: #$!>" unless value_str.is_a?(String) value_str = "ERROR: #{value.class}.to_s method returns #{value_str.class}. Should return String." end if value_str =~ /^\"(.*)"$/ value_str = $1 end end value_str = "[Binary Data]" if value_str.is_binary_data? print("", CGI.escapeHTML(name), kind, CGI.escapeHTML(value_str), value.class, has_children, value.respond_to?(:object_id) ? value.object_id : value.id) end def print_breakpoints(breakpoints) print_element 'breakpoints' do breakpoints.sort_by{|b| b.id }.each do |b| print "", b.id, b.source, b.pos.to_s end end end def print_breakpoint_added(b) print "", b.id, b.source, b.pos end def print_breakpoint_deleted(b) print "", b.id end def print_breakpoint_enabled(b) print "", b.id end def print_breakpoint_disabled(b) print "", b.id end def print_contdition_set(bp_id) print "", bp_id end def print_catchpoint_set(exception_class_name) print "", exception_class_name end def print_expressions(exps) print_element "expressions" do exps.each_with_index do |(exp, value), idx| print_expression(exp, value, idx+1) end end unless exps.empty? end def print_expression(exp, value, idx) print "", exp, value, idx end def print_eval(exp, value) print "", CGI.escapeHTML(exp), value end def print_pp(exp, value) print value end def print_list(b, e, file, line) print "[%d, %d] in %s\n", b, e, file if lines = Debugger.source_for(file) n = 0 b.upto(e) do |n| if n > 0 && lines[n-1] if n == line print "=> %d %s\n", n, lines[n-1].chomp else print " %d %s\n", n, lines[n-1].chomp end end end else print "No sourcefile available for %s\n", file end end def print_methods(methods) print_element "methods" do methods.each do |method| print "", method end end end # Events def print_breakpoint(n, breakpoint) print("", breakpoint.source, breakpoint.pos, Debugger.current_context.thnum) end def print_catchpoint(exception) context = Debugger.current_context print("", context.frame_file(0), context.frame_line(0), exception.class, CGI.escapeHTML(exception.to_s), context.thnum) end def print_trace(context, file, line) print "", file, line, context.thnum end def print_at_line(file, line) print "", file, line, Debugger.current_context.thnum, Debugger.current_context.stack_size end def print_exception(exception, binding) print "", exception.class, CGI.escapeHTML(exception.to_s) end def print_inspect(eval_result) print_element("variables") do print_variable("eval_result", eval_result, 'local') end end def print_load_result(file, exception=nil) if exception then print("", file, exception.class, CGI.escapeHTML(exception.to_s)) else print("", file) end end def print_element(name) print("<#{name}>") begin yield ensure print("") end end private def print(*params) print_debug(*params) @interface.print(*params) end end end