| ############################################################################### |
| # 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 'socket' |
| require 'base64' |
| |
| module XoredDebugger |
| |
| class Printer |
| |
| private |
| def escape(text) |
| text.gsub(/&/,"&").gsub(/"/,""").gsub(/</,"<").gsub(/>/,">") |
| end |
| |
| def escape_data(data) |
| if data.class == String |
| escape(data) |
| elsif data.class == Array |
| data.collect! { |v| |
| escape_data(v) |
| } |
| elsif data.class == Hash |
| data.each { |k, v| |
| if (k.class == String or k.class == Symbol) and k.to_s.match('^_.*$').nil? |
| data[k] = escape_data(v) |
| end |
| } |
| else |
| data |
| end |
| end |
| |
| def bool_to_bit(value) |
| return value ? '1' : '0' |
| end |
| |
| |
| def wrap(xml) |
| '<?xml version="1.0" encoding="UTF-8"?>' + xml |
| end |
| |
| def cdata(s) |
| sprintf('<![CDATA[%s]]>', s) |
| end |
| |
| |
| def print_property(m) |
| if m.nil? |
| return '' |
| end |
| |
| children = m[:children_props] |
| |
| children_str = '' |
| unless children.nil? |
| children_str = children.collect { |p| print_property(p) }.join("\n") |
| end |
| |
| sprintf('<property name="%s" fullname="%s" type="%s" constant="%d" children="%d" encoding="base64" key="%s" %s>%s%s</property>', |
| m[:name], |
| m[:eval_name], |
| m[:type].to_s, |
| bool_to_bit(m[:is_cosntant]), |
| bool_to_bit(m[:has_children]), |
| m[:key].to_s, |
| m[:num_children].nil? ? '' : 'numchildren="' + m[:num_children].to_s + '"', |
| cdata(Base64.encode64(m[:_value].nil? ? 'nil' : m[:_value])), |
| children_str) |
| end |
| |
| def print_breakpoint(m) |
| sprintf('<breakpoint id="%d" type="%s" state="%s" filename="%s" hit_count="%d" hit_value="%d" hit_condition="%s" lineno="%d"/>', |
| m[:breakpoint_id], |
| m[:type], |
| m[:state], |
| m[:filename], |
| m[:hit_count], |
| m[:hit_value], |
| m[:hit_condition], |
| m[:lineno]) |
| end |
| |
| def print_continuation(command, m) |
| sprintf('<response command="%s" status="%s" reason="%s" transaction_id="%d"/>', |
| command, m[:status], m[:reason], m[:id]) |
| end |
| |
| public |
| def print(command, data) |
| self.send('print_' + command, escape_data(data)) |
| end |
| |
| # Init command |
| def print_init(m) |
| sprintf('<init appid="%s" idekey="%s" session="%s" thread="%s" parent="%s" language="ruby" protocol_version="1.0" fileuri="%s"/>', |
| m[:app_id], m[:ide_key], m[:session], m[:thread], m[:parent], m[:file_uri]) |
| end |
| |
| # Status command |
| def print_status(m) |
| print_continuation('status', m) |
| end |
| |
| # Feature commands |
| def print_feature_get(m) |
| sprintf('<response command="feature_get" feature_name="%s" supported="%d" transaction_id="%d">%s</response>', |
| m[:name], m[:supported], m[:id], cdata(Base64.encode64(m[:value]))) |
| end |
| |
| def print_feature_set(m) |
| sprintf('<response command="feature_set" feature="%s" success="%d" transaction_id="%d"/>', |
| m[:name], m[:success], m[:id]) |
| end |
| |
| # Continuation commands |
| def print_run(m) |
| print_continuation('run', m) |
| end |
| |
| def print_step_into(m) |
| print_continuation('step_into', m) |
| end |
| |
| def print_step_over(m) |
| print_continuation('step_over', m) |
| end |
| |
| def print_step_out(m) |
| print_continuation('step_out', m) |
| end |
| |
| def print_stop(m) |
| print_continuation('stop', m) |
| end |
| |
| def print_detach(m) |
| print_continuation('detach', m) |
| end |
| |
| def print_break(m) |
| sprintf('<response command="break" transaction_id="%d" success="%s"/>', |
| m[:id], bool_to_bit(m[:success])) |
| end |
| |
| # Properties |
| def print_property_get(m) |
| sprintf('<response command="property_get" transaction_id="%d">%s</response>', |
| m[:id], print_property(m[:property])) |
| end |
| |
| def print_property_set(m) |
| sprintf('<response command="property_set" transaction_id="%d" success="%d"/>', |
| m[:id], bool_to_bit(m[:success])) |
| end |
| |
| def print_property_value(m) |
| sprintf('<response command="property_value" size="%d" encoding="%s" transaction_id="%d">%s</response>', |
| m[:size], m[:encoding], m[:id], Base64.encode64(m[:value])); |
| end |
| |
| # Contexts |
| def print_context_names(m) |
| ctxs = '' |
| m[:contexts].each { |s| |
| ctxs += sprintf('<context name="%s" id="%d"/>', |
| s[:name], s[:id]) |
| } |
| sprintf('<response command="context_names" transaction_id="%d">%s</response>', |
| m[:id], ctxs) |
| end |
| |
| def print_context_get(m) |
| props = m[:properties].collect { |p| print_property(p) }.join("\n") |
| |
| sprintf('<response command="context_get" context="%d" transaction_id="%d">%s</response>', |
| m[:context_id], m[:id], props) |
| end |
| |
| # Stream commands |
| def print_stream(stream, m) |
| sprintf('<response command="%s" success="%d" transaction_id="%d"/>', |
| stream, bool_to_bit(m[:success]), m[:id]) |
| end |
| private :print_stream |
| |
| def print_stdout(m) |
| print_stream('stdout', m) |
| end |
| |
| def print_stderr(m) |
| print_stream('stderr', m) |
| end |
| |
| def print_stdin(m) |
| print_stream('stdin', m) |
| end |
| |
| # Data |
| def print_stream_data(command, m) |
| sprintf('<stream type="%s">%s</stream>', |
| command, cdata(Base64.encode64(m[:_data].nil? ? 'nil' : m[:_data]))) |
| end |
| private :print_stream_data |
| |
| def print_stdout_data(m) |
| print_stream_data('stdout', m) |
| end |
| |
| def print_stderr_data(m) |
| print_stream_data('stderr', m) |
| end |
| |
| # Stack commands |
| def print_stack_depth(m) |
| sprintf('<response command="stack_depth" depth="%d" transaction_id="%d"/>', |
| m[:depth], m[:id]) |
| end |
| |
| def print_stack_get(m) |
| levels = '' |
| m[:levels].each { |s| |
| levels += sprintf('<stack level="%d" type="%s" filename="%s" lineno="%d" cmdbegin="%s" cmdend="%s" where="%s"/>', |
| s[:level], s[:type], s[:filename], s[:lineno], s[:cmdbegin], s[:cmdend], s[:where]) |
| } |
| |
| sprintf('<response command="stack_get" transaction_id="%d">%s</response>', |
| m[:id], levels) |
| end |
| |
| # Breakpoint commands |
| def print_breakpoint_set(m) |
| sprintf('<response command="breakpoint_set" state="%s" id="%d" transaction_id="%d"/>', |
| m[:state] == true ? 'enabled' : 'disabled', m[:breakpoint_id], m[:id]) |
| end |
| |
| def print_breakpoint_get(m) |
| sprintf('<response command="breakpoint_get" transaction_id="%d">%s</response>', |
| m[:id], print_breakpoint(m[:breakpoint])) |
| end |
| |
| def print_breakpoint_update(m) |
| sprintf('<response command="breakpoint_update" transaction_id="%d"/>', |
| m[:id]) |
| end |
| |
| def print_breakpoint_remove(m) |
| sprintf('<response command="breakpoint_remove" transaction_id="%d"/>', |
| m[:id]) |
| end |
| |
| def print_breakpoint_list(m) |
| # TODO: |
| end |
| |
| # Extended commands |
| def print_eval(m) |
| sprintf('<response command="eval" transaction_id="%d" success="%s">%s</response>', |
| m[:id], bool_to_bit(m[:success]), print_property(m[:property])) |
| end |
| |
| end # class Printer |
| |
| end # module |