From e9ae80694875f869892f13f4fcaf1170a00dea41 Mon Sep 17 00:00:00 2001 From: toma Date: Wed, 25 Nov 2009 17:56:58 +0000 Subject: Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features. BUG:215923 git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdewebdev@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da --- kxsldbg/kxsldbgpart/libxsldbg/search.cpp | 1584 ++++++++++++++++++++++++++++++ 1 file changed, 1584 insertions(+) create mode 100644 kxsldbg/kxsldbgpart/libxsldbg/search.cpp (limited to 'kxsldbg/kxsldbgpart/libxsldbg/search.cpp') 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; +} -- cgit v1.2.1