summaryrefslogtreecommitdiffstats
path: root/kxsldbg/kxsldbgpart/libxsldbg/search.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kxsldbg/kxsldbgpart/libxsldbg/search.cpp')
-rw-r--r--kxsldbg/kxsldbgpart/libxsldbg/search.cpp1584
1 files changed, 1584 insertions, 0 deletions
diff --git a/kxsldbg/kxsldbgpart/libxsldbg/search.cpp b/kxsldbg/kxsldbgpart/libxsldbg/search.cpp
new file mode 100644
index 00000000..68fcd7e1
--- /dev/null
+++ b/kxsldbg/kxsldbgpart/libxsldbg/search.cpp
@@ -0,0 +1,1584 @@
+
+/***************************************************************************
+ search.c - search implementation
+ -------------------
+ begin : Fri Nov 2 2001
+ copyright : (C) 2001 by Keith Isdale
+ email : k_isdale@tpg.com.au
+ ***************************************************************************/
+
+
+#include "xsldbg.h"
+#include "debugXSL.h"
+#include "breakpoint.h"
+#include "search.h"
+#include "options.h"
+#include "files.h"
+
+#ifdef __riscos
+
+/* Include for filename conversions */
+#include "libxml/riscos.h"
+#endif
+
+/* our private function*/
+void scanForBreakPoint(void *payload, void *data,
+ xmlChar * name);
+
+/* store all data in this document so we can write it to file*/
+static xmlDocPtr searchDataBase;
+
+/* the topmost node in document*/
+static xmlNodePtr searchDataBaseRoot;
+
+/* what was the last query that was run */
+static xmlChar *lastQuery;
+
+#define BUFFER_SIZE 500
+static xmlChar searchBuffer[BUFFER_SIZE];
+
+/* -----------------------------------------
+ Private function declarations for dbgsearch.c
+ -------------------------------------------*/
+
+/**
+ * findNodeByLineNoHelper:
+ * @payload: valid xsltStylesheetPtr
+ * @data: valid searchInfoPtr
+ * @name: not used
+ *
+ * We are walking through stylesheets looking for a match
+ */
+void
+ findNodeByLineNoHelper(void *payload, void *data,
+ xmlChar * name);
+
+/**
+ * globalVarHelper:
+ * @payload: valid xsltStylesheetPtr
+ * @data: is valid
+ * @name: not used
+ *
+ * Helper to find the global variables. We are given control via
+ * walkStylesheets globalWalkFunc will always be set to the
+ * walkFunc to call
+ */
+void
+ globalVarHelper(void **payload, void *data,
+ xmlChar * name);
+
+/**
+ * localVarHelper:
+ * @payload: valid xsltTemplatePtr
+ * @data: is valid
+ * @name: not used
+ *
+ * Helper to find the local variables. We are given control via walkTemplates
+ * globalWalkFunc will always be set to the walkFunc to call
+ * localWalkFunc will always be set to the walkFunc to call
+ */
+void
+ localVarHelper(void **payload, void *data,
+ xmlChar * name);
+
+
+/* -------------------------------------
+ End private functions
+ ---------------------------------------*/
+
+
+/**
+ * searchInit:
+ *
+ * Initialize the search module
+ *
+ * Returns 1 if search structures have been initialized properly and all
+ * memory required has been obtained,
+ * 0 otherwise
+*/
+int
+searchInit(void)
+{
+ searchDataBase = NULL;
+ searchDataBaseRoot = NULL;
+ lastQuery = NULL;
+ if (!searchEmpty()) {
+ xsldbgGenericErrorFunc(i18n("Error: Out of memory.\n"));
+ }
+ return (searchRootNode() != NULL);
+}
+
+
+/**
+ * searchFree:
+ *
+ * Free all memory used by the search module
+ */
+void
+searchFree(void)
+{
+ if (searchDataBase) {
+ xmlFreeDoc(searchDataBase);
+ searchDataBase = NULL;
+ searchDataBaseRoot = NULL;
+ }
+}
+
+
+/**
+ * searchNewInfo:
+ * @type: What type of search is required
+ *
+ * Create a new search
+ *
+ * Returns A valid search info pointer if successful
+ * NULL otherwise
+ */
+searchInfoPtr
+searchNewInfo(SearchEnum type)
+{
+ searchInfoPtr result = NULL;
+ int searchType = type;
+
+ switch (searchType) {
+ case SEARCH_BREAKPOINT:
+ result = (searchInfoPtr) xmlMalloc(sizeof(searchInfo));
+ if (result) {
+ breakPointSearchDataPtr searchData;
+
+ result->type = SEARCH_BREAKPOINT;
+ searchData = (breakPointSearchDataPtr)
+ xmlMalloc(sizeof(breakPointSearchData));
+ if (searchData) {
+ searchData->id = -1;
+ searchData->templateName = NULL;
+ searchData->breakPtr = NULL;
+ result->data = searchData;
+ } else {
+ xmlFree(result);
+ result = NULL;
+ }
+ }
+ break;
+
+ case SEARCH_NODE:
+ result = (searchInfoPtr) xmlMalloc(sizeof(searchInfo));
+ if (result) {
+ nodeSearchDataPtr searchData;
+
+ result->type = SEARCH_NODE;
+ searchData =
+ (nodeSearchDataPtr) xmlMalloc(sizeof(nodeSearchData));
+ if (searchData) {
+ searchData->node = NULL;
+ searchData->lineNo = -1;
+ searchData->url = NULL;
+ searchData->nameInput = NULL;
+ searchData->guessedNameMatch = NULL;
+ searchData->absoluteNameMatch = NULL;
+ result->data = searchData;
+ } else {
+ xmlFree(result);
+ result = NULL;
+ }
+ }
+ break;
+
+ case SEARCH_XSL:
+ break;
+
+ case SEARCH_VARIABLE:
+ result = (searchInfoPtr) xmlMalloc(sizeof(searchInfo));
+ if (result) {
+ variableSearchDataPtr searchData;
+
+ result->type = SEARCH_VARIABLE;
+ searchData = (variableSearchDataPtr)
+ xmlMalloc(sizeof(variableSearchData));
+ if (searchData) {
+ searchData->name = NULL;
+ searchData->nameURI = NULL;
+ searchData->select = NULL;
+ result->data = searchData;
+ } else {
+ xmlFree(result);
+ result = NULL;
+ }
+ }
+ break;
+
+ }
+ if (result) {
+ result->found = 0;
+ result->error = 0;
+ }
+ return result;
+}
+
+
+/**
+ * searchFreeInfo:
+ * @info: valid search info
+ *
+ * Free memory used by @info
+ */
+void
+searchFreeInfo(searchInfoPtr info)
+{
+ if (info) {
+ if (info->data) {
+ switch (info->type) {
+ case SEARCH_BREAKPOINT:
+ {
+ breakPointSearchDataPtr searchData =
+ (breakPointSearchDataPtr) info->data;
+
+ if (searchData->templateName)
+ xmlFree(searchData->templateName);
+ }
+ break;
+
+ case SEARCH_NODE:
+ {
+ nodeSearchDataPtr searchData =
+ (nodeSearchDataPtr) info->data;
+
+ if (searchData->url)
+ xmlFree(searchData->url);
+
+ if (searchData->nameInput)
+ xmlFree(searchData->nameInput);
+
+ if (searchData->guessedNameMatch)
+ xmlFree(searchData->guessedNameMatch);
+
+ if (searchData->absoluteNameMatch)
+ xmlFree(searchData->absoluteNameMatch);
+
+ /* we never free searchData->node as we did not create it! */
+ }
+ break;
+
+ case SEARCH_XSL:
+ break;
+
+ case SEARCH_VARIABLE:
+ {
+ variableSearchDataPtr searchData =
+ (variableSearchDataPtr) info->data;
+
+ if (searchData->name)
+ xmlFree(searchData->name);
+
+ if (searchData->nameURI)
+ xmlFree(searchData->nameURI);
+
+ if (searchData->select)
+ xmlFree(searchData->select);
+ }
+ break;
+
+ }
+ xmlFree(info->data);
+ }
+ xmlFree(info);
+ }
+}
+
+
+/**
+ * searchEmpty:
+ *
+ * Empty the seach dataBase of its contents
+ *
+ * Returns 1 on success,
+ * 0 otherwise
+ */
+int
+searchEmpty(void)
+{
+ if (searchDataBase) {
+ xmlFreeDoc(searchDataBase);
+ }
+ searchDataBase = xmlNewDoc((xmlChar *) "1.0");
+ searchDataBaseRoot = NULL;
+ if (searchDataBase) {
+ xmlCreateIntSubset(searchDataBase,
+ (xmlChar *) "search", (xmlChar *)
+ "-//xsldbg//DTD search XML V1.1//EN",
+ (xmlChar *) "search_v1_1.dtd");
+ searchDataBaseRoot = xmlNewNode(NULL, (xmlChar *) "search");
+ if (searchDataBaseRoot)
+ xmlAddChild((xmlNodePtr) searchDataBase, searchDataBaseRoot);
+ }
+ if (lastQuery)
+ xmlFree(lastQuery);
+ lastQuery = NULL;
+ if (searchRootNode() == NULL) {
+#ifdef WITH_XSLDBG_DEBUG_PROCESS
+ xsltGenericError(xsltGenericErrorContext,
+ "Error: Unable to clear old search results, memory error?\n");
+#endif
+ }
+
+ return (searchRootNode() != NULL);
+}
+
+
+/**
+ * searchDoc:
+ *
+ * Return the document used for seaching ie the search dataBase
+ *
+ * Returns The document used for searching
+ * Dangerous function to use! Does NOT return a copy of
+ * search data so don't free it
+ */
+xmlDocPtr
+searchDoc(void)
+{
+ return searchDataBase;
+}
+
+
+/**
+ * searchRootNode:
+ *
+ * Get the topmost node in the search dataBase
+ *
+ * Returns The topmost xml node in search dataBase.
+ * Dangerous function to use! Does NOT return a copy of
+ * search root node so don't free it
+ */
+xmlNodePtr
+searchRootNode(void)
+{
+ return searchDataBaseRoot;
+}
+
+
+/**
+ * searchAdd:
+ * @node: Is valid
+ *
+ * Add a node to the search dataBase
+ *
+ * Returns 1 if able to add @node to top node in search dataBase,
+ * 0 otherwise
+ */
+int
+searchAdd(xmlNodePtr node)
+{
+ int result = 0;
+
+ if (node && searchDataBaseRoot
+ && xmlAddChild(searchDataBaseRoot, node)) {
+ result = 1;
+ }
+
+ return result;
+}
+
+
+/**
+ * searchSave:
+ * @fileName: A valid file name, or NULL for the default
+ *
+ * Save the search dataBase to @fileName
+ *
+ * Returns 1 on success,
+ * 0 otherwise
+ */
+int
+searchSave(const xmlChar * fileName)
+{
+
+ int result = 0;
+ xmlChar *searchInput = NULL;
+
+ if (fileName == NULL)
+ searchInput = filesSearchFileName(FILES_SEARCHINPUT);
+ else
+ searchInput = xmlStrdup(fileName);
+
+ if (xmlSaveFormatFile((char *) searchInput, searchDataBase, 1) != -1){
+ result = 1;
+ }else{
+ xsldbgGenericErrorFunc(i18n("Error: Unable to write search Database to file %1. Try setting the \"searchresultspath\" option to a writable path.\n").arg(xsldbgText(searchInput)));
+ }
+
+ if (searchInput)
+ xmlFree(searchInput);
+
+ return result;
+}
+
+
+/**
+ * searchQuery:
+ * @query: The query to run . If NULL then query is "//search/ *"
+ * @tempFile: Where do we load the search dataBase from to execute
+ * query. If tempFile is NULL "searchresult.xml" is used
+ * @outputFile : Where do we store the result. If NULL
+ * then default to "searchresult.html"
+ *
+ * Send query as parameter for execution of search.xsl using
+ * data stored in @tempFile
+ *
+ * Returns 1 on success,
+ * 0 otherwise
+ */
+int
+searchQuery(const xmlChar * tempFile, const xmlChar * outputFile,
+ const xmlChar * query)
+{
+ int result = 0;
+
+ /* The file name of where the input is comming from */
+ xmlChar *searchInput = NULL;
+
+ /* The XSL file name to use during transformation of searchInput */
+ xmlChar *searchXSL = NULL;
+
+ /* Where to store the result of transformation */
+ xmlChar *searchOutput = NULL;
+
+
+ /* if a tempFile if provided its up you to make sure that it is correct !! */
+ if (tempFile == NULL)
+ searchInput = filesSearchFileName(FILES_SEARCHINPUT);
+ else
+ searchInput = xmlStrdup(tempFile);
+
+ searchXSL = filesSearchFileName(FILES_SEARCHXSL);
+
+ /* if a outputFile if provided its up you to make sure that it is correct */
+ if (outputFile == NULL)
+ searchOutput = filesSearchFileName(FILES_SEARCHRESULT);
+ else
+ searchOutput = xmlStrdup(outputFile);
+
+ if (!query || (xmlStrlen(query) == 0))
+ query = (xmlChar *) "--param query //search/*";
+
+ /* see configure.in for the definition of XSLDBG_BIN, the name of our binary */
+ if (searchInput && searchXSL && searchOutput) {
+ if (optionsGetIntOption(OPTIONS_CATALOGS) == 0)
+ snprintf((char *) searchBuffer, sizeof(searchBuffer),
+ "%s -o %s %s %s %s", XSLDBG_BIN,
+ searchOutput, query, searchXSL, searchInput);
+ else
+ /* assume that we are to use catalogs as well in our query */
+ snprintf((char *) searchBuffer, sizeof(searchBuffer),
+ "%s --catalogs -o %s %s %s %s", XSLDBG_BIN,
+ searchOutput, query, searchXSL, searchInput);
+ result = xslDbgShellExecute(searchBuffer, 1);
+
+ if (result && (optionsGetIntOption(OPTIONS_PREFER_HTML) == 0)) {
+ /* try printing out the file */
+ result = filesMoreFile(searchOutput, NULL);
+ }
+
+ xsldbgGenericErrorFunc(i18n("Information: Transformed %1 using %2 and saved to %3.\n").arg(xsldbgText(searchInput)).arg(xsldbgText(searchXSL)).arg(xsldbgText(searchOutput)));
+ } else {
+ xsldbgGenericErrorFunc(i18n("Error: Invalid arguments to command %1.\n").arg("search"));
+ }
+
+ if (searchInput)
+ xmlFree(searchInput);
+
+ if (searchXSL)
+ xmlFree(searchXSL);
+
+ if (searchOutput)
+ xmlFree(searchOutput);
+
+ return result;
+}
+
+
+/**
+ * scanForBreakPoint:
+ * @payload: A valid breakPointPtr
+ * @data: The criteria to look for and a valid searchInfoPtr of
+ * type SEARCH_BREAKPOINT
+ * @name: Not used
+ *
+ * Test if break point matches criteria given by @data. If so then
+ * set @data->found to 1 and stores reference to break point found in
+ * @data->data->node
+ * otherwise @data is unchanged
+*/
+void
+scanForBreakPoint(void *payload, void *data,
+ xmlChar * name)
+{
+ Q_UNUSED(name);
+ breakPointPtr breakPtr = (breakPointPtr) payload;
+ searchInfoPtr searchInf = (searchInfoPtr) data;
+ breakPointSearchDataPtr searchData = NULL;
+ int found = 0;
+
+ if (!payload || !searchInf || !searchInf->data
+ || (searchInf->type != SEARCH_BREAKPOINT) || searchInf->found)
+ return;
+
+ searchData = (breakPointSearchDataPtr) searchInf->data;
+
+ if (searchData->id && (breakPtr->id == searchData->id))
+ found = 1;
+ else if (searchData->templateName && breakPtr->templateName &&
+ (xmlStrCmp(breakPtr->templateName, searchData->templateName)
+ == 0))
+ found = 1;
+
+ if (found) {
+ searchInf->found = 1;
+ searchData->breakPtr = breakPtr;
+ }
+}
+
+
+
+/**
+ * scanForNode:
+ * @payload: A valid xmlNodePtr
+ * @data: The criteria to look for and a valid searchInfo of
+ * type SEARCH_NODE
+ * @name: Not used
+
+ * Test if node matches criteria given by @data if so then set @data->found
+ * to 1 and stores reference to node found in @data->data->node
+ * otherwise @data is unchanged
+ */
+void
+scanForNode(void *payload, void *data, xmlChar * name)
+{
+ Q_UNUSED(name);
+ searchInfoPtr searchInf = (searchInfoPtr) data;
+ nodeSearchDataPtr searchData = NULL;
+ xmlNodePtr node = (xmlNodePtr) payload;
+ xmlChar *baseUri = NULL;
+ int match = 1;
+
+ if (!node || !node->doc || !node->doc->URL ||
+ !searchInf || (searchInf->type != SEARCH_NODE))
+ return;
+
+ searchData = (nodeSearchDataPtr) searchInf->data;
+
+ if (searchData->lineNo >= 0)
+ match = searchData->lineNo == xmlGetLineNo(node);
+
+ if (searchData->url)
+ baseUri = filesGetBaseUri(node);
+ if (baseUri) {
+ match = match && (xmlStrCmp(searchData->url, baseUri) == 0);
+ xmlFree(baseUri);
+ } else {
+ match = match && (xmlStrcmp(searchData->url, node->doc->URL) == 0);
+ }
+
+ if (match) {
+ searchData->node = node;
+ searchInf->found = 1;
+ }
+
+}
+
+
+/**
+ * findNodeByLineNoHelper:
+ * @payload: A valid xsltStylesheetPtr
+ * @data: A valid searchInfoPtr
+ * @name: Not used
+ *
+ * We are walking through stylesheets looking for a match
+ */
+void
+findNodeByLineNoHelper(void *payload, void *data,
+ xmlChar * name)
+{
+ Q_UNUSED(name);
+ xsltStylesheetPtr style = (xsltStylesheetPtr) payload;
+ searchInfoPtr searchInf = (searchInfoPtr) data;
+
+ if (!payload || !searchInf || !style->doc)
+ return;
+
+ walkChildNodes((xmlHashScanner) scanForNode, searchInf,
+ (xmlNodePtr) style->doc);
+
+ /* try the included stylesheets */
+ if (!searchInf->found)
+ walkIncludes((xmlHashScanner) scanForNode, searchInf, style);
+}
+
+
+/**
+ * findNodeByLineNo:
+ * @ctxt: Valid ctxt to look into
+ * @url: Non-null, non-empty file name that has been loaded by debugger
+ * @lineNumber: @lineNumber >= 0 and is available in @url
+ *
+ * Finds the closest line number in file specified that can be a point
+ *
+ * Returns The node at line number number specified if successfull,
+ * NULL otherwise
+ */
+xmlNodePtr
+findNodeByLineNo(xsltTransformContextPtr ctxt,
+ const xmlChar * url, long lineNumber)
+{
+ xmlNodePtr result = NULL;
+ searchInfoPtr searchInf = searchNewInfo(SEARCH_NODE);
+ nodeSearchDataPtr searchData = NULL;
+
+ if (!searchInf) {
+#ifdef WITH_XSLDBG_DEBUG_PROCESS
+ xsltGenericError(xsltGenericErrorContext,
+ "Error: Unable to create searchInfo in findNodeByLineNo\n");
+#endif
+ return result;
+ }
+
+ if (!ctxt || !url || (lineNumber == -1)) {
+#ifdef WITH_XSLDBG_DEBUG_PROCESS
+ xsltGenericError(xsltGenericErrorContext,
+ "Error: Invalid ctxt, url or line number to findNodeByLineNo\n");
+#endif
+ return result;
+ }
+
+ searchData = (nodeSearchDataPtr) searchInf->data;
+ searchData->url = (xmlChar *) xmlMemStrdup((char *) url);
+ searchData->lineNo = lineNumber;
+ walkStylesheets((xmlHashScanner) findNodeByLineNoHelper, searchInf,
+ ctxt->style);
+ if (!searchInf->found) {
+ /* try searching the document set */
+ xsltDocumentPtr document = ctxt->document;
+
+ while (document && !searchInf->found) {
+ walkChildNodes((xmlHashScanner) scanForNode, searchInf,
+ (xmlNodePtr) document->doc);
+ document = document->next;
+ }
+ }
+ result = searchData->node;
+ searchFreeInfo(searchInf);
+
+ return result;
+}
+
+
+/**
+ * findTemplateNode:
+ * @style: A valid stylesheet collection to look into
+ * @name: A valid template name to look for
+ *
+ * Find a template node
+ *
+ * Returns The template node found if successful,
+ * NULL otherwise
+ */
+xmlNodePtr
+findTemplateNode(xsltStylesheetPtr style, const xmlChar * name)
+{
+ xmlNodePtr result = NULL;
+ xmlChar *templName;
+ xsltTemplatePtr templ;
+
+ if (!style || !name) {
+#ifdef WITH_XSLDBG_DEBUG_PROCESS
+ xsltGenericError(xsltGenericErrorContext,
+ "Error: Invalid stylesheet or template name : findTemplateNode\n");
+#endif
+ return result;
+ }
+
+ while (style) {
+ templ = style->templates;
+
+ while (templ) {
+ if (templ->match)
+ templName = (xmlChar *) templ->match;
+ else
+ templName = (xmlChar *) templ->name;
+
+ if (templName) {
+ if (!xmlStrCmp((char *) templName, (char *) name)) {
+ return templ->elem;
+ }
+ }
+ templ = templ->next;
+ }
+ if (style->next)
+ style = style->next;
+ else
+ style = style->imports;
+ }
+
+ if (!result)
+ xsldbgGenericErrorFunc(i18n("Error: XSLT template named \"%1\" was not found.\n").arg(xsldbgText(name)));
+ return result;
+}
+
+
+/**
+ * findBreakPointByName:
+ * @templateName: The template name to look for
+ *
+ * Find the breakpoint at template with "match" or "name" equal
+ * to templateName
+ *
+ * Returns The break point that matches @templateName
+ * NULL otherwise
+*/
+breakPointPtr
+findBreakPointByName(const xmlChar * templateName)
+{
+ breakPointPtr result = NULL;
+ searchInfoPtr searchInf = searchNewInfo(SEARCH_BREAKPOINT);
+ breakPointSearchDataPtr searchData;
+
+ if (!searchInf || (searchInf->type != SEARCH_BREAKPOINT))
+ return result;
+
+ searchData = (breakPointSearchDataPtr) searchInf->data;
+ searchData->templateName = (xmlChar *) xmlStrdup(templateName);
+ if (templateName) {
+ walkBreakPoints((xmlHashScanner) scanForBreakPoint, searchInf);
+ if (!searchInf->found) {
+#ifdef WITH_XSLDBG_DEBUG_PROCESS
+ xsltGenericError(xsltGenericErrorContext,
+ "Error: Breakpoint with template name of \"%s\" not found\n",
+ templateName);
+#endif
+ } else
+ result = searchData->breakPtr;
+ }
+
+ searchFreeInfo(searchInf);
+
+ return result;
+}
+
+
+/**
+ * findBreakPointById:
+ * @id: The break point id to look for
+ *
+ * Find a break point by its id
+ *
+ * Returns The break point with given the break point id if found,
+ * NULL otherwise
+ */
+breakPointPtr
+findBreakPointById(int id)
+{
+ breakPointPtr result = NULL;
+ searchInfoPtr searchInf = searchNewInfo(SEARCH_BREAKPOINT);
+ breakPointSearchDataPtr searchData;
+
+ if (!searchInf || !searchInf->data)
+ return result;
+
+ searchData = (breakPointSearchDataPtr) searchInf->data;
+ if (id >= 0) {
+ searchData->id = id;
+ walkBreakPoints((xmlHashScanner) scanForBreakPoint, searchInf);
+ if (!searchInf->found) {
+#ifdef WITH_XSLDBG_DEBUG_PROCESS
+ xsltGenericError(xsltGenericErrorContext,
+ "Error: Breakpoint id %d not found\n", id);
+#endif
+ } else
+ result = searchData->breakPtr;
+ }
+
+ searchFreeInfo(searchInf);
+ return result;
+}
+
+
+/**
+ * findNodesByQuery:
+ * @query: The xpath query to run, see docs/en/search.dtd for more details
+ *
+ * Find nodes in search dataBase using an xpath query
+ *
+ * Returns The nodes that match the given query on success,
+ * NULL otherwise
+ */
+xmlXPathObjectPtr
+findNodesByQuery(const xmlChar * query)
+{
+ Q_UNUSED(query);
+ xmlXPathObjectPtr list = NULL;
+
+ return list;
+}
+
+
+
+/**
+ * walkBreakPoints:
+ * @walkFunc: The function to callback for each break point found
+ * @data: The extra data to pass onto walkFunc
+ *
+ * Walks through all break points calling walkFunc for each. The payload
+ * sent to walkFunc is of type breakPointPtr
+ */
+void
+walkBreakPoints(xmlHashScanner walkFunc, void *data)
+{
+ int lineNo;
+ xmlHashTablePtr hashTable;
+
+ if (!walkFunc)
+ return;
+
+ for (lineNo = 0; lineNo < breakPointLinesCount(); lineNo++) {
+ hashTable = breakPointGetLineNoHash(lineNo);
+ if (hashTable) {
+ xmlHashScan(hashTable, walkFunc, data);
+ }
+ }
+}
+
+
+/**
+ * walkTemplates:
+ * @walkFunc: The function to callback for each template found
+ * @data: The extra data to pass onto walkFunc
+ * @style: The stylesheet to start from
+ *
+ * Walks through all templates calling walkFunc for each. The payload
+ * of walkFunc is of type xsltTemplatePtr
+ */
+void
+walkTemplates(xmlHashScanner walkFunc, void *data, xsltStylesheetPtr style)
+{
+ xsltTemplatePtr templ;
+
+ if (!walkFunc || !style)
+ return;
+
+ while (style) {
+ templ = style->templates;
+ while (templ) {
+ (*walkFunc) (templ, data, NULL);
+ templ = templ->next;
+ }
+ if (style->next)
+ style = style->next;
+ else
+ style = style->imports;
+ }
+}
+
+
+/**
+ * walkStylesheets:
+ * @walkFunc: The function to callback for each stylesheet found
+ * @data: The extra data to pass onto walkFunc
+ * @style: The stylesheet to start from
+ *
+ * Walks through all templates calling walkFunc for each. The payload
+ * sent to walkFunc is of type xsltStylesheetPtr
+ */
+void
+walkStylesheets(xmlHashScanner walkFunc, void *data,
+ xsltStylesheetPtr style)
+{
+ xsltStylesheetPtr next;
+
+ if (!walkFunc || !style)
+ return;
+
+ next = style->next;
+ while (style) {
+ (*walkFunc) (style, data, NULL);
+ if (style->imports)
+ style = style->imports;
+ else
+ style = next;
+ }
+}
+
+
+
+xmlHashScanner globalWalkFunc = NULL;
+
+/**
+ * globalVarHelper:
+ * @payload: valid xsltStylesheetPtr
+ * @data: is valid
+ * @name: not used
+ *
+ * Helper to find the global variables. We are given control via
+ * walkStylesheets globalWalkFunc will always be set to the
+ * walkFunc to call
+ */
+void
+globalVarHelper(void **payload, void *data,
+ xmlChar * name)
+{
+ Q_UNUSED(data);
+ Q_UNUSED(name);
+ xsltStylesheetPtr style = (xsltStylesheetPtr) payload;
+ xsltStackElemPtr global;
+
+ if (style) {
+ global = style->variables;
+
+ while (global &&global->comp) {
+ (*globalWalkFunc) (global->comp->inst, data, NULL);
+ global = global->next;
+ }
+ }
+}
+
+
+/**
+ * walkGlobals:
+ * @walkFunc: The function to callback for each gobal variable found
+ * @data: The extra data to pass onto walkFunc
+ * @style: The stylesheet to start from
+ *
+ * Call walkFunc for each global variable. The payload
+ * sent to walkFunc is of type xmlNodePtr
+ */
+void
+walkGlobals(xmlHashScanner walkFunc, void *data,
+ xsltStylesheetPtr style)
+{
+ Q_UNUSED(data);
+ if (!walkFunc || !style)
+ return;
+
+ globalWalkFunc = walkFunc;
+
+ walkStylesheets((xmlHashScanner) globalVarHelper, data, style);
+}
+
+
+
+xmlHashScanner localWalkFunc = NULL;
+
+/**
+ * localVarHelper:
+ * @payload: valid xsltTemplatePtr
+ * @data: is valid
+ * @name: not used
+ *
+ * Helper to find the local variables. We are given control via walkTemplates
+ * globalWalkFunc will always be set to the walkFunc to call
+ * localWalkFunc will always be set to the walkFunc to call
+ */
+void
+localVarHelper(void **payload, void *data,
+ xmlChar * name)
+{
+ Q_UNUSED(data);
+ Q_UNUSED(name);
+ xsltTemplatePtr templ = (xsltTemplatePtr) payload;
+ xmlNodePtr node;
+
+ if (templ && templ->elem) {
+ node = templ->elem->children;
+
+ while (node) {
+ if (IS_XSLT_NAME(node, "param")
+ || IS_XSLT_NAME(node, "variable")) {
+ (*localWalkFunc) (node, data, NULL);
+ node = node->next;
+ } else
+ break;
+ }
+ }
+}
+
+
+/**
+ * walkLocals:
+ * @walkFunc: The function to callback for each local variable found
+ * @data: The extra data to pass onto walkFunc
+ * @style: The stylesheet to start from
+ *
+ * Walks through all local variables calling walkFunc for each. The payload
+ * of walkFunc is of type xmlNodePtr
+ */
+void
+walkLocals(xmlHashScanner walkFunc, void *data, xsltStylesheetPtr style)
+{
+ if (!walkFunc || !style)
+ return;
+
+ localWalkFunc = walkFunc;
+
+ walkTemplates((xmlHashScanner) localVarHelper, data, style);
+
+}
+
+
+/**
+ * walkIncludes:
+ * @walkFunc: The function to callback for each included stylesheet
+ * @data: The extra data to pass onto walkFunc
+ * @style: The stylesheet to start from
+ *
+ * Walks through all included stylesheets calling walkFunc for each.
+ * The payload of walkFunc is of type xmlNodePtr
+ */
+
+void
+walkIncludes(xmlHashScanner walkFunc, void *data, xsltStylesheetPtr style)
+{
+ xsltDocumentPtr document; /* included xslt documents */
+
+ if (!walkFunc || !style)
+ return;
+
+ while (style) {
+ document = style->docList;
+ /* look at included documents */
+ while (document) {
+ (*walkFunc) ((xmlNodePtr) document->doc, data, NULL);
+ document = document->next;
+ }
+ /* try next stylesheet */
+ if (style->next)
+ style = style->next;
+ else
+ style = style->imports;
+ }
+}
+
+
+/**
+ * walkIncludeInst:
+ * @walkFunc: The function to callback for each xsl:include instruction found
+ * @data: The extra data to pass onto walkFunc
+ * @style: The stylesheet to start from
+ *
+ * Walks through all xsl:include calling walkFunc for each. The payload
+ * of walkFunc is of type xmlNodePtr
+ */
+void
+walkIncludeInst(xmlHashScanner walkFunc, void *data,
+ xsltStylesheetPtr style)
+{
+ xmlNodePtr node = NULL, styleChild = NULL;
+
+ if (!walkFunc || !style)
+ return;
+
+ while (style) {
+ /*look for stylesheet node */
+ if (style->doc) {
+ node = (xmlNodePtr) style->doc->children;
+ while (node) {
+ /* not need but just in case :) */
+ if (IS_XSLT_NAME(node, "stylesheet")
+ || IS_XSLT_NAME(node, "transform")) {
+ styleChild = node->children; /* get the topmost elements */
+ break;
+ } else
+ node = node->next;
+ }
+
+ /* look for includes */
+ while (styleChild) {
+ if (IS_XSLT_NAME(styleChild, "include"))
+ (*walkFunc) (styleChild, data, NULL);
+ styleChild = styleChild->next;
+ }
+ }
+ /* try next stylesheet */
+ if (style->next)
+ style = style->next;
+ else
+ style = style->imports;
+ }
+}
+
+
+/**
+ * walkChildNodes:
+ * @walkFunc: The function to callback for each child/sibling found
+ * @data: The extra data to pass onto walkFunc
+ * @node: Is valid
+ *
+ * Call walkFunc for each child of @node the payload sent to walkFunc is
+ * a xmlNodePtr
+ */
+void
+walkChildNodes(xmlHashScanner walkFunc, void *data, xmlNodePtr node)
+{
+ xmlNodePtr child = NULL;
+ searchInfoPtr searchInf = (searchInfoPtr) data;
+
+ if (!walkFunc || !searchInf || !searchInf->data)
+ return;
+
+ while (node && !searchInf->found) {
+ (walkFunc) (node, data, NULL);
+ child = node->children;
+ if (child && !searchInf->found) {
+ walkChildNodes(walkFunc, data, child);
+ }
+ node = node->next;
+ }
+}
+
+
+/**
+ * searchBreakPointNode:
+ * @breakPtr: Is valid
+ *
+ * Convert @breakPtr into search dataBase format
+ *
+ * Returns @breakPtr as a new xmlNode in search dataBase format
+ * if successful,
+ * NULL otherwise
+ */
+xmlNodePtr
+searchBreakPointNode(breakPointPtr breakPtr)
+{
+
+ xmlNodePtr node = NULL;
+ int result = 1;
+
+ if (breakPtr) {
+ node = xmlNewNode(NULL, (xmlChar *) "breakpoint");
+ if (node) {
+ /* if unable to create any property failed then result will be equal to 0 */
+ result = result
+ && (xmlNewProp(node, (xmlChar *) "url", breakPtr->url) !=
+ NULL);
+ sprintf((char *) searchBuffer, "%ld", breakPtr->lineNo);
+ result = result
+ &&
+ (xmlNewProp(node, (xmlChar *) "line", (xmlChar *) searchBuffer)
+ != NULL);
+ if (breakPtr->templateName) {
+ result = result
+ &&
+ (xmlNewProp
+ (node, (xmlChar *) "template",
+ breakPtr->templateName) != NULL);
+ }
+ sprintf((char *) searchBuffer, "%d", breakPtr->flags & BREAKPOINT_ENABLED);
+ result = result
+ &&
+ (xmlNewProp
+ (node, (xmlChar *) "enabled", (xmlChar *) searchBuffer)
+ != NULL);
+ sprintf((char *) searchBuffer, "%d", breakPtr->type);
+ result = result
+ &&
+ (xmlNewProp(node, (xmlChar *) "type", (xmlChar *) searchBuffer)
+ != NULL);
+ sprintf((char *) searchBuffer, "%d", breakPtr->id);
+ result = result
+ && (xmlNewProp(node, (xmlChar *) "id", (xmlChar *) searchBuffer)
+ != NULL);
+ } else
+ result = 0;
+ if (!result) {
+ xsldbgGenericErrorFunc(i18n("Error: Out of memory.\n"));
+ }
+ }
+ return node;
+}
+
+
+/**
+ * searchTemplateNode:
+ * @templNode: Is valid
+ *
+ * Convert @templateNode into search dataBase format
+ *
+ * Returns @templNode as a new xmlNode in search dataBase format
+ * if successful,
+ * NULL otherwise
+ */
+xmlNodePtr
+searchTemplateNode(xmlNodePtr templNode)
+{
+ xmlNodePtr node = NULL;
+ xmlChar *value;
+ int result = 1;
+
+ if (templNode) {
+ node = xmlNewNode(NULL, (xmlChar *) "template");
+ if (node) {
+ /* if unable to create any property failed then result will be equal to 0 */
+ value = xmlGetProp(templNode, (xmlChar *) "match");
+ if (value) {
+ result = result
+ && (xmlNewProp(node, (xmlChar *) "match", value) !=
+ NULL);
+ xmlFree(value);
+ }
+ value = xmlGetProp(templNode, (xmlChar *) "name");
+ if (value) {
+ result = result
+ && (xmlNewProp(node, (xmlChar *) "name", value) !=
+ NULL);
+ xmlFree(value);
+ }
+ if (templNode->doc) {
+ result = result
+ &&
+ (xmlNewProp
+ (node, (xmlChar *) "url",
+ templNode->doc->URL) != NULL);
+ }
+ sprintf((char *) searchBuffer, "%ld", xmlGetLineNo(templNode));
+ result = result
+ &&
+ (xmlNewProp(node, (xmlChar *) "line", (xmlChar *) searchBuffer)
+ != NULL);
+ if (result) {
+ xmlNodePtr textNode = searchCommentNode(templNode);
+
+ if (textNode && !xmlAddChild(node, textNode))
+ result = 0;
+ }
+ } else
+ result = 0;
+ if (!result) {
+ xsldbgGenericErrorFunc(i18n("Error: Out of memory.\n"));
+ }
+ }
+ return node;
+}
+
+
+/**
+ * searchGlobalNode:
+ * @globalVariable: Is valid
+ *
+ * Convert @globalVariable into search dataBase format
+ *
+ * Returns @globalVariable as a new xmlNode in search dataBase format
+ * if successful,
+ * NULL otherwise
+ */
+xmlNodePtr
+searchGlobalNode(xmlNodePtr variable)
+{
+ xmlNodePtr node = NULL;
+ int result = 1;
+ xmlChar *value;
+
+ if (variable) {
+ node = xmlNewNode(NULL, (xmlChar *) "variable");
+ if (node) {
+ /* if unable to create any property failed then result will be equal to 0 */
+ if (variable->doc) {
+ result = result &&
+ (xmlNewProp(node, (xmlChar *) "url",
+ variable->doc->URL) != NULL);
+ sprintf((char *) searchBuffer, "%ld", xmlGetLineNo(variable));
+ result = result
+ && (xmlNewProp(node, (xmlChar *) "line",
+ (xmlChar *) searchBuffer) != NULL);
+ }
+ value = xmlGetProp(variable, (xmlChar *) "name");
+ if (value) {
+ result = result
+ && (xmlNewProp(node, (xmlChar *) "name", value) !=
+ NULL);
+ xmlFree(value);
+ }
+ value = xmlGetProp(variable, (xmlChar *) "select");
+ if (value) {
+ result = result
+ && (xmlNewProp(node, (xmlChar *) "select", value) !=
+ NULL);
+ xmlFree(value);
+ }
+ if (result) {
+ xmlNodePtr textNode = searchCommentNode(variable);
+
+ if (textNode && !xmlAddChild(node, textNode))
+ result = 0;
+ }
+ } else
+ result = 0;
+ }
+ if (!result) {
+ xsldbgGenericErrorFunc(i18n("Error: Out of memory.\n"));
+ }
+ return node;
+}
+
+
+/**
+ * searchLocalNode:
+ * @localvariable: Is valid
+ *
+ * Convert @localVariable into search dataBase format
+ *
+ * Returns @localVariable as a new xmlNode in search dataBase format
+ * if successful,
+ * NULL otherwise
+ */
+xmlNodePtr
+searchLocalNode(xmlNodePtr variable)
+{
+ xmlNodePtr node = NULL;
+ int result = 1;
+ xmlChar *value;
+ xmlNodePtr parent;
+
+ if (variable) {
+ node = searchGlobalNode(variable);
+ if (node) {
+ /* if unable to create any property failed then result will be equal to 0 */
+ parent = variable->parent;
+ /* try to find out what template this variable belongs to */
+ if (parent && IS_XSLT_NAME(parent, "template")) {
+ value = xmlGetProp(parent, (xmlChar *) "name");
+ if (value) {
+ result = result
+ &&
+ (xmlNewProp(node, (xmlChar *) "templname", value)
+ != NULL);
+ xmlFree(value);
+ }
+ value = xmlGetProp(parent, (xmlChar *) "match");
+ if (value) {
+ result = result
+ &&
+ (xmlNewProp(node, (xmlChar *) "templmatch", value)
+ != NULL);
+ xmlFree(value);
+ }
+ }
+ } else
+ result = 0;
+ }
+ if (!result) {
+ xsldbgGenericErrorFunc(i18n("Error: Out of memory.\n"));
+ }
+ return node;
+}
+
+
+/**
+ * searchSourceNode:
+ * @style: Is valid
+ *
+ * Convert @style into search dataBase format
+ *
+ * Returns @style as a new xmlNode in search dataBase format if successful,
+ * NULL otherwise
+ */
+xmlNodePtr
+searchSourceNode(xsltStylesheetPtr style)
+{
+ xmlNodePtr node = NULL;
+ int result = 1;
+
+ if (style) {
+ if (style->parent == NULL)
+ node = xmlNewNode(NULL, (xmlChar *) "source");
+ else
+ node = xmlNewNode(NULL, (xmlChar *) "import");
+ if (node) {
+ /* if unable to create any property failed then result will be equal to 0 */
+ if (style->doc) {
+ result = result &&
+ (xmlNewProp(node, (xmlChar *) "href", style->doc->URL)
+ != NULL);
+ if (style->parent && style->parent->doc) {
+ result = result &&
+ (xmlNewProp(node, (xmlChar *) "parent",
+ style->parent->doc->URL) != NULL);
+ }
+ if (result) {
+ xmlNodePtr textNode =
+ searchCommentNode((xmlNodePtr) style->doc);
+ if (textNode && !xmlAddChild(node, textNode))
+ result = 0;
+ }
+ }
+ } else
+ result = 0;
+ }
+ if (!result) {
+ xsldbgGenericErrorFunc(i18n("Error: Out of memory.\n"));
+ }
+ return node;
+}
+
+
+/**
+ * searchIncludeNode:
+ * @include: Is a valid xsl:include instruction
+ *
+ * Convert @include into search dataBase format
+ *
+ * Returns @include as a new xmlNode in search dataBase format if successful,
+ * NULL otherwise
+ */
+xmlNodePtr
+searchIncludeNode(xmlNodePtr include)
+{
+ xmlNodePtr node = NULL;
+ int result = 1;
+ xmlChar *value;
+
+ if (include) {
+ node = xmlNewNode(NULL, (xmlChar *) "include");
+ if (node) {
+ /* if unable to create any property failed then result will be equal to 0 */
+ if (include->doc) {
+ value = xmlGetProp(include, (xmlChar *) "href");
+ if (value) {
+ result = result
+ && (xmlNewProp(node, (xmlChar *) "href", value) !=
+ NULL);
+ xmlFree(value);
+ }
+ if (include->parent && include->parent->doc) {
+ result = result &&
+ (xmlNewProp(node, (xmlChar *) "url",
+ include->parent->doc->URL) != NULL);
+ sprintf((char *) searchBuffer, "%ld", xmlGetLineNo(include));
+ result = result
+ && (xmlNewProp(node, (xmlChar *) "line",
+ (xmlChar *) searchBuffer) != NULL);
+ }
+ if (result) {
+ xmlNodePtr textNode = searchCommentNode(include);
+
+ if (textNode && !xmlAddChild(node, textNode))
+ result = 0;
+ }
+ }
+ } else
+ result = 0;
+ }
+ if (!result) {
+ xsldbgGenericErrorFunc(i18n("Error: Out of memory.\n"));
+ }
+ return node;
+}
+
+
+/**
+ * searchCallStackNode:
+ * @callStackItem: Is valid
+ *
+ * Convert @callStackItem into search dataBase format
+ *
+ * Returns @callStackItem as a new xmlNode in search dataBase format
+ * if successful,
+ * NULL otherwise
+ */
+xmlNodePtr
+searchCallStackNode(callPointPtr callStackItem)
+{
+ xmlNodePtr node = NULL;
+ int result = 1;
+
+ if (callStackItem) {
+ node = xmlNewNode(NULL, (xmlChar *) "callstack");
+ if (node) {
+ /* if unable to create any property failed then result will be equal to 0 */
+ if (callStackItem->info && callStackItem->info->url)
+ result = result
+ &&
+ (xmlNewProp
+ (node, (xmlChar *) "url", callStackItem->info->url)
+ != NULL);
+ sprintf((char *) searchBuffer, "%ld", callStackItem->lineNo);
+ result = result
+ &&
+ (xmlNewProp(node, (xmlChar *) "line", (xmlChar *) searchBuffer)
+ != NULL);
+ if (callStackItem->info && callStackItem->info->templateName) {
+ result = result &&
+ (xmlNewProp
+ (node, (xmlChar *) "template",
+ callStackItem->info->templateName) != NULL);
+ }
+ } else
+ result = 0;
+ if (!result) {
+ xsldbgGenericErrorFunc(i18n("Error: Out of memory.\n"));
+ }
+ }
+ return node;
+}
+
+
+static xmlChar *commentText(xmlNodePtr node);
+
+/*
+ * Returns A copy of comment text that applies to node,
+ * NULL otherwise
+ */
+xmlChar *
+commentText(xmlNodePtr node)
+{
+ xmlChar *result = NULL;
+
+ if (node) {
+ if (node->type == XML_COMMENT_NODE)
+ result = xmlNodeGetContent(node);
+ }
+
+ return result;
+}
+
+/**
+ * searchCommentNode:
+ * @sourceNode: Is valid
+ *
+ * Find documentation comment that applies to @node. If found convert comment
+ * into search dataBase format required
+ *
+ * Returns Documentation comment for @node as a new xmlNode in search dataBase format
+ * if successful,
+ * NULL otherwise
+ */
+xmlNodePtr
+searchCommentNode(xmlNodePtr sourceNode)
+{
+ xmlNodePtr node = NULL, textChild = NULL;
+ xmlChar *text = NULL;
+ int result = 0;
+
+ if (sourceNode) {
+ text = commentText(sourceNode->prev);
+ if (!text) {
+ text = commentText(sourceNode->children);
+ }
+
+ if (text) {
+ node = xmlNewNode(NULL, (xmlChar *) "comment");
+ textChild = xmlNewText(text);
+ if (node && textChild && xmlAddChild(node, textChild)) {
+ result = 1;
+ }
+ if (!result) {
+ if (node) {
+ xmlFreeNode(node);
+ node = NULL;
+ }
+ if (textChild)
+ xmlFreeNode(textChild);
+ }
+
+ xmlFree(text);
+ }
+ }
+ return node;
+}