diff options
Diffstat (limited to 'kxsldbg/kxsldbgpart/libxsldbg/debugXSL.cpp')
-rw-r--r-- | kxsldbg/kxsldbgpart/libxsldbg/debugXSL.cpp | 2118 |
1 files changed, 2118 insertions, 0 deletions
diff --git a/kxsldbg/kxsldbgpart/libxsldbg/debugXSL.cpp b/kxsldbg/kxsldbgpart/libxsldbg/debugXSL.cpp new file mode 100644 index 00000000..39aea804 --- /dev/null +++ b/kxsldbg/kxsldbgpart/libxsldbg/debugXSL.cpp @@ -0,0 +1,2118 @@ + +/*************************************************************************** + 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); +} |