You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdewebdev/quanta/components/debugger/dbgp/quantadebuggerdbgp.cpp

1043 lines
34 KiB

/***************************************************************************
quantadebuggerdbgp.cpp
-------------------
begin : 2004-03-12
copyright : (C) 2004 Linus McCabe <linus@mccabe.nu>
***************************************************************************/
/****************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include <errno.h>
#include <kdebug.h>
#include <kdeversion.h>
#include <kgenericfactory.h>
#include <klocale.h>
#include <kmdcodec.h>
#include <kmessagebox.h>
#include <krun.h>
#include <tqcheckbox.h>
#include <tqcombobox.h>
#include <tqfile.h>
#include <tqlineedit.h>
#include <tqmap.h>
#include <tqregexp.h>
#include <tqslider.h>
#include <tqstring.h>
#include <stdarg.h>
#include "debuggerclient.h"
#include "quantadebuggerdbgp.h"
#include "debuggerinterface.h"
#include "debuggerbreakpoint.h"
#include "dbgpsettings.h"
#include "debuggervariable.h"
#include "variableslistview.h"
#include "pathmapper.h"
K_EXPORT_COMPONENT_FACTORY( quantadebuggerdbgp,
KGenericFactory<QuantaDebuggerDBGp>("quantadebuggerdbgp"))
const char QuantaDebuggerDBGp::protocolversion[] = "1.0";
QuantaDebuggerDBGp::QuantaDebuggerDBGp (TQObject *tqparent, const char*, const TQStringList&)
: DebuggerClient (tqparent, "DBGp")
{
// Create a socket object and set up its signals
m_errortqmask = 1794;
m_supportsasync = false;
m_defaultExecutionState = Starting;
setExecutionState(m_defaultExecutionState);
emit updatetqStatus(DebuggerUI::NoSession);
connect(&m_network, TQT_SIGNAL(command(const TQString&)), this, TQT_SLOT(processCommand(const TQString&)));
connect(&m_network, TQT_SIGNAL(active(bool)), this, TQT_SLOT(slotNetworkActive(bool)));
connect(&m_network, TQT_SIGNAL(connected(bool)), this, TQT_SLOT(slotNetworkConnected(bool)));
connect(&m_network, TQT_SIGNAL(networkError(const TQString &, bool)), this, TQT_SLOT(slotNetworkError(const TQString &, bool)));
}
QuantaDebuggerDBGp::~QuantaDebuggerDBGp ()
{
// kdDebug(24002) << k_funcinfo << endl;
m_network.sessionEnd();
}
void QuantaDebuggerDBGp::slotNetworkActive(bool active)
{
// debuggerInterface() might not be available, for example from project dialog
if(!debuggerInterface())
return;
debuggerInterface()->enableAction("debug_request", active);
debuggerInterface()->enableAction("debug_connect", !active);
debuggerInterface()->enableAction("debug_disconnect", active);
setExecutionState(m_defaultExecutionState);
if(active)
emit updatetqStatus(DebuggerUI::AwaitingConnection);
else
emit updatetqStatus(DebuggerUI::NoSession);
}
void QuantaDebuggerDBGp::slotNetworkConnected(bool connected)
{
// debuggerInterface() might not be available, for example from project dialog
if(!debuggerInterface())
return;
m_active = connected;
debuggerInterface()->enableAction("debug_run", connected);
debuggerInterface()->enableAction("debug_leap", connected);
debuggerInterface()->enableAction("debug_pause", connected);
debuggerInterface()->enableAction("debug_kill", connected);
debuggerInterface()->enableAction("debug_stepinto", connected);
debuggerInterface()->enableAction("debug_stepover", connected);
debuggerInterface()->enableAction("debug_stepout", connected);
debuggerInterface()->setActiveLine("", 0);
if(connected)
emit updatetqStatus(DebuggerUI::Connected);
else
{
setExecutionState(m_defaultExecutionState);
emit updatetqStatus(DebuggerUI::AwaitingConnection);
profilerOpen(false);
}
}
void QuantaDebuggerDBGp::slotNetworkError(const TQString &errormsg, bool log)
{
debuggerInterface()->showtqStatus(errormsg, log);
}
// Try to make a connection to the dbgp server
void QuantaDebuggerDBGp::startSession()
{
kdDebug(24002) << k_funcinfo << endl;
m_network.sessionStart(m_useproxy, m_serverHost, m_useproxy ? m_serverPort : m_listenPort);
// setExecutionState(Starting);
}
void QuantaDebuggerDBGp::endSession()
{
kdDebug(24002) << k_funcinfo << endl;
// Close the socket
m_network.sessionEnd();
// debuggerInterface()->enableAction("debug_request", false);
// debuggerInterface()->enableAction("debug_run", false);
// debuggerInterface()->enableAction("debug_leap", false);
// debuggerInterface()->enableAction("debug_pause", false);
}
// Change executionstate of the script
void QuantaDebuggerDBGp::setExecutionState( const State & state, bool forcesend )
{
if(m_executionState != state || forcesend)
{
if(state == Running)
m_network.sendCommand("run");
else if (state == Break)
m_network.sendCommand("break");
}
m_executionState = state;
if(debuggerInterface()) {
// The run action will be active if we're started, stopped or paused
debuggerInterface()->enableAction("debug_run", m_executionState == Break || m_executionState == Starting || m_executionState == Stopped);
// The pause action will be enabled if we're running and either supports async or we're not connected (ie will start running)
debuggerInterface()->enableAction("debug_pause", m_executionState == Running && (m_supportsasync || !isActive())) ;
// Kill is active if we're paused, just started of the debugger supports async, as long as we have an active session
debuggerInterface()->enableAction("debug_kill", isActive() && (m_executionState == Break || (m_executionState == Running && m_supportsasync) || m_executionState == Starting || m_executionState == Stopping ));
// These are only activated when we have an active seesion and are paused
debuggerInterface()->enableAction("debug_stepinto", isActive() && (m_executionState == Break || m_executionState == Starting ));
debuggerInterface()->enableAction("debug_stepout", isActive() && (m_executionState == Break || m_executionState == Starting));
debuggerInterface()->enableAction("debug_stepover", isActive() && (m_executionState == Break || m_executionState == Starting));
}
}
// Change executionstate of the script
void QuantaDebuggerDBGp::setExecutionState(const TQString &state)
{
kdDebug(24002) << k_funcinfo << state << endl;
if(state == "starting")
{
setExecutionState(Starting);
emit updatetqStatus(DebuggerUI::Paused);
}
else if(state == "stopping")
{
setExecutionState(Stopping);
emit updatetqStatus(DebuggerUI::Paused);
m_network.slotSocketDestroyed(); //XDebug disconnects when stopped and destroys our socket
}
else if(state == "stopped")
{
setExecutionState(Stopped);
emit updatetqStatus(DebuggerUI::Paused);
m_network.slotSocketDestroyed(); //XDebug disconnects when stopped and destroys our socket
}
else if(state == "running")
{
setExecutionState(Running);
emit updatetqStatus(DebuggerUI::Running);
}
else if(state == "break")
{
setExecutionState(Break);
emit updatetqStatus(DebuggerUI::Paused);
}
}
// Return capabilities of dbgp
const uint QuantaDebuggerDBGp::supports(DebuggerClientCapabilities::Capabilities cap)
{
switch(cap)
{
case DebuggerClientCapabilities::LineBreakpoints:
// case DebuggerClientCapabilities::ConditionalBreakpoints:
case DebuggerClientCapabilities::StartSession:
case DebuggerClientCapabilities::EndSession:
case DebuggerClientCapabilities::Kill:
case DebuggerClientCapabilities::Pause:
case DebuggerClientCapabilities::Run:
//case DebuggerClientCapabilities::Skip:
case DebuggerClientCapabilities::StepOut:
case DebuggerClientCapabilities::StepInto:
case DebuggerClientCapabilities::StepOver:
case DebuggerClientCapabilities::Watches:
case DebuggerClientCapabilities::VariableSetValue:
case DebuggerClientCapabilities::ProfilerOpen:
return true;
default:
return false;
}
}
// Process a dbgp command
void QuantaDebuggerDBGp::processCommand(const TQString& datas)
{
kdDebug(24002) << k_lineinfo << datas.left(50) << " (" << datas.length() << " bytes)" << endl;
TQDomDocument data;
data.setContent(datas);
kdDebug(24002) << datas << endl;
// Did we get a normal response?
if(data.elementsByTagName("response").count() > 0)
{
TQDomNode response = data.elementsByTagName("response").item(0);
TQString command = attribute(response, "command");
// tqStatus command
if(command == "status")
setExecutionState(attribute(response, "status"));
// Callback stack
else if(command == "stack_get")
stackShow(response);
// Reply from a user execution action
else if(command == "break"
|| command == "step_over"
|| command == "step_into"
|| command == "step_out")
{
handleError(response);
// If this is the acknoledge of a step command, request the call stack
m_network.sendCommand("stack_get");
setExecutionState(attribute(response, "status"));
handleError(response);
m_network.sendCommand("feature_get", "-n profiler_filename");
sendWatches();
}
// Run
else if(command == "run" )
{
setExecutionState(attribute(response, "status"));
handleError(response);
m_network.sendCommand("stack_get");
}
// Feature get replu
else if(command == "feature_get")
checkSupport(response);
// Reply after adding a breakpoint
else if(command == "breakpoint_set")
setBreakpointKey(response);
else if(command == "typemap_get")
typemapSetup(response);
else if(command == "property_get")
showWatch(response);
else if(command == "property_set")
propertySetResponse(response);
else if(command == "stop")
setExecutionState("stopped");
// Unknown command...
else
{
kdDebug(24002) << " * Unknown command: " << command << endl;
}
}
else if(data.elementsByTagName("init").count() > 0)
{
TQDomNode init = data.elementsByTagName("init").item(0);
initiateSession(init);
return;
}
else
{
debuggerInterface()->showtqStatus(i18n("Unrecognized package: '%1%2'").tqarg(datas.left(50)).tqarg(datas.length() > 50 ? "..." : ""), true);
kdDebug(24002) << datas << endl;
}
}
void QuantaDebuggerDBGp::initiateSession(const TQDomNode& initpacket)
{
if(attribute(initpacket, "protocol_version") != protocolversion)
{
debuggerInterface()->showtqStatus(
i18n("The debugger for %1 uses an unsupported protocol version (%2)")
.tqarg(attribute(initpacket, "language"))
.tqarg(attribute(initpacket, "protocol_version"))
, true);
endSession();
return;
}
TQString path = attribute(initpacket, "fileuri");
if (path.startsWith("file://"))
{
path.remove(0, 7);
}
debuggerInterface()->setActiveLine(mapServerPathToLocal(path), 0);
// Store some vars
m_initialscript = attribute(initpacket, "fileuri");
m_appid = attribute(initpacket, "appid");
// setExecutionState(Starting);
// m_network.sendCommand("feature_get", "-n encoding");
m_network.sendCommand("feature_get", "-n supports_async");
// m_network.sendCommand("feature_get", "-n breakpoint_types");
// m_network.sendCommand("feature_get", "-n profiler_filename");
m_network.sendCommand("feature_get", "-n breakpoint_set");
m_network.sendCommand("feature_get", "-n supports_postmortem");
m_network.sendCommand("typemap_get");
m_network.sendCommand("feature_get", "-n quanta_initialized");
}
void QuantaDebuggerDBGp::stackShow(const TQDomNode&node)
{
bool foundlowlevel = false;
BacktraceType type;
TQString typestr;
// Clear backtrace
debuggerInterface()->backtraceClear();
// Add new one
for(TQDomNode child = node.firstChild(); !child.isNull(); child = child.nextSibling())
{
// Type isnt currently correct with xdebug
// type = (attribute(child, "type") == "file" ? File : Eval);
typestr = attribute(child, "filename");
if(typestr.tqfind(TQRegExp(".*%28[0-9]+%29%20%3A%20eval")) >= 0)
type = Eval;
else
type = File;
// kdDebug(24002) << " * Stck " << attribute(child, "level") << ": " << attribute(child, "type") << " (" << type << ") = " << attribute(child, "filename") << ", " << attribute(child, "lineno") << endl;
// If this is the lowest level and the type
if(type == File && !foundlowlevel)
{
foundlowlevel = true;
debuggerInterface()->setActiveLine(mapServerPathToLocal(attribute(child, "filename")), attribute(child, "lineno").toLong() - 1);
}
debuggerInterface()->backtraceShow(
attribute(child, "level").toLong(),
type,
attribute(child, "filename"),
attribute(child, "lineno").toLong() - 1, // Quanta lines are 0-based, DBGp is 1 based
attribute(child, "where"));
}
}
void QuantaDebuggerDBGp::checkSupport( const TQDomNode & node )
{
TQString feature = attribute(node, "feature_name");
TQString data = node.nodeValue();
if(feature == "supports_async")
m_supportsasync = data.toLong();
// if the debugger supports breakpoints, we have to send all current ones
else if(feature == "breakpoint_set"/* && data.toLong()*/)
debuggerInterface()->refreshBreakpoints();
// Our own feature, probably not available but then we know we're done initiating
else if(feature == "quanta_initialized" )
{
m_network.sendCommand("stack_get");
if(m_executionState != Break)
setExecutionState(m_executionState, true);
}
}
TQString QuantaDebuggerDBGp::attribute(const TQDomNode&node, const TQString &attribute)
{
return node.attributes().namedItem(attribute).nodeValue();
}
// Turn on/off actions related to a debugging session
void QuantaDebuggerDBGp::debuggingState(bool enable)
{
debuggerInterface()->enableAction("debug_kill", enable);
debuggerInterface()->enableAction("debug_stepout", enable);
debuggerInterface()->enableAction("debug_stepinto", enable);
debuggerInterface()->enableAction("debug_stepover", enable);
debuggerInterface()->enableAction("debug_skip", enable);
}
void QuantaDebuggerDBGp::sendWatches()
{
for(TQValueList<TQString>::iterator it = m_watchlist.begin(); it != m_watchlist.end(); ++it)
m_network.sendCommand("property_get", "-n " + (*it));
}
// Return name of debugger
TQString QuantaDebuggerDBGp::getName()
{
return "DBGp"; // no i18n on the name
}
// Send HTTP Request
void QuantaDebuggerDBGp::request()
{
TQString request;
request = debuggerInterface()->activeFileParts(m_startsession);
//if(request.startsWith(m_localBasedir, false))
// request.remove(0, m_localBasedir.length());
//request = m_startsession + request;
kdDebug(24002) << k_funcinfo << ", request: " << request << endl;
debuggerInterface()->sendRequest(request);
}
// Go as fast as possible and dont update current line or watches
void QuantaDebuggerDBGp::run()
{
setExecutionState(Running);
// m_network.sendCommand("run");
// m_network.sendCommand("status");
}
// Step into function
void QuantaDebuggerDBGp::stepInto()
{
m_network.sendCommand("step_into");
}
// Step over function
void QuantaDebuggerDBGp::stepOver()
{
if(m_executionState == Starting)
m_network.sendCommand("step_into");
else
m_network.sendCommand("step_over");
}
// Step out of function
void QuantaDebuggerDBGp::stepOut()
{
m_network.sendCommand("step_out");
}
// Kill the running script
void QuantaDebuggerDBGp::kill()
{
m_network.sendCommand("stop");
}
// Pause execution
void QuantaDebuggerDBGp::pause()
{
if(isActive())
setExecutionState(Break);
else
setExecutionState(Starting);
// m_network.sendCommand("break");
// m_network.sendCommand("status");
}
// Add a breakpoint
void QuantaDebuggerDBGp::addBreakpoint (DebuggerBreakpoint* breakpoint)
{
TQString type;
if(breakpoint->type() == DebuggerBreakpoint::LineBreakpoint)
type = "line";
else if(breakpoint->type() == DebuggerBreakpoint::ConditionalTrue)
type = "conditional";
else
type = "watch";
long id = m_network.sendCommand(
"breakpoint_set",
"-t " + type +
" -f " + mapLocalPathToServer(breakpoint->filePath()) +
" -n " + TQString::number(breakpoint->line() + 1)
, breakpoint->condition());
breakpoint->setKey(TQString("id %1").tqarg(id));
}
void QuantaDebuggerDBGp::setBreakpointKey( const TQDomNode & response )
{
long id;
id = attribute(response, "transaction_id").toLong();
if(id > 0)
{
TQString oldkey = TQString("id %1").tqarg(id);
DebuggerBreakpoint *bp = debuggerInterface()->findDebuggerBreakpoint(oldkey);
if(bp)
debuggerInterface()->updateBreakpointKey(*bp, attribute(response, "id"));
}
}
// Clear a breakpoint
void QuantaDebuggerDBGp::removeBreakpoint(DebuggerBreakpoint* bp)
{
m_network.sendCommand("breakpoint_remove", "-d " + bp->key());
}
// A file was opened...
void QuantaDebuggerDBGp::fileOpened(const TQString&)
{
// sendCommand("reinitialize", 0);
}
// Watch a variable
void QuantaDebuggerDBGp::addWatch(const TQString & variable)
{
if(m_watchlist.tqfind(variable) == m_watchlist.end())
m_watchlist.append(variable);
m_network.sendCommand("property_get", "-n " + variable);
}
// Remove watch
void QuantaDebuggerDBGp::removeWatch(DebuggerVariable *variable)
{
if(m_watchlist.tqfind(variable->name()) != m_watchlist.end())
m_watchlist.remove(m_watchlist.tqfind(variable->name()));
}
// Show conditional breakpoint state
void QuantaDebuggerDBGp::showCondition(const StringMap &)
{
// DebuggerBreakpoint *bp = debuggerInterface()->newDebuggerBreakpoint();
// bp->setType(args["type"] == "true" ? DebuggerBreakpoint::ConditionalTrue : DebuggerBreakpoint::ConditionalChange);
// bp->setCondition(args["expression"]);
// bp->setFilePath(mapServerPathToLocal(args["filename"]));
// bp->setClass(args["class"]);
// bp->setFunction(args["function"]);
// bp->setValue(args["value"]);
//
// bp->setState(DebuggerBreakpoint::Undefined);
//
// debuggerInterface()->showBreakpoint(*bp);
}
// Read configuration
void QuantaDebuggerDBGp::readConfig(TQDomNode node)
{
// Server
TQDomNode valuenode = node.namedItem("serverhost");
m_serverHost = valuenode.firstChild().nodeValue();
if(m_serverHost.isEmpty())
m_serverHost = "localhost";
valuenode = node.namedItem("serverport");
m_serverPort = valuenode.firstChild().nodeValue();
if(m_serverPort.isEmpty())
m_serverPort = "9000";
valuenode = node.namedItem("localbasedir");
m_localBasedir = valuenode.firstChild().nodeValue();
if(debuggerInterface())
debuggerInterface()->Mapper()->setLocalBasedir(m_localBasedir);
valuenode = node.namedItem("serverbasedir");
m_serverBasedir = valuenode.firstChild().nodeValue();
if(debuggerInterface())
debuggerInterface()->Mapper()->setServerBasedir(m_serverBasedir);
valuenode = node.namedItem("listenport");
m_listenPort = valuenode.firstChild().nodeValue();
if(m_listenPort.isEmpty())
m_listenPort = "9000";
valuenode = node.namedItem("startsession");
m_startsession = valuenode.firstChild().nodeValue();
if(m_startsession.isEmpty())
m_startsession = "http://localhost/%rfpp?XDEBUG_SESSION_START=1&XDEBUG_PROFILE";
valuenode = node.namedItem("defaultexecutionstate");
if(valuenode.firstChild().nodeValue().isEmpty())
m_defaultExecutionState = Starting;
else
{
if(valuenode.firstChild().nodeValue() == "break")
m_defaultExecutionState = Starting;
else
m_defaultExecutionState = Running;
}
valuenode = node.namedItem("useproxy");
m_useproxy = valuenode.firstChild().nodeValue() == "1";
valuenode = node.namedItem("errortqmask");
m_errortqmask = valuenode.firstChild().nodeValue().toLong();
kdDebug(24002) << k_funcinfo << ", m_errortqmask = " << m_errortqmask << endl;
// Profiler
valuenode = node.namedItem("profilerfilename");
m_profilerFilename = valuenode.firstChild().nodeValue();
if(m_profilerFilename.isEmpty())
m_profilerFilename = "/tmp/cachegrind.out.%a";
valuenode = node.namedItem("profiler_autoopen");
m_profilerAutoOpen = valuenode.firstChild().nodeValue().toLong();
valuenode = node.namedItem("profiler_mapfilename");
m_profilerMapFilename = valuenode.firstChild().nodeValue().toLong();
}
// Show configuration
void QuantaDebuggerDBGp::showConfig(TQDomNode node)
{
DBGpSettings set(protocolversion);
readConfig(node);
if(m_localBasedir == "/" && m_serverBasedir == "/")
set.checkLocalProject->setChecked(true);
set.lineLocalBasedir->setText(m_localBasedir);
set.lineServerBasedir->setText(m_serverBasedir);
set.lineServerListenPort->setText(m_listenPort);
set.lineStartSession->setText(m_startsession);
if(m_defaultExecutionState == Starting)
set.comboDefaultExecutionState->setCurrentItem(0);
else
set.comboDefaultExecutionState->setCurrentItem(1);
set.checkBreakOnNotice->setChecked(QuantaDebuggerDBGp::Notice & m_errortqmask);
set.checkBreakOnWarning->setChecked(QuantaDebuggerDBGp::Warning & m_errortqmask);
set.checkBreakOnUserNotice->setChecked(QuantaDebuggerDBGp::User_Notice & m_errortqmask);
set.checkBreakOnUserWarning->setChecked(QuantaDebuggerDBGp::User_Warning & m_errortqmask);
set.checkBreakOnUserError->setChecked(QuantaDebuggerDBGp::User_Error & m_errortqmask);
set.lineProfilerFilename->setText(m_profilerFilename);
if(m_profilerAutoOpen)
set.checkProfilerAutoOpen->setChecked(true);
if(m_profilerMapFilename)
set.checkProfilerMapFilename->setChecked(true);
if(set.exec() == TQDialog::Accepted )
{
TQDomElement el;
el = node.namedItem("localproject").toElement();
if (!el.isNull())
el.tqparentNode().removeChild(el);
el = node.ownerDocument().createElement("localproject");
node.appendChild( el );
if(set.checkLocalProject->isChecked())
{
m_localBasedir = "/";
m_serverBasedir = "/";
}
else
{
m_localBasedir = set.lineLocalBasedir->text();
m_serverBasedir = set.lineServerBasedir->text();
if (!m_localBasedir.endsWith("/"))
m_localBasedir.append('/');
if (!m_serverBasedir.endsWith("/"))
m_serverBasedir.append('/');
}
el = node.namedItem("localbasedir").toElement();
if (!el.isNull())
el.tqparentNode().removeChild(el);
el = node.ownerDocument().createElement("localbasedir");
node.appendChild( el );
el.appendChild( node.ownerDocument().createTextNode(m_localBasedir) );
if(debuggerInterface())
debuggerInterface()->Mapper()->setLocalBasedir(m_localBasedir);
el = node.namedItem("serverbasedir").toElement();
if (!el.isNull())
el.tqparentNode().removeChild(el);
el = node.ownerDocument().createElement("serverbasedir");
node.appendChild( el );
if(debuggerInterface())
debuggerInterface()->Mapper()->setServerBasedir(m_serverBasedir);
el.appendChild( node.ownerDocument().createTextNode(m_serverBasedir) );
el = node.namedItem("listenport").toElement();
if (!el.isNull())
el.tqparentNode().removeChild(el);
el = node.ownerDocument().createElement("listenport");
node.appendChild( el );
m_listenPort = set.lineServerListenPort->text();
el.appendChild( node.ownerDocument().createTextNode(m_listenPort) );
el = node.namedItem("startsession").toElement();
if (!el.isNull())
el.tqparentNode().removeChild(el);
el = node.ownerDocument().createElement("startsession");
node.appendChild( el );
m_startsession = set.lineStartSession->text();
el.appendChild(node.ownerDocument().createTextNode(m_startsession));
el = node.namedItem("defaultexecutionstate").toElement();
if (!el.isNull())
el.tqparentNode().removeChild(el);
el = node.ownerDocument().createElement("defaultexecutionstate");
node.appendChild( el );
if(set.comboDefaultExecutionState->currentItem() == 0)
{
m_defaultExecutionState = Starting;
el.appendChild(node.ownerDocument().createTextNode("break"));
}
else
{
m_defaultExecutionState = Running;
el.appendChild(node.ownerDocument().createTextNode("run"));
}
el = node.namedItem("errortqmask").toElement();
if (!el.isNull())
el.tqparentNode().removeChild(el);
el = node.ownerDocument().createElement("errortqmask");
node.appendChild( el );
m_errortqmask = (set.checkBreakOnNotice->isChecked() ? QuantaDebuggerDBGp::Notice : 0)
+ (set.checkBreakOnWarning->isChecked() ? QuantaDebuggerDBGp::Warning : 0)
+ (set.checkBreakOnUserNotice->isChecked() ? QuantaDebuggerDBGp::User_Notice : 0)
+ (set.checkBreakOnUserWarning->isChecked() ? QuantaDebuggerDBGp::User_Warning : 0)
+ (set.checkBreakOnUserError->isChecked() ? QuantaDebuggerDBGp::User_Error : 0);
kdDebug(24002) << k_funcinfo << ", m_errortqmask = " << m_errortqmask << endl;
el.appendChild( node.ownerDocument().createTextNode(TQString::number(m_errortqmask)));
// Profiler
el = node.namedItem("profilerfilename").toElement();
if (!el.isNull())
el.tqparentNode().removeChild(el);
el = node.ownerDocument().createElement("profilerfilename");
node.appendChild( el );
m_profilerFilename = set.lineProfilerFilename->text();
el.appendChild(node.ownerDocument().createTextNode(m_profilerFilename));
el = node.namedItem("profilerfilename_map").toElement();
if (!el.isNull())
el.tqparentNode().removeChild(el);
el = node.ownerDocument().createElement("profilerfilename_map");
node.appendChild( el );
m_profilerMapFilename = (set.checkProfilerMapFilename->isChecked() ? true : false);
el.appendChild(node.ownerDocument().createTextNode(m_profilerMapFilename ? "1" : "0"));
el = node.namedItem("profiler_autoopen").toElement();
if (!el.isNull())
el.tqparentNode().removeChild(el);
el = node.ownerDocument().createElement("profiler_autoopen");
node.appendChild( el );
m_profilerAutoOpen = (set.checkProfilerAutoOpen->isChecked() ? true : false);
el.appendChild(node.ownerDocument().createTextNode(m_profilerAutoOpen ? "1" : "0"));
}
}
// Map a server filepath to a local one using project settings
TQString QuantaDebuggerDBGp::mapServerPathToLocal(const TQString& serverpath)
{
// Translate filename from server to local
return debuggerInterface()->Mapper()->mapServerPathToLocal(serverpath);
}
// Map a local filepath to a server one using project settings
TQString QuantaDebuggerDBGp::mapLocalPathToServer(const TQString& localpath)
{
// Translate filename from local to server
return debuggerInterface()->Mapper()->mapLocalPathToServer(localpath);
}
void QuantaDebuggerDBGp::variableSetValue(const DebuggerVariable &variable)
{
m_network.sendCommand("property_set", "-n " + variable.name(), variable.value());
for(TQValueList<TQString>::iterator it = m_watchlist.begin(); it != m_watchlist.end(); ++it)
if((*it) == variable.name())
{
m_network.sendCommand("property_get", "-n " + variable.name(), variable.value());
return;
}
return;
}
void QuantaDebuggerDBGp::profilerOpen()
{
profilerOpen(true);
}
void QuantaDebuggerDBGp::profilerOpen(bool forceopen)
{
TQString profileroutput = m_profilerFilename;
profileroutput.tqreplace("%a", m_appid);
profileroutput.tqreplace("%c", m_initialscript);
if(m_profilerMapFilename)
profileroutput = mapServerPathToLocal( profileroutput);
bool exists = TQFile::exists(profileroutput);
if(m_profilerAutoOpen || forceopen)
{
if(exists)
{
KRun *run = new KRun(profileroutput);
run->setAutoDelete(true);
}
else
{
if(forceopen)
KMessageBox::sorry(NULL, i18n("Unable to open profiler output (%1)").tqarg(profileroutput), i18n("Profiler File Error"));
else
debuggerInterface()->showtqStatus(i18n("Unable to open profiler output (%1)").tqarg(profileroutput), false);
}
}
else
{
debuggerInterface()->enableAction("debug_profiler_open", exists);
}
}
void QuantaDebuggerDBGp::typemapSetup( const TQDomNode & typemapnode )
{
/*
<map name="bool" type="bool" xsi:type="xsd:boolean"></map>
<map name="int" type="int" xsi:type="xsd:decimal"></map>
<map name="float" type="float" xsi:type="xsd:double"></map>
<map name="string" type="string" xsi:type="xsd:string"></map>
<map name="null" type="null"></map>
<map name="array" type="hash"></map>
<map name="object" type="object"></map>
<map name="resource" type="resource"></map>
*/
// // First defaults in case they are not sent (which seems to be the case with hash and xdebug)
// m_variabletypes["bool"] = "bool";
// m_variabletypes["int"] = "int";
// m_variabletypes["float"] = "float";
// m_variabletypes["string"] = "string";
// m_variabletypes["null"] = "null";
// m_variabletypes["array"] = "hash";
// m_variabletypes["hash"] = "hash";
// m_variabletypes["object"] = "object";
// m_variabletypes["resource"] = "resource";
TQDomNode child = typemapnode.firstChild();
while(!child.isNull())
{
if(child.nodeName() == "map")
{
m_variabletypes[attribute(child, "name")] = attribute(child, "type");
}
child = child.nextSibling();
}
}
void QuantaDebuggerDBGp::showWatch( const TQDomNode & variablenode)
{
debuggerInterface()->showVariable(buildVariable(variablenode.firstChild()));
}
void QuantaDebuggerDBGp::propertySetResponse( const TQDomNode & setnode)
{
if(attribute(setnode, "success") == "0")
{
debuggerInterface()->showtqStatus(i18n("Unable to set value of variable."), true);
}
}
DebuggerVariable* QuantaDebuggerDBGp::buildVariable( const TQDomNode & variablenode)
{
/*
Sample:
<property name="$arrayVar" fullname="$arrayVar" address="-1073754976" type="hash" tqchildren="1" numtqchildren="4">
<property name="birthyear" fullname="$arrayVar['birthyear']" address="135522364" type="int">
<![CDATA[1949]]>
</property>
<property name="songs" fullname="$arrayVar['songs']" address="135522236" type="hash" tqchildren="1" numtqchildren="3">
<property name="0" fullname="$arrayVar['songs'][0]" address="135522332" type="string" encoding="base64">
<![CDATA[SW5ub2NlbnQgV2hlbiBZb3UgRHJlYW0=]]>
</property>
<property name="1" fullname="$arrayVar['songs'][1]" address="135522300" type="string" encoding="base64">
<![CDATA[Q2hyaXN0bWFzIENhcmQgRnJvbSBBIEhvb2tlcg==]]>
</property>
</property>
</property>
*/
TQString name = attribute(variablenode, "name");
TQString type = m_variabletypes[attribute(variablenode, "type")];
if(type == "int")
{
TQString value = variablenode.firstChild().nodeValue();
return debuggerInterface()->newDebuggerVariable( name, value, DebuggerVariableTypes::Integer);
}
else if (type == "string")
{
TQCString value = TQCString(variablenode.firstChild().nodeValue().ascii());
value = KCodecs::base64Decode(value);
return debuggerInterface()->newDebuggerVariable( name, value, DebuggerVariableTypes::String);
}
else if (type == "bool")
{
TQString value = variablenode.firstChild().nodeValue();
return debuggerInterface()->newDebuggerVariable( name, value, DebuggerVariableTypes::Boolean);
}
else if (type == "resource")
{
TQString value = variablenode.firstChild().nodeValue();
return debuggerInterface()->newDebuggerVariable( name, value, DebuggerVariableTypes::Resource);
}
else if (type == "float")
{
TQString value = variablenode.firstChild().nodeValue();
return debuggerInterface()->newDebuggerVariable( name, value, DebuggerVariableTypes::Float);
}
else if (type == "null")
{
TQString value = variablenode.firstChild().nodeValue();
return debuggerInterface()->newDebuggerVariable( name, "", DebuggerVariableTypes::Undefined);
}
else if (type == "hash" || type == "array" || type == "object")
{
TQDomNode child = variablenode.firstChild();
TQPtrList<DebuggerVariable> vars ;
while(!child.isNull())
{
DebuggerVariable* var = buildVariable( child);
if(var)
vars.append(var);
child = child.nextSibling();
}
if(type == "object")
return debuggerInterface()->newDebuggerVariable(name, vars, DebuggerVariableTypes::Object);
else
return debuggerInterface()->newDebuggerVariable(name, vars, DebuggerVariableTypes::Array);
}
return debuggerInterface()->newDebuggerVariable(name, "", DebuggerVariableTypes::Error);;
}
void QuantaDebuggerDBGp::handleError(const TQDomNode & statusnode )
{
if(attribute(statusnode, "reason") == "error" || attribute(statusnode, "reason") == "aborted")
{
TQDomNode errornode = statusnode.firstChild();
while(!errornode.isNull())
{
if(errornode.nodeName() == "error")
{
if(attribute(statusnode, "reason") == "error")
{
// Managable error
long error = attribute(errornode, "code").toLong();
if(!(error & m_errortqmask))
{
setExecutionState(Running);
}
else
{
emit updatetqStatus(DebuggerUI::HaltedOnError);
debuggerInterface()->showtqStatus(errornode.firstChild().nodeValue(), true);
}
break;
}
else
{
// Fatal error
emit updatetqStatus(DebuggerUI::HaltedOnError);
debuggerInterface()->showtqStatus(errornode.firstChild().nodeValue(), true);
}
}
errornode = errornode.nextSibling();
}
}
}
#include "quantadebuggerdbgp.moc"