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.
2119 lines
65 KiB
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)) + TQString("\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 = fullTQName(rootCopy->nameURI, rootCopy->name);
|
|
rootModeTemp = fullTQName(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 = fullTQName(callPointItem->info->templateURI,
|
|
callPointItem->info->templateName);
|
|
modeTemp = fullTQName(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 = fullTQName(root->nameURI, root->name);
|
|
modeTemp = fullTQName(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)) {
|
|
TQString 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)) {
|
|
TQString 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) + TQString("\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("tdewebdev/xsldsbg");
|
|
bindtextdomain("tdewebdev/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);
|
|
}
|