summaryrefslogtreecommitdiffstats
path: root/kxsldbg/kxsldbgpart/libxsldbg/debugXSL.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kxsldbg/kxsldbgpart/libxsldbg/debugXSL.cpp')
-rw-r--r--kxsldbg/kxsldbgpart/libxsldbg/debugXSL.cpp2118
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);
+}