|
|
|
|
|
|
|
/***************************************************************************
|
|
|
|
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: TQName part of template name to add
|
|
|
|
* @modeName: Mode of template
|
|
|
|
* @modeURI: TQName 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: TQName part of template name to add
|
|
|
|
* @modeName: Mode of template
|
|
|
|
* @modeURI: TQName 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;
|
|
|
|
}
|