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/breakpoint.cpp

697 lines
17 KiB

/***************************************************************************
breakpoint.c - breakpoint implementation
-------------------
begin : Fri Nov 2 2001
copyright : (C) 2001 by Keith Isdale
email : k_isdale@tpg.com.au
***************************************************************************/
#include "xsldbg.h"
#include "breakpoint.h"
#include "arraylist.h"
#include "options.h"
extern int xsldbgValidateBreakpoints; /*located in debugXSL.c*/
/*-----------------------------------------------------------
Private functions
-----------------------------------------------------------*/
/**
* lineNoItemNew:
*
* Returns a new hash table for break points
*/
xmlHashTablePtr lineNoItemNew(void);
/**
* lineNoItemFree:
* @item: valid hashtable of break points
*
* Free @item and all its contents
*/
void lineNoItemFree(void *item);
/**
* lineNoItemDelete:
* @breakPointHash: Is valid
* @breakPtr: Is valid
*
* Returns 1 if able to delete @breakPtr from @breakPointHash,
* 0 otherwise
*/
int lineNoItemDelete(xmlHashTablePtr breakPointHash,
breakPointPtr breakPtr);
/**
* lineNoItemAdd:
* @breakPointHash: is valid
* @breakPtr: is valid
*
* Add breakpoint to hash
*
* Returns 1 if able to add @breakPtr to @breakPointHash,
* 0 otherwise
*/
int lineNoItemAdd(xmlHashTablePtr breakPointHash, breakPointPtr breakPtr);
/*-----------------------------------------------------------
Breakpoint debugger functions
-----------------------------------------------------------*/
/* This is our major structure, it is a list of hash tables. Each
hash table has breakpoints with the same line number. A line
number is used as an index into this list to get the right hash table.
Then its just a matter of a simple hash table lookup */
arrayListPtr breakList;
/* keep track of what break point id we're up to*/
int breakPointCounter = 0;
/* What is the current breakpoint is only valid up to the start of
xsldbg command prompt. ie don't use it after deletion of breakpoints */
breakPointPtr activeBreakPointItem = NULL;
/**
* lineNoItemNew:
*
* Returns a new hash table for break points
*/
xmlHashTablePtr
lineNoItemNew(void)
{
xmlHashTablePtr hash;
hash = xmlHashCreate(4);
return hash;
}
/**
* lineNoItemFree:
* @item: valid hashtable of break points
*
* Free @item and all its contents
*/
void
lineNoItemFree(void *item)
{
xmlHashTablePtr hash = (xmlHashTablePtr) item;
if (item) {
#if 0
#ifdef WITH_XSLDBG_DEBUG_BREAKPOINTS
xsltGenericError(xsltGenericErrorContext,
"Freeing breakpoint line hash"
" with %d elements \n", xmlHashSize(item));
#endif
#endif
xmlHashFree(hash, breakPointItemFree);
}
}
/**
* lineNoItemDelete:
* @breakPointHash: is valid
* @breakPtr: is valid
*
* Returns 1 if able to delete @breakPtr from @breakPointHash,
* 0 otherwise
*/
int
lineNoItemDelete(xmlHashTablePtr breakPointHash, breakPointPtr breakPtr)
{
int result = 0;
if (breakPointHash && breakPtr) {
if (xmlHashRemoveEntry(breakPointHash, breakPtr->url,
breakPointItemFree) == 0){
result = 1;
}else{
#ifdef WITH_XSLDBG_DEBUG_BREAKPOINTS
xsltGenericError(xsltGenericErrorContext,"lineNoItemDelete failed");
#endif
}
}else {
#ifdef WITH_XSLDBG_DEBUG_BREAKPOINTS
xsltGenericError(xsltGenericErrorContext, "lineNoItemDelete failed args %d %d", breakPointHash, breakPtr);
#endif
}
return result;
}
/**
* lineNoItemAdd:
* @breakPointHash: is valid
* @breakPtr: is valid
*
* Returns 1 if able to add @breakPtr to @breakPointHash,
* 0 otherwise
*/
int
lineNoItemAdd(xmlHashTablePtr breakPointHash, breakPointPtr breakPtr)
{
int result = 0;
if (breakPointHash && breakPtr) {
if (xmlHashAddEntry(breakPointHash, breakPtr->url, breakPtr) == 0)
result = 1;
}
return result;
}
/**
* breakPointGetLineNoHash:
* @lineNo: Line number of of breakpoints of interest
*
* Return A hash of breakpoints with same line number
*
* Returns A hash of breakpoints with a line number of @lineNo
*/
xmlHashTablePtr
breakPointGetLineNoHash(long lineNo)
{
if (!breakList) {
#ifdef WITH_XSLDBG_DEBUG_BREAKPOINTS
xsltGenericError(xsltGenericErrorContext,
"Error: Breakpoints structures not initialized\n");
#endif
return NULL;
} else
return (xmlHashTablePtr) arrayListGet(breakList, lineNo);
}
/**
* breakPointInit:
*
* Returns 1 if breakpoints have been initialized properly and all
* memory required has been obtained,
* 0 otherwise
*/
int
breakPointInit(void)
{
int result = 0;
/* the average file has 395 lines of code so add 100 lines now */
breakList = arrayListNew(100, lineNoItemFree);
if (breakList) {
/*
* We don't need to do any thing else, as its done when we add the
* breakPoints
*/
result = 1;
} else {
#ifdef WITH_XSLDBG_DEBUG_BREAKPOINTS
xsltGenericError(xsltGenericErrorContext,
"Unable to intialize breakPoints: memory error\n");
#endif
}
return result;
}
/**
* breakPointFree:
*
* Free all memory used by breakPoints
*/
void
breakPointFree(void)
{
if (breakList)
arrayListFree(breakList);
breakList = NULL;
}
/**
* breakPointEmpty:
*
* Empty the break point collection
*
* Returns 1 if able to empty the breakpoint list of its contents,
* 0 otherwise
*/
int
breakPointEmpty(void)
{
return arrayListEmpty(breakList);
}
/**
* breakPointItemNew:
*
* Create a new break point item
* Returns valid break point with default values set if successful,
* NULL otherwise
*/
breakPointPtr
breakPointItemNew(void)
{
breakPointPtr breakPtr = (breakPointPtr) xmlMalloc(sizeof(breakPoint));
if (breakPtr) {
breakPtr->url = NULL;
breakPtr->lineNo = -1;
breakPtr->templateName = NULL;
breakPtr->modeName = NULL;
breakPtr->flags = BREAKPOINT_ENABLED;
breakPtr->id = ++breakPointCounter;
breakPtr->type = DEBUG_BREAK_SOURCE;
}
return breakPtr;
}
/**
* breakPointItemFree:
* @payload: valid breakPointPtr
* @name: not used
*
* Free memory associated with this break point
*/
void
breakPointItemFree(void *payload, xmlChar * name)
{
Q_UNUSED(name);
if (payload) {
breakPointPtr breakPtr = (breakPointPtr) payload;
if (breakPtr->url)
xmlFree(breakPtr->url);
if (breakPtr->templateName)
xmlFree(breakPtr->templateName);
if (breakPtr->modeName)
xmlFree(breakPtr->modeName);
xmlFree(breakPtr);
}
}
/**
* breakPointActiveBreakPoint:
*
* Get the active break point
*
* Returns The last break point that we stoped at
*
* Depreciated
*/
breakPointPtr
breakPointActiveBreakPoint(void)
{
/* This function is depreciated */
return NULL; /* activeBreakPointItem; */
}
/**
* breakPointSetActiveBreakPoint:
* @breakPtr: Is valid break point or NULL
*
* Set the active break point
*
* Depreciated
*/
void
breakPointSetActiveBreakPoint(breakPointPtr breakPtr)
{
Q_UNUSED(breakPtr);
/*
* activeBreakPointItem = breakPtr;
*/
}
/**
* breakPointAdd:
* @url: Non-null, non-empty file name that has been loaded by
* debugger
* @lineNumber: @lineNumber >= 0 and is available in url specified and
* points to an xml element
* @templateName: The template name of breakPoint or NULL
* @modeName : The mode of breakpoint or NULL
* @type: Valid BreakPointTypeEnum
*
* Add break point at file and line number specified
*
* Returns 1 if successful,
* 0 otherwise
*/
int
breakPointAdd(const xmlChar * url, long lineNumber,
const xmlChar * templateName,
const xmlChar * modeName,
BreakPointTypeEnum type)
{
int result = 0, breakPointType = type;
xmlHashTablePtr breakPointHash = NULL; /* hash of breakPoints */
breakPointPtr breakPtr;
if (!breakList) {
#ifdef WITH_XSLDBG_DEBUG_BREAKPOINTS
xsltGenericError(xsltGenericErrorContext,
"Error: Breakpoints structures not initialized\n");
#endif
return result;
}
if (!url || (lineNumber == -1)) {
#ifdef WITH_XSLDBG_DEBUG_BREAKPOINTS
xsltGenericError(xsltGenericErrorContext,
"Error: Invalid url or line number to breakPointAdd\n");
#endif
return result;
}
/* if breakpoint already exists then don;t add it */
if (breakPointIsPresent(url, lineNumber)) {
#ifdef WITH_XSLDBG_DEBUG_BREAKPOINTS
xsltGenericError(xsltGenericErrorContext,
"Warning: Breakpoint at file %s: line %d exists\n",
url, lineNumber);
#endif
return result;
}
breakPtr = breakPointItemNew();
if (breakPtr) {
breakPtr->url = (xmlChar *) xmlMemStrdup((char *) url);
breakPtr->lineNo = lineNumber;
if (templateName)
breakPtr->templateName =
xmlStrdup( templateName);
else
breakPtr->templateName = NULL;
if (modeName)
breakPtr->modeName =
xmlStrdup(modeName);
else
breakPtr->modeName = NULL;
breakPtr->type = BreakPointTypeEnum(breakPointType);
/* add new breakPoint to the right hash table */
breakPointHash = breakPointGetLineNoHash(lineNumber);
if (breakPointHash) {
result = lineNoItemAdd(breakPointHash, breakPtr);
} else {
/* Grow breakList size */
int lineIndex;
int newEntries = breakList->count;
xmlHashTablePtr hash;
result = 1;
if ((lineNumber < breakList->count) && breakList->count) {
#ifdef WITH_XSLDBG_DEBUG_BREAKPOINTS
xsltGenericError(xsltGenericErrorContext,
"Error: Unable to find breakpoint line hash at %d\n",
lineNumber);
#endif
} else {
if (breakList->count + newEntries < lineNumber)
newEntries = lineNumber - breakList->count + 1;
#ifdef WITH_XSLDBG_DEBUG_BREAKPOINTS
/*
* xsltGenericError(xsltGenericErrorContext,
* "Size of line list was %d adding %d entries\n",
* breakList->count, newEntries);
*/
#endif
lineIndex = 0;
while ((lineIndex < newEntries) && result) {
hash = lineNoItemNew();
if (hash) {
result = result && arrayListAdd(breakList, hash);
} else {
result = 0;
#ifdef WITH_XSLDBG_DEBUG_BREAKPOINTS
xsltGenericError(xsltGenericErrorContext,
"Error: Unable to create hash table breakPoint list: memory error\n");
#endif
return result;
}
lineIndex++;
}
/* find the newly added hashtable of breakpoints */
breakPointHash = breakPointGetLineNoHash(lineNumber);
if (breakPointHash) {
result = lineNoItemAdd(breakPointHash, breakPtr);
} else {
#ifdef WITH_XSLDBG_DEBUG_BREAKPOINTS
xsltGenericError(xsltGenericErrorContext,
"Error: Unable to create new breakPoint:interal error\n");
#endif
return result;
}
}
}
} else {
#ifdef WITH_XSLDBG_DEBUG_BREAKPOINTS
xsltGenericError(xsltGenericErrorContext,
"Error: Unable to create new breakPoint: memory error\n");
#endif
}
if (result && (optionsGetIntOption(OPTIONS_GDB) > 1) &&
(xsldbgValidateBreakpoints != BREAKPOINTS_BEING_VALIDATED)){
breakPointPrint(breakPtr);
xsldbgGenericErrorFunc("\n");
}
return result;
}
/**
* breakPointDelete:
* @breakPtr: Is valid
*
* Delete the break point specified if it can be found using
* @breakPoint's url and lineNo
*
* Returns 1 if successful,
* 0 otherwise
*/
int
breakPointDelete(breakPointPtr breakPtr)
{
int result = 0;
xmlHashTablePtr breakPointHash; /* hash of breakPoints */
if (!breakPtr)
return result;
breakPointHash = breakPointGetLineNoHash(breakPtr->lineNo);
if (breakPointHash) {
result = lineNoItemDelete(breakPointHash, breakPtr);
} else {
#ifdef WITH_XSLDBG_DEBUG_BREAKPOINTS
xsltGenericError(xsltGenericErrorContext,
"Error: Breakpoint not found: xslDeleteBreakPoint\n");
#endif
}
return result;
}
/**
* breakPointEnable:
* @breakPtr: A valid breakpoint
* @enable: Enable break point if 1, disable if 0, toggle if -1
*
* Enable or disable a break point
*
* Returns 1 if successful,
* 0 otherwise
*/
int
breakPointEnable(breakPointPtr breakPtr, int enable)
{
int result = 0;
if (breakPtr) {
int enableFlag = 1;
if (enable != XSL_TOGGLE_BREAKPOINT){
enableFlag = enable;
}else {
if (breakPtr->flags & BREAKPOINT_ENABLED)
enableFlag = 0;
}
if (enableFlag)
breakPtr->flags |= BREAKPOINT_ENABLED;
else
breakPtr->flags = breakPtr->flags & (BREAKPOINT_ALLFLAGS ^ BREAKPOINT_ENABLED);
result = 1;
}
return result;
}
/**
* breakPointLinesCount:
*
* Return the number of hash tables of break points with the same line number
*
* Returns The number of hash tables of break points with the same line number
*/
int
breakPointLinesCount(void)
{
if (!breakList) {
#ifdef WITH_XSLDBG_DEBUG_BREAKPOINTS
xsltGenericError(xsltGenericErrorContext,
"Error: Breakpoints structures not initialized\n");
#endif
return 0;
} else
return arrayListCount(breakList);
}
/**
* breakPointLinesList:
*
* Returns The list of hash tables for break points
* Dangerous function to use!!
*/
arrayListPtr
breakPointLineList(void)
{
return breakList;
}
/**
* breakPointGet:
* @url: Non-null, non-empty file name that has been loaded by
* debugger
* @lineNumber: lineNumber >= 0 and is available in @url
*
* Get a break point for the breakpoint collection
*
* Returns break point if break point exists at location specified,
* NULL otherwise
*/
breakPointPtr
breakPointGet(const xmlChar * url, long lineNumber)
{
xmlHashTablePtr breakHash = breakPointGetLineNoHash(lineNumber);
breakPointPtr breakPtr = NULL;
if (!breakHash || !url)
return breakPtr;
breakPtr = (breakPointPtr)xmlHashLookup(breakHash, url);
return breakPtr;
}
/**
* breakPointPrint:
* @breakPtr: A valid break point
*
* Print the details of @breakPtr
*
* Returns 1 if successful,
* 0 otherwise
*/
int
breakPointPrint(breakPointPtr breakPtr)
{
int result = 0;
const char *breakStatusText[2] = {
I18N_NOOP("disabled"),
I18N_NOOP("enabled")
};
const char *breakTemplate="";
const char *breakMode = "";
const char *breakStatus;
if (!breakPtr)
return result;
if (breakPtr->templateName){
if (breakPtr->modeName)
breakMode = (const char*)breakPtr->modeName;
breakTemplate = (const char*)breakPtr->templateName;
}
breakStatus = breakStatusText[breakPtr->flags & BREAKPOINT_ENABLED];
if (breakPtr->url)
xsldbgGenericErrorFunc(i18n("Breakpoint %1 %2 for template: \"%3\" mode: \"%4\" in file \"%5\" at line %6").arg(breakPtr->id).arg(i18n(breakStatus)).arg(xsldbgText(breakTemplate)).arg(xsldbgText(breakMode)).arg(xsldbgUrl(breakPtr->url)).arg(breakPtr->lineNo));
else
xsldbgGenericErrorFunc(i18n("Breakpoint %1 %2 for template: \"%3\" mode: \"%4\"").arg(breakPtr->id).arg(i18n(breakStatus)).arg(xsldbgText(breakTemplate)).arg(xsldbgText(breakMode)));
return ++result;
}
/**
* breakPointIsPresent:
* @url: Non-null, non-empty file name that has been loaded by
* debugger
* @lineNumber: @lineNumber >= 0 and is available in @url
*
* Determine if there is a break point at file and line number specified
*
* Returns 1 if successful,
* 0 otherwise
*/
int
breakPointIsPresent(const xmlChar * url, long lineNumber)
{
int result = 0;
if (!url || (lineNumber == -1))
return result;
result = (breakPointGet(url, lineNumber) != NULL);
return result;
}
/**
* breakPointIsPresentNode:
* @node: node != NULL
*
* Determine if a node is a break point
*
* Returns 1 on success,
* 0 otherwise
*/
int
breakPointIsPresentNode(xmlNodePtr node)
{
int result = 0;
if (!node || !node->doc)
return result;
if (xmlGetLineNo(node) == -1)
return result;
if (node->doc->URL) {
result = breakPointIsPresent(node->doc->URL, xmlGetLineNo(node));
}
return result;
}