summaryrefslogtreecommitdiffstats
path: root/kxsldbg/kxsldbgpart/libxsldbg/nodeview_cmds.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kxsldbg/kxsldbgpart/libxsldbg/nodeview_cmds.cpp')
-rw-r--r--kxsldbg/kxsldbgpart/libxsldbg/nodeview_cmds.cpp609
1 files changed, 609 insertions, 0 deletions
diff --git a/kxsldbg/kxsldbgpart/libxsldbg/nodeview_cmds.cpp b/kxsldbg/kxsldbgpart/libxsldbg/nodeview_cmds.cpp
new file mode 100644
index 00000000..5fcbef00
--- /dev/null
+++ b/kxsldbg/kxsldbgpart/libxsldbg/nodeview_cmds.cpp
@@ -0,0 +1,609 @@
+
+/***************************************************************************
+ nodeview_cmds.c - node viewing commands for xsldbg
+ -------------------
+ begin : Wed Nov 21 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. *
+ * *
+ ***************************************************************************/
+
+#include "xsldbg.h"
+#include <libxml/xpathInternals.h>
+#include <libxml/HTMLparser.h>
+#include <libxml/HTMLtree.h>
+#include <ctype.h> /* for isspace*/
+#include "debugXSL.h"
+#include "arraylist.h"
+#include "breakpoint.h"
+#include "xsldbgmsg.h"
+#include "xsldbgthread.h" /* for getThreadStatus */
+#include "files.h"
+#include "options.h"
+
+
+/* -----------------------------------------
+ Private function declarations for nodeview_cmds.c
+ -------------------------------------------*/
+static xmlChar nodeViewBuffer[500];
+static int printVariableValue = 0;
+
+/*
+ * xslDbgShellPrintNames:
+ * Print a name of variable found by scanning variable table
+ * It is used by print_variable function.
+ * @payload : not used
+ * @data : not used
+ * @name : the variable name
+ */
+void *xslDbgShellPrintNames(void *payload,
+ void *data, xmlChar * name);
+
+/**
+ * xslDbgCatToFile:
+ * @node : Is valid
+ * @file : Is valid
+ *
+ * Send the results of cat command in @node to @file
+ */
+static void xslDbgCatToFile(xmlNodePtr node, FILE * file);
+
+
+/**
+ * printXPathObject:
+ * @item : XPath object to print
+ * @xPath : The XPath used to find item
+ *
+ * Print an XPath object
+ *
+ * Returns 1 on success,
+ * 0 otherwise
+ */
+static int printXPathObject(xmlXPathObjectPtr item, xmlChar* xPath);
+
+/* -------------------------------------
+ End private functions
+---------------------------------------*/
+
+
+/**
+ * xslDbgShellPrintList:
+ * @ctxt: The current shell context
+ * @arg: What xpath to display and in UTF-8
+ * @dir: If 1 print in dir mode?,
+ * otherwise ls mode
+ *
+ * Print list of nodes in either ls or dir format
+ *
+ * Returns 1 on success,
+ * 0 otherwise
+ */
+int
+xslDbgShellPrintList(xmlShellCtxtPtr ctxt, xmlChar * arg, int dir)
+{
+ xmlXPathObjectPtr list;
+ int result = 0;
+
+ if (!ctxt || !arg) {
+#ifdef WITH_XSLDBG_DEBUG_PROCESS
+ xsltGenericError(xsltGenericErrorContext,
+ "Error: NULL arguments provided\n");
+#endif
+ return result;
+ }
+
+ if (arg[0] == 0) {
+ if (dir)
+ xmlShellDir(ctxt, NULL, ctxt->node, NULL);
+ else
+ xmlShellList(ctxt, NULL, ctxt->node, NULL);
+ result = 1; /*assume that this worked */
+ } else {
+ ctxt->pctxt->node = ctxt->node;
+ ctxt->pctxt->node = ctxt->node;
+ if (!xmlXPathNsLookup(ctxt->pctxt, (xmlChar *) "xsl"))
+ xmlXPathRegisterNs(ctxt->pctxt, (xmlChar *) "xsl",
+ XSLT_NAMESPACE);
+ list = xmlXPathEval(arg, ctxt->pctxt);
+ if (list != NULL) {
+ switch (list->type) {
+ case XPATH_NODESET:{
+ int indx;
+
+ for (indx = 0;
+ indx < list->nodesetval->nodeNr; indx++) {
+ if (dir)
+ xmlShellList(ctxt, NULL,
+ list->nodesetval->
+ nodeTab[indx], NULL);
+ else
+ xmlShellList(ctxt, NULL,
+ list->nodesetval->
+ nodeTab[indx], NULL);
+ }
+ result = 1;
+ break;
+ }
+ default:
+ xmlShellPrintXPathError(list->type, (char *) arg);
+ }
+ xmlXPathFreeObject(list);
+ } else {
+ xsldbgGenericErrorFunc(i18n("Error: XPath %1 results in an empty Node Set.\n").arg(xsldbgText(arg)));
+ }
+ ctxt->pctxt->node = NULL;
+ }
+ return result;
+}
+
+
+
+/**
+ * xslDbgCatToFile:
+ * @node : Is valid
+ * @file : Is valid
+ *
+ * Send the results of cat command in @node to @file
+ */
+void
+xslDbgCatToFile(xmlNodePtr node, FILE * file)
+{
+ if (!node || !file)
+ return;
+
+ /* assume that HTML usage is enabled */
+ if (node->doc->type == XML_HTML_DOCUMENT_NODE) {
+ if (node->type == XML_HTML_DOCUMENT_NODE)
+ htmlDocDump(file, (htmlDocPtr) node);
+ else
+ htmlNodeDumpFile(file, node->doc, node);
+ } else if (node->type == XML_DOCUMENT_NODE) {
+ /* turn off encoding for the moment and just dump UTF-8
+ * which will be converted by xsldbgGeneralErrorFunc */
+ xmlDocPtr doc = (xmlDocPtr) node;
+ const xmlChar *encoding = doc->encoding;
+
+ if (encoding) {
+ xsldbgGenericErrorFunc(i18n("Information: Temporarily setting document's encoding to UTF-8. Previously was %1.\n").arg(xsldbgText(encoding)));
+ }
+ doc->encoding = (xmlChar *) "UTF-8";
+ xmlDocDump(file, (xmlDocPtr) node);
+ doc->encoding = encoding;
+ } else {
+ xmlElemDump(file, node->doc, node);
+ }
+}
+
+
+/**
+ * printXPathObject:
+ * @item : XPath object to print
+ * @xPath : The XPath used to find item
+ *
+ * Print an XPath object
+ *
+ * Returns 1 on success,
+ * 0 otherwise
+ */
+
+static int
+printXPathObject(xmlXPathObjectPtr item, xmlChar* xPath){
+ int result = 0;
+ if (item){
+ switch (item->type) {
+ case XPATH_BOOLEAN:
+ xsltGenericError(xsltGenericErrorContext,
+ "= %s\n%s\n", xPath,
+ xmlBoolToText(item->boolval));
+ result = 1;
+ break;
+
+ case XPATH_NUMBER:
+ xsltGenericError(xsltGenericErrorContext,
+ "= %s\n%0g\n", xPath, item->floatval);
+ result = 1;
+ break;
+
+ /* case XPATH_NODESET:*/
+ default:{
+ /* We may need to convert this XPath to a string,
+ plus ensure that we print required the number of
+ lines of text */
+ int indx;
+
+ const char *fileName = filesTempFileName(0);
+ FILE *file = NULL;
+
+ if (!fileName)
+ break;
+ file = fopen(fileName, "w+");
+ if (!file) {
+ xsldbgGenericErrorFunc(i18n("Error: Unable to save temporary results to %1.\n").arg(xsldbgText(fileName)));
+ break;
+ } else {
+ fprintf(file, "= %s\n", xPath);
+ switch(item->type){
+
+ case XPATH_NODESET:
+ if (item->nodesetval){
+ for (indx = 0;
+ indx < item->nodesetval->nodeNr; indx++){
+ xslDbgCatToFile(item->nodesetval->
+ nodeTab[indx], file);
+ }
+ } else {
+ xsldbgGenericErrorFunc(i18n("Error: XPath %1 results in an empty Node Set.\n").arg(xsldbgText(xPath)));
+ }
+ break;
+
+ case XPATH_STRING:
+ if (item->stringval)
+ fprintf(file, "\'%s\'", item->stringval);
+ else
+ fprintf(file, "%s", i18n("NULL string value supplied.").utf8().data());
+ break;
+
+ default:{
+ xmlXPathObjectPtr tempObj =
+ xmlXPathObjectCopy(item);
+ if (tempObj)
+ tempObj = xmlXPathConvertString(tempObj);
+ if (tempObj && tempObj->stringval){
+ fprintf(file, "%s", tempObj->stringval);
+ }else{
+ fprintf(file, "%s", i18n("Unable to convert XPath to string.").utf8().data());
+ }
+ if (tempObj)
+ xmlXPathFreeObject(tempObj);
+ }
+ break;
+ fprintf(file,"\n");
+
+ } /* inner switch statement */
+ if (getThreadStatus() == XSLDBG_MSG_THREAD_RUN) {
+ fclose(file);
+ file = NULL;
+ /* send the data to application */
+ notifyXsldbgApp(XSLDBG_MSG_FILEOUT, fileName);
+ } else {
+ int lineCount = 0, gdbModeEnabled = 0;
+
+ /* save the value of option to speed things up
+ * a bit */
+ gdbModeEnabled =
+ optionsGetIntOption(OPTIONS_GDB);
+ rewind(file);
+
+ /* when gdb mode is enable then only print the first
+ * GDB_LINES_TO_PRINT lines */
+ while (!feof(file)) {
+ if (fgets
+ ((char *) nodeViewBuffer, sizeof(nodeViewBuffer),
+ file))
+ xsltGenericError
+ (xsltGenericErrorContext, "%s",
+ nodeViewBuffer);
+ if (gdbModeEnabled) {
+ lineCount++;
+ /* there is an overhead of two lines
+ * when print expression values */
+ if (lineCount ==
+ GDB_LINES_TO_PRINT + 2) {
+ xsltGenericError
+ (xsltGenericErrorContext,
+ "...");
+ break;
+ }
+ }
+ }
+ xsltGenericError
+ (xsltGenericErrorContext, "\n");
+ }
+ if (file)
+ fclose(file);
+ result = 1;
+ break;
+ }
+ }
+ }
+ }
+ return result;
+}
+
+
+/**
+ * xslDbgShellCat:
+ * @styleCtxt: the current stylesheet context
+ * @ctxt: The current shell context
+ * @arg: The xpath to print (in UTF-8)
+ *
+ * Print the result of an xpath expression. This can include variables
+ * if styleCtxt is not NULL
+ *
+ * Returns 1 on success,
+ * 0 otherwise
+ */
+
+int
+xslDbgShellCat(xsltTransformContextPtr styleCtxt, xmlShellCtxtPtr ctxt,
+ xmlChar * arg)
+{
+ xmlXPathObjectPtr list;
+ int result = 0;
+ static const char * QUIET_STR = "-q";
+ bool silenceCtxtErrors = false;
+
+ if ((arg == NULL) || (xmlStrLen(arg) == 0))
+ arg = (xmlChar *) ".";
+
+ /* Do we quietly ingore style context errors */
+ if (strncasecmp((char*)arg, QUIET_STR, strlen(QUIET_STR))== 0){
+ silenceCtxtErrors = true;
+ arg = arg + strlen(QUIET_STR);
+ while (isspace(*arg)){
+ arg++;
+ }
+ }
+
+ if (!styleCtxt || !ctxt || !ctxt->node) {
+ if (!(!xsldbgReachedFirstTemplate && silenceCtxtErrors))
+ xsldbgGenericErrorFunc(i18n("Warning: Unable to print expression. No stylesheet was properly loaded.\n"));
+ return 0;
+ }
+
+ if ((arg == NULL) || (xmlStrLen(arg) == 0))
+ arg = (xmlChar *) ".";
+
+ ctxt->pctxt->node = ctxt->node;
+ if (!styleCtxt) {
+ list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
+ } else {
+ xmlNodePtr savenode = styleCtxt->xpathCtxt->node;
+
+ ctxt->pctxt->node = ctxt->node;
+ styleCtxt->xpathCtxt->node = ctxt->node;
+ if (!xmlXPathNsLookup(styleCtxt->xpathCtxt, (xmlChar *) "xsl"))
+ xmlXPathRegisterNs(styleCtxt->xpathCtxt, (xmlChar *) "xsl",
+ XSLT_NAMESPACE);
+ list = xmlXPathEval((xmlChar *) arg, styleCtxt->xpathCtxt);
+ styleCtxt->xpathCtxt->node = savenode;
+ }
+ if (list != NULL) {
+ result = printXPathObject(list, arg);
+ xmlXPathFreeObject(list);
+ } else {
+ xsldbgGenericErrorFunc(i18n("Error: XPath %1 results in an empty Node Set.\n").arg(xsldbgText(arg)));
+ }
+ ctxt->pctxt->node = NULL;
+ return result;
+}
+
+/* only used by xslDbgPrintNames and xslDbgPrintVariable cound number of variables */
+static int varCount;
+
+/*
+ * xslDbgShellPrintNames:
+ * Print a name of variable found by scanning variable table
+ * It is used by print_variable function.
+ * @payload : Global variable of type xsltStackElemPtr
+ * @data : not used
+ * @name : the variable name
+ */
+void *
+xslDbgShellPrintNames(void *payload,
+ void *data, xmlChar * name)
+{
+ Q_UNUSED(payload);
+ Q_UNUSED(data);
+ if (getThreadStatus() == XSLDBG_MSG_THREAD_RUN) {
+ notifyListQueue(payload);
+ } else if (payload && name) {
+ xmlChar * fullQualifiedName = nodeViewBuffer;
+ xsltStackElemPtr item = (xsltStackElemPtr)payload;
+ if (item->nameURI == NULL){
+ snprintf((char*)fullQualifiedName, sizeof(nodeViewBuffer), "$%s", item->name);
+ }else{
+ snprintf((char*)fullQualifiedName, sizeof(nodeViewBuffer), "$%s:%s",
+ item->nameURI, item->name);
+ }
+ if (printVariableValue == 0){
+ xsldbgGenericErrorFunc(i18n(" Global %1\n").arg(xsldbgText(fullQualifiedName)));
+ }else{
+ if (item->computed == 1){
+ xsldbgGenericErrorFunc(i18n(" Global "));
+ printXPathObject(item->value, fullQualifiedName);
+ }else if (item->tree){
+ xsldbgGenericErrorFunc(i18n(" Global = %1\n").arg(xsldbgText(fullQualifiedName)));
+ xslDbgCatToFile(item->tree, stderr);
+ }else if (item->select){
+ xsldbgGenericErrorFunc(i18n(" Global = %1\n%2").arg(xsldbgText(fullQualifiedName)).arg(xsldbgText(item->select)));
+ }else{
+ /* can't find a value give only a variable name an error message */
+ xsldbgGenericErrorFunc(i18n(" Global = %1\n%2").arg(xsldbgText(fullQualifiedName)).arg(i18n("Warning: No value assigned to variable.\n")));
+ }
+ xsltGenericError(xsltGenericErrorContext, "\n\032\032\n");
+ }
+ varCount++;
+ }
+ return NULL;
+}
+
+
+
+/**
+ * xslDbgShellPrintVariable:
+ * @styleCtxt: The current stylesheet context
+ * @arg: The name of variable to look for '$' prefix is optional and in UTF-8
+ * @type: A valid VariableTypeEnum
+ *
+ * Print the value variable specified by args.
+ *
+ * Returns 1 on success,
+ * 0 otherwise
+ */
+int
+xslDbgShellPrintVariable(xsltTransformContextPtr styleCtxt, xmlChar * arg,
+ VariableTypeEnum type)
+{
+ int result = 0;
+ /* command argument to include both name and its value */
+ static const char * FULLNAME_STR = "-f";
+ /* Quietly exit if an invalid stylesheet is provided */
+ static const char * QUIET_STR = "-q";
+ bool silenceCtxtErrors = false;
+
+ if (!arg) {
+#ifdef WITH_XSLDBG_DEBUG_PROCESS
+ xsltGenericError(xsltGenericErrorContext,
+ "Error: NULL argument provided\n");
+#endif
+ return result;
+ }
+
+ varCount = 0;
+ /* Do we quietly ingore style context errors */
+ if (strncasecmp((char*)arg, QUIET_STR, strlen(QUIET_STR))== 0){
+ silenceCtxtErrors = true;
+ arg = arg + strlen(QUIET_STR);
+ while (isspace(*arg)){
+ arg++;
+ }
+ }
+
+ if (!styleCtxt) {
+ if (!(!xsldbgReachedFirstTemplate && silenceCtxtErrors))
+ xsldbgGenericErrorFunc(i18n("Error: Debugger has no files loaded or libxslt has not reached a template.\nTry reloading files or taking more steps.\n"));
+ return result;
+ }
+
+ /* Do we include the name as well as its value */
+ if (strncasecmp((char*)arg, FULLNAME_STR, strlen(FULLNAME_STR))== 0){
+ printVariableValue = 1;
+ arg = arg + strlen(FULLNAME_STR);
+ while (isspace(*arg)){
+ arg++;
+ }
+ }
+ if (arg[0] == 0) {
+ /* list variables of type requested */
+ if (type == DEBUG_GLOBAL_VAR) {
+ if (styleCtxt->globalVars) {
+ if (getThreadStatus() == XSLDBG_MSG_THREAD_RUN) {
+ notifyListStart(XSLDBG_MSG_GLOBALVAR_CHANGED);
+ /* list global variables */
+ xmlHashScan(styleCtxt->globalVars,
+ (xmlHashScanner) xslDbgShellPrintNames,
+ NULL);
+ notifyListSend();
+ } else
+ /* list global variables */
+ xmlHashScan(styleCtxt->globalVars,
+ (xmlHashScanner) xslDbgShellPrintNames,
+ NULL);
+ result = 1;
+ /* ensure that the locals follow imediately after the
+ * globals when in gdb mode */
+ if (optionsGetIntOption(OPTIONS_GDB) == 0)
+ xsltGenericError(xsltGenericErrorContext, "\n");
+ } else {
+ if (getThreadStatus() != XSLDBG_MSG_THREAD_RUN) {
+ /* Don't show this message when running as a thread as it
+ * is annoying */
+ xsldbgGenericErrorFunc(i18n("Error: Libxslt has not initialized variables yet; try stepping to a template.\n"));
+ } else {
+ /* send an empty list */
+ notifyListStart(XSLDBG_MSG_GLOBALVAR_CHANGED);
+ notifyListSend();
+ result = 1;
+ }
+ }
+ } else {
+ /* list local variables */
+ if (styleCtxt->varsNr && styleCtxt->varsTab) {
+ if (getThreadStatus() == XSLDBG_MSG_THREAD_RUN) {
+ notifyListStart(XSLDBG_MSG_LOCALVAR_CHANGED);
+ for (int i = styleCtxt->varsNr; i > styleCtxt->varsBase; i--) {
+ xsltStackElemPtr item = styleCtxt->varsTab[i-1];
+ while (item) {
+ notifyListQueue(item);
+ item = item->next;
+ }
+ }
+ notifyListSend();
+ } else {
+ xmlChar * fullQualifiedName = nodeViewBuffer;
+ for (int i = styleCtxt->varsNr; i > styleCtxt->varsBase; i--) {
+ xsltStackElemPtr item = styleCtxt->varsTab[i-1];
+ while (item) {
+ if (item->name) {
+ if (item->nameURI == NULL){
+ snprintf((char*)fullQualifiedName, sizeof(nodeViewBuffer), "$%s",
+ item->name);
+ }else{
+
+ snprintf((char*)fullQualifiedName, sizeof(nodeViewBuffer), "$%s:%s",
+ item->nameURI, item->name);
+ }
+ if (printVariableValue == 0){
+ xsldbgGenericErrorFunc(i18n(" Local %1").arg(xsldbgText(fullQualifiedName)));
+ }else{
+ if (item->computed == 1){
+ xsldbgGenericErrorFunc(i18n(" Local "));
+ printXPathObject(item->value, fullQualifiedName);
+ }else if (item->tree){
+ xsldbgGenericErrorFunc(i18n(" Local = %1\n").arg(xsldbgText(fullQualifiedName)));
+ xslDbgCatToFile(item->tree, stderr);
+ }else if (item->select){
+ xsldbgGenericErrorFunc(i18n(" Local = %1\n%2").arg(xsldbgText(fullQualifiedName)).arg(xsldbgText(item->select)));
+ }else{
+ /* can't find a value give only a variable name and an error */
+ xsldbgGenericErrorFunc(i18n(" Local = %1\n%2").arg(xsldbgText(fullQualifiedName)).arg(i18n("Warning: No value assigned to variable.\n")));
+ }
+ }
+ xsltGenericError(xsltGenericErrorContext, "\n\032\032\n");
+ }
+ item = item->next;
+ }
+ }
+ }
+ result = 1;
+ xsltGenericError(xsltGenericErrorContext, "\n");
+ } else {
+ if (getThreadStatus() != XSLDBG_MSG_THREAD_RUN) {
+ /* Don't show this message when running as a thread as it
+ * is annoying */
+ xsldbgGenericErrorFunc(i18n("Error: Libxslt has not initialized variables yet; try stepping past the xsl:param elements in the template.\n"));
+ } else {
+ /* send an empty list */
+ notifyListStart(XSLDBG_MSG_LOCALVAR_CHANGED);
+ notifyListSend();
+ result = 1;
+ }
+ }
+ }
+ } else {
+ /* Display the value of variable */
+ if (arg[0] == '$') {
+ printXPathObject(xmlXPathEval(arg, styleCtxt->xpathCtxt), arg);
+ xsltGenericError(xsltGenericErrorContext, "\032\032\n");
+ } else {
+ xmlStrCpy(nodeViewBuffer, "$");
+ xmlStrCat(nodeViewBuffer, arg);
+ printXPathObject(xmlXPathEval((xmlChar*)nodeViewBuffer,styleCtxt->xpathCtxt),
+ (xmlChar*)nodeViewBuffer);
+ xsltGenericError(xsltGenericErrorContext, "\032\032\n");
+ }
+
+ }
+
+ printVariableValue = 0;
+ return result;
+}