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/kxsldbg/kxsldbgpart/libxsldbg/debugXSL.cpp

2119 lines
65 KiB

/***************************************************************************
debugXSL.c - debugger commands to use
-------------------
begin : Sun Sep 16 2001
copyright : (C) 2001 by Keith Isdale
email : k_isdale@tpg.com.au
***************************************************************************/
/***************************************************************************
* *
* 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. *
* *
***************************************************************************/
/*
* Orinal file : debugXML.c : This is a set of routines used for
* debugging the tree produced by the XML parser.
*
* New file : shell.c : Debug support version
*
* See Copyright for the status of this software.
*
* Daniel Veillard <daniel@veillard.com>
*
* Permission obtained to modify the LGPL'd code and extend to include breakpoints, inspections of
* stylesheet source, xml data, stylesheet variables
*/
#ifdef WIN32
#include <wtypes.h>
#include <winbase.h> /* needed fort the sleep function */
#endif
#include "xsldbg.h"
#include "files.h"
#include "cmds.h" /* list of command Id's */
#include "debug.h"
#include "debugXSL.h"
#include "options.h"
#include "breakpoint.h"
#include "help.h"
#include <stdlib.h>
#include <libxslt/transform.h> /* needed by source command */
#include <libxslt/xsltInternals.h>
#include <libxml/debugXML.h>
#include <stdio.h>
/* language change support */
#ifdef LOCALE_PREFIX
#include <locale.h>
#endif
#include "xsldbgmsg.h"
#include "xsldbgthread.h" /* for get thread status */
#include "xsldbgio.h"
/* current template being processed */
xsltTemplatePtr rootCopy;
/* how may items have been printed */
int printCount;
/* used to sending small amounts data when xsldbg runs as a thread */
xmlChar messageBuffer[2000];
/* To achieve the same fucntionality of a next command
we first do a step, then a step up */
int nextCommandActive = 0;
/* Do we print the values for watches each time the debugger stops */
int showWatchesActive = 1;
extern FILE *terminalIO;
int xsldbgStop = 0;
int xsldbgValidateBreakpoints = BREAKPOINTS_NEED_VALIDATION;
int xsldbgHasLineNumberFix;
bool xsldbgReachedFirstTemplate = false;
/* valid commands of xslDbgShell */
const char *commandNames[] = {
"help",
"bye",
"exit",
"quit",
"step",
"stepup",
"stepdown",
"next", /* next ie step over template function call*/
"continue",
"run",
"templates",
"where",
"frame",
"stylesheets",
"break",
"showbreak",
"delete",
"enable",
"disable",
"ls",
"dir",
"du",
"cat",
"print",
"pwd",
"dump",
"base",
"globals",
"locals",
/* "cat", already listed */
"source",
"data",
"output", /* output file name */
"cd",
/* file related */
/* "output", already listed */
"entities",
"system",
"public",
"encoding",
"validate",
"load",
"save",
"write",
"free",
/* Operating system related */
"chdir",
"shell",
"tty",
/* libxslt parameter related */
"addparam",
"delparam",
"showparam",
"setoption",
"options",
/* extra options */
"trace",
"walk",
"addwatch",
"delwatch",
"showwatch",
/* searching */
"search",
/*variable value change */
"set",
/* language change */
"lang",
NULL /* Indicate the end of list */
};
/* valid commands of xslShell in there alternative|shorter format */
const char *shortCommandNames[] = {
"h",
"bye",
"exit",
"q", /*quit */
"s", /* step */
"up", /*stepup */
"down", /* stepdown */
"n", /* next ie step over function call*/
"c", /* continue */
"r", /* run */
"t", /* templates */
"w", /* where */
"f",
"style",
"b", /* break */
"show",
"d", /* delete */
"e", /* enabled */
"disable",
"ls",
"dir",
"du",
"cat",
"print",
"pwd",
"dump",
"base",
"globals",
"locals",
/* "cat", already listed */
"source",
"data",
"o", /* output file name */
"cd",
/* file related */
/* "output", already listed */
"ent", /* entities command */
"sys", /* sytem command */
"pub", /* public command */
"encoding",
"validate",
"load",
"save",
"write",
"free",
/* Operating system related */
"chdir",
"shell",
"tty",
/* libxslt parameter related */
"addparam",
"delparam",
"showparam",
"setoption",
"options",
/* extra options/commands */
"trace",
"walk",
"watch",
"delwatch",
"watches",
/* searching */
"search",
/*variable value change */
"set",
/* language change */
"lang",
NULL /* Indicate the end of list */
};
/* some convenient short cuts when using cd command*/
const char *cdShortCuts[] = {
"<<",
">>",
"<-",
"->",
NULL /* indicate end of list */
};
/* what to replace shortcuts with */
const char *cdAlternative[] = {
"preceding-sibling::node()",
"following-sibling::node()",
"ancestor::node()",
"descendant::node()",
NULL /* indicate end of list */
};
/* what enum to use for shortcuts */
enum ShortcutsEnum {
DEBUG_PREV_SIBLING = 200,
DEBUG_NEXT_SIBLING,
DEBUG_ANCESTOR_NODE,
DEBUG_DESCENDANT_NODE
};
#include <libxml/xpathInternals.h>
#include <libxslt/extra.h>
#include <string.h>
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#include <libxml/xmlmemory.h>
#include <libxml/tree.h>
#include <libxml/parser.h>
#include <libxml/valid.h>
#include <libxml/debugXML.h>
#include <libxml/HTMLtree.h>
#include <libxml/HTMLparser.h>
/* -----------------------------------------
Private function declarations for debugXSL.c
-------------------------------------------*/
/* xslDbgCd :
* Change directories
* @styleCtxt : current stylesheet context
* @ctxt : current shell context
* @arg : path to change to
* @source : is valid
*
* Returns 1 on success,
* 0 otherwise
*/
int xslDbgCd(xsltTransformContextPtr styleCtxt, xmlShellCtxtPtr ctxt,
xmlChar * arg, xmlNodePtr source);
/**
* xslDbgPrintCallStack:
* @arg : the number of frame to print, NULL if all items
*
* Print all items found on the callStack
*
* Returns 1 on success,
* 0 otherwise
*/
int xslDbgPrintCallStack(const xmlChar * arg);
/**
* xslDbgSleep:
* @delay : the number of microseconds to delay exection by
*
* Delay execution by a specified number of microseconds. On some system
* this will not be at all accurate.
*/
void xslDbgSleep(long delay);
/**
* xslDbgWalkContinue:
*
* Delay execution for time as indicated by OPTION_WALK_SPEED
* Can only be called from within shellPrompt!
* OPTION_WALK_SPEED != WALKSPEED_STOP
*
* Returns 1 if walk is to continue,
* 0 otherwise
*/
int xslDbgWalkContinue(void);
/**
* addBreakPointNode:
* @payload : valid breakPointPtr
* @data : not used
* @name : not used
*
* Convert payload into format needed, and add to search dataBase
*/
void
addBreakPointNode(void *payload, void *data,
xmlChar * name);
/**
* addSourceNode:
* @payload : valid xsltStylesheetPtr
* @data : not used
* @name : not used
*
* Convert payload into format needed, and add to search dataBase
*/
void
addSourceNode(void *payload, void *data,
xmlChar * name);
/**
* addTemplateNode:
* @payload : valid xsltTemplatePtr
* @data : not used
* @name : not used
*
* Convert payload into format needed, and add to search dataBase
*/
void
addTemplateNode(void *payload, void *data,
xmlChar * name);
/**
* addGlobalNode:
* @payload : valid xmlNodePtr of global variable
* @data : not used
* @name : not used
*
* Convert payload into format needed, and add to search dataBase
*/
void
addGlobalNode(void *payload, void *data,
xmlChar * name);
/**
* addLocalNode:
* @payload : valid xmlNodePtr of local variable
* @data : not used
* @name : not used
*
* Convert payload into format needed, and add to search dataBase
*/
void
addLocalNode(void *payload, void *data,
xmlChar * name);
/**
* addIncludeNode:
* @payload : valid xmlNodePtr of include instuction
* @data : not used
* @name : not used
*
* Convert payload into format needed, and add to search dataBase
*/
void
addIncludeNode(void *payload, void *data,
xmlChar * name);
/**
* addCallStackItems:
*
* Convert call stack items into format needed, and add to search dataBase
*/
void
addCallStackItems(void);
/**
* shellPrompt:
* @source: The current stylesheet instruction being executed
* @doc: The current document node being processed
* @filename: Not used
* @input: The function to call to when reading commands from stdio
* @output: Where to put the results
* @styleCtxt: Is valid
*
* Present to the user the xsldbg shell
*/
void shellPrompt(xmlNodePtr source, xmlNodePtr doc,
xmlChar * filename,
xmlShellReadlineFunc input,
FILE * output, xsltTransformContextPtr styleCtxt);
/* -------------------------------------
End private functions
---------------------------------------*/
/**
* debugXSLGetTemplate:
*
* Return the last template node found, if an
*
* Returns The last template node found, if any
*/
xsltTemplatePtr
debugXSLGetTemplate(void)
{
return rootCopy;
}
/****************************************************************
* *
* The XSL shell related functions *
* *
****************************************************************/
/* xslDbgCd :
* Change directories
* @styleCtxt : current stylesheet context
* @ctxt : current shell context
* @arg : path to change to and in UTF-8
* @source : is valid
*
* Returns 1 on success,
* 0 otherwise
*/
int
xslDbgCd(xsltTransformContextPtr styleCtxt, xmlShellCtxtPtr ctxt,
xmlChar * arg, xmlNodePtr source)
{
xmlXPathObjectPtr list = NULL;
int result = 0;
int offset = 2; /* in some cases I'm only interested after first two chars */
if (!ctxt) {
xsldbgGenericErrorFunc(i18n("Error: Debugger has no files loaded. Try reloading files.\n"));
return result;
}
if (arg == NULL)
arg = (xmlChar *) "";
if (arg[0] == 0) {
ctxt->node = (xmlNodePtr) ctxt->doc;
} else {
if ((arg[0] == '-') && (xmlStrLen(arg) > 2)) {
if (styleCtxt) {
if (arg[1] == 't') {
xmlNodePtr templateNode;
/* quickly find a template */
/* skip any white spaces */
while (_IS_BLANK(arg[offset]))
offset++;
templateNode =
findTemplateNode(styleCtxt->style, &arg[offset]);
if (!templateNode) {
xsldbgGenericErrorFunc(i18n("Error: The XSLT template named \"%1\" was not found.\n").arg(xsldbgText(&arg[offset])));
return result;
} else {
xsldbgGenericErrorFunc(i18n(" template: \"%1\"\n").arg(xsldbgText(&arg[offset])));
ctxt->node = templateNode;
result = 1;
return result;
}
} else if (arg[1] == 's') {
/*quickly switch to another stylesheet node */
xmlXPathContextPtr pctxt;
if (source) {
pctxt = xmlXPathNewContext(source->doc);
if (pctxt == NULL) {
xmlFree(ctxt);
/* xslDebugStatus = DEBUG_QUIT; */
return result;
}
if (!xmlXPathNsLookup(pctxt, (xmlChar *) "xsl"))
xmlXPathRegisterNs(pctxt, (xmlChar *) "xsl",
XSLT_NAMESPACE);
list =
xmlXPathEval((xmlChar *) & arg[offset], pctxt);
if (pctxt) {
xmlFree(pctxt);
}
} else {
xsldbgGenericErrorFunc(i18n("Error: Unable to cd. No stylesheet loaded.\n"));
}
} else {
xsldbgGenericErrorFunc(i18n("Error: Unknown arguments to the command %1.\n").arg("cd"));
}
} else
xsldbgGenericErrorFunc(i18n("Error: Unable to cd. No stylesheet loaded.\n"));
} else {
xmlNodePtr savenode;
if (styleCtxt) {
savenode = styleCtxt->xpathCtxt->node;
ctxt->pctxt->node = ctxt->node;
styleCtxt->xpathCtxt->node = ctxt->node;
if (!xmlXPathNsLookup(ctxt->pctxt, (xmlChar *) "xsl"))
xmlXPathRegisterNs(ctxt->pctxt, (xmlChar *) "xsl",
XSLT_NAMESPACE);
list = xmlXPathEval((xmlChar *) arg, styleCtxt->xpathCtxt);
styleCtxt->xpathCtxt->node = savenode;
} else if (ctxt->pctxt) {
if (!xmlXPathNsLookup(ctxt->pctxt, (xmlChar *) "xsl"))
xmlXPathRegisterNs(ctxt->pctxt, (xmlChar *) "xsl",
XSLT_NAMESPACE);
list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
} else {
xsldbgGenericErrorFunc(i18n("Error: Invalid arguments to the command %1.\n").arg("cd"));
}
}
if (list != NULL) {
switch (list->type) {
case XPATH_NODESET:
if (list->nodesetval) {
if (list->nodesetval->nodeNr == 1) {
ctxt->node = list->nodesetval->nodeTab[0];
/* tell the application about the new line
* number we are looking at */
if (getThreadStatus() == XSLDBG_MSG_THREAD_RUN) {
int breakpoint = 0;
xsldbgUpdateFileDetails(ctxt->node);
notifyXsldbgApp(XSLDBG_MSG_LINE_CHANGED,
&breakpoint);
}
result = 1;
} else
xsldbgGenericErrorFunc(i18n("Warning: XPath %1 is a Node Set with %n child.", "Warning: XPath %1 is a Node Set with %n children.", list->nodesetval->nodeNr).arg(xsldbgText(arg)) + QString("\n"));
} else {
xsldbgGenericErrorFunc(i18n("Warning: XPath %1 is an empty Node Set.\n").arg(xsldbgText(arg)));
}
break;
default:
xmlShellPrintXPathError(list->type, (char *) arg);
}
xmlXPathFreeObject(list);
} else {
xsldbgGenericErrorFunc(i18n("Error: XPath %1 was not found.\n").arg(xsldbgText(arg)));
}
if (ctxt->pctxt)
ctxt->pctxt->node = NULL;
}
return result;
}
/**
* xslDbgPrintCallStack:
* @arg : the number of frame to print, NULL if all items
*
* Print all items found on the callStack
*
* Returns 1 on success,
* 0 otherwise
*/
int
xslDbgPrintCallStack(const xmlChar * arg)
{
int depth = 0;
int result = 1;
callPointPtr callPointItem;
if (arg == NULL) {
if (getThreadStatus() == XSLDBG_MSG_THREAD_RUN) {
notifyListStart(XSLDBG_MSG_CALLSTACK_CHANGED);
/* we send the oldest frame stack first */
for (depth = 1; depth <= callStackGetDepth(); depth++) {
callPointItem = callStackGet(depth);
if (callPointItem && callPointItem->info) {
notifyListQueue(callPointItem);
}
}
notifyListSend();
} else {
xmlChar *nameTemp, *modeTemp;
for (depth = callStackGetDepth(); depth >= 1; depth--) {
callPointItem = callStackGet(depth);
nameTemp = NULL;
modeTemp = NULL;
if (callPointItem && callPointItem->info) {
if (depth == callStackGetDepth()) {
xmlChar *curUrl = xsldbgUrl();
long curLine = xsldbgLineNo();
/* if possible list the current location */
if (rootCopy && (rootCopy->match || rootCopy->name)
&& curUrl) {
xmlChar *rootNameTemp, *rootModeTemp;
rootNameTemp = fullQName(rootCopy->nameURI, rootCopy->name);
rootModeTemp = fullQName(rootCopy->modeURI, rootCopy->mode);
if (rootNameTemp && rootModeTemp){
if (rootCopy->match)
/* display information about the current XSLT template */
xsldbgGenericErrorFunc(i18n("#%1 template: \"%2\" mode: \"%3\"").arg(depth).arg(xsldbgText(rootCopy->match)).arg(xsldbgText(rootModeTemp)));
else
/* display information about the current XSLT template */
xsldbgGenericErrorFunc(i18n("#%1 template: \"%2\" mode: \"%3\"").arg(depth).arg(xsldbgText(rootNameTemp)).arg(xsldbgText(rootModeTemp)));
/* display where we are in the source/document file */
xsldbgGenericErrorFunc(i18n(" in file \"%1\" at line %2\n").arg(xsldbgUrl(curUrl)).arg(curLine));
}else{
xsldbgGenericErrorFunc(i18n("Error: Out of memory.\n"));
result = 0;
}
if (rootNameTemp){
xmlFree(rootNameTemp);
rootNameTemp = NULL;
}
if (rootModeTemp){
xmlFree(rootModeTemp);
rootModeTemp = NULL;
}
} else if (curUrl) {
/* display information about the current XSLT template */
xsldbgGenericErrorFunc(i18n("#%1 template: \"LIBXSLT_DEFAULT\" mode: \"\"").arg(depth));
/* display where we are in the source/document file */
xsldbgGenericErrorFunc(i18n(" in file \"%1\" at line %2\n").arg(xsldbgUrl(curUrl)).arg(curLine));
}
if (curUrl)
xmlFree(curUrl);
}
nameTemp = fullQName(callPointItem->info->templateURI,
callPointItem->info->templateName);
modeTemp = fullQName(callPointItem->info->modeURI,
callPointItem->info->modeName);
if (nameTemp && modeTemp){
/* display information about the current XSLT template */
xsldbgGenericErrorFunc(i18n("#%1 template: \"%2\" mode: \"%3\"").arg(depth - 1).arg(xsldbgText(nameTemp)).arg(xsldbgText(modeTemp)));
if (callPointItem->info->url)
/* display where we are in the source/document file */
xsldbgGenericErrorFunc(i18n(" in file \"%1\" at line %2\n").arg(xsldbgUrl(callPointItem->info->url)).arg(callPointItem->lineNo));
else
xsldbgGenericErrorFunc("\n");
}else{
xsldbgGenericErrorFunc(i18n("Error: Out of memory.\n"));
result = 0;
}
if (nameTemp){
xmlFree(nameTemp);
nameTemp = NULL;
}
if(modeTemp){
xmlFree(modeTemp);
modeTemp = NULL;
}
} else {
#ifdef WITH_XSLDBG_DEBUG_PROCESS
xsltGenericError(xsltGenericErrorContext,
"Error: Call stack item not found at depth %d : xslDbgPrintCallStack\n", depth);
#endif
result = 0;
break;
}
}
if (callStackGetDepth() == 0)
xsldbgGenericErrorFunc(i18n("\tNo items in call stack.\n"));
else
xsldbgGenericErrorFunc("\n");
}
} else {
long templateDepth = atol((char *) arg);
if (getThreadStatus() == XSLDBG_MSG_THREAD_RUN) {
/* should never happen but just in case, when running as a
* thread always provide NO params to the where command */
#ifdef WITH_XSLDBG_DEBUG_PROCESS
xsltGenericError(xsltGenericErrorContext,
"Error: Notification of a frame not supported\n");
#endif
result = 0;
return result;
}
if (templateDepth >= 0) {
callPointItem = callStackGet(templateDepth + 1);
if (callPointItem && callPointItem->info) {
/* display information about the current XSLT template */
xsldbgGenericErrorFunc(i18n("#%1 template: \"%2\"").arg(templateDepth).arg(xsldbgText(callPointItem->info->templateName)));
/* should alays be present but .. */
if (callPointItem->info->url)
/* display where we are in the source/document file */
xsldbgGenericErrorFunc(i18n(" in file \"%1\" at line %2\n").arg(xsldbgUrl(callPointItem->info->url)).arg(callPointItem->lineNo));
else
xsldbgGenericErrorFunc("\n");
} else {
#ifdef WITH_XSLDBG_DEBUG_PROCESS
xsltGenericError(xsltGenericErrorContext,
"Error: Call stack item not found at templateDepth %d : xslDbgPrintCallStack\n", depth);
#endif
result = 0;
}
}
}
return result;
}
/**
* xslDbgSleep:
* @delay : the number of microseconds to delay exection by
*
* Delay execution by a specified number of microseconds. On some system
* this will not be at all accurate.
*/
void
xslDbgSleep(long delay)
{
#ifdef HAVE_USLEEP
usleep(delay);
#else
#ifdef WIN32
Sleep(delay / 1000);
#else
/* try to delay things by doing a lot of floating point
* multiplication
*/
long loop1, loop2;
float f1 = 1.0000001, f2;
for (loop1 = 0; loop1 < 100000 * delay; loop1++)
for (loop2 = 0; loop2 < 100000; loop2++) {
f2 = f1 * f1;
}
#endif
#endif
}
/**
* xslDbgWalkContinue:
*
* Delay execution for time as indicated by OPTION_WALK_SPEED
* Can only be called from within shellPrompt!
* OPTION_WALK_SPEED != WALKSPEED_STOP
*
* Returns 1 if walk is to continue,
* 0 otherwise
*/
int
xslDbgWalkContinue(void)
{
int result = 0, speed = optionsGetIntOption(OPTIONS_WALK_SPEED);
/* We need to ensure that output is realy sent. Otherwise
* walking using xemacs under WIN32 will not work */
fflush(stderr);
switch (speed) {
case WALKSPEED_1:
case WALKSPEED_2:
case WALKSPEED_3:
case WALKSPEED_4:
case WALKSPEED_5:
case WALKSPEED_6:
case WALKSPEED_7:
case WALKSPEED_8:
case WALKSPEED_9:
/* see options.h for defintion of WALKDAY */
xslDbgSleep(speed * WALKDELAY);
result = 1;
break;
default: /* stop walking */
optionsSetIntOption(OPTIONS_WALK_SPEED, WALKSPEED_STOP);
xslDebugStatus = DEBUG_STOP;
break;
}
return result;
}
/**
* addBreakPointNode:
* @payload : valid breakPointPtr
* @data : not used
* @name : not used
*
* Convert payload into format needed, and add to search dataBase
*/
void
addBreakPointNode(void *payload, void *data,
xmlChar * name)
{
Q_UNUSED(data);
Q_UNUSED(name);
xmlNodePtr node = searchBreakPointNode((breakPointPtr) payload);
searchAdd(node);
}
/**
* addSourceNode:
* @payload : valid xsltStylesheetPtr
* @data : not used
* @name : not used
*
* Convert payload into format needed, and add to search dataBase
*/
void
addSourceNode(void *payload, void *data,
xmlChar * name)
{
Q_UNUSED(data);
Q_UNUSED(name);
xmlNodePtr node = searchSourceNode((xsltStylesheetPtr) payload);
searchAdd(node);
}
/**
* addTemplateNode:
* @payload : valid xsltTemplatePtr
* @data : not used
* @name : not used
*
* Convert payload into format needed, and add to search dataBase
*/
void
addTemplateNode(void *payload, void *data,
xmlChar * name)
{
Q_UNUSED(data);
Q_UNUSED(name);
xmlNodePtr node =
searchTemplateNode(((xsltTemplatePtr) payload)->elem);
searchAdd(node);
}
/**
* addGlobalNode:
* @payload : valid xmlNodePtr of global variable
* @data : not used
* @name : not used
*
* Convert payload into format needed, and add to search dataBase
*/
void
addGlobalNode(void *payload, void *data,
xmlChar * name)
{
Q_UNUSED(data);
Q_UNUSED(name);
xmlNodePtr node = searchGlobalNode((xmlNodePtr) payload);
searchAdd(node);
}
/**
* addLocalNode:
* @payload : valid xmlNodePtr of local variable
* @data : not used
* @name : not used
*
* Convert payload into format needed, and add to search dataBase
*/
void
addLocalNode(void *payload, void *data,
xmlChar * name)
{
Q_UNUSED(data);
Q_UNUSED(name);
xmlNodePtr node = searchLocalNode((xmlNodePtr) payload);
searchAdd(node);
}
/**
* addIncludeNode:
* @payload : valid xmlNodePtr of include instuction
* @data : not used
* @name : not used
*
* Convert payload into format needed, and add to search dataBase
*/
void
addIncludeNode(void *payload, void *data,
xmlChar * name)
{
Q_UNUSED(data);
Q_UNUSED(name);
xmlNodePtr node = searchIncludeNode((xmlNodePtr) payload);
searchAdd(node);
}
/**
* addCallStackItems:
*
* Convert call stack items into format needed, and add to search dataBase
*/
void
addCallStackItems(void)
{
callPointPtr item;
xmlNodePtr node;
int depth;
for (depth = callStackGetDepth(); depth > 0; depth--) {
item = callStackGet(depth);
if (item) {
node = searchCallStackNode(item);
if (node)
searchAdd(node);
}
}
}
/**
* updateSearchData:
* @styleCtxt: Not used
* @style: Is valid
* @data: Not used but MUST be NULL for the moment
* @variableTypes: What types of variables to look
*
* Update the searchDatabase
*
* Returns 1 on success,
* 0 otherwise
*/
int
updateSearchData(xsltTransformContextPtr styleCtxt,
xsltStylesheetPtr style,
void *data, VariableTypeEnum variableTypes)
{
Q_UNUSED(styleCtxt);
Q_UNUSED(variableTypes);
int result = 0;
if (!style) {
#ifdef WITH_XSLDBG_DEBUG_PROCESS
xsltGenericError(xsltGenericErrorContext,
"Error: Unable to update search database no stylesheet loaded\n");
#endif
return result;
}
searchEmpty();
xsldbgGenericErrorFunc(i18n("Information: Updating search database. This may take a while...\n"));
/* add items to the search dataBase */
addCallStackItems();
xsldbgGenericErrorFunc(i18n("Information: Looking for breakpoints.\n"));
walkBreakPoints((xmlHashScanner) addBreakPointNode, data);
xsldbgGenericErrorFunc(i18n("Information: Looking for imports and top-level stylesheets.\n"));
walkStylesheets((xmlHashScanner) addSourceNode, data, style);
xsldbgGenericErrorFunc(i18n("Information: Looking for xsl:includes.\n"));
walkIncludeInst((xmlHashScanner) addIncludeNode, data, style);
xsldbgGenericErrorFunc(i18n("Information: Looking for templates.\n"));
walkTemplates((xmlHashScanner) addTemplateNode, data, style);
xsldbgGenericErrorFunc(i18n("Information: Looking for global variables.\n"));
walkGlobals((xmlHashScanner) addGlobalNode, data, style);
xsldbgGenericErrorFunc(i18n("Information: Looking for local variables.\n"));
walkLocals((xmlHashScanner) addLocalNode, data, style);
xsldbgGenericErrorFunc(i18n("Information: Formatting output.\n"));
result = searchSave(NULL);
return result;
}
/**
* debugXSLBreak:
* @templ: The source node being executed
* @node: The data node being processed
* @root: The template being applied to "node"
* @ctxt: The transform context for stylesheet being processed
*
* A break point has been found so pass control to user
*/
void
debugXSLBreak(xmlNodePtr templ, xmlNodePtr node, xsltTemplatePtr root,
xsltTransformContextPtr ctxt)
{
xmlDocPtr tempDoc = NULL;
xmlNodePtr tempNode = NULL;
rootCopy = root;
static const xmlChar *lastTemplate = NULL;
xmlBufferPtr buffer = xmlBufferCreate();
static char mybuff[6] = " 0\n\x0";
if (ctxt && templ && root && !xsldbgReachedFirstTemplate)
xsldbgReachedFirstTemplate = true;
if (templ == NULL) {
tempDoc = xmlNewDoc((xmlChar *) "1.0");
if (!tempDoc)
return;
tempNode = xmlNewNode(NULL, (xmlChar *) "xsldbg_default_node");
if (!tempNode) {
xmlFreeDoc(tempDoc);
return;
}
xmlAddChild((xmlNodePtr) tempDoc, tempNode);
templ = tempNode;
}
if (node == NULL)
node = (xmlNodePtr) filesGetMainDoc();
if (node == NULL) {
tempDoc = xmlNewDoc((xmlChar *) "1.0");
if (!tempDoc)
return;
tempNode = xmlNewNode(NULL, (xmlChar *) "xsldbg_default_node");
if (!tempNode) {
xmlFreeDoc(tempDoc);
return;
}
xmlAddChild((xmlNodePtr) tempDoc, tempNode);
node = tempNode;
}
if (root) {
xmlChar *nameTemp = NULL, *modeTemp = NULL;
nameTemp = fullQName(root->nameURI, root->name);
modeTemp = fullQName(root->modeURI, root->mode);
if (!nextCommandActive){
/* we only want messages if we are not
in the process of completing the next command */
if (terminalIO == NULL) {
if (root->match){
xsldbgGenericErrorFunc(i18n("\nReached template: \"%1\" mode: \"%2\"\n").arg(xsldbgText(root->match)).arg(xsldbgText(modeTemp)));
if (lastTemplate != root->match && buffer){
xmlBufferCCat(buffer, "\nreached matched template:");
xmlBufferCat(buffer, root->match);
xmlBufferCCat(buffer, mybuff);
xsltCopyTextString(ctxt, ctxt->insert,xmlBufferContent(buffer),0);
mybuff[1]++;
lastTemplate = root->match;
}
}else{
xsldbgGenericErrorFunc(i18n("\nReached template: \"%1\" mode: \"%2\"\n").arg(xsldbgText(nameTemp)).arg(xsldbgText(modeTemp)));
if (lastTemplate != root->name && buffer){
xmlBufferCCat(buffer, "\nreached named template:");
xmlBufferCat(buffer,root->match);
xmlBufferCCat(buffer,mybuff);
xsltCopyTextString(ctxt, ctxt->insert,xmlBufferContent(buffer),0);
mybuff[1]++;
lastTemplate = root->name;
}
}
if (buffer)
xmlBufferFree(buffer);
} else {
if ((xslDebugStatus == DEBUG_TRACE) ||
(xslDebugStatus == DEBUG_WALK)) {
QString message;
if (root->match)
message = i18n("\nReached template: \"%1\" mode: \"%2\"\n").arg(xsldbgText(root->match)).arg(xsldbgText(modeTemp));
else
message = i18n("\nReached template: \"%1\" mode: \"%2\"\n").arg(xsldbgText(nameTemp)).arg(xsldbgText(modeTemp));
fprintf(terminalIO, "%s", message.local8Bit().data());
}
}
}
if (nameTemp)
xmlFree(nameTemp);
if (modeTemp)
xmlFree(modeTemp);
}
shellPrompt(templ, node, (xmlChar *) "index.xsl",
(xmlShellReadlineFunc) xslDbgShellReadline, stdout, ctxt);
if (tempDoc)
xmlFreeDoc(tempDoc);
}
/* Highly modified function based on xmlShell */
/**
* shellPrompt:
* @source: The current stylesheet instruction being executed
* @doc: The current document node being processed
* @filename: Not used
* @input: The function to call to when reading commands from stdio
* @output: Where to put the results
* @styleCtxt: Is valid
*
* Present to the user the xsldbg shell
*/
void
shellPrompt(xmlNodePtr source, xmlNodePtr doc, xmlChar * filename,
xmlShellReadlineFunc input, FILE * output,
xsltTransformContextPtr styleCtxt)
{
xmlChar prompt[DEBUG_BUFFER_SIZE] = "/ > ";
xmlChar *cmdline = NULL, *cur;
int nbargs = 0;
int loadedFiles = 0;
int commandId = -1; /* stores what was the last
* command id entered by user */
xmlChar command[DEBUG_BUFFER_SIZE]; /* holds the command user entered */
xmlChar arg[DEBUG_BUFFER_SIZE]; /* holds any extra arguments to
* command entered */
xmlChar dir[DEBUG_BUFFER_SIZE]; /* temporary buffer used by where
* and pwd commands */
int cmdResult; /* result of last command */
int shortCutId = -1; /* used by cd command */
int i;
static int showSource = 1; /* Do we first show source or data ? */
xmlChar *baseUri = NULL; /* for used for included xml entities */
const xmlChar *breakUri;
/* for convenience keep track of which node was last
* selected of source and doc */
xmlNodePtr lastSourceNode, lastDocNode;
xmlShellCtxtPtr ctxt;
int exitShell = 0; /* Indicate when to exit xslShell */
if (source == NULL){
#ifdef WITH_XSLDBG_DEBUG_PROCESS
xsltGenericError(xsltGenericErrorContext,
"Error: Source NULL in shellPrompt\n");
#endif
return;
}
if (doc == NULL){
#ifdef WITH_XSLDBG_DEBUG_PROCESS
xsltGenericError(xsltGenericErrorContext,
"Error: doc NULL in shellPrompt\n");
#endif
return;
}
if (filename == NULL){
#ifdef WITH_XSLDBG_DEBUG_PROCESS
xsltGenericError(xsltGenericErrorContext,
"Error: fileName NULL in shellPrompt\n");
#endif
return;
}
if (input == NULL){
#ifdef WITH_XSLDBG_DEBUG_PROCESS
xsltGenericError(xsltGenericErrorContext,
"Error: Input function NULL in shellPrompt\n");
#endif
return;
}
if (output == NULL){
#ifdef WITH_XSLDBG_DEBUG_PROCESS
xsltGenericError(xsltGenericErrorContext,
"Error: Output NULL in shellPrompt\n");
#endif
return;
}
ctxt = (xmlShellCtxtPtr) xmlMalloc(sizeof(xmlShellCtxt));
if (ctxt == NULL){
xsldbgGenericErrorFunc(i18n("Error: Out of memory.\n"));
return;
}
/* flag that we've received control */
debugGotControl(1);
ctxt->loaded = 0;
lastSourceNode = source;
lastDocNode = doc;
/* show the doc or source first? */
if (showSource) {
ctxt->doc = source->doc;
ctxt->node = source;
xsldbgUpdateFileDetails(source);
} else {
ctxt->doc = doc->doc;
ctxt->node = (xmlNodePtr) doc;
xsldbgUpdateFileDetails((xmlNodePtr) doc);
}
ctxt->input = input;
ctxt->output = output;
ctxt->filename = (char *) xmlStrdup((xmlChar *) filename);
if (xsldbgStop == 1){
xslDebugStatus = DEBUG_STOP;
optionsSetIntOption(OPTIONS_TRACE, TRACE_OFF);
optionsSetIntOption(OPTIONS_WALK_SPEED, WALKSPEED_STOP);
xsldbgStop = 0;
}
/* let any listener know that we got to a new line */
if (xslDebugStatus != DEBUG_TRACE) {
/* don't send notify message if we are tracing stylesheet */
int breakpoint = 1;
notifyXsldbgApp(XSLDBG_MSG_LINE_CHANGED, &breakpoint);
}
/* If using a thread and the thread is running then we don't need to
* send this as the application will see the XSLDBG_MSG_LINE_CHANGED message */
if ((getThreadStatus() == XSLDBG_MSG_THREAD_NOTUSED) ||
(xslDebugStatus == DEBUG_TRACE)) {
QString messageTxt;
if (!nextCommandActive && ctxt->node && ctxt->node && ctxt->node->doc
&& ctxt->node->doc->URL) {
if (!showSource) {
baseUri = filesGetBaseUri(ctxt->node);
if (baseUri != NULL)
breakUri = baseUri;
else
breakUri = ctxt->node->doc->URL;
} else
breakUri = ctxt->node->doc->URL;
if (xmlGetLineNo(ctxt->node) != -1)
messageTxt = i18n("Breakpoint for file \"%1\" at line %2.\n").arg(xsldbgUrl(breakUri)).arg(xmlGetLineNo(ctxt->node));
else
messageTxt = i18n("Breakpoint at text node in file \"%1\".\n").arg(xsldbgUrl(breakUri));
if (baseUri != NULL) {
xmlFree(baseUri);
baseUri = NULL;
}
if (((xslDebugStatus == DEBUG_TRACE) ||
(xslDebugStatus == DEBUG_WALK)) && (terminalIO != NULL))
fprintf(terminalIO, "%s", messageTxt.utf8().data());
else
xsldbgGenericErrorFunc(messageTxt);
}
}
if ((showWatchesActive && (xslDebugStatus == DEBUG_TRACE)) ||
(xslDebugStatus == DEBUG_WALK)){
ctxt->pctxt = xmlXPathNewContext(ctxt->doc);
if (ctxt->pctxt) {
xslDbgShellShowWatches(styleCtxt, ctxt, 0);
xsldbgGenericErrorFunc("\n");
xmlXPathFreeContext(ctxt->pctxt);
ctxt->pctxt = NULL;
}
}
if (xslDebugStatus == DEBUG_TRACE) {
if (ctxt->filename)
xmlFree(ctxt->filename);
xmlFree(ctxt);
return; /* All done. Trace next instruction/node */
}
if (xslDebugStatus == DEBUG_WALK) {
if (xslDbgWalkContinue()) {
if (ctxt->filename)
xmlFree(ctxt->filename);
xmlFree(ctxt);
return; /* All done. Walk to next instruction/node */
}
}
ctxt->pctxt = xmlXPathNewContext(ctxt->doc);
if (ctxt->pctxt == NULL) {
xmlFree(ctxt);
xsldbgGenericErrorFunc(i18n("Error: Out of memory.\n"));
return;
}
if (showWatchesActive){
xslDbgShellShowWatches(styleCtxt, ctxt, 0);
xsldbgGenericErrorFunc("\n");
}
while (!exitShell && (xslDebugStatus != DEBUG_QUIT)) {
if (getThreadStatus() != XSLDBG_MSG_THREAD_RUN) {
if (ctxt->node == (xmlNodePtr) ctxt->doc)
snprintf((char *) prompt, DEBUG_BUFFER_SIZE - 1,
"(xsldbg) %s > ", "/");
else if ((ctxt->node->name) && (ctxt->node->ns))
snprintf((char *) prompt, DEBUG_BUFFER_SIZE - 1,
"(xsldbg) %s:%s > ", ctxt->node->ns->prefix,
ctxt->node->name);
else if (ctxt->node->name)
snprintf((char *) prompt, DEBUG_BUFFER_SIZE - 1,
"(xsldbg) %s > ", ctxt->node->name);
else
snprintf((char *) prompt, DEBUG_BUFFER_SIZE - 1,
"(xsldbg) ? > ");
prompt[sizeof(prompt) - 1] = 0;
/*
* Get a new command line
*/
if (nextCommandActive && (xslDebugStatus == DEBUG_STEP))
/* we are processing the "next command" do the next
part of the command which is the up command */
cmdline = xmlStrdup((xmlChar*)"up");
else
cmdline = (xmlChar *) ctxt->input((char *) prompt);
if (cmdline && (optionsGetIntOption(OPTIONS_UTF8_INPUT) == 0)) {
/* we are getting encoded characters from the command line
* so decode them into UTF-8 */
xmlChar *tempResult = filesDecode(cmdline);
if (tempResult) {
xmlFree(cmdline);
cmdline = tempResult;
}
}
} else {
/* don't need a prompt for running as when running as a thread */
xmlStrCpy(messageBuffer, "");
if (nextCommandActive && (xslDebugStatus == DEBUG_STEP))
/* we are processing the "next command" do the next
part of the command which is the up command */
cmdline = xmlStrdup((xmlChar*)"up");
else
cmdline = (xmlChar *) ctxt->input((char *) messageBuffer);
}
if (cmdline == NULL)
break;
/* don't allow next command to be active more than at one breakpoint */
if (nextCommandActive)
nextCommandActive = 0;
notifyXsldbgApp(XSLDBG_MSG_PROCESSING_INPUT, NULL);
/* remove leading/trailing blanks */
trimString(cmdline);
/*
* Parse the command itself
*/
cur = cmdline;
nbargs = 0;
while ((*cur == ' ') || (*cur == '\t'))
cur++;
i = 0;
while ((*cur != ' ') && (*cur != '\t') &&
(*cur != '\n') && (*cur != '\r')) {
if (*cur == 0)
break;
command[i++] = *cur++;
}
command[i] = 0;
if (i == 0)
continue;
nbargs++;
/*
* Parse the argument
*/
while ((*cur == ' ') || (*cur == '\t'))
cur++;
i = 0;
while ((*cur != '\n') && (*cur != '\r') && (*cur != 0)) {
if (*cur == 0)
break;
arg[i++] = *cur++;
}
arg[i] = 0;
if (i != 0)
nbargs++;
commandId = lookupName(command, (xmlChar **) commandNames);
/* try command shorts if command is not found */
if (commandId < 0)
commandId =
lookupName(command, (xmlChar **) shortCommandNames);
cmdResult = -1; /* flag that it contains no result */
/*
* start interpreting the command
*/
switch (commandId + DEBUG_HELP_CMD) {
/* --- Help related commands --- */
case DEBUG_HELP_CMD:
cmdResult = helpTop(arg);
if (!cmdResult)
xsldbgGenericErrorFunc(i18n("Unable to print local help. Online help can be found at http://xsldbg.sourceforge.net/docs/index.html.\n"));
break;
/* --- Running related commands --- */
case DEBUG_BYE_CMD:
case DEBUG_EXIT_CMD:
case DEBUG_QUIT_CMD:
/* allow the stylesheet to exit */
xslDebugStatus = DEBUG_QUIT;
exitShell++;
cmdResult = 1;
break;
case DEBUG_NEXT_CMD:
xslDebugStatus = DEBUG_STEP;
exitShell++;
cmdResult = 1;
/* Do the the next part of this command
which is the up command */
nextCommandActive = 1;
break;
case DEBUG_STEP_CMD:
xslDebugStatus = DEBUG_STEP;
exitShell++;
cmdResult = 1;
break;
case DEBUG_STEPUP_CMD:
{
xmlChar *noOfFrames = arg;
/* skip until next space character */
while (*noOfFrames && (*noOfFrames != ' ')) {
noOfFrames++;
}
cmdResult = xslDbgShellFrameBreak(noOfFrames, 1);
exitShell++;
}
break;
case DEBUG_STEPDOWN_CMD:
{
xmlChar *noOfFrames = arg;
/* skip until next space character */
while (*noOfFrames && (*noOfFrames != ' ')) {
noOfFrames++;
}
cmdResult = xslDbgShellFrameBreak(noOfFrames, 0);
exitShell++;
}
break;
/* continue to next break point */
case DEBUG_CONT_CMD:
xslDebugStatus = DEBUG_CONT;
exitShell++;
cmdResult = 1;
break;
/* restart */
case DEBUG_RUN_CMD:
xslDebugStatus = DEBUG_RUN_RESTART;
exitShell++;
cmdResult = 1;
break;
/* --- Template related commands --- */
case DEBUG_TEMPLATES_CMD:
{
int allFiles = 1, verbose = 1;
if (xmlStrLen(arg) && (xmlStrCmp(arg, "this") == 0)) {
allFiles = 0;
}
/* be verbose when printing template names */
/* if args is not empty then print names this stylesheet */
cmdResult =
xslDbgShellPrintTemplateNames(styleCtxt, ctxt, arg,
verbose, allFiles);
break;
}
case DEBUG_WHERE_CMD:
/* Print the current working directory as well */
xslDbgPrintCallStack(NULL);
if (getThreadStatus() != XSLDBG_MSG_THREAD_RUN) {
if (!xmlShellPwd(ctxt, (char *) dir, ctxt->node, NULL)){
xsldbgGenericErrorFunc((const char*)dir);
xsldbgGenericErrorFunc("\n");
}
}
cmdResult = 1;
break;
case DEBUG_FRAME_CMD:
cmdResult = xslDbgPrintCallStack(arg);
break;
case DEBUG_STYLESHEETS_CMD:
cmdResult = xslDbgShellPrintStyleSheets(arg);
break;
/* --- Break point related commands --- */
case DEBUG_BREAK_CMD:
if (xmlStrLen(arg)) {
if (styleCtxt)
cmdResult =
xslDbgShellBreak(arg, styleCtxt->style,
styleCtxt);
else
cmdResult = xslDbgShellBreak(arg, NULL, styleCtxt);
} else {
/* select current node to break at */
xmlChar buff[100];
xmlChar *tempBaseName = filesGetBaseUri(ctxt->node);
if (tempBaseName){
snprintf((char *) buff, sizeof(buff), "-l %s %ld",
tempBaseName,
xmlGetLineNo(ctxt->node));
xmlFree(tempBaseName);
}
if (styleCtxt)
cmdResult =
xslDbgShellBreak(buff, styleCtxt->style,
styleCtxt);
else
cmdResult =
xslDbgShellBreak(buff, NULL, styleCtxt);
}
break;
case DEBUG_SHOWBREAK_CMD:
if (getThreadStatus() == XSLDBG_MSG_THREAD_RUN) {
notifyListStart(XSLDBG_MSG_BREAKPOINT_CHANGED);
walkBreakPoints((xmlHashScanner)
xslDbgShellPrintBreakPoint, NULL);
notifyListSend();
} else {
xsldbgGenericErrorFunc("\n");
printCount = 0; /* printCount will get updated by
* xslDbgShellPrintBreakPoint */
walkBreakPoints((xmlHashScanner)
xslDbgShellPrintBreakPoint, NULL);
if (printCount == 0)
xsldbgGenericErrorFunc(i18n("\nNo breakpoints are set for the file.\n"));
else
xsldbgGenericErrorFunc(i18n("\tTotal of %n breakpoint present.","\tTotal of %n breakpoints present.", printCount) + QString("\n"));
}
cmdResult = 1;
break;
case DEBUG_DELETE_CMD:
if (xmlStrLen(arg))
cmdResult = xslDbgShellDelete((xmlChar *) arg);
else {
breakPointPtr breakPtr = NULL;
xmlChar* tempBaseName = filesGetBaseUri(ctxt->node);
if (tempBaseName){
breakPtr =
breakPointGet(tempBaseName,
xmlGetLineNo(ctxt->node));
xmlFree(tempBaseName);
}
if (!breakPtr || !breakPointDelete(breakPtr)) {
xsldbgGenericErrorFunc(i18n("Error: Unable to delete breakpoint.\n"));
cmdResult = 0;
}
}
break;
case DEBUG_ENABLE_CMD:
if (xmlStrLen(arg))
cmdResult =
xslDbgShellEnable(arg, XSL_TOGGLE_BREAKPOINT);
else {
breakPointPtr breakPtr = NULL;
xmlChar * tempBaseName = filesGetBaseUri(ctxt->node);
if (tempBaseName){
breakPtr =
breakPointGet(tempBaseName,
xmlGetLineNo(ctxt->node));
xmlFree(tempBaseName);
}
if (!breakPtr ||
(!breakPointEnable(breakPtr, !(breakPtr->flags & BREAKPOINT_ENABLED)))) {
xsldbgGenericErrorFunc(i18n("Error: Unable to enable/disable breakpoint.\n"));
cmdResult = 0;
}
}
break;
case DEBUG_DISABLE_CMD:
if (xmlStrLen(arg))
cmdResult = xslDbgShellEnable(arg, 0);
else {
breakPointPtr breakPtr = NULL;
xmlChar *tempBaseName = filesGetBaseUri(ctxt->node);
if (tempBaseName){
breakPtr =
breakPointGet(tempBaseName,
xmlGetLineNo(ctxt->node));
xmlFree(tempBaseName);
}
if (!breakPtr || !breakPointEnable(breakPtr, 0)) {
xsldbgGenericErrorFunc(i18n("Error: Unable to enable/disable breakpoint.\n"));
cmdResult = 0;
}
}
break;
/* --- Node view related commands --- */
case DEBUG_LS_CMD:
cmdResult = xslDbgShellPrintList(ctxt, arg, 0);
break;
case DEBUG_DIR_CMD:
cmdResult = xslDbgShellPrintList(ctxt, arg, 1);
break;
case DEBUG_DU_CMD:
xmlShellDu(ctxt, NULL, ctxt->node, NULL);
cmdResult = 1;
break;
case DEBUG_CAT_CMD:
case DEBUG_PRINT_CMD:
cmdResult = xslDbgShellCat(styleCtxt, ctxt, arg);
break;
case DEBUG_PWD_CMD:
if (!xmlShellPwd(ctxt, (char *) dir, ctxt->node, NULL)) {
xmlChar* tempBaseName = filesGetBaseUri(ctxt->node);
if(tempBaseName){
xsldbgGenericErrorFunc("\n");
xsldbgGenericErrorFunc((char*)dir);
xsldbgGenericErrorFunc(i18n(" in file \"%1\" at line %2").arg(xsldbgUrl(tempBaseName)).arg(xmlGetLineNo(ctxt->node)));
xmlFree(tempBaseName);
cmdResult = 1;
}
}
if (cmdResult)
xsldbgGenericErrorFunc("\n");
else
xsldbgGenericErrorFunc(i18n("Error: Unable to print working directory.\n"));
break;
case DEBUG_DUMP_CMD:
xmlDebugDumpDocument(stdout, ctxt->doc);
cmdResult = 1;
break;
case DEBUG_BASE_CMD:
xmlShellBase(ctxt, NULL, ctxt->node, NULL);
cmdResult = 1;
break;
/* --- Variable related commands --- */
case DEBUG_GLOBALS_CMD:
if (loadedFiles == 0)
cmdResult = xslDbgShellPrintVariable(styleCtxt, arg,
DEBUG_GLOBAL_VAR);
else {
xsldbgGenericErrorFunc(i18n("Error: Need to use the run command first.\n"));
cmdResult = 0;
}
break;
case DEBUG_LOCALS_CMD:
if (loadedFiles == 0)
/* if gdb compatability mode is enable print the globals then
* the locals */
if (optionsGetIntOption(OPTIONS_GDB) == 1) {
cmdResult =
xslDbgShellPrintVariable(styleCtxt, arg,
DEBUG_GLOBAL_VAR);
if (cmdResult == 1)
cmdResult =
xslDbgShellPrintVariable(styleCtxt, arg,
DEBUG_LOCAL_VAR);
} else
cmdResult =
xslDbgShellPrintVariable(styleCtxt, arg,
DEBUG_LOCAL_VAR);
else {
xsldbgGenericErrorFunc(i18n("Error: Need to use the run command first.\n"));
cmdResult = 0;
}
break;
/* It's difficult to put the following commands into
* a separe file so they stay here! */
/* --- Node selection related commands --- */
case DEBUG_SOURCE_CMD:
cmdResult = 1; /* only one case where this will command fail */
xsldbgValidateBreakpoints = BREAKPOINTS_NEED_VALIDATION;
if (xmlStrLen(arg) == 0) {
if (ctxt->doc == doc->doc)
lastDocNode = ctxt->node;
ctxt->doc = source->doc;
ctxt->node = lastSourceNode;
if (ctxt->pctxt)
xmlXPathFreeContext(ctxt->pctxt);
ctxt->pctxt = xmlXPathNewContext(ctxt->doc);
showSource = 1;
xsldbgUpdateFileDetails((xmlNodePtr) ctxt->node);
/* let any listener know that we got to a new line */
notifyXsldbgApp(XSLDBG_MSG_LINE_CHANGED, NULL);
if (ctxt->pctxt == NULL) {
xmlFree(ctxt);
xslDebugStatus = DEBUG_QUIT;
return;
} else
break;
} else {
/* load new stylesheet file, actual loading happens later */
xmlChar *expandedName = filesExpandName(arg);
if (expandedName) {
xsldbgGenericErrorFunc(i18n("Load of source deferred. Use the run command.\n"));
optionsSetStringOption(OPTIONS_SOURCE_FILE_NAME,
expandedName);
notifyXsldbgApp(XSLDBG_MSG_FILE_CHANGED, 0L);
loadedFiles = 1;
xmlFree(expandedName);
cmdResult = 1;
} else {
cmdResult = 0;
}
}
break;
case DEBUG_DATA_CMD:
cmdResult = 1; /* only one case where this will command fail */
xsldbgValidateBreakpoints = BREAKPOINTS_NEED_VALIDATION;
if (xmlStrLen(arg) == 0) {
if (ctxt->doc == source->doc)
lastSourceNode = ctxt->node;
ctxt->doc = doc->doc;
ctxt->node = lastDocNode;
if (ctxt->pctxt)
xmlXPathFreeContext(ctxt->pctxt);
ctxt->pctxt = xmlXPathNewContext(ctxt->doc);
showSource = 0;
xsldbgUpdateFileDetails((xmlNodePtr) ctxt->node);
/* let any listener know that we got to a new line */
notifyXsldbgApp(XSLDBG_MSG_LINE_CHANGED, NULL);
if (ctxt->pctxt == NULL) {
xmlFree(ctxt);
xslDebugStatus = DEBUG_QUIT;
return;
} else
break;
} else {
/* load new xml file actual loading hapens later */
xmlChar *expandedName = filesExpandName(arg);
if (expandedName) {
xsldbgGenericErrorFunc(i18n("Load of data file deferred. Use the run command.\n"));
optionsSetStringOption(OPTIONS_DATA_FILE_NAME,
expandedName);
notifyXsldbgApp(XSLDBG_MSG_FILE_CHANGED, 0L);
loadedFiles = 1;
xmlFree(expandedName);
cmdResult = 1;
} else {
cmdResult = 0;
}
}
break;
case DEBUG_OUTPUT_CMD:
/* set the output file name to use */
cmdResult = xslDbgShellOutput(arg);
break;
case DEBUG_CD_CMD:
/* use dir as a working buffer */
xmlStrnCpy(dir, arg, 2);
dir[2] = '\0';
shortCutId = lookupName(dir, (xmlChar **) cdShortCuts);
if (shortCutId >= 0) {
if (xmlStrLen(arg) == 2) {
cmdResult = xslDbgCd(styleCtxt, ctxt, (xmlChar *)
cdAlternative[shortCutId],
source);
} else {
xmlStrCpy(dir, cdAlternative[shortCutId]);
xmlStrCat(dir, &arg[2]);
cmdResult = xslDbgCd(styleCtxt, ctxt, dir, source);
}
} else
cmdResult = xslDbgCd(styleCtxt, ctxt, arg, source);
break;
/* --- File related commands --- */
case DEBUG_ENTITIES_CMD:
cmdResult = xslDbgEntities();
break;
case DEBUG_SYSTEM_CMD:
/* strip off a single argument. I need to do it this
way because I've already public this API */
{
xmlChar *systemID;
if (splitString(arg, 1, &systemID) == 1){
cmdResult = xslDbgSystem(systemID);
}else{
xsldbgGenericErrorFunc(i18n("Error: Invalid arguments for the command %1.\n").arg("system"));
}
}
break;
case DEBUG_PUBLIC_CMD:
/* strip off a single argument. I need to do it this
way because I've already public this API */
{
xmlChar *publicID;
if (splitString(arg, 1, &publicID) == 1){
cmdResult = xslDbgPublic(publicID);
}else{
xsldbgGenericErrorFunc(i18n("Error: Invalid arguments for the command %1.\n").arg("public"));
}
}
break;
case DEBUG_ENCODING_CMD:
cmdResult = xslDbgEncoding(arg);
break;
case DEBUG_VALIDATE_CMD:
xsldbgGenericErrorFunc(i18n("Warning: The %1 command is disabled.\n").arg("validate"));
cmdResult = 0;
/*
* xmlShellValidate(ctxt, arg, NULL, NULL);
*/
break;
case DEBUG_LOAD_CMD:
cmdResult = optionsLoad();
/* restart xsldbg and activate new configuration */
if (cmdResult == 1) {
xslDebugStatus = DEBUG_RUN_RESTART;
exitShell++;
}
break;
case DEBUG_SAVE_CMD:
cmdResult = optionsSave();
break;
case DEBUG_WRITE_CMD:
xsldbgGenericErrorFunc(i18n("Warning: The %1 command is disabled.\n").arg("write"));
cmdResult = 0;
/*
* xmlShellWrite(ctxt, arg, NULL, NULL);
*/
break;
case DEBUG_FREE_CMD:
xsldbgGenericErrorFunc(i18n("Warning: The %1 command is disabled.\n").arg("free"));
cmdResult = 0;
/*
* if (arg[0] == 0) {
* xmlMemShow(stdout, 0);
* } else {
* int len = 0;
* sscanf(arg, "%d", &len);
* xmlMemShow(stdout, len);
* }
*/
break;
/* operating system related */
case DEBUG_CHDIR_CMD:
cmdResult = xslDbgShellChangeWd(arg);
break;
case DEBUG_SHELL_EXEC_CMD:
cmdResult = xslDbgShellExecute(arg, 1);
break;
/* libxslt parameter related commands */
case DEBUG_ADDPARAM_CMD:
cmdResult = xslDbgShellAddParam(arg);
break;
case DEBUG_DELPARAM_CMD:
cmdResult = xslDbgShellDelParam(arg);
break;
case DEBUG_SHOWPARAM_CMD:
cmdResult = xslDbgShellShowParam(arg);
break;
/* option related commmands */
case DEBUG_SETOPTION_CMD:
cmdResult = xslDbgShellSetOption(arg);
break;
case DEBUG_OPTIONS_CMD:
cmdResult = xslDbgShellOptions();
break;
/* misc commands */
case DEBUG_TTY_CMD:
if (openTerminal(arg)) {
/* gdb does to say anything after redirecting its
output */
if (optionsGetIntOption(OPTIONS_GDB) < 2)
xsldbgGenericErrorFunc(i18n("Opening terminal %1.\n").arg(xsldbgText(arg)));
cmdResult = 1;
} else
cmdResult = 0;
break;
/* language selection for messages */
case DEBUG_LANG_CMD:
#ifdef LOCALE_PREFIX
if (xmlStrlen(arg) > 0){
setlocale(LC_MESSAGES, (char*)arg);
textdomain("kdewebdev/xsldsbg");
bindtextdomain("kdewebdev/xsldbg", LOCALE_PREFIX);
cmdResult = 1;
}else{
xsldbgGenericErrorFunc(i18n("Error: Missing arguments for the command %1.\n").arg("lang"));
cmdResult = 0;
}
#else
xsldbgGenericErrorFunc(i18n("Warning: The %1 command is disabled\n").arg("lang"));
cmdResult = 1;
#endif
break;
/* tracing related commands */
case DEBUG_TRACE_CMD:
if (xslDbgShellTrace(arg)) {
exitShell++;
cmdResult = 1;
} else
cmdResult = 0;
break;
case DEBUG_WALK_CMD:
if (xslDbgShellWalk(arg)) {
exitShell++;
cmdResult = 1;
} else
cmdResult = 0;
break;
case DEBUG_ADDWATCH_CMD:
cmdResult = xslDbgShellAddWatch(arg);
break;
case DEBUG_DELWATCH_CMD:
cmdResult = xslDbgShellDeleteWatch(arg);
break;
case DEBUG_SHOWWATCH_CMD:
trimString(arg);
switch (arg[0]){
case '\0':
cmdResult = xslDbgShellShowWatches(styleCtxt, ctxt, 1);
break;
case '0':
case '1':
showWatchesActive = arg[0] - '0';
cmdResult = 1;
break;
default:
xsldbgGenericErrorFunc(i18n("Error: Invalid arguments for the command %1.\n").arg("showmatch"));
}
break;
/* search related commands */
case DEBUG_SEARCH_CMD:
cmdResult =
xslDbgShellSearch(styleCtxt, filesGetStylesheet(),
arg);
break;
case DEBUG_SET_CMD:
cmdResult = xslDbgShellSetVariable(styleCtxt, arg);
break;
default:
xsldbgGenericErrorFunc(i18n("Error: Unknown command %1. Try help.\n").arg(xsldbgText(command)));
cmdResult = 0;
}
/* KDbg likes to get the marker after every command so here it is */
if ((optionsGetIntOption(OPTIONS_GDB) >1) && optionsGetIntOption(OPTIONS_VERBOSE) && !nextCommandActive
&& (commandId != DEBUG_STEPUP_CMD - DEBUG_HELP_CMD)) {
if (ctxt->node && ctxt->node &&
ctxt->node->doc && ctxt->node->doc->URL) {
if (xmlGetLineNo(ctxt->node) != -1)
xsldbgGenericErrorFunc(i18n("Breakpoint for file \"%1\" at line %2.\n").arg(xsldbgUrl(ctxt->node->doc->URL)).arg(xmlGetLineNo(ctxt->node)));
else
xsldbgGenericErrorFunc(i18n("Breakpoint at text node in file \"%1\".\n").arg(xsldbgUrl(ctxt->node->doc->URL)));
}
}
/* notify any listeners of that the command failed */
if (cmdResult == 0 && (xmlStrlen(messageBuffer) > 0)) {
snprintf((char *) messageBuffer, sizeof(messageBuffer),
"\nRequest to xsldbg failed:%s\n", cmdline);
notifyTextXsldbgApp(XSLDBG_MSG_TEXTOUT,
(char *) messageBuffer);
}
xmlFree(cmdline);
cmdline = NULL;
}
xmlXPathFreeContext(ctxt->pctxt);
if (ctxt->filename)
xmlFree(ctxt->filename);
xmlFree(ctxt);
if (cmdline)
xmlFree(cmdline);
}