/***************************************************************************
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
# if LIBXML_VERSION >= 20908
breakPointItemFree ( void * payload , const xmlChar * name )
# else
breakPointItemFree ( void * payload , xmlChar * name )
# endif
{
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 ;
}