You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1592 lines
43 KiB
1592 lines
43 KiB
|
|
/***************************************************************************
|
|
search.c - search implementation
|
|
-------------------
|
|
begin : Fri Nov 2 2001
|
|
copyright : (C) 2001 by Keith Isdale
|
|
email : k_isdale@tpg.com.au
|
|
***************************************************************************/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include "config.h"
|
|
#endif
|
|
|
|
#ifndef XSLDBG_BIN
|
|
#define XSLDBG_BIN "xsldbg"
|
|
#endif
|
|
|
|
#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;
|
|
}
|