/*************************************************************************** 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; }