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.
tdewebdev/kxsldbg/kxsldbgpart/libxsldbg/callstack.cpp

510 lines
13 KiB

/***************************************************************************
callstack.c - call stack implementation
-------------------
begin : Fri Nov 2 2001
copyright : (C) 2001 by Keith Isdale
email : k_isdale@tpg.com.au
***************************************************************************/
#include "xsldbg.h"
#include "utils.h"
#include "breakpoint.h"
#include "arraylist.h"
#include "callstack.h"
#include "xsldbgmsg.h"
/*------------------------------------------------------
Private functions
-----------------------------------------------------*/
/**
* addCallInfo:
* @templateName: Template name to add
* @templateURI: QName part of template name to add
* @modeName: Mode of template
* @modeURI: QName part of node of template
* @url: The url for the template
*
* Add template "call" to call stack
*
* Returns A reference to the added info if successful,
* NULL otherwise
*/
callPointInfoPtr
addCallInfo(const xmlChar * templateName, const xmlChar *templateURI,
const xmlChar * modeName, const xmlChar* modeURI, const xmlChar * url);
/*------------------------------------------------------
Xsl call stack related
-----------------------------------------------------*/
/* keep track of the top and bottom of call stack*/
/* This is the major structure and contains a stack of call points */
callPointPtr callStackBot, callStackTop;
/* save memory by keep only one copy of data used for several
items on call stack */
callPointInfoPtr callInfo;
/* What frame depth are we to stop at */
int stopDepth = -1;
/**
* callStackInit:
*
* Returns If callStack has been initialized properly and all
* memory required has been obtained,
* 0 otherwise
*
* Returns 1 if callStack has been initialized properly and all
* memory required has been obtained,
* 0 otherwise
*/
int
callStackInit(void)
{
callInfo = (callPointInfoPtr) xmlMalloc(sizeof(callPointInfo));
if (callInfo) {
callInfo->next = NULL;
callInfo->templateName = NULL;
callInfo->templateURI = NULL;
callInfo->modeName = NULL;
callInfo->modeURI = NULL;
callInfo->url = NULL;
}
callStackBot = (callPointPtr) xmlMalloc(sizeof(callPoint));
if (callStackBot) {
callStackBot->next = NULL;
callStackBot->info = NULL;
callStackBot->lineNo = -1;
callStackTop = callStackBot;
}
return (callInfo != NULL) && (callStackBot != NULL);
}
/**
* callStackFree:
*
*
* Free all memory used by callStack
*/
void
callStackFree(void)
{
callPointInfoPtr curInfo = callInfo, nextInfo;
callPointPtr curCall = callStackBot, nextCall;
/* remove all call info's */
while (curInfo) {
nextInfo = curInfo->next;
if (curInfo->templateName)
xmlFree(curInfo->templateName);
if (curInfo->templateURI)
xmlFree(curInfo->templateURI);
if (curInfo->modeName)
xmlFree(curInfo->modeName);
if (curInfo->modeURI)
xmlFree(curInfo->modeURI);
if (curInfo->url)
xmlFree(curInfo->url);
xmlFree(curInfo);
curInfo = nextInfo;
}
curInfo = NULL;
/* remove all call stack items left. There should be none !! */
while (curCall) {
nextCall = curCall->next;
xmlFree(curCall);
curCall = nextCall;
}
callStackBot = NULL;
callStackTop = NULL;
callInfo = NULL;
}
/**
* addCallInfo:
* @templateName: Template name to add
* @templateURI: QName part of template name to add
* @modeName: Mode of template
* @modeURI: QName part of node of template
* @url: The url for the template
*
* Add template "call" to call stack
*
* Returns A reference to the added info if successful,
* NULL otherwise
*/
callPointInfoPtr
addCallInfo(const xmlChar * templateName, const xmlChar *templateURI,
const xmlChar * modeName, const xmlChar* modeURI, const xmlChar * url)
{
callPointInfoPtr result = NULL, cur = callInfo;
int found;
if (!templateName || !url) {
#ifdef WITH_XSLDBG_DEBUG_PROCESS
xsltGenericError(xsltGenericErrorContext,
"Error: Null template name or url: addCallInfo\n");
if (templateName)
xsltGenericError(xsltGenericErrorContext, "template :\"%s\"\n",
templateName);
if (url)
xsltGenericError(xsltGenericErrorContext, "url :\"%s\"\n", url);
#endif
return result;
}
while (cur->next) {
found = 1;
if (templateName && cur->templateName
&& !xmlStrEqual(cur->templateName, templateName))
found = 0;
if (found && !xmlStrEqual(cur->templateURI, templateURI))
found = 0;
if (found && !xmlStrEqual(cur->modeName, modeName))
found = 0;
if (found && !xmlStrEqual(cur->modeURI, modeURI))
found = 0;
if (found && !xmlStrEqual(cur->url, url))
found = 0;
if (found){
result = cur;
break;
}
cur = cur->next;
}
if (!result && cur) {
result = (callPointInfoPtr) xmlMalloc(sizeof(callPointInfo));
if (result) {
if ((cur == callInfo) && !cur->templateName && !cur->templateURI
&& !cur->modeName && !cur->modeURI
&& !cur->url){
xmlFree(callInfo);
callInfo = result;
} else{
cur->next = result;
}
result->templateName =
(xmlChar *) xmlMemStrdup((char *) templateName);
result->templateURI =
(xmlChar *) xmlMemStrdup((char *) templateURI);
result->modeName =
(xmlChar *) xmlMemStrdup((char *) modeName);
result->modeURI =
(xmlChar *) xmlMemStrdup((char *) modeURI);
result->url = (xmlChar *) xmlMemStrdup((char *) url);
result->next = NULL;
}else {
#ifdef WITH_XSLDBG_DEBUG_PROCESS
xsltGenericError(xsltGenericErrorContext,
"Error: Unable to create callPointInfo from : addCallInfo\n");
#endif
}
}
if (!cur){
#ifdef WITH_XSLDBG_DEBUG_PROCESS
xsltGenericError(xsltGenericErrorContext,
"Error: Unable to create callPointInfo from : addCallInfo\n");
#endif
}
return result;
}
/**
* callStackAdd:
* @templ: The current template being applied
* @source: The source node being processed
*
* Add template "call" to call stack
*
* Returns 1 on success,
* 0 otherwise
*/
int
callStackAdd(xsltTemplatePtr templ, xmlNodePtr source)
{
int result = 0;
const char *name = "Default template";
callPointInfoPtr info;
if (!templ || !source)
return result;
if (!source->doc || !source->doc->URL) {
#ifdef WITH_XSLDBG_DEBUG_PROCESS
xsltGenericError(xsltGenericErrorContext,
"Error: Invalid document url in call from : callStackAdd\n");
#endif
return result;
}
/* are at a "frame" break point ie "step down" */
if ((xslDebugStatus == DEBUG_STEPDOWN)
&& (stopDepth == callStackGetDepth())) {
xslDebugStatus = DEBUG_STOP;
stopDepth = 0;
}
/* this need not be an error just we've got a text in source */
if (xmlGetLineNo(source) == -1) {
return result;
}
if (templ) {
if (templ->name)
name = (char *) templ->name;
else {
if (templ->match)
name = (char *) templ->match;
}
}
if (!name) {
#ifdef WITH_XSLDBG_DEBUG_PROCESS
xsltGenericError(xsltGenericErrorContext,
"Error: Invalid template name : callStackAdd\n");
#endif
return result;
}
info = addCallInfo((xmlChar *) name, (xmlChar *) templ->nameURI,
(xmlChar *) templ->mode, (xmlChar *) templ->modeURI,
source->doc->URL);
if (info) {
callPointPtr cur;
cur = (callPointPtr) xmlMalloc(sizeof(callPoint));
if (cur) {
callStackTop->next = cur;
callStackTop = cur;
cur->info = info;
cur->lineNo = xmlGetLineNo(source);
cur->next = NULL;
result = 1;
} else {
#ifdef WITH_XSLDBG_DEBUG_PROCESS
xsltGenericError(xsltGenericErrorContext,
"Error: Unable to create call point : callStackAdd\n");
#endif
}
} else {
#ifdef WITH_XSLDBG_DEBUG_PROCESS
xsltGenericError(xsltGenericErrorContext,
"Error: Unable to create call info : callStackAdd\n");
#endif
}
return result;
}
/**
* callStackDrop:
*
*
* Drop the topmost item off the call stack
*/
void
callStackDrop(void)
{
if (!callStackBot) {
#ifdef WITH_XSLDBG_DEBUG_PROCESS
xsltGenericError(xsltGenericErrorContext,
"Error: callStackDrop failed invalid call stack: dbgcallstack.c");
#endif
return;
}
/* are we at a "frame" break point ie "step up". if we've gone too
* far stop imediately */
if ((xslDebugStatus == DEBUG_STEPUP)
&& (-1 * callStackGetDepth()) >= stopDepth) {
xslDebugStatus = DEBUG_STOP;
stopDepth = 0;
}
if (callStackBot->next) {
callPointPtr cur = callStackBot;
while (cur->next && cur->next->next) {
cur = cur->next;
}
if (cur->next)
xmlFree(cur->next);
cur->next = NULL;
callStackTop = cur;
} else {
#ifdef WITH_XSLDBG_DEBUG_PROCESS
xsltGenericError(xsltGenericErrorContext,
"Error: callStackDrop failed no items on call stack : dbgcallstack.c");
#endif
}
}
/**
* callStackStepup:
* @depth:The frame depth to step up to
* 0 < @depth <= callStackGetDepth()
*
* Set the frame depth to step up to
*
* Returns 1 on success,
* 0 otherwise
*/
int
callStackStepup(int depth)
{
int result = 0;
if ((depth > 0) && (depth <= callStackGetDepth())) {
stopDepth = -1 * depth;
xslDebugStatus = DEBUG_STEPUP;
result = 1;
} else {
#ifdef WITH_XSLDBG_DEBUG_PROCESS
xsltGenericError(xsltGenericErrorContext,
"Error: callStackStepup failed invalid depth %d: callstack.c", depth);
#endif
}
return result;
}
/**
* callStackStepdown:
* @depth: The frame depth to step down to,
* 0 < @depth <= callStackGetDepth()
*
* Set the frame depth to step down to
*
* Returns 1 on success,
* 0 otherwise
*/
int
callStackStepdown(int depth)
{
int result = 0;
if ((depth > 0) && (depth >= callStackGetDepth())) {
stopDepth = depth;
xslDebugStatus = DEBUG_STEPDOWN;
result = 1;
} else {
#ifdef WITH_XSLDBG_DEBUG_PROCESS
xsltGenericError(xsltGenericErrorContext,
"Error: callStackStepdown failed invalid depth %d: dbgcallstack.c", depth);
#endif
}
return result;
}
/**
* callStackGet:
* @depth: 0 < @depth <= callStackGetDepth()
*
* Retrieve the call point at specified call depth
* Returns Non-null if depth is valid,
* NULL otherwise
*/
callPointPtr
callStackGet(int depth)
{
callPointPtr result = NULL, cur = callStackBot;
if (!callStackBot) {
#ifdef WITH_XSLDBG_DEBUG_PROCESS
xsltGenericError(xsltGenericErrorContext,
"Error: callStackGet failed invalid call stack: callstack.c");
#endif
return result;
}
if ((depth < 1) && (depth > callStackGetDepth())) {
#ifdef WITH_XSLDBG_DEBUG_PROCESS
xsltGenericError(xsltGenericErrorContext,
"Error: callStackGet failed invalid call depth: callstack.c");
#endif
return result;
}
while (depth > 0 && cur->next) {
cur = cur->next;
depth--;
}
if (depth == 0)
result = cur;
else {
#ifdef WITH_XSLDBG_DEBUG_PROCESS
xsltGenericError(xsltGenericErrorContext,
"Error: callStackGet failed invalid call depth: callstack.c");
#endif
}
return result;
}
/**
* callStackGetTop:
*
* Get the top item in the call stack
*
* Returns The top of the call stack
*/
callPointPtr
callStackGetTop(void)
{
return callStackTop;
}
/**
* callStackGetDepth:
*
* Return the depth of call stack
*
* Returns The depth of call stack
*/
int
callStackGetDepth(void)
{
callPointPtr cur = callStackBot;
int depthCount = 0;
if (!callStackBot) {
#ifdef WITH_XSLDBG_DEBUG_PROCESS
xsltGenericError(xsltGenericErrorContext,
"Error: calldepth failed invalid call stack: dbgcallstack.c");
#endif
return depthCount;
}
while (cur->next) {
depthCount++;
cur = cur->next;
}
return depthCount;
}